Bootloader的启动流程

来源:互联网 发布:javzoo2016最新域名 编辑:程序博客网 时间:2024/05/16 12:30

Bootloader启动大多数都分为两个阶段。第一阶段主要包含依赖于CPU的体系结构硬件初始化的代码,通常都用汇编语言来实现。这个阶段的任务有:

基本的硬件设备初始化(屏蔽所有的中断、关闭处理器内部指令/数据Cache等)。

为第二阶段准备RAM空间。

如果是从某个固态存储媒质中,则复制Bootloader的第二阶段代码到RAM。

设置堆栈。

在第一阶段中为什么要关闭Cache?通常使用Cache以及写缓冲是为了提高系统性能,但由于Cache的使用可能改变访问主存的数量、类型和时间,因此Bootloader通常是不需要的。

跳转到第二阶段的C程序入口点。

第二阶段通常用C语言完成,以便实现更复杂的功能,也使程序有更好的可读性和可移植性。这个阶段的任务有:

初始化本阶段要使用到的硬件设备。

检测系统内存映射。

将内核映像和根文件系统映像从Flash读到RAM。

为内核设置启动参数。

调用内核。

在U-Boot中,我们通过下面两行代码实现了两个阶段的工作交接:

ldr pc, _start_armboot  _start_armboot: .word start_armboot 

该函数一般是不返回的,但也有些Bootloader在此函数返回后直接重新启动目标板,在vivi中是通过下面的代码实现的:

bl main             @ call main   mov pc, #FLASH_BASE @ otherwise, reboot 

Bootloader调用Linux内核的方法是直接跳转到内核的第一条指令处,即直接跳转到MEM_START+0x8000地址处。在跳转时必须满足下列条件。

(1)CPU寄存器的设置。

R0为0;

R1为机器类型ID;

R2为启动参数,标记列表在RAM中的起始基地址。

(2)CPU模式。

必须禁止中断(IRQs和FIQs);

CPU必须设置为SVC模式。

(3)Cache和MMU的设置。

MMU必须关闭;

指令Cache可以打开也可以关闭;

数据Cache必须关闭。

如果用C语言,可以像下列示例代码这样来调用内核:

void (*theKernel)(int zero, int arch, u32 params_addr) = (void (*)(int, int, u32))KERNEL_RAM_BASE;  M  theKernel(0, ARCH_NUMBER, (u32) kernel_params_start)。 

以上只是介绍了一些Bootloader的基本概念及其基本流程,从下一节开始,我们会介绍Bootloader的代码以加深对Bootloader的理解。顺利阅读这些代码需要读者对ARM汇编指令很熟悉,同时还要了解ARM编程模型等。推荐的参考资料包括:

《ARM920T技术参考手册》http://www.arm.com/pdfs/DDI0151C_920T_TRM.pdf

詹荣开. 《嵌入式系统Boot Loader技术内幕》http://www-128.ibm.com/developerworks/ cn/linux/l-btloader/index.html

原创粉丝点击