2. 启动流程基础:CPU复位后的第一条指令、启动介质选择与设备优先级

芯片上电那一刻,CPU 到底在干什么?

很多人觉得启动就是“加载操作系统”,其实没那么简单。从复位到第一条指令执行,中间藏着不少门道。我做了这么多年嵌入式,见过不少工程师在这块栽跟头——板子焊好了,死活起不来,最后发现是启动介质配置错了。

这一章,我们就从 CPU 复位后的第一行代码讲起,把启动介质的选择逻辑和优先级判定彻底说清楚。

2.1 复位向量:CPU 的第一口“奶”

CPU 复位后,内部寄存器会被硬件强制初始化。PC(程序计数器)会被赋一个固定值——这个值就是复位向量(Reset Vector)。

不同架构的复位向量地址不一样:

架构 复位向量地址 说明
ARM Cortex-M 0x00000000(向量表基址) 从该地址取栈指针,0x00000004 取复位处理函数地址
ARM Cortex-A 0x00000000 或 0xFFFF0000 由硬件配置引脚决定,通常从 0x00000000 启动
x86 0xFFFFFFF0 传统 BIOS 的入口,位于 4GB 地址空间顶端
RISC-V 0x00000000 或自定义 由具体芯片设计决定,常见为 0x80000000

关键点:复位向量指向的地址,必须是非易失性存储介质(ROM/NOR Flash)的映射区域。如果这个地址是空的,CPU 就会“跑飞”。

我个人习惯在项目初期先确认芯片的复位向量地址,然后检查 BootROM 是否真的映射到了那个位置。有一次,我发现某款 SoC 的 BootROM 默认映射在 0x00000000,但板级设计把 NOR Flash 接到了另一个片选上——结果 CPU 复位后读到的全是 0xFF,直接死机。

2.2 第一条指令:BootROM 的“开场白”

CPU 从复位向量取到的第一条指令,通常位于芯片内部的 BootROM 中。BootROM 是芯片出厂时固化的一段只读代码,不可修改。

这条指令做什么?

  • 初始化基础硬件:关闭中断、设置栈指针、配置时钟(至少让 CPU 能跑起来)。
  • 检测启动模式:读取芯片的启动模式选择引脚(BOOT_MODE[1:0] 之类的),判断从哪种介质启动。
  • 跳转到启动加载器:根据检测结果,从对应介质加载下一级代码(SPL、U-Boot、或直接加载 OS)。

嗯,这里要注意:BootROM 的代码量非常有限,通常只有 4KB~64KB。所以它只能做最基础的事情——说白了,就是“把接力棒交给下一棒”。

实战经验:我在调试某款 ARM SoC 时,发现 BootROM 执行后系统卡死。用逻辑分析仪抓片选信号,发现 BootROM 根本没去访问外部 Flash。后来查手册才知道,该芯片的 BootROM 会先检查一个“启动有效标志”——如果该标志被擦除,BootROM 会进入下载模式,等待串口或 USB 烧录。这个坑,我踩了整整两天。

2.3 启动介质选择:NOR Flash、NAND Flash、eMMC、SD 卡

BootROM 检测到启动介质类型后,会用对应的协议去读取数据。不同介质的电气特性和读取方式完全不同。

2.3.1 NOR Flash

NOR Flash 支持随机访问,CPU 可以直接在 NOR Flash 上执行代码(XIP,eXecute In Place)。

  • 优点:无需拷贝到 RAM,启动速度快。
  • 缺点:容量小(通常 8MB~64MB),写入慢,价格高。
  • 典型场景:BIOS/UEFI 固件存储、小容量嵌入式系统。

2.3.2 NAND Flash

NAND Flash 是块设备,不能直接执行代码。BootROM 必须先把 NAND 中的前几页读到内部 SRAM 中,然后跳转执行。

  • 优点:容量大(GB 级别),成本低。
  • 缺点:存在坏块,需要 ECC 校验,读取速度受限于接口。
  • 典型场景:嵌入式 Linux 系统、消费电子。

