利用qemu搭建arm cortex a9开发环境以及gdb调试

来源:互联网 发布:统计年鉴数据不一致 编辑:程序博客网 时间:2024/05/18 13:23

网上有利用qemu搭建linux和uboot开发的教程,但是没有如何搭建裸机开发,这篇文章记录一下如何利用qemu来学习arm架构的东西。

裸机运行Hello World

网上有一个是关于使用arm926来跑裸机程序的帖子,我这里的代码主要参考了他的,改了一些硬件上的配置。我把原帖贴出来,对于想在qemu上跑arm926的可以参考他。
Hello world for bare metal ARM using QEMU

下载qemu-system-arm和编译器

qemu-system-arm有两种下载方式:1.直接sudo apt-get install qemu-system-arm;2.下载源代码自己编译。为了方便我直接使用了apt-get下载qemu-system-arm,因为他也支持gdb,但是版本较低,支持的板子少一点。本文模拟的是arm公司的vexpress-a9这块板子。

编译器的话本文使用了arm-none-eabi-工具链,也是直接使用apt-get就能下载到。

Hello World裸机源码

代码很简单,设置一下c程序的栈指针,跳转到c代码执行

/*startup.s*/    .global _Reset        _Reset:         ldr sp, =stack_top         bl c_entry         b .

c代码也很简单,往串口数据寄存器里写入Hello world,因为这个是虚拟机,所以不需要写什么串口驱动。这样的代码放到实际的板子上不能运行的,串口需要设置,并且读写也不是这么简单。

串口0的数据寄存器的地址是0x10009000,这个值可以在qemu的源码中找到,目录位于/qemu/hw/arm/vexpress.c,这个文件描述了vexpress-a9的板子,板子上其他硬件的地址也在该文件中可以找到。如果换了其他的板子,可以在其他的一些文件找到相应的硬件地址,更改即可

/*test.c*/volatile unsigned int * const UART0DR = (unsigned int *)0x10009000;void print_uart0(const char *s) {     while(*s != '\0') {         *UART0DR = (unsigned int)(*s++);     }}void c_entry() {     print_uart0("Hello world!\n");}

链接脚本,链接地址是0x60010000,这个值是qemu使用-kernel启动时第一条指令执行的地址,每个板子和机器上都有差异,同样的需要自己到相应的板子源文件中去查,这里是vexpress.c。链接脚本最后就是在img最后定义了4kb的栈。

/*test.ld*/ENTRY(_Reset)SECTIONS{    . = 0x60010000;    .startup . : { startup.o(.text) }    .text : { *(.text) }    .data : { *(.data) }    .bss : { *(.bss COMMON) }    . = ALIGN(8);    . = . + 0x1000; /* 4kB of stack memory */    stack_top = .;}

编译运行

编译成test.bin和test.elf,test.elf调试使用

$ arm-none-eabi-as  -g startup.s -o startup.o$ arm-none-eabi-gcc -c -s -g test.c -o test.o$ arm-none-eabi-ld -T test.ld test.o startup.o -o test.elf$ arm-none-eabi-objcopy -O binary test.elf test.bin

使用该命令运行qemu模拟vexpress-a9板子,-kernel后面就是编译出来的二进制执行文件

qemu-system-arm -M vexpress-a9-m 256M -nographic -kernel test.bin

GDB调试

这个gdb调试搞了漫长时间后来终于能调通,实际上网上关于这方面的东西很多,这里仅仅只是整理一下,做知识的搬运工。

首先是编译arm-linux-gdb,需要下载源码自己编译, 照着下面这篇文章就能很快的搭建好gdb
arm-linux-gdb 交叉编译工具的安装使用

OK,编译完之后就可以进行qemu的调试了。首先要开两个终端,一个终端运行

qemu-system-arm -M vexpress-a9 -m 256M -nographic -kernel test.elf -s -S

会打印
mjm@mjm-VirtualBox:~/smc_demo$ qemu-system-arm -M vexpress-a9 -m 256M -nographic -kernel smc_test.elf -s -S
pulseaudio: set_sink_input_volume() failed
pulseaudio: Reason: Invalid argument
pulseaudio: set_sink_input_mute() failed
pulseaudio: Reason: Invalid argument

然后启动另外一个终端执行以下命令

arm-linux-gdb test.elf

进入gdb后输入target remote localhost:1234就能连接到qemu的gdb server了,连接后使用l命令可以看到如下消息

(gdb) target remote localhost:1234Remote debugging using localhost:1234[New thread 1]reset () at smc_start.s:6161              mrs r0, cpsrwarning: shared library handler failed to enable breakpointCurrent language:  auto; currently asm(gdb) l56      .global call_smc57      .global test_call_smc5859      reset:60              /*set the cpu to monitor mode and stack*/61              mrs r0, cpsr62              bic r0, r0, #0x1f63              orr r0, r0, #0xd664              msr cpsr, r065              ldr sp, =smc_stack_top(gdb)

到此gdb也能使用了,这样就可以使用qemu来学习a9架构或者其他架构的芯片了,省去了硬件连接的繁琐,对于学习来说是一种不错的方式。

1 0
原创粉丝点击