LV01-02-IMX6ULL-ALPHA开发板体验-05-从tftp和nfs启动系统

本文主要是体验正点原子I.MX6U-ALPHA开发板出厂系统——从TFTP加载linux镜像和设备树,从NFS加载根文件系统的相关笔记,若笔记中有错误或者不合适的地方,欢迎批评指正😃。

点击查看使用工具及版本
Windows版本 windows11
Ubuntu版本 Ubuntu16.04的64位版本
VMware® Workstation 16 Pro 16.2.3 build-19376536
终端软件 MobaXterm(Professional Edition v23.0 Build 5042 (license))
Linux开发板 正点原子 i.MX6ULL Linux 阿尔法开发板
uboot NXP官方提供的uboot,NXP提供的版本为uboot-imx-rel_imx_4.1.15_2.1.0_ga(使用的uboot版本为U-Boot 2016.03)
linux内核 linux-4.15(NXP官方提供)
Win32DiskImager Win32DiskImager v1.0
点击查看本文参考资料
分类 网址 说明
官方网站 https://www.arm.com/ ARM官方网站,在这里我们可以找到Cotex-Mx以及ARMVx的一些文档
https://www.nxp.com.cn/ NXP官方网站
https://www.nxpic.org.cn/NXP 官方社区
https://u-boot.readthedocs.io/en/latest/u-boot官网
https://www.kernel.org/linux内核官网
点击查看相关文件下载
分类 网址 说明
NXP https://github.com/nxp-imx NXP imx开发资源GitHub组织,里边会有u-boot和linux内核的仓库
https://elixir.bootlin.com/linux/latest/source 在线阅读linux kernel源码
nxp-imx/linux-imx/releases/tag/rel_imx_4.1.15_2.1.0_ga NXP linux内核仓库tags中的rel_imx_4.1.15_2.1.0_ga
nxp-imx/uboot-imx/releases/tag/rel_imx_4.1.15_2.1.0_ga NXP u-boot仓库tags中的rel_imx_4.1.15_2.1.0_ga
I.MX6ULL i.MX 6ULL Applications Processors for Industrial Products I.MX6ULL 芯片手册(datasheet,可以在线查看)
i.MX 6ULL Applications ProcessorReference Manual I.MX6ULL 参考手册(下载后才能查看,需要登录NXP官网)

一、概述

前面我们已经可以将正点原子出厂的系统烧写到SD卡或者EMMC中了,但是在开发过程中我们是要不断修改镜像和设备树以及根文件系统的,这样调试的话每次都要重新烧写,就格外的麻烦,其实uboot是支持从tftp下载设备树和linux镜像的,然后支持从nfs挂载根文件系统,这一节我们就来试一试吧。由于还未开始学习uboot和linux内核、根文件系统等的移植,所以先使用正点原子出厂系统,先熟悉操作流程。注意本节使用的ubuntu版本是22.04。

二、设备配置

首先在正点原子出厂系统下,根据《LV02-03-网络环境-01-网络开发环境搭建》、《LV02-03-网络环境-02-TFTP环境搭建》和《LV02-03-网络环境-03-NFS环境搭建》这三节的笔记搭建好网络环境。

  • ubuntu的IP地址如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
