启动模式与设备枚举:常见的启动设备、Boot Mode Pins 与优先级轮询
芯片上电后,第一件事就是去取指令、开始执行。但有个问题——它该从哪儿取?
我早年做第一个 SoC 项目时,以为 BootROM 就是死板地从 Flash 读代码。结果板子焊回来,死活起不来。后来发现是 Boot Mode Pins 的电平没拉对,芯片一直在等 UART 数据。嗯,从那以后,我对启动模式这部分就再也不敢马虎了。
说白了,BootROM 的启动流程就是一套「找启动设备」的逻辑。它得知道:从哪个设备读代码?按什么顺序找?找不到怎么办? 这一章,我们就来拆解这些细节。
常见的启动设备
不同的芯片、不同的应用场景,支持的启动设备差别很大。但主流的基本就这几种:
| 设备类型 | 接口 | 典型容量 | 读速度 | 特点 |
|---|---|---|---|---|
| NAND Flash | 8-bit/16-bit 并行 | 1Gb ~ 256Gb | 中 | 容量大、有坏块、需 ECC |
| eMMC | MMC/SD 协议 | 4GB ~ 256GB | 快 | 内置控制器、坏块管理透明 |
| SPI NOR Flash | SPI/QSPI | 1MB ~ 256MB | 中 | XIP 执行、可靠性高 |
| UART | 串口 | N/A | 慢 | 用于调试、下载 |
| USB | USB 2.0/3.0 | N/A | 快 | 支持 DFU、大文件传输 |
启动模式选择引脚(Boot Mode Pins)
芯片怎么知道该从哪个设备启动?靠的是硬件引脚。
一般芯片会留出 2~4 个 GPIO,在复位时采样它们的电平状态。这些引脚就叫 Boot Mode Pins。BootROM 在初始化完最基本的硬件(时钟、引脚复用)后,第一件事就是读这些引脚的电平。
举个例子,一个典型的配置可能是这样:
| BOOT[1:0] | 启动设备 | 备注 |
|---|---|---|
| 00 | SPI NOR | 从片选 0 启动 |
| 01 | eMMC | 从 boot partition 启动 |
| 10 | NAND | 从第 0 块启动 |
| 11 | UART | 等待串口下载 |
启动设备优先级与轮询
Boot Mode Pins 只是第一层选择。很多时候,芯片会支持 启动设备优先级 和 轮询机制。
什么意思呢?比如你设定了从 SPI NOR 启动,但 SPI NOR 里没烧录代码,或者读出来校验失败。这时候 BootROM 不会死等,而是会按预设的优先级列表,挨个尝试下一个设备。
典型的轮询流程是这样的:
- 读取 Boot Mode Pins,确定首选启动设备。
- 初始化该设备的控制器(比如 SPI 控制器、NAND 控制器)。
- 读取设备头部信息(通常是前 512 字节或前 4KB)。
- 校验头部签名或 CRC。如果通过,加载并跳转。
- 如果校验失败,记录错误,切换到下一个设备。
- 所有设备都试过?进入 recovery 模式(比如 UART 等待)。
下面这张图,就是 BootROM 启动设备轮询的典型流程:
设备枚举的细节
设备枚举不只是「读一下设备 ID」那么简单。BootROM 需要做几件事:
- 识别设备类型: 比如同样是 SPI 接口,NOR Flash 和 NAND Flash 的指令集完全不同。
- 获取设备参数: 容量、页大小、块大小、擦除时间等。这些信息通常通过读 ID 指令或 JEDEC 标准获取。
- 初始化控制器: 根据设备参数配置时钟、时序、DMA 等。
- 验证可用性: 比如写一个测试模式,读回来确认总线是否正常。
你想想看,如果 BootROM 不做这些检查,直接按固定时序去读,万一设备没焊好或者总线短路,芯片可能就死机了。所以,健壮性 是 BootROM 设备枚举的第一原则。
优先级表的配置
启动设备的优先级,通常固化在 BootROM 里,但有些芯片允许通过 OTP 或 eFuse 来修改。典型的优先级表长这样:
| 优先级 | 设备 | 条件 |
|---|---|---|
| 1(最高) | SPI NOR | Boot Mode Pins = 00 |
| 2 | eMMC | Boot Mode Pins = 01 |
| 3 | NAND | Boot Mode Pins = 10 |
| 4 | UART | Boot Mode Pins = 11 或所有设备失败 |
这里有个细节:优先级和 Boot Mode Pins 是两回事。Boot Mode Pins 决定的是「首选设备」,而优先级决定的是「首选失败后,下一个试谁」。有些芯片允许你通过软件配置优先级表,但大部分是写死的。
嗯,说到这儿,我想起一个案例。有个客户做工业控制器,要求启动时必须先尝试从 UART 下载固件,如果 5 秒内没收到数据,再切到 SPI NOR。但他们的芯片 BootROM 不支持这种「超时优先」的逻辑。最后我们只能在外围加了一个 CPLD,在复位时控制 Boot Mode Pins 的电平切换,模拟出这个效果。所以,了解你的芯片 BootROM 的灵活性边界,比什么都重要。
这一章的内容就到这里。启动模式与设备枚举,说白了就是 BootROM 的「导航系统」。它决定了芯片从哪里找代码、按什么顺序找、找不到怎么办。理解了这些,你就能更好地设计启动流程,也能更快地定位启动失败的问题。