【正点原子FPGA连载】第十一章U-Boot使用实验 摘自【正点原子】DFZU2EG

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

1实验平台正点原子MPSoC开发板
2平台购买地址https://detail.tmall.com/item.htm?id=692450874670
3全套实验源码+手册+视频下载地址 http://www.openedv.com/thread-340252-1-1.html

第十一章U-Boot使用实验

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

11.1U-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 Loaderuboot是一个遵循GPL协议的开源软件。uboot是一个裸机代码可以看作是一个裸机综合项目。现在的uboot已经支持液晶屏、网络、USB等高级功能。uboot官网地址http://www.denx.de/wiki/U-Boot/如下图所示
在这里插入图片描述

图 11.1.1 uboot官网
我们可以在uboot官网下载uboot源码点击上图中左侧Topics中的“Source Code”打开如下图所示界面
在这里插入图片描述

图 11.1.2 uboot源码界面
点击上图中的“HTTPS”进入其服务器即可看到uboot源码如下图所示
在这里插入图片描述

图 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下载界面如下图所示
在这里插入图片描述

图 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源码就可以了。
11.2Petalinux配置和编译U-Boot
进入到第六章Petalinux设计流程实战中创建的petalinux工程目录下然后按照6.3.2小节设置Petalinux环境变量。
uboot的功能有很多虽然默认的功能一般而言已经够用了但在项目开发过程中可能会使用到uboot平时不常用的功能这时就需要配置uboot以使能相应功能。在Petalinux中配置uboot的方法很简单在搭建好的petalinux工程目录下执行如下命令即可进入uboot图形配置界面
petalinux-config -c u-boot
执行后会在终端中打开另一个配置uboot的标签页如下图所示
在这里插入图片描述

图 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的源码如下图所示
在这里插入图片描述

图 11.2.2 uboot源码
现在编译uboot。编译uboot的命令很简单执行如下命令即可编译uboot
petalinux-build -c u-boot
也可以只使用“petalinux-build”命令用来编译fsbl、uboot、设备树、Linux内核和根文件系统等如果是重新创建Petalinux工程推荐使用“petalinux-build”命令不带“-c u-boot”参数。
命令执行完以后uboot也就编译成功了如下图所示
在这里插入图片描述

图 11.2.3 编译U-Boot
注有一个警告Petalinux版本的问题不影响使用。
编译完成以后会在当前Petalinux工程目录的images/linux目录下生成u-boot.elf文件如下图所示
在这里插入图片描述

图 11.2.4 u-boot镜像文件
11.3U-Boot烧写与启动
uboot编译好以后就可以烧写到板子上使用了。我们将u-boot.elf文件打包到ZYNQ MPSoC的启动文件BOOT.BIN中在终端中输入如下命令
petalinux-package --boot --fsbl --fpga --u-boot --force
执行结果如下图所示
在这里插入图片描述

图 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的命令行模式如下图所示
在这里插入图片描述

图 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行从SPIQSPI加载环境变量检测到开发板使用的QSPI为n25q256a大小为32MiB。
第21~23是标准输入、标准输出和标准错误所使用的终端这里都使用串口(serial)作为终端。
第26~30行是网口信息提示我们当前有两个网口eth0和eth1其中eth0的phy地址为4eth1的phy地址为7。
第31行是倒计时提示默认倒计时4秒倒计时结束之前按下回车键就会进入Uboot命令行模式。如果在倒计时结束以后没有按下回车键那么Linux内核就会启动Linux内核一旦启动uboot就会寿终正寝。这个值与我们在11.2节介绍的配置项“(4) delay in seconds before automatically booting”有关。
uboot是来干活的我们现在已经进入uboot的命令行模式了进入命令行模式以后就可以给uboot发号施令了。当然了不能随便发号施令得看看uboot支持哪些命令然后使用这些uboot所支持的命令来做一些工作。下一节讲解uboot命令的使用。
11.4U-Boot命令的使用
进入uboot的命令行模式以后输入“help”或者“”然后按下回车即可查看当前uboot所支持的命令如图 11.4.1所示。该图只是uboot的一部分命令并不是uboot所支持的所有命令。前面说过uboot是可配置的需要什么命令就使能什么命令所以该图中的命令是正点原子提供的uboot中使能的命令uboot支持的命令还有很多而且也可以在uboot中自定义命令。这些命令后面都跟有命令说明用于描述此命令的作用但是命令具体怎么用呢我们输入“help(或?) 命令名”就可以获取可用命令的完整列表以及查看对应命令的详细用法。
在这里插入图片描述

图 11.4.1 uboot命令列表
以“bootm”这个命令为例我们输入如下命令即可查看“bootm”这个命令的用法
? bootm 或 help bootm
结果如下图所示
在这里插入图片描述

