3. CI环境搭建
U-Boot 在 Jacinto 平台上的角色,说白了就是硬件的「初始化管家」和内核的「搬运工」。很多刚接触 BSP 的工程师容易把 U-Boot 当成黑盒,出了问题只会反复烧写。其实把源码结构和启动流程理清楚,大部分启动故障都能自己定位。
我个人习惯把 U-Boot 调试分成三个层次:源码结构理解、板级配置适配、启动流程跟踪。下面我们一层层拆开讲。
3.1 U-Boot 源码结构:别被目录吓到
第一次解压 U-Boot 源码,看到几十个目录确实头大。但 Jacinto 平台相关的代码其实集中在几个关键位置:
| 目录/文件 | 作用 | Jacinto 关注点 |
|---|---|---|
arch/arm/mach-omap2/ |
SoC 级初始化代码 | 包含 AM65x / J721E 的时钟、DDR、PLL 配置 |
board/ti/j721e/ |
板级特定代码 | 板级 GPIO、电源时序、EEPROM 读取 |
include/configs/j721e_evm.h |
板级配置头文件 | 内存映射、环境变量、外设使能开关 |
drivers/ |
外设驱动 | MMC、NAND、以太网、USB 等驱动 |
common/ |
通用命令和框架 | md/mw/bdinfo 等命令实现 |
board/ti/ 下对应目录的 board.c 和 Kconfig。这里藏着板级初始化的「第一手线索」。
3.2 Jacinto 平台板级配置:从 defconfig 到实际运行
配置 U-Boot 不是直接改源码里的宏定义那么简单。现代 U-Boot 使用 Kconfig 机制,配置流程是:
- 选择 defconfig:
make j721e_evm_defconfig生成 .config - 调整配置:
make menuconfig可视化修改 - 编译:
make CROSS_COMPILE=aarch64-linux-gnu-
这里有个容易踩的坑——环境变量默认值。我曾经在调试一块 J721E 板子时,网络启动总是超时,查了两天才发现是 CONFIG_BOOTARGS 里控制台参数写错了。嗯,这种问题用 bdinfo 命令一眼就能看出来。
make clean 再编译。我遇到过好几次因为增量编译导致配置没生效的「灵异事件」。
3.3 U-Boot 启动流程分析:三段式跳转
Jacinto 平台的 U-Boot 启动分为三个阶段,我画了张图帮你建立整体认知:
三个阶段各有各的调试重点。SPL 阶段资源受限,调试手段有限,主要靠串口打印。U-Boot 阶段就灵活多了,各种命令都能用。
3.4 常用调试命令:三板斧解决 80% 问题
调试 U-Boot 不需要记住所有命令,把下面三个用熟就够了:
3.4.1 md(内存显示)
查看指定内存地址的内容,我最常用的场景是检查设备树是否加载正确:
=> md 0x82000000 20
82000000: 12345678 9abcdef0 11223344 55667788 ...4...."3DUfw.
82000010: aabbccdd eeff0011 22334455 66778899 ........"3DUfw.
...
md.b 按字节显示,md.w 按半字显示,md.l 按字显示。检查设备树魔数(0xd00dfeed)时,我习惯用 md.l 0x82000000 1 快速确认。
3.4.2 mw(内存写入)
调试时经常需要手动修改内存,比如临时改个内核参数:
=> mw.l 0x82000000 0xdeadbeef 4
=> md.l 0x82000000 4
82000000: deadbeef deadbeef deadbeef deadbeef ........
3.4.3 bdinfo(板级信息)
这个命令是我调试时的「第一站」。它能显示当前板级的所有关键参数:
=> bdinfo
arch_number = 0x00000000
boot_params = 0x80000100
DRAM bank = 0x00000000
-> start = 0x80000000
-> size = 0x80000000
ethaddr = 70:ff:76:1a:2b:3c
ip_addr = 192.168.1.100
baudrate = 115200 bps
TLB addr = 0xffff0000
relocaddr = 0x9ff70000
reloc off = 0x1ff70000
...
为什么我强调这个命令?因为它能快速验证 DDR 初始化是否正确、网络配置是否生效。有一次我发现 DRAM bank size 只有 256MB,但板子明明有 2GB——后来查出是 SPL 阶段的 DDR 配置表选错了。
3.5 网络启动与 NFS 挂载:开发效率翻倍
做 BSP 开发,频繁烧写 SD 卡或 eMMC 太浪费时间。网络启动是必备技能。
3.5.1 网络启动配置
在 U-Boot 中设置网络参数:
=> setenv ipaddr 192.168.1.100
=> setenv serverip 192.168.1.10
=> setenv netmask 255.255.255.0
=> setenv gatewayip 192.168.1.1
=> saveenv
然后从 TFTP 服务器加载内核和设备树:
=> tftp 0x82000000 Image
=> tftp 0x83000000 k3-j721e-common-proc-board.dtb
=> booti 0x82000000 - 0x83000000
3.5.2 NFS 根文件系统挂载
调试驱动时,频繁更新文件系统很痛苦。NFS 挂载可以让你在主机上修改,板子上实时生效:
=> setenv bootargs console=ttyS2,115200n8 root=/dev/nfs
nfsroot=192.168.1.10:/srv/nfs/rootfs,v3,tcp
ip=192.168.1.100:192.168.1.10:192.168.1.1:255.255.255.0::eth0:off
=> booti 0x82000000 - 0x83000000
实战经验:NFS 挂载失败 90% 是网络不通或权限问题。我的排查步骤:
- 先
ping serverip确认二层连通性 - 在主机上
exportfs -v确认 NFS 导出目录 - 检查主机防火墙(尤其 Ubuntu 的 ufw)
3.6 常见启动故障定位
最后分享几个我实际遇到过的故障案例:
| 现象 | 可能原因 | 排查命令 |
|---|---|---|
| SPL 输出后无反应 | DDR 初始化失败 | 检查串口日志中的 DDR 校准信息 |
| U-Boot 启动到一半重启 | 环境变量损坏 | env default -a 恢复默认 |
| 网络启动超时 | PHY 未初始化或 IP 冲突 | md 0x46000000 10 检查 PHY 寄存器 |
| 内核崩溃 | 设备树与内核不匹配 | fdt addr 0x83000000; fdt list |
调试 U-Boot 其实没那么玄乎。把源码结构理清楚,把启动流程走一遍,再配合那三个命令,大部分问题都能自己搞定。下次遇到板子起不来,别急着重新烧写——先接上串口,看看 U-Boot 到底卡在哪一步。