避坑指南:我曾经遇到过 NAND Flash 启动失败的问题。原因是 BootROM 读取 NAND 时,默认的 ECC 强度不够,导致前几页数据出现位翻转。后来我强制在 BootROM 配置中启用更强的 ECC 算法,问题才解决。如果你用 NAND 启动,务必确认 BootROM 的 ECC 能力与 NAND 的坏块管理策略匹配。

2.3.3 eMMC

eMMC 内部集成了 Flash 控制器和坏块管理,对外提供标准的 MMC 接口。BootROM 通过 MMC 协议读取数据。

  • 优点:无需关心坏块,接口标准化,读写速度快。
  • 缺点:启动过程比 NOR 复杂,需要初始化 MMC 控制器。
  • 典型场景:手机、平板、高端嵌入式设备。

2.3.4 SD 卡

SD 卡与 eMMC 协议类似,但通常用于可插拔场景。BootROM 通过 SPI 或 SDIO 接口访问。

  • 优点:可更换,方便调试和量产。
  • 缺点:速度受限于接口,可靠性不如 eMMC。
  • 典型场景:开发板、单板计算机(如 Raspberry Pi)。
介质类型 是否支持 XIP 是否需要 ECC 典型容量 启动速度
NOR Flash 是 否 8MB~64MB 快
NAND Flash 否 是 128MB~8GB 中
eMMC 否 内置 4GB~128GB 快
SD 卡 否 内置 1GB~1TB 中

2.4 启动设备优先级:谁先被“翻牌”?

大多数 SoC 支持从多种介质启动。BootROM 会按照预设的优先级顺序尝试每个介质,直到成功读取到有效启动代码。

优先级通常由以下因素决定:

  • 硬件引脚电平:芯片的 BOOT_MODE 引脚组合决定第一优先级。
  • 熔丝/OTP 配置:一次性可编程区域,固化启动顺序。
  • BootROM 内部逻辑:某些芯片固定先尝试 SPI NOR,再尝试 NAND,最后尝试 SD 卡。

举个例子,某款 i.MX 系列 SoC 的默认启动顺序是:

  1. eMMC(如果检测到有效启动标志)
  2. NAND Flash(如果 eMMC 失败)
  3. SD 卡(如果 NAND 也失败)
  4. USB 下载模式(所有介质都失败后)

注意:启动优先级不是死的。你可以通过修改 OTP 或外部引脚来改变顺序。但 OTP 是一次性的,改错了就得换芯片。我建议在开发阶段用引脚配置,量产时再固化 OTP。

你想想看,如果 BootROM 按顺序尝试每个介质,但某个介质上恰好有残留数据(比如一块旧 Flash 没擦干净),BootROM 可能误判为“有效启动代码”,然后加载失败。这就是为什么很多芯片要求启动介质的前几个字节必须是特定的“启动签名”(Boot Signature)。

2.5 启动流程总览图

下面这张图展示了从 CPU 复位到 BootROM 选择启动介质的完整流程:

BootROM 启动流程与介质选择 BootROM 启动流程与介质选择 CPU 复位 读取复位向量(0x00000000) BootROM 执行 检测启动模式引脚 / OTP 按优先级尝试启动介质 NOR Flash NAND / eMMC SD 卡 所有介质尝试失败后,BootROM 进入下载模式(USB/UART)

2.6 实际项目中的启动配置建议

说了这么多理论,最后给几条实在的建议:

  • 开发阶段用 SD 卡或 USB 下载模式:方便反复烧录,不用频繁擦写 Flash。
  • 量产前务必确认启动介质优先级:用硬件引脚模拟所有可能的启动失败场景,确保 BootROM 能正确 fallback。
  • 检查启动签名:如果 BootROM 要求特定签名(比如 0xAA55 或自定义 Magic Number),确保你的启动镜像头部包含它。
  • 预留调试接口:哪怕产品最终只用 eMMC 启动,也建议在板上留一个 SPI NOR Flash 焊盘——万一 eMMC 坏了,还能从 NOR 启动救砖。

我的习惯:每次拿到新开发板,第一件事就是看 BootROM 的启动日志。通过串口输出,你能看到 BootROM 尝试了哪些介质、在哪一步失败了。这些日志是调试启动问题的最直接线索——比看原理图快多了。