Olimex CS-E9302日記 - hello 作成

とりあえず hello を作ってみる。

全体の手順
わたしの環境では、LANが使えない。従ってプログラムの転送が少し面倒になる。全体の手順は以下の通り。
(1)hello のクロスコンパイル
(2)hello コマンドを入れてルートファイルシステムを作る。
(3)RedBoot 経由でルートファイルシステムをボードのFlashに書き込む。
(4)ボード再起動
(5)ログインしてhello 実行

まずクロスコンパイラの導入
ボード付属CDのarm-linux-gcc-3.4.1.tar.bz2 を使う。arm用にコンパイル済みのgccパッケージである。(なお付属CDには gcc-4.0.2 も入っている。3.4.1にしたのはなんとなく。)

$ cd /
$ su
# tar jxf arm-linux-gcc-3.4.1.tar.bz2

これで /usr/local/arm 以下に gcc その他が展開される。gccコンパイラなどの名前は、arm-linux-gcc。パスを通しておく。

$ export PATH=/usr/local/arm:$PATH

hello の作成
(注)共有ライブラリが使えないのでstaticリンクする。

$ vi hello.c
#include <stdio.h>
int main(){
  printf("hello\n");
  return 0;
}
$ arm-linux-gcc -static -o hello hello.c

ルートファイルシステムの作成
付属CDに入っているルートファイルシステムを流用する。

$ cp /mnt/cdrom/linux-2.6\ images/ramdisk.gz .
$ gunzip ramdisk.gz

これをループバックでマウントする。

$ mkdir initrd
$ su
# mount -o loop ramdisk initrd

次に、hello をルートファイルシステムにコピーする。
その前に、要らないファイルを消す。(サイズが厳しいので)

# rm initrd/Noise.wav
# rm initrd/funcky.mp3
# cp hello initrd/bin
# chmod 755 initrd/bin/hello

最後にアンマウントして圧縮。

# umount initrd
# gzip ramdisk

(参考)「組み込みLINUXシステム構築」8.6章

続いてルートファイルシステムをボードに書き込む。そのためにRedBootのコマンドモードに入る。
コマンドモードの入り方
(1)ボードの電源を入れる。
(2)起動中にCtrl-Cを押す。

...(起動中)
== Executing boot script in 5.00 seconds - enter ^C to abort
^C
RedBoot>

ルートファイルシステムの書き込み先のアドレスを確認する。

RedBoot> fis list 
Name        FLASH addr  Mem addr    Length    Entry point
...
ramdisk.gz  0x60A40000  0x00800000  0x00300000  0x00800000
zImge       0x60D40000  0x00080000  0x00140000  0x00080000

ramdisk.gz 領域のサイズは、0x300000=3145728バイト。
一方、先ほど作った ramdisk.gz のサイズは 2746991バイトだったで、上書きしても大丈夫。<br>

(参考) RedBoot のマニュアル fis の説明

ルートファイルシステムをFLASHに書き込む。
めちゃややこしいが、こうやるらしい。
まず、先ほど作った ramdisk.gz をボードのRAMにアップロードする。

RedBoot> load -r -b 0x00800000  -m xmodem  
CCC      ← ボード側RedBootが受信待ちになっている。

別のX端末で送信コマンドを発行する。

↓ Kermit を実行してるのとは別のX端末
$ sx /home/homerun/ramdisk.gz < /dev/ttyS0 > /dev/ttyS0 
Sending ramdisk.gz, 22575 blocks: Give your local XMODEM receive command now.
Xmodem sectors/kbyte sent: 0/0kRetry 0: NAK on sector   
...
Xmodem sectors/kbyte sent: 22161/2770kRetry 0: NAK on sector ← ここまで10分くらい
Bytes Sent:2747008  BPS:5571

Transfer complete   ← 転送成功

もとのKermitの画面のほうを見ると転送が終了している。

... Row file loaded 0x00800000-0x00a9ea6e, assumed entry at 0x00800000  云々...
RedBoot>

転送終了。

(参考) RedBoot のマニュアル loadの説明
kermitとsxの使い方

次に、RAM上の ramdisk.gz を FLASH に書き込む。

RedBoot> fis write -f 0x60A40000(*注) -b 0x00800000 -l 0x300000  ← -f アドレスに注意
* CAUTION * about to program FLASH
   at 0x60a40000..0x60d3ffff from 0x00800000 - continue (y/n) ? y ← アドレスが間違ってないことを確認してyを入力
... Erase from 0x60a40000-0x60d40000: .....
... Program from 0x00800000-0x00b00000 at 0x60a40000: .....
RedBoot>

(*注) fis write の -f アドレスは、fis list で確認した各ボードの値入力すること。間違えないこと。間違って、他の領域をつぶすとボードが起動しなくなる。(たとえは、RedBootを破壊したり、FLASHの情報領域を破壊したりとか、、、→ こうなるとJTAG接続でFLASHを再構築しないといけない)

(参考) RedBoot のマニュアル fis writeの説明

以上で書き込み終了。再起動する。
再起動は、ボードのリセットボタン(RSTNと刻印のあるボタン)を押すか、

RedBoot> reset
とする。

起動後ログイン。hello が入っていることを確認。

~ # ls -al /bin/hello
-rwxr-xr-x  1 root root  510927 Jul 14 2008 /bin/hello
~ #

hello の実行

~ # /bin/hello
hello
~ #

上の転送では、Kermitと別のX端末の2つの端末を使ったが、Kermitをエスケープすると、1つの端末でも送信可能である。

RedBoot> load -r -b 0x00800000  -m xmodem  
Ctrl+\c   ← Kermitのエスケープを入力
C-Kermit>  ← カーミットのコマンドモードに戻る。
C-Kermit> !sx /home/homerun/ramdisk.gz < /dev/ttyS0 > /dev/ttyS0 ← 送信コマンド発行
Sending ramdisk.gz ...
...
Bytes Sent:2747008  BPS:5571
Transfer complete 
C-Kermit> c  ← 再度ボードに接続する
Row file loaded 0x00800000-0x00a9ea6e, assumed entry at 0x00800000  云々...
RedBoot>