(注意)このブログは本家のほうの文章部分のみの転載です.ソースコードの配布,画像などについては本家のほうを参照してください.文章中のリンク先は面倒なのですべて本家のほうに変換してしまっているのでご注意ください.

ここのところOSC関西OSC名古屋に出展したが,やっぱし実機で動いているとインパクトあるので,ボードコンピュータへの移植を進めたいなあと思っていたのだがちょっと時間がとれたので進めてみた.ようやく第一段階にたどりついた感じ.

まずはターゲットボードの選定なのだけど,いろいろ探したのだけど,秋月電子H8/3069Fネット対応マイコンLANボード(完成品)というのに決めた.理由は以下.
  • なんといっても安い.(完成品だと3750円,キットだと3400円.これなら中学生や高校生でも買える)
  • 完成品の形で売っていて,シリアルコネクタが実装済みなので,そのまま使える(半田づけが完全に不要).(もちろん,キットで買って自分で組み立てれば安く済む)
  • フラッシュ書き換え回路が実装されているので,ROMライタなどを使わずにシリアル経由でフラッシュROMを書き換えられる.(フラッシュをとばしても安心)
  • H8は巷に書籍や資料がたくさんある.日本語資料も豊富.(これは,中学生にはとても嬉しいはずだ.英語資料だと中学英語の知識で読めるかどうか微妙なので)
  • 内蔵ROM,内蔵RAMの容量がそれなりにある(ROM512KB,RAM16KB).H8/3048だとRAMが4KBでいろいろやるにはちょっと不安.
ちなみに電源アダプタは別売りなので,5Vのやつを一緒に買う必要があります.これは秋葉原の秋月の店舗で買うなら,適当なのを一緒に買いましょう.

買ってから気がついたのだけど,付属のCD-ROMにフラッシュROM書き換えソフトがついているのだけど,これがCのソースで配布されていて,FreeBSDでもあっさりコンパイルできて動作した.なのでWindowsに頼らずに,完全にFreeBSD上で開発ができます(これはぼくにはとても嬉しい).

ちなみに秋月でもうひとつ,SH2の似たようなボードがあってそっちも候補だったのだけど,フラッシュROM書き換えソフトがWindows用なのでそれを使わないとならない.まあブートローダーだけ焼いてしまえばあとはOS開発では使うことはないのだけど,ちょっとイマイチではある.(実はそのSH2のボードも一緒に買ったのだけど,最終的に上記の理由が決定打になってH8ボードをターゲットに決めた)

で,まずはクロスビルド環境の作成なのだけど,まあこれは付属のCD-ROMにtoolchainが一式が入っているのだけど,当然ながらWindows用かLinux用になってしまう.やっぱしFreeBSD上で開発したいし,まあクロスコンパイラくらい自分で用意したいというのもあるので,いつもどおりbinutils+gccの組合せで,クロスビルド環境を構築する.

OSの起動には,ブートローダーをどこかから持ってきて動かして,OSはシリアル経由でダウンロードして動かす,という構成が開発には都合がいい.ブートローダーなのだけど,eCos付属のRedBootというのがH8に対応しているらしい.

ということで当初はRedBootを移植する予定だったのだけど,まあ結論から言っちゃうとRedBootは使わずに自前でブートローダーを作成することにしました.

なぜかというと,RedBootってC++で書いてある部分があるのでC++のクロスコンパイラが必要になる.しかしgccのクロスコンパイラ作成時にc++有効にすると,ライブラリがなんか必要になってしまうようで,newlib入れたりとかいろいろ試したのだけどうまくクロスコンパイラが作れなかったのよ.c++を外すと簡単にコンパイラが作れるのだが.

で,たとえこれでなんとかc++のクロスコンパイラを用意したところで,この文書を読んで試すひとが同じようにはまったりしてもつまらないし,なんかクロスコンパイラ作成にひと苦労ってものなんだかな~って気がするし,組み込みOS作るならブートローダーくらい自作しても面白いんじゃないかと思う(OSの動作だけでなく,ブートストラップの勉強にもなる)ので,自作してみることにしました.ちょうどCQ出版からブートローダーの本が出たことだし.(CQは,相変わらず良い本を出すね!みんな買いましょう!)

で,話がそれたけど,まずはクロスビルド環境の構築なのだけど,H8用のクロスのbinutilsとgccは以下で構築できた.ちなみに環境はFreeBSD-6.2ね.

■ binutils-2.19 をインストール

% ./configure --target=h8300-elf --prefix=/usr/local --disable-nls
% gmake

# gmake install



■ gcc-3.4.6 をインストール

% cd gcc-3.4.6
% setenv SHELL /usr/local/bin/bash (シェルがbash以外の場合)
% ./configure --target=h8300-elf --prefix=/usr/local --disable-nls --disable-threads --disable-shared --enable-languages=c
% gmake

# setenv SHELL /usr/local/bin/bash
# gmake install

あとフラッシュROM書き換え用のアプリなのだけど,h8write というのがCD-ROMに付属しているのだけど,これはネット上のOpen SH/H8 writerで配布されていて,しかもFreeBSDでも動くらしい.なのでいちおうネットのほうから最新版を持ってきて,以下の修正をしてビルドした.

% gcc h8write.c -o h8write

これであっさりビルド完了.

--- h8write.c~ Mon Aug 24 13:45:33 2009
+++ h8write.c Mon Aug 24 13:45:52 2009
@@ -1,6 +1,6 @@
-#define LINUX
+#undef LINUX
#undef Solaris
-#undef FreeBSD
+#define FreeBSD
#undef Win32
/*******************************************/
/* EEPROM write program to H8/300H */
@@ -42,7 +42,7 @@
#define RSLINE "/dev/ttyS0"
#endif
#ifdef FreeBSD
- #define RSLINE "/dev/cuaa0"
+ #define RSLINE "/dev/cuad0"
#endif
#ifdef Solaris
#define RSLINE "/dev/cua/b"

#define でプラットホームを指定しているけど,結局はシリアルデバイスをOSごとに指定しているだけだったりする.ちなみにFreeBSDではFreeBSD-4.x系は /dev/cuaaXだけど,FreeBSD-6.x 系は /dev/cuadX になるので注意.(でも実行時にデバイス指定できるみたいなので,そうして使うならこの修正もいらないかも)

これで,ビルド環境はそろった.あとは以下あたりを参考にして,てきとうにサンプルプログラムを書いてフラッシュに焼いて動作させてみる.上の「H8マイコンLANボードではじめる...」のほうに hello world のサンプル(h8_sci_rom.lzh)があるので, make.sh とか作ってとりあえずそれを動かしてみたらあっさり動いた.ただし上記サンプルでは,スタートアップでスタックポインタの設定がされていないので,ちょっと不気味ではある.(設定忘れだと思う)

ちなみにフラッシュへの焼き込みだけど,以下のようにする.
  1. プログラムのビルドに成功するとELF形式の実行形式が作成される.これをobjcopy を使ってモトローラSフォーマットに変換する.以下のような感じ.

    objcopy -O srec sample.elf sample.mot

  2. シリアルのストレートケーブル(シリアル延長ケーブル)でPCとボードを接続する.(クロスケーブルは不要)
  3. ディップスイッチを左からON,ON,OFF,ONにして起動.
  4. 作成した redboot.mot を h8write で焼く.

    h8write.exe -3069 -f20 redboot.mot

  5. 書き込み時に

    WARNING:This Line dosen't start with"S".
    Address Size seems wrong

    とかいうワーニングが出てたけど successed と言われたので,とりあえず気にしない.
  6. 以下のようにしてcuとかで38400bpsで接続する.

    # cu -s 38400 -l /dev/cuad0

  7. ディップスイッチを左からON,OFF,ON,OFFにしてリセットすることで,プログラムが起動する.リセットボタンを押すたびに hello world が表示される.
注意として,cuが起動しっぱなしで繋がったままだと,h8write で新たに書き込もうとしても書き込みできないので注意.h8write で書き込む際にはcuを切ること(シリアルがcuに占有されるので当然なのだが,ぼくはこれでけっこうハマった...).ちなみにcuは「~」「.」を押すことで切れます.

ちなみにCD-ROMにH8/OSというOSが付属していて,プログラムをメモリ上にロードして実行する機能がある.さらにputというコマンドがCD-ROMに付属していて,FreeBSDにも対応しているみたい.(h8writeと同様に,先頭にFreeBSD用の#defineがある)

ということでH8/OSをフラッシュに焼けばブートローダーとして使えて,putでKOZOSを送って実行する,ということができそう.まあでもネタとして面白いので,ブートローダー自作しようかとは思ってはいる.

で,まあとりあえず hello world くらいは全部自分で書いてみたいのと,上記サンプルプログラムはグローバル変数の書き込みができないはずなので,hello world を自分でスクラッチで書いてみた.以下のような感じ.

以下の考慮をしてある.
  • リンカスクリプトを自前で用意.
    • リンカスクリプトに関しては,付属のCD-ROMにあるH8/OSで使われているものを 流用できて,上記サンプルもそれを利用しているみたいなのだが,以下で説明する ように VADDR と LADDR を別にする必要があるのでそのままでは使えない.なので せっかくなので自分で書いてみた.
  • グローバル変数の書き込みに対応.
    • 上記サンプルはROM上で動作する前提なので,グローバル変数もROMに配置されて しまっていて書き込みできない(はずだ).なのでグローバル変数の初期値はROM 上に持って,起動時にRAM上にコピーしてそっちを使うように修正. (このためグローバル変数に関しては VADDR ≠ LADDR になるので, リンカスクリプトで工夫している) (グローバル変数のVADDRやLADDRが期待通りに配置されているかどうかは, readelf や逆アセンブル結果を参照して確認した)
  • スタートアップでスタックポインタを設定.
  • 割り込みベクタテーブルをリンカスクリプト側で作成せず,配列として定義. (このほうが一般の人は修正しやすいんではないかな,と)
  • ビルド用に make.sh を用意.(これは PowerPC で使ったやつを適当に修正して 利用)
  • シリアル関連とかをライブラリ化してソースコードを整理.
まあこんなところかな.

ビルドの方法は簡単で,make.sh というスクリプトを用意してあるので,以下のようにするだけです.PowerPCのと同じ感じ.

% ./make.sh clean
% ./make.sh
% ./make.sh image

./make.sh image することで,sample.mot が作成されます.で,スーパーユーザになって

# ./make.sh write

で,h8write を起動してフラッシュに書き込みます.シリアルは9600bpsで接続.

ちなみに以下が実行結果.グローバル変数の書き換えもばっちしうまくできてるみたい.

teapot# cu -l /dev/cuad0
Connected
Hello World! 10 1234 0 1 1 10
Hello World! 10 1234 0 1 1 10
Hello World! 10 1234 0 1 1 10