u-boot(五) - 启动流程概述

news2024/12/25 12:24:38

一,XIP设备

  • 一上电,CPU必定从XIP设备得到第1条指令。

  • XIP设备是指一种可以直接在存储器中执行程序代码的设备,而不需要将代码复制到内存中。XIP的全称是eXecute In Place,即芯片内执行。这类设备包括片内的SRAM、NOR Flash、BootROM等。XIP设备的启动方式是系统上电之后CPU执行的第一条指令是直接在非易失性存储器中执行的,比如被存储在flash中的启动程序,便可以直接在flash中执行,而不需要拷贝到内存中运行。这种启动方式的特点是节省了从存储器到内存的复制过程,从而减少了启动时间和资源消耗。

  • CPU上电之后可以直接从XIP设备中取指令到CPU中运行,看上去像是在flash或者ram中执行。

  • Nand Flash是非XIP设备,CPU不能直接从nand flash中取指令运行。

 

二,BootROM的作用

号称支持Nand启动、支持SD卡启动、支持USB启动、支持UART启动的芯片,里面必定有BootROM。

BootROM:硬件初始化、把程序从非XIP设备复制进RAM,从RAM里执行。

如何支持多种启动方式(SD卡、EMMC、USB、UART启动):

  • 方法1:芯片有boot pin,决定使用哪个外设。bootrom根据引脚决定读取哪个设备的程序

  • 方法2:芯片有boot pin,决定多种外设的尝试顺序

            示例顺序1:SD、EMMC、USB

            示例顺序2:EMMC、SD、USB

            示例顺序3:USB

三,完整的u-boot复制进内存

BootROM被用来启动用户程序,用户程序可能有几百KB、几MB,但是片内的RAM只有几KB:

  • 方法1:

        BootROM从启动设备读取用户程序的前几KB到SRAM,运行它;

        这前几KB的代码负责:初始化DDR、把完整的程序从启动设备复制到DDR、并跳到DDR运行。

  • 方法2:

        BootROM从启动设备读取SPL到SRAM,运行它;

        SPL负责:初始化DDR、把用户程序从启动设备复制到DDR、并跳到DDR运行。

四,SPL

SPL 全称叫做:Secondary Program Loader,看名字,像是一个什么二级加载相关的;实质上,也是二级加载;

那么BootROM 的代码除了去初始化硬件环境以外,还需要去外部存储器上面,将接下来可执行的程序读到内存来执行;

既然是读到内存执行,那么这个内存可以不可以是我们板载的 DDR 呢?理论上是可以的,但是,SoC 厂家设计的 DDR 控制器呢,一般会支持很多种类型的 DDR 设备,并且会提供兼容性列表,SoC 厂家怎么可能知道用户 PCB 上到底用了哪种内存呢?所以,直接把外部可执行程序读到 DDR 显然是不太友好的,一般来说呢,SoC 都会做一个内部的小容量的 SRAM (又是成本),BootROM 将外部的可执行程序从存储器中读出来,放到 SRAM 去执行;

BootROM 会根据 Bootstrap Pin 去确定从某个存储器来读可执行的二进制文件到 SRAM 并执行;理论上来说,这个二进制文件就可以是我们的 u-boot.bin 文件了;也就是 BootROM 直接加载 u-boot.bin;

理论上是这样的,但是这里有一个问题,就是 SRAM 很贵,一般来说,SoC 的片上 SRAM 都不会太大,一般 4KB、8KB、16KB...256KB不等;但是呢,u-boot 编译出来,却很大,好几百KB,放不下!

放不下怎么办?有两种办法:

1、放不下就放不下呗,BootROM 加载多少算多少;

2、做一个小一点的 boot 程序,先让 BootROM 加载这个小的程序,后面再由这个小 boot 去加载 u-boot;

 

比如,我们的 u-boot 有 300KB,SRAM 有 8KB,外部 DDR 1GB:

如果使用第一种方案的话,u-boot 的前面 8K 被加载进入 SRAM 执行,u-boot 被截断,我们就需要保证在 u-boot 的前 8KB 代码,把板载的 DDR 初始化好,把整个 u-boot 拷贝到 DDR,然后跳转到 DDR 执行;

第二种方案的话,我们做一个小的 u-boot ,这个 u-boot 就叫做 spl,它很小很小(小于SRAM大小),它先被 BootROM 加载到 SRAM 运行,那么这个 spl 要做什么事情呢?最主要的就是要初始化 DDR Controller,然后将真正的大 u-boot 从外部存储器读取到 DDR 中,然后跳转到大 u-boot;

