タスクとは
今回からは、リアルタイムOSが提供する機能について説明します。
毎回サンプルプログラムを示しながら、リアルタイムOSが提供する機能について具体的に説明していきます。なお、本稿で説明するサンプルプログラムは、T-Engineフォーラムが無償でソースコードを配布しているT-Kernel 2.0で実際に動作させることができます。
T-Kernel 2.0は、Arm11を搭載したT-Engineリファレンスボードに対応していますが、Windows PCで動作するCPUエミュレータ(Arm11をエミュレートします)や統合開発環境(Eclipse)も用意してあります。Windows PCがあればT-Kernel 2.0のプログラムを動作させることができますので、是非、毎回プログラムを実行して実際のリアルタイムOSの動作を確認してみてください。
タスクとは?
一般に、組み込み機器にはいろいろな機能が必要とされます。例えば、センサーの値を読み取って結果を解析するとか、画面に図形を描画するとか、ネットワーク経由で外部と通信するとか。これらはそれぞれが独立して動作できる機能です。
T-Kernel 2.0(以降、単にT-Kernelとします)には、このような複数の処理を並列して実行させる機能があります。T-Kernelでは、このような並列に実行する際の処理の単位を「タスク」と呼びます。T-Kernelで動作させるプログラムは、一つのタスクの中では逐次的に実行されますが、異なるタスクの間では並行して実行されることになります。
ただし、「並行して実行される」というのはアプリケーションからみた概念的な動作であり、実際にはT-Kernelが自動的に複数のタスクを切り換えて実行しています。
では、具体的にはどうやってタスクを記述するのか?
T-KernelのタスクはC言語の関数として記述できます。C言語で関数を作って、それをT-Kernelに登録すれば、後はT-Kernelがタスクとして実行してくれます。
例えば、以下の例では5行目〜12行目と14行目〜21行目の関数がタスクとして実行されるプログラムになります。2つとも一定時間毎にメッセージを出力するだけのシンプルなタスクですが、基本的なタスクの書き方はこのプログラムに含まれています。この基本さえおさえておけば、T-Kernelを使ったマルチタスクのプログラムを開発することができます。
【リスト1:タスクAのdoWorkAはタスクBのdoWorkBが完了してから実行する】
#include <basic.h> /* 型などの基本的な定義 */ #include <tk/tkernel.h> /* T-Kernel関連の定義 */ #include <tm/tmonitor.h> /* モニタ機能を使う場合の定義 */ void taskA( INT stacd, VP exinf ) /* タスクA(関数名は任意) */ { while(1){ tm_putstring( (UB*)"I'm Task A.¥n" ); tk_dly_tsk( 1000 ); /* 処理を1秒間保留 */ } tk_ext_tsk(); /* タスクの終了 */ } void taskB( INT stacd, VP exinf ) /* タスクB(関数名は任意) */ { while(1){ tm_putstring( (UB*)"I'm Task B.¥n" ); tk_dly_tsk( 2000 ); /* 処理を2秒間保留 */ } tk_ext_tsk(); /* タスクの終了 */ } EXPORT INT usermain( void ) /* 初期タスクから呼ばれる関数 */ { T_CTSK ctskA = { NULL, TA_HLNG|TA_RNG0, taskA, 1, 4*1024 }; T_CTSK ctskB = { NULL, TA_HLNG|TA_RNG0, taskB, 1, 4*1024 }; ID tskIdA; /* タスクAの識別子 */ ID tskIdB; /* タスクBの識別子 */ tskIdA = tk_cre_tsk( &ctskA ); /* T-KernelにタスクAを登録 */ tk_sta_tsk( tskIdA, 0 ); /* タスクAの実行を開始 */ tskIdB = tk_cre_tsk( &ctskB ); /* T-KernelにタスクBを登録 */ tk_sta_tsk( tskIdB, 0 ); /* タスクBの実行を開始 */ tk_slp_tsk(TMO_FEVR); /* 起床待ち状態に移行 */ return 0; }
タスク間通信
組み込みシステムの場合は、各タスクが連携して一つの処理単位となることも多いものです。その時に使用するのが、「タスク間通信」と呼ばれるものです。タスク間通信を上手に使いこなせると、組み込みシステムの設計が楽になることと、実際に動いた時は、とても感慨深いものになります。ぜひ使いこなせるようにしましょう。
イベントフラグによる割り込みとの同期
タスク間通信で、イベントフラグを使用すると、「〇〇がセットされたら、△△をする」と言った処理が簡単に「システマチック」に組み込むことができます。これらの処理は、以前から「フラグで待つ」とか、「ポーリングで待つ」などで活用されていました。RTOSでは、データのサイズに応じて、イベントフラグやセマフォ、メールボックス、データキュー、メッセージバッファ、ランデブーなどの仕組みが用意されています。
組み込みシステムでは、周辺機能や外部の要因に対する外部割り込み機能が数多く実装されています。これを有効に活用するために必要なのが、「割り込み」です。例外という言い方もします。この割り込みを使用して、どうシステムを構築していくかで、システムの性能やパフォーマンスも改善することがあります。
もちろん、RTOSを使用した場合と、そうでない場合の差は、0ではありませんが、扱いやすさはかなり違います。
こちらも是非
“もっと見る” RTOS編
Toppers/ASP3の使い方
SOLID-OSによる割り込みは、Toppers/ASP3がベースになっており、カーネルの管理下で割り込みの処理を行いますので、「割り込みサービスルーチン(ISR)」または「管理内割り込み」と呼んだりします。それ以外のものは、「割り込みハンドラ」もしくは「カーネル管理外割り込み」と呼びます。
組み込みソフトウェア開発にRTOSを採用する場合の「4つの心得」
リアルタイムOSを使った組み込みソフトウェア開発を行う際、覚えておいたほうがよい「4つの心得」を紹介しましょう。
組み込みOSに最適なのは?リアルタイムOSとLinuxの違い
組み込みシステムの構成を考えていく上で、どのOSを採用するかは、開発初期段階においてとても重要です。一般的には、時間的制約があるシステムの場合はリアルタイムOSが、ネットワークやファイルシステム、高度なグラフィカル表示が必要な場合はLinuxが向いていると言われています。