芯片启动过程全解析

内容总结自 B 站 Up【蛋饼嵌入式】我提着鞋带拎自己?嵌入式芯片启动过程全解析,彻底理解 bootloader

当你按下电源开关的那一瞬间,第一行代码如何在芯片上运行起来的呢?嵌入式软件代码需要一定的方式烧录到芯片中才能运行,除了物理刻蚀,无论是通讯端口的传输或者调试端口的烧录,都需要驱动程序的支持。所以说是程序烧录了程序,软件启动了软件

这就像自己提着自己的鞋带,把自己拎起来。靴子(Boot),鞋带(Strap),提鞋带(Loader)。这就是Boot Strap Loader的命名来源。通常称BootLoader,中文翻译为自举

BootLoader是芯片最初运行的代码吗?当然不是,其实每一块芯片在出厂时都在其内部的ROM中,烧录了它最基础的软件。CPU 搬运并运行的第一条代码的默认位置,就在ROM的地址空间。所以一切的起始都在硬件上。

以 X86 架构的鼻祖 8086 芯片为例,按下开关的一瞬间,芯片 Reset 引脚接收到了电平跳变,在一连串电路的作用下,代码段寄存器CS恢复成0XFFFF,指令指针寄存器IP恢复成0X0000,他们组合成 20 位的地址正好等于 ROM 中存放第一条代码的位置。之后取出这里的指令在跳转到别处。

ARM 架构的芯片也是类似的过程,对于 32 位的芯片,通电后,PC指针寄存器复位至零地址,随后从中断向量表表头的 reset 向量处获取下一个跳转的地址。这时候的代码已经以二进制形式存储,处理器可以直接搬到自身缓存中运行。有了这部分代码,就能跳转到存放有更多更复杂的代码的地址。执行硬件自检,基本的初始化操作,提供基础的输入输出支持。之后可以将操作系统从外部的存储空间加载到内部。代码就这样接力式的流转起来。

所以我们把出厂就写在ROM里,负责启动后续用户软件的软件,称为Boot ROM或者ROM Code。现在不一定是用只读存储器(Read Only Memory),但是至少是一块掉电不易失的存储器,现在主要用EEPROMNOR Flash。我们一般没有权限修改它,但是它也不完全是黑盒,大部分芯片都会有外部启动配置引脚,通常是以拨码快关的形式。对于 PC 机来说,Boot ROM就是我们常说的BIOS,它也有启动配置途径。而且提供了交互界面,用于配置部分功能和选择后续的引导设备。

除了芯片自带的Boot ROM,还需要再给自己实际的应用程序,写一个二次引导代码或者 N 次引导代码,用作操作系统,文件系统加载等等。我们所说的Bootloader时,其实大多数就是这样的二次引导代码。

这些事其实Boot ROM它也能做,但是Boot ROM实现的功能和配置方法不灵活,但是Bootloader是开发人员可以而完全控制的引导代码。

在设计Bootloader时,MCU的引导步骤就开始和嵌入式 Linux 或者 PC 有所不同。这一定程度与芯片架构所采用的的存储方案有关。

先来说MCU,与SOC相比MCU的主要特征是单核和或多核同构的微处理器,单核或多核同构,主频 < 1GHz,没有MMU内存管理单元,只能运行实时操作系统。常见MCU内核:

程序的主要运行介质为NOR Flash,因为和RAM一样有分离的地址线和数据线。并且可以以字节长度精确寻址,所以程序不需要拷贝到RAM中运行的。

以英飞凌家的 TC27x 系列 MCU 为例,上电后的默认取址位置是0x8FFF 8000,这就是他的Boot ROMNorFlash中的地址。并且这块Boot Rom分为SSWBSLTF

SSW 每次上电必须运行,他会根据写在program flashPFO地址的前 32byte 中的配置字,来决定SSW执行完的跳转地址。我们可以选择一个合适的跳转地址,比如0x80000020,放上自己写的Bootloader。也可以选择不跳转,运行厂家提供的Bootloader(BSL)。

MCU下的Bootloader主要完成的事情有以下:

  • 关闭看门狗,初始化中断和 trap 向量表,进行时钟和外设初始化,让芯片正常运行起来。
  • 提供CAN,UART, ETH等用于通讯功能的驱动,能够接收外部数据传输请求。
  • 提供FLASH的读写与擦除驱动,设计服务来对通讯端口接收到的更新代码进行校验、存储,以及跳转操作系统或后续应用程序代码。
  • 如有必要,还会开发一些基础诊断服务,串口交互程序等等。

那么运行 Linux 的SOC和 PC 的这一过程有何不同呢。还是先看存储方案,运行嵌入式 Linux 的 SoC。一般将它的操作系统,文件系统和他的应用程序放在nand flash中。运行代码前,现将代码搬运到SRAM中,相比MCU多了一道步骤。

对于SOCBoot ROM 和 PC 的BIOS而言,他们结束运行前的最终任务,是将某些代码从nand flash搬运到SRAM中,其中最重要的内容就是Boot Loader

而一般SOCBootloader,又分为SPL(Secondary Program Loader)和uBOOT两个阶段。SPL的 Secondary 就是相对于BootROM而言,他就像是接力赛中的第二棒选手。SPL会初始化更大空间的外部DRAM,再把uBoot搬运到外部DRAM中去运行。uBoot作为第三棒选手,开始运行它的初始化程序。之后再根据系统环境变量,将 OS 内核搬运到外部DRAM中去运行。OS 再完成根文件系统的加载等等等等。