linux平台下嵌入式实验qemu tftp nfs kernel uboot busybox vexpress-a9
记录这个日志的主要原因是,网上这方面资料有很多,但大部分原理是完全对的,但就是不能顺利地运行,由于软件版本过老,部分已被弃用,还有nfs配置太XXX了,要做大量的调试,一个参数不对,需要拆腾好长时间,为了节约时间,提高效率,留个小记录吧,所用的软件及环境基本上是当前最新的。
准备环境及软件
1、openEluer21.04,其实哪个linux发行版都是可以的,我用的这个,只好在上面测试了
2、kernel5.10,linux的内核代码,目前基本上是最新的版本
3、qemu模拟器,可以模拟x86、arm等平台的软件
4、busybox,号称linux瑞士军刀,集成大部分经常使用的命令和工具。
5、uboot,嵌入式开发引导程序
6、nfs,网络协议及工具,可以映射文件及目录
7、tftp,网络上传下载基础协议及工具pxe
8、virbr0,虚拟桥接网卡,linux环境下基本都有,不用再安装配置。
一、下载安装arm工具链
1、https://releases.linaro.org/components/toolchain/binaries/latest-7/
2、https://publishing-ie-linaro-org.s3.amazonaws.com/releases/components/toolchain/binaries/latest-7/
3、https://mirrors.tuna.tsinghua.edu.cn/armbian-releases/_toolchain/
1、2那个两个地址下载简直是龟速,没办法,国外的链接,,第三个是清华的下载速度超快,下载版本用比较新的吧。
gcc-linaro-7.4.1-2019.02-x86_64_arm-linux-gnueabi.tar.xz
下载解压缩后在~/.bashrc添加相应的搜索路径,随时随地可以调用。
这个工具链信赖gcc版本,我在测试中发现需要升级到gcc7.3.0以上
如果gcc版本在这个以下,可以参考下面内容来升级。
https://blog.csdn.net/lenovo8088/article/details/116647203
二、下载安装模拟器qemu
下面的地址不能下载的可以在网上搜,直接编译安装。
https://download.qemu.org/qemu-6.0.0.tar.xz
下面命令中有很多参数,测试中用到的不多,只写几个能跑起来必用的参数。
qemu-system-arm
三、下载编译linux kernel
下载地址还是清华的,选比较新的内核吧5.10
wget https://mirrors.tuna.tsinghua.edu.cn/kernel/v5.x/linux-5.10.1.tar.gz
解压缩后编译
调用vexpress_defconfig配置文件会生成.config
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- vexpress_defconfig
清除编译相关配置
make mrproper ARCH=arm CROSS_COMPILE=arm-linux-gnueabi-
打开编译选项图形化配置
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- menuconfig
编译选项默认配置基本够用的,可以检查下面选项否开启组件nfs
Networking support->Networking options->TCP/IP networking->IP:
[ * ] IP: DHCP support
[ * ] IP: BOOTP support
File systems ->Network File Systems->
< * > NFS client support
[ * ] NFS client support for NFS version 3
[ * ] NFS client support for NFS version 4 (EXPERIMENTAL)
[ * ] Root file system on NFS
开始编译
make -j4 ARCH=arm CROSS_COMPILE=arm-linux-gnueabi-
编译完成后会生成zImage文件,不过在下一步测试中还需要uImage文件
执行下面命令可生成uImage,各个参数解释,有时间我再整理。
mkimage -C none -A arm -O linux -T kernel -a 0x60003000 -e 0x60003040 -d arch/arm/boot/zImage uImage
内存地址为什么0x60003000改为0x60003040呢,zImage是原始文件,uImage是uboot要调用的文件,他规定要偏移的0x40,没办法,照上面做就行了其实你用0x60006000也可以的。
把uImage zImage vexpress-v2p-ca9.dtb 三个文件复制到tftp目录,没有这个文件夹可以自己创建,以后要用的,当然你也可以自定义目录。
cp uImage /var/lib/tftpboot
cp arch/arm/boot/zImage /var/lib/tftpboot
cp arch/arm/boot/dts/vexpress-v2p-ca9.dtb /var/lib/tftpboot
好了,可以先测试一下,看看能不能跑起来
qemu-system-arm -M vexpress-a9 -m 512M -kernel /var/lib/tftpboot/zImage -dtb /var/lib/tftpboot/vexpress-v2p-ca9.dtb -nographic
运行后,一般会出现下面错误提示,暂时不用管他。
VFS: Cannot open root device "(null)" or unknown-block(0,0): error -6
Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0)
panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0) ]---
四、下载编译busybox
https://www.busybox.net/downloads/busybox-1.33.0.tar.bz2
解压缩后编译
默认配置生成.config
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- defconfig
打开图形化界面编译组件选项,默认配置就可以了
make menuconfig ARCH=arm CROSS_COMPILE=arm-linux-gnueabi-
生成文件硬链接
[*]setting->use static-libgcc
install as hard links
要指定自已安装的目录,可自定义。
path for make install
/nfsroot/rootfs
不指定的话,会生成一个_install的文件夹。
make -j4 ARCH=arm CROSS_COMPILE=arm-linux-gnueabi-
然后再安装
make install
自动生目录_install文件或自己定义的。
编译后的文件需要增加几个目录和文件
cd _install
新建目录
mkdir dev etc lib proc sys tmp etc/init.d
登录控制台文件
cd /dev
sudo mknod -m 666 tty1 c 4 1
sudo mknod -m 666 tty2 c 4 2
sudo mknod -m 666 tty3 c 4 3
sudo mknod -m 666 tty4 c 4 4
sudo mknod -m 666 console c 5 1
sudo mknod -m 666 null c 1 3
在/etc目录下新建文件 fstab inittab profile init.d/rcS
内容如下:
vi profile
#!/bin/sh
export HOSTNAME=helloArm
export USER=root
export HOME=root
export PS1="[$USER@$HOSTNAME \W]\# "
PATH=/bin:/sbin:/usr/bin:/usr/sbin
LD_LIBRARY_PATH=/lib:/usr/lib:$LD_LIBRARY_PATH
export PATH LD_LIBRARY_PATH
基本配置
vi inittab
::sysinit:/etc/init.d/rcS
::askfirst:-/bin/sh
::restart:/sbin/init
::ctrlaltdel:/sbin/reboot
挂载配置
vi fstab
#device mount-point type options dump fsck orde
proc /proc proc defaults 0 0
tmpfs /tmp tmpfs defaults 0 0
sysfs /sys sysfs defaults 0 0
tmpfs /dev tmpfs defaults 0 0
vi init.d/rcS
#!/bin/sh
/bin/mount -a
echo /sbin/mdev > /proc/sys/kernel/hotplug
/sbin/mdev -s
欢迎界面
vi /etc/init.d/rcS
echo
echo "##################################"
echo
echo "Welcome to A9 vexpress borad"
echo
echo "##################################"
虚拟一张sd卡,busybox文件比较大,大小为1024M
dd if=/dev/zero of=rootfs.ext4 bs=1M count=1024
文件格式为ext4
mkfs.ext4 rootfs.ext4
挂载sd卡
sudo mount -t ext4 rootfs.ext4 /mnt/ -o loop
查看目录
ls /mnt/
复制busybox _install文件
sudo cp -r /nfsroot/rootfs /mnt/
再次查看文件内容
ls /mnt/
干掉挂载的sd卡
sudo umount /mnt/
好了,终于可以测试一下。
qemu-system-arm -M vexpress-a9 -m 512M -kernel /var/lib/tftpboot/zImage -dtb /var/lib/tftpboot/vexpress-v2p-ca9.dtb -nographic -append "root=/dev/mmcblk0 rw console=ttyAMA0" -sd rootfs.ext4
显示下面信息就是成功的
EXT4-fs (mmcblk0): recovery complete
EXT4-fs (mmcblk0): mounted filesystem with ordered data mode. Opts: (null)
VFS: Mounted root (ext4 filesystem) on device 179:0.
Freeing unused kernel memory: 1024K
Run /sbin/init as init process
random: crng init done
#############################
Welcome to A9 vexpress borad
#############################
可以执行linux 常用命令了如:ls vi reboot等
其实调试到这里如果不用tftp nfs uboot下面的不用看了。
五、下载编译uboot
上面并没有使用到uboot,下面才是坑人的地方。
git clone git://git.denx.de/u-boot.git
上面这个太慢了,可以到网站下载
https://ftp.denx.de/pub/u-boot/
下载这个可以用浏览器直接下载
https://ftp.denx.de/pub/u-boot/u-boot-2021.04.tar.bz2
解压缩后直接编译
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- vexpress_ca9x4_defconfig
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- menuconfig
用默认配置就可以了,dhcp nfs组件可以加上,以后会用上的。
Command line interface->network command
[*]dhcp
[*]dns
[*]ping
[*]nfs
下面选项,暂时可以不用管他,以后调试通过之后再用。
boot options->
[*]enable arguments
()boot arguments这里可以填写环境变量参数,没有调试成功前,暂时不改(做个记号1)
[*]run bootcmd 这里可以填写启动命令,没有调试成功前暂时不改(做个记号2)
好了,可以编译
make -j8 ARCH=arm CROSS_COMPILE=arm-linux-gnueabi-
下面是内容可参考
修改网络配置的文件,其实这些参数可以在好多地方修改,不仅仅局限于这个文件。
vi include/configs/vexpress_common.h:
#define CONFIG_IPADDR 192.168.122.149
#define CONFIG_NETMASK 255.255.255.0
#define CONFIG_SERVERIP 192.168.122.1
编译完成后会生成u-boot文件
测试一下
qemu-system-arm -M vexpress-a9 -m 256 -kernel u-boot --nographic
一定有错误提示,只要能跑起来就行了,可以忽视错误,因为配置文件没有完成。
六、安装NFS
sudo dnf install nfs-utils
sudo systemctl enable --now nfs-server
sudo systemctl start nfs-server
sudo systemctl status nfs-server
看到绿色成功
● nfs-server.service - NFS server and services
Loaded: loaded (/usr/lib/systemd/system/nfs-server.service; enabled; vendo>
Drop-In: /run/systemd/generator/nfs-server.service.d
└─order-with-mounts.conf
Active: active (exited) since Tue 17:45:25 CST; 42min ago
Process: 1224 ExecStartPre=/usr/sbin/exportfs -r (code=exited, status=0/SUC>
Process: 1243 ExecStart=/usr/sbin/rpc.nfsd (code=exited, status=0/SUCCESS)
Main PID: 1243 (code=exited, status=0/SUCCESS)
showmount
sudo cat /proc/fs/nfsd/versions
测试
sudo vi /etc/exports
/nfsroot/rootfs 192.168.122.1(rw,sync,no_root_squash,no_subtree_check)
sudo exportfs
sudo exportfs -ra
在目标机上测试一下看是否能挂载
sudo mount -t nfs -o nolock 192.168.122.1:/nfsroot/rootfs /mnt/net -o vers=3
ls /mnt/net
sudo mount -t nfs 192.168.122.1:/nfsroot/rootfs /mnt/net
ls /mnt/net
七、安装tftp软件
sudo dnf install -y tftp-server tftp
sudo vim /etc/xinetd.d/tftp
disable = no
server_args = -s /var/lib/tftpboot -c
sudo chmod 777 /var/lib/tftpboot
sudo cp /usr/lib/systemd/system/tftp.service /etc/systemd/system/tftp-server.service
sudo cp /usr/lib/systemd/system/tftp.socket /etc/systemd/system/tftp-server.socket
下面其实就是编辑配置文件用vi也行,只不过下面是官方的文档,直接拿来用了。
/var/lib/tftpboot这个目录就是tftp下载的目录
sudo tee /etc/systemd/system/tftp-server.service<<EOF
[Unit]
Description=Tftp Server
Requires=tftp-server.socket
Documentation=man:in.tftpd
[Service]
ExecStart=/usr/sbin/in.tftpd -c -p -s /var/lib/tftpboot
StandardInput=socket
[Install]
WantedBy=multi-user.target
Also=tftp-server.socket
EOF
sudo systemctl daemon-reload
sudo systemctl enable --now tftp-server
systemctl status tftp-server
看到绿色就可以了
● tftp-server.service - Tftp Server
Loaded: loaded (/etc/systemd/system/tftp-server.service; enabled; vendor p>
Active: inactive (dead) since Tue 18:00:15 CST; 31min ago
TriggeredBy: ● tftp-server.socket
Docs: man:in.tftpd
Process: 814 ExecStart=/usr/sbin/in.tftpd -c -p -s /var/lib/tftpboot (code=>
Main PID: 814 (code=exited, status=0/SUCCESS)
八、虚拟网卡桥接
这里如果机器上有virbr0,直接跳过
启用桥,多个可以分行写,官方文档这样写的 。
vi /etc/qemu/bridge.conf
allow virbr0
更改后,执行。
sudo chmod u+s /usr/libexec/qemu-bridge-helper
添加
sudo brctl addbr br0
sudo brctl stp br0 on
sudo ip tuntap add name br0-nic mode tap
sudo ip link set dev br0-nic up
sudo brctl addif br0 br0-nic
sudo ifconfig br0 11.0.2.1/24 up
删除
sudo ip link set dev br0-nic down
sudo brctl stp br0 off
sudo ip link set dev br0 down
sudo ip tuntap del name br0-nic mode tap
sudo brctl delbr br0
九、测试
qemu-system-arm -M vexpress-a9 -m 128M -kernel u-boot -nographic -net nic,macaddr=88-88-88-88-88-66 -net bridge,id=net0,helper=/usr/libexec/qemu-bridge-helper,br=virbr0
初次启动,按esc键,进入手工调式模式
这一部分可以写到uboot编译参数里,也就是上面作记号的地方,不用分行。
单独调试可以分行测试
配置参数
记号1
setenv rootpath /nfsroot/rootfs;
setenv bootargs console=ttyAMA0,115200n8 init=/linuxrc root=/dev/nfs nfsroot=192.168.122.1:/nfsroot/rootfs,rw,nolock,v3 ip=192.168.122.149 ;
setenv ipaddr 192.168.122.149;
setenv serverip 192.168.122.1;
setenv netmask 255.255.255.0;
setenv gatewayip 192.168.122.1;
setenv dnsip 114.114.114.144;
记号2
setenv tftpboot 'tftp 0x60003040 uImage;tftp 0x60500000 vexpress-v2p-ca9.dtb;bootm 0x60003040 - 0x60500000';run tftpboot;
下面这一部分可以分开慢慢测试
setenv rootpath /nfsroot/rootfs;
下面一行最容易出错
setenv bootargs console=ttyAMA0,115200n8 init=/linuxrc root=/dev/nfs nfsroot=192.168.122.1:/nfsroot/rootfs,rw,nolock,v3 ip=dhcp ;
设置ip地址
setenv ipaddr 192.168.122.149;
设置服务器地址
setenv serverip 192.168.122.1;
设置子网掩码
setenv netmask 255.255.255.0;
设置网关
setenv gatewayip 192.168.122.1;
设置dns服务器
setenv dnsip 114.114.114.144;
将uImage和vexpress-v2p-ca9.dtb载入内存
setenv tftpboot 'tftp 0x60003040 uImage;tftp 0x60500000 vexpress-v2p-ca9.dtb;bootm 0x60003040 - 0x60500000';setenv bootcmd 'run tftpboot;run bootargs' ;
启动配置文件
run bootcmd;
下面的是虚拟SD卡启动的
qemu-system-arm -M vexpress-a9 -m 128M -kernel u-boot -nographic -net nic,macaddr=88-88-88-88-88-66 -net bridge,id=net0,helper=/usr/libexec/qemu-bridge-helper,br=virbr0 -sd /nfsroot/rootfs/rootfs.ext4
setenv ipaddr 192.168.122.149;
setenv serverip 192.168.122.1;
setenv netmask 255.255.255.0;
setenv gatewayip 192.168.122.1
setenv bootargs root=/dev/mmcblk0 rw console=ttyAMA0,115200n8 ip=dhcp
setenv tftpboot 'tftp 0x60003040 uImage;tftp 0x60500000 vexpress-v2p-ca9.dtb;bootm 0x60003040 - 0x60500000';saveenv;
run tftpboot;
十、总结
1、防火增的问题,一定要关闭防火增。当然上手后可以有选择性关闭的就行了。不然nfs挂载会失败的
sudo systemctl stop firewalld.service
sudo systemctl disable firewalld.service
2、新手可先调试qemu+kernel+sd卡这个容易,直接nfs+tftp+uboot会让崩溃的。
3、uboot参数多,一次性调试成功可能性很小,可以一个一个地来。
4、virbr0必须配置好
5、nfs调试有点困难,主要模拟器有点复杂,其实真机不会这么麻烦的。
其他:
dns www.baidu.com在uboot下居然通过了。
nslookup www.baidu.com这个busybox也可以
ping www.baidu.com是不行的,可以ping 后面加IP
可以在sd卡下测试mount命令是否成功,这样测试nfs是否正确配置
mount -t nfs -o nolock 192.168.122.1:/nfsroot/rootfs /mnt
ls /mnt
uboot,qemu参数解释并没有介绍详细,以后有时间补上。
^_^