失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > 使用qemu搭建arm嵌入式linux开发环境

使用qemu搭建arm嵌入式linux开发环境

时间:2020-06-06 16:01:11

相关推荐

使用qemu搭建arm嵌入式linux开发环境

qemu搭建arm虚拟嵌入式linux开发环境

1.前言1.安装qemu与arm交叉编译工具2.Linux内核与设备树编译3.busybox根文件系统制作4.使用u-boot加载Linux内核5.搭建网络开发环境6.挂载NFS网络文件系统

1.前言

对于很多新手来说,上手嵌入式Linux开发是有一定的难度的——往往是各种名词听了一大堆,真正去操作的时候,对着开发板一脸茫然,不知从何下手。其实作为初学者,我们完全可以通过虚拟机来掌握嵌入式Linux的开发框架和基本流程,从而避免硬件上的一些坑。等到我们对整个开发过程比较了解之后,再去上手开发板就会事半功倍。

首先,我们需要了解一些基本概念:

arm交叉编译器:在主机上编译能够在arm开发板上运行的代码。

linux内核:linux运行的核心代码。

linux内核模块:动态可加载内核模块,执行时依赖于内核,可以看做是内核的一个拓展,包含各种驱动程序(驱动开发就主要是这一块)。

linux设备树:与硬件相关,用来描述芯片平台及板级差异的。

根文件系统:内核启动时挂载的第一个文件系统,用来访问各种目录和文件,与内核互相独立。

bootloader:开发板启动时的引导程序,一般使用u-boot来制作。

所以,为了在arm开发板上成功运行Linux系统,我们有如下三个方面的任务:

制作bootloader;编译linux内核、linux内核模块、linux设备树;制作根文件系统。

下面,我们使用qemu虚拟机来上手嵌入式linux的开发。

1.安装qemu与arm交叉编译工具

在命令行输入以下内容安装ARM交叉编译工具:

sudo apt-get install gcc-arm-linux-gnueabi

安装qemu:

sudo apt-get install qemu

若需要安装较新版本的qemu,可以自行下载源码手动编译安装)

使用qemu-system-命令可以查看qemu支持的CPU架构。

使用qemu-system-arm --version命令可以查看qemu的版本。

使用qemu-system-arm -M help命令可以查看支持的开发板类别。

2.Linux内核与设备树编译

下载Linux内核:/

选择长期维护的4.4版本 ,点击tarball进行下载:

将下载下来的Linux内核拷贝到home目录,使用tar xvf linux-4.4.232.tar.xz进行解压缩。

解压好后输入cd linux-4.4.232/进入linux内核目录下

修改Makefile:vim Makefile

搜索交叉编译关键字,在vim编辑器中输入:/CROSS_COMPILE,然后回车

向下移动光标,找到关键字ARCHCROSS_COMPILE,按i键进入插入文本模式,将其修改为如下内容:

按Esc键切换为一般模式,输入:wq保存并退出。

这里我们选择vexpress系列作为我们虚拟开发板,在linux内核目录下,输入make vexpress_defconfig对开发板进行配置,编译后生成.config文件:

配置好后,编译内核,生成zImage镜像文件:make zImage -j6(多线程编译)

编译内核模块make modules -j4

编译设备树,获得dtb文件:make dtbs

在linux内核目录下,使用qemu运行内核:qemu-system-arm -M vexpress-a9 -m 512M -kernel arch/arm/boot/zImage -dtb arch/arm/boot/dts/vexpress-v2p-ca9.dtb -nographic -append "console=ttyAMA0",该命令指定了开发板类别、内存大小、内核zImage文件、dtb文件、无图形界面、串口。

可以看到内核开始运行起来:

但是卡在了挂载根文件系统处,别急,接着往下看。

3.busybox根文件系统制作

使用ps命令查看qemu进程:ps -a

使用kill命令结束qemu进程:kill 25906

接下来,使用busybox制作根文件系统。

下载源码:/downloads/,下载最新版本即可。

解压缩:tar xvf busybox-1.32.0.tar.bz2

进入busybox源码目录:cd busybox-1.32.0/

修改Makefile:vim Makefile

在vim编辑器中输入/CROSS_COMPILE查找关键字CROSS_COMPILE

向下移动光标,找到关键字所在处,按i键切换到插入模式,并将值修改为arm-linux-gnueabi-

按Esc退出插入模式,输入/ARCH查找关键字ARCH

向下移动光标,找到关键字,按i切换到插入模式,并将值修改为arm

按Esc键,输入:wq保存退出。

接着,输入命令make defconfig回车等待配置完毕。

也可以使用图形化配置make menuconfig,按回车然后进入Settings选项,找到Build Options,点y键将选项Build static binary(编译成静态)选中,然后退出:

回到命令行,直接编译:make -j4

然后执行make install,生成一个**_install文件夹。

