01-U-Boot命令与使用.md 21 KB


title: U-Boot命令与使用 tags: [uboot, bootloader, embedded-linux, imx6ull, system-boot] created: 2026-09-17 updated: 2026-09-17

pdf_ref: "【正点原子】I.MX6U嵌入式Linux驱动开发指南V2.0.1 - 第三十章 U-Boot使用实验"

U-Boot命令与使用

1. U-Boot概述

1.1 什么是U-Boot

U-Boot(Universal Boot Loader)是一款遵循GPL协议的开源bootloader程序,广泛应用于嵌入式Linux系统启动。它本质上是一个裸机综合例程,可以看作是一个功能强大的裸机程序。

U-Boot的官网为 http://www.denx.de/wiki/U-Boot/,源码可通过FTP服务器下载。

1.2 U-Boot的作用

Linux系统启动必须依赖bootloader程序。芯片上电后首先运行bootloader,其主要工作包括:

  1. 初始化DDR等外设
  2. 将Linux内核从Flash(NAND、NOR、SD、MMC等)拷贝到DDR中
  3. 启动Linux内核

bootloader与Linux内核的关系类似PC上的BIOS与Windows的关系。

1.3 三种U-Boot来源

种类 描述
官方uboot 由uboot官方维护开发,版本更新快,支持常用芯片
半导体厂商uboot 半导体厂商维护,专门针对自家芯片,支持更全面
开发板厂商uboot 开发板厂商在半导体厂商基础上加入自家开发板支持

实际使用中通常选择半导体厂商或开发板厂商的uboot。NXP维护的版本为2016.03,正点原子在其基础上进行了适配。

1.4 U-Boot版本

U-Boot 官方源码当前最新版本为2019.04,但一般不会直接使用官方源码。NXP(半导体厂商)维护的版本为2016.03,正点原子在此基础上适配了 I.MX6U-ALPHA 开发板(出厂系统由 NXP 官方编译器arm-poky-linux-gnueabi-gcc编译,本教程统一使用arm-linux-gnueabihf-gcc)。版本号可通过version命令查看:

U-Boot 2016.03-gd3f0479 (Aug 07 2020 - 20:47:37 +0800)

2. U-Boot命令详解

进入U-Boot命令行后,输入help?可查看所有支持的命令。使用help 命令名查看具体用法。

2.1 help命令

# 查看所有命令
help
?

# 查看特定命令用法
help bootz
? bootz

2.2 信息查询命令

bdinfo — 板子信息

bdinfo

输出包括:

  • DRAM起始地址和大小
  • 启动参数保存起始地址
  • 波特率
  • sp(堆栈指针)起始地址

printenv — 环境变量

# 查看所有环境变量
printenv
print

U-Boot支持TAB键自动补全功能,输入print后按TAB即可自动补全(直接输入print也可以)。

version — 版本号

version

输出U-Boot版本号和编译时间。

2.3 环境变量操作命令

setenv — 设置环境变量

# 修改环境变量
setenv bootdelay 5
saveenv

# 新建环境变量
setenv author zuozhongkai
saveenv

# 删除环境变量(赋空值)
setenv author
saveenv

# 修改包含空格的值(用单引号括起来)
setenv bootargs 'console=ttymxc0,115200 root=/dev/mmcblk1p2 rootwait rw'
saveenv

saveenv — 保存环境变量

setenv修改的是DRAM中的环境变量,修改后必须使用saveenv保存到Flash中,否则重启后会恢复原值。

保存时会显示存储设备信息:

  • SD卡启动:保存到MMC(0)
  • EMMC启动:保存到MMC(1)
  • NAND启动:保存到NAND

2.4 内存操作命令

内存命令直接对DRAM进行读写操作,所有数字均为十六进制。

md — 显示内存值

