4. Sitara启动流程与压力测试引导

在 Sitara(AM335x/AM437x/AM57xx 等)平台上做压力测试,第一步不是写测试脚本,而是让压力测试镜像能够被可靠地“送进”芯片并跑起来。Sitara 的启动是一条严格分级的链:芯片上电后先执行固化在片内的 ROM Code,由它按启动模式引脚(SYSBOOT)决定的顺序去外部介质寻找一个很小的引导头;找到后加载 SPL(MLO),SPL 完成最关键的 DDR 初始化,再把 U-Boot 搬进内存;U-Boot 提供命令行与网络能力,最终把 Kernel 与根文件系统加载起来。压力测试镜像既可以作为 Kernel + rootfs 整体加载,也可以作为 U-Boot 阶段直接运行的裸机/独立程序,理解这条链的每一级“能做什么、不能做什么”,才能选对加载通道。

启动链的四级分工

ROM Code 是只读的,它只认几种固定格式的引导头(如 AM335x 的 CHSETTINGS/GP header),从 MMC/SD、NAND、SPI、UART、USB 等接口按 SYSBOOT 顺序尝试,把第一段代码(SPL,通常 64~128 KB)读入片内 SRAM 运行。此时 DDR 尚未初始化,所以 SPL 必须足够小。SPL 的核心任务是配置 PLL、DDR 控制器与引脚复用,把 DDR 拉起来,然后从同一介质读取 U-Boot 镜像(u-boot.img)并跳转。U-Boot 运行在 DDR 中,具备完整的驱动栈:MMC、USB、以太网、DFU、TFTP、FAT/EXT4 文件系统等,是压力测试镜像加载方式最灵活的一级。Kernel 阶段则由 U-Boot 通过 bootargs 与设备树决定根文件系统来自何处,压力测试程序通常放在 rootfs 中由 init 或 systemd 拉起。

Sitara 启动链与压力测试镜像加载通道 ROM Code 片内固化 · 只读 按 SYSBOOT 顺序扫描 加载 SPL 到 SRAM SPL (MLO) PLL / DDR / PinMux 运行于片内 SRAM 加载 u-boot.img U-Boot 运行于 DDR MMC/ETH/USB/DFU 加载 Kernel / 裸机镜像 Kernel + rootfs bootargs 指定根文件系统 init/systemd 拉起压测程序 CPU/DDR/IO 压力负载 压力测试镜像的四种加载通道 SD 卡 FAT 分区放 MLO/u-boot.img ext4 分区放 rootfs SYSBOOT 选 MMC0 最易迭代,适合开发 eMMC raw 分区存 MLO/u-boot.img boot 分区存 zImage/dtb SYSBOOT 选 MMC1 量产形态,适合长稳测试 网络 (TFTP/NFS) U-Boot: tftp zImage/dtb bootargs 用 nfsroot 无需反复烧写介质 适合频繁换镜像 UART (XMODEM) ROM Code 串口收 SPL U-Boot: loadx 收镜像 速率低,仅救砖/小镜像 最后手段,可靠性高 选择原则:开发调试优先 SD 卡;量产长稳优先 eMMC;镜像频繁迭代优先网络;介质损坏或板卡无启动介质时用 UART 兜底。 无论哪条通道,SPL 必须与 DDR 配置匹配,U-Boot 的 bootargs 必须与 rootfs 实际位置一致,否则压力测试程序无法被拉起。

从 SD 卡加载:最直接的迭代方式

SD 卡启动是开发阶段的首选。制作时把卡分成两个分区:第一个 FAT32 分区放 MLO、u-boot.img、zImage、设备树 .dtb;第二个 ext4 分区放 rootfs。SYSBOOT 引脚设为 MMC0 优先。上电后 ROM Code 从 FAT 分区读 MLO,SPL 初始化 DDR 后读 u-boot.img,U-Boot 再读 zImage 与 dtb。压力测试镜像若做成独立 rootfs,只需替换第二个分区内容;若做成 U-Boot 可加载的裸机程序,则把它放进 FAT 分区,用 fatload 加载后 go 执行。SD 卡的优点是拔插即换、不损伤板载存储,缺点是卡座与卡本身在振动、高温下可靠性有限,不适合长时间无人值守的压力测试。

