在家学习嵌入式1--搭建qemu环境

前言

新冠疫情期间在家里无事可做,奈何手上没有现成的开发板,又想调试学习linux内核,于是就有了这一系列的文章。本系列文章包含以下内容:

注意:这只是一个入门的文章,介绍自己如何一步步搭建qemu环境以及启动虚拟开发板。如果想要用现成的环境,可以去查看吴章金大牛发起的Linux lab 项目,那个项目做得非常的棒。


需求

作为嵌入式软件工程师,经常需要板子才能开发然后验证某些内容,这些东西在公司很容易实现。但是一回到家里,就没有这样的开发环境。因此,有没有这样一种仿真环境,支持某个虚拟的开发板可以在上面跑uboot、linux kernel,从而进行uboot或kernel的调试而不必关心具体的外设器件。


QEMU介绍

QEMU是一个支持各种目标处理器(例如x86,ARM,MIPS等)的模拟器。当用作机器仿真器时,QEMU可以在另一台机器(例如x86 PC)上运行为一台机器(例如ARM板)制作的操作系统和程序。在本文中,将详细列举出如何一步步搭建QEMU+ARM的仿真环境,虚拟的开发板vexpress-a9


QEMU环境搭建

软件版本

1
2
3
4
5
6
PC:Ubuntu 16.04
QEMU:qemu-arm version 2.5.0 (Debian 1:2.5+dfsg-5ubuntu10.42), Copyright (c) 2003-2008 Fabrice Bellard
Linux Kernel:5.3.0,使用这个版本的kernel,无法显示,换用4.4的kernel就可以显示,原因未知。
Linux Kernel:4.4.0
Target board:vexpress-a9 ARM Versatile Express for Cortex-A9
Cross Compile:arm-linux-gnueabi-gcc (Ubuntu/Linaro 5.4.0-6ubuntu1~16.04.9) 5.4.0 20160609

安装QEMU

1
sudo apt-get install qemu

直接使用apt-get install命令下载,没有参照网上说的下载源码编译。

下载linux kernel并切换到v4.4版本

1
2
git clone https://mirrors.tuna.tsinghua.edu.cn/git/linux.git
git checkout v4.4-rc1

安装arm交叉工具链

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

编译linux kernel

1
2
make CROSS_COMPILE=arm-linux-gnueabi- ARCH=arm vexpress_defconfig
make CROSS_COMPILE=arm-linux-gnueabi- ARCH=arm

这里使用vexpress_defconfig的配置,也就是使用vexpress-a9的板子。据说QEMU对这个板子支持比较好,具体的没有深入的研究。

根文件系统制作

  • 编译busybox
    1
    2
    3
    4
    wget https://busybox.net/downloads/busybox-1.30.0.tar.bz2
    make defconfig
    make CROSS_COMPILE=arm-linux-gnueabi-
    make install CROSS_COMPILE=arm-linux-gnueabi-

