ARMはじめました

QEMUのARMであそぼうと思い、1から環境を構築すべく参考サイトを探していると、

  BishopエミュレータBeta2リリース

という、何ともうってつけの記事を発見したので、参考にさせていただきました。

Goal

あくまでもARMであそぶ事が目的なので、自前のバイナリが動く事の確認まで。

Cross-Toolchainのインストール

1からなので、まずは大工道具から。先のサイトより頂戴&参考にします。
今回の環境はfedoraの6なので以下の通りにyumしました。

 # vim /etc/yum.repos.d/pylone-jp.repo
(リポジトリの編集)
 # yum update
 # yum install gcc-3.4-arm-linux-gnu 
 # yum install gcc-4.1-arm-linux-gnu 

以下の様にしていろいろ確認。*1

 % arm-linux-gnu-gcc -v
 % arm-linux-gnu-as -v
 % arm-linux-gnu-objcopy -v

他、g++とgdbもありましたが、今回はとりあえずgccのみとしました。

QEMUのインストール

Bishop用にカスタマイズされたQEMUをインストールします。
まず注意点として、

  1. gcc-4.x以降ではビルド不可
  2. SDL必須

との事なので、事前に以下を行いました。*2

 # yum install compat-gcc-34
 # yum install compat-gcc-34-c++
 # yum install compat-libgcc-296
 # yum install compat-libstdc++-33
 # yum install sdl

そして、本体のインストール。これも先のサイトにソースが公開されているので有難く頂戴し、

以下のようにしてソースからのMake。

 % ./configure --target-list=arm-softmmu
 % make

これでクロス環境が整いました。

バイナリ作成

とりあえず、UARTにキャラクタを流すぐらいの簡単なものを作成してみます。
以下にコードを記します。

ldr r0,=0x50000000      /* UART0 コントロールレジスタ */
ldr r1,=0x3             /* 通信モードを通常(非IrDA)に、通信パラメータをN-1-8に 設定 */
strb r1, [r0]

ldr r0,=0x50000020      /* UART0 送信バッファレジスタ */
ldr r1,=0x41            /* 以下、'A'、'B'、'C'の順で送信 */
strb r1, [r0]
ldr r1,=0x42
strb r1, [r0]
ldr r1,=0x43
strb r1, [r0]

b .

これを以下のようにアセンブル、バイナリ変換します。

 % arm-linux-gnu-as boot.s -o armtst.bin
 % arm-linux-gnu-objcopy -O binary armtst.bin

実行!

作成したバイナリが正常に動作するか確認します。
まず、Bishopを実機同様に動作させるためのQEMUへの引数を確認します。

 % ./arm-softmmu/qemu-system-arm -M pe201b -serial stdio -kernel dummy -usbdevice keyboard -mtdblock nand-bishop.img
Option 指定 効能
-M pe201b pe201bをエミュレート
-serial stdio 仮想シリアルを標準入出力に
-kernel dummy カーネルイメージの指定
-usbdevice keyboard USBにキーボードを接続
-mtdblock nand-bishop.img mtd(Flash)にFSイメージファイルを指定

掲載されているカーネルイメージは"uImage"なのに、-kernelで実在しないファイル"dummy"を指定しているのは、

2.U-BootがLinuxカーネルを読みこみ

とあり、Bootloader(U-Boot)が"uImage"をロードするので、ただ単に-kernelオプションを明示的に指定しているだけだと思います。*3


さて、今回は掲載されているバイナリは一切使用せずに、自作バイナリをロードさせてみます。
上記のコマンドラインQEMUを実行すると、まず、

1.U-Bootがメモリに読みこまれて起動

されます。U-Bootのバイナリファイルはu-boot.binです。
従って自作バイナリを実行させるには、u-boot.binの代わりにarmtst.binを読み込ませれば良いわけですが、QEMUへの引数に見当たりません。

QEMUディレクトリ以下のファイルに直接定義されているのかと思い、漁ってみると、

% grep -rn u-boot.bin *
バイナリー・ファイルarm-softmmu/bishop.oは一致しました
バイナリー・ファイルarm-softmmu/qemu-system-armは一致しました
hw/bishop.c:226:    load_image("u-boot.bin", image_addr);
hw/gumstix.c:18: * # dd of=flash bs=1k conv=notrunc if=u-boot.bin
hw/gumstix.c:27: * # dd of=flash bs=1k conv=notrunc if=u-boot.bin

と、どうやら hw/bishop.c で直接読み込んでいる模様です。
このため、ソースを修正すればOKだと思いますが、今回は自作バイナリを"u-boot.bin"にリネームする方法を採ります。
いよいよ、自作バイナリを実行します。コマンドラインは以下のように最低限の指定としました。

 % ./arm-softmmu/qemu-system-arm -M pe201b -serial stdio 

が、実行すると以下のエラーを含むusageが表示されてしまいました。

 'disc_image' is a raw hard image image for IDE hard disk 0 

どうやらFS用のimageの指定が必須なようなので、適当にFlashイメージを作成します。

 % ./qemu-image create null.fs 1024 

実機コマンドラインに倣い、作成したFSイメージを指定して、再度実行してみます。

 % ./arm-softmmu/qemu-system-arm -M pe201b -serial stdio -mtdblock null.fs

しばらくしてQEMUのウィンドウが表示されると、仮想端末上にABCと表示されてハングするはずです。
が、ABCABCABC…と繰り返されてしまいます。
なぜだろう…WDTか?とデータシートを確認したところ、defaultで有効のようです。
アドレス0x53000000の0bit目をLowに設定し、WDTによるResetをOFFにし再度確認したところ、晴れて一回のみABCが表示されたあとハングしました。

まとめ

フリーで公開されているARMのエミュレータとtoolchainを使用して、かなり簡素ではありますが自作バイナリが動作する事を確認しました。
環境一式を頂いたサイトではH/Wの仕様が確認でき、かつ、SoC(SAMSUNG)のデータシートも入手できたため比較的スムーズに進められました。
これを機にARMの学習が出来ればと思います。*4

【参考サイト・文献】

修正

ソースコードコメントアウトが#から始まっていたので修正しました。

armでは#から始まるトークンはイミディエイトとなり、コメント文がオペランド扱いになっていました。

*1:asの-vは^Cで抜けなくちゃならないのはなぜ?

*2:libは必要かどうか不明だがとりあえず…

*3:本環境では未指定でもOKでした

*4:早く本家QEMUでSH4が正式に対応されないかなぁ