《uboot基础命令记录①》

《uboot基础命令记录①》

之前学习了uboot的一些基础命令,这里想写一篇博客记录一下

参考文档:<正电原子驱动开发指南>

1.信息查询命令

  1. bdinfo

    这里会打印一些开发板的基本信息,如:

    DRAM 的起始地址和大小、启动参数保存起始地址、波特率、sp(堆栈指针)起始地址等信息。

    bash 复制代码
    => bdinfo
    
    arch_number = 0x00000000
    boot_params = 0x80000100
    DRAM bank   = 0x00000000
    -> start    = 0x80000000
    -> size     = 0x20000000
    eth0name    = FEC1
    ethaddr     = (not set)
    current eth = FEC1
    ip_addr     = <NULL>
    baudrate    = 115200 bps
    TLB addr    = 0x9FFF0000
    relocaddr   = 0x9FF55000
    reloc off   = 0x18755000
    irq_sp      = 0x9EF52EA0
    sp start    = 0x9EF52E90
  2. printenv

    打印开发板的一些环境变量

    bash 复制代码
    => printenv 
    
    author=Yunes
    baudrate=115200
    board_name=EVK
    board_rev=14X14
    boot_fdt=try
    bootcmd=run findfdt;mmc dev ${mmcdev};mmc dev ${mmcdev}; if mmc rescan; then if run loadbootscript; then run bootscript; else if run loadimage; then run mmcboot; else run netboot; fi; fi; else run netboot; fi
    bootcmd_mfg=run mfgtool_args;bootz ${loadaddr} ${initrd_addr} ${fdt_addr};
    bootdelay=5
    bootscript=echo Running bootscript from mmc ...; source
    console=ttymxc0
    ethact=FEC1
    ethprime=FEC
    fdt_addr=0x83000000
    fdt_file=imx6ull-14x14-emmc-4.3-480x272-c.dtb
    fdt_high=0xffffffff
    findfdt=if test $fdt_file = undefined; then if test $board_name = EVK && test $board_rev = 9X9; then setenv fdt_file imx6ull-9x9-evk.dtb; fi; if test $board_name = EVK && test $board_rev = 14X14; then setenv fdt_file imx6ull-14x14-evk.dtb; fi; if test $fdt_file = undefined; then echo WARNING: Could not determine dtb to use; fi; fi;
    image=zImage
    initrd_addr=0x83800000
    initrd_high=0xffffffff
    ip_dyn=yes
    loadaddr=0x80800000
    loadbootscript=fatload mmc ${mmcdev}:${mmcpart} ${loadaddr} ${script};
    loadfdt=fatload mmc ${mmcdev}:${mmcpart} ${fdt_addr} ${fdt_file}
    loadimage=fatload mmc ${mmcdev}:${mmcpart} ${loadaddr} ${image}
    logo_file=alientek.bmp
    mfgtool_args=setenv bootargs console=${console},${baudrate} rdinit=/linuxrc g_mass_storage.stall=0 g_mass_storage.removable=1 g_mass_storage.file=/fat g_mass_storage.ro=1 g_mass_storage.idVendor=0x066F g_mass_storage.idProduct=0x37FF g_mass_storage.iSerialNumber="" clk_ignore_unused 
    mmcargs=setenv bootargs console=${console},${baudrate} root=${mmcroot}
    mmcautodetect=yes
    mmcboot=echo Booting from mmc ...; run mmcargs; if test ${boot_fdt} = yes || test ${boot_fdt} = try; then if run loadfdt; then bootz ${loadaddr} - ${fdt_addr}; else if test ${boot_fdt} = try; then bootz; else echo WARN: Cannot load the DT; fi; fi; else bootz; fi;
    mmcdev=0
    mmcpart=1
    mmcroot=/dev/mmcblk0p2 rootwait rw
    netargs=setenv bootargs console=${console},${baudrate} root=/dev/nfs ip=dhcp nfsroot=${serverip}:${nfsroot},v3,tcp
    netboot=echo Booting from net ...; run netargs; if test ${ip_dyn} = yes; then setenv get_cmd dhcp; else setenv get_cmd tftp; fi; ${get_cmd} ${image}; if test ${boot_fdt} = yes || test ${boot_fdt} = try; then if ${get_cmd} ${fdt_addr} ${fdt_file}; then bootz ${loadaddr} - ${fdt_addr}; else if test ${boot_fdt} = try; then bootz; else echo WARN: Cannot load the DT; fi; fi; else bootz; fi;
    panel=ATK-LCD-4.3-480x272
    script=boot.scr
    splashimage=0x88000000
    splashpos=m,m
    stderr=serial
    stdin=serial
    stdout=serial
    
    Environment size: 2598/8188 bytes

    我们可以看到有两个信息:

    1. author=Yunes
    2. bootdelay=5

    这两个信息都是我之前添加过的,一个是添加作者名字,一个是启动延迟,也就是开发板reset之后倒计时。

  3. version

    打印uoot版本号

    bash 复制代码
    => version 
    
    U-Boot 2016.03 (Dec 27 2025 - 21:01:51 +0800)
    arm-linux-gnueabihf-gcc (Linaro GCC 4.9-2017.01) 4.9.4
    GNU ld (Linaro_Binutils-2017.01) 2.24.0.20141017 Linaro 2014_11-3-git

