連載「H8マイコンボードで動作する組み込みOSを自作してみよう!」の第3回。今回は、OSの起動に必要な「ブートローダー」を作成し、自作の「Hello World」をブートローダーから起動させる!
本連載では、学習用・ホビー用の組み込みOS「KOZOS」を使ってマイコンボード上でいろいろと実験をしつつ、フルスクラッチで組み込みOSを自作していく過程を体験していきます。最終的に、ソフトウェア完全自作のWebサーバを動かすことにチャレンジします!
連載第1回「フルスクラッチの“Hello World”を動かしてみよう」では、「H8/3069Fマイコンボード」上でフルスクラッチの「Hello World」を動かしました。続く、連載第2回「フルスクラッチの“Hello World”の仕組みを見てみよう」では、そのソースコードの解説を行いました。
今回は、OSの起動に必要な「ブートローダー」を作成し、自作の「Hello World」をブートローダーから起動してみます。
本連載では、秋月電子通商の「H8/3069Fネット対応マイコンLANボード(完成品)」(図1)を利用します。マイコンボードの詳細については連載第1回を参照してください。ちなみにこのボードは、3750円(税込)と非常に安価で入手性も良く、個人のホビー用途にオススメです。
本連載で紹介するソースコードは、KOZOSのWebサイトからダウンロードできます。また、開発環境の構築方法は連載第1回で説明してありますので、興味のある方はぜひソースコードをビルドし、実機での動作を試してみてください(幾つか対応は必要となりますが、シミュレータ上でも動作させることが可能です)。
なお、上記ソースコードは、筆者の書籍「12ステップで作る組込みOS自作入門」の各章(ステップ)に応じたものになっています。書籍の方にも詳しい説明がありますので、そちらも参考にしてみてください。
OSを自作する際にまず考えなければならないことは、その起動方法です。つまり「ブートローダーをどうするか?」ということです(注1)。
組み込みOSの起動方法には、大きく分けて2種類があります。
1つは連載第1回で紹介した「Hello World」のように、ROM上にOSの実行コードを配置しておく方法です。電源ONでROM上のコードが実行されるため、そこにOS本体を置いておけば、電源ONですぐにOSを起動できます。この場合、RAMは静的変数とスタック、ヒープのみに利用されます。多くのマイコンはこのような動作を想定して、内蔵フラッシュROMの容量を内蔵RAMよりも多めに取ってあります。
もう1つは、ROM上に「ブートローダー」と呼ばれるプログラムを配置して、(1)電源ONでブートローダーが起動し、(2)ブートローダーがOSを起動するという2段階構造にする方法です。これは一見すると無駄なようにも思えますが、この構成の方が最適なケースがあります。例えば、実行速度が必要な(OSの実行コードを高速なRAM上で動作させたい)場合や、フラッシュROMの領域節約のためにOSの実行コードを圧縮しておきたい場合、ユーザー側でのOSの更新を可能にしたい場合などです。このようなケースでは、OSのモジュールをROM上の別領域に書き込んでおき、ブートローダーはそれをRAM上に展開してOSの起動をかけます。
また、フラッシュROMには書き込み回数に限度がありますし、開発中にいちいちフラッシュROMに書き込んで起動をかけるのは面倒です。このような場合、ブートローダーをフラッシュROMに書き込んでおき、OSのモジュールをシリアルなどでダウンロードして起動すれば、フラッシュROMへの書き込みの手間や回数を削減できます。さらに、ブートローダーに簡単なデバッグ機能などを追加しておけば、OSのデバッグも行えるため、OSの動作が安定していない開発初期段階で非常に重宝します。このようなデバッグ機能を持つブートローダーのことを一般的に「モニター」などと呼びます。
当然ながら、OSの起動にはOSの転送が必要です(電源ONでOSが自動的に起動するわけではありません)。製品化の段階では、OSのモジュールをフラッシュROMなどに書き込む必要があります。このような作業を一般的に「ROM化」と呼びます。
ROM化の際、前述の方法によってフラッシュROMから直接OSを起動させる(つまり、ブートローダーを介さずにOSを起動させる)方法もありますが、先に説明したように、高速性やOSモジュールの圧縮・更新の容易性などのため、ブートローダーを残し、OSのモジュールをフラッシュROM上の別領域に配置しておくケースもあります。
筆者が開発しているKOZOSでは、ブートローダーも作成しています。
ブートローダーは、オープンソース・ソフトウェアとして配布されているものも幾つか存在し(注2)、中には高機能で魅力的なものもあります。しかし、“ソフトウェアを完全自作で開発する”というのがKOZOSのポリシーですので、ブートローダーも“自作”しています!
今回使用するマイコンボードのフラッシュROMにあらかじめブートローダーを書き込んでおきます。(1)電源ONすると、まずブートローダーが起動し、シリアル上にプロンプトが出力されます。(2)OSのモジュールはシリアル経由で転送され、起動をかけることでOSを立ち上げます。
今回、この2段階構成にした理由の1つは、フラッシュROMの書き込み寿命を節約するためです。もう1つは、ブートローダーから自作した方が本格的な組み込みシステムの動作を模倣できて、良い学習用のサンプルになるからです。完全自作のKOZOSでは、電源ON直後のブートローダーの動作から学習することができます。ブートローダーの学習用のシンプルな実装はあまりないため、これは貴重なものだと思います。
それでは、KOZOSのブートローダーを実際に動作させてみましょう。
KOZOSのWebサイトから「osbook_03.zip」をダウンロードしてください。「osbook_03.zip」を解凍すると、「osbook_03」以下に「06」というフォルダがあり、直下に「bootload」「os」という2種類のソースコードがあります。これが今回の対象です。
「bootload」がブートローダー、「os」がブートローダーから起動して動作させるプログラムになります。フォルダ名は「os」ですが、これは“この後OSの形に仕上げていく”ためにこのような名前になっているだけで、ここでは単なる「Hello World」を表示するだけのプログラムになっています。
連載第1回では、マイコンボードの電源ONで「Hello World」をシリアル出力するプログラムを作成しましたが、今回は電源ONでブートローダーを起動し、シリアル経由で「Hello World」のプログラムを転送、起動するという手順になります。
まずは、これらをビルドしてみましょう。「bootload」のフォルダに入って「make」「make image」コマンドを実行し、ブートローダーの実行モジュールを作成します(リスト1)。
% cd osbook_03/06/bootload % make /usr/local/bin/h8300-elf-gcc -c -Wall -mh -nostdinc -nostdlib -fno-builtin -I. -Os -DKZLOAD vector.c /usr/local/bin/h8300-elf-gcc -c -Wall -mh -nostdinc -nostdlib -fno-builtin -I. -Os -DKZLOAD startup.s /usr/local/bin/h8300-elf-gcc -c -Wall -mh -nostdinc -nostdlib -fno-builtin -I. -Os -DKZLOAD main.c /usr/local/bin/h8300-elf-gcc -c -Wall -mh -nostdinc -nostdlib -fno-builtin -I. -Os -DKZLOAD lib.c /usr/local/bin/h8300-elf-gcc -c -Wall -mh -nostdinc -nostdlib -fno-builtin -I. -Os -DKZLOAD serial.c /usr/local/bin/h8300-elf-gcc -c -Wall -mh -nostdinc -nostdlib -fno-builtin -I. -Os -DKZLOAD xmodem.c /usr/local/bin/h8300-elf-gcc -c -Wall -mh -nostdinc -nostdlib -fno-builtin -I. -Os -DKZLOAD elf.c /usr/local/bin/h8300-elf-gcc vector.o startup.o main.o lib.o serial.o xmodem.o elf.o -o kzload -Wall -mh -nostdinc -nostdlib -fno-builtin -I. -Os -DKZLOAD -static -T ld.scr -L. cp kzload kzload.elf /usr/local/bin/h8300-elf-strip kzload % make image /usr/local/bin/h8300-elf-objcopy -O srec kzload kzload.mot % ls kzload* kzload kzload.elf kzload.mot %
リスト1 ブートローダーのビルド結果 |
ここで作成された「kzload」というファイルがブートローダーの実行モジュールです。「kzload.mot」は、実行モジュールをマイコンボードへ転送するためのファイル形式(注3)に変換したものです。
さらに「os」のフォルダに入り、「make」コマンドを実行することで、「Hello World」の実行モジュールを作成します(リスト2)。
% cd osbook_03/06/os % make /usr/local/bin/h8300-elf-gcc -c -Wall -mh -nostdinc -nostdlib -fno-builtin -I. -Os -DKOZOS startup.s /usr/local/bin/h8300-elf-gcc -c -Wall -mh -nostdinc -nostdlib -fno-builtin -I. -Os -DKOZOS main.c /usr/local/bin/h8300-elf-gcc -c -Wall -mh -nostdinc -nostdlib -fno-builtin -I. -Os -DKOZOS lib.c /usr/local/bin/h8300-elf-gcc -c -Wall -mh -nostdinc -nostdlib -fno-builtin -I. -Os -DKOZOS serial.c /usr/local/bin/h8300-elf-gcc startup.o main.o lib.o serial.o -o kozos -Wall -mh -nostdinc -nostdlib -fno-builtin -I. -Os -DKOZOS -static -T ld.scr -L. cp kozos kozos.elf /usr/local/bin/h8300-elf-strip kozos % ls kozos* kozos kozos.elf %
リスト2 Hello Worldのビルド結果 |
「kozos」というファイルが「Hello World」の実行モジュールです。
では、実際に動作させてみます。まずは連載第1回と同じ要領で、ブートローダーをマイコンボードのフラッシュROMに書き込みます。
PCとマイコンボードをシリアルケーブルで接続し、マイコンボードのディップスイッチを左から「ON、ON、OFF、ON(上、上、下、上)」にした状態(フラッシュROM書き込みモード)で、電源アダプターを接続して電源をONにします。
「bootload」のフォルダに入って「make write」コマンドを実行することで、マイコンボードのフラッシュROMにブートローダーを書き込みます。
書き込み方法については、連載第1回で説明してありますので、詳しくはそちらを参照してください。さらに、本稿執筆時点で「h8write」の幾つかの不具合を修正し、新たに実装しなおされた「kz_h8write」がshintaさんによって作成されています(原稿執筆の現時点ではLinux版とWindows版があるようです)。フラッシュROMへの書き込みがうまくいかない場合には、こちらも利用してみてください。
Copyright © ITmedia, Inc. All Rights Reserved.