3、U-Boot命令行基础:进入U-Boot命令行、常用命令分类、命令帮助系统

U-Boot启动后,如果你看到那个熟悉的 => 提示符,恭喜,你已经进入了U-Boot的命令行世界。很多刚接触嵌入式Linux的工程师,总觉得U-Boot就是个“黑盒子”,其实它更像一把瑞士军刀——功能多,但得知道怎么用。

我个人习惯把U-Boot命令行比作“裸机时代的救生员”。系统起不来?内核挂掉?文件系统损坏?只要串口还能输出,U-Boot命令行就是你排查问题的第一站。这一章,我们就把它的基本操作摸透。

3.1 如何进入U-Boot命令行

大多数开发板在启动时,串口终端会输出类似这样的信息:

U-Boot 2023.04 (Jan 15 2024 - 14:30:00 +0800)

CPU:   i.MX6ULL
Board: MY-IMX6ULL
DRAM:  512 MiB
MMC:   FSL_SDHC: 0, FSL_SDHC: 1
Net:   FEC [PRIME]
Hit any key to stop autoboot:  3

看到 Hit any key to stop autoboot 这行字了吗?在倒计时结束前,随便按键盘上的一个键(空格、回车都行),就能进入命令行。倒计时一般是3秒,有些板子设成1秒,手速要快。

避坑指南: 我曾经遇到过一块板子,串口线接触不良,倒计时都跑完了才连上,结果直接进内核了。后来我养成习惯:上电前先把串口终端打开,确保能看到输出。另外,有些终端软件(如SecureCRT)需要设置“Send break”或“立即发送”才能中断启动,别傻等。

如果倒计时已经结束,系统已经开始加载内核了怎么办?别急,按住复位键重启,或者重新上电,再来一次。实在不行,检查一下 bootdelay 环境变量是不是被改成了0。

3.2 常用命令分类

U-Boot的命令少说也有上百个,但常用的其实就那几十个。我按功能把它们分成四类,你记牢这四类,基本就能应付90%的调试场景。

3.2.1 信息查询类

这类命令用来“看”,看硬件状态、看环境变量、看内存布局。调试的第一步,永远是先搞清楚当前系统是什么状态。

命令 功能 典型用法
bdinfo 显示板级信息(DRAM起始地址、大小、时钟等) bdinfo
printenv 打印所有环境变量 printenv 或 printenv bootargs
version 显示U-Boot版本和编译时间 version
iminfo 检查镜像文件头(校验CRC) iminfo 0x80800000
flinfo 显示Flash信息(NOR/NAND) flinfo

举个例子,你拿到一块新板子,第一件事就是敲 bdinfo,看看DRAM起始地址是不是0x80000000,大小是不是512MB。如果这里就不对,后面所有操作都是白费。

个人经验: 我调试一块新板子时,习惯先执行 printenv 把环境变量全部保存到终端日志里。这样万一改乱了,还能对照着恢复。别问我为什么知道——有一次我手滑把 bootcmd 清空了,系统直接变砖,还好有备份。

3.2.2 内存操作类

这类命令是调试的“手术刀”。内存读写、查看、修改、比对,全指望它们。

命令 功能 典型用法
md 显示内存内容(Memory Display) md.b 0x80000000 0x100(字节显示)
mw 填充内存(Memory Write) mw.l 0x80000000 0xdeadbeef 0x100
mm 交互式修改内存 mm.b 0x80000000
cmp 比较两段内存 cmp.b 0x80000000 0x81000000 0x1000
cp 拷贝内存 cp.b 0x80000000 0x81000000 0x1000

注意 md 和 mw 后面的 .b、.w、.l 后缀,分别代表字节(8位)、半字(16位)、字(32位)操作。我见过不少新手用 md.l 查看寄存器,结果读出来的值完全不对——因为寄存器是32位的,但地址偏移是按字节算的,用 .l 一次读4字节,地址会自动加4。

核心要点: 内存操作命令是验证硬件映射是否正确的唯一手段。比如你配置了某个外设的基地址是0x020E0000,用 md.l 0x020E0000 1 读一下,如果返回0xFFFFFFFF,说明要么地址没映射,要么外设没使能。

3.2.3 网络操作类

网络是U-Boot里最实用的功能之一。通过网络下载内核、文件系统,比从Flash烧写快得多。

命令 功能 典型用法
ping 测试网络连通性 ping 192.168.1.100
tftp 通过TFTP下载文件 tftp 0x80800000 zImage
dhcp 通过DHCP获取IP并下载 dhcp 0x80800000 zImage
nfs 通过NFS挂载根文件系统 nfs 0x80800000 192.168.1.100:/nfs/zImage

