首页 > 系统相关 >《DFZU2EG_4EV MPSoC之嵌入式Linux开发指南》第十一章 U-Boot使用实验

《DFZU2EG_4EV MPSoC之嵌入式Linux开发指南》第十一章 U-Boot使用实验

时间:2023-01-13 10:07:51浏览次数:67  
标签:MPSoC uboot 11.4 DFZU2EG Boot 如下 命令 所示 mmc

U-Boot使用实验​

在移植linux内核之前,我们肯定要先了解U-Boot。因为U-boot是我们的开发板加载引导启动linux内核的必要工具。本章我们讲解U-Boot是什么、有何作用,有哪些命令以及如何通过U-boot加载引导启动linux内核。​


U-Boot简介

对于计算机系统而言,从开机上电到操作系统启动需要一个引导过程,这个引导过程由引导程序指定。引导程序是系统加电启动运行的第一段软件代码。在PC体系结构中,引导程序由主板上的BlOS和位于硬盘MBR中的启动代码组成。系统上电后,首先运行BlOS,在完成硬件检测和资源分配后,将硬盘MBR中的引导程序读到系统的RAM中,然后将控制权交给引导程序。引导程序的主要运行任务就是将内核映像从硬盘读到RAM中,然后跳转到内核的入口点去运行,也即开始启动操作系统。嵌入式Linux系统同样离不开引导程序,这个引导程序一般我们叫作启动加载程序(Bootloader)。​

Bootloader是在操作系统运行之前执行的一段小程序。通过这段小程序,可以初始化硬件设备、建立内存空间的映射表,从而建立适当的系统软硬件环境,为最终调用操作系统内核做好准备。也就是说芯片上电以后先运行一段bootloader程序。这段bootloader程序会先初始化DDR等外设,然后将Linux内核从flash(SD、eMMC、NAND、NOR FLASH等)拷贝到DDR中,最后启动Linux内核。当然了,bootloader的实际工作要复杂的多,但是它最主要的工作就是启动Linux内核。​

对于嵌入式系统,bootloader是基于特定硬件平台实现的。因此,几乎不可能为所有的嵌入式系统建立一个通用的bootloader,不同的处理器架构都有不同的bootloader。Bootloader不仅依赖于CPU的体系结构,而且依赖于嵌入式系统板级设备的配置。对于两块不同的嵌入式开发板而言,即使它们使用同一种处理器,要想让运行在一块板子上的bootloader程序也能运行在另一块板子上,一般需要修改bootloader的源程序。庆幸的是,大部分bootloader仍具有很多共性,某些bootloader能够支持多种体系结构的嵌入式系统。​

现成的bootloader软件有很多,比如U-Boot、vivi、RedBoot等等,其中以U-Boot使用最为广泛,为了方便书写,本书会将U-Boot写为uboot。特别说明的是对于ZYNQ MPSoC而言,在引导过程中,先运行FSBL来设置PS,然后运行U-Boot用于加载Linux内核映像并引导Linux,所以uboot对于ZYNQ MPSoC而言是第二阶段引导程序,FSBL是第一阶段引导程序。​

uboot的全称是Universal Boot Loader,uboot是一个遵循GPL协议的开源软件。uboot是一个裸机代码,可以看作是一个裸机综合项目。现在的uboot已经支持液晶屏、网络、USB等高级功能。uboot官网地址:​http://www.denx.de/wiki/U-Boot/​,如下图所示:​

《DFZU2EG_4EV MPSoC之嵌入式Linux开发指南》第十一章 U-Boot使用实验_开发板


图11.1.1 uboot官网​

我们可以在uboot官网下载uboot源码,点击上图中左侧Topics中的“Source Code”,打开如下图所示界面:​

《DFZU2EG_4EV MPSoC之嵌入式Linux开发指南》第十一章 U-Boot使用实验_linux_02


图11.1.2 uboot源码界面​

点击上图中的“HTTPS”,进入其服务器即可看到uboot源码,如下图所示:​

《DFZU2EG_4EV MPSoC之嵌入式Linux开发指南》第十一章 U-Boot使用实验_开发板_03


图11.1.3 uboot源码​

上图显示的就是uboot原汁原味的源码文件,目前最新的版本是2022.04。但是我们一般不会直接用uboot官方的U-Boot源码的。uboot官方的uboot源码是给半导体厂商准备的,半导体厂商会下载uboot官方的uboot源码,然后将自家相应的芯片移植进去。也就是说半导体厂商会自己维护一个为其设计的芯片定制的uboot版本。既然是定制的,那么肯定对自家的芯片支持会很全,虽然uboot官网的源码中一般也会支持他们的芯片,但是绝对是没有半导体厂商自己维护的uboot全面。​

Xilinx维护的uboot版本可在网站​https://github.com/Xilinx/u-boot-xlnx​查看,下载地址为:​https://github.com/Xilinx/u-boot-xlnx/releases​,下载界面如下图所示:​

《DFZU2EG_4EV MPSoC之嵌入式Linux开发指南》第十一章 U-Boot使用实验_环境变量_04


图11.1.4 Xilinx官方uboot下载界面

点击上图中箭头所指的zip或tar.gz就可以下载,xilinx-v2019.2对应的就是2019.2的版本,与我们使用的petalinux版本相对应,如果不对应可能会出现某些问题。图11.1.4中的uboot基本支持了Xilinx当前所有可以跑Linux的芯片,而且支持各种启动方式,比如SD卡、eMMC、NAND、NOR FLASH等等,这些都是uboot官方所不支持的。但是图11.1.4中的uboot是针对Xilinx自家评估板的,如果是我们自己做的板子就需要修改Xilinx官方的uboot,使其支持我们自己做的板子,正点原子的DFZU2EG_4EV MPSoC开发板就是自己做的板子,虽然大部分都参考了Xilinx官方的ZYNQ MPSoC开发板,但是还是有很多不同的地方,所以需要修改Xilinx官方的uboot,使其适配正点原子的ZYNQ MPSoC开发板。所以当我们拿到开发板以后,是有三种uboot的,这三种uboot的区别如下表所示:​

种类

描述

uboot官方的uboot代码

由uboot官方维护开发的uboot版本,版本更新快,基本包含所有常用的芯片​

半导体厂商的uboot代码

半导体厂商维护的一个uboot,专门针对自家的芯片,在对自家芯片支持上要比uboot官方的好​

开发板厂商的uboot代码

开发板厂商在半导体厂商提供的uboot基础上加入了对自家开发板的支持​

表11.1.2三种uboot的区别​

那么这三种uboot该如何选择呢?首先uboot官方的基本是不会用的,因为支持太弱了。最常用的就是半导体厂商或者开发板厂商的uboot,如果你用的半导体厂商的评估板,那么就使用半导体厂商的uboot,如果你是购买的第三方开发板,比如正点原子的ZYNQ MPSoC开发板,那么就使用正点原子提供的uboot源码(也是在半导体厂商的uboot上修改的)。当然了,你也可以在购买了第三方开发板以后使用半导体厂商提供的uboot,只不过有些外设驱动可能不支持,需要自己移植,这个就是我们常说的uboot移植。​

注:上面介绍的是一般情况,对于Xilinx厂商的芯片而言有些区别,因为Xilinx提供了Petalinux开发工具。在第六章Petalinux设计流程实战中,我们并没有设置uboot,而是使用默认的官方的uboot,也可以正常运行在我们的ZYNQ MPSoC开发板上。这是因为Petalinux开发工具会根据xsa文件自动分析ZYNQ MPSoC的配置,从而自动配置uboot,相当于自动移植了uboot,严谨一点,应该称为自动适配。这种自动适配主要是使uboot能够在开发板上正常运行,基本能满足我们的使用。所以我们的ZYNQ MPSoC开发板没有提供移植的uboot,也就是没有上面所说的开发板厂商的uboot代码,使用Petalinux自带的uboot源码就可以了。​

