2. BootROM 启动流程全景:上电复位、CPU 从复位向量取指、BootROM 代码执行、硬件初始化

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

很多人觉得 BootROM 启动很神秘。其实说白了,就是芯片从「死」到「活」的第一个步骤。我做了十几年固件,每次调试启动失败,最后发现的问题往往都出在这个阶段。所以,把这一章吃透,后面会省很多力气。

2.1 上电复位:芯片的「第一口气」

按下电源键,或者系统刚上电,芯片内部并不是瞬间就稳定了。电压会有一个爬升过程,时钟也需要时间起振。这时候,芯片内部有一个硬件模块叫 POR(Power-On Reset,上电复位),它负责做一件事:

  • 监测电源电压是否达到稳定阈值
  • 监测外部复位引脚是否释放
  • 等待时钟 PLL 锁定

当这三个条件都满足后,POR 会释放一个内部复位信号。这个信号会告诉 CPU 核心:「可以开始干活了」。

我的经验: 有些芯片的 POR 阈值是可编程的。我曾经遇到一个项目,因为电源纹波偏大,导致 POR 反复触发,芯片一直无法正常启动。后来在电源端加了一个 RC 延时电路才解决。所以,硬件设计时一定要留出足够的复位去抖时间。

2.2 CPU 从复位向量取指:第一行代码在哪?

CPU 被复位后,它的程序计数器(PC)会被硬件强制设置为一个固定地址。这个地址就是 复位向量(Reset Vector)。

不同的架构,复位向量位置不一样:

架构 复位向量地址 说明
ARM Cortex-M 0x00000000(向量表基址) 从该地址取栈顶指针,再取复位中断入口
ARM Cortex-A 0x00000000 或 0xFFFF0000 由硬件配置引脚决定
RISC-V 0x00000000 或 0x80000000 由 mtvec 寄存器复位值决定
Xtensa(ESP32) 0x40000000 直接映射到内部 ROM

CPU 从这个地址读到的第一条指令,就是 BootROM 的第一行代码。注意,这时候 DDR/SDRAM 还没有初始化,CPU 只能访问芯片内部的 SRAM 或 ROM。

避坑指南: 我曾经调试过一个 RISC-V 芯片,复位向量默认是 0x00000000,但 BootROM 实际映射在 0x00010000。硬件团队忘记配置地址重映射,导致 CPU 取到的全是 0xFFFFFFFF,直接跑飞。所以,拿到新芯片,第一件事就是确认复位向量和 BootROM 的物理地址是否匹配。

2.3 BootROM 代码执行:芯片的「自检与引导」

CPU 开始执行 BootROM 代码后,会按顺序做以下几件事:

  1. 设置栈指针 —— 因为后面要调用 C 函数,必须先有栈。
  2. 初始化关键硬件 —— 比如时钟、看门狗、中断控制器。
  3. 检查启动模式 —— 通过 GPIO 电平或 eFuse 判断是从 Flash、UART 还是 USB 启动。
  4. 加载并验证启动镜像 —— 从启动介质读取第一级 Bootloader,校验签名或 CRC。
  5. 跳转到下一级代码 —— 将控制权交给 SPL 或 U-Boot。

这个过程,我习惯把它叫做 「芯片的自我认知阶段」。因为这时候芯片还不知道自己要从哪里启动,需要先「问」一下硬件引脚。

核心要点: BootROM 是只读的,出厂后无法修改。所以它的代码必须极其稳定,不能有 bug。一旦 BootROM 有缺陷,芯片就只能通过「启动回退模式」或「JTAG 修复」来救活。

2.4 硬件初始化:让芯片「活起来」

BootROM 中的硬件初始化,和操作系统启动后的驱动初始化完全不同。它只做最基础、最必要的初始化:

  • 时钟系统:配置 PLL,让 CPU 跑在目标频率。我见过一个项目,PLL 锁定时间太长,导致 BootROM 超时复位,反复重启。
  • 看门狗:先喂一次狗,然后设置超时时间。防止 BootROM 卡死。
  • 中断控制器:默认关闭所有中断,只允许 NMI(不可屏蔽中断)。
  • 内存控制器:如果芯片有内部 SRAM,需要初始化时序。如果是外部 DDR,BootROM 通常不碰,留给下一级 Bootloader。
  • 启动介质接口:比如 SPI Flash 控制器、SD/MMC 控制器、USB 设备控制器。BootROM 需要能用它们读取数据。

嗯,这里要注意:BootROM 的初始化顺序是固定的。你不能先初始化 Flash 再初始化时钟,因为 Flash 控制器依赖时钟。这个顺序在芯片设计阶段就定死了。

2.5 启动流程全景图

下面这张图,把整个流程串起来了。我建议你把它存下来,后面调试启动问题时会经常用到。

BootROM 启动流程全景图 BootROM 启动流程全景图 ① 上电复位 (POR) ② CPU 从复位向量取指 ③ BootROM 代码执行 设置栈指针 初始化关键硬件 检查启动模式 加载并验证镜像 ④ 跳转到下一级 Bootloader 💡 关键说明 • BootROM 是只读的,出厂固化 • 此时 DDR 尚未初始化 • 只能访问内部 SRAM/ROM • 启动模式由 GPIO/eFuse 决定

2.6 几个容易踩的坑

做 BootROM 调试这么多年,我总结了几条血泪教训:

  • 复位向量指向了未初始化的内存 —— 有些芯片复位后内存控制器默认是关闭的,CPU 取指直接挂死。解决办法是确保复位向量落在 ROM 或已使能的 SRAM 区域。
  • 看门狗没有及时喂 —— BootROM 执行时间如果超过看门狗超时时间,芯片会反复复位。我遇到过一例,因为 Flash 读取速度太慢,导致 BootROM 超时,最后只能调整看门狗预分频。
  • 启动模式检测引脚电平不稳定 —— 如果 GPIO 上拉/下拉电阻没焊,或者外部电路有干扰,BootROM 可能检测到错误的启动模式,从错误的介质加载镜像。
我的调试习惯: 每次拿到新板子,我会先用示波器抓一下复位引脚和 BootROM 的片选信号。如果复位释放后 1ms 内没有看到 Flash 片选被拉低,那大概率是 BootROM 根本没跑起来。这时候回头查 POR 和时钟,比查代码更有效。

好了,这一章的内容就是这些。BootROM 启动流程,说白了就是芯片从「死」到「活」的四个关键步骤。理解了这个全景,后面讲烧录流程时,你就能明白为什么有些烧录方式需要先进入「下载模式」—— 那其实就是 BootROM 在启动模式检测阶段做的手脚。