hk@ubuntu2204:~$ ifconfig
ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.19.131 netmask 255.255.255.0 broadcast 192.168.19.255
inet6 fe80::7bef:a0d9:48df:1aed prefixlen 64 scopeid 0x20<link>
ether 00:0c:29:42:15:e2 txqueuelen 1000 (以太网)
RX packets 535 bytes 302111 (302.1 KB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 368 bytes 44892 (44.8 KB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

ens37: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.10.101 netmask 255.255.255.0 broadcast 192.168.10.255
inet6 fe80::cd90:fd60:2b69:629c prefixlen 64 scopeid 0x20<link>
ether 00:0c:29:42:15:ec txqueuelen 1000 (以太网)
RX packets 473 bytes 45801 (45.8 KB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 227 bytes 19227 (19.2 KB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
inet6 ::1 prefixlen 128 scopeid 0x10<host>
loop txqueuelen 1000 (本地环回)
RX packets 418 bytes 44679 (44.6 KB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 418 bytes 44679 (44.6 KB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
  • windows以太网口的信息如下
image-20230731182813253
1
2
3
IPv4地址    192.168.10.100
IPv4子网掩码 255.255.255.0
IPv4默认网关 192.168.10.1

三、文件准备

我们需要准备zImage、dtb和根文件系统,我们从正点原子出厂开发工具中拷贝出来,

image-20230731182205914

将对应的文件拷贝到虚拟机中的ubuntu中,分别放在ubuntu的指定目录下,如下图:

image-20230731182025523

四、uboot下的操作

我这里是用了后边自己移植的uboot,并且使用的是从SD卡启动,所以有一些打印信息可能跟正点原子出厂的uboot有些不同。需要注意的是我们使用的uboot要想从网络下载文件,一定是要保证网口驱动移植过,在uboot下可以正常ping通ubuntu的。

1. 进入uboot

开机时会有如下提示:

image-20230731182402754

在读秒结束前,按下任意按键,这里就会停在uboot界面啦。

2. 网络环境变量设置

由于我们使用的是正点原子出厂的uboot,所以网络的驱动是移植好的,我们直接进行一下配置:

1
2
3
4
5
6
7
=>setenv ipaddr 192.168.10.105     # 开发板 IP 地址
=>setenv ethaddr b8:ae:1d:01:00:00 # 开发板网卡 MAC 地址
=>setenv gatewayip 192.168.10.1 # 开发板默认网关
=>setenv netmask 255.255.255.0 # 开发板子网掩码
=>setenv serverip 192.168.10.101 # 服务器地址,也就是 Ubuntu 地址
=>saveenv # 保存环境变量
=>print ipaddr ethaddr gatewayip netmask serverip

配置完我们可以打印看一下这些环境变量的值对不对:

image-20230731182659315

然后我们ping一下ubuntu和windows:

1
2
=>ping 192.168.10.100  # windows
=>ping 192.168.10.101 # ubuntu22.04
image-20230731183629137

这样表示可以正常通信,这里可能会有几个个问题:

(1)那就是ubuntu若是使用的双网卡的话,它可能会ping失败,由于我之前是没有找到怎么放开发板默认与ubuntu的桥接网卡通信,所以这里我就直接把NAT网卡关掉了,后边找到方法了再补充。

(2)和windows进行ping的时候也有时候ping不通,后来发现可能是因为我使用的是扩展坞扩展的网口的原因,所以这里就可以重启一下网口,可以使用win+r组合键调出运行框,然后输入以下命令:

1
ncpa.cpl

然后就会打开控制界面,我们可以双击扩展的以太网口,进行禁用,然后重新启动即可。

3. 修改 bootcmd 和 bootargs

3.1 bootcmd

我们在uboot输入以下命令:

1
2
=> setenv bootcmd 'tftp 80800000 /imx6ull/zImage\;tftp 83000000 /imx6ull/imx6ull-14x14-emmc-4.3-800x480-c.dtb\;bootz 80800000 - 83000000'
=> saveenv

这里主要是设置从哪里下载设备树和linux镜像,我们在ubuntu中,tftp服务器目录下相关文件如下:

image-20230731184048600

这里在进行配置的时候 /home/hk/3tftp 是作为根目录的,所以对于开发板来说,zImage 所在的目录为 /imx6ull/zImage。

3.2 bootargs

1
2
=> setenv bootargs 'console=ttymxc0,115200 root=/dev/nfs nfsroot=192.168.10.101:/home/hk/4nfs/imx6ull_rootfs,proto=tcp rw ip=192.168.10.102:192.168.10.101:192.168.10.1:255.255.255.0::eth0:off init=/linuxrc'
=> saveenv

这里主要是设置nfs根文件系统的挂载目录,我们在ubuntu中,nfs目录下相关文件如下:

image-20230731184607455

这里配置的时候就直接配置完整的绝对路径即可。

4. 重启uboot测试

接下来就是重启测试了,我们可直接按下复位键或者在uboot中输入 re ,再按下回车即可。

4.1 uboot启动

最开始就是uboot的启动,我们可以看到会有以下打印信息:

image-20230731184858116

这里读秒结束后,便会开始运行bootcmd中的命令了。

4.2 下载设备树和linux镜像

image-20230731185001203

到这一阶段,会先检测网络是否正常,若是正常,则会打印出服务器的地址和开发板的地址。然后就会开始下载linux镜像文件zImage。接着就会开始下载设备树,同样会先检测网络,然后打印服务器信息,最后开始下载文件。

4.3 启动linux镜像

接下来就是启动linux内核了:

image-20230731185247183

后边还有很多,这里就截取了一部分,其实要是用的ubuntu16.04及以下的话,这个时候系统应该是可以正常启动的,但是我用的版本较高,所以最后挂载根文件系统失败了:

image-20230731185428305

这里会发现的VFS就表示从nfs挂载根文件系统失败了。我们后边再说怎么处理,其实到这里按理说正常是已经实现了从tftp下载linux镜像和设备树,从nfs挂载镜像,这里怎么处理可以看下一节的笔记。

五、问题处理

1. NFS版本问题

对于上边开发板无法从新版本的ubuntu挂载nfs上的根文件系统的问题,这里我们来看一下怎么处理。在网上查阅资料会发现,linux内核支持的nfs协议是2.0的,但是新版本的ubuntu默认是不支持nfs2.0的,我们可以看一下当前系统支持的nfs协议版本:

1
sudo cat /proc/fs/nfsd/versions
image-20230731192258556

可以看到,新版本的ubuntu是没有支持nfs2.0协议的,所以开发板和ubuntu通过nfs通信失败也是正常,那怎么处理?网上一搜就有很多资料,一般都是修改下边这个文件,添加nfs2.0协议:

1
sudo vim /etc/default/nfs-kernel-server

这个文件修改后的完成内容为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# Number of servers to start up
RPCNFSDCOUNT="8"

# Runtime priority of server (see nice(1))
RPCNFSDPRIORITY=0

# Options for rpc.mountd.
# If you have a port-based firewall, you might want to set up
# a fixed port here using the --port option. For more information,
# see rpc.mountd(8) or http://wiki.debian.org/SecuringNFS
# To disable NFSv4 on the server, specify '--no-nfs-version 4' here
RPCMOUNTDOPTS="--manage-gids"

# Do you want to start the svcgssd daemon? It is only required for Kerberos
# exports. Valid alternatives are "yes" and "no"; the default is "no".
NEED_SVCGSSD=""

# Options for rpc.svcgssd.
RPCSVCGSSDOPTS=""
RPCNFSDOPTS="--nfs-version 2,3,4 --debug --syslog"

其实就是在最后一行添加了一个2,修改完后我们保存,然后重启nfs服务:

1
sudo service nfs-kernel-server restart

然后再查看一下nfs的支持版本:

1
sudo cat /proc/fs/nfsd/versions
image-20230731193136229

发现并未生效,原因在哪呢?原因在于我们的系统实在太信了,所以还有其他的文件需要配置,哪个文件?我们可以去ubuntu官网搜索一下(Enterprise Open Source and Linux | Ubuntu)会发现这样一篇文章:

image-20230731192629843

我们可以点进去看一下,它其实说的就是Network File System (NFS),我们往下阅读就可以看到这部分关于ubuntu22.04的:

image-20230731192747078

从这里可以知道还有个 /etc/nfs.conf 文件,我们修改下这个文件:

1
sudo vim /etc/nfs.conf

把文件汇总vers2=n改为vers2=y,并把前面的#去掉:

image-20230731193359465

然后我们重启nfs服务并查看一下当前系统支持的nfs协议版本:

image-20230731193446085

发现这个时候,nfs2.0协议被支持,然后我们重启开发板,就会正常挂载nfs中的根文件系统啦,此时我们的uboot相关环境变量如下所示:

image-20230731195134292

不出意外的话,VFS这里是可以加载成功的,但是又报错了:

image-20230731195712698

后边这些错似乎是因为根文件系统,我后来换了自己以前移植的busybox根文件系统后就正常了,可以正常进入终端:

image-20230731200100507

所以前边的方法是可以处理掉nfs协议不对的问题的。

2. 设备树名称问题

2.1 问题复现

有时候可能会出现这样的问题uboot可以正常启动内核,但是显示完 Starting kernel … 之后,就卡死了,不再有输出,然后我们还会看到有这么一个 error :

image-20221023160744688

这是我以前遇到的一个问题,在这里也记录一下吧。我们其实可以将ubuntu中设备树的名字改掉,例如:

image-20230731200750378

然后我们按之前的参数重启开发板:

image-20230731201012558

就会发现,这里会提示找不到文件,但是系统还是正常起来了,以前遇到的卡死问题,倒是不知道为什么发生了,先不管,这里了解一下就行。

2.2 问题分析

其实很明显,出现这个错误的原因是因为 uboot 里面默认的设备树名字就是 imx6ull-14x14-emmc-4.3-800x480-c.dtb,但是呢,我们读取的地方并不存在这个文件,或者文件名不对的时候,就会出现这样的情况。

2.3 解决方法

2.3.1 解决方法1

我们修改一下 boocmd 和 bootargs 环境变量的值:

1
2
=> setenv bootcmd 'tftp 80800000 /imx6ull/zImage\;tftp 83000000 /imx6ull/imx6ull-alpha-emmc.dtb\;bootz 80800000 - 83000000'
=> saveenv

然后我们重启开发板,就会发现可以正常启动了:

image-20230731201429073

2.3.2 解决方法2

上边的解决办法在每次重新烧写系统以后都要先手动设置一下 bootcmd 的值,这样有点麻烦 ,当然还有一劳永逸的方法,那就是我们直接修改 uboot 源码中默认的环境变量值。打开 uboot 源码中 include/configs/mx6ull_alpha_emmc.h 文件,在宏 CONFIG_EXTRA_ENV_SETTINGS 中找到如下所示内容:

1
2
3
4
5
6
7
8
9
"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;\0" \

findfdt 就是用于确定设备树文件名字的环境变量, fdt_file 环境变量保存着设备树文件名。第 3 行和 4 行用于判断设备树文件名字是否为 imx6ull-9x9-evk.dtb,第 5 行和 6 行用于判断设备树文件名字是否为 imx6ull-14x14-evk.dtb。这两个设备树都是 NXP 官方开发板使用的, I.MX6U-ALPHA 开发板用不到,因此直接将 findfdt 的值改为如下内容:

1
2
3
4
"findfdt="\
"if test $fdt_file = undefined; then " \
"setenv fdt_file imx6ull-alpha-emmc.dtb; " \
"fi;\0" \

然后我们重新编译uboot,替换掉之前的uboot.imx文件,然后重新烧写就可以啦,就可以达到与之前一样的效果啦。