QEMU で Hello world を動かす試みは探してみるといくつか実施されています。
- ARM QEMU でベアメタルコードを動かす | Atelier Orchard
- Hello world for bare metal ARM using QEMU | Freedom Embedded
いずれも versatilepb モデルで実施されているので、vexpress や virt でもできるかどうか試してみました。toolchain は Linaro toolchain を使いましたが、外部関数を呼び出さないので baremetal toolchain でなくても使えます。
プログラムソース init.c、スタートコード startup.s、リンカスクリプト link.ld を用意します。
init.c は "Hello, world!" を一文字ずつ UART I/O に書き込むだけのプログラムです。
/* init.c */ static void print(const char *str) { while (*str) *(volatile unsigned char *)UART0_PTR = *str++; } int init() { print("Hello, world!\n"); }
link.ld は外部定義された START からセクション定義を行います。スタックを 0x800 byte 分空けて スタックポインタの開始位置 sp_top を定義します。
/* link.ld */ ENTRY(_start) SECTIONS { . = START; startup : { startup.o(.text)} .data : {*(.data)} .bss : {*(.bss)} . = . + 0x800; sp_top = .;
vexpress(aarch32) の場合
aarch32 とaarch64 で命令体系が変わるので、startup.s はそれぞれのものを用意します。aarch32 向けはスタックポインタに直接 sp_top を設定して init 関数を呼び出します。最後は無限ループです。
/* startup.s */ .global _start _start: ldr sp,=sp_top bl init b .
vexpress-a9 モデルの場合のビルド・実行例です。UART0 I/O と SDRAM がモデルで異なるので、コマンドラインで設定しています。
$ arm-linux-gnueabihf-as -mcpu=cortex-a9 -o startup.o startup.s $ arm-linux-gnueabihf-gcc -mcpu=cortex-a9 -c init.c -DUART0_PTR=0x10009000 $ arm-linux-gnueabihf-ld -T link.ld -defsym START=0x60010000 -o output.elf startup.o init.o $ arm-linux-gnueabihf-objcopy -O binary output.elf output.bin $ qemu-system-aarch64 -M vexpress-a9 -cpu cortex-a9 -nographic -kernel output.bin Hello, world!
vexpress-a15 モデルの場合は以下のようにします。
$ arm-linux-gnueabihf-as -mcpu=cortex-a15 -o startup.o startup.s $ arm-linux-gnueabihf-gcc -mcpu=cortex-a15 -c init.c -DUART0_PTR=0x1c090000 $ arm-linux-gnueabihf-ld -T link.ld -defsym START=0x80010000 -o output.elf startup.o init.o $ arm-linux-gnueabihf-objcopy -O binary output.elf output.bin $ qemu-system-aarch64 -M vexpress-a15 -cpu cortex-a15 -nographic -kernel output.bin Hello, world!
virt(aarch64) の場合
aarch64 向けのスタートコード startup64.s を用意します。sp は直接代入できないので、x0 を間接的に使います。
/* startup64.s */ .global _start _start: ldr x0,=sp_top mov sp,x0 bl init b .
virt モデルの場合の実行例です。toolchain は aarch64 のものを使います。
$ aarch64-linux-gnu-as -mcpu=cortex-a53 startup64.s $ aarch64-linux-gnu-gcc -mcpu=cortex-a53 -DUART0_PTR=0x09000000 -c init.c $ aarch64-linux-gnu-ld -T link.ld -defsym START=0x80000 -o output.elf startup64.o init.o $ aarch64-linux-gnu-objcopy -O binary output.elf output.bin $ qemu-system-aarch64 -M vexpress-a53 -cpu cortex-a53 -nographic -kernel output.bin Hello, world!
上記のソースは Makefile を使う形で github に置く予定です。
コメント
Good work!!!
can you give me example how to test 4 different program on different core with -pflash option.
Domo Arigatou Gozaimasu.
Umm.., sorry I’m not sure about how to treat parallel core directly with QEMU.
Maybe you’d better ask other open communities more deeply.
Thanks.