当前位置: 首页 > news >正文

imx6ull-系统移植篇2—— U-Boot 命令使用(上)

目录

前言

U-Boot 命令

help

信息查询命令

bdinfo

printenv

version

环境变量操作命令

setenv 和 saveenv

修改环境变量

新建环境变量

删除环境变量

内存操作命令

md

nm

mm

mw

cp

cmp

网络操作命令

ping 命令

dhcp 命令

nfs 命令

tftp 命令

EMMC 和 SD 卡操作命令

mmc

mmc info 命令

mmc rescan 命令

mmc list 命令

mmc dev 命令

mmc part 命令

mmc read 命令

mmc write 命令

mmc erase 命令


前言

我们使用正点原子开发板imx6ull,在上一讲实验中:UBoot使用体验,我们介绍了UBoot的编译步骤、烧写启动流程,讲解到在倒计时3秒内按下回车键进入命令行模式。

聪明的宝子们就会问了,命令行模式有什么作用?能够用来做什么?本讲实验就来学习一下U-Boot 命令使用,主要包含:help、信息查询命令(bdinfo/printenv/version)、环境变量操作命令(setenv/saveenv)、内存操作命令(md/nm/mm/mw/cp/cmp)、网络操作命令(ping/dhcp/nfs/tftp)、操作MMC设备命令(mmc)等。

U-Boot 命令

help

进入 uboot 的命令行模式以后输入“help”或者“?”,然后按下回车即可查看当前 uboot 所支持的命令,如图:

Uboot 是可配置的,需要什么命令就使能什么命令。这些命令后面都跟有命令说明,用于描述此命令的作用。

输入“help(或?) 命令名”,可以查看命令的详细用法:

信息查询命令

bdinfo

bdinfo 命令,此命令用于查看板子信息:

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

printenv

“printenv”用于输出环境变量信息:

=> printenv
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=1
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=serialEnvironment size: 2583/8188 bytes

uboot 中的环境变量都是字符串,是可以修改的,有专门的命令来修改环境变量的值。

version

version 用于查看 uboot 的版本号:

环境变量操作命令

setenv 和 saveenv

命令 setenv 用于设置或者修改环境变量的值。

命令 saveenv 用于保存修改后的环境变量。

一般环境变量是存放在外部 flash 中的, uboot 启动的时候会将环境变量从 flash 读取到 DRAM 中。所以使用命令 setenv 修改的是 DRAM中的环境变量值,修改以后要使用 saveenv 命令将修改后的环境变量保存到 flash 中,否则的话uboot 下一次重启会继续使用以前的环境变量值。

修改环境变量

比如我们要将环境变量 bootdelay (倒计时延时时间)改为 5,就可以使用如下所示命令:

可以看出环境变量保存到了 MMC(0)中,也就是 SD 卡中。

修改 bootdelay 以后,重启开发板, uboot 就会变为 5 秒倒计时。嫌时间太久记得修改回来哦。

有时候我们修改的环境变量值可能会有空格, 比如 bootcmd、 bootargs 等, 这个时候环境变量值就得用单引号括起来,每组值之间用空格隔开。

比如下面修改环境变量 bootargs 的值:

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

新建环境变量

命令 setenv 也可以用于新建命令,比如我们新建一个环境变量cmdtest,将这个变量的值设为huaxuan,那么就可以使用如下命令:

setenv cmdtest huaxuan
saveenv

新建环境变量以后,需要重启 uboot,然后使用命令 printenv 查看是否有我们新增的命令。

删除环境变量

要删除一个环境变量只要给这个环境变量赋空值即可,像这样删掉我们刚新增的命令:

setenv cmdtest
saveenv

内存操作命令

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

md

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

