4. Boot ROM与启动流程
i.MX 9 系列上电后,最先运行的并不是我们烧写到 eMMC 或 SD 卡里的 U-Boot,而是固化在芯片内部 ROM 中的一段代码,通常称为 Boot ROM。它承担了“把外部存储中的第一段可执行镜像搬进片内 RAM 并跳转执行”的职责。理解 Boot ROM 的行为,是排查“板子上电无输出”“卡在 SPL”“DDR 初始化失败”等问题的前提。本节围绕启动介质选择、IVT 与 DCD、SCU 固件加载以及 SPL/U-Boot 阶段划分展开。
一、启动介质与启动顺序
i.MX 9 的 Boot ROM 支持多种启动介质,常见包括 eMMC、SD 卡、QSPI NOR、NAND、串行下载(Serial Download,USB/ UART)以及部分型号支持的以太网启动。芯片通过一组 eFuse(熔丝位)和 BOOT_MODE 引脚共同决定启动顺序。典型做法是:BOOT_MODE[1:0] 选择内部 Boot 还是串行下载;在内部 Boot 模式下,Boot ROM 按 eFuse 中配置的 BOOT_CFG 顺序依次尝试各介质,第一个成功加载到有效镜像的介质即被采用。
以一块常见 i.MX 9 评估板为例,假设 eFuse 配置的启动顺序为 SD → eMMC → QSPI,则上电后 Boot ROM 先探测 SD 卡。若 SD 卡存在且偏移处包含合法 IVT,则从 SD 启动;否则继续尝试 eMMC,依此类推。若全部失败,且 BOOT_MODE 允许,则进入串行下载模式,等待主机通过 USB 下载镜像。这一顺序对量产和调试都很关键:调试阶段常把 SD 放在首位,方便替换镜像;量产阶段则把 eMMC 放在首位,避免误插 SD 卡改变启动路径。
二、IVT 与 DCD:Boot ROM 能读懂的第一段数据
Boot ROM 并不理解文件系统,它按固定偏移读取原始扇区。以 SD/eMMC 为例,镜像通常从 0x400 字节(即第 1 个扇区偏移 1KB 处)开始放置 IVT(Image Vector Table)。IVT 是一张“指路表”,告诉 Boot ROM:镜像入口地址在哪、DCD 在哪、Boot Data 在哪、各段长度是多少。Boot ROM 解析 IVT 后,先执行 DCD,再把镜像搬入目标地址并跳转。
DCD(Device Configuration Data)是一段由命令字组成的配置脚本,用于在加载镜像前初始化 DDR 控制器、IOMUX、时钟和电源等关键外设。因为此时 DDR 尚未工作,DCD 中的写操作针对的是芯片内部寄存器地址,而不是 DDR 地址。DCD 命令常见类型包括写数据(Write)、检查数据(Check)和等待(Wait/NOP)。例如,配置 DDR PHY 时,需要按顺序写入一系列寄存器值,并在关键步骤后插入延时,等待 PLL 锁定。若 DCD 中某条 Check 命令读回的值与预期不符,Boot ROM 会判定该介质启动失败,转而尝试下一介质。
三、SCU 固件加载
i.MX 9 内部集成了 SCU(System Controller Unit),它负责电源域管理、时钟门控、复位控制和部分安全功能。SCU 自身运行一段固件(SCU Firmware),通常由 Boot ROM 在启动早期从外部存储或内部 ROM 加载到 SCU 专用 RAM 中。SCU 固件加载成功后,主 CPU 才能通过消息单元(MU)与 SCU 通信,请求开启某些电源域或配置时钟。
在启动流程中,SCU 固件加载位于 DCD 之后、SPL 之前。如果 SCU 固件缺失或校验失败,Boot ROM 可能仍能加载 SPL,但 SPL 在访问被 SCU 管理的电源域或时钟时会失败,表现为“串口无输出”或“卡在时钟初始化”。因此,制作启动镜像时,SCU 固件必须与 IVT、DCD、SPL 一起打包,且地址和长度要与 IVT 中的描述一致。
四、SPL 与 U-Boot 阶段划分
Boot ROM 加载并跳转的第一段用户代码通常是 SPL(Secondary Program Loader)。SPL 运行在片内 SRAM 中,体积受限,因此只做最必要的事:初始化串口用于打印、初始化 DDR(若 DCD 未完成)、从启动介质读取完整的 U-Boot 镜像到 DDR,然后跳转到 U-Boot。U-Boot 运行在 DDR 中,空间充裕,负责更完整的外设初始化、环境变量加载、启动脚本执行,最终引导 Linux 内核。
阶段划分可以概括为:Boot ROM → SPL → U-Boot → Linux Kernel。每一阶段的职责和运行位置不同,排查问题时需要先确认卡在哪一阶段。例如,串口完全无输出,问题可能在 Boot ROM 或 DCD;有 SPL 打印但无 U-Boot 打印,问题可能在 SPL 读取介质或 DDR 搬运;有 U-Boot 打印但内核不启动,问题则在 U-Boot 环境或内核镜像。
五、启动镜像的组成与制作要点
一个可被 Boot ROM 识别的启动镜像,通常由 IVT、Boot Data、DCD、SCU 固件和 SPL 组成,按约定偏移排列。制作时需要注意几点:第一,IVT 中的入口地址必须与 SPL 的链接地址一致;第二,DCD 长度和 SCU 固件长度必须准确写入 IVT 对应字段;第三,镜像总大小不能超过 Boot ROM 单次可搬运的上限,否则需要 SPL 自行从介质继续读取。实际项目中,这些内容一般由 Yocto 的 imx-boot 配方或 NXP 的 mkimage 工具自动打包,开发者只需提供正确的 DDR 配置文件和 SPL/U-Boot 二进制。
理解这条链路后,再看启动日志就会清晰很多:Boot ROM 的打印通常很少甚至没有,SPL 会打印 DDR 容量和介质信息,U-Boot 会打印版本、DRAM 配置和启动脚本。把日志与上述阶段对应起来,就能快速缩小问题范围,而不是盲目更换镜像或反复烧写。