md[.b, .w, .l] address [# of objects]
  • .b:字节显示
  • .w:字(2字节)显示
  • .l:长字(4字节)显示

    # 以字节格式查看0x80000000开始的0x10个数据(16字节)
    md.b 80000000 10
    
    # 以字格式查看(16*2=32字节)
    md.w 80000000 10
    
    # 以长字格式查看(16*4=64字节)
    md.l 80000000 10
    

注意:uboot命令中的数字都是十六进制的!十进制20应写为14

nm — 修改指定地址内存值

nm [.b, .w, .l] address

# 示例:修改0x80000000地址数据为0x12345678
nm.l 80000000
# 输入: 12345678
# 输入q退出

mm — 修改内存(地址自增)

nm类似,但修改后地址会自动递增。

# 以 .l 格式修改 0x80000000 起连续 3 个内存块(3*4=12 字节)
mm.l 80000000
# 输入05050505
# 输入05050505
# 输入05050505
# 输入q退出

mw — 填充内存

mw [.b, .w, .l] address value [count]

# 以长字格式填充0x80000000开始的0x10个内存块为0x0A0A0A0A
mw.l 80000000 0A0A0A0A 10

cp — 数据拷贝

cp [.b, .w, .l] source target count

# 将0x80000000处0x10个内存块拷贝到0x80000100
cp.l 80000000 80000100 10

cmp — 内存比较

cmp [.b, .w, .l] addr1 addr2 count

# 比较0x80000000和0x80000100处的0x10个内存块
cmp.l 80000000 80000100 10

2.5 网络命令

使用网络命令前需设置网络环境变量:

setenv ipaddr 192.168.1.50
setenv ethaddr b8:ae:1d:01:00:00
setenv gatewayip 192.168.1.1
setenv netmask 255.255.255.0
setenv serverip 192.168.1.253
saveenv

ping — 网络连通测试

ping 192.168.1.253

重要:只能在U-Boot中ping其他机器,其他机器不能ping U-Boot。

dhcp — 获取IP地址

dhcp

DHCP会同时通过TFTP尝试启动Linux内核。

nfs — 网络文件系统下载

nfs [loadAddress] [[hostIPaddr:]bootfilename]

# 示例:下载zImage到0x80800000
nfs 80800000 192.168.1.253:/home/user/linux/nfs/zImage

tftpboot — TFTP下载

tftpboot [loadAddress] [[hostIPaddr:]bootfilename]

# 示例:下载zImage(只需文件名,无需完整路径)
tftp 80800000 zImage

TFTP比NFS更简洁,不需要输入完整路径。

2.6 块设备命令(MMC)

mmc info — 查看设备信息

mmc info
# 或
mmcinfo

mmc list — 列出所有MMC设备

mmc list

mmc dev — 切换设备

mmc dev [dev] [part]

# 切换到SD卡
mmc dev 0

# 切换到EMMC分区0
mmc dev 1 0

# 切换到EMMC分区2
mmc dev 1 2

mmc read — 读取数据

mmc read addr blk# cnt

# 从EMMC第0x600块读取0x10个块到0x80800000
mmc read 80800000 600 10

mmc write — 写入数据

mmc write addr blk# cnt

# 将0x80800000处数据写入SD卡第2块开始的位置
mmc write 80800000 2 2E6

警告:千万不要写SD卡或EMMC的前两个块(扇区),里面保存着分区表!

mmc part — 查看分区

mmc part

mmc rescan — 扫描设备

mmc rescan

mmc erase — 擦除指定块

mmc erase blk# cnt

警告:没事不要使用mmc erase擦除 MMC 设备!

mmc 其他命令(PDF 表 30.4.5.1)

命令 描述
mmc hwpartition 设置 MMC 设备的分区
mmc bootbus 设置指定 MMC 设备的 BOOT_BUS_WIDTH 域的值
mmc bootpart 设置指定 MMC 设备的 boot 和 RPMB 分区的大小
mmc partconf 设置指定 MMC 设备的 PARTITION_CONFIG 域的值
mmc rst 复位 MMC 设备
mmc setdsr 设置 DSR 寄存器的值

用 mmc write 更新 U-Boot

SD 卡(742 块,即 0x2E6):

mmc dev 0 0                    # 切换到 SD 卡分区 0
mmc write 80800000 2 2E6       # 从第 2 个扇区开始写 0x2E6 个块

EMMC(需要额外做分区配置):

mmc dev 1 0                    # 切换到 EMMC 分区 0
tftp 80800000 u-boot.imx       # 下载 u-boot.imx 到 DRAM
mmc write 80800000 2 32E       # 烧写 u-boot.imx 到 EMMC 中
mmc partconf 1 1 0 0           # 分区配置,EMMC 需要这一步!

2.7 FAT文件系统命令

相关命令有fatinfofatlsfstypefatloadfatwrite仅支持FAT格式文件系统

# fatinfo <interface> [<dev[:part]>]  查询文件系统信息
fatinfo mmc 1:1

# fatls <interface> [<dev[:part]>] [directory]  列出目录/文件
fatls mmc 1:1

# fstype <interface> <dev>:<part>  查看分区文件系统格式
fstype mmc 1:0
fstype mmc 1:1
fstype mmc 1:2

# fatload <interface> [<dev[:part]> [<addr> [<filename> [bytes [pos]]]]]
# bytes 为 0 或省略表示读整个文件,pos 为文件内偏移
fatload mmc 1:1 80800000 zImage

# fatwrite <interface> <dev[:part]> <addr> <filename> <bytes>
# 需在板级配置头文件中使能 CONFIG_FAT_WRITE
fatwrite mmc 1:1 80800000 zImage 6788f8

2.8 EXT文件系统命令

U-Boot 支持ext2ext4两种格式,常用命令有ext2loadext2lsext4loadext4lsext4write,含义和用法与 FAT 系列一致。EMMC 分区 2 为 ext4 格式,用于存放根文件系统(rootfs)。

# 列出 EMMC 分区 2(ext4)中的文件和目录
ext4ls mmc 1:2

# 读取文件到 DRAM(用法同 fatload)
ext4load mmc 1:2 <addr> <filename>

# 写入(用法同 fatwrite)
ext4write mmc 1:2 <addr> <filename> <bytes>

2.9 NAND操作命令(NAND核心板)

前提是使用 NAND 版本核心板并编译对应的 U-Boot。常用命令有nand infonand devicenand erasenand writenand read,以及查看/操作设备树的fdt命令。

# 打印 NAND 信息(页大小、OOB、擦除大小等)
nand info

# nand erase[.spread] [clean] off size     从 off 开始擦除 size 区域
nand erase.part [clean] partition          擦除指定分区
nand erase.chip [clean]                    全片擦除

# nand write addr off size    向 NAND 指定地址写数据
# nand read  addr off size    从 NAND 指定地址读数据到 DRAM

I.MX6U-ALPHA 出厂系统 NAND 分区(共 6 个分区):

分区 地址范围 大小 内容
boot 0x000000~0x3FFFFF 4MB uboot
env 0x400000~0x41FFFF 128KB 环境变量
logo 0x420000~0x51FFFF 1MB 启动图标
dtb 0x520000~0x61FFFF 1MB 设备树
kernel 0x620000~0xE1FFFF 8MB Linux 内核
rootfs 0xE20000~0x20000000 剩余 根文件系统

烧写 kernel 与 dtb 示例:

tftp 0x87800000 zImage
nand erase 0x620000 0x800000
nand write 0x87800000 0x620000 0x800000

tftp 0x87800000 imx6ull-14x14-emmc-7-1024x600-c.dtb
nand erase 0x520000 0x100000
nand write 0x87800000 0x520000 0x100000

注意:I.MX6ULL 要求 NAND 版 U-Boot 额外包含 BCB 和 DBBT,直接编译出的u-boot.imx不能烧写到 NAND(需 mfgtool 用kogs-ng工具添加)。rootfs 太大,也不在 U-Boot 中更新,改用 Mfgtool 烧写。

读取设备树并用fdt查看:

nand read 0x83000000 0x520000 0x19000
fdt addr 83000000
fdt header
fdt print

2.10 boot命令

bootz — 启动zImage

bootz [addr [initrd[:size]] [fdt]]

# 示例:从网络启动
tftp 80800000 zImage
tftp 83000000 imx6ull-14x14-emmc-7-1024x600-c.dtb
bootz 80800000 - 83000000

# 示例:从 EMMC 分区 1 启动
fatload mmc 1:1 80800000 zImage
fatload mmc 1:1 83000000 imx6ull-14x14-emmc-7-1024x600-c.dtb
bootz 80800000 - 83000000

bootm — 启动uImage

bootm [addr [initrd[:size]] [fdt]]

boot — 自动启动

读取bootcmd环境变量中的命令自动启动:

boot

2.11 其他常用命令

# 复位重启
reset

# 跳转到指定地址执行(arg 为可选参数)
go addr [arg ...]
# 例:tftp 87800000 printf.bin; go 87800000(裸机程序链接首地址为 0x87800000)
tftp 87800000 printf.bin
go 87800000

# 运行环境变量中的命令
run bootcmd

# 内存读写测试
mtest [start [end [pattern [iterations]]]]
mtest 80000000 80001000

3. 环境变量详解

3.1 bootargs — 启动参数

bootargs保存Linux内核启动参数,是最关键的环境变量之一:

setenv bootargs 'console=ttymxc0,115200 root=/dev/mmcblk1p2 rootwait rw'
saveenv

常用参数:

  • console=ttymxc0,115200:串口控制台配置
  • root=/dev/mmcblk1p2:根文件系统设备
  • rootwait:等待根设备就绪
  • rw:以读写方式挂载

若不设置bootargs,启动内核时会报错:Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0),原因是内核找不到根文件系统。

