オリジナルOS「MicrOS」の設計と実装(3) ―― MicrOSのシステム・コール

田口 信夫

tag: 組み込み

技術解説 2008年5月27日

● ウェイト関数

 int __wait(unsigned int waitstatus)

 ウェイト関数には二つの役割があります.一つ目の役割は,ほかの関数の下位関数としてタスクのウェイト処理を一手に引き受けることです.このときのウェイト・ステータスは0x01~0xfdの値を持ちます.そして,ウェイト・ステータスとレジスタのセーブ処理以外のウェイト処理は,上位の関数によって行われなければなりません.

 もう一つは,30ビットのイベントを定義して,ビット単位のイベントによるANDまたはOR条件によってウェイトする役割です.ANDはビットで指定したすべてのイベントが発生するまでウェイトします.ORはビットで指定したイベントのどれか一つが発生すればウェイトを解除します.MicrOSではアプリケーション・システムの初期設定を各タスクで分散して行う可能性が高いので,このようなときに簡易なイベント処理として使用できます.

 ウェイト関数によってタスクはウェイト状態になり,結果としてタスク・スイッチが発生します.__waitを含むウェイト系の関数は,タスクの中でしかコールできません.タスク以外でコールすると,ウェイト関数の中で永久ループするようになっています.

● アクティブ関数

 int __active(_TCB *tcb, unsigned int resetstatus)
 int __activex(_TCB *tcb, unsigned int resetstatus)

 アクティブ関数は,ウェイト状態にあるタスクをレディ状態にします注1.指定されたタスクのウェイト状態をチェックします.ANDウェイトもしくはORウェイトでない場合,ウェイト・ステータスがresetstatusに一致しなければウェイトを解除しません.このアクティブは,アクティブ系の関数の下位関数として動作したときに行われるウェイトの解除です.ウェイトを解除されたタスクの返り値は,上位関数によってセットされています.ANDウェイトであれば,resetstatusとタスクのイベント待ちのビットのANDをとった値と,イベント待ちビットについてExclusive ORをとった値が0になるまで,幾つかのイベントを待ちます.ORウェイトの場合は,resetstatusとイベント待ちビットのandをとった値が0でなければウェイトを解除します.ANDウェイト,ORウェイトでウェイトを解除されたタスクのリターン・コードはウェイトを解除したイベントになります.アクティブ関数の返り値は指定したタスクがウェイト状態であれば正常に処理されます.

注1;この関数はV850_MicrOSsampleとアセンブラ版ではコーリング・シーケンスが逆になる.

 アクティブ関数は,割り込み処理の中からもコールできます.気を付けなければならないのは,割り込み処理の中でコールしたときはアクティブ関数によってタスク・スイッチが必要な状態であってもタスク・スイッチが行われない点です.この場合はtrap00a関数をコールすることによってタスク・スイッチが行われます.また,システム・コールを新たに追加したときに複数のタスクをアクティブにするようなものは,__activex関数を使って自動的にタスク・スイッチを行わないようにしなければなりません.このときも最後にtrap00a関数でタスク・スイッチの状態をチェックします.

● リクエスト・ウェイト関数

 void *__reqwait(void *scb, void *rqb, int return_status)

 この関数は,排他制御が必要なドライバをタスクで作成する場合に使用されます.SCBにリンクされたサービス要求(RQBの形式)があれば,そのアドレスを返り値としてリターンします.この返り値がNULLなのはサービス要求以外の条件(周辺機器からの割り込みなど)でウェイト状態が解かれた場合です.サービス要求が終了したとき,rqbのアドレスとリターン状態を示すそれらのコードをセットします.そして,__reqwait関数をコールするとrqbに終了コードがセットされ,要求列のリンクから取り外されます.rqbがTCBならタスクのウェイトが解除され,レディ・タスク・プールに登録します.

 このように,__reqwait関数はサービス要求の開始と終了の機能を兼ねているため,この関数を使ったドライバ・タスクは通常は次のように組まれます.

 RQBのポインタをセーブするrqb変数を定義し,ドライバ・タスクの初期処理の部分でこれにNULLをセットします.永久ループで構成された主要な処理の先頭

  rqb = __reqwait(scb, rqb, retcode);

のサービス要求を待ち,rqbがNULLでなければサービス要求の処理を行います.

 このドライバ・タスクにサービス要求を行うタスクがTCBでサービス要求を行えば,ウェイト系のサービス要求になり,TCBでないRQBを使えば,次の__rqbwaitでサービスの終了をチェックできます.これはデマンド型のサービス要求になります.

● rqbウェイト関数

 int __rqbwait(_RQB *rqb[], int n)

 複数のサービス要求を行ったRQB(TCBであってはならない)のサービスの終了状態をチェックします.すべての要求が完了しなければ,この関数からは戻れません.

 この機能と__reqwait関数を組み合わせれば,UNIX流のfork,joinに似た機能を実現できます.

● タスクのディレイ

 int __delay(unsigned int Timer) (ウェイト系)

 タスクの処理を指定時間だけ遅らせ(ディレイ)ます.ディレイしている間はウェイト状態です.時間の設定には次のマクロを使うことができます.

  __sec(x) 秒単位の時間を設定
  __ms(x) ミリ秒単位の時間を設定

組み込みキャッチアップ

お知らせ 一覧を見る

電子書籍の最新刊! FPGAマガジン No.12『ARMコアFPGA×Linux初体験』好評発売中

FPGAマガジン No.11『性能UP! アルゴリズム×手仕上げHDL』好評発売中! PDF版もあります

PICK UP用語

EV(電気自動車)

関連記事

EnOcean

関連記事

Android

関連記事

ニュース 一覧を見る
Tech Villageブログ

渡辺のぼるのロボコン・プロモータ日記

2年ぶりのブログ更新w

2016年10月 9日

Hamana Project

Hamana-8最終打ち上げ報告(その2)

2012年6月26日