嵌入式Linux设备驱动程序开发指南(原书第2版)
上QQ阅读APP看书,第一时间看更新

1.6 Linux启动过程

下面这些是嵌入式Linux启动的主要步骤:

1. 启动过程开始于POR(上电复位),此时硬件复位逻辑强制ARM核心从片上启动ROM执行初始指令。启动ROM可以支持好几种设备(例如NOR闪存、NAND闪存、SD/eMMC)。在i.MAX7D处理器上,片上启动ROM还会配置并启动DDR内存控制器。DDR技术是不同设备板之间潜在的关键差异。如果在DDR技术方面有差异,应该移植DDR初始化程序。i.MAX7D的初始化程序被编码在U-Boot映像的引导起始区的DCD表里。DCD(设备配置数据)允许启动ROM代码从驻留在引导设备上的外部引导加载器获取SoC配置数据。举个例子,DCD可用于对DDR控制器进行配置,以获得最佳设置,并提高启动性能。在设定了DDR控制器后,启动ROM把U-Boot映像数据加载到片外DDR里,并运行它。

Microchip SAMA5D2处理器同样嵌入了启动ROM代码。在设备重启时判断BMS(启动模式选择)引脚的状态来决定是否使能它。ROM代码扫码不同的媒介设备的内容,例如串行闪存、NAND闪存、SD/MMC卡和串行EEPROM。ROM代码从NAND闪存获取AT91Bootstrap,并将其放在片内SRAM上。AT91Bootstrap是用于SAMA5D2 SoC芯片的二级引导加载程序,它提供了一组算法来管理硬件初始化,如时钟速度配置、PIO设置和DRAM初始化。AT91Bootstrap将从NAND闪存中获取U-Boot并将其放到DDR RAM上。

在其他处理器上,第二级引导加载程序叫作SPL。

2. U-Boot将内核映像和已编译好的设备树二进制文件加载到RAM中,并将设备树二进制文件的内存地址作为启动参数的一部分传递到内核中。

027-01

图1-3 加载内核映像和设备树

3. U-Boot跳转到内核代码。

4. 内核执行底层初始化,启用MMU、创建页面的初始表并设置缓存。这是在arch/arm/kernel/head.s中完成的。head.s文件包含那些CPU体系结构特定的与平台无关的初始化代码。然后,系统切换到与体系结构无关的内核启动函数start_kernel()中。

5. 内核运行位于init/main.c中的start_kernel()函数:

  • 初始化内核(例如内存、调度、中断等)。
  • 初始化静态编译的驱动程序。
  • 根据从U-Boot传递到内核的启动参数挂载根文件系统。
  • 执行第一个用户进程init。默认的情况下,在initramfs中是/init,在常规文件系统中是/sbin/init。在嵌入式Linux设备中通常可以找到的三个init程序,分别是BusyBox初始程序、System V初始程序和systemd。如果使用System V,则进程init会读取其配置文件/etc/inittab,并执行配置脚本,实现系统的最终初始化。

在图1-4中,你可以看到嵌入式Linux的启动过程:

028-01

图1-4 嵌入式Linux启动过程