从 eMMC 加载:量产与长稳测试的形态

eMMC 启动更接近最终产品形态。典型分区布局是:mmcblk1boot0/boot1 或用户区前若干 MB 的 raw 区域存放 MLO 与 u-boot.img(ROM Code 按 eMMC 的 boot partition 或用户区偏移读取),随后是 boot 分区(FAT)放内核与设备树,再是 rootfs 分区。烧写可用 U-Boot 的 mmc write,也可在 Linux 下用 dd。例如把 MLO 写入 eMMC 用户区偏移 0x100 扇区:

# 在 U-Boot 中从 SD 卡把 MLO 写入 eMMC
mmc dev 0
fatload mmc 0:1 0x82000000 MLO
mmc dev 1
mmc write 0x82000000 0x100 0x200

# 在 Linux 下烧写 rootfs 到 eMMC
dd if=rootfs.ext4 of=/dev/mmcblk1p2 bs=4M conv=fsync

eMMC 的读写寿命与坏块管理是压力测试要重点观察的对象:长时间高频写入会触发 eMMC 内部 GC 与磨损均衡,表现为写入延迟抖动甚至超时。因此 eMMC 方案下,压力测试应同时监控 mmc 子系统的错误计数与写入吞吐变化。

从网络加载:TFTP + NFS 的快速迭代

网络加载把镜像放在主机上,U-Boot 通过 TFTP 取内核与设备树,Kernel 通过 NFS 挂载 rootfs。U-Boot 侧典型命令:

setenv ipaddr 192.168.1.100
setenv serverip 192.168.1.10
tftp 0x82000000 zImage
tftp 0x88000000 am335x-evm.dtb
setenv bootargs console=ttyO0,115200n8 root=/dev/nfs rw \
  nfsroot=192.168.1.10:/nfs/rootfs ip=dhcp
bootz 0x82000000 - 0x88000000

这种方式换压力测试程序只需改主机上的 rootfs 目录,无需重新烧写介质,非常适合反复调整测试参数。代价是网络本身成为变量:TFTP 超时、NFS 重传、链路抖动都会影响测试结果,因此做 CPU/DDR 压力测试时建议网络加载仅用于“送镜像”,测试期间尽量减少网络依赖,或把测试程序与数据预先拷到本地 tmpfs 再运行。

从 UART 加载:救砖与最小镜像兜底

当板卡没有任何可启动介质,或 eMMC/SD 引导头损坏时,ROM Code 的 UART 启动是最后手段。它通过串口以 XMODEM 协议接收 SPL,因此需要一个极小的 SPL 与稳定的串口连接。进入 U-Boot 后,也可用 loadx 通过串口把镜像收到内存:

# U-Boot 中通过串口 XMODEM 接收镜像到 0x82000000
loadx 0x82000000
# 主机端用 sx 发送
sx -k zImage < /dev/ttyUSB0 > /dev/ttyUSB0

UART 速率通常限制在 115200 或 921600,传输几十 MB 的 rootfs 不现实,所以它主要用于加载 SPL、U-Boot 或几 MB 的裸机压力测试程序。它的价值在于“一定能进”,是排障与恢复的保底通道。

把压力测试镜像接进启动链

选定通道后,还要决定压力测试程序在链的哪一级运行。若测试 CPU、DDR、缓存一致性,通常做成 Kernel 模块或用户态程序,由 rootfs 的 init 脚本在启动完成后自动执行,并通过串口打印吞吐、错误计数与温度。若测试的是启动阶段本身的可靠性(如反复冷启动、SPL 加载 DDR 训练稳定性),则应把测试逻辑放进 U-Boot 脚本或裸机程序,用 bootcount 与看门狗配合实现“启动—压测—复位”循环。判断结果是否达标,关键看三类信号:串口日志中是否有 SPL/U-Boot/Kernel 阶段的报错、压力程序自身的错误计数是否为零、以及 SoC 温度与电源轨是否在规格内。只有加载通道稳定、启动链每一级都无异常,压力测试的数据才有意义。