图 11.4.2 bootm命令使用说明
上图详细的列出了“bootm”这个命令的用法其它的命令也可以使用此方法查询具体的使用方法。接下来我们学习一下一些常用的uboot命令。
11.4.1信息查询命令
常用的和信息查询有关的命令有3个bdinfo、printenv和version。先来看一下bdinfo命令此命令用于查看板子信息直接输入“bdinfo”即可结果如下图所示
在这里插入图片描述

图 11.4.3 bdinfo命令
从上图中可以得出DRAM的起始地址和大小UART波特率、sp(堆栈指针)起始地址等信息。
命令“printenv”用于输出环境变量信息uboot也支持TAB键自动补全功能输入“print”然后按下TAB键就会自动补全命令直接输入“print”也可以。输入“print”然后按下回车键环境变量如下图所示
在这里插入图片描述

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

图 11.4.5 version命令结果
从上图可以看出当前uboot版本号为2019.012021年11月3日编译的编译器为aarch64-xilinx-linux-gcc等信息。
11.4.2环境变量操作命令
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
上述命令执行过程如下图所示
在这里插入图片描述

图 11.4.6环境变量修改
在上图中当我们使用命令saveenv保存修改后的环境变量的话会有保存过程提示信息根据提示可以看出环境变量保存到了SPI flash中也就是开发板上的QSPI Flah–w25q256中。
修改bootdelay以后重启开发板uboot就是变为5秒倒计时如下图所示
在这里插入图片描述

图 11.4.7 5秒倒计时
2、新建环境变量
命令setenv也可以用于新建命令用法和修改环境变量一样比如我们新建一个环境变量authorauthor的值为“alientek”那么就可以使用如下命令
setenv author alientek
saveenv
新建命令author完成以后重启uboot然后使用命令printenv查看当前环境变量如下图所示
在这里插入图片描述

图 11.4.8环境变量
从上图可以看到新建的环境变量author其值为alientek。
3、删除环境变量
既然可以新建环境变量那么就可以删除环境变量删除环境变量也是使用命令setenv要删除一个环境变量只要给这个环境变量赋空值即可比如我们删除掉上面新建的author这个环境变量命令如下
setenv author
saveenv
上面命令中通过setenv给author赋空值也就是什么都不写来删除环境变量author。重启uboot就会发现环境变量author没有了。
11.4.3内存操作命令
内存操作命令就是用于直接对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也就是202=40个字节如果显示格式为.l的话就表示20个long也就是204=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也就是162=32个字节第二个命令以.l格式显示长度为0x10也就是164=64个字节最后一个命令以.q格式显示长度也是0x10也就是16*8=128个字节。这四个命令的执行结果如下图所示
在这里插入图片描述

图 11.4.9 md命令使用示例
2、nm命令
nm命令用于修改指定地址的内存值命令格式如下
nm [.b, .w, .l .q] address
nm命令同样可以以.b、.w、.l和.q来指定操作格式比如现在以.l格式修改0x8000000地址的数据为0x12345678。输入命令
nm.l 8000000
输入上述命令以后如下图所示
在这里插入图片描述

图 11.4.10 nm命令
在上图中8000000表示现在要修改的内存地址1400000a表示地址0x8000000现在的数据后面就可以输入要修改后的数据0x12345678输入完成以后按下回车然后再输入‘q’即可退出如下图所示
在这里插入图片描述

图 11.4.11修改内存数据
修改完成以后再使用命令md来查看一下有没有修改成功命令md.l 8000000 1如下图所示
在这里插入图片描述

图 11.4.12查看修改后的值
从上图可以看出此时地址0X8000000的值变为了0x12345678。
3、mm命令
mm命令也是修改指定地址内存值的使用mm修改内存值的时候地址会自增而使用命令nm的话地址不会自增。比如以.l格式修改从地址0x8000000开始的连续3个内存块(3*4=12个字节)的数据为0x05050505操作如下图所示命令mm.l 8000000
在这里插入图片描述

图 11.4.13命令mm
从上图可以看出修改了地址0X8000000、0X8000004和0X8000008的内容为0x05050505。使用命令md查看修改后的值命令md.l 8000000 3结果如下图所示
在这里插入图片描述

图 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
结果如下图所示
在这里插入图片描述

图 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处的内容
结果如下图所示
在这里插入图片描述

图 11.4.16 cp命令操作结果
在上图中先使用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
结果如下图所示
在这里插入图片描述

图 11.4.17 cmp命令比较结果
从上图可以看出两段内存的数据相等。我们再随便挑两段内存比较一下比如地址0x8002000和0x8003000长度为0X10比较结果如下图所示命令cmp.l 8002000 8003000 10
在这里插入图片描述

