SSブログ

Smalight OSを使おう 7タスク目 タスク管理を使う1 [Smalight OS]

※sus_tskは、引数にタスクID番号を取る事から、他タスクを強制的にSUSPENDさせるのが普通の使い方だと思いますが、ここでは引数に自タスクIDを使って、自分自身をSUSPENDに遷移させて見せています。

※この文章を読んで貰えれば判るかと思いますが、よくsmalight osの特徴として、小さく軽くて、更に簡単と言う文章を見受ける事ができますが、それはどうかと思います。つまり小さく軽く作る事の見返りとしてOS内部のチェックが甘くなり、と言うよりプログラマーのスキルに依存する事が前提となってしまっており、その辺をよく理解して使わないと、とんでもないバグを作り込む事になるかもしれません。 また、タスク間通信機能が一切無いのは、ちょっとやり難いなあ。イベントフラグで待ち解除時のパターンを戻り値として取得可能。 小さくて軽いと言うのは同意しますが。

この記事は、某SNSで書いているものを転載しています。
今回は最も基本的なサービスコールであるタスク管理機構を使ってみます。

前にsmalight osにおけるタスクの状態遷移を示しましたが、このタスク管理機構が提供する機能は、直接的に(自または他)タスクに対して状態の遷移を起させる物です。

サービスコールの動作を解説します。
まずはタスク部(タスクの中)から発行できるサービスコールです。

 自タスクをWAITに遷移させるには「slp_tsk」
 WAITのタスクをREADYに遷移させるには「wup_tsk」
 READYのタスクをSUSPENDに遷移させるには「sus_tsk」
 WAITのタスクをWAIT+SUSPENDに遷移させるには「sus_tsk」
 自タスクをSUSPENDに遷移させるには「sus_tsk」
 SUSPENDのタスクをREADYに遷移させるには「rsm_tsk」
 WAIT+SUSPENDのタスクをWAITに遷移させるには「rsm_tsk」
 WAIT+SUSPENDのタスクをSUSPENDに遷移させるには「wup_tsk」
 ローテーションタスクの順番の入れ替えを行う「rot_rdq」

※「sus_tsk」を実行中のタスクから自タスクIDを引数に使用する時には注意が必要です。
もし実行中のタスクが一時的に割り込みを禁止した状態で「sus_tsk」を発行してしまった時、それ以降割り込み禁止状態が継続する事となり、必要なディスパッチが発生しなくなる可能性が有ります。
本来はSUSPENDに入らず、エラーコードを返すべきかと思いますが、smalight osでは、OS自身でこのチェックを行う事は無く、プログラマーの責任となっています。

次いでOS管理下の割り込みハンドラから発行できるサービスコールです。

 WAITのタスクをREADYに遷移させるには「iwup_tsk」
 READYのタスクをSUSPENDに遷移させるには「isus_tsk」
 WAITのタスクをWAIT+SUSPENDに遷移させるには「isus_tsk」
 SUSPENDのタスクをREADYに遷移させるには「irsm_tsk」
 WAIT+SUSPENDのタスクをWAITに遷移させるには「irsm_tsk」
 WAIT+SUSPENDのタスクをSUSPENDに遷移させるには「iwup_tsk」
 ローテーションタスクの順番の入れ替えを行う「irot_rdq」

まずサービスコール名を見れば判る様に、同じ機能のサービスコールの先頭に"i"を付ける事で、割り込みハンドラで使用できるサービスコールである事を示しています。
タスク部から発行できるサービスコールとの違いは、割り込みの一番最後にディスパッチを行う為に、サービスコール内部ではディスパッチを行っていない点です。

※基本的に、割り込みハンドラの中から利用できるサービスコールには、自ら待ち状態に入るサービスコールを利用する事はできません。それは、割り込みの中で無限ループに入るのと同じだからです。
しかしsmalight osの場合はサービスコール内でチェックしませんので、この点もプログラマが注意する必要が有ります。

