はじめに
uITRON(FreeRTOSベース)Windowsシミュレータ - Qiita
https://qiita.com/imagou/items/42c687402e6e58fccddb
にて、せっかくuITRONを体験できる環境を作りましたんで、体験してみましょう。
今回のお題は、**RTOSの肝である「タスク」**です。
本編
1. 環境
前回記事を参照ください。
2. 動かしてみる
ビルド方法はこちら。
後はF5押下などしてやれば、コンソールウインドウでデモプログラムが動きます。
2-1. タイマタスク
放置しておくと、コンソールで以下が出力されるはずです。
[TimerTask]: DELAY 3000ms
[TimerTask]: DELAY 3000ms
[TimerTask]: DELAY 3000ms
[TimerTask]: DELAY 3000ms
TimerTask
とやらが、3000msecおきに動作しているらしい、ということがわかるかと思います。
(当方の環境ですと3000msecより相当長いですが、その解析は後回し)
2-2. 送信タスク・受信タスク
まずはコンソールで「10」と入力してみましょう(入力後にEnterを押してください)。
[TimerTask]: DELAY 3000ms
[TimerTask]: DELAY 3000ms
10
[SendTask]: RECV EVENT (00000400)
[RecvTask]: RECV MESSAGE (10,1)
どうやら「10」がSendTask
からRecvTask
に通知されているようです。
そこで次は、「stop」を入力後、再度「10」を入力してみます。
[TimerTask]: DELAY 3000ms
stop
[SendTask]: RECV EVENT (00010000)
10
[SendTask]: RECV EVENT (00000400)
[TimerTask]: DELAY 3000ms
おや?今回はRecvTask
が動いていませんね。
次に「start」を入力します。
[TimerTask]: DELAY 3000ms
start
[SendTask]: RECV EVENT (00020000)
[RecvTask]: RECV MESSAGE (10,2)
お察しの通り、RecvTask
が動き出し、先ほどの「10」を受信しています。
2-3. もっと動かしたくなったら
使い方を読んでください(雑)。
3. コードによる解説
では、プログラムコード - main.c
を引用して説明します。
なお、実際に裏で動いているのはFreeRTOSですので、その制限を受けています。
3-1. タスク生成
cre_tsk()
を使います。
#define CREATE_TASK(name, act, func) { \
T_CTSK ctsk_; \
ATR tskatr_ = TA_HLNG; \
if (act) tskatr_ |= TA_ACT; \
ctsk_.tskatr = tskatr_; /* タスク属性 */ \
ctsk_.exinf = NULL; /* タスク起動時パラメータ */ \
ctsk_.task = func; /* タスク関数 */ \
ctsk_.itskpri = TASK_PRI(name); /* タスクの優先度 */ \
ctsk_.stksz = sizeof(TASK_STACK(name)); /* タスクスタックサイズ */ \
ctsk_.stk = TASK_STACK(name); /* タスクスタック(静的に確保しておく必要あり) */ \
cre_tsk(TASK_ID(name), &ctsk_); \
}
マクロ定義しちゃってますが、要は以下を指定して、タスクを生成しています。
- タスク属性(TA_ACT指定で即「実行可能状態」となる)
- タスク関数
- 優先度
- スタックとそのサイズ
3-2. タスク起動・中断・再開
3-2-1. タスク起動
CREATE_TASK(TIMER, FALSE, TimerTask);
とあるように、TimerTask
- タイマタスクは遅延起動しているので、sta_tsk()
を明示的に呼ぶ必要があります。
/* タイマタスクは遅延起動 */
/* sta_tsk()を使いたいがためだけにこうしている */
sta_tsk(TASK_ID(TIMER), NULL);
3-2-2. タスク中断・再開
それぞれsus_tsk()
とrsm_tsk()
を使います。
/* Suspend Task */
if (flgptn & EVENT_STOP) {
sus_tsk(TASK_ID(RECV));
continue;
}
/* Resume Task */
if (flgptn & EVENT_RESTART) {
rsm_tsk(TASK_ID(RECV));
continue;
}
3-2-3. 補足
uITRONでは「待ち状態 - WAITING」「強制待ち状態 - SUSPENDED」の区別があります。
関数との関係はこちら:
- 「待ち状態」から「実行可能状態 - READY」とするのが
sta_tsk()
- 「実行状態」などから「強制待ち状態」とするのが
sus_tsk()
- 「強制待ち状態」から「実行可能状態」とするのが
rsm_tsk()
しかしながら、FreeRTOSには「SUSPENDED」状態しかないらしく、よってsta_tsk()
とrsm_tsk()
の本シュミレータ上の実装は同じです。
3-3. タスク遅延
dly_tsk()
を使います。
while (1) {
RELTIM tim = 3000;
DEBUG_PRINT("[%s]: DELAY %dms", __func__, tim);
dly_tsk(tim);
}
3-4. TBD
TBD(今後追加していく予定)
おわりに
簡単(フワフワっとした)なタスク操作の説明でした。
読むだけでなく、実際に動かしてみると、より理解が深まるかと思います!
参考
FreeRTOS API categories
https://www.freertos.org/a00106.html
Micro-ITRON4.0 Specification (in Japanese)
http://www.ertl.jp/ITRON/SPEC/mitron4-j.html