编译生成的bin文件在busybox-1.30.0/_install/目录下。

  • 创建根目录

    1
    mkdir -p rootfs/{dev,etc/init.d,lib}
  • 拷贝bin文件到rootfs

    1
    cp -rf ./busybox-1.30.0/_install/* rootfs/
  • 拷贝库文件到rootfs/lib/目录下

    1
    cp -P /usr/arm-linux-gnueabi/lib/* rootfs/lib/
  • 创建procsys目录等目录

    1
    2
    3
    4
    mkdir rootfs/proc
    mkdir rootfs/sys
    mkdir rootfs/config
    mkdir rootfs/debug

之所以要创建这两个目录,因为后面需要挂载procfssysfs两个文件系统。当然,这两个目录也可以在启动脚本中创建。

  • 修改为root

    1
    sudo chown -R root:root rootfs/
  • 创建4个tty终端设备

    1
    2
    3
    4
    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
  • 制作根文件系统镜像a9rootfs.ext4

    1
    dd if=/dev/zero of=a9rootfs.ext4 bs=1M count=32
  • 格式化成ext4文件系统

    1
    mkfs.ext4 a9rootfs.ext4
  • 将rootfs文件拷贝到文件系统中

    1
    2
    3
    4
    mkdir tempfs
    sudo mount -t ext4 a9rootfs.ext4 tempfs/ -o loop
    sudo cp -rf rootfs/* tempfs/
    sudo umount tempfs/
  • 设置开机启动命令

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    sudo vi rootfs/etc/init.d/rcS

    写入以下内容:
    #!/bin/sh
    mount -t sysfs sysfs /sys
    mount -t proc procfs /proc
    mount -t debugfs debugfsfs /debug
    mount -t configfs configfs /config

    mount -o rw,remount /

启动QEMU

1
qemu-system-arm -M vexpress-a9 -m 512M -kernel /home/victor/work/linux/linux/arch/arm/boot/zImage -dtb /home/victor/work/linux/linux/arch/arm/boot/dts/vexpress-v2p-ca9.dtb -append "root=/dev/mmcblk0 console=ttyAMA0" -sd /home/victor/work/linux/a9rootfs.ext4 -serial stdio

至此,就可以看到vexpress-a9板子启动的kernel log,并且出来一个串口,并且可以看到小企鹅的界面出现,后面我们就可以使用这块虚拟的开发板学习linux graphic相关的内容了。
关于qemu-system-arm命令各个参数详细解释如下:

  • -M vexpress-a9:表示使用vexpress-a9开发板的配置;
  • -m 512M:表示这只内存为512M;
  • -kernel xxx/arch/arm/boot/zImage:表示使用哪个内核镜像;
  • -dtb xxx/arch/arm/boot/dts/vexpress-v2p-ca9.dtb:表示使用哪个dtb文件;
  • -nographic:表示不启动图形化界面;
  • -append:表示设置kernel的cmdline;
  • -sd xxx/a9rootfs.ext4:表示使用sd卡上某个文件作为根文件系统;
  • qemu-system-arm -M help:可以查看支持的板子情况。

注意:在xshell远程ubuntu的使用使用-serial stdio的参数会提示如下错误,在ubuntu使用则不会,具体原因未知。

1
2
(qemu) qemu-system-arm: -serial stdio: cannot use stdio by multiple character devices
qemu-system-arm: -serial stdio: could not connect serial device to character backend 'stdio'

在启动参数加入console=tty0的时候,log会从图形界面输出来。
启动的kernel log如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
victor@victor-linux:~$ qemu-system-arm -M vexpress-a9 -m 512M -kernel /home/victor/work/linux/linux/arch/arm/boot/zImage -dtb /home/victor/work/linux/linux/arch/arm/boot/dts/vexpress-v2p-ca9.dtb -append "root=/dev/mmcblk0 console=ttyAMA0" -sd /home/victor/work/linux/a9rootfs.ext4 -nographic
WARNING: Image format was not specified for '/home/victor/work/linux/a9rootfs.ext4' and probing guessed raw.
Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted.
Specify the 'raw' format explicitly to remove the restrictions.
pulseaudio: set_sink_input_volume() failed
pulseaudio: Reason: Invalid argument
pulseaudio: set_sink_input_mute() failed
pulseaudio: Reason: Invalid argument
[ 0.000000] Booting Linux on physical CPU 0x0
[ 0.000000] Initializing cgroup subsys cpuset
[ 0.000000] Linux version 4.4.0 (victor@victor-linux) (gcc version 5.4.0 20160609 (Ubuntu/Linaro 5.4.0-6ubuntu1~16.04.9) ) #4 SMP Mon Feb 3 23:30:32 CST 2020
[ 0.000000] CPU: ARMv7 Processor [410fc090] revision 0 (ARMv7), cr=10c5387d
[ 0.000000] CPU: PIPT / VIPT nonaliasing data cache, VIPT nonaliasing instruction cache
[ 0.000000] Machine model: V2P-CA9
[ 0.000000] Memory policy: Data cache writeback
[ 0.000000] CPU: All CPU(s) started in SVC mode.
[ 0.000000] PERCPU: Embedded 12 pages/cpu @9fbbc000 s18188 r8192 d22772 u49152
[ 0.000000] Built 1 zonelists in Zone order, mobility grouping on. Total pages: 130048
[ 0.000000] Kernel command line: root=/dev/mmcblk0 console=ttyAMA0
[ 0.000000] log_buf_len individual max cpu contribution: 4096 bytes
[ 0.000000] log_buf_len total cpu_extra contributions: 12288 bytes
[ 0.000000] log_buf_len min size: 16384 bytes
[ 0.000000] log_buf_len: 32768 bytes
[ 0.000000] early log buf free: 14940(91%)
[ 0.000000] PID hash table entries: 2048 (order: 1, 8192 bytes)
[ 0.000000] Dentry cache hash table entries: 65536 (order: 6, 262144 bytes)
[ 0.000000] Inode-cache hash table entries: 32768 (order: 5, 131072 bytes)
[ 0.000000] Memory: 512540K/524288K available (4890K kernel code, 157K rwdata, 1400K rodata, 284K init, 152K bss, 11748K reserved, 0K cma-reserved)
[ 0.000000] Virtual kernel memory layout:
[ 0.000000] vector : 0xffff0000 - 0xffff1000 ( 4 kB)
[ 0.000000] fixmap : 0xffc00000 - 0xfff00000 (3072 kB)
[ 0.000000] vmalloc : 0xa0800000 - 0xff800000 (1520 MB)
[ 0.000000] lowmem : 0x80000000 - 0xa0000000 ( 512 MB)
[ 0.000000] modules : 0x7f000000 - 0x80000000 ( 16 MB)
[ 0.000000] .text : 0x80008000 - 0x8062cb1c (6291 kB)
[ 0.000000] .init : 0x8062d000 - 0x80674000 ( 284 kB)
[ 0.000000] .data : 0x80674000 - 0x8069b5e0 ( 158 kB)
[ 0.000000] .bss : 0x8069e000 - 0x806c43b8 ( 153 kB)
[ 0.000000] SLUB: HWalign=64, Order=0-3, MinObjects=0, CPUs=4, Nodes=1
[ 0.000000] Hierarchical RCU implementation.
[ 0.000000] Build-time adjustment of leaf fanout to 32.
[ 0.000000] RCU restricting CPUs from NR_CPUS=8 to nr_cpu_ids=4.
[ 0.000000] RCU: Adjusting geometry for rcu_fanout_leaf=32, nr_cpu_ids=4
[ 0.000000] NR_IRQS:16 nr_irqs:16 16
[ 0.000000] GIC CPU mask not found - kernel will fail to boot.
[ 0.000000] GIC CPU mask not found - kernel will fail to boot.
[ 0.000000] L2C: platform modifies aux control register: 0x02020000 -> 0x02420000
[ 0.000000] L2C: DT/platform modifies aux control register: 0x02020000 -> 0x02420000
[ 0.000000] L2C-310 enabling early BRESP for Cortex-A9
[ 0.000000] L2C-310 full line of zeros enabled for Cortex-A9
[ 0.000000] L2C-310 dynamic clock gating disabled, standby mode disabled
[ 0.000000] L2C-310 cache controller enabled, 8 ways, 128 kB
[ 0.000000] L2C-310: CACHE_ID 0x410000c8, AUX_CTRL 0x46420001
[ 0.000000] smp_twd: clock not found -2
[ 0.000190] sched_clock: 32 bits at 24MHz, resolution 41ns, wraps every 89478484971ns
[ 0.002513] clocksource: arm,sp804: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 1911260446275 ns
[ 0.005394] Console: colour dummy device 80x30
[ 0.005633] Calibrating local timer... 96.82MHz.
[ 0.064078] Calibrating delay loop... 729.49 BogoMIPS (lpj=3647488)
[ 0.162823] pid_max: default: 32768 minimum: 301
[ 0.163767] Mount-cache hash table entries: 1024 (order: 0, 4096 bytes)
[ 0.163802] Mountpoint-cache hash table entries: 1024 (order: 0, 4096 bytes)
[ 0.171517] CPU: Testing write buffer coherency: ok
[ 0.178226] CPU0: thread -1, cpu 0, socket 0, mpidr 80000000
[ 0.179127] Setting up static identity map for 0x60008280 - 0x600082d8
[ 0.188780] Brought up 1 CPUs
[ 0.188869] SMP: Total of 1 processors activated (729.49 BogoMIPS).
[ 0.188921] CPU: All CPU(s) started in SVC mode.
[ 0.220526] devtmpfs: initialized
[ 0.229612] VFP support v0.3: implementor 41 architecture 3 part 30 variant 9 rev 0
[ 0.238326] clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 19112604462750000 ns
[ 0.271747] NET: Registered protocol family 16
[ 0.274582] DMA: preallocated 256 KiB pool for atomic coherent allocations
[ 0.341602] cpuidle: using governor ladder
[ 0.341743] cpuidle: using governor menu
[ 0.348352] of_amba_device_create(): amba_device_add() failed (-19) for /memory-controller@100e0000
[ 0.348741] of_amba_device_create(): amba_device_add() failed (-19) for /memory-controller@100e1000
[ 0.349094] of_amba_device_create(): amba_device_add() failed (-19) for /watchdog@100e5000
[ 0.355177] of_amba_device_create(): amba_device_add() failed (-19) for /smb/motherboard/iofpga@7,00000000/sysctl@01000
[ 0.359367] of_amba_device_create(): amba_device_add() failed (-19) for /smb/motherboard/iofpga@7,00000000/wdt@0f000
[ 0.363936] hw-breakpoint: debug architecture 0x4 unsupported.
[ 0.364329] Serial: AMBA PL011 UART driver
[ 0.366100] 10009000.uart: ttyAMA0 at MMIO 0x10009000 (irq = 38, base_baud = 0) is a PL011 rev1
[ 0.399131] console [ttyAMA0] enabled
[ 0.410469] 1000a000.uart: ttyAMA1 at MMIO 0x1000a000 (irq = 39, base_baud = 0) is a PL011 rev1
[ 0.413902] 1000b000.uart: ttyAMA2 at MMIO 0x1000b000 (irq = 40, base_baud = 0) is a PL011 rev1
[ 0.415754] 1000c000.uart: ttyAMA3 at MMIO 0x1000c000 (irq = 41, base_baud = 0) is a PL011 rev1
[ 0.468356] SCSI subsystem initialized
[ 0.471182] usbcore: registered new interface driver usbfs
[ 0.472194] usbcore: registered new interface driver hub
[ 0.472940] usbcore: registered new device driver usb
[ 0.479099] Advanced Linux Sound Architecture Driver Initialized.
[ 0.495147] clocksource: Switched to clocksource arm,sp804
[ 0.543080] NET: Registered protocol family 2
[ 0.550144] TCP established hash table entries: 4096 (order: 2, 16384 bytes)
[ 0.551136] TCP bind hash table entries: 4096 (order: 3, 32768 bytes)
[ 0.552088] TCP: Hash tables configured (established 4096 bind 4096)
[ 0.553728] UDP hash table entries: 256 (order: 1, 8192 bytes)
[ 0.554304] UDP-Lite hash table entries: 256 (order: 1, 8192 bytes)
[ 0.556766] NET: Registered protocol family 1
[ 0.562762] RPC: Registered named UNIX socket transport module.
[ 0.564303] RPC: Registered udp transport module.
[ 0.564932] RPC: Registered tcp transport module.
[ 0.565518] RPC: Registered tcp NFSv4.1 backchannel transport module.
[ 0.575851] hw perfevents: enabled with armv7_cortex_a9 PMU driver, 1 counters available
[ 0.583459] futex hash table entries: 1024 (order: 4, 65536 bytes)
[ 0.625642] squashfs: version 4.0 (2009/01/31) Phillip Lougher
[ 0.631739] jffs2: version 2.2. (NAND) © 2001-2006 Red Hat, Inc.
[ 0.636289] 9p: Installing v9fs 9p2000 file system support
[ 0.643103] io scheduler noop registered (default)
[ 0.647942] clcd-pl11x 10020000.clcd: PL111 rev2 at 0x10020000
[ 0.656081] clcd-pl11x 10020000.clcd: /clcd@10020000 hardware, 1024x768@59 display
[ 0.739792] Console: switching to colour frame buffer device 128x48
[ 0.765090] clcd-pl11x 1001f000.clcd: PL111 rev2 at 0x1001f000
[ 0.766322] clcd-pl11x 1001f000.clcd: /smb/motherboard/iofpga@7,00000000/clcd@1f000 hardware, 640x480@59 display
[ 0.959531] 40000000.flash: Found 2 x16 devices at 0x0 in 32-bit bank. Manufacturer ID 0x000000 Chip ID 0x000000
[ 0.960863] Intel/Sharp Extended Query Table at 0x0031
[ 0.962127] Using buffer write method
[ 0.965497] 40000000.flash: Found 2 x16 devices at 0x0 in 32-bit bank. Manufacturer ID 0x000000 Chip ID 0x000000
[ 0.966484] Intel/Sharp Extended Query Table at 0x0031
[ 0.967741] Using buffer write method
[ 0.968342] Concatenating MTD devices:
[ 0.968765] (0): "40000000.flash"
[ 0.969100] (1): "40000000.flash"
[ 0.969360] into device "40000000.flash"
[ 1.060412] libphy: smsc911x-mdio: probed
[ 1.141943] smsc911x 4e000000.ethernet eth0: attached PHY driver [Generic PHY] (mii_bus:phy_addr=4e000000.etherne:01, irq=-1)
[ 1.152222] smsc911x 4e000000.ethernet eth0: MAC Address: 52:54:00:12:34:56
[ 1.265819] isp1760 4f000000.usb: bus width: 32, oc: digital
[ 1.269152] isp1760 4f000000.usb: NXP ISP1760 USB Host Controller
[ 1.271897] isp1760 4f000000.usb: new USB bus registered, assigned bus number 1
[ 1.279117] isp1760 4f000000.usb: Scratch test failed.
[ 1.281119] isp1760 4f000000.usb: can't setup: -19
[ 1.283532] isp1760 4f000000.usb: USB bus 1 deregistered
[ 1.299955] usbcore: registered new interface driver usb-storage
[ 1.310767] mousedev: PS/2 mouse device common for all mice
[ 1.323388] rtc-pl031 10017000.rtc: rtc core: registered pl031 as rtc0
[ 1.332061] mmci-pl18x 10005000.mmci: Got CD GPIO
[ 1.333047] mmci-pl18x 10005000.mmci: Got WP GPIO
[ 1.335764] mmci-pl18x 10005000.mmci: No vqmmc regulator found
[ 1.336790] mmci-pl18x 10005000.mmci: mmc0: PL181 manf 41 rev0 at 0x10005000 irq 34,35 (pio)
[ 1.388634] ledtrig-cpu: registered to indicate activity on CPUs
[ 1.406549] usbcore: registered new interface driver usbhid
[ 1.408744] usbhid: USB HID core driver
[ 1.425196] input: AT Raw Set 2 keyboard as /devices/platform/smb/smb:motherboard/smb:motherboard:iofpga@7,00000000/10006000.kmi/serio0/input/input0
[ 1.446792] mmc0: new SD card at address 4567
[ 1.455678] mmcblk0: mmc0:4567 QEMU! 32.0 MiB
[ 1.502967] aaci-pl041 10004000.aaci: ARM AC'97 Interface PL041 rev0 at 0x10004000, irq 33
[ 1.505573] aaci-pl041 10004000.aaci: FIFO 512 entries
[ 1.508563] oprofile: using arm/armv7-ca9
[ 1.511244] NET: Registered protocol family 17
[ 1.513656] 9pnet: Installing 9P2000 support
[ 1.515497] Registering SWP/SWPB emulation handler
[ 1.526156] rtc-pl031 10017000.rtc: setting system clock to 2020-02-03 17:13:06 UTC (1580749986)
[ 1.534574] ALSA device list:
[ 1.535249] #0: ARM AC'97 Interface PL041 rev0 at 0x10004000, irq 33
[ 2.041615] input: ImExPS/2 Generic Explorer Mouse as /devices/platform/smb/smb:motherboard/smb:motherboard:iofpga@7,00000000/10007000.kmi/serio1/input/input2
[ 2.065749] EXT4-fs (mmcblk0): couldn't mount as ext3 due to feature incompatibilities
[ 2.104035] EXT4-fs (mmcblk0): mounted filesystem with ordered data mode. Opts: (null)
[ 2.107922] VFS: Mounted root (ext4 filesystem) readonly on device 179:0.
[ 2.119440] Freeing unused kernel memory: 284K (8062d000 - 80674000)
[ 2.375731] random: nonblocking pool is initialized
[ 3.460303] EXT4-fs (mmcblk0): Filesystem with huge files cannot be mounted RDWR without CONFIG_LBDAF
[ 3.495909] EXT4-fs (mmcblk0): re-mounted. Opts: data=ordered

Please press Enter to activate this console.
/ #


参考资料

Title:在家学习嵌入式1--搭建qemu环境

Author:Victor Huang

Time:2020-03-27 / 18:03

Link:http://wowothink.com/90fb723e/

License: Attribution-NonCommercial-NoDerivatives 4.0 International (CC BY-NC-ND 4.0)