Bootloader设计

引导加载程序是系统加电后运行的第一段代码。我们熟悉的 PC 中的引导程序一般由BIOS(Basic Input/Output System) 和位于 MBR(Master boot record) 的 OS bootloader(例如 LILO 或者 GRUB)一起组成。然而在嵌入式系统中通常没有像 BIOS 那样的固件程序,因此整个系统的加载启动任务就完全由 bootloader 来完成。设计bootloader的主要目的在于初始化系统的软硬件环境进行引导启动(“启动加载”模式)以及系统的升级维护(“下载”模式)。

bootloader 是依赖于硬件而实现的,不同的体系结构及板级配置的bootloader 是不同的,比如常见的简单的无外部存储器的STM32所使用的IAP(In Application Programming)及使用外部存储的u-boot。但它们的基本设计原理都是一样的。


阶段设计

由于 Boot Loader 的实现依赖于 CPU 的体系结构,因此大多数 Boot Loader 都分为 stage1 和 stage2 两大部分。依赖于 CPU 体系结构的代码,比如设备初始化代码等,通常都放在 stage1 中,而且通常都用汇编语言来实现,以达到短小精悍的目的。而 stage2 则通常用C语言来实现,这样可以实现复杂的功能,而且代码会具有更好的可读性和可移植性(对于相同的 CPU 以及存储设备,要增加外设支持,阶段 1 的代码可以维护不变,只对阶段 2 的代码进行修改)。

Stage1

  1. 硬件设备初始化

    a. 屏蔽所有的中断。
        为中断提供服务通常是 OS 设备驱动程序的责任,因此在 Boot Loader 的执行全过程中可以不必响应任何中断。中断屏蔽可以通过写 CPU 的中断屏蔽寄存器或状态寄存器(比如 ARM 的 CPSR 寄存器)来完成。       
    b. 设置 CPU 的速度和时钟频率。
    c. RAM 初始化。     
    d. 初始化 LED。
    e. 关闭 CPU 内部指令/数据 cache。
        Bootloader 中所有对地址的操作都是使用物理地址,是实在的实地址,不存在虚拟地址,因此 MMU 必须关闭。Bootloader 主要是装载内核镜像,镜像数据必须真实写回 SDRAM 中,所以数据 cache 必须关闭;而对于指令 cache,不存在强制性的规定,但是一般情况下,推荐关闭指令 cache
  2. 为加载 Boot Loader 的 stage2 准备 RAM 空间

  3. 拷贝 Boot Loader 的 stage2 到 RAM 空间中
  4. 设置好堆栈

  5. 跳转到 stage2 的 C 入口点

Stage2

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

  2. 检测系统内存映射(memory map)

  3. 将 kernel 映像和根文件系统映像从 flash 上读到 RAM 空间中

  4. 设置启动参数
  5. 调用内核

地址规划设计

当 bootloader 阶段设计好之后,需要考虑的是镜像存储的地址分配:总镜像保存在什么地方,阶段 2 对应的镜像会被拷贝到什么地方;内核镜像原先存放在什么地方,bootloader会把它又重新加载到什么地方。

Nor Flash启动

    Norflash像内存一样是直接挂在系统总线上的,这样有足够多的地址线使得CPU能够寻址到每一个存储单元上去,这也意味着CPU能够直接通过总线访问Norflash上存储的内容,同时他还支持XIP(即Execute in place,不用将代码搬到内存中,直接在Norflash上就能运行)。所以在这种启动模式下,可以将整个bootloader放置其中,然后将地址映射到0x00000000,CPU从0x00000000直接启动完成整个bootloader过程。

Nand Flash启动

    Nand flash不能直接挂到系统总线上(一般为8位,数据、指令共用地址线),且他其读写,擦除操作必须依赖Nand flash控制器,这也就意味着Nand flash的存储空间永远不能映射到0x00000000这个地址上去。这时,常见的方式是Nand flash控制器会自动将其前4k内容拷贝到CPU内部的SRAM中。因此stage1的代码就放在这最前面的4k空间中,它先完成外部SDRAM、Nand Flash等必要外设的初始化工作使它们可用之后将整个bootloader从Nand Flash拷贝到SDRAM中,为C语言设置好栈,然后跳转到新拷贝的stage2的C人口处,开始stage2阶段。

由于成本的问题,在发布的产品中我们一般直接唯一使用Nand Flash。

模式设计

对于普通用户来说只需要 bootloader 的启动加载模式,但是对于开发者来说,则需要下载模式,因为他们需要时时刻刻地进行一些镜像的更新。

    具体思路:在 bootloader 做完一些硬件初始化工作后,在加载内核镜像之前,先在一定的时间内等待有没有用户有键盘输入,如果没有,则为启动加载模式,直接加载内核镜像进行启动;如果有,则进入命令行格式,这时开发者就可以根据自己的需要以及 bootloader 的支持情况,做一些其他的工作。模式的转换设计主要在阶段 2 中实现。

猜你喜欢

转载自www.linuxidc.com/Linux/2016-12/138048.htm