嵌入式系统学习涉及广泛的知识和技术。与特定种类的应用开发相比,嵌入式系统软件的开发环境构建显得尤为“奢侈”。很多时侯我们需要购买许多价格不菲、种类各异的嵌入式开发板以及配套的各类工具如JTAG/SWI烧录器、串口连接线等等。而准备这一切不仅需要金钱,还得有时间。而QEMU则可在一定程度缓解这种尴尬。本文记录在Ubuntu2204上基于QEMU搭建一个基础的嵌入式ARM开发板Vexpress-A9模拟运行环境的全过程。

ARM express 全称versatile express family, 是ARM公司自己推出的开发板,主要用于SOC厂商设计,验证和测试自己的SOC芯片。
采用主板+子板设计,主板提供各种外围接口,子板提供CPU运算,支持的Cortex-A5/A9/A15/R5等处理器。

一、安装QEMU

安装qemu虚拟机工具。

# For full system emulation
sudo apt install qemu-system
#For emulating Linux binaries
sudo apt install qemu-user-static

有兴趣的同学也可手动编译安装

https://www.qemu.org/
https://wiki.qemu.org/Hosts/Linux

git clone https://gitlab.com/qemu-project/qemu.git
git checkout remotes/origin/stable-8.2 -b stable-8.2

sudo apt-get install git libglib2.0-dev libfdt-dev libpixman-1-dev zlib1g-dev ninja-build

sudo apt-get install git-email
sudo apt-get install libaio-dev libbluetooth-dev libcapstone-dev libbrlapi-dev libbz2-dev
sudo apt-get install libcap-ng-dev libcurl4-gnutls-dev libgtk-3-dev
sudo apt-get install libibverbs-dev libjpeg8-dev libncurses5-dev libnuma-dev
sudo apt-get install librbd-dev librdmacm-dev
sudo apt-get install libsasl2-dev libsdl2-dev libseccomp-dev libsnappy-dev libssh-dev
sudo apt-get install libvde-dev libvdeplug-dev libvte-2.91-dev libxen-dev liblzo2-dev
sudo apt-get install valgrind xfslibs-dev 

sudo apt-get install libnfs-dev libiscsi-dev

./configure --target-list=arm-softmmu --audio-drv-list=
make 
sudo make install

测试安装结果

qemu-system-arm --version
#查看支持的开发板
qemu-system-arm -M help
#vexpress-a9

二、安装ARM交叉工具链

安装arm交叉工具链

sudo apt install -y gcc-arm-linux-gnueabihf
sudo apt install -y g++-arm-linux-gnueabihf

工具链的命令规则一般是:arch-core-kernel-system-language。其中:

(一)languag

译语言,表示该编译器用于编译何种语言,最常见的就是gcc,g++; 

(二)arch

体系架构,如ARM,MIPS等,表示该编译器用的指令集和CPU架构;

(三)core

使用的是哪个CPU Core,如Cortex A8;或者是指定工具链的供应商。如果没有特殊指定,则留空不填。这一组命名比较灵活,在某些厂家提供的交叉编译链中,有以厂家名称命名的,也有以开发板命名的,或者直接是none或cross的;

(四)kernel

所运行的OS,见过的有Linux,uclinux,bare(无OS);

(五)system

交叉编译链所选择的库函数和目标映像的规范,如gnu,gnueabi等。其中gnu等价于glibc+oabi;gnueabi等价于glibc+eabi。若不指定,则也可以留空不填;

1.ABI

二进制应用程序接口(Application Binary Interface(ABI) for the ARM Architecture),在计算机中,应用二进制接口描述了应用程序(或者其他类型)和操作系统之间或其他应用程序的低级接口,涵盖了数据类型的大小,布局和对齐,调用约定.

2.EABI

嵌入式ABI 嵌入式应用二进制接口指定了文件格式,数据类型,寄存器使用,堆积组织优化和在一个嵌入式软件中的参数的标准约定.
Arm-none-gnueabi-linux比arm-linux-gcc要好,在可一致性,兼容性上面
早期u-boot和Linux编译可能使用的都不是一个arm-linux-gcc版本 

3.HF

启用硬浮点计算(hf = hard-float)。 硬浮点(hard-float):依赖ARM CPU的浮点运算单元(FPU)执行浮点操作,速度快、效率高,需硬件支持(如Cortex-A系列)。 软浮点(soft-float):通过软件模拟浮点运算,兼容性广但性能差,适用于无FPU的低端ARM芯片(如Cortex-M系列)。

