4. i.MX 93启动流程与引导

i.MX 93 上电后的启动过程是一条严格分阶段的信任链:芯片内部固化的 Boot ROM 最先运行,它根据 eFUSE 与启动引脚决定从哪里取第一段代码;随后由 SPL(Secondary Program Loader)完成最关键的 DDR 初始化,把运行环境从片内 SRAM 搬到外部 DRAM;再由 U-Boot 完成外设、镜像校验与启动参数准备,最终加载 Linux 内核与设备树,把控制权交给内核。理解这条链路,是排查“板子不启动、卡在某一阶段、内核起来但外设不工作”等问题的基础。

一、四个阶段各自解决什么问题

Boot ROM 位于芯片内部,不可修改,它只做最小化的工作:读取启动模式(如 eMMC、SD、QSPI、串行下载),从对应介质加载一段带 IVT(Image Vector Table)和 DCD(Device Config Data)的镜像到片内 OCRAM,校验通过后跳转执行。Boot ROM 阶段能访问的存储非常有限,因此它加载的通常是 SPL,而不是完整 U-Boot。

SPL 的核心任务是初始化 DDR 控制器和 PHY,把后续的 U-Boot proper 从启动介质搬到 DDR 中运行。i.MX 93 的 DDR 参数(如 DDR4/LPDDR4 的时序、频率、驱动强度)通常由 NXP 提供的 DDR 工具生成,并以配置文件形式参与编译。SPL 运行在 OCRAM 中,空间小,因此它只包含必要的驱动。

U-Boot proper 运行在 DDR 中,负责更完整的外设初始化、环境变量管理、镜像加载与校验。它可以从 eMMC、SD、网络(TFTP)或 USB 加载内核镜像(Image 或 FIT 镜像)与设备树(.dtb),并把启动参数写入 bootargs,最后通过 booti 或 bootm 跳转到内核入口。

内核加载阶段,Linux 会解析设备树,识别 CPU、内存、时钟、引脚复用、外设控制器等硬件信息,并据此加载对应驱动。设备树配置错误,往往表现为内核能启动但某个外设不可用,或启动日志中出现 probe 失败。

i.MX 93 启动链路:从 Boot ROM 到内核与设备树 Boot ROM 芯片内部固化,不可修改 读 eFUSE / 启动引脚 加载 IVT + DCD 到 OCRAM 校验后跳转 SPL SPL 运行于 OCRAM 初始化 DDR 控制器与 PHY 加载 U-Boot proper 跳转到 DDR 中执行 U-Boot proper 运行于 DDR 外设初始化 / 环境变量 加载 Image / FIT 与 .dtb bootargs → booti / bootm Linux 内核 解析设备树 匹配并 probe 驱动 挂载 rootfs 启动 init 存储与内存层次 Boot ROM (片内) OCRAM (片内 SRAM) DDR (外部 DRAM) eMMC / SD / QSPI rootfs (ext4 / squashfs) 关键镜像与配置产物 SPL + IVT + DCD u-boot.bin / u-boot.itb Image / FIT + .dtb bootargs / bootcmd 调试观察点与典型现象 • 串口无输出:Boot ROM 未找到有效镜像,检查启动模式、IVT 偏移、DCD 校验 • 卡在 SPL:DDR 初始化失败,检查 DDR 配置文件、电源与时钟 • U-Boot 能进但内核不启动:检查 bootargs、Image 地址、.dtb 是否匹配

二、启动介质与镜像布局

i.MX 93 常见的启动介质包括 eMMC、SD 卡、QSPI NOR 和串行下载(USB)。以 SD 卡启动为例,镜像通常按固定偏移写入:SPL 放在 0x400 字节偏移处(具体偏移由 Boot ROM 约定),U-Boot proper 与内核镜像可以放在 FAT 分区或原始偏移处。eMMC 启动时,Boot ROM 会读取 eMMC 的 boot 分区,因此需要先用 mmc partconf 或量产工具把 boot 分区使能并写入 SPL。

镜像中的 IVT 告诉 Boot ROM:镜像入口地址、DCD 位置、自检位置等。DCD 是一段配置脚本,用于在 SPL 运行前设置 DDR 相关寄存器或时钟。若 DCD 写错,Boot ROM 可能在加载阶段就失败,串口没有任何输出。

三、U-Boot 阶段的关键配置

U-Boot 的环境变量决定了内核如何被加载。一个典型的启动命令如下:

setenv bootargs 'console=ttymxc0,115200 root=/dev/mmcblk1p2 rootwait rw'
setenv loadaddr 0x80400000
setenv fdtaddr  0x83000000
fatload mmc 1:1 ${loadaddr} Image
fatload mmc 1:1 ${fdtaddr} imx93-11x11-evk.dtb
booti ${loadaddr} - ${fdtaddr}

其中 console=ttymxc0,115200 指定调试串口,root=/dev/mmcblk1p2 指定根文件系统所在分区。若设备树文件名与硬件不匹配,内核可能无法识别 eMMC 或网络控制器。实际项目中,建议把启动命令固化到 bootcmd,并通过 saveenv 写入环境变量分区。

四、设备树配置与内核加载

设备树是内核识别硬件的依据。以 i.MX 93 EVK 为例,设备树中会描述 UART、I2C、SPI、GPIO、eMMC、以太网等节点。若要在自定义板上使用某个 I2C 传感器,需要在对应 I2C 控制器节点下增加子节点,并配置 reg、compatible 和引脚复用(pinctrl)。例如:

&i2c3 {
    status = "okay";
    clock-frequency = <400000>;
    sensor@48 {
        compatible = "ti,tmp102";
        reg = <0x48>;
    };
};

编译设备树使用 make dtbs,生成 arch/arm64/boot/dts/freescale/imx93-11x11-evk.dtb。内核启动日志中若出现 OF: fdt: ... 与 probe 成功信息,说明设备树被正确解析。若某个外设没有出现,应检查 status 是否为 okay、引脚复用是否冲突、时钟是否使能。

调试启动问题时,优先确认串口输出停在哪个阶段:Boot ROM 无输出、SPL 无输出、U-Boot 命令行出现、内核日志出现,分别对应不同的排查方向。不要一上来就改内核配置。

五、启动流程的验证方法

验证启动链路是否完整,可以按以下顺序观察:上电后串口是否打印 Boot ROM 版本信息;是否出现 SPL 的 DDR 初始化日志;是否进入 U-Boot 命令行并显示 => 提示符;执行 boot 后是否出现内核解压与启动日志;最后是否进入登录提示符。若在 U-Boot 阶段能执行 mmc list、fatls mmc 1:1,说明存储与外设基本正常,问题更可能出在内核镜像或设备树。

对于量产板,建议把 SPL、U-Boot、内核、设备树和 rootfs 的版本号统一记录,并在 U-Boot 环境变量中保留 bootargs 的调试串口配置。这样即使更换 DDR 或 eMMC 型号,也能快速定位是引导链哪一环发生了变化。