Petalinux配置和编译U-Boot

进入到第六章Petalinux设计流程实战中创建的petalinux工程目录下,然后按照6.3.2小节设置Petalinux环境变量。​

uboot的功能有很多,虽然默认的功能一般而言已经够用了,但在项目开发过程中,可能会使用到uboot平时不常用的功能,这时就需要配置uboot以使能相应功能。在Petalinux中配置uboot的方法很简单,在搭建好的petalinux工程目录下,执行如下命令即可进入uboot图形配置界面:​

petalinux-config -c u-boot​

执行后会在终端中打开另一个配置uboot的标签页,如下图所示:​

《DFZU2EG_4EV MPSoC之嵌入式Linux开发指南》第十一章 U-Boot使用实验_linux_05


图11.2.1 uboot配置界面​

如果有配置uboot的需求可以自行配置。笔者一般使用默认的配置,除了配置项“(4) delay in seconds before automatically booting”外,没有遇到额外配置的情况,所以就不对这些配置项进行介绍了。这里说一下配置项“(4) delay in seconds before automatically booting”的含义,该配置是用来设置启动uboot后,延时多长时间自动启动linux,默认为4秒,如果读者觉得太长的话,可以重新设置,笔者此处使用默认的设置。​

配置完成后,保存配置退出。此处笔者由于没有进行配置,直接退出。对于Petalinux19.2版本而言,执行上面的配置操作后,会在当前Petalinux工程的components/plnx_workspace/sources/目录下生成uboot的源码,如下图所示:​

《DFZU2EG_4EV MPSoC之嵌入式Linux开发指南》第十一章 U-Boot使用实验_环境变量_06


图11.2.2 uboot源码​

现在编译uboot。编译uboot的命令很简单,执行如下命令即可编译uboot:​

petalinux-build -c u-boot​

也可以只使用“petalinux-build”命令,用来编译fsbl、uboot、设备树、Linux内核和根文件系统等,如果是重新创建Petalinux工程,推荐使用“petalinux-build”命令,不带“-c u-boot”参数。​

命令执行完以后uboot也就编译成功了,如下图所示:​

《DFZU2EG_4EV MPSoC之嵌入式Linux开发指南》第十一章 U-Boot使用实验_开发板_07


图11.2.3 编译U-Boot​

注:有一个警告,Petalinux版本的问题,不影响使用。​

编译完成以后会在当前Petalinux工程目录的images/linux目录下生成u-boot.elf文件,如下图所示:​

《DFZU2EG_4EV MPSoC之嵌入式Linux开发指南》第十一章 U-Boot使用实验_环境变量_08


图11.2.4 u-boot镜像文件​

U-Boot烧写与启动

uboot编译好以后就可以烧写到板子上使用了。我们将u-boot.elf文件打包到ZYNQ MPSoC的启动文件BOOT.BIN中,在终端中输入如下命令:​

petalinux-package --boot --fsbl --fpga --u-boot --force​

执行结果如下图所示:​

《DFZU2EG_4EV MPSoC之嵌入式Linux开发指南》第十一章 U-Boot使用实验_环境变量_09


图11.3.1 打包生成BOOT.BIN文件​

生成BOOT.BIN文件后,插上SD启动,将该Petalinux工程image/linux目录下的BOOT.BIN文件拷贝到SD卡的boot分区也即FAT32分区。​

拷贝完成后将SD卡插到MPSoc开发板上,启动模式设置从SD卡启动,使用USB线将开发板的串口和电脑连接,如果有条件可以用以太网线将PS以太网口连接到能够联网的路由器。打开串口上位机如putty,设置好串口参数并打开,最后复位开发板。在串口上位机上出现“Hit any key to stop autoboot: ”倒计时的时候按下键盘上的回车键,默认是4秒倒计时,在4秒倒计时结束以后如果没有按下回车键的话uboot就会使用默认参数来启动Linux内核了。如果在4秒倒计时结束之前按下回车键,那么就会进入uboot的命令行模式,如下图所示:​

《DFZU2EG_4EV MPSoC之嵌入式Linux开发指南》第十一章 U-Boot使用实验_linux_10


图11.3.2 uboot启动过程​

从上图可以看出,当进入到uboot的命令行模式以后,左侧会出现一个“ZynqMP>”标志。启动的时候会输出一些信息,这些信息如下所示:​

1 Xilinx Zynq MP First Stage Boot Loader​
2 Release 2019.2 Mar 14 2022 - 01:27:14​
3 NOTICE: ATF running on XCZU4EV/silicon v4/RTL5.1 at 0xfffea000​
4 NOTICE: BL31: Secure code at 0x0​
5 NOTICE: BL31: Non secure code at 0x8000000​
6 NOTICE: BL31: v2.0(release):xilinx-v2019.1-12-g713dace9​
7 NOTICE: BL31: Built : 10:53:49, Mar 14 2022​
8 PMUFW: v1.1​
9 ​
10 ​
11 U-Boot 2019.01 (Mar 29 2022 - 03:16:53 +0000)​
12 ​
13 Model: Alientek Zynq MpSoc Development Board​
14 Board: Xilinx ZynqMP​
15 DRAM: 2 GiB​
16 EL Level: EL2​
17 Chip ID: zu4ev​
18 MMC: mmc@ff160000: 0, mmc@ff170000: 1​
19 Loading Environment from SPI Flash... SF: Detected n25q256a with page size 256 Bytes, erase size 64 KiB, total 32 MiB​
20 OK​
21 In: serial@ff000000​
22 Out: serial@ff000000​
23 Err: serial@ff000000​
24 Model: Alientek Zynq MpSoc Development Board​
25 Board: Xilinx ZynqMP​
26 Net: ZYNQ GEM: ff0b0000, phyaddr 4, interface gmii​
27 eth0: ethernet@ff0b0000ZYNQ GEM: ff0e0000, phyaddr 7, interface rgmii-id​
28 ​
29 Warning: ethernet@ff0e0000 (eth1) using random MAC address - 46:15:4f:73:5b:11​
30 , eth1: ethernet@ff0e0000​
31 Hit any key to stop autoboot: 0​
32 ZynqMP>

下面我们简单的了解一下这些信息。​

第1~8行是First Stage Boot Loader启动输出的信息。第3行可以看到当前使用的ZYNQ芯片是XCZU4EV。​

从第11行起是uboot启动输出的信息。​

第11行是uboot版本号和编译时间,可以看出,当前的uboot版本号是2019.01,编译时间是2022年3月29日3点16分。​

第13~17行是开发板相关信息,可以看出当前使用的开发板名称为“Alientek Zynq MpSoc Development Board”,核心板为“Xilinx ZynqMP”,核心板的芯片id为zu4ev。​

第15行提示当前板子的DRAM(内存)为2GiB。​

第18提示当前有两个MMC/SD卡控制器:mmc@ff160000和mmc@ff170000。​

第19行从SPI(QSPI)加载环境变量;检测到开发板使用的QSPI为n25q256a,大小为32MiB。​

第21~23是标准输入、标准输出和标准错误所使用的终端,这里都使用串口(serial)作为终端。​

第26~30行是网口信息,提示我们当前有两个网口eth0和eth1,其中eth0的phy地址为4,eth1的phy地址为7。​

第31行是倒计时提示,默认倒计时4秒,倒计时结束之前按下回车键就会进入Uboot命令行模式。如果在倒计时结束以后没有按下回车键,那么Linux内核就会启动,Linux内核一旦启动,uboot就会寿终正寝。这个值与我们在11.2节介绍的配置项“(4) delay in seconds before automatically booting”有关。​