md[.b, .w, .l] address [# of objects]
  • 命令中的[.b .w .l]对应 byte、 word 和 long,也就是分别以 1 个字节、 2 个字节、 4 个字节来显示内存值。
  • address 就是要查看的内存起始地址。
  •  [# of objects]表示要查看的数据长度。

查看以 0X80000000 为起始地址的内存数据:

nm

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

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

比如想修改 0x80000000 地址的数据:

?后面就可以输入要修改后的数据,输入完成以后按下回车,然后再输入‘q’即可退出。

但是可以看见使用nm命令修改地址的时候,地址不会自己递增,一直操作的都是同一个地址。

mm

mm 命令也是修改指定地址内存值的,使用 mm 修改内存值的时候地址会自增。

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

mw

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

mw [.b, .w, .l] address value [count]
  • mw 命令同样可以以.b、 .w 和.l 来指定操作格式,
  • address 表示要填充的内存起始地址,
  • value为要填充的数据,
  • count 是填充的长度。

比如使用.l 格式将以 0X80000000 为起始地址的 0x10 个内存块(0x10 * 4=64 字节)填充为 0X0A0A0A0A

怎么知道数据填充成功没有呢?使用命令 md 来查看:

cp

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

cp [.b, .w, .l] source target count
  • 以.b、 .w 和.l 来指定操作格式,
  • source 为源地址,
  • target 为目的地址,
  • count为拷贝的长度。

比如使用.l 格式将 0x80000000 处的地址拷贝到 0X80000040 处,长度为 0x10 个内存块(0x10 * 4=64 个字节):

cmp

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

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

我们使用.l 格式来比较 0x80000000 和 0X80000040 这两个地址数据是否相等,比较长度为 0x10 个内存块:

可以看出这两段内存的数据相等。那么不相等的时候会怎么样显示呢?

网络操作命令

uboot 支持大量的网络相关命令,比如 dhcp、ping、 nfs 和 tftpboot。

在使用 uboot 的网络功能之前先用网线将开发板的 ENET2 接口和电脑或者路由器连接起来。

还要设置表中所示的几个环境变量:

网络地址环境变量的设置,要确保 Ubuntu 主机和开发板的 IP地址在同一个网段内。

ping 命令

通过 ping 命令,ping 服务器的 IP 地址,来检测两者之间网络是否连通。如果网络正常,如下图:

dhcp 命令

dhcp 用于从路由器获取 IP 地址,前提得开发板连接到路由器上的,如果开发板是和电脑直连的,那么 dhcp 命令就会失效。

直接输入 dhcp 命令即可通过路由器获取到 IP 地址:

nfs 命令

nfs(Network File System)网络文件系统,通过 nfs 可以在计算机之间通过网络来分享资源。

uboot 中的 nfs 命令格式如下所示:

nfs [loadAddress] [[hostIPaddr:]bootfilename]
  • loadAddress 是要保存的 DRAM 地址,
  • [[hostIPaddr:]bootfilename]是要下载的文件地址。

在 uboot 中使用 nfs 命令,将 Ubuntu 中的 linux 镜像和设备树下载到开发板的 DRAM 中
,可以更方便调试 linux 镜像和设备树。我们之后都会使用网络调试的方法。

首先需要开启 Ubuntu 主机的 NFS 服务,然后新建一个 NFS 使用的目录,以后所有要通过NFS 访问的文件都需要放到这个 NFS 目录中。现在nfs目录里我已经放了一个zImage的镜像文件。

使用 nfs 命令来将 zImage 下载到开发板 DRAM 的 0X80800000 地址处:

nfs 80800000 192.168.1.253:/home/huax/linux/nfs/zImage
  • “ 80800000 ” 表 示 zImage 保 存 地 址 ,
  • “192.168.1.253:/home/huax/linux/nfs/zImage”表示 zImage 在 192.168.1.253 这个主机中,对应的nfs目录路径。

下载过程如图:打印done就是下载结束了。

下载完成以后可以查看 0x80800000 地址处的数据,使用命令 md.b 来查看前 0x100 个字节的数据,然后再用能查看二进制的工具比对,可以看见数据一致的。

tftp 命令

tftp 命令的作用和 nfs 命令一样,都是用于通过网络下载东西到 DRAM 中,只是 tftp 命令使用的 TFTP 协议, Ubuntu 主机作为 TFTP 服务器。

需要在 Ubuntu 上搭建 TFTP 服务器,需要安装 tftp-hpa 和 tftpd-hpa,命令如下:

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

TFTP 也需要一个文件夹tftpboot来存放文件,记得给 tftpboot 文件夹权限:

最后配置 tftp,安装完成以后新建文件/etc/xinetd.d/tftp, 如果没有/etc/xinetd.d 目录的话自行创建。

 然后在里面输入如下内容:

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

完了以后启动 tftp 服务,命令如下:

sudo service tftpd-hpa start

打开/etc/default/tftpd-hpa 文件,将TFTP_DIRECTORY 修改为我们上面创建的 tftp 文件夹目录,以后我们就将所有需要通过TFTP 传输的文件都放到这个文件夹里面,并且要给予这些文件相应的权限。

然后再重启一次 tftp 服务器。tftp 服务器已经搭建好了。

将我们需要烧写的zImage 镜像文件拷贝到 tftpboot 文件夹中,并且给予 zImage 相应的权限。

uboot 中的 tftp 命令格式如下:

tftpboot [loadAddress] [[hostIPaddr:]bootfilename]
  • loadAddress 是文 件在 DRAM 中的 存放 地址 ,
  • [[hostIPaddr:]bootfilename]是要从 Ubuntu 中下载的文件。

将 tftpboot 文件夹里面的 zImage 文件下载到开发板 DRAM 的 0X80800000 地址处,命令如下:

tftp 80800000 zImage

EMMC 和 SD 卡操作命令

mmc

mmc 后面跟不同的参数可以实现不同的功能:

我们常用的几个功能如下:

mmc info 命令

mmc info 命令用于输出当前选中的 mmc info 设备的信息:

mmc rescan 命令

mmc rescan 命令用于扫描当前开发板上所有的 MMC 设备,包括 EMMC 和 SD 卡。

mmc list 命令

mmc list 命令用于来查看当前开发板一共有几个 MMC 设备:

mmc dev 命令

mmc dev 命令用于切换当前 MMC 设备,命令格式如下:

mmc dev [dev] [part]
  • [dev]用来设置要切换的 MMC 设备号,
  • [part]是分区号。如果不写分区号的话默认为分区 0。

我们现在使用的EMMC,可以使用如下命令切换到 SD 卡:

mmc part 命令

有时候 SD 卡或者 EMMC 会有多个分区,可以使用命令“mmc part”来查看其分区。

比如查看 EMMC 的分区情况,输入如下命令:

mmc dev 1 //切换到 EMMC
mmc part //查看 EMMC 分区

由上图可知:此时 EMMC 有两个分区, 第一个分区起始扇区为 20480,长度为 262144 个扇区; 第二个分区起始扇区为 282624,长度为 14594048 个扇区。

如果 EMMC 里面烧写了 Linux 系统的话, EMMC 是有 3 个分区的:

  • 第 0 个分区存放 uboot,
  • 第 1 个分区存放Linux 镜像文件和设备树,
  • 第 2 个分区存放根文件系统。

如果要将 EMMC 的分区 2 设置为当前 MMC 设备,可以使用如下命令:

mmc read 命令

mmc read 命令用于读取 mmc 设备的数据,命令格式如下:

mmc read addr blk# cnt
  • addr 是数据读取到 DRAM 中的地址,
  • blk 是要读取的块起始地址(十六进制),一个块是 512字节,
  • cnt 是要读取的块数量(十六进制)。

比如从 EMMC 的第 1536(0x600)个块开始,读取 16(0x10)个块的数据到 DRAM 的0X80800000 地址处,命令如下::

mmc write 命令

要将数据写到 MMC 设备里面,可以使用命令“mmc write”,格式如下:

mmc write addr blk# cnt
  • addr 是要写入 MMC 中的数据在 DRAM 中的起始地址,
  • blk 是要写入 MMC 的块起始地址(十六进制),
  • cnt 是要写入的块大小,一个块为 512 字节。

我们可以使用命令“mmc write”来升级 uboot,也就是在 uboot 中更新 uboot。这里要用到 nfs 或者 tftp 命令,通过 nfs 或者 tftp 命令将新的 u-boot.bin 下载到开发板的 DRAM 中,然后再使用命令“mmc write”将其写入到 MMC设备中。

tftp 80800000 u-boot.imx
mmc dev 0 0
mmc write 80800000 2 2E6

使用 tftp 命令将烧写文件下载到 0x80800000 地址处,假设u-boot.imx 大小为 379904 字节, 379904/512=742,所以我们要向 SD 卡中写入742 个块,如果有小数的话就要加 1 个块。使用命令“mmc write”从 SD 卡分区 0 第 2 个块(扇区)开始烧写,一共烧写 742(0x2E6)个块。

如果要在 uboot 中更新 EMMC 对应的 uboot,可以使用如下所示命令:

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 需要这一步.

mmc erase 命令

如果要擦除 MMC 设备的指定块就是用命令“mmc erase”,命令格式如下:

mmc erase blk# cnt
  • blk 为要擦除的起始块,
  • cnt 是要擦除的数量。

本讲实验就先写到这吧,这些命令实在太多了,为了方便阅读和复习,我觉得分为上下两讲比较好。

在下讲内容里,我们会介绍:FAT 格式文件系统操作命令、EXT 格式文件系统操作命令、NAND 操作命令、BOOT 操作命令、和其它常用的命令(reset、 go、 run 和 mtest)。

http://www.dtcms.com/a/274076.html

相关文章:

  • Java 中线程通信方式笔记
  • tailwindCSS === 使用插件自动类名排序
  • ssm框架整合全攻略:从环境搭建到功能实现
  • 什么是Podman?能否替代Docker?Podman快速入门
  • dockerfile 笔记
  • STM32-DAC数模转换
  • 将英语转化为语音 英文转音频 英语转语音朗读
  • 嵌入式八股文之 GPIO
  • RISC-V:开源芯浪潮下的技术突围与职业新赛道 (三)RISC-V架构深度解剖(下)
  • FPGA实现SDI转LVDS视频发送,基于GTX+OSERDES2原语架构,提供2套工程源码和技术支持
  • Spring注解IoC与JUnit整合实战
  • MyBatis-Plus通用中等、大量数据分批查询和处理
  • 蔚来测开一面:HashMap从1.7开始到1.8的过程,既然都解决不了并发安全问题,为什么还要进一步解决环形链表的问题?
  • XPath 语法【Web 自动化-定位方法】
  • [java][springboot]@PostConstruct的介绍和用法
  • 机器学习基础知识【 激活函数、损失函数、优化器、 正则化、调度器、指标函数】
  • AI加持的开源知识库新秀:PandaWiki,如何用它打造智能化文档系统?
  • 「日拱一码」024 机器学习——防止过拟合
  • 【yolo】模型训练参数解读
  • 哪个ai写论文比较好?实测推荐这6大AI论文写作神器
  • CCF-GESP 等级考试 2025年6月认证C++五级真题解析
  • 2025年值得推荐的5款 AI赋能企业级项目管理软件工具大盘点!
  • Linux:多线程---同步生产者消费者模型
  • 【尝试】基于YoloV8做安全帽识别
  • 12. 说一下 https 的加密过程
  • 2025 年第十五届 APMCM 亚太地区大学生数学建模竞赛-B题 疾病的预测与大数据分析
  • CCN-508 规范
  • Web 网站性能优化之 Nginx 优化指南
  • 提示工程:突破Transformer极限的计算科学
  • S7-1200 系列 PLC 中 SCL 语言的 PEEK 和 POKE 指令使用详解