2.环境变量操作命令

环境变量操作涉及到两个命令setenvsaveenv,这两个很好理解吧,一个是设置一个是保存

setenv是修改DRAM 中的环境变量值,而saveenv是将修改后的环境变量存放到flash中,否则下次重启还是之前的变量


2.1添加or修改环境变量

回想第一小节的version下两个变量,具体操作如下

bash 复制代码
setenv bootdelay 5
saveenv

serenv aothor Yunes
saveenv

遇到修改环境变量出现空格的情况,需要增加引号

bash 复制代码
setenv bootargs 'console=ttymxc0,115200 root=/dev/mmcblk1p2 rootwait rw'
saveenv

2.2删除环境变量

bash 复制代码
setenv author
saveenv
#后面加空值即可

3.内存操作命令

内存操作命令就是用于直接对 DRAM 进行读写操作的,常用的内存操作命令有 md、nm、mm、mw、cp 和 cmp


3.1、md

md 命令用于显示内存值,格式如下:

bash 复制代码
md[.b , .w, .l] address [# of objects]

b(byte)、w(word)、l(long) 分别对应1、2、4个字节,address 就是要查看的内存起始地址,[# of objects]表示要查看的数据长度

Ps:uboot命令中的数字都是十六进制的!

例如:

bash 复制代码
=> md.b 80000000 10
80000000: 9f 77 ff fb df bf bf b2 ff fb fa ff ff bf be 7f    .w..............
=> md.w 80000000 10
80000000: 779f fbff bfdf b2bf fbff fffa bfff 7fbe    .w..............
80000010: 7ffe 5fff eab6 fff4 fbdd f5fc faef eafd    ..._............
=> md.l 80000000 10
80000000: fbff779f b2bfbfdf fffafbff 7fbebfff    .w..............
80000010: 5fff7ffe fff4eab6 f5fcfbdd eafdfaef    ..._............
80000020: 3fbff47e aabcbebf fef17dce e8eaffde    ~..?.....}......
80000030: fd7efdf3 bf8b6eab df6d7f5f eabedaee    ..~..n.._.m.....

分析一下这三个命令

bash 复制代码
=> md.b 80000000 10 #起始地址0x80000000 ,大小16*1=16字节
=> md.w 80000000 10 #起始地址0x80000000 ,大小16*2=32字节
=> md.l 80000000 10 #起始地址0x80000000 ,大小16*4=64字节

3.2、nm

nm 命令用于修改指定地址的内存值,格式如下:

bash 复制代码
nm[.b , .w, .l] address

例如:

bash 复制代码
=> nm.l 80000000
80000000: fbff779f ?

?后面写你要改成的内容,我们就写0x123456678,再q退出

bash 复制代码
=> nm.l 80000000
80000000: fbff779f ? 12345678
80000000: 12345678 ? q

修改完成之后,我们在使用md命令查看一下,一共四个字节

bash 复制代码
=> md.l 80000000 1
80000000: 12345678                               xV4.

3.3 、mm

mm命令会自增

bash 复制代码
=> mm.l 80000000
80000000: 12345678 ? 01010101
80000004: b2bfbfdf ? 02020202 
80000008: fffafbff ? 03030303 
8000000c: 7fbebfff ? q

=> md.l 80000000 3
80000000: 01010101 02020202 03030303             ............

3.4、mw

命令 mw 用于使用一个指定的数据填充一段内存,命令格式如下:

bash 复制代码
mw[.b , .w, .l] address value [count]

例如:

bash 复制代码
=> mw.l 80000000 0a0a0a0a 10

=> md.l 80000000 10
80000000: 0a0a0a0a 0a0a0a0a 0a0a0a0a 0a0a0a0a    ................
80000010: 0a0a0a0a 0a0a0a0a 0a0a0a0a 0a0a0a0a    ................
80000020: 0a0a0a0a 0a0a0a0a 0a0a0a0a 0a0a0a0a    ................
80000030: 0a0a0a0a 0a0a0a0a 0a0a0a0a 0a0a0a0a    ................

3.5、cp

cp 是数据拷贝命令,用于将 DRAM 中的数据从一段内存拷贝到另一段内存中命令格式如下:

bash 复制代码
cp [.b, .w, .l] source target count

例如:

bash 复制代码
=> cp.l 80000000 80000100 10

=> md.l 80000100 10
80000100: 0a0a0a0a 0a0a0a0a 0a0a0a0a 0a0a0a0a    ................
80000110: 0a0a0a0a 0a0a0a0a 0a0a0a0a 0a0a0a0a    ................
80000120: 0a0a0a0a 0a0a0a0a 0a0a0a0a 0a0a0a0a    ................
80000130: 0a0a0a0a 0a0a0a0a 0a0a0a0a 0a0a0a0a    ................

3.6、cmp

cmp 是比较命令,用于比较两段内存的数据是否相等,命令格式如下:

bash 复制代码
cmp [.b, .w, .l] addr1 addr2 count

例如:

bash 复制代码
=> cmp.l 80000000 80000100 10
Total of 16 word(s) were the same

4.总结

这些基础命令简单了解掌握,本来还有一个网络操作命令的,由于缺少路由器,uboot下的网络比较难搞,打算在后续linux篇章再介绍

4.网络操作命令

uboot 是支持网络的,我们在移植 uboot 的时候一般都要调通网络功能,因为在移植 linuxkernel 的时候需要使用到 uboot 的网络功能做调试。uboot 支持大量的网络相关命令,比如 dhcp、ping、nfs 和 tftpboot,我们接下来依次学习一下这几个和网络有关的命令。

记得进行以下步骤

  1. 查看主机网卡(网线),再去修改虚拟机网络适配器桥接模式下的网卡
  2. 修改ubuntu下的IP,将其设置为静态,这样不会因为后续开机dhcp导致不必要的麻烦
环境变量 描述
ipaddr 开发板 ip 地址,可以不设置,使用 dhcp 命令来从路由器获取 IP 地址。
ethaddr 开发板的 MAC 地址,一定要设置。
gatewayip 网关地址。
netmask 子网掩码。
serverip 服务器 IP 地址,也就是 Ubuntu 主机 IP 地址,用于调试代码。
bash 复制代码
=> setenv ipaddr 10.135.25.24
=> setenv ethaddr b8:ae:1d:01:00:00
=> setenv gatewayip 10.135.25.1
=> setenv netmask 255.255.255.0
=> setenv serverip 10.135.25.24
=> saveenv
Saving Environment to MMC...
Writing to MMC(0)... done

修改完我们就重启,来测试一个最基本命令


4.1、ping

bash 复制代码
=> ping 10.135.25.24
Using FEC1 device
host 10.135.25.24 is alive

4.2、nfs

这里直接对原文总结并修改:

NFS (网络文件系统)是一种通过网络在不同计算机之间共享文件的机制。

在嵌入式 Linux 开发中,常利用 NFS 在 Ubuntu 主机开发板 之间共享资源。

例如:

我们可以将 Linux 内核镜像(zImage/uImage)设备树文件(.dtb) 放在 Ubuntu 主机中,然后在 U-Boot 中通过 nfs 命令,把这些文件直接下载到开发板的 DRAM 中并运行。

这种方式的主要目的在于:

方便调试 Linux 内核和设备树文件**,也称为 网络调试


为什么嵌入式 Linux 要用网络调试?

嵌入式 Linux 的开发方式与单片机开发有很大不同:

  • 单片机开发
    • 可以通过 J-Link、ST-Link 等仿真器
    • 使用 MDK、IAR 等 IDE
    • 一键下载程序到 MCU 内部 Flash
  • 嵌入式 Linux 开发
    • 系统通常存放在 eMMC / NAND / SPI Flash 等外部存储中
    • 没有类似 MDK、IAR 这种"一键下载"的 IDE
    • 固件烧写一般依赖厂家提供的烧写工具

而厂家提供的烧写工具通常:

  • 操作步骤复杂
  • 更适合 量产
  • 在内核调试阶段频繁使用会 极大浪费时间

因此,在 Linux 内核调试阶段,直接反复烧写 Flash 并不高效。


网络调试的优势

网络调试正是为了解决上述问题而出现的:

  • 内核或设备树修改后
  • 只需在 Ubuntu 上重新编译
  • 通过 U-Boot + NFS
  • 直接将文件下载到 DRAM 中运行

无需烧写 Flash,大大提高调试效率。

这也是 嵌入式 Linux 开发中最常用的调试方式之一


U-Boot 中使用 NFS

通常流程如下:

  1. 在 Ubuntu 主机上:
    • 开启 NFS 服务
    • 创建一个 NFS 共享目录
    • 所有需要通过网络加载的文件(内核、设备树等)都放在该目录中
  2. 在 U-Boot 中:
    • 使用 nfs 命令
    • 将 Ubuntu 主机 NFS 目录中的文件下载到开发板的 DRAM 中运行

但是nfs不稳定还要改很多东西,我直接上tftp


4.3、tftp

安装环境

bash 复制代码
sudo apt-get install tftp-hpa tftpd-hpa
sudo apt-get install xinetd

依旧创建文件夹

bash 复制代码
mkdir /home/yunes/linux/tftpboot && chmod 777 /home/yunes/linux/tftpboot
bash 复制代码
vi /etc/xinetd.d/tftp


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

启动tftp

bash 复制代码
sudo service tftpd-hpa start

再编写修改

bash 复制代码
vi /etc/default/tftpd-hpa

# /etc/default/tftpd-hpa

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

重启:

bash 复制代码
sudo service tftpd-hpa restart

zImage放到tftp文件夹里

下载

bash 复制代码
tftp 80800000 zImage

下载完毕

bash 复制代码
=> tftp 80800000 zImage
Using FEC1 device
TFTP from server 10.135.25.24; our IP address is 10.135.25.25
Filename 'zImage'.
Load address: 0x80800000
Loading: #################################################################
	 #################################################################
	 #################################################################
	 #################################################################
	 #################################################################
	 #################################################################
	 #################################################################
	 ########
	 1.9 MiB/s
done
Bytes transferred = 6785480 (6789c8 hex)

5.总结

目前还只总结了一部分,后续还要再补充,但是这个网络真的麻烦啊,没路由器只能再虚拟机网络桥接网线和无线来回摆动,浪费了很多时间,尤其是这个nfs,版本兼容问题,气死我了!!!不过好在加深了印象,继续努力😀

相关推荐
渝妳学C2 小时前
深度解析Linux中编译器gcc/g++
linux·运维
姚青&2 小时前
二.文件处理命令-文件操作
linux
陌路202 小时前
简写网络库(2)--封装socket类
linux·服务器·网络
JiMoKuangXiangQu2 小时前
Linux 内存案例:DDR 访问出错?
linux·内存·ddr ecc
Xの哲學2 小时前
从硬中断到 softirq:Linux 软中断机制的全景解剖
linux·服务器·网络·算法·边缘计算
lsp84ch803 小时前
MacBookPro运行飞牛Nas,解决合盖亮屏
linux·网络·macbook·nas·飞牛
wdfk_prog3 小时前
[Linux]学习笔记系列 -- [fs]mnt_idmapping
linux·笔记·学习
jencepan3 小时前
【3C拓展坞】40V20A同步四开关升降压控制器 太矽TX9575
单片机·嵌入式硬件
optimistic_chen3 小时前
【Redis 系列】常用数据结构---Hash类型
linux·数据结构·redis·分布式·哈希算法