978-4-87783-239-1

12ステップで作る 組込みOS自作入門
(坂井 弘亮著、カットシステム、2010年)

が面白そうだったので、OS X 10.9 Mavericks で実際に作ってみることにしました。

(2014.7.24 追記;
 gcc-3.4.6 を使った記事に書き直し、gcc-4.7.1 を使う記事は別記事にしました。)


書籍の説明は Windows と Linux だったのですが、Mac でも開発された方がいたのでそちらを参考にしました。

(公式サポートページ)
→・「12ステップで作る 組込みOS自作入門」のサポートページ 

(その他参考になったページ)
→・2回目のC言語で『12ステップで作る組込みOS自作入門 』の通りに組込みOSを作ってみた - sandai - 三等兵
→・【学習メモ#1st】12ステップで作る組込みOS自作入門 - sandai - SlideShare
→・MacでH8開発環境構築 - 12ステップ本を試す - satfyの日記
→・組み込み自作OS-Macにて-Step1-その3 - Bioinformaticsのお勉強

この手の本では、一番ハードルが高くて挫折しやすい所は、実は最初の開発環境の構築だったりするのですが、上記の sandaiさんの OS X Lion での記事 が超丁寧に記述されていたので、OS X Mavericks でもとても参考になりました。感謝


なので、ここでは sandaiさんの記事を基に、実際の行った操作をメモしておきます。
ただし、自分なりに変更した箇所は、赤字にしてあります。


◆ハードウェア
○マイコンボード
今回自作するOS は、PC上ではなくH8/3069Fマイコンボード上で動作するものなので、ハードウェアが必要です。

幸い、出版元が書籍とハードウェア一式をセットにしたものを販売していたので、それを購入しました。(注意;『12ステップで作る 組込みOS自作入門』の書籍も含まれたセットです。)

→・「組込みOSセット」販売のご案内 - カットシステム

IMG_4476



○USBシリアルケーブル
1.ケーブルの購入
MacBook Air にはシリアルポート(RS232C)がありません。
そのため、USBシリアル変換ケーブルも必要です。

USBシリアルケーブルだとフラッシュROMの書き込みが失敗しやすい、と書籍やサポートページには記載がありますが、フラッシュROM書き込みツールとして後述の kz_h8write を使うことで今のところうまくできています。

今回は、以前 Amazon で購入した手持ちのものが使えました。


このケーブルは、対応OS に Macの記載がなく、メーカーのサイトにも Mac用のドライバはありませんが、使用しているチップのメーカーである FTDI のサイトには Mac用のドライバがあります。Mavericks なので「Mac OS X x64 (64-bit)」をダウンロードします。

→・Virtual COM Port Drivers - FTDI chip

(2014.7.30 追記;
OS X 10.9 Mavericks からは Apple純正のUSBシリアルドライバが標準で入っているそうです。そのため、このドライバのインストールは必要ありません

ドライバの確認方法;
(USBシリアルケーブルを Macにつないだ状態で)
$ kextstat | grep FTDI
  125    0 0xffffff7f80f1d000 0x7000     0x7000     com.apple.driver.AppleUSBFTDI (1.0.1b3) <115 36 5 4 3>

このように表示されれば、Apple製のドライバがすでに入っています。
ここで;
com.FTDI.driver.FTDIUSBSerialDriver
も表示されて、2行表示されるようなら、FTDI社製のドライバと二重に登録されています。
そのままでも動作に問題はないようですが、削除してもいいでしょう。

$ cd /System/Library/Extensions
$ sudo rm -r FTDIUSBSerialDriver.kext
$ cd /Library/Receipts
$ sudo rm -r ftdiusbserialdriver.pkg
$ sudo rm -r ftdiusbserialdriverinstallerPostflight.pkg
$ sudo rm -r ftdiusbserialdriverinstallerPreflight.pkg 

→・Mac OS X MavericksにおけるFTDIシリアルポートドライバの取扱い - オーバーシー・パブリッシング
→・AN_134_FTDI_Drivers_Installation_Guide_for_MAC_OSX - FTDI Chip(インストール法、アンインストール法、さらに Mavericks についての記載あり)

以上、追記終わり。)


2.動作、デバイス名の確認
USBシリアルケーブルを接続し、ターミナルを起動します。
(ターミナルは、Macintosh HD>アプリケーション>ユーティリティ>ターミナル.app にあります。)

