2013年2月25日月曜日

ARM QEMUでU-Bootを動かす

ブートローダの一種であるDas U-Bootは組み込みLinuxのブートにも良く使われていて、BeagleboardをいじっていたときにはAndroidを起動するときにカーネルパラメータを渡すのによくいじっていました。今回はそのU-BoolをQEMUで動かす練習。

まずはU-BootのFTPサーバからダウンロード。続いて解凍してコンフィギュレーションしてビルドする定番の流れです。
本稿執筆時点ではu-boot-2013.01.tar.bz2までリリースされていたんですが、u-boot-2010.12.tar.bz2以降では、ビルドが失敗したり、実行がうまくいかなかったりしたので、やや古いですが上記を選んでいます。コンフィギュレーションターゲットの対応とか、ツールチェインとの相性とかが原因かと思いますが、詳しくは調べてません。


さて、できあがったバイナリを確認。
u-bootがコンパイルされたバイナリで、さらにobjdumpでセクションギャップに0xFFをフィルした上でRAWバイナリにしたのがu-boot.binでしょうか。0xFFフィルは、一つのフェイルセーフですかね。NOPとかの有効な命令だと危なそうですし。0xFFフィルは、実際のFlashメモリ内の各ビットの初期値が1であるため、無用な書き込みを減らして効率化と書き込み回数の温存を図るための「おまじない」らしいです(参考)。コメント欄でのご指摘ありがとうございました。
早速QEMUで実行してみます。
で、U-Bootのコマンド待ちになるわけですね。
printenvで環境変数一覧を表示できます。bootargsはカーネルパラメータですね。コマンド一覧はhelpで表示可能です。

で、このU-Bootのバイナリに、前回作ったinitのバイナリをマージします。そのために、リンカスクリプトを少し細工してビルドし直しておきます。
先頭アドレスの位置が0x10000から0x100000になっています。
これをmkimageコマンドを使ってU-Bootがロード可能なフォーマットに変換します。
で、先ほど作ったU-BootのRAWバイナリと一つのイメージの中にまとめます。

このイメージをQEMUで実行するわけですが、その前にマージしたinitのイメージのブートアドレスを調べておきます。
まず、statでu-boot.binのサイズを調べます。それに65536を足して16進形式で出力しています。これは、QEMUが-kernelパラメータで指定されたイメージを65536、すなわち0x10000だけオフセットした場所に配置するからです。catコマンドでtest.uimgをu-boot.binの直後に配置したので、その先頭は0x10000にu-boot.binのサイズを足したアドレスになるということです。
ではイメージを起動してみます。
起動前に調べた0x253DCの位置にあるはずのinitのイメージを確認してみます。
よさげです。ではブート。
起動しましたー!

参考情報

Using QEMU for Embedded Systems Development, Part 3 - LINUX For You
U-boot for ARM on QEMU - Balau

2013年2月24日日曜日

ARM QEMUでベアメタルコードを動かす

これまで、ARM用QEMUでHello World!したりlinuxカーネルを動かしたりするのをやってみました。そのとき使ったのがqemu-armというツール。Hello World!の話でQEMUをインストールするときに
./configure --target-list=arm-softmmu,arm-linux-user
という風にコンフィギュレーションしたわけですが、arm-linux-userを含めることでビルドされるのが、qemu-armで、ユーザモードのプログラムを動かすツールです。一方のarm-softmmu、これがシステムモードのプログラムを動かすためのツールをビルドするらしいです。そのツールがqemu-system-armです。ユーザモードのプログラムでは、mainのようなエントリポイントからプログラムが始まるわけですが、システムモードではリセットベクタからプログラムの実行がスタートします。この前はlinuxカーネルを動かすのに使いましたが、今回はリセットベクタからスタートする小さなコードを書いてみます。

Hello World!を動かしたときにはarm-none-linux-gnueabi-というツールを使いましたが、今回はベアメタル用のプログラムをコンパイルするため、くarm-none-eabi-を使います。まずはそのインストール。
次にQEMUのCPU種を調べます。ソースのアーカイブを展開したディレクトリの下のhwに移動して、エミュレーションターゲットとして用いるVersatilePBのCPUを特定してみます。
cpu_model = "arm926"だそうです、ARM9っすね。