使用网络命令前,必须先设置好环境变量:ipaddr(板子IP)、serverip(服务器IP)、netmask(子网掩码)。我习惯在 bootcmd 里加一段自动检测网络的逻辑,如果ping不通服务器,就回退到本地启动。

注意: 网络调试最怕的是MAC地址冲突。U-Boot里有个 ethaddr 环境变量,就是板子的MAC地址。如果多块板子共用一个镜像,记得改掉这个变量,否则网络会随机掉线。我曾经在实验室里被这个问题折磨了一下午,最后发现三块板子MAC地址一模一样。

3.2.4 存储操作类

存储操作涉及Flash、MMC、SD卡、USB等设备。这类命令通常以设备名开头,比如 mmc、sf(SPI Flash)、nand。

命令 功能 典型用法
mmc info 显示MMC/SD卡信息 mmc info
mmc read 从MMC读取数据到内存 mmc read 0x80800000 0x800 0x1000
mmc write 从内存写入数据到MMC mmc write 0x80800000 0x800 0x1000
sf probe 探测SPI Flash sf probe 0:0
sf read 从SPI Flash读取数据 sf read 0x80800000 0x100000 0x800000
sf erase 擦除SPI Flash扇区 sf erase 0x100000 0x800000
sf write 写入数据到SPI Flash sf write 0x80800000 0x100000 0x800000
fatls 列出FAT分区文件 fatls mmc 0:1
ext4ls 列出ext4分区文件 ext4ls mmc 0:2

存储操作的关键是理解“块地址”和“字节地址”的区别。比如 mmc read 的第二个参数是块号(LBA),第三个参数是块数,一块通常是512字节。而 sf read 的第二个参数是字节偏移,第三个参数是字节长度。搞混了,读出来的数据全是乱的。

避坑指南: 我曾经在给SPI Flash烧写U-Boot时,用 sf write 写了一个错误的偏移地址,结果把启动引导区覆盖了,板子直接变砖。后来我学乖了:写Flash之前,先用 sf read 把原内容读到内存里备份一份,万一写错了还能恢复。

3.3 命令帮助系统

U-Boot的命令太多,记不住怎么办?别担心,它自带帮助系统。

  • help 或 ?:列出所有可用命令。
  • help 命令名:查看某个命令的详细用法。

比如你忘了 tftp 的用法,直接敲:

=> help tftp
tftp [loadAddress] [[hostIPaddr:]bootfilename]

输出会告诉你:第一个参数是加载地址,第二个参数是服务器上的文件名,还可以指定服务器IP。

我个人觉得,U-Boot的帮助系统虽然简陋,但足够用了。它不会像Linux的man手册那样长篇大论,而是直接告诉你参数格式和示例。如果你需要更详细的信息,可以查看U-Boot源码里的 doc/ 目录,或者直接读命令的C文件——很多命令的实现代码也就几百行,读起来并不难。

核心要点: 命令帮助系统是U-Boot自带的“速查手册”。遇到不熟悉的命令,先敲 help 命令名,90%的情况下能解决问题。剩下的10%,要么是命令拼写错了,要么是板子没编译进那个命令。

3.4 本章知识体系

下面这张图总结了U-Boot命令行的核心知识结构,你可以把它当作一张“地图”,随时回来对照。

U-Boot命令行知识体系 U-Boot 命令行 信息查询类 bdinfo - 板级信息 printenv - 环境变量 version - 版本信息 iminfo - 镜像校验 内存操作类 md - 内存显示 mw - 内存填充 mm - 交互修改 cmp/cp - 比较/拷贝 网络操作类 ping - 网络测试 tftp - 文件下载 dhcp - 自动获取IP nfs - 网络文件系统 存储操作类 mmc - MMC/SD操作 sf - SPI Flash操作 nand - NAND操作 fatls/ext4ls - 文件列表 命令帮助系统 help / ? - 列出所有命令 help 命令名 - 查看详细用法 源码 doc/ 目录 - 完整文档

这张图把U-Boot命令行分成了五个模块:信息查询、内存操作、网络操作、存储操作,以及贯穿始终的命令帮助系统。每个模块下都有对应的核心命令和典型用途。调试时遇到问题,先定位属于哪一类,再去找对应的命令,效率会高很多。

个人建议: 刚开始学U-Boot时,别试图记住所有命令。先把 help、printenv、md、tftp、mmc read 这五个命令练熟,剩下的遇到再查。我当年就是这么过来的,到现在也只用到了U-Boot命令集的20%,但这20%已经能解决80%的问题了。