Help us understand the problem. What is going on with this article?

Windowsシミュレータで学ぶuITRON (3) - メールボックス

はじめに

uITRON(FreeRTOSベース)Windowsシミュレータ - Qiita
https://qiita.com/imagou/items/42c687402e6e58fccddb

今回のお題は、何かあったことに加え、追加情報を伝えるメールボックスです。
(「何かあったこと」のみであれば、イベントフラグでOK)

本編

1. 環境

こちらの記事を参照ください。

2. 動かしてみる

こちらは初回記事を参照。

2-1. タスクでのメール送受信

改めて「2-2. 送信タスク・受信タスク」の動作を確認してください。

3. 解説

3-1. 概要

メールボックスとは、前述したように「何かが発生したことに加え、情報を伝える仕組み」です。
(「メール」って名称からお察しではありますが・・・)

メールの型(メッセージという呼び方をします)はユーザーで自由に決められます。
若干面倒なポイントは以下です:

  • ユーザーがメッセージ領域を確保する必要あり
  • メッセージの取得・解放もユーザーの責務

3-2. コードによる説明

以降は、プログラムコード - main.cを引用して説明します。

3-2-1. メッセージ定義・領域確保

メッセージの型と、領域(64個分)の確保箇所は以下です。

/*--- Message ---*/
typedef struct {
    T_MSG       msg;
    ID          id;
    uint32_t    params[1];
} MESSAGE_ENTITY;

#define MESSAGE_SIZE    (64)
static MESSAGE_ENTITY   g_Messages[MESSAGE_SIZE];
static uint16_t         g_MessageIndex = 0;

注意事項として、構造体先頭のT_MSG msg;は必ず含めてください。RTOSの予約領域です。

3-2-2. メッセージ取得・解放

以下を参照ください。

/* メッセージ取得 */
static MESSAGE_ENTITY* GetUserMessage(void) {
    uint16_t index = g_MessageIndex++;
    index %= MESSAGE_SIZE;
    return &(g_Messages[index]);
}
/* 解放はまだ用意していない */

GetUserMessage()は、リングバッファとして領域を扱い、返しているだけです。

解放は色々あって未実装ですが、メッセージを同時に64個以上送信することがなければ、なくてもいいかなーと思っています(面倒くさいわけではないですよ!笑)。

3-2-3. メールボックス生成

cre_mbx()で生成します。

    T_CMBX cmbx;
    cmbx.mbxatr = TA_TFIFO;
    cre_mbx(MAILBOX_ID(RECV), &cmbx);

cre_mbx()のパラメータは下表:

パラメータ番号 名称 説明
第1パラメータ メールボックスID 単なるID。
以降はこのIDでもってメールボックス送信・受信を実施。
第2パラメータ T_CMBX構造体変数 以下で説明

T_CMBXのメンバは下表:

名称 指定可能な値 説明
mbxatr TA_TFIFO | TA_TPRI メールボックス属性。
それぞれ、待ちキューの順序をFIFO順とするか、優先度順とするか。

※なお、mbxatrはこれ以外の値も指定可能(だが、上記のみで必要十分と考える)。

3-2-4. メールボックスへの送信

snd_mbx()を使います。
idにはイベントを数値に変換したもの、params[0]にはカウンタを渡して送信しています。

        MESSAGE_ENTITY* ent;
        ent = GetUserMessage();
        /* Numeric Event */
        /* メッセージIDはイベントを(数値に戻して)設定 */
        /* パラメータにカウンタを渡す */
        int32_t num = 0;
        for (num = 0; !((flgptn >> num) & 1) ; num++) ;
        ent->id = (ID)num;
        ent->params[0] = ++count;

        snd_mbx(MAILBOX_ID(RECV), (T_MSG *)ent);

3-2-5. メールボックスからの受信

rcv_mbx()を使用します。

        T_MSG *msg;
        rcv_mbx(MAILBOX_ID(RECV), &msg);
        MESSAGE_ENTITY* ent = (MESSAGE_ENTITY*)(msg);
        DEBUG_PRINT("[%s]: RECV MESSAGE (%d,%d)", __func__, ent->id, ent->params[0]);

3-3. TBD

TBD(今後追加していく予定)

おわりに

メールボックスは、メッセージ領域の確保が若干面倒なので、
イベントフラグ+外部変数
という使い方をする方も多いように思います(やってることは変わりませんからね)。
が、一応解説してみました。笑

参考

Micro-ITRON4.0 Specification (in Japanese)
http://www.ertl.jp/ITRON/SPEC/mitron4-j.html

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away