以下、$ の行が入力する行で、実際の入力はコマンドプロンプトの の次の文字からです。
(入力文字数が長いと2行以上にまたがるときもありますが、改行は入れません。)

$
 ls /dev/tty.*
/dev/tty.usbserial-FTFMNRDG

usbserial-XXXX のように表示されたらOKです。XXXXのところは機器によって異なります。
この名前は後で使うので控えておきます。

あるいは、以下の方法でも確認できます。
アップルメニュー>このMacについて>詳しい情報>システムレポート>ハードウェア>USB>USB HS SERIAL CONVERTER:>シリアル番号:

USB HS SERIAL CONVERTER という項目があれば正常に動作しています。シリアル番号 がデバイス名になります。



◆ソフトウェア
○セルフコンパイラ
Mac の場合、Command Line Tools が入っていれば改めて他に必要ありません。
Xcode とともに入れてもいいですし、Command Line Tools のみインストールしてもかまいません。
今回は、Xcode 5.1用の Command Line Tools (OS X Mavericks) を使用しました。

Command Line Tools のダウンロードサイト;
→・Apple Developer メンバーセンター(要 AppleID)

ただし、Xcode 5.1 の gcc は実は本当の gcc ではなく llvmです。クロスコンパイラの gcc をインストールするときに、この llvm を使ってクロスコンパイラ用の gcc をコンパイルすることになるので、問題が起こるようなら本当の gcc を入れた方がいいのかもしれません。


○クロスコンパイラ
1.インストール先のディレクトリの作成
インストール先は書籍とは違うsandaiさんのやり方を倣い、$HOME直下に 12stepディレクトリを作り、その下に作った build、src、 tools ディレクトリにそれぞれインストールすることにします。
こうすると、必要なくなったら ~/12stepディレクトリを削除するだけで全部まとめて削除されます。
(ここはお好みで。ビルド時の --prefix=xxxx と Makefile の設定で指定可能です。)

$ cd ~
$ mkdir 12step
$ cd 12step
$ mkdir build src tools


2.クロスコンパイラをダウンロード、解凍
必要なのは、以下の3つです。
・binutils-2.19.1
gcc-3.4.6
gcc-3.4.6 の 64bitマシン用パッチ

binutils、gcc ともにサポートページで勧められている通り書籍と同じバージョンにしておいた方がよさそうです。

sandaiさんの記事では gcc-4.7.1 を使っています。しかし、実際に gcc-4.7.1 を使ってみたところ(→別記事)、書籍を読み進めていくうちに gcc のバージョンの違いにより、書籍と同じ結果が得られなかったり、プログラムの修正が必要だったりしたので gcc3.4.6 を入れ直しました。なにより、gcc-3.4.6 のインストールの方が簡単です。

ただし、gcc-3.4.6 は、64bit マシン(OS X Mavericks も 64bit)ではパッチを当てる必要があるそうです。

なので、いきなりここは自分なりのやり方になっています。

binutils-2.19.1、gcc-3.4.6 はサポートページからダウンロードできます。
ダウンロードしたファイルは、ダブルクリックで解凍後、~/12step/build に移動します。
Finderを使う場合は; Macintosh HD>ユーザ>(自分のユーザ名)>12step>build です。

ターミナルでGNUのページからダウンロードして解凍する場合は;
・「binutils」
$ cd ~/12step/build
$ curl -O http://ftp.gnu.org/gnu/binutils/binutils-2.19.1.tar.bz2
$ tar jxvf binutils/binutils-2.19.1.tar.bz2

・「gcc」
$ cd ~/12step/build
$ curl -O http://ftp.gnu.org/gnu/gcc/gcc-3.4.6/gcc-3.4.6.tar.gz
$ tar xvzf gcc-3.4.6.tar.gz


・「gccのパッチ」
gcc-3.4.6 のパッチは、サポートページからのリンクがあります。
ただし、これだけだとよく分からなかったのですが、次のようにすればよいようです;

→ Uros Bizjak - [PATCH, h8300]/ Fix build on 64bit targets
のページのパッチの部分 ↓ をコピーして、適当な名前(ここでは 64bit.patch にしました)で保存しておきます。(後で使うときに移動するので保存場所も適当で。)

Index: h8300.c
===================================================================
--- h8300.c (revision 117513)
+++ h8300.c (working copy)
@@ -83,8 +83,8 @@
 static int h8300_saveall_function_p (tree);
 static int h8300_monitor_function_p (tree);
 static int h8300_os_task_function_p (tree);