3.2 bootcmd — 启动命令

bootcmd保存自动启动时执行的命令集合:

# 从网络启动
setenv bootcmd 'tftp 80800000 zImage; tftp 83000000 imx6ull-14x14-emmc-7-1024x600-c.dtb; bootz 80800000 - 83000000'
saveenv

# 从EMMC启动
setenv bootcmd 'fatload mmc 1:1 80800000 zImage; fatload mmc 1:1 83000000 imx6ull-14x14-emmc-7-1024x600-c.dtb; bootz 80800000 - 83000000'
saveenv

3.3 网络环境变量

变量 说明
ipaddr 开发板IP地址
ethaddr MAC地址(必须设置,且唯一)
gatewayip 网关地址
netmask 子网掩码
serverip 服务器IP(Ubuntu主机)

3.4 自定义环境变量

# 定义不同启动方式
setenv mybootemmc 'fatload mmc 1:1 80800000 zImage; fatload mmc 1:1 83000000 imx6ull-14x14-emmc-7-1024x600-c.dtb; bootz 80800000 - 83000000'
setenv mybootnand 'nand read 80800000 4000000 800000; nand read 83000000 6000000 100000; bootz 80800000 - 83000000'
setenv mybootnet 'tftp 80800000 zImage; tftp 83000000 imx6ull-14x14-emmc-7-1024x600-c.dtb; bootz 80800000 - 83000000'
saveenv

