4. U-Boot移植与启动流程
在TI Sitara(如AM335x、AM437x、AM57x)平台上,U-Boot并不是一个“单阶段”程序。芯片上电后,片内ROM会先执行一段固化代码,再根据启动介质(SD卡、eMMC、NAND、UART、以太网等)加载第一级引导程序。对于DDR容量较大、需要完整U-Boot功能的工业HMI与边缘控制终端,通常采用SPL + U-Boot两阶段结构:SPL(Secondary Program Loader)负责最小化初始化,把U-Boot proper搬到DDR并跳转;U-Boot proper负责完整外设、环境变量、启动脚本和操作系统加载。
理解这条链路,是后续移植、裁剪和排障的基础。下面这张图把上电到内核启动的关键阶段、运行位置和职责串起来,便于对照调试。
SPL 与 U-Boot proper 的职责边界
SPL 运行在片内 SRAM(AM335x 约 128KB,可用约 100KB),因此必须极度精简。它主要做三件事:配置时钟与 DDR 控制器、设置关键引脚复用(pinmux)、从启动介质读取 U-Boot proper 到 DDR 并跳转。DDR 参数来自 board/ti/am335x/board.c 中的 ddr_init() 与 sdram_init(),实际时序由 arch/arm/mach-omap2/am33xx/emif4.c 和 board/ti/am335x/mux.c 配合完成。若 DDR 参数错误,典型现象是 SPL 打印 U-Boot SPL 2021.01 ... 后卡死或反复复位,串口无后续输出。
U-Boot proper 运行在 DDR,负责完整外设初始化、环境变量、启动脚本和镜像加载。移植时通常先保证 SPL 能稳定打印并进入 U-Boot,再处理 U-Boot 的驱动与启动逻辑。判断阶段是否正常,最直接的方法是看串口输出:SPL 阶段会打印 DDR 频率、启动介质;U-Boot 阶段会打印 U-Boot 2021.01、DRAM 容量、MMC 设备列表。
DDR 与引脚复用配置
DDR 配置的核心是 EMIF 寄存器组:SDRAM_CONFIG、SDRAM_REF_CTRL、SDRAM_TIM_1/2/3、ZQ_CONFIG 等。以 AM335x + DDR3 为例,常见参数包括 DDR3_EMIF_READ_LATENCY=0x06、DDR3_SDRAM_TIM_1=0x0AAAD4DB、DDR3_SDRAM_CONFIG=0x61C05332。这些值必须与硬件原理图上的 DDR 型号、位宽、频率一致。若更换 DDR 颗粒,需要重新计算或从 TI 的 DDR 寄存器配置工具导出。
引脚复用(pinmux)决定每个引脚是作为 MMC、UART、I2C 还是 GPIO。AM335x 的 pinmux 通过 CONF_<module>_<signal> 宏定义,例如 CONF_UART0_RXD | CONF_UART0_TXD 用于调试串口,CONF_MMC0_DAT3 | CONF_MMC0_CMD 用于 SD 卡。移植时若串口无输出,先检查 UART0 的 pinmux 是否被其他功能占用;若 SD 卡无法识别,检查 MMC0 的 CLK、CMD、DAT 是否配置为 MMC 模式且上拉正确。
环境变量管理
U-Boot 环境变量默认保存在 CONFIG_ENV_IS_IN_MMC 或 CONFIG_ENV_IS_IN_FAT 指定的位置。常见做法是在 eMMC 上划分一个 raw 分区存放 env,或在 boot 分区放 uboot.env 文件。关键变量包括:
bootcmd:默认启动命令,通常为run findfdt; run mmcboot或run netboot。bootargs:内核命令行,如console=ttyO0,115200n8 root=/dev/mmcblk0p2 rw rootwait。fdtfile:设备树文件名,如am335x-hmi.dtb。ipaddr、serverip、gatewayip:网络启动参数。
修改环境变量后必须执行 saveenv 才会写入存储介质。若 saveenv 报错,通常是 env 分区偏移或大小与 CONFIG_ENV_OFFSET、CONFIG_ENV_SIZE 不匹配。调试时可先用 env default -a 恢复默认值,再逐项设置。
从 SD 卡、eMMC、网络启动的调试方法
SD 卡启动是最常用的调试方式。将 MLO 和 u-boot.img 放入 FAT 分区,插入 SD 卡并设置启动引脚为 SD 启动。串口应依次出现 SPL 和 U-Boot 输出。若只看到 SPL 输出,说明 U-Boot proper 未正确加载,检查 u-boot.img 是否在 FAT 分区根目录、文件名是否正确。
eMMC 启动通常用于量产。可通过 SD 卡启动后,在 U-Boot 中用 mmc dev 1 切换到 eMMC,再用 fatwrite 或 mmc write 写入 MLO、u-boot.img 和内核。写入前务必确认 eMMC 分区表与偏移,避免覆盖关键数据。若 eMMC 启动失败,可回到 SD 卡启动,用 mmc part 查看分区,用 mmc read 验证数据。
网络启动适合快速迭代内核和设备树。在 U-Boot 中设置 serverip 为 TFTP 服务器地址,执行 tftp 0x82000000 zImage、tftp 0x88000000 am335x-hmi.dtb,再 bootz 0x82000000 - 0x88000000。若 TFTP 超时,先 ping $serverip 确认链路;若内核启动后挂载 rootfs 失败,检查 bootargs 中的 root 和 ip 参数。
综合来看,U-Boot 移植的关键在于:先让 SPL 稳定运行并正确初始化 DDR 与 pinmux,再让 U-Boot proper 完成外设与环境变量管理,最后根据产品形态选择 SD 卡、eMMC 或网络启动路径。每一步都应以串口输出和实际启动结果作为判断依据,而不是仅凭配置完成就认为移植成功。