続いて、ツールチェインの対応を確認。
(`・ω・´) おk。

んで、とりあえずHello World!を出力してみようと思いますが、システムモードで動かすので、printfのようなライブラリ関数を使わずにUARTに直接キャラクタを叩き込むなんてこともできます。

UARTのアドレスは
となっているので、とりあえず0x101f1000に送り込んでみます。

まずはCソースinit.cの作成。
UARTのアドレスにvolatileを指定することで、コンパイラによる最適化を防ぎます。普通、コンパイラは冗長なアクセスは省略するのですが、volatile指定されたアドレスにはそれが適用されません。UARTの場合、キャラクタ数だけ書き込みを行う必要がありますが、普通のメモリアクセスを仮定して最適化するとすれば、最後の一回の書き込み以外は、結局上書きされてしまうものなので、コンパイラは不要なものと判断します。組み込みの世界では、こういうことを気にしなければならないことがしばしばありますね。

で、ユーザプログラムなら何も考えずにmain()を実装すれば自動的にそれをエントリポイントとして実行してくれるわけですが、 リセットベクタから始まるプログラムの場合、最初にどの関数に飛ぶかを指定しなければなりません。より正確に言えば、所望の関数へジャンプするコードを書く必要があるということです。それが、次のアセンブラコード、startup.sです。
私は昔、MIPSのアセンブラを触ったことがあるのですが、MIPSにはJALという命令があって、シンボルへのジャンプに使ったのを思い出しました。Jump And Linkという意味で、現在の実行箇所をリターン先としてスタックに積んだ上で、指定のシンボル(関数)へジャンプするというものです。上記のARMアセンブラコードのBLはおそらくそれに相当するものだと思います。Bというのは分岐の意味のBranchでしょうか。その前のLDRが、sp_topというシンボルで指定するスタックポインタをSPレジスタにロード、後のBはその場でループといったところでしょう。

最後に、これらをまとめるリンカスクリプト、
ENTRY(_Start)でリセットベクタのエントリポイントを指定。startup.sの_Startシンボルを指定しています。0x10000から初めて、.test、.data、.bssセクションを置いて、0x500だけ離して、スタックポインタを指定しています。この0x500は、下に伸びるスタックポインタのためのマージンといえますね。今回は関数を一つジャンプするだけなので、大きなスタックは必要ありません。さて、ビルドします。普段はMakefileで自動化されてて見えませんが、一つ一つコマンドで、コンパイル、リンク、バイナリの変換を行っていきます。
ELFフォーマットで作られた実行バイナリを、ベアメタルで実行できるようにRAWバイナリに変換しています。
では実行。


参考情報

Using QEMU for Embedded Systems Development, Part 2 - LINUX For You
Hello world for bare metal ARM using QEMU - Balau

2013年2月18日月曜日

ARM QEMUでlinuxカーネルを起動

QEMUでARMの話の続き。

linuxを動かしてみたいと思います。


1. linuxカーネルのビルド

kernel.orgからダウンロードしてビルドします。3.xもありますが、今回は2.6を選んでみました。
ここでコンフィギュレーションは次のようにしておきます。 
で、ビルド。
ビルドできたらイメージを確かめてみます。

2. とりあえずQEMUに放り込んでみる

ここでQEMUのビルドのとき、--target-listオプションにarm-softmmuを仕込んでおいた効果が出ます。linuxカーネルを動かすときはqemu-system-armコマンドを使います。
私はx11vncを使っているので、-vnc :0オプションでvncに出力して見ています。linuxデスクトップで試している場合はナシでOKです。それから先にvncのセッションが存在している場合も良くない場合があるので、止めておきます。x11vncなら下記です。

実行してみると、kernel panicで落ちています。
ということで、rootを指定しろ、と言われます。

3. ダミーファイルシステムの作成

ルートファイルシステムに指定するためのダミーを作成します。適当なディレクトリで、下記のようにエディタでcコードを書いてください。

続いてコンパイル。
ここで-staticにしておくのがミソのようです。
cpioコマンドでルートファイルシステムに変換します。

で、これをルートに指定して実行します。-kernelオプションの引数は正しいカーネルの位置を指定してください。

すると、cコードに書いたとおり、Hello World!を出力する様子が確認できると思います。





トラブルシューティング。



◆実行時

oss: Could not initialize DAC
oss: Failed to open `/dev/dsp'
oss: Reason: No such file or directory
oss: Could not initialize DAC
oss: Failed to open `/dev/dsp'
oss: Reason: No such file or directory
audio: Failed to create voice `lm4549.out'

下記を入れてから実行します。

----
Unimplemented flash cmd sequence

これは、 grepしてみるとkernelではなくQEMUのhw/pflash_cfi01.cが出していることがわかります。この辺で調べてみたところ、どうやらQEMUのバージョンが古いのがダメらしい。このブログの前回のQEMUでARMの記事で、当初1.3.1を入れたとか書いてたりしてたんですが、1.4以降を入れる必要があったようです。ここで最新のReleaseをDLしましょう。


参考情報

Using QEMU for Embedded Systems Development, Part 1
Compiling Linux kernel for QEMU ARM emulator 
Architectures/ARM/HowToQemu

2013年2月15日金曜日

APCのuzImageって何だ?

先日、APC8750のイメージを焼く話を書いたんですが、そのときAPCのサイトから落としてきて解凍したzipアーカイブのファームウェアの中に、uzImageっていうファイルがあったんですね。linuxイメージって言ったら、vmlinux、vmlinuz、zImage、uImageとかじゃないですか。大雑把に言うと、実行形式のvmlinuxをzip圧縮してzImageができ、それをU-bootでブートできるように手を加えたのがuImageだと。ググってみると、ざっとそんなことがわかったりしますが。

だから、、uzImageは?なんとなく「zip圧縮されたU-boot用のカーネルイメージ」っていう気がしますが、そもそもuImageも中身のカーネルはzip圧縮されてるし・・・っていう。ね。

なので、ちょっとだけ調べてみます。

ふむ。fileコマンドさんがおっしゃるには、U-boot用のイメージのようですが(信頼できるかわかりませんが)。

別の用途のために数日前にソースビルドしたarm用のlinuxカーネルがあるので、 こちらも同様に見てみると、、

似ている。

とりあえずAPCのuzImageはuImageなんだと思います。

2013年2月13日水曜日

ARM QEMUでHello World!


1. QEMUのインストール


パッケージでもOKですが、ためしにソースビルドしてみます。

2. ARMコンパイラのインストール


Sourcery CodeBenchのARMコンパイラをインストールします。

一応、インストール確認として、

3. ソース作成、コンパイル、実行


テキストエディタでソースコードを作成します。
内容は、
続いてコンパイル。
出力されたバイナリを確認。
test: ELF 32-bit LSB executable, ARM, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.16, not stripped

実行。
"Hello World!"が出力されればOKです。



さて、ここからはトラブルシューティング編。上記インストール手順の実施中に直面したエラーたちと、その対策です。

1. configure時


Error: zlib check failed
Make sure to have the zlib libs and headers installed.


zlibをインストール

Error: pkg-config binary 'pkg-config' not found

pkg-configをインストール

glib-2.12 required to compile QEMU

glibのインストール

    さらにglibのconfigure中、、

    configure: error: Package requirements (libffi >= 3.0.0) were not met:

    No package 'libffi' found
   
    Consider adjusting the PKG_CONFIG_PATH environment variable if you
    installed software in a non-standard prefix.
   
    Alternatively, you may set the environment variables LIBFFI_CFLAGS
    and LIBFFI_LIBS to avoid the need to call pkg-config.
    See the pkg-config man page for more details.


    → libffiのインストール

    configure: error:
    *** You must have either have gettext support in your C library, or use the
    *** GNU gettext library. (http://www.gnu.org/software/gettext/gettext.html


    → gettextのインストール

    configure: error: Package requirements (libpcre >= 8.13) were not met:

    No package 'libpcre' found
   
    Consider adjusting the PKG_CONFIG_PATH environment variable if you
    installed software in a non-standard prefix.
   
    Alternatively, you may set the environment variables PCRE_CFLAGS
    and PCRE_LIBS to avoid the need to call pkg-config.
    See the pkg-config man page for more details.

    → libpcreのインストール
        libpcreのconfigure中、、

        ** Cannot --enable-pcregrep-libbz2 because bzlib.h was not found
        → libbz2のインストール

2. make時


(cd /home/hoge/foo/bar/qemu-1.3.1/pixman; autoreconf -v --install)
/bin/sh: 1: autoreconf: not found
make: *** [/home/kim/work/qemu/qemu-1.3.1/pixman/configure] エラー 127

autoconfのインストール

configure.ac:75: error: possibly undefined macro: AC_PROG_LIBTOOL
  If this token and others are legitimate, please use m4_pattern_allow.
  See the Autoconf documentation.
autoreconf: /usr/bin/autoconf failed with exit status: 1
make: *** [/home/hoge/foo/bar/qemu-1.3.1/pixman/configure] エラー 1
make: *** ファイル `/home/hoge/foo/bar/qemu-1.3.1/pixman/configure' を削除します

libtoolのインストール



参考情報

Using QEMU for Embedded Systems Development, Part 1
Compiling Linux kernel for QEMU ARM emulator 



追記

2013年2月18日 インストールするQEMUのバージョンを1.3.1から1.4.0に修正。

VMwareのHDDを拡張

VMwareに入れたLinuxでAndroidのソースなんかをビルドしようとすると、ソース本体だけで何GBってあるので、repoが容量不足で失敗、うまく言ってもビルド時に失敗、なんてことがあります。
そんなときのためのHDD拡張手順をメモっておきます。
 

1. GPartedのイメージを入手


このへんからLive CDのISOイメージをダウンロードします。CDには焼かなくてOKです。

2. 仮想マシンの設定を編集


[仮想マシン設定の編集]メニューから、[ハードディスク(SCSI)]エントリを選び、[ユーティリティ]→[拡張]へ進んでHDDを必要な容量に拡張します。このとき、仮想マシンが「パワーオフ」状態である必要があります。
次に、[CD/DVD(IDE)]エントリを選び、[ISOイメージファイルを指定する]をチェックして、ダウンロードしたISOファイルを指定します。

3. vmxファイルの編集


HDD拡張する対象の仮想マシンのイメージが保存されているフォルダにあるvmxファイルをテキストエディタで開きます。末尾に、 bios.bootDelay="5000" などと追記します。OSを起動したときにBIOSセットアップに入るキーを押すための待ち時間をミリ秒で指定しています。

4. 起動デバイス順をBIOSで設定


HDDより先にCD-ROMを読みに行くように指定してください。これを設定することで、GPartedのISOが起動します。



5. GParted起動


ブートメニューが表示されたらGParted Liveを選びます。


6. GPartedでパーティション操作


当該のパーティションを拡張します。GPartedの詳しい操作は省略します。操作と適用が終わったら、[Exit]から[Shutdown]します。

7. OSを起動


BIOSの起動ドライブの順をいじる等して、HDDからブートするようにします。OSが起動したら、dfコマンドとかで容量が増えたことを確認してください。



APC8750を起動する

APC8750に火入れしてみます。

私なんかはBeagleboardでの経験が染み付いていて、このボードもブートローダ、カーネルイメージ、ファイルシステムを入れたSDカードを挿して起動するものと思っていましたが、Manualページを読んでみると、
  1. キーボードとマウスをUSBコネクタに挿す
  2. VGAかHDMIのモニタをつなぐ
  3. スピーカとかイヤホンがLine-outにつなげられる
  4. EthernetケーブルをLANポートにつなぐ
  5. ACアダプタをDCジャックにつなぐ
  6. 電源ボタンを押す
となっている。つまり、SDカード不要なのです。
とりあえず3と4はスキップで、やってみました。

まず最初に現れる起動ロゴ。


しばらく待つとAndroidのHOME画面が現れます。結構古い。マウスで操作できます。


アプリメニュー。モアレてすみません。


SettingsからAbout deviceを開いてみたところ。


さて、このボードにはSDカードスロットが付いてるわけですが、何でもファームウェアアップデートができるそうです。これを使ってオンボードフラッシュにあるOSを書き換えられるわけですね。
APCのLibraryページに、"APC System Software"というzipアーカイブがあります。ダウンロードして開いてみると、中にはu-boot.binやらuzImageといった、なんともそれっぽい名前のファイルが鎮座しています。READMEによると、これらZipの中身一式をSDカードに入れて、スロットに挿してボードを起動すると、ファクトリリセットされるとか。早速最新版(v1.0.2)のアーカイブで試してみます。

SDスロットに入れて電源ON。最初のブートロゴの次に、中央にプログレスバーがある青い画面が表示されます。


数分で書き込み完了。インストレーションメディアを外せって出ているので外してみると、なんと電源を落とさなくてもそのまま再起動に入ります!


で、起動してバージョン確認してみたところ。変化なしです。最初から最新版だったんですね。。。


2013年2月11日月曜日

APC8750 開封の儀

VIAのAPC8750を購入したので、Unboxingしたいと思います。先日書いたように、本当はRock狙いだったんですが、ちょっとした勘違いが生じ、8750となりました。$49でございます。

まずは荷姿。台湾からEMS便で$16です。発注から三日くらいで届きました。だいぶ早いです。



外袋を開けると、エアキャップに包まれたダンボールのパッケージ。


パッケージの底面にInstruction & SoftwareのURLが書かれています。QRコードもなんかおされ。


パッケージを開けた様子。まず最初に目に入るのはACアダプタと"APC a bicycle for your mind"ステッカー。APCのロゴが書かれている部分は仕切りになっています。


手前面はこんな感じでATXパネル側のコネクタ配置がイラストでかかれてます。これまたかわいらしいデザイン。


中身を取り出してみる。ACアダプタは9V出力のセンタープラスです。


仕切りの下には、袋に包まれたNeo-ITXのボード本体。いい色してます。


そしてボードの下にATXパネルです。


ボード本体を袋から取り出す。A面


B面。


WM8750チップです。


Rockと比べると、LAN+USBコネクタやオーディオコネクタがある分、厚みが出てしまっているのが気になります。ARM11コアですし、これから買う方はCortex-A9のRockをおすすめします。また、Rockとは電源ジャックの位置が逆なんですね。

2013年2月7日木曜日

Raspberry PiでAndroid

とりあえずプレビルトのAndroidイメージをRaspberry Piで走らせてみます。

環境はLubuntu 12.10 32bitです。

1. イメージのダウンロード


wikiaAndroid Pi Wikiのページから、 CyanogenMOD 7.2イメージをダウンロード。

2. 解凍


7zファイルを解凍。コマンドのインストールはこちらを参照。

3. SDカードへの書き込み

2GB以上の容量があるSDカードを用意して、USBのカードリーダーとかで接続します。
ddコマンドを使ってimgファイルを書き込みますが、書き込み先のデバイスファイルは、dfコマンドとかdmesg | tailとかを使って確認しておいてください。私の環境では/dev/sdcでした。

4. 起動


イメージを書き込んだSDカードをRaspberry Piに挿し、HDMIで画面接続します。microUSBを接続すると電源が入り、起動します。





あとはキーボードとマウスとEthernetをつなげて夢が広がるというわけです。


Linuxで7zファイル(7zip)を解凍する

最近、仕事でも7z圧縮のアーカイブをもらうことがよくあります。WindowsならLhaforgeとかで解凍できますね。

Laspberry PiにAndroidを載っけようと思ってこちらのサイトを見ていたら、イメージが7z圧縮で配布されてるんですね。tar.bz2とかじゃなく。まぁWindowsマシンにダウンロードして解凍したあと、Win32 Disk ImagerとかでSDカードに焼いてもいいんですが、せっかくなのでLinuxでの解凍方法を調べました。

といっても、手順はいたって簡単です。以下、Lubuntu 12.10での手順です。


で、


これだけ。

eオプションは解凍(Extract)の意味です。圧縮(Archive)はa。

参考情報


How to use 7zip on Linux command Line

2013年2月4日月曜日

Lubuntuでvncサーバーを立ち上げる

私はWindowsをメインで使ってますが、遊びでいろいろビルドする用途でLinuxマシンも一台動かしています。安価なMini-ITXのオンボードCPUマシン、ASUSのC60M1-Iに、Ubuntu派生の軽量LinuxディストリビューションのLubuntu 12.10を入れて使ってます。マシンごとにマウスとキーボードを用意するのは厄介なので、もちろんSSL接続。でも、デスクトップにオートアップデートのダイアログが出てくることもあるので、それだけではいまひとつなときもあります。

そこでLubuntuにvncを入れたので、メモっておきます。

1. パッケージのインストール



2. パスワードの設定



3. ファイアウォールのポート開放


必要に応じて、

などでポート開放。使用している環境に応じた方法で設定してください。

4. 起動


実際に、WindowsマシンからTightVNCなどのvncクライアントを使ってアクセスしてみましょう。

5. 自動起動設定

上記コマンドをしなくても、マシンが起動したときに自動的にvncサーバーが立ち上がるように設定します。まず、

など、エディタで開き、ファイル末尾に下記を追記します。

これで再起動してもすぐvnc接続ができるようになります。


参考情報


Setup VNC Server for Lubuntu


2013年2月1日金曜日

2013年 最近気になるボードたち

2012年の Raspberry Pi ブームも覚めやらぬ昨今、とりあえずクリスマスにUKから取り寄せてはみたものの、ゆっくりいじる時間をなかなかとれずにもどかしい思いをしています。

Mini-ITXで10,000円を切るオンボードCPUのPCも最近たくさん出ています。Lubuntuなんかを入れてちょっと遊ぶにはいい感じだったりして、いろいろコマンドをたたいているとあっという間に寝る時間になってしまいますね。

でも、2013年もまだまだ面白そうなボードが目白押しです。


1. Gizmo

http://www.gizmosphere.org/

AMD Embedded G-Series APU に DDR3 1GHz、SATA搭載と、組み込みというよりファンレスPCに近いボードですが、電源はATXではなくDC12Vに4インチ(10.16cm)四方という取り回しのよさは必見。車載用なんかにももってこいだと思います。199USDで今後発売予定。

2. Rock

http://apc.io/products/rock/

台湾APC(VIA)からは、79USDぽっきりのAndroid 4.0ボード。Cortex-A9シングルの800MHzにDDR3 512MB。HDMI、VGA、各種USBにEthernetなど標準的なI/Oがそろって、Neo-ITXの小ぶりな一枚にまとまっています。
赤い基板もいいですね。Beagleboardを思い出します。


3. ORIGEN 4

http://www.origenboard.org/

Samsung Exynos 4 Quad Cortex-A9 core 1.4 GHz に1GHz DRAM を積んだ、スマートフォンのリファレンスデザインのようなボード。何より魅力的なのは多彩なペリフェラルで、7インチLCD (1024 x 600) に 静電タッチパネル、カメラやジャイロセンサ、GPSなどの外部モジュールが追加できるという拡張性に夢が広がります。お値段はベースボード199USD~。Gizmoと同じ値段でも、だいぶ性格が異なっていて面白いですね。サイズは 140 x 195mm、A5用紙より一回り小さいくらいです。

ちなみに、Exynos 5 Cortex-A15 dual core 1.7 GHz を積んだ Arndale Board という上位機もあります。249USD~。

4. ARMBRIX Zero

http://www.armbrix.com/

Arndale と同様、Samsung Exynos 5 Dual Cortex-A15 に 2GB DDR3 を積んだボード。95 x 85mm の小型ボードにまとめて、145USDです。Android 4.1も動作。デリバリーにやや不安はありそうですが、かなりお得な一枚と言えそうです。


個人的にはGizmoが大本命。発売が待ち遠しいです。それまでは Raspberry Pi で遊んで時間をつぶしますかねぇ。