交叉编译器的作用就不需要详细解释了,因为我们是在x86平台上进行编译,而运行的平台是ARM系统,这2个平台的指令集不一样,所以需要交叉编译得到ARM系统上可以执行的程序。
sudo apt-get install gcc-arm-linux-gnueabi gcc-arm-linux-gnueabihf
验证安装结果:
dpkg -l gcc-arm-linux-gnueabi
下载内核kernel压缩包:
wget https://mirror.bjtu.edu.cn/kernel/linux/kernel/v5.x/linux-5.10.tar.xz
使用 vexpress-a9 这款开发板。vexpress-a9 是 Arm 公司自己设计的一款 4 核 Cortex-A9 开发板,U-Boot、Linux Kernel 和 QEMU 对这款开发板都做了完整的支持。
解压:
tar -xvf linux-5.10.tar.xz
在解压后的linux-5.10目录下,生成vexpress开发板子的config文件:
cd linux-5.10
make CROSS_COMPILE=arm-linux-gnueabihf- ARCH=arm vexpress_defconfig
编译32位kernel:
make CROSS_COMPILE=arm-linux-gnueabihf- ARCH=arm
生成的内核镱像位于arch/arm/boot/zImage
设备树 arch/arm/boot/dts/vexpress-v2p-ca9.dtb
注意更改当前路径
wget https://ftp.denx.de/pub/u-boot/u-boot-2020.10.tar.bz2
解压:
tar -xvf u-boot-2020.10.tar.bz
解压完后,可以看到 configs 目录下有针对这款开发板的配置文件。ca9x4表示cortexA9架构,4核心,vexpress_ca9x4_defconfig
。
ls configs/ | grep vexpress
编译:
make vexpress_ca9x4_defconfig
make CROSS_COMPILE=arm-linux-gnueabihf- all
编译时可能会出现提示:Your GCC is older than 6.0 and is not supported,解决方式如下:
更改uboot的源码:/arch/arm/config.mk
# Only test once
ifeq ($(CONFIG_$(SPL_)SYS_THUMB_BUILD),y)
#archprepare: checkthumb checkgcc6
archprepare: checkthumb
checkthumb:
@if test "$(call cc-name)" = "gcc" -a \
"$(call cc-version)" -lt "0404"; then \
echo -n '*** Your GCC does not produce working '; \
echo 'binaries in THUMB mode.'; \
echo '*** Your board is configured for THUMB mode.'; \
false; \
fi
#else
#archprepare: checkgcc6
endif
#checkgcc6:
# @if test "$(call cc-name)" = "gcc" -a \
# "$(call cc-version)" -lt "0600"; then \
# echo '*** Your GCC is older than 6.0 and is not supported'; \
# false; \
# fi
最终编译生成 elf 格式的可执行文件 u-boot 和纯二进制文件u-boot.bin,其中 QEMU 可以启动的为 elf 格式的可执行文件 u-boot :
根文件系统放在哪里?
其实依赖于每个开发板支持的存储设备,可以放到Nor Flash上,也可以放到SD卡,甚至外部磁盘上。最关键的一点是你要清楚知道开发板有什么存储设备。本次使用SD卡做为存储空间,文件格式为ext3格式。
①下载、编译和安装busybox:(注意更改当前路径)
链接:busybox - BusyBox: The Swiss Army Knife of Embedded Linux
版本:busybox-1_30_0
解压,并进入该目录下:
tar xjvf busybox-1_30_0.tar.bz2
cd busybox-1_30_0
因为是配置arm环境,交叉编译到arm上运行, 需要修改Makefile:
vim Makefile
修改成这样:
编译,安装:
make menuconfig
执行上述指令会出现如下界面,点击Settings->,再设置静态编译:
编译:
make -j6
编译完成后检查,成功:
ls -l busybox
安装(在
busybox-1_30_0/_install
目录下安装):make install
安装完成后会形成
_install
目录:
②形成根目录结构:
在Ubuntu主机环境下,形成目录结构,里面存放的文件和目录与单板上运行所需要的目录结构完全一样,然后再打包成镜像(在开发板看来就是SD卡),这个临时的目录结构称为根目录。
首先创建rootfs目录(根目录),根文件系统内的文件全部放到这里:
mkdir -p rootfs/{dev,etc/init.d,lib}
把busybox中的文件复制到rootfs根目录下,主要是一些基本的命令:
sudo cp busybox-1_30_0/_install/* -r rootfs/
把交叉编译工具链中的库文件复制到rootfs根目录的lib文件夹下:
sudo cp -P /usr/arm-linux-gnueabi/lib/* rootfs/lib/
创建4个tty端终设备:
sudo mknod rootfs/dev/tty1 c 4 1 sudo mknod rootfs/dev/tty2 c 4 2 sudo mknod rootfs/dev/tty3 c 4 3 sudo mknod rootfs/dev/tty4 c 4 4
③制作根文件系统镜像:
根文件系统镜像就相当于一个硬盘,就是把上面rootfs根目录中的所有文件复制到这个硬盘中。
生成512M大小的镜像:
dd if=/dev/zero of=a9rootfs.ext3 bs=1M count=32
格式化成ext3文件系统:
mkfs.ext3 a9rootfs.ext3
挂载,将文件拷贝到镜像中:
sudo mkdir tmpfs
sudo mount -t ext3 a9rootfs.ext3 tmpfs/ -o loop
sudo cp -r rootfs/* tmpfs/
sudo umount tmpfs
目录结构:
启动qemu(arm环境):
qemu-system-arm -M vexpress-a9 -m 512M -kernel linux-5.10/arch/arm/boot/zImage -dtb linux-5.10/arch/arm/boot/dts/vexpress-v2p-ca9.dtb -nographic -append "root=/dev/mmcblk0 console=ttyAMA0" -sd a9rootfs.ext3
启动完成:
退出qemu:Ctrl+A 松开后按 X 退出qemu。
关于qemu启动ARM虚拟机运行指令解析:
qemu-system-arm #qemu主要配置
-M vexpress-a9 #模拟vexpress-a9单板
-m 512M #内存配置
-kernel linux-5.10/arch/arm/boot/zImage #内核路径
-dtb linux-5.10/arch/arm/boot/dts/vexpress-v2p-ca9.dtb #设备树路径
-nographic #不使用图形化界面,只使用串口
-append "root=/dev/mmcblk0 console=ttyAMA0" #内核启动参数(vexpress单板运行)
-sd a9rootfs.ext3 #SD卡印像
在Ubuntu任意一个目录,编写HelloWorld可执行程序hello.c:
vim hello.c
#include
int main()
{
printf("HelloWorld! \n");
return 0;
}
交叉编译hello.c,得到arm的可执行程序hello:
arm-linux-gnueabi-gcc hello.c -g -o hello.exe #带上-g选项编译debug版本
通过file指令,可查看hello.exe程序:
file hello.exe
把hello可执行程序复制到磁盘镜像disk.img中:
挂载(路径/home/kevin/kernel510):
sudo mount -o loop ./a9rootfs.ext3 tmpfs/
复制文件(注意路径):
sudo cp /home/kevin/hello.exe /home/kevin/kernel510/tmpfs/
卸载:
sudo umount tmpfs
再次启动虚拟机:
qemu-system-arm -M vexpress-a9 -m 512M -kernel linux-5.10/arch/arm/boot/zImage -dtb linux-5.10/arch/arm/boot/dts/vexpress-v2p-ca9.dtb -nographic -append "root=/dev/mmcblk0 console=ttyAMA0" -sd a9rootfs.ext3 -S -gdb tcp::8080
执行hello.exe程序,即可看到输出结果: