4、U-Boot与TFTP烧录:U-Boot网络命令体系

嵌入式开发中,烧录系统最常用的方式就是通过网络。你想想看,总不能每次改个设备树都去插拔SD卡或者接JTAG吧?U-Boot自带的网络命令体系,就是干这个用的。我个人习惯先把网络调通,再考虑烧录的事。

核心思路:U-Boot通过网卡驱动,把开发板变成一个简易的TFTP客户端。只要PC端搭好TFTP服务器,两边网络能ping通,就能用tftp命令把内核、设备树、根文件系统甚至裸机程序拉到板子的内存里,然后烧写到Flash或直接启动。

4.1 U-Boot网络命令体系(ping/dhcp/tftp)

U-Boot的网络命令不多,但个个都是硬货。我列个表,你一看就明白。

命令 功能 典型用法
ping 测试网络连通性 ping 192.168.1.100
dhcp 自动获取IP地址 dhcp
tftp 通过TFTP下载文件 tftp 0x42000000 uImage

ping命令:说白了就是看板子和PC能不能说上话。我在项目中遇到过,明明网线插着,灯也亮,但就是ping不通。后来发现是PC的防火墙把ICMP包给拦了。嗯,这里要注意,U-Boot的ping实现比较精简,不支持域名解析,只能ping IP地址。

dhcp命令:这个命令挺省事。执行后U-Boot会自动向局域网内的DHCP服务器请求IP地址,同时会把serverip、gateway等环境变量也一并更新。我建议在调试初期先用dhcp,省得手动配错地址。

tftp命令:这才是重头戏。格式是 tftp [内存地址] [文件名]。比如 tftp 0x42000000 zImage,就是把PC上TFTP服务器根目录里的zImage文件,下载到板子的0x42000000地址处。为什么会用0x42000000?这是DDR内存的起始地址偏移量,不同芯片不一样,你得看芯片手册。

我的经验:第一次用tftp前,一定先ping一下serverip。ping不通就别折腾tftp了,先查网线、IP、防火墙这三样。

4.2 U-Boot环境变量配置(serverip/ipaddr/netmask/gateway)

U-Boot的环境变量,你可以理解成它的“配置文件”。网络相关的几个变量,必须配对了才能干活。

环境变量 含义 示例值
ipaddr 开发板自己的IP地址 192.168.1.10
serverip PC端TFTP服务器的IP地址 192.168.1.100
netmask 子网掩码 255.255.255.0
gateway 网关地址(跨网段时必需) 192.168.1.1

配置方法很简单,在U-Boot命令行里直接设:

setenv ipaddr 192.168.1.10
setenv serverip 192.168.1.100
setenv netmask 255.255.255.0
setenv gateway 192.168.1.1
saveenv

注意最后那个saveenv,不执行的话,重启就丢了。我曾经吃过这个亏,配了半天,一断电全没了,气得够呛。

如果你用的是dhcp,其实可以省掉手动配置。但我的习惯是:dhcp拿地址确认网络没问题后,再把地址手动写死。因为有些项目的网络环境没有DHCP服务器,或者分配的IP会变,写死了省心。

4.3 U-Boot下TFTP下载内核与设备树

网络通了,环境变量配好了,接下来就是真刀真枪地下载了。我一般按这个流程走:

  1. 先ping确认连通:ping 192.168.1.100
  2. 下载设备树:tftp 0x43000000 imx6ull-14x14-evk.dtb
  3. 下载内核:tftp 0x42000000 zImage
  4. 启动内核:bootz 0x42000000 - 0x43000000

这里的内存地址分配是有讲究的。我一般把内核放在0x42000000,设备树放在0x43000000,中间留出足够的空间,防止数据覆盖。你想想看,如果内核很大,设备树地址离得太近,下载设备树时就把内核尾巴给冲了,那启动肯定崩。

避坑指南:我曾经遇到过下载设备树时提示“TFTP error: File not found”。查了半天,发现是PC上TFTP服务器根目录下没有这个文件,或者文件名大小写不对。Linux下文件名是区分大小写的,.dtb和.DTB是两码事。

4.4 U-Boot下TFTP下载根文件系统

根文件系统一般比较大,几十兆甚至上百兆。用TFTP下载到内存后,通常有两种处理方式:

  • 直接NFS挂载:不烧写,通过网络挂载根文件系统,适合开发调试阶段。
  • 烧写到Flash:下载到内存后,再用update或nand write命令写到Flash里。

这里我重点讲烧写的方式。假设根文件系统是rootfs.ubifs格式:

# 1. 下载根文件系统到内存
tftp 0x44000000 rootfs.ubifs

# 2. 擦除NAND Flash上的对应分区
nand erase.part rootfs

# 3. 写入根文件系统
nand write 0x44000000 rootfs ${filesize}

注意${filesize}这个变量,它是tftp命令自动设置的,表示刚才下载的文件大小。用这个变量比手动输入字节数靠谱多了。我刚开始学的时候,傻乎乎地自己算大小,写错一次就得重来。

小技巧:如果根文件系统是squashfs或ext4格式,烧写方式类似,只是文件系统和Flash类型不同。建议先确认你的Flash类型(NAND还是NOR),再选对应的烧写命令。

4.5 U-Boot下TFTP下载裸机程序

裸机程序没有操作系统,直接跑在硬件上。下载方式其实更简单,因为不需要考虑文件系统格式。裸机程序通常是.bin文件,下载到内存后直接跳转执行就行。

# 1. 下载裸机程序
tftp 0x40000000 led.bin

# 2. 跳转执行
go 0x40000000

go命令就是直接跳转到指定地址执行代码。这里要注意,裸机程序必须位置无关,或者链接地址和下载地址一致,否则跑不起来。我踩过这个坑,写了一个LED闪烁程序,链接地址是0x40000000,结果下载到0x41000000,一执行就死机。

另外,裸机程序一般比较小,几KB到几十KB,下载速度很快。但如果你用的是老旧的10M半双工网络,那速度就有点捉急了。我建议至少用100M全双工,TFTP下载速度能到几MB每秒,体验好很多。

总结一下:U-Boot的网络命令体系,核心就是ping、dhcp、tftp这三板斧。环境变量配好,网络调通,剩下的就是下载、烧写、执行。不管是内核、设备树、根文件系统还是裸机程序,流程都差不多。多练几次,闭着眼睛都能搞定。
U-Boot TFTP烧录流程 开发板 (U-Boot) PC (TFTP服务器) ping / dhcp / tftp 1. 配置环境变量 ipaddr / serverip / netmask 2. ping测试连通性 ping 192.168.1.100 3. TFTP下载文件 tftp 0x42000000 zImage 4. 烧写或直接启动 nand write / bootz / go 可下载的文件 • 内核 (zImage/uImage) • 设备树 (.dtb) • 根文件系统 (.ubifs) • 裸机程序 (.bin)