如下图所示:

0)、上电后,BootROM 开始执行,初始化时钟,关闭看门狗,关 Cache,关中断等等,根据 Bootstrap Pin 来确定启动设备,初始化外设;

1)、使用外设驱动,从存储器读取 SPL;

---------------- 以上部分是 SoC 厂家的事情,下面是用户要做的事情 ----------------

2)、SPL 被读到 SRAM 执行,此刻,控制权以及移交到我们的 SPL 了;

3)、SPL 初始化外部 DDR;

4)、SPL 使用驱动从外部存储器读取 u-boot 并放到 DDR;

5)、跳转到 DDR 中的 u-boot 执行;

6)、加载内核;

原文链接:u-boot (3) —— spl_uboot spl-CSDN博客

五,bss段,data段、text段、堆heap和栈stack

1,程序的内存分配

2,基本概念

bss段:

bss段(bss segment)通常是指用来存放程序中未初始化的全局变量的一块内存区域。一般在初始化时bss 段部分将会清零。bss段属于静态内存分配,即程序一开始就将其清零了。

bss是英文Block Started by Symbol的简称。

bss段属于静态内存分配,

data段:

数据段(data segment)通常是指用来存放程序中已初始化的全局变量的一块内存区域。

数据段属于静态内存分配。

注意,如果你想要确保变量存储在"data段",你应该确保它是已初始化的,因为未初始化的全局变量和静态局部变量通常存储在".bss段"。

堆(heap):

堆是用于存放进程运行中被动态分配的内存段,它的大小并不固定,可动态扩张或缩减。

当进程调用malloc等函数分配内存时,新分配的内存就被动态添加到堆上(堆被扩张);

当利用free等函数释放内存时,被释放的内存从堆中被剔除(堆被缩减)。

栈(stack):

栈又称堆栈,是用户存放程序临时创建的局部变量,

也就是说我们函数括弧“{}”中定义的变量(但不包括static声明的变量,static意味着在数据段中存放变量)。

除此以外,在函数被调用时,其参数也会被压入发起调用的进程栈中,并且待到调用结束后,函数的返回值也会被存放回栈中。

由于栈的先进先出(FIFO)特点,所以栈特别方便用来保存/恢复调用现场。

从这个意义上讲,我们可以把堆栈看成一个寄存、交换临时数据的内存区。

一个位于.bss段,而另一个位于.data段,两者的区别在于:

全局的未初始化变量存在于.bss段中,具体体现为一个占位符;

全局的已初始化变量存于.data段中;

而函数内的自动变量都在栈上分配空间;

.bss是不占用.exe文件空间的,其内容由操作系统初始化(清零);

.data却需要占用,其内容由程序初始化。因此造成了上述情况。

bss段(未手动初始化的数据)并不给该段的数据分配空间,只是记录数据所需空间的大小;

bss段的大小从可执行文件中得到 ,然后链接器得到这个大小的内存块,紧跟在数据段后面。

data段(已手动初始化的数据)则为数据分配空间,数据保存在目标文件中;

data段包含经过初始化的全局变量以及它们的值。当这个内存区进入程序的地址空间后全部清零。

六,重定位

1,基本概念

重定位: 

就是 uboot 将自身拷贝到 DRAM 的另一个地方去继续运行(DRAM 的高地址处)。

链接地址:

在链接脚本里指定内存地址,编译时指定的代码运行时应该所处的内存地址。它是绝对地址(编译后的定值)。

运行地址:

当前代码运行时实际所处的地址。它是相对地址(相对于当前程序开始运行时的内存地址)。

存储地址:

代码烧写到ROM中的地址,比如NANDFLASH。

链接地址和运行地址的关系:

正常情况下 链接地址 = 运行地址,当运行地址等于链接地址时,程序肯定能运行,因为我们指定链接地址的初衷就是为了让代码能在我们指定的位置中运行。

位置无关码:

从本质上讲,位置无关码就是代码中跳转或者取值、赋值的目标地址都使用相对地址,位置有关码使用的是绝对地址。

2,重定位的两种方法

方法一:

链接地址是Addr_A,拷贝到Addr_A去运行,此时链接地址和运行地址相等,程序可以正常运行。

方法二:

