目次

内部動作

 RTOSを実現するには、スケジューラ、ディスパッチャ、システムコールを
 どう記述するかを考えなければなりません。

 スケジューラ、ディスパッチャは、Cのmain関数で実現します。

 システムコールは、個々に関数を定義しています。


スケジューラ、ディスパッチャ

 USOは、PLC(Programable Logic Controller)の動作を参考にしています。  PLCは、全回路をスキャンして、必要であれば、その回路を動かします。  USOのスケジューラ、ディスパッチャは、タスクの状態をスキャンして  READYであれば、対応する関数を実行します。 run_tsk = TSK_ID0 ; while ( ON ) { /* タスクの状態がREADYであれば、タスク実行 */ /* スキャン */ }  タスクの状態をスキャンするために、変数run_tskを用意します。  変数run_tskを、TSK_ID0からTSK_ID_MAX-1まで増やし、タスクの  状態を調べていきます。 run_tsk = TSK_ID0 ; while ( ON ) { /* タスクの状態がREADYであれば、タスク実行 */ /* スキャン */ run_tsk++; if ( run_tsk == TSK_ID_MAX ) { run_tsk = TSK_ID0 ; } }  該当タスクの状態が、READYかを確認する必要があります。  タスクのIDを与えて、READYであればYESを返す関数を定義  して、使います。この関数を、is_tsk_readyとします。 run_tsk = TSK_ID0 ; while ( ON ) { if ( is_tsk_ready( run_tsk ) == YES ) { /* タスク実行 */ } /* スキャン */ run_tsk++; if ( run_tsk == TSK_ID_MAX ) { run_tsk = TSK_ID0 ; } }  タスク実行は、関数の開始アドレスをテーブルに入れておき  開始アドレスを取り出す方式が楽なので、ポインタを使って  タスク関数に分岐します。  まとめると、次のようになります。 run_tsk = TSK_ID0 ; while ( ON ) { pcur_tsk = tcb[run_tsk] ; if ( is_tsk_ready( run_tsk ) == YES ) { (*(pcur_tsk.tsk))(); } run_tsk++; if ( run_tsk == TSK_ID_MAX ) { run_tsk = TSK_ID0 ; } }  配列tcbは、別の章で説明します。

状態管理変数

 タスクの状態を管理するための変数が必要になります。  タスクは、RUN、READY、SUSPEND、WAIT、DORMANTのいずれか  の状態を取るので、1タスクあたり3ビットで管理できます。  メモリの少ないマイコンでは、状態管理のためだけに多くの変数を  使えないので、工夫して1ビットの組み合わせで状態を表現します。  5状態あるうちで、RUNはREADYであることがわかれば、遷移する  必要はないので、変数は4個あれば状態を管理できます。  従って、READYを表現するための変数readyを用意します。  RUNを除くと、READY、SUSPEND、WAIT、DORMANTと4状態を表現  できればよいので、変数は3個で足ります。  READY、SUSPEND、DORMANTを表現する変数を各々  とします。  タスクrが、READYかどうかは、変数readyのrビット目で判断します。  rビット目が1であれば、タスクrはREADY状態にあります。  タスクsが、SUSPENDかどうかは、変数suspendのsビット目で判断します。  sビット目が1であれば、タスクsはSUSPEND状態にあります。  タスクvが、USOで管理できるか否かは、変数vldtskのvビット目  で判断します。  vビット目が1であれば、タスクvはUSOで管理できます。  タスクwが、WAITかどうかは、3変数ready、suspend、vldtskの  論理演算で求めた結果のwビット目で判断します。  wビット目が1であれば、タスクwはWAIT状態にあります。

システムコールcre_tsk

 cre_tskは、タスクIDとタスク関数を関連づけ、タスク関数の  実行開始アドレスをTCB(Task Control Block)に設定します。  タスクIDとタスク関数名をパラメータとします。 cre_tsk(TSK_ID0,tsk0_proc); cre_tsk(TSK_ID1,tsk1_proc);  内部は、次のように処理します。   変数vldtskのタスクIDに相当するビットに、1を設定。   タスクIDで指定する変数wcountを、0クリア。  変数wcountは、WAITを実現するためのカウンタで、10msのN倍  (1〜65535)を記憶します。  以下のように定義します。  void cre_tsk(UBYTE tid,void (*tsk)(void))  {   if ( tid >= TSK_ID_MAX ) return ;   vldtsk |= (1 << tid) ;   tcb[tid].tsk = tsk;   tcb[tid].wcount = 0;  }

システムコールsta_tsk

 sta_tskは、タスクIDを使い、タスクの初期状態を指定します。  タスクIDとタスク状態をパラメータとします。 sta_tsk(TSK_ID0,TTS_READY) ; sta_tsk(TSK_ID1,TTS_SUSPEND);  指定された状態に合わせて、変数readyとsuspendのタスクIDで  指定するビットを0あるいは1にします。  以下のように定義します。  void sta_tsk(UBYTE tid,UBYTE sta)  {   if ( tid >= TSK_ID_MAX ) return ;   if ( sta == TTS_READY ) {   ready |= (1 << tid);   suspend &= ~(1 << tid);   }   if ( sta == TTS_WAIT ) {   ready &= ~(1 << tid);   suspend &= ~(1 << tid);   }   if ( sta == TTS_SUSPEND ) {   ready &= ~(1 << tid);   suspend |= (1 << tid);   }  }

システムコールrsm_tsk

 rsm_tskは、タスクIDを使い、該当タスクをREADY状態にします。  タスクIDをパラメータとします。 rsm_tsk(TSK_ID1) ;  変数readyは、タスクIDで指定するビット位置の値を1にします。  変数suspendは、タスクIDで指定するビット位置の値を0にします。  以下のように定義します。  void rsm_tsk(UBYTE tid)  {   if ( tid >= TSK_ID_MAX ) return ;   ready |= (1 << tid);   suspend &= ~(1 << tid);  }

システムコールsus_tsk

 sus_tskは、タスクIDを使い、該当タスクをSUSPEND状態にします。  タスクIDをパラメータとします。 sus_tsk(TSK_ID2) ;  変数readyは、タスクIDで指定するビット位置の値を0にします。  変数suspendは、タスクIDで指定するビット位置の値を1にします。  以下のように定義します。  void sus_tsk(UBYTE tid)  {   if ( tid >= TSK_ID_MAX ) return ;   ready &= ~(1 << tid);   suspend |= (1 << tid);  }

システムコールslp_tsk

 slp_tskは、タスクが自身をSUSPEND状態にするときに使います。 slp_tsk() ;  タスクがCPUを使っているとき、タスクIDは変数run_tskに入っています。  システムコールsus_tskに、run_tskを入力しタスク自身の状態を変更します。  以下のように定義します。  void slp_tsk(void)  {   sus_tsk(run_tsk);  }

システムコールwai_tsk

 wai_tskは、タスクが自身をWAIT状態にするときに使います。 wai_tsk( 500 ) ;  USOでは、WAITは、自身で時間待ちをしている状態とします。  変数ready、suspendは、変数run_tskで指定するビット位置の値を0にします。  変数wcountにカウント値を設定します。  カウント値は、タイマー割込みでカウントダウンします。  カウント値が0になると、タイマー割込み内部で、該当タスクを  WAITからREADYに状態遷移させます。  システムコールそのものは、以下のように定義します。  void wai_tsk(UWORD x)  {   ready &= ~(1 << run_tsk);   suspend &= ~(1 << run_tsk);   tcb[run_tsk].wcount = x ;  }  WAITからREADYへの状態遷移の仕掛けは、別の章で説明します。
目次

inserted by FC2 system