uboot是来干活的,我们现在已经进入uboot的命令行模式了,进入命令行模式以后就可以给uboot发号施令了。当然了,不能随便发号施令,得看看uboot支持哪些命令,然后使用这些uboot所支持的命令来做一些工作。下一节讲解uboot命令的使用。​

U-Boot命令的使用

进入uboot的命令行模式以后输入“help”或者“?”,然后按下回车即可查看当前uboot所支持的命令,如图11.4.1所示。该图只是uboot的一部分命令,并不是uboot所支持的所有命令。前面说过uboot是可配置的,需要什么命令就使能什么命令,所以该图中的命令是正点原子提供的uboot中使能的命令,uboot支持的命令还有很多,而且也可以在uboot中自定义命令。这些命令后面都跟有命令说明,用于描述此命令的作用,但是命令具体怎么用呢?我们输入“help(或?) 命令名”就可以获取可用命令的完整列表以及查看对应命令的详细用法。​

《DFZU2EG_4EV MPSoC之嵌入式Linux开发指南》第十一章 U-Boot使用实验_环境变量_11


图11.4.1命令列表​

以“bootm”这个命令为例,我们输入如下命令即可查看“bootm”这个命令的用法:​

? bootm 或 bootm​

结果如下图所示:​

《DFZU2EG_4EV MPSoC之嵌入式Linux开发指南》第十一章 U-Boot使用实验_开发板_12


图11.4.2命令使用说明​

上图详细的列出了“bootm”这个命令的用法,其它的命令也可以使用此方法查询具体的使用方法。接下来我们学习一下一些常用的uboot命令。​

信息查询命令

常用的和信息查询有关的命令有3个:bdinfo、printenv和version。先来看一下bdinfo命令,此命令用于查看板子信息,直接输入“bdinfo”即可,结果如下图所示:​

《DFZU2EG_4EV MPSoC之嵌入式Linux开发指南》第十一章 U-Boot使用实验_linux_13


图11.4.3命令​

从上图中可以得出DRAM的起始地址和大小,UART波特率、sp(堆栈指针)起始地址等信息。​

命令“printenv”用于输出环境变量信息,uboot也支持TAB键自动补全功能,输入“print”然后按下TAB键就会自动补全命令,直接输入“print”也可以。输入“print”,然后按下回车键,环境变量如下图所示:​

《DFZU2EG_4EV MPSoC之嵌入式Linux开发指南》第十一章 U-Boot使用实验_开发板_14


图11.4.4命令结果​

在上图中有很多的环境变量,比如baudrate、board_name、boot_img、bootcmd等等。uboot中的环境变量都是字符串,既然叫做环境变量,那么它的作用就和“变量”一样。比如bootdelay这个环境变量就表示uboot启动延时时间,默认bootdelay=4,也就默认延时4秒。前面说的4秒倒计时就是由bootdelay定义的,如果将bootdelay改为5的话就会倒计时5s了。uboot中的环境变量是可以修改的,有专门的命令来修改环境变量的值,稍后我们会讲解。​

命令version用于查看uboot的版本号,输入“version”,uboot版本号如下图所示:​

《DFZU2EG_4EV MPSoC之嵌入式Linux开发指南》第十一章 U-Boot使用实验_环境变量_15


图11.4.5命令结果​

从上图可以看出,当前uboot版本号为2019.01,2021年11月3日编译的,编译器为aarch64-xilinx-linux-gcc等信息。​

环境变量操作命令

1、修改环境变量

环境变量的操作涉及到两个命令:setenv和saveenv,命令setenv用于设置或者修改环境变量的值。命令saveenv用于保存修改后的环境变量,一般环境变量是存放在外部flash中的,uboot启动的时候会将环境变量从flash读取到DRAM中。所以使用命令setenv修改的是DRAM中的环境变量值,修改以后要使用saveenv命令将修改后的环境变量保存到flash中,否则的话uboot下一次重启会继续使用以前的环境变量值。​

命令setenv使用起来很简单,格式为:​

setenv 命令 值​

或​

setenv 命令‘值1 值2 值3’​

比如我们要将环境变量bootdelay该为5,就可以使用如下所示命令:​

setenv bootdelay 5​

saveenv​

上述命令执行过程如下图所示:​

《DFZU2EG_4EV MPSoC之嵌入式Linux开发指南》第十一章 U-Boot使用实验_开发板_16


图11.4.6环境变量修改​

在上图中,当我们使用命令saveenv保存修改后的环境变量的话会有保存过程提示信息,根据提示可以看出环境变量保存到了SPI flash中,也就是开发板上的QSPI Flah--w25q256中。​

修改bootdelay以后,重启开发板,uboot就是变为5秒倒计时,如下图所示:​

《DFZU2EG_4EV MPSoC之嵌入式Linux开发指南》第十一章 U-Boot使用实验_开发板_17


图11.4.7 5秒倒计时​

2、新建环境变量

命令setenv也可以用于新建命令,用法和修改环境变量一样,比如我们新建一个环境变量author,author的值为“alientek”,那么就可以使用如下命令:​

setenv author alientek​

saveenv​

新建命令author完成以后重启uboot,然后使用命令printenv查看当前环境变量,如下图所示:​

《DFZU2EG_4EV MPSoC之嵌入式Linux开发指南》第十一章 U-Boot使用实验_环境变量_18


图11.4.8环境变量​

从上图可以看到新建的环境变量:author,其值为:alientek。​

3、删除环境变量

既然可以新建环境变量,那么就可以删除环境变量,删除环境变量也是使用命令setenv,要删除一个环境变量只要给这个环境变量赋空值即可,比如我们删除掉上面新建的author这个环境变量,命令如下:​

setenv author​

saveenv​

上面命令中通过setenv给author赋空值,也就是什么都不写来删除环境变量author。重启uboot就会发现环境变量author没有了。​

内存操作命令

内存操作命令就是用于直接对DRAM进行读写操作的,常用的内存操作命令有md、nm、mm、mw、cp和cmp。我们依次来看一下这些命令都是做什么的。​

1、md命令

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

