2.5.1程序启动过程:
1.首先u-boot上电后执行的第一个文件为arch/arm/cpu/armv7/start.S文件,start.S文件准备好第二阶段的运行环境。
2.上面start.S执行完毕最终会调用到arch/arm/lib/board.c中的board_init_r函数,函数对会对flash、net、串口等进行初始化,最终会进入死循环,如下:
for (; ; )
{
main_loop (); //进入等待命令解析状态,直到启动内核后,u-boot就退出了。
}
2.5.2 Bootloader的两个阶段
Bootloader的启动过程可以分为单阶段(single Stage)、多阶段(Multi-stage)两种。通常多阶段的Bootloader能提供更为复杂的功能以及更好的可移植性。从固态存储设备上启动的Bootloader大多都是两阶段的启动过程。第一阶段使用汇编来实现,它完成一些依赖于CPU体系结构的初始化,并调用第二阶段的代码;第二阶段则通常使用C语言实现,这样可以实现更复杂的功能,而且代码会有更好的可读性和可移植性。
一般而言,这两个阶段完成的功能可以如下分类:
1.Bootloader第一阶段的功能:
1)硬件设备初始化。
2)为加载Bootloader的第二阶段代码准备RAM空间。
3)设置CPU的速度、时钟频率及终端控制寄存器
4)初始化内存控制器
5)复制Bootloader的第二阶段代码到RAM空间中。
6)设置好栈。
7)跳转到第二阶段代码的C入口点。
在第一阶段进行的硬件初始化一般包括:关闭WATCHDOG、关中断、设置CPU的速度和时钟频率、RAM初始化等。这些并不都是必需的,比如S3C2410/S3C2440的开发板所使用的U-Boot中,就将CPU的速度和时钟频率的设置放在第二阶段。
甚至,将第二阶段的代码复制到RAM空间中也不是必需的,对于NOR FLASH等存储设备,完全可以在上面直接执行代码,只不过相比在RAM中执行效率大为降低。
2.Bootloader第二阶段的功能:
1)初始化本阶段要使用的硬件设备。
2)检测系统内存映射(memory map)。
3)将内核映像和根文件系统映像从FLASH上读到RAM空间中。
4)为内核设置启动参数。
5)调用内核。
C语言代码部分 arch/arm/lib/board.c中的board_init_f是C语言开始的函数也是整个启动代码中C语言的主函数,同时还是整个u-boot的主函数,该函数只要完成如下操作:
1)调用一系列的初始化函数。
2)初始化Flash设备。
3)初始化系统内存分配函数。
4)如果目标系统拥有NAND设备,则初始化NAND(闪存)设备。
5)如果目标系统有显示设备,则初始化该类设备。
6)初始化相关网络设备,填写IP、MAC地址等。
7)进去命令循环(即整个boot的工作循环),接受用户从串口输入的命令,然后进行相应的工作。