图 11.4.18 cmp命令比较结果
从上图可以看出0x8002000处的数据和0x8003000处的数据就不一样。
11.4.4网络操作命令
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芯片的寄存器该命令的详细用法说明如下
在这里插入图片描述

图 11.4.19 mdio用法说明
一般我们用mdio命令获取当前可用的phy芯片也就是mdio总线。输入“mdio list”结果如下图所示
在这里插入图片描述

图 11.4.20获取当前可用的phy芯片
可以看到当前开发板有两个可用的phy芯片eth0的phy地址为4eth1的phy地址为7。phy地址为7的是开发板上的PS网口PS_ETHphy地址为4的是开发板上的PL网口PL_ETH。
获取到phy地址及其对应的eth*后就可以用mii命令进行切换选择正确的网口。
mii命令与mdio命令相似也可用于列出当前可用的phy芯片以及读写phy芯片的寄存器该命令的详细用法说明如下
在这里插入图片描述

图 11.4.21 mii用法说明
一般我们用mii命令对多网口进行网口切换。
先用mii获取当前可用的phy芯片。输入“mii device”结果如下图所示
在这里插入图片描述

图 11.4.22获取当前可用的phy芯片
显示有mii器件eth1和eth0当前使用的器件为eth0。
命令“mii info”可显示mii phy的信息如下图所示
在这里插入图片描述

图 11.4.23 mii phy的信息
显示“PHY 0x04”为“10baseTHDX”也就是地址为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
结果如下图所示
在这里插入图片描述

图 11.4.24 切换到eth1
显示“PHY 0x07”为“1000baseTFDX”也就是地址为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
结果如下图所示
在这里插入图片描述

图 11.4.25 ping命令
从上图可以看出192.168.2.134这个主机存在说明ping成功uboot的网络工作正常。
注意如果是通过网线直接将开发板和电脑连接ping不通的情况除了以上设置不正确外还有可能是电脑的防火墙导致的。可以关闭防火墙或者允许文件和打印共享应用通过防火墙针对Windows系统。
2、dhcp命令
dhcp用于从路由器获取IP地址前提是开发板连接到路由器如果开发板是和电脑直连的那么dhcp命令就会失效。直接输入dhcp命令即可通过路由器获取到IP地址如下图所示
在这里插入图片描述

图 11.4.26 dhcp命令
从上图可以看出开发板通过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目录如下图所示
在这里插入图片描述

图 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。下载过程如下图所示
在这里插入图片描述

图 11.4.28 nfs命令下载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字节如下图所示
在这里插入图片描述

图 11.4.29 zImage大小
下载完成以后查看0x00200000地址处的数据使用命令md.b来查看前0x100个字节的数据命令md.b 200000 100如下图所示
在这里插入图片描述

图 11.4.30下载的数据
在Ubuntu虚拟机中使用od命令或xxd命令来查看Image检查一下前面的数据是否和上图中的一致命令如下
od -tx1 -vN 0x100 Image

xxd -g 1 -l 0x100 Image
结果如下图所示
在这里插入图片描述

图 11.4.31 winhex查看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目录下
在这里插入图片描述

万事俱备只剩验证了uboot中的tftp命令格式如下
tftpboot [loadAddress] [[hostIPaddr:]bootfilename]
看起来和nfs命令格式一样的loadAddress是文件在DRAM中的存放地址[[hostIPaddr:]bootfilename]是要从Ubuntu中下载的文件。但是和nfs命令的区别在于tftpboot命令不需要输入文件在Ubuntu中的完整路径只需要输入文件名即可。比如我们现在将tftpboot文件夹里面的Image文件下载到开发板DRAM的0x00000000地址处命令如下
tftpboot 0 Image
下载过程如下图所示
在这里插入图片描述

图 11.4.32 tftp命令下载过程
从上图可以看出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主机中下载文件。
11.4.5eMMC和SD卡操作命令
uboot支持eMMC和SD卡因此也要提供eMMC和SD卡的操作命令。一般认为eMMC和SD卡是同一个东西所以没有特殊说明本教程统一使用MMC来代指eMMC和SD卡。uboot中常用于操作MMC设备的命令为“mmc”。
mmc是一系列的命令其后可以跟不同的参数输入“mmc”即可查看mmc有关的命令如下图所示
在这里插入图片描述

图 11.4.33 mmc命令
从上图可以看出mmc后面跟不同的参数可以实现不同的功能部分命令如下表所示
表 11.4.2 mmc命令
命令 描述
mmc info 输出MMC设备信息
mmc read 读取MMC中的数据
mmc wirte 向MMC设备写入数据
mmc erase 擦除MMC中的数据
mmc rescan 重新扫描MMC设备
mmc part 列出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”结果如下图所示
在这里插入图片描述