md [.b, .w, .l .q] address [# of objects]​

命令中的[.b .w .l .q]分别对应byte、word、long、qword,也就是分别以1个字节、2个字节、4个字节和8个字节来显示内存值。address就是要查看的内存起始地址,[# of objects]表示要查看的数据长度,这个数据长度单位不是字节,而是跟你所选择的显示格式有关。比如你设置要查看的内存长度为20(十六进制为0x14),如果显示格式为.b的话那就表示20个字节;如果显示格式为.w的话就表示20个word,也就是20*2=40个字节;如果显示格式为.l的话就表示20个long,也就是20*4=80个字节。另外要注意:​

uboot命令中的数字都是十六进制的!不是十进制的!​

比如你想查看以0X8000000开始的20个字节的内存值,显示格式为.b的话,应该使用如下所示命令:​

md.b 8000000 14​

而不是:​

md.b 8000000 20​

上面说了,uboot命令里面的数字都是十六进制的,所以可以不用写“0x”前缀,十进制的20其十六进制为0x14,所以命令md后面的个数应该是14,如果写成20的话就表示查看32(十六进制为0x20)个字节的数据。分析下面四个命令的区别:​

md.b 8000000 10​

md.w 8000000 10​

md.l 8000000 10​

md.q 8000000 10​

上面这四个命令都是查看以0X8000000为起始地址的内存数据,第一个命令以.b格式显示,长度为0x10,也就是16个字节;第二个命令以.w格式显示,长度为0x10,也就是16*2=32个字节;第二个命令以.l格式显示,长度为0x10,也就是16*4=64个字节;最后一个命令以.q格式显示,长度也是0x10,也就是16*8=128个字节。这四个命令的执行结果如下图所示:​

《DFZU2EG_4EV MPSoC之嵌入式Linux开发指南》第十一章 U-Boot使用实验_linux_19


图11.4.9命令使用示例​

2、nm命令

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

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

nm命令同样可以以.b、.w、.l和.q来指定操作格式,比如现在以.l格式修改0x8000000地址的数据为0x12345678。输入命令:​

nm.l 8000000​

输入上述命令以后如下图所示:​

《DFZU2EG_4EV MPSoC之嵌入式Linux开发指南》第十一章 U-Boot使用实验_linux_20


图11.4.10命令​

在上图中,8000000表示现在要修改的内存地址,1400000a表示地址0x8000000现在的数据,?后面就可以输入要修改后的数据0x12345678,输入完成以后按下回车,然后再输入‘q’即可退出,如下图所示:​

《DFZU2EG_4EV MPSoC之嵌入式Linux开发指南》第十一章 U-Boot使用实验_linux_21


图11.4.11修改内存数据​

修改完成以后再使用命令md来查看一下有没有修改成功(命令md.l 8000000 1),如下图所示:​

《DFZU2EG_4EV MPSoC之嵌入式Linux开发指南》第十一章 U-Boot使用实验_环境变量_22


图11.4.12查看修改后的值​

从上图可以看出,此时地址0X8000000的值变为了0x12345678。​

3、mm命令

mm命令也是修改指定地址内存值的,使用mm修改内存值的时候地址会自增,而使用命令nm的话地址不会自增。比如以.l格式修改从地址0x8000000开始的连续3个内存块(3*4=12个字节)的数据为0x05050505,操作如下图所示(命令mm.l 8000000):​

《DFZU2EG_4EV MPSoC之嵌入式Linux开发指南》第十一章 U-Boot使用实验_开发板_23


图11.4.13命令mm​

从上图可以看出,修改了地址0X8000000、0X8000004和0X8000008的内容为0x05050505。使用命令md查看修改后的值(命令md.l 8000000 3),结果如下图所示:​

《DFZU2EG_4EV MPSoC之嵌入式Linux开发指南》第十一章 U-Boot使用实验_linux_24


图11.4.14查看修改后的内存数据​

从上图可以看出内存数据修改成功。​

4、mw命令

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

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

mw命令同样可以以.b、.w、.l和.q来指定操作格式,address表示要填充的内存起始地址,value为要填充的数据,count是填充的长度。比如使用.l格式将以0X8000000为起始地址的0x10个内存块(0x10 * 4=64字节)填充为0X0A0A0A0A,然后使用命令md来查看,命令如下:​

mw.l 8000000 0A0A0A0A 10​

md.l 8000000 10​

结果如下图所示:​

《DFZU2EG_4EV MPSoC之嵌入式Linux开发指南》第十一章 U-Boot使用实验_开发板_25


图11.4.15查看修改后的内存数据​

从上图可以看出内存数据修改成功。​

5、cp命令

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

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

cp命令同样可以以.b、.w、.l和.q来指定操作格式,source为源地址,target为目的地址,count为拷贝的长度。我们使用.l格式将0x8000000处的地址拷贝到0X8000100处,长度为0x10个内存块(0x10 * 4=64个字节),命令如下所示:​

md.l 8000000 10 #查看地址0x8000000处的内容​

md.l 8000100 10 #查看地址0x8000100处的内容​

cp.l 8000000 8000100 10 #复制数据​

md.l 8000100 10 #查看地址0x8000100处的内容​

结果如下图所示:​

《DFZU2EG_4EV MPSoC之嵌入式Linux开发指南》第十一章 U-Boot使用实验_开发板_26


图11.4.16命令操作结果​

在上图中,先使用md.l命令打印出地址0x8000000和0x8000100处的数据,然后使用命令cp.l将0x8000000处的数据拷贝到0x8000100处。最后使用命令md.l查看0x8000100处的数据有没有变化,检查拷贝是否成功。​

6、cmp命令

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

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

cmp命令同样可以以.b、.w、.l和.q来指定操作格式,addr1为第一段内存首地址,addr2为第二段内存首地址,count为要比较的长度。我们使用.l格式来比较0x8000000和0X8000100这两个地址数据是否相等,比较长度为0x10个内存块(16 * 4=64个字节),命令如下所示:​

cmp.l 8000000 8000100 10​

结果如下图所示:​

《DFZU2EG_4EV MPSoC之嵌入式Linux开发指南》第十一章 U-Boot使用实验_linux_27


图11.4.17 cmp命令比较结果​

从上图可以看出两段内存的数据相等。我们再随便挑两段内存比较一下,比如地址0x8002000和0x8003000,长度为0X10,比较结果如下图所示(命令cmp.l 8002000 8003000 10):​

《DFZU2EG_4EV MPSoC之嵌入式Linux开发指南》第十一章 U-Boot使用实验_环境变量_28


图11.4.18命令比较结果​

从上图可以看出,0x8002000处的数据和0x8003000处的数据就不一样。​

网络操作命令

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

开发板有两个网口:PS_ETH和PL_ETH,在使用uboot的网络功能之前先用网线将开发板的以太网PS_ETH或者PL_ETH接口和电脑或者路由器连接起来。建议开发板和主机PC都连接到同一个路由器上。​

连接好后,如何在uboot中选择正确的网口呢?​

uboot对网口phy芯片的操作有两个命令——mdio和mii。mdio命令可用于列出当前可用的phy芯片,以及读写phy芯片的寄存器,该命令的详细用法说明如下:​

《DFZU2EG_4EV MPSoC之嵌入式Linux开发指南》第十一章 U-Boot使用实验_linux_29


图11.4.19 mdio用法说明​

一般我们用mdio命令获取当前可用的phy芯片,也就是mdio总线。输入“mdio list”,结果如下图所示: ​

《DFZU2EG_4EV MPSoC之嵌入式Linux开发指南》第十一章 U-Boot使用实验_环境变量_30


图11.4.20获取当前可用的phy芯片​

可以看到,当前开发板有两个可用的phy芯片,eth0的phy地址为4,eth1的phy地址为7。phy地址为7的是开发板上的PS网口(PS_ETH),phy地址为4的是开发板上的PL网口(PL_ETH)。​

获取到phy地址及其对应的eth*后,就可以用mii命令进行切换,选择正确的网口。​

mii命令与mdio命令相似,也可用于列出当前可用的phy芯片,以及读写phy芯片的寄存器,该命令的详细用法说明如下:​

《DFZU2EG_4EV MPSoC之嵌入式Linux开发指南》第十一章 U-Boot使用实验_环境变量_31


图11.4.21 mii用法说明​

一般我们用mii命令对多网口进行网口切换。​

先用mii获取当前可用的phy芯片。输入“mii device”,结果如下图所示:​

《DFZU2EG_4EV MPSoC之嵌入式Linux开发指南》第十一章 U-Boot使用实验_开发板_32


图11.4.22获取当前可用的phy芯片​

显示有mii器件eth1和eth0,当前使用的器件为eth0。​

命令“mii info”可显示mii phy的信息,如下图所示:​

《DFZU2EG_4EV MPSoC之嵌入式Linux开发指南》第十一章 U-Boot使用实验_linux_33


图11.4.23 mii phy的信息​

显示“PHY 0x04”为“10baseT,HDX”,也就是地址为4的PHY芯片通信速度为10Mb,半双工,“PHY 0x00”也是如此,不过笔者好奇的是,哪来的地址为0的PHY芯片。从前面mdio list得到的只有phy地址为4和7的,没有0,不知道是uboot的bug还是笔者理解的不对。​

出现上面通信速度为10baseT的,先看看与开发板连接的路由器或者电脑是否也是千兆的,如果是的话,那应该是当前使用的phy芯片不对,需要切换到正确的phy芯片上。前面“mii device”显示当前使用的是eth0,既然不对我们将其切换到eth1,命令如下:​

mii device eth1​

mii info​

结果如下图所示:​

《DFZU2EG_4EV MPSoC之嵌入式Linux开发指南》第十一章 U-Boot使用实验_开发板_34


图11.4.24 切换到eth1​

显示“PHY 0x07”为“1000baseT,FDX”,也就是地址为7的PHY芯片通信速度为1000Mb,全双工。笔者当前使用的也的确是PHY地址为7的网口——PS_ETH。​

切换到正确的phy芯片之后,就可以进行下面的操作了。​

注:mdio和mii命令的读写phy寄存器功能在调试phy芯片时很有用,特别是在自己画板时使用的phy芯片不受uboot支持,或延时不对,导致链路不通时。不过现在uboot对市面上常用的phy芯片支持很好,哪怕用的是国产的phy芯片,也基本做到完美支持,当然了这也于国产phy芯片一般兼容于市面上常用的phy芯片有关,所以导致了mdio和mii命令现在用的不多,常见的用法也就是上面介绍的切换phy芯片。​

与网络相关的环境变量如下表所示:​

表11.4.1 网络相关环境变量​

环境变量

描述

ipaddr

开发板ip地址,可以不设置,使用dhcp命令来从路由器获取IP地址​

ethaddr

开发板的MAC地址,一定要设置​

gatewayip

网关地址​

netmask

子网掩码​

serverip

TFTP服务器IP地址,使用tftp相关命令要用到,用于调试代码​

这里重点说一下serverip,也就是TFTP服务器的IP地址,一般我们用Ubuntu主机作为TFTP服务器,所以也就是Ubuntu主机的IP地址。​

连接网线,开发板上电后uboot默认通过dhcp获取网络ip地址(与路由器连接时有效),若与电脑直连,可以在进入uboot命令行模式后通过以下命令手动设置:​

setenv ipaddr 192.168.2.123​

setenv ethaddr 00:0a:35:00:1e:53​

setenv gatewayip 192.168.2.1​

setenv netmask 255.255.255.0​

setenv serverip 192.168.2.134​

saveenv​

注意,连接到电脑的以太网接口需要同时设置电脑以太网适配器的Ipv4属性。另外网络地址环境变量的设置要根据自己的实际情况,确保Ubuntu主机和开发板的IP地址在同一个网段内,比如笔者现在的开发板和电脑都在192.168.2.0这个网段内,所以设置开发板的IP地址为192.168.2.123,笔者的Ubuntu主机的地址为192.168.2.134,因此serverip就是192.168.2.134。设置电脑的以太网和Ubuntu主机网络的方法可参考7.7.3小节。​

ethaddr为网络MAC地址,是一个48bit的地址,如果在同一个网段内有多个开发板的话一定要保证每个开发板的ethaddr是不同的,否则通信会有问题。设置好网络相关的环境变量以后就可以使用网络相关命令了。​

与路由器连接时需要设置serverip,也就是Ubuntu主机的IP地址(如笔者的为192.168.2.134):​

setenv serverip 192.168.2.134​

saveenv​

1、ping命令

开发板的网络能否使用,是否可以和服务器(Ubuntu主机)进行通信,通过ping命令就可以验证,直接ping服务器的IP地址即可,比如笔者的服务器IP地址为192.168.1.,命令如下:​

ping 192.168.2.134​

结果如下图所示:​

《DFZU2EG_4EV MPSoC之嵌入式Linux开发指南》第十一章 U-Boot使用实验_环境变量_35


图11.4.25命令​

从上图可以看出,192.168.2.134这个主机存在,说明ping成功,uboot的网络工作正常。​

注意:如果是通过网线直接将开发板和电脑连接,ping不通的情况,除了以上设置不正确外,还有可能是电脑的防火墙导致的。可以关闭防火墙或者允许文件和打印共享应用通过防火墙(针对Windows系统)。​

2、dhcp命令

dhcp用于从路由器获取IP地址,前提是开发板连接到路由器,如果开发板是和电脑直连的,那么dhcp命令就会失效。直接输入dhcp命令即可通过路由器获取到IP地址,如下图所示:​

《DFZU2EG_4EV MPSoC之嵌入式Linux开发指南》第十一章 U-Boot使用实验_环境变量_36


图11.4.26命令​

从上图可以看出,开发板通过dhcp获取到的IP地址为192.168.2.181,和我们手动设置的不同,这不影响使用,因为没有连接路由器,不参与局域网,所以手动设置的IP地址只在开发板和电脑之间有效。​

3、nfs命令

nfs也就是网络文件系统,通过nfs可以在计算机之间通过网络来分享资源,比如我们将linux镜像和设备树文件放到Ubuntu中,然后在uboot中使用nfs命令将Ubuntu中的linux镜像和设备树下载到开发板的DRAM中。这样做的目的是为了方便调试linux镜像和设备树,也就是网络调试,使用网络调试是Linux开发中最常用的调试方法。原因是嵌入式linux开发不像单片机开发,可以直接通过JLINK或STLink等仿真器将代码直接烧写到单片机内部的flash中,嵌入式Linux通常是烧写到SD卡、eMMC、QSPI Flash等外置flash中,但是嵌入式Linux开发也没有MDK、IAR这样的IDE,更没有烧写算法,因此不可能通过点击一个“download”按钮就将固件烧写到外部flash中。这个时候网络调试的优势就显现出来了,可以通过网络将编译好的linux镜像和设备树文件下载到DRAM中,然后就可以直接运行。​

我们一般使用uboot中的nfs命令将Ubuntu中的文件下载到开发板的DRAM中,在使用之前需要开启Ubuntu主机的NFS服务,并且要新建一个NFS使用的目录,以后所有要通过NFS访问的文件都需要放到这个NFS目录中。Ubuntu的NFS服务开启我们在4.4.1小节已经详细讲解过了,包括NFS文件目录的创建,如果忘记的话可以去查看一下该小节。笔者设置的/home/shang/workspace/nfs这个目录为笔者的NFS文件目录。uboot中的nfs命令格式如下所示:​

nfs [loadAddress] [[hostIPaddr:]bootfilename]​

loadAddress是要加载到的DRAM地址,[[hostIPaddr:]bootfilename]是要下载的文件地址。这里我们将当前Petalinux工程目录images/linux下的内核镜像文件Image复制到NFS目录下,比如笔者放到/home/shang/workspace/nfs这个目录下,完成后的NFS目录如下图所示:​

《DFZU2EG_4EV MPSoC之嵌入式Linux开发指南》第十一章 U-Boot使用实验_开发板_37


图11.4.27 NFS目录中的Image文件​

准备好以后就可以使用nfs命令来将Image下载到开发板DRAM的0x00200000地址处。在串口终端中输入如下命令:​

nfs 200000 192.168.2.134:/home/shang/workspace/nfs/Image​

命令中的“200000”表示Image加载到DRAM中的地址,“192.168.2.134:/home/shang/workspace/nfs/Image”表示Image在192.168.2.134这个主机中,路径为/home/shang/workspace/nfs/Image。下载过程如下图所示:​

《DFZU2EG_4EV MPSoC之嵌入式Linux开发指南》第十一章 U-Boot使用实验_linux_38


图11.4.28命令下载Image过程​

在上图中会以“#”提示下载过程。如果出现“ERROR: `serverip' not set”的错误,就设置serverip为Ubuntu主机的IP地址。笔者的Ubuntu主机的IP地址为192.168.2.134,因此使用命令“setenv serverip 192.168.2.134”设置serverip为192.168.2.134。下载完成以后会提示下载的数据大小,这里下载的18082304字节,而Image的大小就是18082304字节,如下图所示:​

《DFZU2EG_4EV MPSoC之嵌入式Linux开发指南》第十一章 U-Boot使用实验_开发板_39


图11.4.29大小​

下载完成以后查看0x00200000地址处的数据,使用命令md.b来查看前0x100个字节的数据(命令md.b 200000 100),如下图所示:​

《DFZU2EG_4EV MPSoC之嵌入式Linux开发指南》第十一章 U-Boot使用实验_开发板_40


图11.4.30下载的数据​

在Ubuntu虚拟机中,使用od命令或xxd命令来查看Image,检查一下前面的数据是否和上图中的一致,命令如下:​

od -tx1 -vN 0x100 Image​

或​

xxd -g 1 -l 0x100 Image​

结果如下图所示:​

《DFZU2EG_4EV MPSoC之嵌入式Linux开发指南》第十一章 U-Boot使用实验_linux_41


图11.4.31查看Image​

可以看出图11.4.30和图11.4.31的前0x100个字节的数据一致,说明nfs命令下载到的zImage是正确的。​

4、tftpboot命令

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

在Ubuntu虚拟机中,将Image镜像文件拷贝到TFTP服务器使用的tftpboot文件夹中。这一步我们在6.3.8节编译工程完成后Petalinux工具已经为我们做好了,从下图我们可以看到Image已经存在于/tftpboot目录下:​

《DFZU2EG_4EV MPSoC之嵌入式Linux开发指南》第十一章 U-Boot使用实验_linux_42


万事俱备,只剩验证了,uboot中的tftp命令格式如下:​

tftpboot [loadAddress] [[hostIPaddr:]bootfilename]​

看起来和nfs命令格式一样的,loadAddress是文件在DRAM中的存放地址,[[hostIPaddr:]bootfilename]是要从Ubuntu中下载的文件。但是和nfs命令的区别在于,tftpboot命令不需要输入文件在Ubuntu中的完整路径,只需要输入文件名即可。比如我们现在将tftpboot文件夹里面的Image文件下载到开发板DRAM的0x00000000地址处,命令如下:​

tftpboot 0 Image​

下载过程如下图所示:​

《DFZU2EG_4EV MPSoC之嵌入式Linux开发指南》第十一章 U-Boot使用实验_linux_43


图11.4.32命令下载过程​

从上图可以看出,Image下载成功了,网速为3 MiB/s,文件大小为18082304字节。同样的,可以使用md.b命令来查看前100个字节的数据是否和上图中的相等。有时候使用tftpboot命令从Ubuntu中下载文件的时候会出现如“TFTP error: 'Permission denied' (0)”这样的错误提示,提示没有权限,出现这个错误一般有两个原因:​

①、在Ubuntu中创建tftpboot目录的时候没有给予tftboot相应的权限。​

②、tftpboot目录中要下载的文件没有给予相应的权限。​

针对上述两个问题,使用命令“chmod 777 xxx”来给予权限,其中“xxx”就是要给予权限的文件或文件夹。有时候使用tftpboot命令会出现“Retry count exceeded; starting again”的提示,这是因为网络不稳定造成的,重新执行命令即可。​

好了,uboot中关于网络的命令就讲解到这里,我们最常用的就是ping、nfs和tftpboot这三个命令。使用ping命令来查看网络的连接状态,使用nfs和tftp命令来从Ubuntu主机中下载文件。​

eMMC和SD卡操作命令

uboot支持eMMC和SD卡,因此也要提供eMMC和SD卡的操作命令。一般认为eMMC和SD卡是同一个东西,所以没有特殊说明,本教程统一使用MMC来代指eMMC和SD卡。uboot中常用于操作MMC设备的命令为“mmc”。​

mmc是一系列的命令,其后可以跟不同的参数,输入“?mmc”即可查看mmc有关的命令,如下图所示:​

《DFZU2EG_4EV MPSoC之嵌入式Linux开发指南》第十一章 U-Boot使用实验_环境变量_44


图11.4.33 mmc命令​

从上图可以看出,mmc后面跟不同的参数可以实现不同的功能,部分命令如下表所示:​

表11.4.2命令​

命令

描述

mmc info

输出MMC设备信息​

mmc read

读取MMC中的数据​

mmc wirte

向MMC设备写入数据​

mmc erase

擦除MMC中的数据​

mmc rescan

重新扫描MMC设备​

mmcpart

列出MMC设备的分区​

mmc dev

切换MMC设备​

mmc list

列出当前所有有效的MMC设备​

mmc hwpartition

设置MMC设备的分区​

mmc setdsr

设置DSR寄存器的值​

1、mmc rescan命令

mmc rescan命令用于扫描当前开发板上所有的MMC设备,包括eMMC和SD卡,输入命令“mmc rescan”即可。​

2、mmc list命令

mmc list命令用于来查看当前开发板一共有几个MMC设备,输入“mmc list”,结果如下图所示:​

《DFZU2EG_4EV MPSoC之嵌入式Linux开发指南》第十一章 U-Boot使用实验_环境变量_45


图11.4.34扫描MMC设备​

可以看出当前开发板有两个MMC设备:mmc@ff160000: 0 (eMMC)和mmc@ff170000: 1 (SD),mmc@ff160000: 0 (eMMC)是eMMC,mmc@ff170000: 1 (SD)是SD卡。​

3、mmc info命令

mmc info命令用于输出当前选中的mmc info设备的信息,输入命令“mmc info”即可,如下图所示:​

《DFZU2EG_4EV MPSoC之嵌入式Linux开发指南》第十一章 U-Boot使用实验_环境变量_46


图11.4.35 mmc info命令​

从上图可以看出,当前选中的MMC设备是版本号为5.1,容量为7.3GiB的eMMC,速度为52MHz,使用4位宽的总线。还有一个与mmc info命令相同功能的命令:mmcinfo,“mmc”和“info”之间没有空格。默认会将SD卡设置为当前MMC设备。

4、mmc dev命令

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

mmc dev [dev] [part]​

[dev]用来设置要切换的MMC设备号,[part]是分区号。如果不写分区号的话默认为分区0。使用如下命令切换到eMMC: ​

mmc dev 1 //切换到SD卡,0为eMMC,1为SD卡​

结果如下图所示:​

《DFZU2EG_4EV MPSoC之嵌入式Linux开发指南》第十一章 U-Boot使用实验_开发板_47


图11.4.36切换到SD卡​

从上图可以看出,切换到eMMC成功,mmc1为当前的MMC设备,输入命令“mmc info”即可查看eMMC的信息,结果如下图所示:​

《DFZU2EG_4EV MPSoC之嵌入式Linux开发指南》第十一章 U-Boot使用实验_linux_48


图11.4.37信息​

从上图可以看出当前SD卡版本为 3.0,容量为 14.8GiB,速度为50000000Hz=50MHz,4 位宽的总线。​

5、mmc part命令

有时候SD卡或者eMMC会有多个分区,可以使用命令“mmc part”来查看其分区,比如查看SD卡的分区情况,输入如下命令:​

mmc dev 1 //切换到SD卡​

mmc part //查看SD卡分区​

结果如下图所示:​

《DFZU2EG_4EV MPSoC之嵌入式Linux开发指南》第十一章 U-Boot使用实验_环境变量_49


图11.4.38查看SD卡分区​

从上图中可以看出,此时SD卡有两个分区,扇区2048~196608为第一个分区,扇区198656~30916608为第二个分区。​

6、mmc read命令

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

mmc read addr blk# cnt​

addr是数据读取到DRAM中的地址,blk是要读取的块起始地址(十六进制),一个块是512字节,这里的块和扇区是一个意思,在MMC设备中我们通常说扇区,cnt是要读取的块数量(十六进制)。比如从SD卡的第2048(0x800)个块开始,读取16(0x10)个块的数据到DRAM的0x00000000地址处,命令如下:​

mmc dev 1 0 //切换到MMC分区0​

mmc read 00000000 800 10 //读取数据​

结果如下图所示:​

《DFZU2EG_4EV MPSoC之嵌入式Linux开发指南》第十一章 U-Boot使用实验_环境变量_50


图11.4.39 mmc read命令​

7、mmc write命令

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

mmc write addr blk# cnt​

addr是要写入MMC中的数据在DRAM中的起始地址,blk是要写入MMC的块起始地址(十六进制),cnt是要写入的块大小,一个块为512字节。注意千万不要写SD卡或者eMMC的前两个块(扇区),里面保存着分区表信息。​

8、mmc erase命令

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

mmc erase blk# cnt​

blk为要擦除的起始块,cnt是要擦除的数量。没事不要用mmc erase来擦除MMC设备。​

关于MMC设备相关的命令就讲解到这里,表中还有一些跟MMC设备操作有关的命令,但是很少用到,这里就不讲解了,感兴趣的可以上网查一下,或者在uboot中查看这些命令的使用方法。​

FAT格式文件系统操作命令

有时候需要在uboot中对SD卡或者eMMC中存储的文件进行操作,这时候就要用到文件操作命令,跟文件操作相关的命令有:fatinfo、fatls、fstype、fatload和fatwrite,但是这些文件操作命令只支持FAT格式的文件系统。​

1、fatinfo命令

fatinfo命令用于查询指定MMC指定分区的文件系统信息,格式如下:​

fatinfo <interface> [<dev[:part]>]​

interface表示接口,比如mmc,dev是查询的设备号,part是要查询的分区。比如我们要查询SD卡分区1的文件系统信息,命令如下:​

fatinfo mmc 1:1​

结果如下图所示:​

《DFZU2EG_4EV MPSoC之嵌入式Linux开发指南》第十一章 U-Boot使用实验_环境变量_51


图11.4.40卡分区1文件系统信息​

从上图可以看出,SD卡分区1的文件系统为FAT32格式的。​

2、fatls命令

fatls命令用于查询FAT格式设备的目录和文件信息,命令格式如下:​

fatls <interface> [<dev[:part]>] [directory]​

interface是要查询的接口,比如mmc,dev是要查询的设备号,part是要查询的分区,directory是要查询的目录。比如查询SD卡分区1中的所有的目录和文件,输入命令:​

fatls mmc 1:1​

结果如下图所示:​

《DFZU2EG_4EV MPSoC之嵌入式Linux开发指南》第十一章 U-Boot使用实验_开发板_52


图11.4.41 SD卡分区1文件查询​

从上图可以看出,SD卡的分区1中存放着2个文件:BOOT.BIN和image.ub,没有目录。其中BOOT.BIN文件是我们拷贝到SD卡的FAT32分区中的ZYNQ MPSoC启动文件。​

3、fstype命令

fstype用于查看MMC设备某个分区的文件系统格式,命令格式如下:​

fstype <interface> <dev>:<part>​

在6.3.10小节制作SD启动卡时我们将SD卡分成两个分区,我们来查看一下这两个分区的文件系统格式,输入命令:​

fstype mmc 1:1​

fstype mmc 1:2​

结果如下图所示:​

《DFZU2EG_4EV MPSoC之嵌入式Linux开发指南》第十一章 U-Boot使用实验_linux_53


图11.4.42命令​

从上图可以看出,分区1的格式为fat,分区1用于存放BOOT.BIN等启动镜像文件。分区2的格式为ext4,用于存放Linux的根文件系统。​

4、fatload命令

fatload命令用于将指定的文件读取到DRAM中,命令格式如下:​

fatload <interface> [<dev[:part]> [<addr> [<filename> [bytes [pos]]]]]​

interface为接口,比如mmc,dev是设备号,part是分区,addr是保存在DRAM中的起始地址,filename是要读取的文件名字。bytes表示读取多少字节的数据,如果bytes为0或者省略的话表示读取整个文件。pos是要读的文件相对于文件首地址的偏移,如果为0或者省略的话表示从文件首地址开始读取。我们将SD卡分区1中的BOOT.BIN文件读取到DRAM中的0X00000000地址处,命令如下:​

fatload mmc 1:1 00000000 BOOT.BIN​

操作过程如下图所示:​

《DFZU2EG_4EV MPSoC之嵌入式Linux开发指南》第十一章 U-Boot使用实验_环境变量_54


图11.4.43读取过程​

从上图可以看出在756ms内读取了8911864个字节的数据,速度为11.2MiB/s。​

5、fatrm命令

fatrm命令用于删除MMC中指定的文件,命令格式如下:​

fatrm <interface> [<dev[:part]>] <filename>​

interface为接口,比如mmc,dev是设备号,part是分区,filename是要删除的文件名字。​

我们将SD卡分区1中的image.ub文件删除,完成以后使用“fatls”命令查看一下SD卡分区1里面的文件,命令如下:​

fatrm mmc 1:1 image.ub​

fatls mmc 1:1​

操作过程如下图所示:​

《DFZU2EG_4EV MPSoC之嵌入式Linux开发指南》第十一章 U-Boot使用实验_linux_55


图11.4.44删除文件​

可以看到image.ub已删除。​

6、fatwrite命令

fatwirte命令用于将DRAM中的数据写入到MMC设备中,命令格式如下:​

fatwrite <interface> <dev[:part]> <addr> <filename> [<bytes> [<offset>]]​

interface为接口,比如mmc,dev是设备号,part是分区,addr是要写入的数据在DRAM中的起始地址,filename是写入的数据文件名字,bytes表示要写入多少字节的数据,offset表示写入到文件相对于文件首地址的偏移。我们可以通过fatwrite命令在uboot中更新linux镜像文件和设备树。​

我们以更新linux镜像文件image.ub为例,首先将Petalinux工程目录images/linux下的image.ub镜像文件拷贝到Ubuntu中的tftpboot目录下,这一步我们在6.3.8节编译工程完成后Petalinux工具已经为我们做好了,从下图我们可以看到image.ub镜像文件已经存在于/tftpboot目录下,如下图所示:​

《DFZU2EG_4EV MPSoC之嵌入式Linux开发指南》第十一章 U-Boot使用实验_环境变量_56


图11.4.45 tftpboot目录中image.ub镜像文件​

在串口终端中使用命令tftpboot将image.ub镜像文件下载到DRAM的0x00000000地址处,命令如下:​

tftpboot 00000000 image.ub​

下载过程如下图所示:​

《DFZU2EG_4EV MPSoC之嵌入式Linux开发指南》第十一章 U-Boot使用实验_linux_57


图11.4.46 image.ub下载过程​

image.ub大小为17976928 (0x1124e60)个字节,接下来使用命令fatwrite将其写入到SD卡的分区1中,文件名字为image.ub,命令如下:​

fatwrite mmc 1:1 00000000 image.ub 1124e60​

结果如下图所示:​

《DFZU2EG_4EV MPSoC之嵌入式Linux开发指南》第十一章 U-Boot使用实验_linux_58


图11.4.47 将image.ub烧写到SD卡分区1中​

完成以后使用“fatls”命令(命令fatls mmc 1:1)查看一下SD卡分区1里面的文件,结果如下图所示:​

《DFZU2EG_4EV MPSoC之嵌入式Linux开发指南》第十一章 U-Boot使用实验_linux_59


图11.4.48卡分区1里面的文件​

EXT格式文件系统操作命令

uboot有ext2和ext4这两种格式的文件系统的操作命令,常用的就五个命令,分别为:ext2load、ext2ls、ext4load、ext4ls和ext4write。这些命令的含义和使用与fatload、fatls和fatwrit一样,只是ext2和ext4都是针对ext文件系统的。比如ext4ls命令,SD卡的分区2就是ext4格式的,使用ext4ls就可以查询SD卡的分区2中的文件和目录,输入命令:​

ext4ls mmc 1:2​

结果如下图所示:​

《DFZU2EG_4EV MPSoC之嵌入式Linux开发指南》第十一章 U-Boot使用实验_linux_60


图11.4.49命令​

关于ext格式文件系统其他命令的操作参考11.4.6小节的即可,这里就不讲解了。​

系统引导命令

uboot的本质工作是引导操作系统如Linux,所以uboot肯定有相关的引导(boot)命令来启动操作系统。常用的跟系统引导有关的命令有:boot、bootm和booti(用于启动Image镜像文件,常见于64位ARM平台,如ZYNQ MPSoC系列)、bootz(用于启动压缩的zImage镜像文件,多用于32位ARM平台,如ZYNQ-7000系列)。​

要启动Linux,需要先将Linux镜像文件拷贝到DRAM中,如果使用到设备树的话也需要将设备树拷贝到DRAM中。可以从SD卡中将Linux镜像和设备树文件加载到DRAM,也可以通过nfs或者tftp协议将Linux镜像文件和设备树文件下载到DRAM中。无论用哪种方法,只要能将Linux镜像和设备树文件存到DRAM中就行,然后使用bootm命令来启动。​

一般更多的是通过tftp协议从网络获取,这样调试内核和设备树时极其方便。需要注意的是通过tftp协议从网络获取时需要先设置serverip变量值为内核和设备树文件所在的Ubuntu主机的IP地址,如何设置见11.4.4节的网络操作命令。另外使用tftp协议时需要将对应文件拷贝到Ubuntu主机的tftp服务器存储文件夹下,如我们在4.3节Ubuntu系统搭建tftp服务器中的/tftpboot目录,这一步通常我们在编译Petalinux工程的时候Petalinux工具已经帮我们做好了。如果/tftpboot目录下没有对应文件,可以将Petalinux工程所在目录的image/linux目录下对应文件拷贝到/tftpboot目录中。下面我们学习如何通过网络启动Linux。​

1、bootm命令

bootm命令用于启动在内存中的用mkimage工具处理过的内核映象。由于zynq使用image.ub镜像文件,而image.ub镜像文件属于U-Boot fitImage(参考13.8节image.ub的来源),里面通常包括linux内核和设备树,所以可以将image.ub镜像文件写到DRAM中,然后使用bootm命令来启动。启动Linux内核的命令如下:​

bootm addr​

addr是image.ub镜像在DRAM中的首地址。​

现在我们使用tftp网络协议来启动Linux系统。image.ub文件可以在/tftpboot文件夹找到,如下图所示:​

《DFZU2EG_4EV MPSoC之嵌入式Linux开发指南》第十一章 U-Boot使用实验_环境变量_61


图11.4.50目录中image.ub镜像文件​

如果没有该文件,可以将Petalinux工程所在目录的image/linux目录下对应文件拷贝到/tftpboot文件夹。万事俱备后我们将image.ub下载到DRAM的0x10000000地址处,然后使用命令bootm启动,命令如下:​

tftpboot 10000000 image.ub​

bootm 10000000​

命令运行结果如下图所示:​

《DFZU2EG_4EV MPSoC之嵌入式Linux开发指南》第十一章 U-Boot使用实验_开发板_62


图11.4.51 通过tftp协议启动Linux系统镜像​

上图就是我们通过tftpboot和bootm命令来从网络启动Linux系统。其实这两步命令可以简化为一步命令,启动uboot后(默认已设置好serverip变量),使用“run netboot”命令即可,如下图所示:​

《DFZU2EG_4EV MPSoC之嵌入式Linux开发指南》第十一章 U-Boot使用实验_环境变量_63


图11.4.52 使用“run netboot”命令启动linux​

从上图可以看到“run netboot”命令运行的结果与我们在此之前运行的两步命令结果一样,只是更方便了些,这是因为Xilinx将之前分开的两步命令写到了netboot变量中,如下图所示:​

《DFZU2EG_4EV MPSoC之嵌入式Linux开发指南》第十一章 U-Boot使用实验_linux_64


图11.4.53变量​

所以后面我们调试内核的时候直接使用“run netboot”命令即可,方便快捷。​

2、booti命令

booti和bootm功能类似,只是booti命令用于启动Image镜像文件,zynq使用的不多,了解即可。booti命令格式如下:​

booti [addr [initrd[:size]] [fdt]]​

命令booti有三个参数,addr是Linux镜像文件在DRAM中的位置,initrd是initrd文件在DRAM中的地址,如果不使用initrd的话使用‘-’代替即可,fdt就是设备树文件在DRAM中的地址。可以在/tftpboot目录找到Image和system.dtb文件,如下图所示:​

《DFZU2EG_4EV MPSoC之嵌入式Linux开发指南》第十一章 U-Boot使用实验_linux_65


图11.4.54文件夹​

使用tftpboot命令将Image下载到DRAM的0x00200000地址处,然后将设备树system.dtb下载到DRAM中的0x00100000地址处,最后使用命令booti启动,命令如下:​

tftpboot 0x00200000 Image​

tftpboot 0x00100000 system.dtb​

booti 0x00200000 - 0x00100000​

命令运行结果如下图所示:​

《DFZU2EG_4EV MPSoC之嵌入式Linux开发指南》第十一章 U-Boot使用实验_环境变量_66


图11.4.55通过网络启动Linux​

上图就是我们通过tftpboot和booti命令来从网络启动Linux系统。如果我们要从SD中启动Linux系统的话只需要使用命令fatload将Image和system.dtb从SD卡的分区1中拷贝到DRAM中,然后使用命令booti启动即可,bootm同理。​

3、boot命令

boot命令也是用来启动Linux系统的,只是boot会读取环境变量bootcmd来启动Linux系统,bootcmd是一个很重要的环境变量!其名字分为“boot”和“cmd”,也就是“引导”和“命令”,说明这个环境变量保存着引导命令,其实就是启动的命令集合,具体的引导命令内容是可以修改的。比如我们要想使用tftpboot命令从网络启动Linux那么就可以设置bootcmd为“tftpboot 10000000 image.ub;bootm”,然后使用saveenv将bootcmd保存起来。然后直接输入boot命令即可从网络启动Linux系统,命令如下:​

setenv bootcmd 'tftpboot 10000000 image.ub;bootm'​

boot​

运行结果如下图所示:​

《DFZU2EG_4EV MPSoC之嵌入式Linux开发指南》第十一章 U-Boot使用实验_环境变量_67


图11.4.56设置bootcmd从网络启动Linux​

前面说过uboot倒计时结束以后就会启动Linux系统,其实就是执行的bootcmd中的启动命令。​

其他常用命令

uboot中还有其他一些常用的命令,比如reset、run和mtest等。​

1、reset命令

reset命令顾名思义就是复位,输入“reset”即可复位重启,如下图所示:​

《DFZU2EG_4EV MPSoC之嵌入式Linux开发指南》第十一章 U-Boot使用实验_linux_68


图11.4.57命令运行结果​

2、run命令

run命令用于运行环境变量中定义的命令,比如可以通过“run bootcmd”来运行bootcmd中的启动命令。我们在讲解bootm命令时就使用过“run netboot”命令以使用tftp网络协议下载linux镜像并启动。​

  1. mtest命令

mtest命令是一个简单的内存读写测试命令,可以用来测试自己开发板上的DDR。​

注:实测Petalinux 2019.2版本中的uboot该命令有bug,此处就不讲解该命令的用法了。如果开发板能启动进入linux系统,就说明DDR是OK的。

至此,uboot常用的命令就讲解完了,如果要使用uboot的其他命令,可以查看uboot中的帮助信息,或者上网查询一下相应的资料。​



标签:MPSoC,uboot,11.4,DFZU2EG,Boot,如下,命令,所示,mmc
From: https://blog.51cto.com/u_15046463/6005765

相关文章