# 使用run命令切换启动方式
run mybootemmc
run mybootnand
run mybootnet

3.5 bootdelay

控制启动倒计时时间,默认为3秒。修改方法:

setenv bootdelay 5
saveenv

4. 网络启动配置

4.1 TFTP服务器配置

在Ubuntu上安装TFTP服务:

sudo apt-get install tftp-hpa tftpd-hpa
sudo apt-get install xinetd

创建TFTP目录并设置权限:

mkdir ~/linux/tftpboot
chmod 777 ~/linux/tftpboot

配置/etc/xinetd.d/tftp

server tftp
{
    socket_type = dgram
    protocol = udp
    wait = yes
    user = root
    server = /usr/sbin/in.tftpd
    server_args = -s /home/user/linux/tftpboot/
    disable = no
    per_source = 11
    cps = 100 2
    flags = IPv4
}

配置/etc/default/tftpd-hpa

TFTP_USERNAME="tftp"
TFTP_DIRECTORY="/home/user/linux/tftpboot"
TFTP_ADDRESS=":69"
TFTP_OPTIONS="-l -c -s"

启动服务:

sudo service tftpd-hpa start
sudo service tftpd-hpa restart

4.2 NFS服务器配置

NFS目录创建和权限设置:

mkdir ~/linux/nfs
chmod 777 ~/linux/nfs

