はじめに
uITRON(FreeRTOSベース)Windowsシミュレータ - Qiita
https://qiita.com/imagou/items/42c687402e6e58fccddb
今回のお題は、何かあったことを伝えるイベントフラグです。
本編
1. 環境
こちらの記事を参照ください。
2. 動かしてみる
こちらは初回記事を参照。
2-1. タスクでのイベント設定・待ち
改めて「2-2. 送信タスク・受信タスク」の動作を確認してください。
2-2. 割り込みでのイベント設定
次にコンソールで「cyclic」と入力してみます。
[TimerTask]: DELAY 3000ms
cyclic
[SendTask]: RECV EVENT (00000001)
[SendTask]: Cyclic Timer Expired (1)
[TimerTask]: DELAY 3000ms
[SendTask]: RECV EVENT (00000001)
[SendTask]: Cyclic Timer Expired (2)
[SendTask]: RECV EVENT (00000001)
[SendTask]: Cyclic Timer Expired (3)
[SendTask]: RECV EVENT (00000001)
[SendTask]: Cyclic Timer Expired (4)
[TimerTask]: DELAY 3000ms
[SendTask]: RECV EVENT (00000001)
[SendTask]: Cyclic Timer Expired (5)
どうやら、1000msecおきに「Cyclic Timer Expired」が発生するようになったようです。
3. 解説
3-1. 概要
イベントフラグとは、前述したように**「何かが発生したことを伝える仕組み」**です。
型は32-bitであり、それぞれのビットにイベントを割り当てることができます。
3-2. コードによる説明
以降は、プログラムコード - main.c
を引用して説明します。
3-2-1. イベント定義
イベントの定義は以下。
/*--- Event ---*/
#define EVENT_ALL (0x00FFFFFF) /* FreeRTOS仕様制限で、最大で24-bit */
#define EVENT_CYCLIC (0x00000001)
/* Reserved bit1 - bit15 */
#define EVENT_STOP (0x00010000)
#define EVENT_RESTART (0x00020000)
コメントにあるように、FreeRTOS制限で24-bitしか使えないのですが(笑)、日本語で書くと以下の割り当てとなっています。
bit | 説明 |
---|---|
bit0 | CYCLICイベント(周期タイマを開始するイベント) |
bit1 - bit15 | 予約(数値を通知するイベント) |
bit16 | 停止イベント |
bit17 | 再開イベント |
3-2-2. イベントフラグ生成
cre_flg()
で生成します。
T_CFLG cflg;
cflg.flgatr = TA_WSGL;
cflg.iflgptn = 0;
cre_flg(FLAG_ID(SEND), &cflg);
cre_flg()
のパラメータは下表:
パラメータ番号 | 名称 | 説明 |
---|---|---|
第1パラメータ | イベントフラグID | 単なるID。 以降はこのIDでもってイベントフラグ設定・待ちを実施。 |
第2パラメータ | T_CFLG構造体変数 | 以下で説明 |
T_CFLGのメンバは下表:
名称 | 指定可能な値 | 説明 |
---|---|---|
flgatr | TA_WSGL | TA_WMUL | イベントフラグ属性。 それぞれ、1つのタスクで待つか・複数のタスクで待つか。 たいていの場合はTA_WSGLでよい。 |
iflgptn | イベントフラグ初期値 | 左記の通り。たいていの場合は0でよいだろう。 |
※なお、flgatrはこれ以外の値も指定可能(だが、TA_WSGLで必要十分と考える)。
3-2-3. イベントフラグ設定
通常のタスクではset_flg()
を使います。
/* Numeric Event (1 To 15) */
if ((0 < num) && (num < 16)) {
set_flg(FLAG_ID(SEND), (1 << num));
}
#define EQUALS_(x) (0 == strcmp(str, #x))
/* Suspend */
else if (EQUALS_(stop)) {
set_flg(FLAG_ID(SEND), EVENT_STOP);
}
/* Resume */
else if (EQUALS_(start)) {
set_flg(FLAG_ID(SEND), EVENT_RESTART);
}
上記コードでは、以下のイベントを設定しています:
- 数値が指定されたら、対応するビットを立てたイベント
- 「stop」「start」が指定されたら、それぞれ停止・再開イベント
対して、割り込みではiset_flg()
を用います。
static void UserCyclicHandler(void* params)
{
/* Just to remove compiler warning. */
(void)params;
iset_flg(FLAG_ID(SEND), EVENT_CYCLIC);
}
こちらは、CYCLICイベントを設定しています。
3-2-4. イベント待ち
wai_flg()
を使用します。
FLGPTN flgptn;
wai_flg(FLAG_ID(SEND), EVENT_ALL, TWF_ORW, &flgptn);
DEBUG_PRINT("[%s]: RECV EVENT (%08X)", __func__, flgptn);
/* Suspend Task */
if (flgptn & EVENT_STOP) {
sus_tsk(TASK_ID(RECV));
continue;
}
/* Resume Task */
if (flgptn & EVENT_RESTART) {
rsm_tsk(TASK_ID(RECV));
continue;
}
/* Cyclic Event */
if (flgptn & EVENT_CYCLIC) {
static int32_t expired = 0;
DEBUG_PRINT("[%s]: Cyclic Timer Expired (%d)", __func__, ++expired);
continue;
}
wai_flg()
のパラメータで重要なものは以下:
パラメータ番号 | 指定可能な値 | 説明 |
---|---|---|
第2パラメータ | 待ち合わせるビットパターン | 本デモではすべてのビットを指定 |
第3パラメータ | TWF_ANDW / TWF_ORW | 指定したビットがすべて立つまで待つ / いずれか1つが立つまで待つ |
第4パラメータ | 受信したビットパターン |
第4パラメータflgptn
でもって、それ以降の判定を実施しています。
また、数値用イベントのコードは抜粋していませんので、コードを直接参照ください(雑)。
3-3. TBD
TBD(今後追加していく予定)
おわりに
1ビットだけでは情報が足りない場合は、メールボックス(メッセージ)を使いましょう(次回への伏線)。
参考
Micro-ITRON4.0 Specification (in Japanese)
http://www.ertl.jp/ITRON/SPEC/mitron4-j.html