图 11.4.34扫描MMC设备
可以看出当前开发板有两个MMC设备mmc@ff160000: 0 (eMMC)和mmc@ff170000: 1 (SD)mmc@ff160000: 0 (eMMC)是eMMCmmc@ff170000: 1 (SD)是SD卡。
3、mmc info命令
mmc info命令用于输出当前选中的mmc info设备的信息输入命令“mmc info”即可如下图所示
在这里插入图片描述

图 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为eMMC1为SD卡
结果如下图所示
在这里插入图片描述

图 11.4.36切换到SD卡
从上图可以看出切换到eMMC成功mmc1为当前的MMC设备输入命令“mmc info”即可查看eMMC的信息结果如下图所示
在这里插入图片描述

图 11.4.37 eMMC信息
从上图可以看出当前SD卡版本为 3.0容量为 14.8GiB速度为50000000Hz=50MHz4 位宽的总线。
5、mmc part命令
有时候SD卡或者eMMC会有多个分区可以使用命令“mmc part”来查看其分区比如查看SD卡的分区情况输入如下命令
mmc dev 1 //切换到SD卡
mmc part //查看SD卡分区
结果如下图所示
在这里插入图片描述

图 11.4.38查看SD卡分区
从上图中可以看出此时SD卡有两个分区扇区2048196608为第一个分区扇区19865630916608为第二个分区。
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 //读取数据
结果如下图所示
在这里插入图片描述

图 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设备相关的命令就讲解到这里表 11.4.5.1中还有一些跟MMC设备操作有关的命令但是很少用到这里就不讲解了感兴趣的可以上网查一下或者在uboot中查看这些命令的使用方法。
11.4.6FAT格式文件系统操作命令
有时候需要在uboot中对SD卡或者eMMC中存储的文件进行操作这时候就要用到文件操作命令跟文件操作相关的命令有fatinfo、fatls、fstype、fatload和fatwrite但是这些文件操作命令只支持FAT格式的文件系统。
1、fatinfo命令
fatinfo命令用于查询指定MMC指定分区的文件系统信息格式如下
fatinfo [<dev[:part]>]
interface表示接口比如mmcdev是查询的设备号part是要查询的分区。比如我们要查询SD卡分区1的文件系统信息命令如下
fatinfo mmc 1:1
结果如下图所示
在这里插入图片描述

图 11.4.40 SD卡分区1文件系统信息
从上图可以看出SD卡分区1的文件系统为FAT32格式的。
2、fatls命令
fatls命令用于查询FAT格式设备的目录和文件信息命令格式如下
fatls [<dev[:part]>] [directory]
interface是要查询的接口比如mmcdev是要查询的设备号part是要查询的分区directory是要查询的目录。比如查询SD卡分区1中的所有的目录和文件输入命令
fatls mmc 1:1
结果如下图所示
在这里插入图片描述

图 11.4.41 SD卡分区1文件查询
从上图可以看出SD卡的分区1中存放着2个文件BOOT.BIN和image.ub没有目录。其中BOOT.BIN文件是我们拷贝到SD卡的FAT32分区中的ZYNQ MPSoC启动文件。
3、fstype命令
fstype用于查看MMC设备某个分区的文件系统格式命令格式如下
fstype :
在6.3.10小节制作SD启动卡时我们将SD卡分成两个分区我们来查看一下这两个分区的文件系统格式输入命令
fstype mmc 1:1
fstype mmc 1:2
结果如下图所示
在这里插入图片描述

图 11.4.42 fstype命令
从上图可以看出分区1的格式为fat分区1用于存放BOOT.BIN等启动镜像文件。分区2的格式为ext4用于存放Linux的根文件系统。
4、fatload命令
fatload命令用于将指定的文件读取到DRAM中命令格式如下
fatload [<dev[:part]> [ [ [bytes [pos]]]]]
interface为接口比如mmcdev是设备号part是分区addr是保存在DRAM中的起始地址filename是要读取的文件名字。bytes表示读取多少字节的数据如果bytes为0或者省略的话表示读取整个文件。pos是要读的文件相对于文件首地址的偏移如果为0或者省略的话表示从文件首地址开始读取。我们将SD卡分区1中的BOOT.BIN文件读取到DRAM中的0X00000000地址处命令如下
fatload mmc 1:1 00000000 BOOT.BIN
操作过程如下图所示
在这里插入图片描述

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

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

“【正点原子FPGA连载】第十一章U-Boot使用实验 摘自【正点原子】DFZU2EG” 的相关文章