4. U-Boot移植与启动流程
在i.MX多媒体终端的设计中,U-Boot承担着从芯片上电到操作系统内核接管之间的全部关键工作。与许多MCU直接执行Flash中的代码不同,i.MX系列采用多级启动链,芯片内部固化的Boot ROM先运行,再逐级加载外部程序。理解这条启动链,是移植U-Boot、定位启动故障、实现网络批量部署的前提。
一、i.MX启动链:从Boot ROM到U-Boot proper
i.MX6、i.MX8等处理器的上电启动遵循固定顺序。芯片复位后,CPU首先执行片内Boot ROM中的代码。Boot ROM会读取启动模式引脚(如i.MX6的BOOT_MODE[1:0]与eFUSE配置),决定从eMMC、SD卡、QSPI NOR、NAND或串行下载模式获取镜像。它并不直接加载完整的U-Boot,而是先加载一个很小的镜像头,再根据镜像中的IVT(Image Vector Table)和Boot Data结构,把真正的程序搬移到片内OCRAM或DDR中执行。
因此,i.MX的U-Boot通常被构建为两段:第一段是SPL(Secondary Program Loader),体积小、运行在片内RAM,负责最基础的时钟和DDR初始化;第二段是U-Boot proper,运行在DDR中,提供命令行、驱动模型、网络、文件系统等完整功能。Boot ROM加载SPL,SPL再加载U-Boot proper,这就是典型的“两级引导”。
二、DDR初始化:SPL中最关键也最容易出错的部分
DDR初始化之所以放在SPL而不是U-Boot proper,是因为U-Boot proper本身要被加载到DDR中运行,DDR必须先可用。i.MX的DDR初始化通常由两部分组成:一是MMDC(Multi Mode DDR Controller)寄存器配置,二是DDR PHY的训练。前者设定时序参数,后者通过写电平校准和读门控校准,补偿PCB走线延迟差异。
以i.MX6ULL搭配一颗16位DDR3L为例,SPL中需要配置的关键参数包括:tRCD、tRP、tRAS、tRC、CL、CWL等,这些值来自DDR颗粒数据手册。例如某颗DDR3L-1600颗粒在400MHz时钟下,tRCD约为13.75ns,换算成MMDC的时钟周期数需要向上取整。这些参数通常以结构体形式写在 board/freescale/mx6ull_xxx/ 目录下的 ddr.c 或 spl.c 中,也可能通过DCD表在Boot ROM阶段预置一部分。
判断DDR是否初始化成功,最直接的方法是看SPL串口输出。如果DDR训练失败,SPL通常会打印类似“DDR calibration failed”或直接卡死。此时应优先核对:DDR颗粒型号是否与参数表一致、VREF电压是否正常、PCB是否等长布线、以及是否误用了其他板级的DDR配置。
三、SPL与U-Boot proper的配置
在U-Boot源码中,i.MX平台的SPL和U-Boot proper共用一套配置体系,但通过不同的defconfig和编译目标区分。以i.MX6ULL EVK为例,常用配置为 mx6ull_14x14_evk_defconfig,其中会启用 CONFIG_SPL=y、CONFIG_SPL_DM=y 等选项。编译时执行:
make mx6ull_14x14_evk_defconfig
make -j4
编译产物中,SPL 和 u-boot.img 是两个独立镜像。烧录时,SPL通常写入启动介质的固定偏移(如SD卡的1KB处),u-boot.img则写入后续偏移。i.MX的 imx-mkimage 工具可以把SPL、U-Boot proper、ATF(如i.MX8需要)打包成最终可启动的 flash.bin。
对于i.MX8系列,启动链中还会插入ARM Trusted Firmware(ATF)和SCU固件,顺序变为:Boot ROM → SPL → ATF → U-Boot proper。移植时需要确认ATF的编译产物是否正确嵌入,否则会在SPL跳转后无输出。
四、环境变量与网络启动
U-Boot proper启动后,会读取环境变量。环境变量默认值在 include/configs/mx6ull_evk.h 中定义,运行时保存在eMMC或SPI Flash的 env 分区。常用命令包括 printenv、setenv、saveenv。网络启动依赖 ipaddr、serverip、gatewayip、netmask 等变量,以及 bootcmd 中定义的加载命令。
一个典型的网络启动配置如下:
setenv ipaddr 192.168.1.100
setenv serverip 192.168.1.10
setenv gatewayip 192.168.1.1
setenv netmask 255.255.255.0
setenv bootcmd 'tftp 0x80800000 zImage; tftp 0x83000000 imx6ull-14x14-evk.dtb; bootz 0x80800000 - 0x83000000'
saveenv
执行 run bootcmd 后,U-Boot会通过TFTP从主机下载内核和设备树,然后跳转执行。判断网络启动是否成功,可以观察:TFTP传输是否显示“Bytes transferred”、内核是否打印解压信息、设备树是否被正确识别。若TFTP超时,应检查网线连接、主机TFTP服务是否开启、防火墙是否放行69端口。
saveenv,否则重启后丢失。五、移植检查要点
移植U-Boot到新的i.MX板卡时,建议按以下顺序推进:先确认Boot ROM能识别启动介质并加载SPL;再确认SPL能完成DDR初始化并打印U-Boot proper的启动信息;然后进入U-Boot命令行,验证串口、MMC、网络等基本驱动;最后配置环境变量和bootcmd,实现从网络或本地存储加载内核。每一步都应有明确的串口输出作为判断依据,避免跳步导致问题难以定位。