ここでは、Toppers/ASP3のタスク以外の実装方法について解説します。CARTOS編と同様の環境で使用することを前提としていますので、併せてご覧ください。
あわせて読みたい
あわせて読みたい
イベントフラグ
イベントフラグについても、簡単に触れておきます。
イベントフラグの場合は、T_CFLG
を使用しています。
T_CFLG flg; flg.flgatr = TA_CLR; flg.iflgptn = 0;
イベントフラグの生成
fid = acre_flg(&flg);
イベントフラグのセット
set_flg(fid, FLG_PTN);
※FLG_PTN
は任意の32ビット長
タスクでイベントフラグを使うときは、wai_flg
でイベントフラグがセットされるのを待ちます。
イベントフラグの使用例
void adc_task(intptr_t exif) { FLGPTN flg_ptn; /* ToDo */ for(;;) { wai_flg(fid, FLG_PTN, TWF_ANDW, &flg_ptn); clr_flg(fid, 0); } }
イベントフラグを待つときは、事前にFLGPTN flg_ptn
を定義して、フラグパターンを受け取とれるようにする必要があります。そして、wai_flg(…)
は、対象とするイベントフラグID(fid)
が、指定パターン(FLG_PTN)
と受け取ったフラグパターン(flg_ptn)
が完全一致(TWF_ANDW)
した時にだけ、次の行を実行することができます。それ以外の場合は、他のタスクに処理が移ります。(通常、この動作を「ディスパッチされる」と言ったりします。)
また、wai_flg()
でパターンが合致した場合は、受け取ったフラグのパターンをクリアしてやる必要があります。clr_flg(fid, 0);
とすることで、イベントフラグが解除され、この例のタスクの場合、またイベントフラグ待ちになります。
図1は、イベントフラグをセットしたところでプログラムを止めた時のRTOSビューアーの様子です。フラグパターンが0x5555AAAA
にセットされたことがわかります。
周期ハンドラの設定
周期ハンドラについても、簡単に触れておきます。
周期ハンドラの登録
周期ハンドラの場合は、T_CCYC
とT_NFYINFO
を使用しています。この例では、cyc_func
という周期ハンドラを10秒ごとに起動させます。
T_CCYC cyc; T_NFYINFO nfy; nfy.nfymode = 0; nfy.nfy.handler.tmehdr = cyc_func; cyc.cycatr = TA_NULL; cyc.nfyinfo = nfy; cyc.cyctim = (RELTIM)10000000; cyc.cycphs = (RELTIM)10000000; /** 周期ハンドラ本体は、タスクと同じように、関数のように記述します。 */ void cyc_func(intptr_t exif) { /* ToDo */ }
周期ハンドラの生成
周期ハンドラの生成は、acre_cyc
です。
cycid = acre_cyc(&cyc);
周期ハンドラの起動
周期ハンドラの起動は、sta_cyc
です。
ercd = sta_cyc(cycid);
図2は、RTOSビューアーで周期ハンドラの状態を確認したものです。
割り込みの設定
割り込みは、どんなにCPUが速くなってもほぼ全てのシステムで使われるといっても過言ではないでしょう。それだけ、多くの組込みシステム開発に使われています。
SOLID-OSによる割り込みは、Toppers/ASP3がベースになっており、カーネルの管理下で割り込みの処理を行いますので、「割り込みサービスルーチン(ISR)」または「管理内割り込み」と呼んだりします。それ以外のものは、「割り込みハンドラ」もしくは「カーネル管理外割り込み」と呼びます。
割り込みベクタテーブル
組み込みシステムで割り込みを使う場合、いくつかファイルをいじらなければいけなくなります。その一つが、割り込みベクターテーブルと呼ばれるものです。
SOLID-OSの場合も、基本的には同じ考えではありますが、kernel_cfg.c
の中で登録できてしまいます。実際に見てみましょう。
使用する割り込みリソースの数を登録します。kernel_cfg.c中で以下のように定義します。
#define TNUM_AID_ISR 0 //ISR(割り込みサービスルーチン
ISRとして2本使用する場合は、以下のように定義します。
#define TNUM_AID_ISR 2 //ISR(割り込みサービスルーチン
割り込み初期化設定ブロック
次に、「割り込み初期化設定ブロック」の設定をします。今回は、CARTOS編の第4回で使用したGPIを割り込みとして使用します。RZ/Aの場合は、割り込みIDが該当し、GPI_2
が34
、GPI_3
が35
になります。
const INTINIB _kernel_intinib_table[] = { {34, TA_NULL, INTINIB_USE_ISR, TA_NULL, -16}, {35, TA_NULL, INTINIB_USE_ISR, TA_NULL, -16}, }
この内容で登録します。もし、他の割り込みソースを使用するのであれば、割り込みIDを変更して下さい。この設定が、割り込みベクターテーブルへの登録に該当します。SOLID-OSは、kernel_cfg.c
内で記述できるので、とても便利ですね。
あわせて読みたい
割り込みサービスルーチンの登録
次に、割り込みサービスルーチンの登録です。T_CISR
を使用します。
T_CISR adisr[2]; adisr[0].isr = adc_start_isr; adisr[0].intno = 34; adisr[0].isratr = TA_NULL; adisr[0].isrpri = 2; adisr[1].isr = adc_stop_isr; adisr[1].intno = 35; adisr[1].isratr = TA_NULL; adisr[1].isrpri = 2;
adisr[0]
で登録しているのは、「スタートボタン」を割り込みとして使用した時の設定で、GPI_2
にアサインされています。そして、割り込みの優先度は比較的高くしているので、「2
」としています。割り込みサービスルーチンに該当する関数は、「adc_start_isr
」としています。
adc_start_isr
は、下記のようにしています。
void adc_start_isr(intptr_t exif) { /* フラグ設定 */ /* 待ち状態のタスクを起動*/ wup_tsk(…); }
同じように、adisr[1]
には、「ストップボタン」として登録し、GPI_3
をアサインしています。割り込みサービスルーチンの関数としては、「adc_stop_isr
」としています。
adc_stop_isr
は、下記のようにしています。
void adc_start_isr(intptr_t exif) { /* フラグ設定 */ }
ここでのフラグ設定は、イベントフラグではなく、グローバル変数のフラグを設定しているだけです(図3)。もちろん、イベントフラグを指定しても構いません。
同じμITRON系でも割り込みサービスルーチン内でタスクの制御を行う場合は、iwup_tsk
としなければいけないものもありますが、Toppers/ASP3の場合は、同一のものとして扱われます。
割り込みサービスルーチンの生成
割り込みの登録ができたら、割り込みサービスルーチンを生成する必要があります。
acre_isr(&adisr[0]); acre_isr(&adisr[1]);
これで割り込みサービスルーチンがカーネル管理下に登録されました。
割り込みの許可と禁止
割り込みサービスルーチンを動かすためには、割り込みを許可する必要があります。
割り込み許可と割り込み禁止
- 割り込み許可
ena_int(…)
- 割り込み禁止
dis_int(…)
引数には、該当する割り込み番号(RZ/Aでは、割り込みID)を指定する必要があります。これで、いつでもボタンの割り込みが働くようになります。今回は、実際にSOLID-OSのリソースを使用して、タスク、イベントフラグ、周期ハンドラ、割り込みサービスルーチンの使用方法まで触れてみました。
あわせて読みたい
こちらも是非
“もっと見る” RTOS編
組み込みソフトウェア開発にRTOSを採用する場合の「4つの心得」
リアルタイムOSを使った組み込みソフトウェア開発を行う際、覚えておいたほうがよい「4つの心得」を紹介しましょう。
組み込みOSに最適なのは?リアルタイムOSとLinuxの違い
組み込みシステムの構成を考えていく上で、どのOSを採用するかは、開発初期段階においてとても重要です。一般的には、時間的制約があるシステムの場合はリアルタイムOSが、ネットワークやファイルシステム、高度なグラフィカル表示が必要な場合はLinuxが向いていると言われています。
割り込み
割り込みは、タスクとは独立して実行される処理です。そこで、T-Kernelにおける割り込みの利用方法に加えて、実行時のコンテキストの違いから生じる動作の違い、割り込みハンドラの作成方法や動作の詳細を説明します。