三、安装编译U-BOOT

(一)获取uboot源码

git clone https://github.com/u-boot/u-boot.git

(二)配置编译选项

make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- vexpress_ca9x4_defconfig

(三)编译uboot

make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -j $(nproc)

编译结束后,会在根目录下生成两个二进制文件uboot和uboot.bin。

(四)测试uboot

通过qemu运行uboot。

qemu-system-arm -kernel u-boot -nographic 

运行结果:

四、编译Linux内核

(一) 下载Linux内核源码

git clone https://mirrors.tuna.tsinghua.edu.cn/git/linux.git -b v5.4 linux-5.4

(二)配置内核

make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- vexpress_defconfig

(三)编译内核

make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -j $(nproc)

1.内核文件

编译将在arch/arm/boot下生成zImage内核压缩文件。

2.设备树文件

在arch/arm/boot/dtb下生成vexpress-v2p-ca9.dtb设备树文件。

五、制作根文件系统

根文件系统是:

  • Linux内核启动后首先挂载的文件系统
  • 包含基本的shell命令,各种库,字符设备,配置脚本等
  • 提供了根目录/
  • 可以放在: nor/nand flash, SD卡, 磁盘, 网络空间上
  • 一般使用busybox构建嵌入式根文件系统。

(一)编译安装busybox

#1.下载源代码
https://busybox.net/
#2.修改Makefile
ARCH = arm
CROSS_COMPILE =arm-linux-gnueabi-
#3.配置
make defconfig
make menuconfig
 Settings  --->  [*] Build static binary (no shared libs)
#4.编译
make -j $(nproc)
#5.安装
make install
#安装生成目录"_install"

在编译配置时,建议设置为表态连接。

如果未选择“Build static binary (no shared libs)",则需要将arm-linux-gnueabihf相关的库文件拷贝至根文件系统的/lib目录下。

(二)制作SD卡镜像

制作SD卡镜像文件

#1.生成镜像
#bs: 缓冲区块的大小
#count: 块的个数
dd if=/dev/zero of=sdcard.img bs=1M count=32
#2.格式化为ext3文件系统
mkfs.ext4 sdcard.img

初始化镜像文件

#3.将各种文件copy到文件系统镜像中
sudo mount -t ext4 sdcard.img /mnt -o loop
#4.创建基础目录
sudo mkdir etc proc sys dev var boot
#5.从busybox中拷贝程序与配置文件
sudo cp -rff ../busybox-1.32.0/_install/* /mnt/
sudo cp -rf ../busybox-1.32.0/examples/bootfloppy/etc/* /mnt/etc/
#6.从交叉编译库中拷贝库文件
cp -avf /usr/arm-linux-gnueabihf/lib/* /mnt/lib/

创建设备节点


#7.创建设备节点
#mknod: 创建块或字符设备节点
#-m 666: 权限读写
#tty1: 节点名称
#c: 字符设备
#4: 主设备号
#1: 次设备号
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  

拷贝内核镜像和设备树文件

cd ../
sudo cp linux-5.4/arch/arm/boot/zImage rootfs/boot/
sudo cp linux-5.4/arch/arm/boot/dts/vexpress-v2p-ca9.dtb rootfs/boot/

修改etc/fstab文件内容如下所示

proc    /proc   proc    defaults    0   0
sysfs   /sys    sysfs   defaults    0   0
tmpfs   /var    tmpfs   defaults    0   0

修改etc/init.d/rcS文件内容如下所示

#! /bin/sh

/bin/mount -a
/sbin/mdev -s

umount镜像

sudo umount /mnt

六、模拟运行

编写启动脚本

#/bin/sh

qemu-system-arm -M vexpress-a9 \
	-kernel u-boot \
	-sd sdcard.img \
	-no-reboot \
	-nographic \
	-m 512M

运行进入uboot界面

u-boot加载内核和设备树文件

load mmc 0:0 0x66000000 boot/zImage
load mmc 0:0 0x66500000 boot/vexpress-v2p-ca9.dtb

设置启动参数

setenv bootargs "root=/dev/mmcblk0 rw console=ttyAMA0,115200 init=/linuxrc"

启动内核并运行

bootz 0x66000000 - 0x66500000

运行界面如下:

七、总结

至此,一个基础的嵌入式模拟环境已经建立,可为后续Linux内核、U-Boot等系统及嵌入式软件调试提供坚实的基础。

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