链接地址是Addr_A,拷贝到Addr_B去运行,运行地址和链接地址就不一样了,这样在进行寻址就会出问题, 解决办法就是使用位置无关码,对.rel.dyn的定位问题进行修复,就是为了解决该问题。

.rel.dyn段存放了.text段中需要重定位地址(也就是搬移了__image_copy_start~__image_copy_end的代码后,需要对其中存的绝对地址进行更新,即绝对地址+偏移地址)的集合。

七,启动过程总结

1,启动流程1

2,启动流程2

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1821031.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

社区论坛圈子软件APP ,提供互动交流、知识共享和专业交流的社交平台。

社区论坛圈子软件APP的开发能够为用户提供一个互动交流的社交平台,促进用户之间的知识分享、交流和互助。本文将突出社区论坛圈子软件APP的前景、作用和特点,以帮助您了解该系统的潜力和优势。 一、前景: 知识共享:社区论坛圈子软…

线程有规律循环打印输出,线程拷贝图片运用

1&#xff1a;线程打印循环&#xff08;保证循环顺序输出&#xff09; 使用互斥锁和条件变量实现&#xff1a; #include <stdio.h>#include <pthread.h>#include <unistd.h>#include <stdlib.h>#include <string.h>#include <semaphore.h>…

【SAP-ABAP】-权限批导-批量给某个角色导入事务码权限

需求&#xff1a;SAP期初上线的时候&#xff0c;业务顾问经常会遇到批量创建角色和分配角色权限的情况 岗位需求&#xff1a;一般是业务顾问定义权限&#xff0c;BASIS进行后期运维&#xff0c;今天讲两个批导功能&#xff0c;方便期初上线 主要函数&#xff1a;PRGN_READ_ROLE…

群体优化算法----多乌鸦搜寻算法介绍,找多目标函数组解,Pareto前沿

介绍 乌鸦搜寻算法&#xff08;Crow Search Algorithm&#xff0c;CSA&#xff09;是一种新型的群体智能优化算法&#xff0c;其灵感来源于乌鸦的行为特性&#xff0c;尤其是乌鸦在食物搜寻和藏匿过程中的智能行为。乌鸦是一种高度聪明的鸟类&#xff0c;它们展示出复杂的社会…

html实现粘贴excel数据,在页面表格中复制

录入数据时&#xff0c;有时候需要把excel中的数据一条条粘贴到页面中&#xff0c;当数据量过多时&#xff0c;这种操作很令人崩溃。本篇文章实现了从excel复制好多行数据后,可在页面粘贴的功能 具体实现代码 <!DOCTYPE html> <html lang"en"> <head…

自适应巡航控制技术规范(简化版)

自适应巡航控制技术规范(简化版) 1 系统概述2 功能需求3 性能需求4 功能激活条件5 功能抑制条件6 系统局限性1 系统概述 ACC 自适应巡航系统可自动控制纵向跟车距离,减轻驾驶员的工作量,即驾驶员无需频繁的踩制动和油门便可完成部分的驾驶任务,但责任主体仍然是驾驶员,驾…

OrangePi AIpro测评:性能、应用与开发者体验解析

一、OrangePi AIpro介绍 OrangePi AIpro(8T)采用昇腾AI技术路线&#xff0c;具体为4核64位处理器AI处理器&#xff0c;集成图形处理器&#xff0c;支持8TOPS AI算力&#xff0c;拥有8GB/16GB LPDDR4X&#xff0c;可以外接32GB/64GB/128GB/256GB eMMC模块&#xff0c;支持双4K高…

SPI转四串口芯片CH9434的设计

一、CH9434的介绍 CH9434 是一款SPI转四串口转接芯片&#xff0c;提供四组全双工的9线异步串口&#xff0c;用于单片机/嵌入式系统扩展异步串口。CH9434包含四个兼容16C550的异步串口&#xff0c;最高支持4Mbps波特率通讯。最多支持25 路GPIO&#xff0c;提供半双工收发自动切换…

Rust基础学习-ModulesPackage

在Rust中&#xff0c;模块有助于将程序分割成逻辑单元&#xff0c;以提高可读性和组织性。一旦程序变得更大&#xff0c;将其拆分为多个文件或命名空间非常重要。 模块有助于构建我们的程序。模块是项目的集合&#xff1a;包括函数、结构体甚至其他模块。 Module 定义模块 在…

嵌入式硬件VS软件,到底哪个更难?