准备好后,下一步开始制作根文件系统。

输入cd回到home目录,新建目录mkdir rootfs,进入该目录cd rootfs/,将刚才生成的_install**目录里的所有文件拷贝到该目录下:

cp -r /home/zvcv/Downloads/busybox-1.32.0/_install/* ./

新建目录mkdir lib,将arm交叉编译器的库复制过来:

cp -r /usr/arm-linux-gnueabi/lib/* lib/

在rootfs目录下新建目录mkdir dev/,进入该目录cd dev/,创建节点sudo mknod -m 666 tty1 c 4 1(这里创建了一个串口字符设备,主设备号为4,从设备号为1)。

重复创建多个串口设备,注意分配好从设备号:

创建一个控制台节点:mknod -m 666 console c 5 1

创建一个空节点:mknod -m 666 null c 1 3

创建好的字符设备用ls查看:

回到home目录,输入命令dd if=/dev/zero of=rootfs.ext3 bs=1M count=32生成虚拟SD卡系统镜像,可以得到一个rootfs.ext3文件。

格式化该镜像:mkfs.ext3 rootfs.ext3

挂载该镜像到本地:mount -t ext3 rootfs.ext3 /mnt -o loop

将之前准备的rootfs目录下的所有文件都拷贝到该镜像挂载点:cp -r /home/zvcv/rootfs/* /mnt/

卸载:umount /mnt/

进入linux源码目录:cd linux/

使用qemu启动内核:qemu-system-arm -M vexpress-a9 -m 512M -kernel arch/arm/boot/zImage -dtb arch/arm/boot/dts/vexpress-v2p-ca9.dtb -nographic -append "root=/dev/mmcblk0 rw console=ttyAMA0" -sd /home/zvcv/rootfs.ext3,这里比之前多指定了一个sd镜像。

点击回车,进入命令行,linux启动完毕。

若要图形化启动,使用命令:qemu-system-arm -M vexpress-a9 -m 512M -kernel arch/arm/boot/zImage -dtb arch/arm/boot/dts/vexpress-v2p-ca9.dtb -append "root=/dev/mmcblk0 rw console=tty0" -sd rootfs.ext3

4.使用u-boot加载Linux内核

下载源码:u-boot下载,选择合适的版本即可。

(较新版本的u-boot需要更高版本的gcc来编译,为了方便起见,可以选用较早版本的u-boot)

下载后解压缩:tar xvf u-boot-.07.tar.bz2

切换到目录:cd u-boot-.07

编辑Makefile文件:vim Makefile

查找关键字:/CROSS_COMPILE

向下翻,找到CROSS_COMPILE,按i键切换模式,修改为如下内容:

按Esc键退出插入模式,输入:wq保存并退出。

命令行输入vim config.mk

查找关键字:/ARCH

按i键切换模式,修改关键字的值:

按Esc键退出插入模式,输入:wq保存并退出。

命令行输入命令进行配置:make vexpress_ca9x4_defconfig

配置好后,编译:make -j4

若make时出现下图中的问题,可能是交叉编译gcc的版本太低,下载新版本点击下载。

先移除旧版:sudo apt-get remove gcc-arm-linux-gnueabi

解压:tar -vxf gcc-linaro-7.2.1-.11-x86_64_arm-linux-gnueabi.tar.xz

拷贝:sudo cp -r ./gcc-linaro-7.2.1-.11-x86_64_arm-linux-gnueabi /opt/

编辑环境变量:sudo vim /etc/bash.bashrc,文件末尾添加如下内容:

PATH="$PATH:/opt/gcc-linaro-7.2.1-.11-x86_64_arm-linux-gnueabi/bin"

使路径生效:source /etc/bash.bashrc

使用arm-linux-gnueabi-gcc -v查看编译器版本

若make时出现如下错误:

则编辑环境变量:vim ~/.bashrc

按G跳到文件结尾,按i键输入,添加如下内容:

export CROSS_COMPILE=arm-linux-gnueabi-export ARCH=arm

更新环镜变量:source ~/.bashrc

然后再次执行即可:

make vexpress_ca9x4_defconfigmake -j4

若make时又出现如下错误:

则需要安装device-tree-compiler:sudo apt-get install device-tree-compiler

make完成后,启动u-boot:qemu-system-arm -M vexpress-a9 -m 512M -nographic -kernel u-boot(注意:按下enter键后,会出现一个2s倒计时,询问你是否停止自动启动,直接回车就可以跳过启动过程中各种外设的加载)

输入命令测试:help,可以查看支持的命令。

运行成功后,删除该qemu进程:ps -a查找PID号,kill命令删除

5.搭建网络开发环境

qemu通过tftp工具下载内核镜像。

接下来配置主机和qemu之间的网络连接。

安装工具包:sudo apt-get install uml-utilities bridge-utils

查看主机网口,命令行输入:ifconfig,记下网口名和IP地址

然后,修改网络接口文件:vim /etc/network/interfaces

添加虚拟网口,配置为桥接模式,添加信息如下:

auto ens33auto br0iface br0 inet dhcpbridge_ports ens33

保存退出,使用命令重启网络:service networking restart

若失败,则重启Ubuntu:reboot

使用ifconfig命令查看生成的虚拟网口br0:

检查无误后,进入linux内核目录:cd linux-4.4.232/

将内核编译为uImage模式:make LOADADDR=0x60003000 uImage -j4

查看生成的镜像文件:ls arch/arm/boot/

可以看到多了一个uImage。

在主机上安装TFTP工具sudo apt-get install tftp-hpa tftpd-hpa xinetd

修改文件权限:chmod 777 /etc/default/tftpd-hpa

再修改配置文件:vim /etc/default/tftpd-hpa,如下图所示:

在主目录创建tftp文件夹:mkdir /home/zvcv/tftpboot,一定要和上面的一致,不然会出错。

修改权限:chmod 777 tftpboot

重启tftp服务:

sudo /etc/init.d/tftpd-hpa restart

把之前生成的的uImage和dtb文件拷贝到刚创建的目录下:

cp -p ./arch/arm/boot/uImage /home/zvcv/tftpboot/cp -p ./arch/arm/boot/dts/vexpress-v2p-ca9.dtb /home/zvcv/tftpboot/

自动引导设置

进入u-boot-.05目录:cd u-boot-.05/

修改配置文件:vim include/configs/vexpress_common.h

查找关键字:/BOOTCOMMAND

注释宏定义CONFIG_BOOTCOMMAND,并添加如下内容(190~197行):

其中,CONFIG_SERVERIP地址根据你主机ifconfig的结果来设置,比如我的是192.168.155.128。

CONFIG_IPADDRCONFIG_SERVERIP设置为同一网段(不冲突就行),如192.168.155.129。

然后,保存退出即可。

如果用ifconfig命令查看ens33网口时,发现没有显示ip地址,可以通过命令ifconfig ens33 192.168.155.128来手动配置ip地址。同样,也可以用ifconfig br0 192.168.155.129来设置br0网口ip地址。

用ping命令测试是否配置成功:

ping 192.168.155.128ping 192.168.155.129

能够ping通则说明配置成功:

可以按ctrl+c来停止ping的运行。

接着,在u-boot-.05目录下重新编译生成u-boot:

make -j4

拷贝u-boot文件到创建的tftpboot目录下:

cp -p ./u-boot /home/zvcv/tftpboot/

tftpboot目录包含的文件如下图所示:

拷贝完成后,进入刚才创建的目录:cd /home/zvcv/tftpboot

启动u-boot引导uImage:qemu-system-arm -M vexpress-a9 -kernel u-boot -nographic -m 512M -net nic,vlan=0 -net tap,vlan=0,ifname=tap0 -sd /home/zvcv/rootfs.ext3,其中rootfs.ext3是前面制作的文件系统。

正常启动如下图所示:

如果启动失败,可以reboot重启一下主机,再执行上述命令。

为了方便起见,可以把上述命令放进一个脚本文件。

创建并编辑文件:vim boot-script.sh,添加内容如下图所示:

保存退出后,就可以通过输入./boot-script直接调用该启动命令了。

启动完后,可以输入命令进行测试:

可以看到,u-boot引导的linux内核能正常工作了。

6.挂载NFS网络文件系统

安装NFS服务:sudo apt-get install nfs-kernel-server

配置NFS挂载目录:vim /etc/exports,添加下面一行内容:

其中rootfs是前面小节创建的用于制作跟文件系统的目录。

开启NFS服务:

/etc/init.d/rpcbind restart/etc/init.d/nfs-kernel-server restart

切换到内核目录,图形化配置内核,使其支持NFS:make menuconfig

然后重新编译内核:make -j4

切换到u-boot目录,编辑文件:vim include/configs/vexpress_common.h

修改关键字:

#define CONFIG_BOOTCOMMAND \"tftp 0x60003000 uImage;tftp 0x60500000 vexpress-v2p-ca9.dtb; \setenv bootargs 'root=/dev/nfs rw\nfsroot=192.168.232.20:/home/qemu-test/rootfs init=/linuxrc \ip=192.168.232.21\console=ttyAMA0'; \bootm 0x60003000 - 0x60500000;"

qemu启动u-boot:

qemu-system-arm \-M vexpress-a9 \-kernel u-boot \-m 512M \-nographic \-net nic,vlan=0 -net tap,vlan=0,ifname=tap0 \-append "root=/dev/mmcblk0 rw console=ttyAMA0"\

教程参考来自《嵌入式工程师自我修养》系列视频。

如果觉得《使用qemu搭建arm嵌入式linux开发环境》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。