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 会判定该介质启动失败,转而尝试下一介质。

DCD 的生成通常由 NXP 提供的工具(如 i.MX 的 mkimage 或专用 DCD 生成脚本)根据 DDR 配置参数自动产生,不建议手工逐条编写。修改 DDR 参数后必须重新生成 DCD,否则会出现“SPL 能跑但 DDR 容量识别错误”或“随机死机”。

三、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 环境或内核镜像。

i.MX 9 启动链路:从 Boot ROM 到 Linux 内核 启动介质选择 BOOT_MODE 引脚 + eFuse BOOT_CFG SD → eMMC → QSPI 失败则串行下载 Boot ROM 读取固定偏移 0x400 解析 IVT 执行 DCD 加载 SCU 固件 搬运并跳转 SPL SPL 运行于片内 SRAM 初始化串口/DDR 从介质读取 U-Boot 搬运到 DDR 跳转 U-Boot U-Boot 运行于 DDR 完整外设初始化 加载环境变量 执行 bootcmd 引导内核 IVT 与 DCD 在镜像中的位置 0x000 0x400 IVT DCD SCU FW IVT 指向 DCD、Boot Data 与入口地址 DCD 在 DDR 可用前配置控制器与时钟 按阶段定位启动故障 无任何串口输出 查 Boot ROM / DCD 有 SPL 无 U-Boot 查介质读取 / DDR 有 U-Boot 无内核 查环境变量 / 镜像 关键判断依据 • IVT 偏移错误或校验失败 → Boot ROM 跳过该介质,继续尝试下一启动项 • DCD 中 Check 命令读回值不符 → 该介质启动失败,常见于 DDR 参数不匹配 • SCU 固件缺失或地址错误 → SPL 访问电源域/时钟失败,表现为早期卡死 • SPL 能打印但搬运失败 → 检查介质读取偏移、U-Boot 镜像大小与 DDR 目标地址

五、启动镜像的组成与制作要点

一个可被 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 配置和启动脚本。把日志与上述阶段对应起来,就能快速缩小问题范围,而不是盲目更换镜像或反复烧写。