では、自タスクをWAITに遷移させる「slp_tsk」と、SUSPENDに遷移させる「sus_tsk」と、他タスクを起床させる「wup_tsk」と、SUSPENDを解除する「rsm_tsk」をやってみます。
今回のサンプルプログラムでは、tsk01とtsk02のみしか使用しませんし、システムタイマー、イベントフラグ、セマフォ等の時間管理機構やカーネルオブジェクトも使用しませんので、コンパイル時の定義や、config.cの要所、要所を適宜合わせて置いてください。

tsk01は優先度1、tsk02は優先度2として、またtsk02はWAITの状態で起動しますので、config.cを以下の様に編集します。

/*------ TCB Status Init -------------------------------------*/
/*
 * Task status Init : CTCB_ST_RDY | CTCB_ST_SLP | ...
 *                   ("slos.h" Refer to for details.)
 */
const UB knl_tcbStInit[KNL_TCB_NUM] = {
  CTCB_ST_RDY, /* TCB1   */
  CTCB_ST_SLP, /* TCB2   */
};


タスクはそれぞれ以下の様に記述します。

#define TID_1 1
#define TID_2 2

void tsk01( void )
{
  int i;

  for( i = 0; i < 2; i++ )
  {
    wup_tsk( TID_2 );
  }
  sus_tsk( TID_1 );  /*ここにブレークポイントを設定*/
  slp_tsk();  /*ここにブレークポイントを設定*/
}

void tsk02( void )
{
  while( 1 )
  {
    rsm_tsk( TID_1 );  /*ここにブレークポイントを設定*/
    slp_tsk();  /*ここにブレークポイントを設定*/
    p2_0 ^= 1;  /*ここにブレークポイントを設定*/
  }
}


さて、今回のサンプルの確認には、オンチップデバッカーを使用します。
コメントで「ここにブレークポイントを設定」と書かれた位置にブレークポイントを設定します。

それでは、「リセット後実行」でプログラムスタートしますと、まず最初に優先度1で起動したtsk01が、2回の「wup_tsk」の発行を行って、「sus_tsk」の位置で停止します。この「sus_tsk」は自らに向けて発行しているので、tsk01はこれ以降SUSPENDに遷移します。

この状態から「実行」を行うと、次はtsk02の「rsm_tsk」の位置で停止します。これは、tsk02はWAITで起動したのですが、tsk01の「wup_tsk」の発行によってREADYに遷移し、またtsk01が自ら待ち状態に入った為に、tsk02がRUNに遷移し、ここまでやって来たのです。

この状態から「実行」を行うと、次はtsk01の「slp_tsk」の位置で停止します。これはtsk02の「rsm_tsk」の発行でtsk01がSUSPENDからREADYに遷移し、さらに優先度が比較された時にtsk01の方が優先度が高かった為に、実行中のタスクが切り替わるプリエンプトが行われた為です。
しかしこれ以降、tsk01は自らWAITに遷移します。

この状態から「実行」を行うと、次はtsk02の「slp_tsk」の位置で停止します。勿論これはtsk01がWAITに遷移した事による、tsk02のREADYからRUNへの遷移が行われた為です。

この状態から「実行」を行うと、tsk02は自らWAITに遷移します。そして次の処理の「p2_0 ^= 1;」には決して到達しません。

μITRONと異なり、smalight osの場合、起床要求はキューイングされません。wup_tskを発行した場合、現在WAIT状態のタスクに対してのみ有効で(rsm_tskの場合はSUSPEND)、READY状態になったタスクには適用されませんので、tsk01で2回「wup_tsk」を発行したとしても、最初の一回しか効かなかったのです。

やっぱりC言語の開発スキルをアップしたいと言う事で、どうぞ!。

H8マイコン+C言語効率アップテクニック

H8マイコン+C言語効率アップテクニック

  • 作者: 鹿取 祐二
  • 出版社/メーカー: オーム社
  • 発売日: 2004/11
  • メディア: 単行本


nice!(0)  コメント(0)  トラックバック(0) 

nice! 0

コメント 0

コメントを書く

お名前:[必須]
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。

※ブログオーナーが承認したコメントのみ表示されます。

トラックバック 0

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。