-static void h8300_emit_stack_adjustment (int, unsigned int);
-static int round_frame_size (int);
+static void h8300_emit_stack_adjustment (int, HOST_WIDE_INT);
+static HOST_WIDE_INT round_frame_size (HOST_WIDE_INT);
 static unsigned int compute_saved_regs (void);
 static void push (int);
 static void pop (int);
@@ -510,7 +510,7 @@
    SIZE to adjust the stack pointer.  */

 static void
-h8300_emit_stack_adjustment (int sign, unsigned int size)
+h8300_emit_stack_adjustment (int sign, HOST_WIDE_INT size)
 {
   /* If the frame size is 0, we don't have anything to do.  */
   if (size == 0)
@@ -546,8 +546,8 @@

 /* Round up frame size SIZE.  */

-static int
-round_frame_size (int size)
+static HOST_WIDE_INT
+round_frame_size (HOST_WIDE_INT size)
 {
   return ((size + STACK_BOUNDARY / BITS_PER_UNIT - 1)
    & -STACK_BOUNDARY / BITS_PER_UNIT);


3.パスを通す
次の gcc-3.4.6 のインストールに必要なのと、後で入れる kz_xmodem、あるいは書籍の 3rdステップで h8300-elf-readelf を使う時に必要なので、~/12step/tools/bin にPATH を通します。

export PATH=${HOME}/12step/tools/bin:$PATH
この一文を「.bashrc」か「.bash_profile」ファイルに書いておきます。

やり方は、例えば;
$ open ~/.bash_profile
で、.bash_profile を開いて編集し、保存。(お好みのエディタでも可。)
$ source ~/.bash_profile あるいはターミナルを再起動します。

$ echo $PATH
でパスの確認をします。 

もちろん、必要なくなったらこのPATH は削除するか、コメントアウト
#export PATH=${HOME}/12step/tools/bin:$PATH
します。 
(→・【学習メモ#1st】12ステップで作る組込みOS自作入門 - スライド14枚目 - sandai - SlideShare


4.ビルド
a)「binutils」
$ cd ~/12step/build/binutils-2.19.1
$ ./configure --target=h8300-elf --disable-nls --disable-werror --prefix=$HOME/12step/tools
$ make
$ make install


b)「gcc」
$ cd ~/12step/build/gcc-3.4.6
$ ./configure --target=h8300-elf --disable-nls --disable-threads --disable-shared --disable-werror --enable-languages=c --prefix=$HOME/12step/tools

$ cd ~/12step/build/gcc-3.4.6/gcc/config/h8300 
先ほどのパッチファイル 64bit.patch をこのディレクトリに移動します。

$ patch < 64bit.patch (これでパッチを当てます。)
patching file h8300.c
Hunk #1 succeeded at 52 (offset -31 lines).
Hunk #2 succeeded at 368 with fuzz 2 (offset -142 lines).
Hunk #3 succeeded at 397 with fuzz 1 (offset -149 lines). 
と表示されれば、成功です。

$ cd ~/12step/build/gcc-3.4.6
$ make
$ make install


○フラッシュROM書き込みツール
書籍で紹介さている h8write ではなく、shintaさんが改良した「kz_h8write」を使用します。
→・H8/3069F writer for KOZOS - kz_h8write 「h8writeリベンジ解決編」- CuBeatSystems

ダウンロードサイト;
→・H8/3069F writer for KOZOS (kz_h8write) - SourceForge.JP

適当な場所にダウンロードして解凍すると、PackageFiles という名前のフォルダができます。(必要ないかもしれませんが、)分かりやすくするためにフォルダ名を kz_h8write-v0.2.1 にリネームします。
そして、~/12step/build/ 以下にこの kz_h8write-v0.2.1 を置きます。
そのあとはターミナルで;

$ cd ~/12step/build/kz_h8write-v0.2.1/src
$ make
$ mv kz_h8write ~/12step/tools/kz_h8write



◆動作確認
1.ソースコードのダウンロード
まずは、動作確認のため(自分で作ったソースコードではなく)サポートページからソースコードをダウンロードします。(クロスコンパイラの動作も確認したいので、コンパイル済みでないソースコードの方を。)

ダウンロードしたソースコードは、以下のようなディレクトリ構造にします。
~12step/src 以下に書籍のステップ毎に配置;

~12step/src/01/bootload/main.c
                                       makefile
                                       defines.h
                                       …
                                       …
                   /02/bootload/main.c
                                       …
                                       …

以下、1stステップの「Hello World」プログラムを使って、動作確認をします。


2.Makefile の修正
書籍とは違う場所にクロスコンパイラ等を置いたので、「bootload」ディレクトリの「Makefile」以下のように修正します。

PREFIX  = ~/12step/tools

H8WRITE = ../../../tools/kz_h8write

H8WRITE_SERDEV = /dev/tty.usbserial-FTFMNRDG

usbserial-XXXX は、USBシリアルケーブルの設定で確認した自分のドライバ名にします。)


