オリジナルOS「MicrOS」の設計と実装(1) ―― MicrOSの概要とソースの概観

田口 信夫

tag: 組み込み

技術解説 2008年2月 8日

 MicrOSは__wait関数と__active関数の処理に内部割り込みを使用します.この割り込み処理の中で内部割り込みを発生させたタスクは現在状態をTCBにセーブします.このとき,コンパイラのレジスタ使用規約で,ワーキング・レジスタかアーギュメント・レジスタとされるレジスタはセーブされません.これらはレジスタ使用規約上,コールされた関数側ではセーブしなくても良いレジスタになっているからです.MicrOSはこの領域を,システム・コールを処理するときのワーク・エリアとして利用します.TCBに現在状態をセーブした後,アクティブ系のシステム・コールのときはReadyプールに登録します(ウェイト系のシステム・コールの場合は__wait関数をコールする前にウェイトに必要な処理は済んでいる).こうした処理の後,ディスパッチャにジャンプします.

 なお,システム・コールであってもコールされたシステム・コールの中で複数のタスクのウェイトを解除するような処理については,__active関数の代わりに__activex関数とこの内部割り込み関数へのコールを組み合わせなければなりません.

 また,V850-MicrOSの内部割り込み処理はこのようになってはいません.CA850の割り込み処理機構を利用しているためです.V850-MicrOSではTCBのワーキング・レジスタなどの領域にはレジスタをセーブせず,単なるワーク・エリアになっています.そのため,すべてのレジスタはスタック領域にセーブするようになっています(V850-MicrOSの割り込み処理はコンパイラの割り込み処理とMicrOSの割り込み処理が重複しており,アセンブリ・コード版のMicrOSに比べてオーバヘッドが大きい).

 MicrOSがこのような処理方法をとっているのはシステム拡張性のためです.アプリケーション・システムが新機能をシステム・コールの形で組み込む場合には,この規約を守ればよいだけなので簡単です.V850-MicrOSでは割り込み処理にCA850の処理機構を利用したので,__wait関数や__active関数もC言語で組み込みました.また,__wait関数や__active関数からディスパッチャまでの処理をアセンブリ・コードで組み込むことにより,かなり高性能の組み込みOSとなります.もっとも,現在組み込まれているシステム・コールの処理は単純なので,すべてアセンブリ・コードにしたところでたかがしれています.

 組み込みOSは,一度作成してしまえば再利用可能な部分の多いプログラムです.できるだけ高性能であるべきで,アセンブリ・コードを使う要素の高いプログラムと言えるでしょう.この辺りの詳細な説明は次回以降にあらためて行います.

 なお,V850-MicrOSのTCBの先頭部分はリスト13のような形式になっています.

リスト13 TCBの先頭部分

typedef struct _TCB_T{
struct _TCB_T           *next;  /* next link */
struct _TCB_T           *prior; /* prior link */
union{
struct _TCB_T       *tcb;   /* (unused) */
struct{
unsigned char   typ;    /* task type */
unsigned char   pri;    /* execution priority */
unsigned char   sts;    /* task status */
unsigned char   prs;
/* orginal priority(unused) */
} s;
} u;
unsigned int            p0;
unsigned int            p1;
unsigned int            p2;
unsigned int            p3;
unsigned int            sp;
unsigned int            psw;
unsigned int            pcr;
unsigned int            pc;
} _TCB;

1-5.システム・コールの処理

 MicrOSのシステム・コールには次のようなタイプのものがあります.

  • その場でサービスを完了するもの
  • その場でサービスが完了するが,データを蓄えなければならないもの
  • データを蓄えるにあたって可変個のデータを保持しなければいけないもの
  • タスクのウェイトが伴うもの

 具体的にMicrOSのシステム・コールを示しながら,こうしたタイプの処理方法の概要を以下に示します.

 まず,その場でサービスが完了するものの代表は__getCurTcb関数です.これは,関数をコールしたタスクのTCBアドレスを返す関数です.タスクが実行するとき,TCBのアドレスはシステム・コントロール・ブロックにセーブされています.それを持ってきて返り値とするだけです.この処理には割り込み禁止にするなどといった排他制御も不要です.

 排他制御が必要なシステム・コールがあります.例えばイベント・フラグ更新用サービス・リクエストのsnd_evt関数です.イベント・フラグはどの処理で必要とされるか分からず,複数のタスクで別々に必要とされるのかもしれません.このようなシステム・コールについては,アプリケーション側でイベント・フラグを構造体として定義し,イベント・フラグのアドレスをsnd_evtで指定するような処理方法を採用します.イベント・フラグを定義するシステム・コールがopn_evtです.このシステム・コールの第1パラメータがイベント・フラグを定義する構造体_EVTCBです.opnDentはイベント・フラグを初期化します.snd_evtの第1パラメータにこの構造体を定義したアドレスを指定してイベント・フラグを更新します.

組み込みキャッチアップ

お知らせ 一覧を見る

電子書籍の最新刊! 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日