简介
Uboot
属于bootloader
的一种,是用来引导启动内核的,它的最终目的就是,从flash
中读出内核,放到内存中,启动内核,需要具有读写flash
的能力
- Flash
flash是存储芯片的一种,通过特定的程序可以修改里面的数据。FLASH在电子以及半导体领域内往往表示Flash Memory的意思,即平时所说的“闪存”,全名叫Flash EEPROM Memory
flash存储器又称闪存,它结合了ROM和RAM的长处,不仅具备电子可擦除可编程(EEPROM)的性能,还可以快速读取数据(NVRAM的优势),使数据不会因为断电而丢失
Bootloader
bootloader作用
PC机中的引导加载程序由BIOS(其本质是一段固件程序)和GRUB或LILO一起组成。BIOS在完成硬件检测和资源分配后,将硬盘中的引导程序读到系统内存中然后将控制权交给引导程序。引导程序的主要任务是将内核从硬盘上读到内存中,然后跳转到内核的入口点去运行,即启动操作系统
简单地说,BootLoader就是在操作系统运行之前运行的一段小程序。通过这段小程序,可以初始化硬件设备,从而将系统的软硬件环境带到一个合适的状态,以便为最终调用操作系统做好准备
系统加电或复位后,所有的CPU通常都从CPU制造商预先安排地址开始执行。比如,S3C2410在复位后从地址0x00000000起开始执行。而嵌入式系统则将固态存储设备(比如:FLASH)安排在这个地址上,而bootloader程序又安排在固态存储器的最前端,这样就能保证在系统加电后,CPU首先执行BootLoader程序
Bootloader 移植
每种不同的CPU体系结构都有不同的BootLoader。除了依赖于CPU的体系结构外,BootLoader 还依赖于具体的嵌入式板级设备的配置,比如板卡的硬件地址分配,外设芯片的类型等。这也就是说,对于两块不同的开发板而言,即使它们是基于同一种CPU而构建的,但如果他们的硬件资源或配置不一致的话,要想在一块开发板上运行的BootLoader程序也能在另一块板子上运行,还是需要作修改
Bootloader 移植流程
BootLoader 的启动过程可分为单阶段(Single-Stage)和多阶段(Multi-Stage)两种。
BootLoader 大多采用两阶段,即启动过程可以分为 stage1和 stage2:stage1完成初始化硬件,为stage2准备内存空间,并将stage2复制到内存中,设置堆栈,然后跳转到stage2
- Stage1:(汇编编写)
- 硬件设备初始化(主要是CPU内部器件)
- 为加载 BootLoader 的 stage2 准备 RAM 空间
- 拷贝 BootLoader 的 stage2 到 RAM 空间中
- 设置好堆栈(why??)
- 跳转到 stage2 的 C 入口点
- Stage2:(C编写)
- 初始化本阶段要使用到的硬件设备(主要是外设)
- 将内核映像和根文件系统映像从 flash 上读到RAM 中
- 调用内核
Uboot
Uboot引导启动内核
Uboot刚开始被放到flash中,板子上电后,会自动把其中的一部分代码拷到内存中执行,这部分代码负责把剩余的Uboot代码拷到内存中,然后Uboot代码再把kernel部分代码也拷到内存中,并且启动,内核启动后,挂着根文件系统,执行应用程序
Uboot启动过程
- 硬件的初始化
- 设置处理器模式为SVC模式
- 关闭看门狗
- 屏蔽中断
- 初始化
sdram
- 设置栈
- 设置时钟
- 从
flash
拷贝代码到内存 - 清除
bss
段等
bss段是用来存储静态变量,全局变量的,然后程序跳转到
start_arm_boot
函数,宣告第一阶段的结束
- Arm的几种工作模式
- USR 正常用户模式,程序正常执行模式
- FIQ(Fast Interrupt Request) 处理快速中断,支持高速数据传送或通道处理
- IRQ 处理普通中断
- SVC模式(Supervisor) 操作系统保护模式,处理软件中断swi reset
- ABT 中止(Abort mode)处理存储器故障、实现虚拟存储器和存储器保护
- UND 未定义(Undefined) 处理未定义的指令陷阱,支持硬件协处理器的软件仿真
- SYS 系统模式(基本上=USR)(System)
除了用户模式之外的其他6种处理器模式称为特权模式
特权模式下,程序可以访问所有的系统资源,也可以任意地进行处理器模式的切换;特权模式中,除系统模式外,其他5种模式又称为异常模式
- 看门狗(WatchDog)
看门狗,全称WatchDog Timer,即看门狗计时器
WatchDog是一种电子或软件定时器,用于检测计算机故障,并从计算机故障中恢复。在正常操作期间,计算机会定期重置看门狗计时器,以防止其丢失或“计时”。 如果由于硬件故障或程序错误而导致计算机无法重置看门狗,则计时器将丢失并生成超时信号, 超时信号会被用于启动一个或多个纠正措施。 纠正措施通常包括将计算机系统置于安全状态并恢复系统的正常运行
嵌入式系统和其他计算机控制的设备通常会使用WatchDog。通常是由于人们无法轻易接触该设备,或者无法及时对故障做出反应。在这样的系统中,如果计算机停车,则不能依靠人工来进行重启,那么它必须自力更生。例如,如空间探测器之类的远程嵌入式系统,人类无法其进行直接的物理操作。车辆中的嵌入式系统,驾驶员也难以进行直接的物理操作。如果它们无法从故障中自动恢复,他们便会一直处于失效状态。在这种情况下看门狗定时器便可以发挥作用。运行不受信任的代码时,也可以使用WatchDog,以限制该代码对CPU的使用时间,从而防止某些类型的拒绝服务攻击
对于含有需要在特定时间间隔内完成的具有高优先级的操作的系统中,也需要使用WatchDog。如果在操作完成之前计时器到期,那么操作系统会通过记录错误数据和终止操作的方式对计时器做出响应。系统可能同时具有两种看门狗定时器
重启WatchDog
重启看门狗的操作通常称为“踢”看门狗,通常是通过写入看门狗控制端口来完成的。 或者,在具有集成WatchDog的微控制器中,有时通过执行特殊的机器语言指令或设置寄存器中的特定位来重启WatchDog。 例如在某些PIC单片机的指令集中可以找到CLRWDT(清除看门狗定时器)指令
单级看门狗
看门狗定时器具有多种配置,并且许多允许更改其配置。微控制器通常含有一个集成的看门狗。 在其他计算机中,看门狗可能位于直接与CPU附近且相连的芯片中,或者可能位于计算机机箱的外部扩展卡上。 看门狗和CPU可以共享一个公共时钟信号
多级看门狗
多级看门狗计时器通常由多个计时器级联而成。其中每个计时器都称为计时器阶段,或简称为一个阶段。在多级看门狗中,处理器只会重启第一级。在第一阶段超时后,将启动纠正措施,并开始级联的下一个阶段。随着每个后续阶段的超时,它将触发纠正措施并开始下一阶段。在最后阶段超时后,将启动纠正措施,但由于已达到级联的末端,因此没有其他阶段被继续启动。通常,单级看门狗计时器用于简单地重新启动计算机,而多级看门狗计时器将依次触发一系列的纠正措施,最后一级触发计算机的重启
- 启动内核
- 从flash中读出内核
- 启动内核
start_arm_boot
的主要流程为,设置机器id,初始化flash
,然后进入main_loop
,等待Uboot
命令,Uboot
要启动内核,
主要经过两个函数,第一个是s=getenv("bootcmd")
,第二个是run_command(s...)
,所以要启动内核,需要根据bootcmd
环境变量的内容启动,bootcmd
环境变量一般指示了从某个flash
地址读取内核到启动的内存地址,然后启动bootm
Uboot
启动的内核为uImage
,这种格式的内核是由两部分组成:真正的内核和内核头部组成,头部中包括内核中的一些信息,比如内核的加载地址,入口地址
Uboot
在接受到启动命令后,要做的主要是:
- 读取内核头部
- 移动内核到合适的加载地址
- 启动内核,执行
do_bootm_linux
do_bootm_linux
主要做的是:
- 设置启动参数,在特定的地址,保存启动参数
- 跳到入口地址,启动内核
启动函数分别为
setup_start_tag
,setup_memory_tag
,setup_commandline_tag
,setup_end_tag
,根据名字我们就知道具体的段内存储的信息,memory中为板子的内存大小信息,commandline为命令行信息,
启动内核的函数为the_kernel(0,bd->bi_arch_number,bd->bi_boot_param)
bd->bi_arch_number
为板子的机器码,bd->bi_boot_param
为启动参数的地址
References
https://www.jianshu.com/p/b7205bb30865
https://www.pianshen.com/article/55871057612/
https://baike.baidu.com/item/Flash/5797776
https://blog.csdn.net/beyond702/article/details/49909051
https://zhuanlan.zhihu.com/p/149328734