3.プログラムのビルド
$ cd ~/12step/src/01/bootload
$ make

~/12step/tools/bin/h8300-elf-gcc -c -Wall -mh -nostdinc -nostdlib -fno-builtin -I. -Os -DKZLOAD vector.c
~/12step/tools/bin/h8300-elf-gcc -c -Wall -mh -nostdinc -nostdlib -fno-builtin -I. -Os -DKZLOAD startup.s
~/12step/tools/bin/h8300-elf-gcc -c -Wall -mh -nostdinc -nostdlib -fno-builtin -I. -Os -DKZLOAD main.c
~/12step/tools/bin/h8300-elf-gcc -c -Wall -mh -nostdinc -nostdlib -fno-builtin -I. -Os -DKZLOAD lib.c
~/12step/tools/bin/h8300-elf-gcc -c -Wall -mh -nostdinc -nostdlib -fno-builtin -I. -Os -DKZLOAD serial.c
~/12step/tools/bin/h8300-elf-gcc vector.o startup.o main.o lib.o serial.o -o kzload -Wall -mh -nostdinc -nostdlib -fno-builtin -I. -Os -DKZLOAD -static -T ld.scr -L.
cp kzload kzload.elf
~/12step/tools/bin/h8300-elf-strip kzload


$ make image
~/12step/tools/bin/h8300-elf-objcopy -O srec kzload kzload.mot

ビルド成功です。


4.マイコンボードの接続
マイコンボードを電源と MacBook Air にそれぞれ接続します。
マイコンボードのディップスイッチを書き込みモードにします。左(1)からON、ON、OFF、ON です。

ディップスイッチの右隣りの丸いリセットボタンを押します。


5.マイコンボードのフラッシュROM へ書き込み
ターミナルで;

$ cd ~/12step/src/01/bootload
$ make write
../../../tools/kz_h8write -3069 -f20 kzload.mot /dev/tty.usbserial-FTFMNRDG
=================================================
 H8/3069F Flash Writer for KOZOS (Version 0.2.1)
 Copyright(C) 2011-2012 Shinichiro Nakamura
=================================================
Bitrate sequence: Done.
Inquiry device: Done.
Select device: Done.
Inquiry clock mode: Done.
Select clock mode: Done.
Select bitrate: Done.
Waiting for erase done:......
Programming:.....
Program: Done.
Complete.

「Complete.」と表示がされれば成功です。


