bootloader与u-boot
Bootloader是在操作系统运行之前执行的一小段程序,通过这一小段程序,可以初始化硬件设备、建立内存空间的映射表,从而建立适当的系统软硬件环境,为最终调用操作系统内核做好准备。
Boot Loader的主要运行任务就是将内核映象从硬盘上读到RAM中,然后跳转到内核的入口点去运行,即开始启动操作系统。
而u-boo就是bootloader的一种
uboot启动流程详解
Romboot(ROM固化程序)->SPL(SRAM上运行)->U-boot(SDRAM上运行)->Linux Kernel->File System->User Application
1、Romboot(ROM固化程序)
表明启动方式,是emmc还是SD卡
2、SPL(uboot中前16k汇编代码/SRAM上运行)(入口通过查看连接脚本文件知道是_start)
对于内部SRAM来说比较小,无法装下整个uboot文件,所以就需要spl,主要是负责初始化外部RAM和环境,并将真正的uboot镜像到外部RAM(SDRAM)中,这个在进入_start的刚开始就完成了。
-
初始化部分时钟(和SDRAM相关的时钟)
-
初始化SDRAM
-
从emmc上(或SD)将uboot中剩余的C代码加载到SDRAM上
-
跳转执行uboot剩余代码
3、U-boot(SDRAM上运行)(真正的uboot)
平台级初始化
-
关闭中断(启动过程不需要中断)
-
cpu_init_cp15()
-
关闭MMU(MMU是虚拟地址向物理地址映射的一个结构,uboot直接是物理地址,不需要MMU)
-
启动Icache(指令)(加快指令读取速度),关闭Dcache(数据)(Dcache本身是CPU的二级缓存,在运行程序的时候可能会往里面去取数据,但此时RAM里卖弄的数据可能没有存在里面,这就可能会导致读取到错误的数据,所以一定要关闭)
-
-
cpu_init_crit()跳转到lowlevel_init()后跳转到_main()函数进入板级初始化
板级初始化
-
初始化DDR、定时器,board_init_f()(没有初始化所有外设,后面还需要其他函数初始化其他外设)
-
将uboot拷贝到DRAM的高地址去运行然后重定位,reocate_code()
-
建立起C运行环境
-
初始化其他外设,board_init_r()
-
进入uboot模式,main_loop()
-
启动内核,bootcmd命令(两种执行方式:倒计时结束无输入/uboot下手动输入)
-
将linux内核压缩文件zImage和设备树文件.dbt从emmc或者SD卡拷贝到DRAM中
-
启动内核,bootz/bootm
-
kernel_entry()(内核的入口函数,内核镜像第一行代码)
kernel_entry(r0,r1,r2); 为汇编函数,因为内核刚开始为汇编代码。r0:0,r2:机器ID,r3:如果使用设备树则为设备树首地址,不使用设备树则为uboot传递给linux的参数首地址。
-
-
uboot为什么要关闭catch和MMU
Catch:cpu内部的一个2级缓存,用来存储数据和指令。
MMU:内存管理单元,是中央处理器(CPU)中用来管理虚拟存储器、物理存储器的控制线路, 同时也负责虚拟地址映射为物理地址。
原因:刚上电的时候,CPU还不能管理MMU与catch,上电的时候MMU必须关闭,指令catch可关闭,可不关闭,但数据catch一定要关闭,否则可能导致刚开始的代码里面,去取数据的时候,从catch里面取,而这时候RAM中数据还没有catch过来,导致数据预取异常。
为什么要传参数给内核
uboot已经完成了硬件的初始化,已经匹配了这个开发板,但每个开发板都有不同的硬件,如果内核能适配所有的开发板,那内核会变的很庞大,所以内核不会适配所有的开发板,此时内核对开发板是一无所知的,所以要想启动内核,uboot必须给内核传递一些必要的信息来告诉内核开发板是什么样子的(当前所处的环境)