4.3 启动参数设置

完整网络启动流程:

# 设置网络环境变量
setenv ipaddr 192.168.1.50
setenv ethaddr b8:ae:1d:01:00:00
setenv gatewayip 192.168.1.1
setenv netmask 255.255.255.0
setenv serverip 192.168.1.253
saveenv

# 测试网络
ping 192.168.1.253

# 下载内核和设备树
tftp 80800000 zImage
tftp 83000000 imx6ull-14x14-emmc-7-1024x600-c.dtb

# 启动
bootz 80800000 - 83000000

4.4 TFTP下载故障排除

出现TFTP error: 'Permission denied'错误时:

  1. 检查tftpboot目录权限:chmod 777 /home/user/linux/tftpboot
  2. 检查文件权限:chmod 777 zImage

5. 完整实验步骤

5.1 环境准备

  1. 安装交叉编译工具链
  2. 安装ncurses库:sudo apt-get install libncurses5-dev
  3. 准备U-Boot源码

5.2 U-Boot编译

U-Boot 源码解压到 ~/linux/uboot/alientek_uboot

tar -vxjf uboot-imx-2016.03-2.1.0-g8b546e4.tar.bz2

512MB(DDR3)+8GB(EMMC)核心板:

# 清理工程
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- distclean

# 配置(EMMC版本)
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- mx6ull_14x14_ddr512_emmc_defconfig

# 编译
make V=1 ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -j12

也可写成脚本 mx6ull_alientek_emmc.sh

#!/bin/bash
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- distclean
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- mx6ull_14x14_ddr512_emmc_defconfig
make V=1 ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -j12

256MB(DDR3)+512MB(NAND)核心板配置文件为 mx6ull_14x14_ddr256_nand_defconfig,脚本名 mx6ull_alientek_nand.sh

编译产物:u-boot.bin(二进制)和u-boot.imx(加头部后的最终镜像)。U-Boot 是裸机程序,需在前面加上 IVT、DCD 等头部才能在 I.MX6U 上执行,u-boot.imx 就是添加头部后的镜像,也是最终烧写的文件。

5.3 U-Boot烧写

chmod 777 imxdownload
./imxdownload u-boot.bin /dev/sdd

注意:不能烧写到/dev/sdasda1

5.4 串口连接与启动

  1. 使用USB-TTL连接开发板串口1
  2. 打开MobaXterm,设置串口参数
  3. 复位开发板
  4. Hit any key to stop autoboot:倒计时内按回车进入命令行

5.5 启动信息解读

U-Boot 2016.03-gd3f0479 (Aug 07 2020 - 20:47:37 +0800)
CPU:   Freescale i.MX6ULL rev1.1 792 MHz (running at 396 MHz)
CPU:   Industrial temperature grade (-40C to 105C) at 51C
Reset cause: POR
Board: I.MX6U ALPHA|MINI
I2C:   ready
DRAM:  512 MiB
MMC:   FSL_SDHC: 0, FSL_SDHC: 1
Display: ATK-LCD-7-1024x600 (1024x600)
Video: 1024x600x24
In:    serial
Out:   serial
Err:   serial
switch to partitions #0, OK
mmc1(part 0) is current device
Net:   FEC1
Error: FEC1 address not set.

Normal Boot
Hit any key to stop autoboot:  0
=>

