今天来看一下U-Boot的常用命令
帮助命令
在进入U-Boot命令行后,可以直接输入?或者help来查看当前uboot支持的所有命令
针对某一条命令,我们也可以直接通过?或者help来显示帮助信息,比如我们想要查看version这条命令的帮助信息,就可以按照下面的方式操作
环境变量操作命令
环境变量的操作命令有3条:printenv,setenv和saveenv,分别为打印环境变量、设置环境变量和保存环境变量。打印环境变量的命令没什么可说的,直接打印出所以环境变量信息;要注意的是,Uboot里变量的数据类型都是字符串。主要看后面两条:
设置环境变量
setenv,设定环境变量的值,语法为
setenv name value
要注意这个语句的用法,如果变量存在,就是修改变量为新的值,如果变量不存在,就创建新的变量。如果没有指定新的value,那么就是删除该变量。如果我们修改的变量的值存在空格,比如这个
那么在使用setenv修改值得时候需要用单引号将值括起来,表明这几组值都属于这个环境变量(我试过用双引号,可以实现功能。)
保存设置
设置过变量后需要通过saveenv命令保存,一般环境变量都是存在外部flash中,uboot启动的时候会将环境变量从flash读取到DDR里,所以一定要清楚setenv修改的是保存在DDR中的变量值,而saveenv是将修改后的变量保存到flash中,否则uboot重启后会继续使用修改前的值。
环境变量的操作涉及到两个命令: setenv 和 saveenv,命令 setenv 用于设置或者修改环境变量的值。命令 saveenv 用于保存修改后的环境变量,一般环境变量是存放在外部 flash 中的,uboot 启动的时候会将环境变量从 flash 读取到 DRAM 中。所以使用命令 setenv 修改的是 DRAM中的环境变量值,修改以后要使用 saveenv 命令将修改后的环境变量保存到 flash 中,否则的话uboot 下一次重启会继续使用以前的环境变量值。
就是讲变量存只eMMc,也就是后面要讲到的MMC(1)中。
内存操作命令
内存命令是直接对DDR进行读写操作的。常用的内存操作命令包括md、nm、mm、mw和cmp。
md命令
显示内存里的数据,语法可以看下帮助信息
其中bwl代表的是byte,word和long,分别一1个字节、2个字节和4个字节来显示内存值。address是我们要查看的内存地址,objects是我们要看的数据长度。一定要注意:
uboot命令中的数字都是16进制的!!!
可以看下下面的效果
命令要求的效果就是查看从0x80000000起始的0x20个(32个)内存的数据。
后面objects的数值和前面数据类型是一致的,比如下面的图
虽然数据长度还是还是0x20,但是由于我们指定的数据类型是word,所以一共显示了32*2=64个字节的数据,并且数据排列好像是小端模式(注意第一个word数据位5FDF,而在byte显示的时候5F在后面)。
nm命令
修改指定内存的值。
注意修改的值,要和指定的寄存器长度保持一致,上图中我们指定的数据类型是b(byte),赋值就是0x00~0xFF,如果是w就是0x0000~0xFFFF。问号前是当前的值,问号后是赋的值。设置好按q退出。
mm命令
和nm命令差不多,但是mm命令是对指定的寄存器赋值,mm是自增的方式可以连续对寄存器赋值
mw命令
mw命令用来使用一个指定的数据填充一段内存
mw在使用的时候也是要按照指定数据长度
cp命令
数据拷贝命令,将DDR中的数据从一段内存拷贝到另外一段内存中,或者把Flash(EMMc/NAND)中的数据拷贝到DDR中
source为源地址,target为目的地址,count为数据长度
cmp命令
比较命令,用于比较两段指定地址内存的数据是否相等
比较的时候也可以指定数据类型。
网络操作命令
在对操作网络时候,需要先连接网络后设置ip什么的。需要设置参数有ip、MAC地址、网关ip、子网掩码等环境变量,由于我的路由IP是192.168.3.1,所以就将参数设置如下
setenv ipaddr 192.168.3.200 setenv ethaddr=00:04:9f:04:d2:35 setenv gatewayip=192.168.3.1 setenv netmask=255.255.255.0 setenv serverip=192.168.3.114 saveenv
从上到下依次为uboot的IP、uboot的MAC地址(这个MAC地址我不知道是怎么来的,随便设定的就行,但是一个网段内MCA必须是唯一的)、网关、子网掩码、服务器(PC端IP)。重启后可以通过ping命令来测试网络效果
这里有个要注意的地方:ping命令只能在uboot里ping网段内其他的机器,在别的地址下pinguboot是不行的,因为uboot里没有对ping命令做相应的处理。所以会失败
dhcp命令
dhcp命令用来从路由器获取IP,该方法不会改变环境变量,也就是说在断电重启后就复位了。但是要注意dhcp命令使用时设备必须在有路由功能的设备上连接,直连到电脑上是不行的。
nfs命令
nfs(network file system)网络文件系统,通过nfs命令可以获取服务器中的文件,这样可以很方便的调试linux镜像或设备树,因为嵌入式linux开发不像单片机一样通过JLINK或STLink等仿真器将代码直接烧录在单片机内而是烧写到EMMC、NANDflash等外置的flash中。但是嵌入式Linux开发也没有合适的IDE为我们提供一个烧写算法供我们使用一个download按钮点击一下就烧写到外部flash中,所以在Linux内核调试过程中,都是通过网络来调试的,将编译好的Linux镜像和设备树文件下载到DDR内直接运行就可以了。在开启了服务器端的NFS功能后,可以通过nfs命令获取文件
这里要插入一个新的部分:Ubuntu20.04的nfs设置。在实际配置nfs时候遇到不少问题。可以点进去看一下。
和nfs命令有个相通功能的命令:tftp,语法一样,但是需要服务器开启tftp服务,有需求的可以百度一下。在实现了nfs功能以后,我们就可以通过网络把镜像或者设备树文件down到DDR或者FLASH里,不用每次烧写了。
EMMC(SD卡)操作
uboot可以支持EMMC和SD卡,所以也提供了EMMC的操作指令,在IMX6U的uboot里,EMMC和SD卡都归属与MMC,而mmc也是一系列的指令,我们可以用? mmc来查看相关命令
上面就是I.MX6UL支持的mmc相关的命令。下面看一下主要的信息
mmc info
显示mmc设备信息
当前选中的设备是EMMC,mmc版本为4.0,容量7.3G,8为总线带宽,速度为52000000Hz(52MHz)。
mmc list
显示MMC设备。
当前开发板有两个mmc设备,FSL_SDHC:0和FSL_SDHC:1(eMMC),前者是SD卡,后者是eMMC,默认eMMC是当前MMC设备。
mmc dev
切换mmc设备,格式如下
dev为mmc设备号,part为分区号,省略时为默认0,可以按照下面的方式切换mmc设备
mmc part
显示当前mmc设备分区信息。
上面的图可以看出来,eMMC分了两个分区,如果eMMC里烧写了Linux,就会有3个分区,第0个用来存放uboot, 第1个放Linux镜像文件和设备树,第2个分区存放根文件系统。而第0个分区由于没有格式化是无法显示出来的。如果mmc设备是一个新的SD卡,那么只会有分区0,所以前面烧写uboot到SD卡就是将uboot烧写到SD卡的分区0里。
mmc read
读取mmc数据到DDR里,格式如下:
addr是目标DDR的地址,blk为要读取到块起始地址,一个块是512字节,这里的块和扇区是一个意思,在MMC中我们常常用扇区来描述。cnt是要读取块的数量,如果我们要从mmc里的第1536个块(0x600),连续16个块(0x10)读取到DDR的0x80800000开始的地址,就可以这么做
这样就读取了eMMC里的数据 ,使用md命令打印一下,截取一段输出值看一下
从输出的数据解析出来的字符可以看出来有baudrate等字符,我们读取的数据就就是rboot里的环境变量。eMMC里uboot的环境变量的存储起始地址就是1536*512=786432。
mmc write
前面讲的是mmc的读取,下面是写mmc指令。格式如下:
addr还是DDR里的地址,blk为起始块地址,cnt为写入块的数量。这个一般是配合nfs命令来使用的,先用nfs获取新编译的uboot到DDR内,再使用mmc write命令将其写到MMC设备中。演示一下:先看一下现有的uboot版本信息
由于用的是教程提供的uboot,编译时间是2019年10月23日, 然后把新编译的uboot文件通过nfs发送到DDR里(注意是带头文件的imx文件!)
并且可以看出来,uboot文件一共是363520字节,363520/512=710个块(0x2C6)。然后按照下面的流程写入eMMC
切换mmc设备置1(eMMC)0分区,写到EMMC里(注意无论是SD卡还是eMMC,千万不能写到前两个块,里面保存着分区表!!!)
重启一下,看看版本信息
uboot编译时间是2022年2月3日。说明uboot更新成功。以后就可以通过这个方法在uboot中更新uboot了。
FAT文件系统操作
有些时候我们需要在uboot内对emmc或者SD卡中的文件操作,这时候就要用到文件操作命令:fatinfo、fatls、fstype、fatload和fatwrite
fat info
查询指定MMC设备指定分区的文件系统信息
其中,interface为mmc等指定的设备、dev是设备号,part是要查询的分区,比如我们要查询emmc分区1的文件系统信息,效果就是这样的
上面的图可以看出来,eMMC分区1的文件系统为FAT32格式的
fatls命令
fatls用来显示指定的路径下的文件信息,语法和fatinfo一样,比如我们想查看eMMC里分区1里的文件信息就可以这样
可以看出来,mmc设备1,分区1里有6个文件,分别是5个设备树文件还有一个镜像文件。
fstype
查看指定设备分区的文件系统格式,前面说过了,mmc1分了3个part,我们可以查看下3个分区的文件系统格式
分区0是放置uboot的未分区格式,分区1是存放镜像和设备树的fat格式,分区2为ext4,用来存放Linux的根文件系统。
fatload
将指定的文件读取到DDR内。
比如我们要读取前面说的mmc1:1里的zimage文件到0x80800000,就可以用下面的命令:
fatload mmc 1:1 80800000 zimage
有兴趣的话可以用md命令打印下DDR里的数据,这里就不再对比了。
fatwrite
fat写
EXT格式文件系统操作
ext文件系统分ext2和ext4,以ext4为例,常用的有ext4load、ext4ls和extwrite,使用方法和fat的方法一样,这里就不讲了。
boot操作
uboot的本质是用来引导Linux的,所以uboot是由boot命令来启动Linux的,常用的命令有下面几种
bootz命令
bootz命令使用前需要将镜像和社保数复制到DDR里,通过bootz命令启动Linux。
boot命令
和bootz差不多,但是boot命令是通过调用环境变量里的bootcmd来实现Linux启动的,我们要把bootcmd保存在环境变量中,每次通过boot来实现引导就行了,不用每次都敲一堆nfs命令然后再启动,调试的时候要方便的多。
其他命令
uboot其余的一些常用的命令
reset
复位命令,输入reset后复位重启
go
跳转到指定地址,可以将编译后的裸机例程(不带IVT等信息的bin文件)拷贝到指定地址,通过go命令跳转。相当于不用SD卡调试裸机驱动了
run
运行环境变量中定义的命令