在嵌入式系统开发中&#xff0c;硬件和软件是密不可分的两个方面。但是&#xff0c;究竟是硬件开发更具挑战性&#xff0c;还是软件开发更难以应对呢&#xff1f;本文将就这一问题展开讨论&#xff0c;探究嵌入式硬件和软件在开发过程中的各种挑战与特点。 一、硬件开发&#…

12.实战私有数据微调ChatGLM3

实战私有数据微调ChatGLM3 实战私有数据微调ChatGLM3实战构造私有的微调数据集基于 ChatGPT 设计生成训练数据的 Prompt使用 LangChain GPT-3.5-Turbo 生成训练数据样例训练数据解析、数据增强和持久化存储自动化批量生成训练数据集流水线提示工程&#xff08;Prompt Engineer…

HTTPS请求阶段图解分析

HTTPS请求阶段分析 请求阶段分析 请求阶段分析 一个完整、无任何缓存、未复用连接的 HTTPS 请求需要经过以下几个阶段&#xff1a; DNS 域名解析、TCP 握手、SSL 握手、服务器处理、内容传输。 一个 HTTPS 请求共需要 5 个 RTT 1 RTT&#xff08;域名解析&#xff09; 1 RTT…

element table 点击某一行中按钮加载

在Element UI中&#xff0c;实现表格&#xff08;element-table&#xff09;中的这种功能通常涉及到数据处理和状态管理。当你点击某一行的按钮时&#xff0c;其他行的按钮需要动态地切换为加载状态&#xff0c;这可以通过以下步骤实现&#xff1a; 1.表格组件&#xff1a;使用…

NodeClub:NodeJS构造开源交流社区

NodeClub&#xff1a; 连接每一个想法&#xff0c;NodeClub让社区更生动- 精选真开源&#xff0c;释放新价值。 概览 NodeClub是一个基于Node.js和MongoDB构建的社区系统&#xff0c;专为开发者和社区爱好者设计。它提供了一套完整的社区功能&#xff0c;包括用户管理、内容发…

基于 Nginx Ingress + 云效 AppStack 实现灰度发布

作者&#xff1a;子丑 场景简介 灰度发布是降低生产部署风险&#xff0c;提升线上服务稳定性的重要手段&#xff0c;这在当前快速迭代的软件研发中尤为重要。相对于 K8s 默认的滚动部署或者简单的 Pod 分批&#xff0c;基于流量特征的灰度发布验证更精准&#xff0c;风险更低…

安鸾学院靶场——安全基础

文章目录 1、Burp抓包2、指纹识别3、压缩包解密4、Nginx整数溢出漏洞5、PHP代码基础6、linux基础命令7、Mysql数据库基础8、目录扫描9、端口扫描10、docker容器基础11、文件类型 1、Burp抓包 抓取http://47.100.220.113:8007/的返回包&#xff0c;可以拿到包含flag的txt文件。…

buuctf----warmup_csaw_2016

进来医院先来一套常规检查 啥保护都没,看大佬说基本栈溢出 CT一看 OK cat flag 更喜欢了 40060D 找到地址 get也来了,稳啦! 0x80-0x40 8 根据上道题的exp from pwn import * ghust remote("node5.buuoj.cn",27229) addr 0x40060D payload bA * 0x40 bB*8…

SpringMVC-基础架构

一、什么是MVC 二、什么是SpringMVC 三、SpringMVC的特点 四、配置SpringMVC 简单流程&#xff1a; 总体框架 1.创建pom.xml依赖 <!--打包方式--><packaging>war</packaging><!--依赖--><dependencies><dependency><groupId>org.s…

路由器怎么设置局域网?

局域网&#xff08;Local Area Network&#xff0c;LAN&#xff09;是指在一个相对较小的地理范围内&#xff0c;如家庭、办公室或学校等&#xff0c;通过路由器等设备连接起来的计算机网络。设置局域网可以方便地实现内部资源共享和信息交流。本文将介绍如何设置局域网以及一个…

C# 设置PDF表单不可编辑、或提取PDF表单数据

PDF表单是PDF中的可编辑区域&#xff0c;允许用户填写指定信息。当表单填写完成后&#xff0c;有时候我们可能需要将其设置为不可编辑&#xff0c;以保护表单内容的完整性和可靠性。或者需要从PDF表单中提取数据以便后续处理或分析。 之前文章详细介绍过如何使用免费Spire.PDF…