Raspberry Piベアメタルプログラミングは、microSDをいちいち抜き差ししないといけないのが面倒です。
SDカードを使わない方法としては、ネットワークブートやUSB接続でホストをマスストレージに見せかけるなどの方法もあるようですが、GPIOなどを操作しない場合にはエミュレータが有効です。
今回Raspberry PiのベアメタルにMicroPythonのREPLを追加するにあたって、Linux上でQEMUを使ってみました。
ARMのバイナリを動作させられるQEMUは、Ubuntuのパッケージで用意されていますのでインストールは簡単です。
Raspberry Piのバイナリを動かす場合は、
qemu-system-arm \ -kernel firmware.elf \ -cpu arm1176 \ -M versatilepb \ -m 256 \ -no-reboot \ -nographic \ -monitor null \ -serial stdio \ -redir tcp:10022::22
というようにすれば動作します。これはMakefileの中にもrunというターゲットで入れてあります。
ただ、QEMUを使う場合にはMini-UARTはうまく動作させるのは難しいようです。
ですので、QEMUの場合はMiniでないほうのUARTを使う必要があります。
今のところ、uart-qemu.cに通常のUARTとMini-UARTの両方を入れて、
#if 1 // 0ならMini-UART 通常のUARTのコード #else Mini-UARTのコード #endif
というやり方で選択できるようにしてあります。
QEMU上で動作しているARM用バイナリは、クロス開発環境用のGDBでデバッグすることができます。
まず、QEMU上でのバイナリは”-s -S”オプションをつけて起動します。
$ qemu-system-arm -kernel build/firmware.elf -cpu arm1176 -M versatilepb -m 256 -no-reboot -nographic -monitor null -serial stdio -s -S
次に、同じマシンの別のターミナルからGDBを起動します。
そして、targetコマンドで「remote localhost:1234」を指定します。
$ arm-none-eabi-gdb -q build/firmware.elf Reading symbols from build/firmware.elf...done. (gdb) target remote localhost:1234 Remote debugging using localhost:1234 0x00008000 in start () (gdb)
あとは普通にGDBのコマンドが使えます。
よく使うのは
・l 現在位置のソースを表示
・n 次の行(関数の中には入らない)
・s ステップ(関数の中に入る)
・c continue
・b file:num fileのnum行をブレークポイントに
・b function functionの先頭をブレークポイントに
・p/x var 変数varを16進数表示(&varや*varという表現も可能)
・awatch var 変数varが読み書きされたらブレーク
あたりです。
以下に今回参考にしたサイトを挙げておきます。
piでベアメタルプログラミング – bobuhiro11's diary
RaspberryPi/kernel/src-qemu at master · richcole/RaspberryPi
QEMU ARM で遊ぼう
gdb の使い方・デバッグ方法まとめ
ちなみにQEMUでRaspbianを起動することもできますが、それにはQEMU用にビルドしたカーネルが必要です。
ビルド済みカーネルや起動方法は下記のGitHubにあります。
コメント