2002年 佐々木 芳
はじめに
最近LegOSにかかわる機会があったので、LegOSについてレポートします。知らない方のために簡単にLegOSの紹介を以下にします。
LegOSは、Lego Mindstorm RCXブロック上で動作する組込みOSです。そのためRCXブロックのハードウェアを制御するために特化したOSと言えます。1998年10月からMarkus Noga氏により開始されたオープンソースプロジェクトとして現在に至ります。(http://www.noga.de/legOS/)
Lego MindstormはLEGO社(http://mindstorms.lego.com/ または http://mindstorms.lego.com/japan/
)がMITの メディアラボ との研究結果として1998年に製品化したものです。
このレポートでは、以下の参考文献をもとにLegOS(version 0.2.4)の機能を検討しました。ソースコードは見ていないのでこの文書で読み取れる範囲でのレポートです。
参考文献
Introduction to the legOS kernel.
Stig
Nielsson
詳しくはレゴ社のホームページ(http://mindstorms.lego.com/ または http://mindstorms.lego.com/japan/
)などを参照してください。
まずRCXのハードウェア構成要素を以下に列挙します。LegOSはこれらのハードウェアを制御する基本プログラムも含んでいるので、アプリケーションプログラムから直接これらのハードウェアを操作する必要はなさそうです。
l
日立 H8/3292 マイクロコントローラ
l
16Kバイト オンチップROM(0x0000〜0x3fff)
l
32Kバイト 外部RAM(0x8000〜0xffff)
l
モータ制御ポート(3個)
l
センサ制御ポート(3個)
l
赤外線通信ポート(1個)
l
LCD制御
l
ボタン(4個)
l
サウンド制御
l
インターバルタイマ
[RCXの外観は、ここをクリックしてください。]
[組み立てガイドに従って組み立てた「ロ−ヴァーボット」は、ここをクリックしてください。]
RCXのソフトウェアの基本構成は以下のように2つの部分から成ります。
l
on-chip driver
l
ファームウェア
on-chip
driverとは、
メーカ作成の電源投入時に動作するROM内のプログラムで、ハードウェアの制御をする低レベルルーチンの集まりです。ROM内の割込みハンドラはRAM上のエントリを呼び出すようになっています。ファームウェアをRAM領域にダウンロードする機能があります。
ファームウェアとは、
on-chip driverによりRAM内にダウンロードされるプログラムをファームウェアと呼びます。標準では、製品付属のバイトコードインタプリタです。LegOSはファームウェアとしてダウンロードされます。
[ファームウェアはPC上の開発環境を使って開発します、LegOSの開発およびLegOS上のアプリケーションの開発にはcygwinが使えるようです。PCから赤外線タワーを使ってRCXへダウンロードしている様子はここをクリックしてください。]
LegOSはRCXブロックのハードウェアを制御するために特化したOSなので、ハードウェアを制御する基本部分も組み込まれています。そのため割り込みをユーザプログラムで扱う必要はなさそうです。LegOSの構成要素を以下に示します。
l
カーネル(スレッド管理機能など)
l
アイドルスレッド
l
ユーザインタフェーススレッド
packet_consumer - プログラムローダ
key_handler -
プログラム実行制御
l
割込みハンドラ -
基本ハードウェア制御
l
サービスコールAPI -
カーネルの機能を公開
LegOSのユーザプログラムは、以下のような特徴があります。
l
カーネルのシンボル(legOS.lds)とリンクして、再配置可能な形式(*.lx)として作成する。
l
RCXへのダウンロード時に、実アドレスに変換される。
RCX上のRunボタンで実行する。
LegOSの起動シーケンスは以下のようになるようです。
@
on-chip
driverによるカーネルモジュールのダウンロード
A
カーネルのkmainがon-chip driverから呼ばれる。
B
割込みを登録する。
タイマハンドラ(systime_handler)
A/Dコンバータ(ds_handler)
シリアル通信
C
カーネル組込みのスレッドを生成する。
アイドルスレッド
packet_consumer
key_handler
D
以後、1msおきにタイマハンドラが起動される。
カーネルの機能を列挙します。以下でこれらの機能を概観します。
l
プログラム管理
l
スレッド管理
l
システムタイマ機能
l
セマフォ機能
l
メモリ管理
l
デバイス制御
これらの機能はサービスコールAPIとしてカーネルモジュールから公開されます。参考文献ではサービスコールの呼び出し規約等には触れていないので本書でも触れません。
まず、ユーザプログラムの形式は整理すると以下のようになります。
l
1つの再配置可能な形式(*.lx)で作成
l
1個のmain関数を含む。
l
各プログラムは複数のスレッドから構成される。
l
main関数内でスレッドを登録する。
LegOSではユーザプログラムを同時に8個までダウンロードできます。RCXのPrgmボタンでプログラムを選択し、Runボタンでmain関数を実行します。
スレッドとはプログラムの実行制御の単位です。(参考文献ではスレッド、プロセス、タスクを同じような意味で使っていますが、この文書では「スレッド」で統一して記述します。)
l
ユーザプログラムはサービスコールexeciでカーネルにスレッドを登録する。
l
スレッドは優先度(1〜20)を持つ。
l
スレッド状態には以下の5つがある。
1)
Dead 未定義スレッド(仮想的な状態)
2)
Zombie 休止状態(メモリ上には存在する)
3)
Waiting イベント待ち状態
4)
Sleeping 実行可能状態(いわゆるReady)
5)
Running 実行状態(CPUを使用している)
カーネル内でスレッドはスレッド管理ブロックとして管理され、スレッドと優先度の管理は下図のような優先度管理チェイン(双方向リスト)で管理されているようです。
スレッド状態間の状態遷移と遷移を引き起こすサービスコールAPIの関係を以下に示します。参考文献を読んだ限りではこのようになると思われます。Zombie状態のスレッドはスケジューラによりカーネル内のメモリをすべて解放されDead状態になるようです。
LegOSでは条件を待ってWaiting状態に入るサービスコールwait_eventに特徴があります。
スレッドはこのサービスコールにユーザ定義の評価関数のポインタを渡して待ちに入ります。この後、評価関数はタイマハンドラ(systime_handler)内で暗黙のうちに呼び出されます。スケジューラは評価関数の戻り値で待ちを解除するかどうか決めます。
このように、待ち解除の条件はプログラマが評価関数を書くことにより自由に設定できますが、待ち解除はタイマハンドラのタイミングでのみ起こります。
LegOSでは、システムタイマに1msの割り込みを使用しています。そのハンドラsystime_handlerでは以下の処理が行われるようです。
l
デバイス制御の関数を呼び出す。
・モータ/センサ/サウンド/LCD
・LNP(LegOSネットワークプロトコル)のタイムアウトチェック
・バッテリ情報の更新
l
wait_eventの評価関数を呼び出す。
l
実行中のスレッドのtimeslice(連続実行割り当て時間、クォータ)を評価する。デフォルトでは20ms。
l
最後にスケジューラを呼び出す。
スケジューラは次にどのスレッドを実行するかを決めるカーネル内のプログラムです。LegOSのスケジューラには以下の特徴があります。
l
systime_handlerとyeildから呼び出される。
l
優先度付きのラウンドロビンスケジューリングを採用している。
l
Priority chainの優先度の高いスレッドから調べる。同じ優先度ならリスト内の順番に調べる。
l
待ちに入るときは暗黙のうちにyeildが呼び出されるのでスケジューラが動く。
最後に実行スレッドの切替を行う。(tm_switcher)
以下にスレッド切り替えの起こる様子を考察します。
1) スレッド1,2は同じ優先度、スレッド3は低優先度の場合
※この場合、優先度の低いスレッド3はまったく動くことができません。
2) 待ちに入る(スレッド1がwait_eventを発行)場合
※この場合、wait_event内でスケジューラが動くのでスレッド切り替えが起こります。
LegOSでは、スレッド間の同期・通信機能としてセマフォのみをサポートしています。以下の特徴があります。
l
計数型セマフォである。
l
複数のスレッドが同じセマフォで待てる。(sem_wait)
l
信号操作sem_postによるセマフォでの待ち解除は、優先度の高いスレッドから。
※LegOSには、プログラム間での同期・通信機能はないようです。
セマフォでの待ち解除の様子を以下に考察します。
スレッド2がすでにセマフォを取得していて、スレッド1の優先度>スレッド2の優先度と仮定します。
LegOSでは、カーネルの使用しないRAM領域を可変長メモリブロックとして管理するようです。以下の領域はカーネルのメモリ管理機能により取得されます。
l
ユーザプログラムのコード、データ領域
l
タスクのスタック領域
l
カーネルの使用する管理ブロックなど
解放された隣接するメモリブロックは1つにまとめるようです。RAMの内訳は下図のとおり。
LegOSでは、以下のハードウェア制御が組み込まれているようです。これらの制御はカーネルのサービスコールAPIを使ってできるので、直接ハードウェアを操作する必要はないようです。
l
IRポートを使ったLNP(LegOS Network Protocol)
l
モータ制御
l
A/Dコンバータを使ったセンサ制御
l
サウンド制御
l
LCD制御
l
ボタン制御
LegOSの開発環境としてはcygwinなどが使えるようです。Cygwinでの開発は従来のプログラム開発方法であり特別目新しい部分はありませんが、製品付属の開発環境(画面例はここ)はグラフィカルなユーザインタフェースで注目してもいいように思いました。この開発環境を見て1年ほど前(2001年)に仕事で半導体工場の生産設備制御システムの開発を手伝ったときの言語開発環境を思い出しました。そこではMES(Manufacturing
Execution System)のデータベースからテーブルを取り出し、それらを加工(演算、フィルター、結合、分離)して新しいテーブルを作成するのですが、それをインタプリタ形式のグラフィカルな言語で記述しました。そこの開発環境はBROOKS AUTOMATION, INC.のAPF(AutoSimulations
Productivity Family)でした(これはレゴと違い?千万円もする製品なのでとても個人では購入できませんが)。
現在UMLが次世代開発言語として注目を集めているようですが、このようなグラフィカルな言語(インタプリタ)も次世代のプログラム開発言語、開発環境としてまだまだ研究の余地があるのかもしれません。