前两天看微信公众号时发现了一个嵌入式模拟器,感觉很不错,自己动手安装了一个,折腾了几天,下载一直是个问题,特此记录如下
模拟器大家应该都听说过,有的小伙伴打游戏也会安装模拟器,今天我们介绍的主角QMEU就是一个可以用在嵌入式的模拟器,如果你想学习嵌入式,但身边没有开发板,这时候你可以尝试使用它来模拟Linux内核的启动,当然它还可以模拟ARM、MIPS等各种CPU架构,本文主要介绍模拟ARM的启动流程
(一)环境介绍
虚拟机:VMware
Ubuntu 16.04LTS
(二)安装QEMU
我们常用的VMware和virtualBox只能在X86架构上,虚拟一台X86计算机,但是QEMU能用在X86架构下虚拟出ARM计算机。QEMU时一个支持跨平台的虚拟机,有两种模式:user mode和system mode,在system mode下能够模拟出整个计算机,可以在qemu上运行 操作系统,在user mode下,可以运行和当前平台指令集不同的可执行程序。例如可以用qemu在x86上运行ARM的可执行程序,但是两个平台必须是同一种操作系统,比如Linux。
由于本文介绍ARM版本,我们可以在Ubuntu里使用sudo apt install qemu-system-arm命令去安装,但是不太推荐此方法,Ubuntu里安装源更新比较慢,安装版本不确定,另外就是从官网(https://www.qemu.org/)下载源码包来安装,如果想了解更多,可以从阅读官网上相关信息。
(1)从官网下载好安装包,或者用我下载好的:qemu
wget https://download.qemu.org/qemu-5.1.0.tar.xz
(2)执行下面的命令
$: tar -xvJf qemu-5.0.1.tar.xz
$: cd qemu-5.0.1
$: ./configure
$: make & make install
//如果报错要安装两个文件:apt-get install libglib2.0-dev
apt-get install libpixman-1-dev
通过上面的安装了32位(qemu-system-arm)和64位(qemu-system-aarch64)的模拟器,使用help命令查看支持的开发板,这里面有很多我们的开发版选项,本文以vexpress-a9 (ARM Versatile Express for Cortex-A9) 为例进行讲解。
(三)编译操作系统
(1)编译u-boot
下载u-boot代码:
git clone https://gitlab.denx.de/u-boot/u-boot.git
//注意这个有时候会比较慢,找个合适的时间下载(比如早上),或者镜像上下载
下载完成后可以在u-boot的configs目录下查看配置文件,我们选择的vexpress-a9 配置文件是vexpress_ca9x4_defconfig,
make vexpress_ca9x4_defconfig
make CROSS_COMPILE=arm-linux-gnueabihf- all
//make的时候可能出错,按照出错提示百度相关错误,可能由于没有相关命令支持,例如我安装时提示flex找不到,执行apt-get install flex在make就成功了
//需要交叉编译工具的可以在这里下载http://releases.linaro.org/components/toolchain/binaries/
注意:如果指定交叉编译器的路径一定要使用绝对路径
(2)制作文件系统
以前都是使用busybox编译,然后手动创建跟文件目录,但是现在我们使用bulidroot可以很轻松容易的构建跟文件系统(这里感谢下文链接的作者提供了这么方便的工具)
buildroot下载
git clone git://git.buildroot.net/buildroot
上面下载的代码并不是真正下载跟文件系统,真正下载跟文件系统是在我们配置好后,编译时下载的。
执行make menuconfig来配置选项:
然后在Target opions选择相应的目标平台,我们这里点进去选择arm(little-endian)即ARM架构小端模式
build options选项我这里不修改保持默认,有需要的可以自行修改
编译工具链toolchain选择外部,找到自己的编译工具链位置,具体参考我的配置情况
上面的配置要注意内核头文件和编译工具链版本一样,不知道的可以在相应选项上按h查看帮助信息
选择对应的控制台信息:
为了减少跟文件系统镜像,这里在filesystem images里面选择如下,意思是使压缩文件系统(lz4),内核启动时解析文件系统。
其他配置先保持默认,有需要我们再修改
执行make savedefconfig命令,就会生成新的 defconfig 文件,然后执行make命令(执行make时会连接网络下载相关资源,注意网络畅通)
(3)编译kernel
代码下载:
git clone https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
不推荐使用上面的方法,下载太慢了,可以在网上直接搜相关镜像下载,这里我使用正点原子提供的kernel作为演示,使用imx的配置文件imx_v7_defconfig
然后把上面buildroot编译的文件系统拷贝过来
cp /opt/buildroot/output/images/rootfs.cpio .
make ARCH=arm vexpress_defconfig
make ARCH=arm menuconfig
make ARCH=arm CROSS_COMPILE=/交叉编译器路径/bin/arm-linux-gnueabihf- -j8
注意:上面一定要指定架构为arm架构
(4)系统启动
下面我们模仿sd卡启动过程
制作sd卡镜像:
dd if=/dev/zero of=sd.img bs=4096 count=4096
mkfs.vfat sd.img
把编译好的 kernel zImage 和 dtb 文件拷贝到 sd.img 中
mount sd.img /mnt/ -o loop,rw
cp arch/arm/boot/zImage /mnt/
cp arch/arm/boot/dts/vexpress-v2p-ca9.dtb /mnt/
umount /mnt
启动qemu
qemu-system-arm -M vexpress-a9 -m 512M -kernel ../u-boot/u-boot -nographic -sd sd.img
可以看到uboot启动了:
但是没有找到内核,我们还需要下面的操作
查看内核执行地址相对内存的偏移地址:0x8000
在 u-boot 命令行中输入bdinfo命令,可以查到这块开发板内存的起始地址:
//读取内核文件到开发板内存中
fatload mmc 0:0 0x62008000 zImage
fatload mmc 0:0 0x64008000 vexpress-v2p-ca9.dtb
//启动内核
bootz 0x62008000 - 0x64008000
(四) 总结
通过上面的操作我们完成了模拟内核启动的流程,有几个问题也折腾了好久说一下注意的几点:
(1)编译uboot、kernel时注意架构的选择
(2)在内核启动不成功,可能是sd.img没有制作成功
当然qemu并不能完全替代开发板,更多的功能可以自己发掘哈哈~