1. 课程导入
各位同学,咱们今天聊聊 BootROM。这东西听起来挺底层,其实它就是 SoC 上电后跑的第一段代码。我做了这么多年嵌入式,发现很多工程师对 BootROM 的理解停留在「知道有这么个东西」,真要问它怎么工作、存在哪、为什么非它不可,就说不清了。
这一章,咱们把 BootROM 的底裤扒干净。
1.1 什么是 BootROM
BootROM,全称 Boot Read-Only Memory。说白了,就是芯片出厂时固化在内部的一块只读存储器里的启动代码。这块存储器是 ROM,不是 Flash,也不是 SRAM。你想想看,芯片一上电,CPU 从哪取第一条指令?
对,就是 BootROM。
它有几个关键特征:
- 只读:出厂后不可修改,除非换芯片掩膜
- 片上集成:在 SoC 内部,不需要外部存储器就能运行
- 最先执行:CPU 复位后,PC 指针直接指向 BootROM 入口
- 体积小:通常 4KB ~ 256KB,视芯片复杂度而定
核心认知:BootROM 是 SoC 启动流程的「第一棒」。它不负责加载操作系统,只负责把第二级 Bootloader(比如 U-Boot)从外部存储介质搬进内存,然后跳转过去。
我在项目中遇到过有人问:「BootROM 能不能升级?」答案是——不能。除非你重新流片。所以 BootROM 里的代码必须极其稳定,bug 要少到几乎没有。嗯,这里要注意,BootROM 一旦有 bug,那就是芯片级的硬伤,只能通过后续的 Bootloader 打补丁绕过去。
1.2 BootROM 在 SoC 启动流程中的位置
咱们来看一个典型的 SoC 启动流程。我习惯把它分成四个阶段:
- 复位阶段:硬件复位,CPU 从复位向量取指
- BootROM 阶段:执行片上 ROM 代码,初始化最小系统
- SPL / 二级 Bootloader 阶段:从 Flash/SD/eMMC 加载 U-Boot SPL
- U-Boot 阶段:初始化 DDR、外设,加载内核
BootROM 处在第二阶段,承上启下。它干的事很具体:
- 配置系统时钟和 PLL
- 初始化片内 SRAM(通常很小,几十 KB)
- 检测启动介质(比如先看 SD 卡有没有插,再看 SPI Flash)
- 从选中的介质读取固定偏移处的代码到 SRAM
- 验证签名(如果使能安全启动)
- 跳转到加载的代码
我的经验:调试启动问题时,很多人一上来就查 U-Boot,其实问题往往出在 BootROM 阶段。比如时钟没配好、启动介质检测顺序不对、签名验证失败。我建议先确认 BootROM 有没有正确执行,再往下追。
为什么会这样?因为 BootROM 执行时,DDR 还没初始化,你连打印都看不到。只能靠 GPIO 电平、示波器抓波形、或者芯片自带的调试接口来观察。
下面这张图,是我画的一个典型 SoC 启动流程,你可以看到 BootROM 的位置和它跟其他模块的关系。
1.3 BootROM 的硬件特性与存储介质
聊完位置,咱们看看 BootROM 的硬件底子。这部分我建议你重点理解,因为很多启动问题追根溯源,都是硬件特性没吃透。
1.3.1 存储介质:为什么是 ROM?
BootROM 用 ROM 而不是 Flash,原因很简单:
| 特性 | ROM | Flash | SRAM |
|---|---|---|---|
| 掉电保持 | 是 | 是 | 否 |
| 可修改 | 否(掩膜) | 是 | 是 |
| 读取速度 | 快 | 中等 | 极快 |
| 面积成本 | 低 | 中等 | 高 |
| 上电可用性 | 立即 | 需初始化 | 立即 |
你看,ROM 在「上电可用性」和「成本」上占优。Flash 需要初始化控制器、配置时序,这本身就需要代码——鸡生蛋蛋生鸡的问题。所以 BootROM 必须用 ROM,上电就能读。
注意:有些芯片会用 Mask ROM 或 OTP ROM。Mask ROM 是流片时用光刻掩膜写入的,成本最低但改不了。OTP ROM 可以一次性编程,适合小批量定制。我见过一个项目,OTP 写错了启动介质优先级,结果只能重新流片——教训惨痛。
1.3.2 硬件特性一览
BootROM 的硬件特性,我总结成几个要点:
- 地址映射:BootROM 通常映射在 CPU 的复位向量地址,比如 0x00000000 或 0xFFFF0000。具体看架构,ARM 一般是 0x00000000,RISC-V 可能是 0x80000000 附近。
- 大小限制:受芯片面积限制,BootROM 通常很小。我做过一个 IoT 芯片,BootROM 只有 8KB。大一点的应用处理器,比如 i.MX 系列,也就 128KB 左右。
- 执行环境:BootROM 在片内 SRAM 中执行,此时外部存储器(DDR、Flash)都不可用。所以它只能用 CPU 的通用寄存器、少量片内 SRAM 做临时数据存储。
- 中断处理:BootROM 阶段通常关中断,或者只允许 NMI(不可屏蔽中断)。因为中断向量表还没配好,开中断就是找死。
1.3.3 启动介质检测机制
BootROM 怎么知道从哪加载代码?靠的是启动介质检测。我见过几种常见方案:
- 硬件引脚选择:芯片有 BOOT0、BOOT1 引脚,外部拉高拉低决定启动介质。STM32 就是这么干的。
- 自动探测:BootROM 按固定顺序尝试每个介质,直到成功。比如先试 SD 卡,再试 SPI Flash,最后试 UART。
- fuse 配置:通过芯片内部的 eFuse 或 OTP 区域,烧录启动介质优先级。适合量产时锁定启动方式。
避坑指南:我曾经在一个项目里,BootROM 自动探测顺序是 SD → eMMC → SPI。结果 SD 卡槽没插卡,但卡检测引脚悬空,BootROM 误判为有卡,卡在 SD 初始化超时上。最后加了上拉电阻才解决。所以硬件设计时,启动检测引脚的上下拉一定要处理好。
1.3.4 BootROM 与安全启动
现在很多芯片要求安全启动,BootROM 是安全链的根信任锚点。它会做这几件事:
- 读取外部存储中的二级 Bootloader
- 用公钥验证代码签名
- 验证通过才跳转,否则死循环或进入恢复模式
公钥通常也固化在 BootROM 里,或者存在 OTP 中。这意味着一旦芯片出厂,你能信任的代码就被锁死了。嗯,这里要注意,如果你的产品需要远程升级 Bootloader,安全启动会带来额外的复杂度——你得保证签名密钥的安全。