使用 QEMU 进行嵌入式系统开发 第3部分 (译)

  2014-02-18 00:00:00 CST

  Jingwen Peng

  Linux

Embedded-Linux

本文翻译自 Linux for You 网站上的文章 Using QEMU for Embedded Systems Development, Part 3 (2011.8)

正文如下


这是这个 QEMU 系列文章的最后一篇了。在上一篇中,我们尝试了裸机开发,并且讨论了 Bootloader 的重要性。许多 GNU/Linux 发行版中使用 GRUB 作为他们的 Bootloader (早期版本使用 LILO)。在这篇文章中,我们将测试最受欢迎的 U-Boot (通用 Bootloader)。

在嵌入式系统中,尤其是移动设备,基于 ARM 处理器的设备统治着市场。对于 ARM 来说,U-Boot 是作为 Bootloader 的最佳选择。好消息是,它可以在很多架构上使用,比如 PPC、MIPS、x86 等。下面正式开始。

下载并编译 U-Boot

U-Boot 遵循 GPL 协议发布。可以从它的 FTP服务器 下载,里面有所有的 U-Boot 版本。在这使用 u-boot-1.2.0.tar.bz2。解压下载好的 tarball 然后进入代码目录:

1
2
$ tar -jxvf u-boot-1.2.0.tar.bz2
$ cd u-boot-1.2.0

开始之前,我们需要为 U-Boot 指定开发板型号。我们继续在前面文章中使用的 ARM Versatile 平台开发板 (versatilepb)。

1
2
3
$ make versatilepb_config arch=ARM CROSS_COMPILE=arm-none-eabi-
Configuring for versatile board...
Variant:: PB926EJ-S

配置结束之后,编译源代码:

1
2
3
4
5
6
7
8
9
$ make all arch=ARM CROSS_COMPILE=arm-none-eabi-
for dir in tools examples post post/cpu ; do make -C $dir _depend ; done
make[1]: Entering directory '/root/qemu/u-boot-1.2.0/tools'
ln -s ../common/environment.c environment.c
.
.
G++_Lite/bin/../lib/gcc/arm-none-eabi/4.4.1 -lgcc -Map u-boot.map -o u-boot
arm-none-eabi-objcopy --gap-fill=0xff -O srec u-boot u-boot.srec
arm-none-eabi-objcopy --gap-fill=0xff -O binary u-boot u-boot.bin

找到编译好的 U-Boot 二进制文件 (以我的经验,大约72KB),我们将在后面用到。假设你已经设置好 QEMU,网络以及 ARM 工具链。如果没有,建议你阅读之前的三篇文章。

在 QEMU 启动 U-Boot

现在我们可以用 U-Boot 二进制文件启动 QEMU 了,很容易。我们把 kernel 指定为 u-boot 二进制文件,而不是 Linux 内核:

1
$ qemu-system-arm -M versatilepb -nographic -kernel u-boot.bin

在 U-Boot 中运行如下代码,检查是否工作正常:

1
2
3
4
5
6
7
8
9
10
Versatile $ printenv
bootargs=root=/dev/nfs mem=128M ip=dhcp netdev=25,0,0xf1010000,0xf1010010,eth0
bootdelay=2
baudrate=38400
bootfile="/tftpboot/uImage"
stdin=serial
stdout=serial
stderr=serial
verify=n
Environment size: 184/65532 bytes

U-Boot

图 1:U-Boot

下一步是从启动一个小程序。在上一篇文章中,我们编写了一个裸机程序,就用它来试试。

我们要创建一个包含 u-boot.bin 和裸机程序的二进制镜像。上篇文章中的测试程序需要再次使用并做一些修改。由于 u-boot.bin 有 72kb 大小。我们将把我们的测试程序放在内存高地址。在连接脚本中更改程序的起始地址:

1
2
3
4
5
6
7
8
9
10
ENTRY(_Start)
SECTIONS
{
. = 0x100000;
startup : { startup.o(.text)}
.data : {*(.data)}
.bss : {*(.bss)}
. = . + 0x500;
sp_top = .;
}

编译测试程序:

1
2
3
4
$ arm-none-eabi-gcc -c -mcpu=arm926ej-s init.c -o init.o
$ arm-none-eabi-as -mcpu=arm926ej-s startup.s -o startup.o
$ arm-none-eabi-ld -T linker.ld init.o startup.o -o test.elf
$ arm-none-eabi-objcopy -O binary test.elf test.bin

现在,我们的测试程序和 u-boot.bin 需要打包成单个文件。使用 mkimage,在 U-Boot 源码目录中有这个工具:

1
2
3
4
5
6
7
$ mkimage -A arm -C none -O linux -T kernel -d test.bin -a 0x00100000 -e 0x00100000 test.uimg
Image Name:
Created:      Wed Jul 6 13:29:54 2011
Image Type:   ARM Linux Kernel Image (uncompressed)
Data Size:    148 Bytes = 0.14 kB = 0.00 MB
Load Address: 0x00100000
Entry Point:  0x00100000

测试用的二进制文件已经就绪,现在把它和 u-boot.bin 结合起来,生成镜像:

1
$ cat u-boot.bin test.uimg > flash.bin

计算测试程序在 flash.bin 中的起始地址:

1
2
$ printf "0x%X" $(expr $(stat -c%s u-boot.bin) + 65536)
0x21C68

使用 QEMU 启动镜像:

1
$ qemu-system-arm -M versatilepb -nographic -kernel flash.bin

检验一下起始地址:

1
2
3
4
5
6
7
8
Versatile $ iminfo 0x21C68
## Checking Image at 00021c68 ...
Image Name:
Image Type:   ARM Linux Kernel Image (uncompressed)
Data Size:    136 Bytes =  0.1 kB
Load Address: 00100000
Entry Point:  00100000
Verifying Checksum ... OK

镜像文件出现在地址 0x21C68 处。使用 bootm 命令启动:

1
2
3
4
5
6
7
8
9
10
11
12
13
Versatile $ iminfo 0x21C68
## Booting image at 00021c68 ...
Image Name:
Image Type:   ARM Linux Kernel Image (uncompressed)
Data Size:    148 Bytes =  0.1 kB
Load Address: 00100000
Entry Point:  00100000
OK

Starting kernel ...

Hello Open World

相关文章

QEMU快速使用指南 (译)

使用QEMU进行嵌入式系统开发 第1部分 (译)

使用QEMU进行嵌入式系统开发 第2部分 (译)

使用QEMU进行嵌入式系统开发 第3部分 (译)

如果您有疑问或建议,请在下方评论区域留言

遵循 BY-NC-ND 协议

评论功能加载中...