要点:CPU 为飞思卡尔 i.MX6ULL,主频 792MHz(此时运行在 396MHz),工业级结温 -40°C~105°C;FSL_SDHC:0 接 SD(TF) 卡,FSL_SDHC:1 接 EMMC;EMMC 版本默认以 EMMC 为存储器,故显示 switch to partitions #0mmc1(part 0)FEC1 address not set 提示网卡 MAC 未设置。NAND 版本无 EMMC/SD 信息,显示 NAND 容量。

5.6 命令验证测试

# 测试信息查询
bdinfo
printenv
version

# 测试内存操作
md.b 80800000 10
mw.l 80800000 0A0A0A0A 10

# 测试网络
ping 192.168.1.253
tftp 80800000 zImage

# 测试启动
bootz 80800000 - 83000000

6. 跨平台对比

⚠️ 来源说明:本节不属于《I.MX6U嵌入式Linux驱动开发指南》内容,为扩展知识。

6.1 IMX6ULL vs STM32MP1 vs RK3568 U-Boot差异

特性 IMX6ULL STM32MP1 RK3568
启动方式 SD/EMMC/NAND SD/MMC/NOR SD/EMMC/NAND/SPI
默认串口 ttymxc0 uart4 ...
内存地址 0x80000000 0xC0000000 0x00000000
内核加载地址 0x80800000 0xC2000000 0x00208000
设备树加载地址 0x83000000 0xC4000000 0x00F80000
U-Boot版本 2016.03 2021.10 2017.09
交叉编译器 arm-linux-gnueabihf arm-ostl-linux-gnueabi arm-linux-gnueabihf

6.2 命令差异说明

不同平台的U-Boot命令基本一致,但配置文件和默认环境变量有所不同:

  • IMX6ULL使用mx6ull_*_defconfig
  • STM32MP1使用stm32mp1_*_defconfig
  • RK3568使用rk3568_*_defconfig

7. 面试精选

⚠️ 来源说明:本节不属于《I.MX6U嵌入式Linux驱动开发指南》内容,为扩展知识(答案基于书中事实整理)。

Q1: U-Boot的作用是什么?与BIOS有什么区别?

:U-Boot是嵌入式系统的bootloader,主要作用是初始化硬件(DDR、串口等)、加载内核到内存并启动Linux。与PC BIOS的区别:

  1. BIOS运行在x86实模式,U-Boot运行在ARM裸机环境
  2. BIOS主要做硬件自检和引导,U-Boot还提供丰富的调试命令
  3. U-Boot支持网络启动、文件系统操作等高级功能
  4. U-Boot是开源的,可高度定制

Q2: U-Boot中setenv和saveenv的区别是什么?

setenv修改的是DRAM中的环境变量,断电后丢失。saveenv将DRAM中的环境变量写入Flash(EMMC/SD/NAND),确保重启后仍然有效。正确流程是先setenvsaveenv

Q3: 为什么U-Boot中ping其他机器可以通,但其他机器ping不通U-Boot?

:因为U-Boot只实现了ping的发送功能,没有实现ICMP应答功能。U-Boot可以发送echo request,但不会响应其他机器的echo request,所以其他机器ping不通U-Boot。

Q4: bootcmd和bootargs的作用分别是什么?

  • bootcmd:保存自动启动时执行的命令序列,如加载内核、设备树并启动
  • bootargs:传递给Linux内核的启动参数,如控制台设备、根文件系统路径、挂载方式等

Q5: 如何在U-Boot中更新U-Boot自身?

:通过mmc write命令实现:

  1. tftp 80800000 u-boot.imx — 下载新U-Boot到DRAM
  2. mmc dev 0 0 — 切换到目标设备
  3. mmc write 80800000 2 2E6 — 写入(742 块,跳过前2个扇区的分区表;EMMC 用 mmc write 80800000 2 32E,还需 mmc partconf 1 1 0 0
  4. 重启验证版本号

内容来源: 《I.MX6U嵌入式Linux驱动开发指南》第30章 U-Boot使用实验