2、SoC启动流程全景:从复位到操作系统加载的完整链路、启动介质类型

好,咱们正式开始聊启动流程。说实话,很多工程师做了好几年嵌入式开发,对启动的理解还停留在「上电→跑代码」这个层面。但你要是去调一次板子起不来的问题,就知道这里面门道有多深了。

我个人习惯把SoC启动分成三个阶段:硬件复位→BootROM→二级引导。今天咱们就把这条链路彻底捋清楚。

2.1 从复位向量说起

芯片上电那一刻,发生了什么?

嗯,首先硬件复位逻辑会强制PC指针跳到一个固定地址。对ARM Cortex-A系列来说,这个地址通常是0x00000000或者0xFFFF0000。对RISC-V,一般是0x80000000附近。这个地址里放的,就是BootROM的第一条指令。

我在项目中遇到过一块国产芯片,复位后PC指向了0x1C000000,当时查手册查了半天才找到。所以你看,不同厂商的约定差别很大,千万别想当然。

核心要点:复位向量是CPU执行的第一个地址,它指向BootROM区域。BootROM是芯片内部固化的只读存储器,出厂就写死了,用户改不了。

2.2 BootROM到底干了什么?

BootROM的代码量通常很小,几KB到几十KB。它要做的事情其实很纯粹:

  1. 初始化最基本的硬件——比如时钟、SRAM、堆栈指针。注意,它不会初始化DDR,因为DDR初始化需要复杂的训练流程,BootROM里放不下那么多代码。
  2. 检测启动介质——从哪启动?是NOR Flash、NAND Flash、eMMC还是SD卡?BootROM会按照芯片厂商预设的优先级去轮询。
  3. 加载二级引导程序——从检测到的介质中读取一段代码(通常是SPL或BL2),放到内部SRAM里,然后跳转过去执行。

说白了,BootROM就是个「快递员」,它自己不干重活,只负责把真正的启动代码搬到内存里。

一个小技巧:调试启动问题时,可以用示波器量一下BootROM访问外部存储器的片选信号。如果片选没拉低,说明BootROM根本没认到你的存储介质。我曾经靠这个办法半小时定位了一个eMMC虚焊的问题。

2.3 启动介质类型详解

不同的启动介质,特性天差地别。咱们一个一个说。

2.3.1 NOR Flash

NOR Flash最大的特点是支持XIP(就地执行)。什么意思?就是CPU可以直接在NOR Flash上取指令运行,不需要先把代码拷贝到RAM里。

我记得早期做路由器的时候,很多方案就是用NOR Flash直接跑u-boot。优点是启动快、电路简单,缺点是容量小、写入慢。现在NOR Flash主要用来存BootROM的备份或者小型的引导代码。

特性 说明
接口 并行(CFI)或SPI
读取速度 快,支持XIP
容量 通常1MB~64MB
典型用途 BootROM备份、小系统引导

2.3.2 NAND Flash

NAND Flash就不一样了。它不支持XIP,因为它的读取方式是按页读取,而且会有坏块。BootROM必须先把NAND Flash前几页的数据读到SRAM里,然后才能执行。

你想想看,这里有个坑:NAND Flash出厂时可能有坏块,如果坏块正好出现在前几页,那BootROM就读不到正确的二级引导程序。所以芯片厂商一般会在NAND Flash的特定位置放一个「启动标志块」,BootROM会跳过坏块去查找。

注意:NAND Flash的ECC校验是必须的。我曾经遇到过一块NAND Flash,读出来的数据偶尔会翻转一位,如果没有ECC,BootROM就会加载到错误的代码,然后系统死得莫名其妙。

2.3.3 eMMC

eMMC本质上就是NAND Flash加了一个控制器,对外暴露MMC接口。BootROM通过MMC协议去访问eMMC,读取特定分区(比如boot0、boot1)里的数据。

eMMC的好处是:不需要你管坏块、不需要你管ECC,控制器全包了。但代价是启动时序比NOR Flash复杂,BootROM需要实现完整的MMC初始化流程。

我个人习惯在eMMC方案的板子上,把二级引导程序放在boot0分区,把内核和文件系统放在用户分区。这样即使文件系统坏了,只要boot0分区完好,系统还能进uboot命令行去救砖。

2.3.4 SD卡

SD卡和eMMC的协议很相似,但SD卡是可插拔的。BootROM检测SD卡时,会先发送CMD0让卡进入空闲状态,然后发送CMD8、ACMD41等命令获取卡的信息,最后读取特定扇区(通常是第0扇区)的MBR或启动代码。

很多开发板(比如树莓派)就是用SD卡启动的。调试阶段特别方便,换一张卡就换一个系统。但量产产品很少用SD卡,因为接触不良的问题太常见了。

2.4 完整启动链路图

下面这张图,是我自己画的SoC启动完整链路。你仔细看,每个箭头都代表一次跳转或加载。

SoC启动完整链路图 上电复位 BootROM执行 初始化时钟/SRAM/堆栈 → 检测启动介质 启动介质检测:NOR Flash / NAND Flash / eMMC / SD卡 加载二级引导程序(SPL/BL2)到SRAM 跳转到二级引导 → 初始化DDR → 加载OS 注:BootROM是芯片内部固化的只读代码,用户无法修改

2.5 避坑指南

最后,分享几个我踩过的坑:

  • 启动介质优先级搞反了——有些芯片默认先从SD卡启动,如果SD卡没插,才去查eMMC。我有一块板子,SD卡槽里插了一张旧卡,结果每次启动都卡在SD卡读取上,拔掉就好了。
  • eMMC的boot分区没使能——eMMC的boot0和boot1分区默认可能是关闭的,需要发CMD0和CMD1去使能。如果BootROM读不到数据,先查一下这个。
  • NAND Flash的页大小不匹配——BootROM通常只支持几种固定的页大小(比如2KB、4KB)。如果你的NAND Flash页大小是8KB,而BootROM不支持,那就启动不了。选型时一定要确认。

嗯,启动流程这块,说白了就是「谁先跑、从哪读、跳到哪」。把这三个问题搞清楚了,大部分启动问题都能迎刃而解。

我的建议:拿到一块新板子,先看芯片手册的「Boot Sequence」章节,把启动介质的优先级和地址映射画出来。这张图比任何代码都重要。

可可精品资料库