6.マイコンボードのフラッシュROMから起動
マイコンボードのディップスイッチを、左(1)からON、OFF、ON、OFF にします。
端末エミュレータは Mac のいつものターミナルが使えます;
ターミナルを起動して、cuコマンドを使います。
(screenコマンドでもよいようです。
→・MacでScreenコマンドでシリアルコンソール接続 - Disce gaudere. 楽しむ事を学べ。

$ sudo cu -l /dev/tty.usbserial-FTFMNRDG (←usbserial-XXXX は各自のドライバ名を入力)
Password:  (←ここでパスワードを入力します)
Connected.

ここでマイコンボードのリセットボタンを押します。
 
リセットボタンを押すたびにターミナルに;
Hello World!
Hello World!

と表示されれば動作確認完了です

cuコマンドを終了するには、~. と入力します。


※もしうまくいかない場合は、サポートページから「コンパイル済みのソースコード」をダウンロードします。
こちらを使ってフラッシュROM へ書き込みを行うことで、プログラムのビルドが失敗しているのか、フラッシュROMの書き込みが失敗しているのかを切り分けることができると思います。



◆追加ソフトウェア
○XMODEMファイル転送ツール「kz_xmodem」のインストール
4thステップから使うファイルのXMODEM転送機能について、kz_h8write の作者である shintaさんが開発された KOZOS専用XMODEM転送ツール「kz_xmodem」がサポートページで紹介されています。これも Mac で動作するそうなのでインストールします。

→・XMODEM for KOZOS (12ステップで作る 組込みOS自作入門 KOZOS用ユティリティ kz_xmodem) - CuBeatSystems

ダウンロードサイト;
→・XMODEM for KOZOS (kz_xmodem)  - SourceForge.JP

適当な場所にダウンロードして解凍します。そして、~/12step/build/ 以下に解凍した kz_xmodem-v0.0.2 フォルダを置きます。
そのあとはターミナルで;
 
$ cd ~/12step/build/kz_xmodem-v0.0.2/src
$ make
$ mv kz_xmodem ~/12step/tools/bin/kz_xmodem

使い方については、別記事にしました。
(→・Macで XMODEM転送して起動させる2つの方法;『12ステップで作る 組込みOS自作入門』



◆書籍を読み進めていく上での注意
○プログラムの修正について
「◆動作確認 2.Makefile の修正」で行った修正を、各ステップの「bootload」ディレクトリ内の「Makefile」と、6thステップから追加する「os」ディレクトリ内の「Makefile」について行う必要があります。
(「os」ディレクトリ内の「Makefile」では、該当の修正箇所は1行だけです。)

それ以外の修正は、最終の 12thステップに至るまで、特に必要ありませんでした。
(gcc-4.7.1 を使った場合の修正点は別記事にしました。)


○2ndステップ以降の make での警告について
2ndステップの make でいきなり警告が出てしまいました。(それ以降もずっと出ます。)
エラーで動かない、という訳ではないのですが気になります。

$ cd ~/12step/src/02/bootload
$ make
~/12step/tools/bin/h8300-elf-gcc -c -Wall -mh -nostdinc -nostdlib -fno-builtin -I. -Os -DKZLOAD vector.c
~/12step/tools/bin/h8300-elf-gcc -c -Wall -mh -nostdinc -nostdlib -fno-builtin -I. -Os -DKZLOAD startup.s
~/12step/tools/bin/h8300-elf-gcc -c -Wall -mh -nostdinc -nostdlib -fno-builtin -I. -Os -DKZLOAD main.c
~/12step/tools/bin/h8300-elf-gcc -c -Wall -mh -nostdinc -nostdlib -fno-builtin -I. -Os -DKZLOAD lib.c
/var/folders/b5/8g6wjg_d5wqcs70tct44nz_h0000gn/T//ccTop6qD.s: Assembler messages:
/var/folders/b5/8g6wjg_d5wqcs70tct44nz_h0000gn/T//ccTop6qD.s:61: Warning: operand #0xffffffffffffffff out of range.
/var/folders/b5/8g6wjg_d5wqcs70tct44nz_h0000gn/T//ccTop6qD.s:130: Warning: operand #0xffffffffffffffff out of range.
/var/folders/b5/8g6wjg_d5wqcs70tct44nz_h0000gn/T//ccTop6qD.s:159: Warning: operand #0xffffffffffffffff out of range.
~/12step/tools/bin/h8300-elf-gcc -c -Wall -mh -nostdinc -nostdlib -fno-builtin -I. -Os -DKZLOAD serial.c
~/12step/tools/bin/h8300-elf-gcc vector.o startup.o main.o lib.o serial.o -o kzload -Wall -mh -nostdinc -nostdlib -fno-builtin -I. -Os -DKZLOAD -static -T ld.scr -L.
cp kzload kzload.elf
~/12step/tools/bin/h8300-elf-strip kzload


○3rdステップで使う readelf について
Mac には readelf は入ってないようです。その代わり、書籍でも紹介されているクロスコンパイラの中(~/12step/tools/bin)にある h8300-elf-readelf が使えます。

$ readelf -a kzload.elf
の代わりに次のようにすれば、同じ出力結果が得られます。
 
$ h8300-elf-readelf -a kzload.elf
(ただし、「○クロスコンパイラ 3.パスを通す」の操作で、h8300-elf-readelf のある ~/12step/tools/bin に PATHが通っていなければなりません。)


○4thステップで使う objdump について
objdump は ~/12step/tools/h8300-elf/bin/ 以下にインストールされているので、逆アセンブルするには;

$ ~/12step/tools/h8300-elf/bin/objdump -d kzload.elf
と入力します。



12ステップで作る組込みOS自作入門
坂井 弘亮
カットシステム
2010-05