Blog:
NXP iMX8MM 通过 TFTP和 NFS 启动示例
1). 简介
嵌入式 Linux 设备开发调试时候为了方便部署各种配置和修改常用的一种方法就是通过网络启动,具体就是将 Linux Kernel(以及 Device tree/Device Tree overlays) 从开发主机的 TFTP 服务加载, Linux rootfs 通过开发主机的 NFS 服务加载,这样开发过程中的功能配置或者文件修改就能直接在开发主机上面完成,而无需先复制到设备端再部署。本文就基于 NXP iMX8MM ARM嵌入式平台演示 TFTP/NFS 启动的简单示例。
本文所演示的平台来自于Toradex VerdiniMX8MM嵌入式平台,基于 NXP iMX8M Mini系列 ARM 处理器,核心为 Cortex-A53。
2). 硬件准备
a). Verdin iMX8MM ARM核心版配合 Dahlia Carrier Board载板,并连接调试串口以便测试。
b). Verdin iMX8MM 核心版 Boot ROM 启动选项已经 fuse ,因此 Bootloader (U-Boot) 必须要从模块 eMMC启动,所以先参考这里说明更新当前最新的 Toradex Ycoto Linux Reference Multimedia Image V6.4 到核心板 eMMC。
c). Verdin iMX8MM 设备平台网口和开发主机单独用于开发的网口直连,如下图所示。由于需要在开发主机配置 DHCP 服务,因此不建议将设备和开发主机直接连接到工作网络,以免多个 DHCP 服务器冲突。
d). 从这里下载 Toradex Ycoto Linux Reference Multimedia Image Quartely 6.4.0 版本到开发主机并解压,以便后续部署。
$ cd <work_dir>
$ tar xvf Verdin-iMX8MM_Reference-Minimal-Image-upstream-Tezi_6.4.0-devel-202309+build.14.tar
$ cd Verdin-iMX8MM_Reference-Minimal-Image-upstream-Tezi_6.4.0-devel-202309+build.14/
$ ls -al
总计 51684
drwxrwxr-x 2 simon simon 4096 12月 21 12:15 .
drwxr-xr-x 3 simon simon 4096 12月 21 12:15 ..
-rw-r--r-- 1 simon simon 2016 9月 2 00:37 image.json
-rw-r--r-- 1 simon simon 1291800 9月 2 00:03 imx-boot
-rw-r--r-- 1 simon simon 69050 9月 1 22:22 LA_OPT_NXP_SW.html
-rw-r--r-- 1 simon simon 378880 9月 1 22:22 marketing.tar
-rw-r--r-- 1 simon simon 183 9月 1 22:22 prepare.sh
-rw-r--r-- 1 simon simon 12981512 9月 2 00:35 Reference-Minimal-Image-upstream-verdin-imx8mm.bootfs.tar.xz
-rw-r--r-- 1 simon simon 38155936 9月 2 00:37 Reference-Minimal-Image-upstream-verdin-imx8mm.tar.xz
-rw-r--r-- 1 simon simon 2434 9月 1 22:22 toradexlinux.png
-rw-r--r-- 1 simon simon 4117 9月 1 23:47 u-boot-initial-env-sd
-rw-r--r-- 1 simon simon 18 9月 1 22:22 wrapup.sh
3). 开发主机部署 DHCP/TFTP/NSF 服务
a). 本文示例以 Ubuntu 22.04 64bit 环境为例,其他环境可以参考这里或者其对应发行版本的相关说明。
b). 配置 DHCP 服务
./ 安装 DHCP Server
$ sudo apt-get install isc-dhcp-server
./ 如下修改 /etc/dhcp/dhcpd.conf 配置文件
--- a/etc/dhcp/dhcpd.conf 2023-12-21 11:31:13.460674880 +0800
+++ b/etc/dhcp/dhcpd.conf 2023-12-21 11:44:49.647593313 +0800
@@ -7,7 +7,7 @@
#
# option definitions common to all supported networks...
-option domain-name "example.org";
+option domain-name "verdin.net";
option domain-name-servers ns1.example.org, ns2.example.org;
default-lease-time 600;
@@ -25,7 +25,7 @@
# Use this to send dhcp log messages to a different log file (you also
# have to hack syslog.conf to complete the redirection).
-#log-facility local7;
+log-facility local7;
# No service will be given on this subnet, but declaring it helps the
# DHCP server to understand the network topology.
@@ -61,11 +61,33 @@
# max-lease-time 7200;
#}
+subnet 192.168.10.0 netmask 255.255.255.0 {
+ default-lease-time 86400;
+ max-lease-time 86400;
+ option broadcast-address 192.168.10.255;
+ option domain-name "verdin.net";
+ option domain-name-servers ns1.example.org;
+ option ip-forwarding off;
+ option routers 192.168.10.1;
+ option subnet-mask 255.255.255.0;
+ interface enx000ec6cbab91;
+ range 192.168.10.32 192.168.10.254;
+}
+
# Hosts which require special configuration options can be listed in
# host statements. If no address is specified, the address will be
# allocated dynamically (if possible), but the host-specific information
# will still come from the host declaration.
+host eval {
+ filename "Image";
+ fixed-address 192.168.10.2;
+ hardware ethernet 00:14:2d:6f:07:22;
+ next-server 192.168.10.1;
+ option host-name "verdin";
+ option root-path "192.168.10.1:/srv/nfs/rootfs,wsize=1024,rsize=1024,v3";
+}
+
#host passacaglia {
# hardware ethernet 0:0:c0:5d:bd:95;
# filename "vmunix.passacaglia";
// 配置文件中,开发主机上面和设备连接的网口名为 “enx000ec6cbab91”,需要根据你的实际网口名对应修改。
// 由于 Verdin iMX8MM U-Boot 环境变量中默认如下配置 IP Address 信息,因此这里将开发主机网口 IP Address 直接配置为 192.168.10.1,否则就需要对应修改设备 U-Boot 环境变量定义。
Verdin iMX8MM # print serverip
serverip=192.168.10.1
Verdin iMX8MM # print ipaddr
ipaddr=192.168.10.2
// “host eval” 部分配置用于后续 NFS 启动,其中 “hardware ethernet” 是你实际使用的 Verdin iMX8MM 网口的 MAC 地址。这里配置是对应 NFSv3 协议,如果是 NFSv4 可以参考这里配置,但是需要注意 DHCP 服务配置这里和下面 NFS 服务配置协议版本必须对应。
./启动 DHCP 服务,然后可以让 Verdin iMX8MM 模块通过 eMMC 正常启动后,查看网口 eth0 是否正常通过上面设置的 DHCP 服务器获取到 192.168.10.2 IP Address 来验证 DHCP 服务。
$ sudo service isc-dhcp-server start
c). 配置 TFTP 服务
./ 安装 TFTP Server
$ sudo apt-get install tftpd-hpa
./ 配置文件 /etc/default/tftpd-hpa 可以不做修改
TFTP_USERNAME="tftp"
TFTP_DIRECTORY="/srv/tftp"
TFTP_ADDRESS=":69"
TFTP_OPTIONS="--secure"
./复制 Verdin iMX8MM Linux Kernel 等 Boot 文件到 TFTP 目录
$ cd <work_dir>/Verdin-iMX8MM_Reference-Minimal-Image-upstream-Tezi_6.4.0-devel-202309+build.14/
$ sudo tar Jxf Reference-Minimal-Image-upstream-verdin-imx8mm.bootfs.tar.xz -C /srv/tftp/
$ ls -al /srv/tftp/
总计 13312
drwxr-xr-x 3 root root 4096 9月 2 00:35 .
drwxr-xr-x 4 root root 4096 12月 21 12:32 ..
-rw-r--r-- 1 root root 6010 9月 2 00:35 boot.scr
-rw-r--r-- 1 root root 13211895 9月 2 00:35 Image.gz
-rw-r--r-- 1 root root 62002 9月 2 00:35 imx8mm-verdin-nonwifi-dahlia.dtb
-rw-r--r-- 1 root root 62246 9月 2 00:35 imx8mm-verdin-nonwifi-dev.dtb
-rw-r--r-- 1 root root 62000 9月 2 00:35 imx8mm-verdin-nonwifi-yavia.dtb
-rw-r--r-- 1 root root 62206 9月 2 00:35 imx8mm-verdin-wifi-dahlia.dtb
-rw-r--r-- 1 root root 62446 9月 2 00:35 imx8mm-verdin-wifi-dev.dtb
-rw-r--r-- 1 root root 62200 9月 2 00:35 imx8mm-verdin-wifi-yavia.dtb
drwxr-xr-x 2 root root 4096 9月 2 00:35 overlays
-rw-r--r-- 1 root root 47 9月 2 00:35 overlays.txt
./启动 TFTP 服务,然后可以通过另外一台 Linux 主机通过安装 TFTP 客户端来测试下 TFTP 服务是否正确配置成功。
$ sudo service tftpd-hpa start
d). 配置 NFS 服务
./ 安装 NFS Server
$ sudo apt-get install nfs-kernel-server
./ NFSv3 配置文件,对应上面 DHCP host eval配置;如果是 NFSv4 配置,可以参考这里。
#/etc/exports
/srv/nfs/rootfs 192.168.10.2(no_root_squash,no_subtree_check,rw)
./创建 NFS 文件目录,然后复制 Verdin iMX8MM Linux rootfs 文件到 NFS 目录
# create NFS folder
$ sudo mkdir -p /srv/nfs/rootfs
# copy Verdin iMX8MM rootfs to NFS folder
$ cd <work_dir>/Verdin-iMX8MM_Reference-Minimal-Image-upstream-Tezi_6.4.0-devel-202309+build.14/
$ sudo tar Jxf Reference-Minimal-Image-upstream-verdin-imx8mm.tar.xz -C /srv/nfs/rootfs
$ ls -al /srv/nfs/rootfs/
总计 72
drwxr-xr-x 18 root root 4096 3月 9 2018 .
drwxr-xr-x 3 root root 4096 12月 21 12:32 ..
drwxr-xr-x 2 root root 4096 3月 9 2018 bin
drwxr-xr-x 2 root root 4096 3月 9 2018 boot
drwxr-xr-x 2 root root 4096 3月 9 2018 dev
drwxr-xr-x 31 root root 4096 12月 21 12:43 etc
drwxr-xr-x 3 root root 4096 3月 9 2018 home
drwxr-xr-x 9 root root 4096 3月 9 2018 lib
drwxr-xr-x 4 root root 4096 12月 21 12:43 media
drwxr-xr-x 2 root root 4096 3月 9 2018 mnt
dr-xr-xr-x 2 root root 4096 3月 9 2018 proc
drwxr-xr-x 2 root root 4096 3月 9 2018 run
drwxr-xr-x 2 root root 4096 3月 9 2018 sbin
drwxr-xr-x 2 root root 4096 3月 9 2018 srv
dr-xr-xr-x 2 root root 4096 3月 9 2018 sys
drwxrwxrwt 2 root root 4096 3月 9 2018 tmp
drwxr-xr-x 10 root root 4096 3月 9 2018 usr
drwxr-xr-x 8 root root 4096 12月 21 12:43 var
./ 由于 Toradex Ycoto Linux 默认使用 connman 来管理网络,而在 NFS rootfs 加载过程中如果启动 connman,会导致网口重置,使得 NFS 服务中断无法启动成功,因此需要如下修改 rootfs 以规避这个问题。
--- a/lib/systemd/system/connman.service 2023-12-21 17:35:38.874742678 +0800
+++ b/lib/systemd/system/connman.service 2023-12-21 13:37:47.435149329 +0800
@@ -7,6 +7,7 @@
Before=network.target multi-user.target shutdown.target
Wants=network.target
Conflicts=systemd-resolved.service
+ConditionKernelCommandLine=!root=/dev/nfs
[Service]
Type=dbus
./启动 NFS 服务
$ sudo service nfs-kernel-server restart
./ 在 Verdin iMX8MM Ycoto Linux 上面可以通过下面命令测试 NFS 服务是否配置成功
root@verdin-imx8mm-07276322:~# mount -t nfs -o vers=3 192.168.10.1:/srv/nfs/rootfs <mount_dir>
4). Verdin iMX8MM 设备通过 TFTP/NFS 启动
a). Verdin iMX8MM 调试串口进入 U-Boot 命令行,执行下面命令即可完成 TFTP/NFS 启动
Verdin iMX8MM # run bootcmd_dhcp
5). 总结
本文基于NXP iMX8MM嵌入式平台演示了 TFTP/NFS 启动示例。
参考文档
https://developer.toradex.cn/linux-bsp/application-development/how-to-setup-networking-for-embedded-linux-application-development/ https://developer.toradex.cn/linux-bsp/os-development/boot/boot-from-a-tftpnfs-server/