2. 嵌入式启动基础
在讨论 U-Boot 之前,必须先理解一个更底层的问题:处理器从按下复位键到执行第一条用户代码,中间究竟发生了什么。很多板级调试问题——串口无输出、启动卡死、镜像校验失败、启动介质切换无效——本质上都发生在 U-Boot 之前,属于“启动链前段”的问题。本节围绕上电复位流程、BootROM 的作用、启动介质类型以及典型启动阶段划分展开,为后续分析 U-Boot SPL、TPL 与主 U-Boot 的衔接建立基础。
一、上电复位流程:从电压稳定到取指
处理器上电并不是“一通电就执行程序”。电源管理芯片(PMIC)或分立电源电路先建立各路电压,复位管理单元等待电源稳定、时钟稳定后释放复位信号。复位释放的瞬间,CPU 内部寄存器被置为确定的复位值,程序计数器(PC)被强制指向一个固定的复位向量地址。这个地址通常位于芯片内部 ROM 或 Flash 映射区,而不是外部 DDR,因为此时 DDR 尚未初始化,无法作为代码运行空间。
复位流程可以概括为几个关键动作:电源建立与稳定、复位信号释放、时钟树初始化、CPU 取复位向量、执行芯片固化的启动代码。对于多核处理器,通常由主核(如 ARM 的 CPU0)先执行,其他核处于等待或由主核后续唤醒。理解这一点很重要:调试时如果发现“只有某个核没起来”,往往不是 U-Boot 的问题,而是复位释放或核间同步配置的问题。
二、BootROM 的作用:芯片内的第一段代码
BootROM 是芯片厂商在硅片内部固化的一段只读代码,用户无法修改。它的核心职责是:在没有任何外部存储可用的情况下,完成最基本的硬件初始化,并按预定策略从启动介质中加载下一阶段代码。BootROM 通常包含以下能力:
- 初始化启动所需的最小外设控制器,如 SPI、SD/eMMC、NAND、USB、UART 等;
- 读取启动模式引脚(Boot Mode Strap)或熔丝位,确定启动介质优先级;
- 从选定介质中读取头部信息,校验签名、校验和或镜像格式;
- 将下一阶段镜像加载到片内 SRAM 或已初始化的 DDR 中;
- 跳转到加载地址执行,并把控制权交给 SPL 或二级引导程序。
BootROM 的行为由芯片决定,但启动顺序通常可通过引脚、eFuse 或 BootROM 配置字调整。例如 Allwinner、Rockchip、NXP i.MX、TI AM335x 等平台都提供不同的启动介质优先级。调试时若发现“从 SD 卡启动失败但从 USB 可以”,往往说明 BootROM 的启动模式选择或介质探测顺序与预期不一致。
三、启动介质类型与选择逻辑
嵌入式系统常见的启动介质包括 SPI NOR、SPI NAND、并行 NAND、eMMC、SD 卡、USB、UART、以太网等。不同介质的访问方式、初始化复杂度、可靠性和成本差异很大。BootROM 一般按固定优先级依次尝试,直到某个介质上找到合法镜像为止。
| 启动介质 | 典型接口 | 特点 | 常见用途 |
|---|---|---|---|
| SPI NOR | SPI/QSPI | 可直接映射执行,容量小,可靠性高 | 小型系统、BootROM 后直接运行 |
| SPI NAND | SPI | 成本低,容量较大,需坏块管理 | 中低端嵌入式产品 |
| eMMC | MMC/SDIO | 容量大,速度快,支持分区 | 主流消费与工业设备 |
| SD 卡 | SDIO/SPI | 可插拔,便于开发调试 | 开发板、量产烧录 |
| USB/UART | USB/串口 | 无需外部存储,依赖主机工具 | 工厂烧录、救砖 |
选择启动介质时,需要同时考虑 BootROM 支持能力、硬件引脚配置、镜像格式和烧录方式。例如某些芯片的 BootROM 只支持从 eMMC 的 boot 分区读取,而不支持 user 分区;某些平台要求 SD 卡镜像必须带特定头部。忽略这些约束,就会出现“镜像明明写进去了却启动不了”的情况。
四、典型启动阶段划分:从 BootROM 到操作系统
为了便于分析和调试,通常把嵌入式启动链划分为若干阶段。一个典型的 ARM 嵌入式平台启动阶段如下:
- BootROM 阶段:芯片固化代码,完成最小初始化并加载 SPL。
- SPL/TPL 阶段:在片内 SRAM 中运行,初始化 DDR、时钟和必要外设,加载主 U-Boot。
- 主 U-Boot 阶段:运行在 DDR 中,提供命令行、驱动模型、环境变量和操作系统加载能力。
- 内核与根文件系统阶段:U-Boot 加载 Linux 内核、设备树和根文件系统,跳转执行。
下面用一张信号链/阶段关系图展示从复位到内核的完整路径,图中标注了各阶段运行位置、关键动作和典型输出。
五、案例与误区复盘
某工业网关板使用 i.MX6ULL,设计为从 eMMC 启动。量产时发现部分板卡上电后串口无任何输出,但同一镜像写入 SD 卡可以正常启动。排查后发现,eMMC 的 boot 分区未烧录 SPL,而 BootROM 默认优先从 eMMC boot 分区读取,读取失败后并未回退到 SD 卡,导致“无输出”。解决方法是使用 mfgtool 或 dd 命令将 SPL 写入 eMMC boot 分区,或调整启动引脚优先级。
另一个常见误区是把 U-Boot 主镜像直接烧到启动介质偏移 0 处,而忽略了 SPL 的头部要求。BootROM 通常只识别带特定 IVT、Boot Header 或校验和的镜像,裸 U-Boot 二进制不会被加载。正确做法是使用厂商提供的 mkimage、imx-mkimage 或 build 脚本生成完整启动镜像。
# 典型启动日志片段
U-Boot SPL 2023.04 (Jan 10 2024 - 10:22:31)
Trying to boot from MMC1
U-Boot 2023.04 (Jan 10 2024 - 10:22:31 +0800)
CPU: i.MX6ULL 792 MHz
DRAM: 512 MiB
MMC: FSL_SDHC: 0, FSL_SDHC: 1
Loading Environment from MMC... OK
掌握本节内容后,再分析 U-Boot 启动链时,就能清楚地区分“BootROM 没找到镜像”“SPL 没初始化好 DDR”“主 U-Boot 没加载内核”这三类问题,从而快速定位故障阶段,而不是在 U-Boot 源码中盲目搜索。