Nucleus SEのキュー:導入とコアサービスコール
RTOS Revealedシリーズを表示
キューは以前の記事で導入されました。メールボックスより柔軟にタスク間でシンプルなメッセージを渡す手段を提供します。
キューの使用
Nucleus SEでは、キューはビルド時に設定されます。アプリケーションあたり最大16キューまで定義可能。キューを設定しない場合、RTOSはすべてのキュー関連データ構造とAPIコードを省略し、バイナリをスリムに保ちます。
キューは単純に、単一のADDRデータ項目を保持するのに十分なストレージスロットの配列です。アクセスは同期化され、複数タスクが安全にエンキューとデキューを行えます。タスクはすべてのスロットが満杯になるまでキューへ書き込み、先入れ先出し(FIFO)順でキューから読み取ります。満杯キューへの送信や空キューからの受信試行は、選択されたAPIオプションとNucleus SE設定に応じてエラーまたはタスクサスペンドをトリガーします。
キュー vs パイプ
Nucleus SEはパイプもサポートします。主な違いはメッセージサイズです。キューが単一ADDR(通常ポインタ)を伝送するのに対し、パイプは可変長バイトブロックを運び、ブロックサイズは設定時に固定されます。パイプは今後の記事で詳細に扱います。
キューの設定
キュー数
キュー設定はnuse_config.h内の#define文で制御されます。鍵設定はNUSE_QUEUE_NUMBERで、有効化するキュー数を決定。デフォルトは0(キューなし)。0~16の任意値を設定可能;範囲外値はnuse_config_check.hによるコンパイル時#errorをトリガー。
NUSE_QUEUE_NUMBERを非ゼロに設定するとキュー サブシステムが活性化し、必要なデータ構造が割り当てられ、関連API呼び出しが有効化されます。
API有効化
各キューAPI関数にはnuse_config.hに有効化#defineシンボルがあります:
NUSE_QUEUE_SEND NUSE_QUEUE_RECEIVE NUSE_QUEUE_JAM NUSE_QUEUE_RESET NUSE_QUEUE_INFORMATION NUSE_QUEUE_COUNT
デフォルトではすべてFALSEで、対応するサービスコールを無効化。特定APIを使用するにはそのシンボルをTRUEに設定。キュー未設定でAPI有効化(NUSE_Queue_Count()は常に許可)はコンパイルエラー。コード内で未有効APIを呼ぶと実装省略によりリンクエラー。
#define NUSE_QUEUE_NUMBER 0 /* システム内のキュー数 – 0-16 */ /* サービスコール有効化 */ #define NUSE_QUEUE_SEND FALSE #define NUSE_QUEUE_RECEIVE FALSE #define NUSE_QUEUE_JAM FALSE #define NUSE_QUEUE_RESET FALSE #define NUSE_QUEUE_INFORMATION FALSE #define NUSE_QUEUE_COUNT FALSE
キュー サービスコール
Nucleus RTOSには10のキュー関連サービスコールがあり、うち6つがNucleus SEで実装されています。提供機能:
- メッセージ送信 – NUSE_Queue_Send()
- メッセージ受信 – NUSE_Queue_Receive()
- メッセージを先頭へ割り込み – NUSE_Queue_Jam()
- キュー リセット – NUSE_Queue_Reset()
- キュー情報照会 – NUSE_Queue_Information()
- 設定済みキュー数取得 – NUSE_Queue_Count()
- 残り(作成、削除、列挙、ブロードキャスト)はNucleus SEでは不可。
各APIの実装は以降のセクションで詳細に議論されます。
書き込みと読み取りサービス
キューのコア操作は書き込み(送信)と読み取り(受信)です。キューの先頭への書き込みはジャムと呼ばれます。Nucleus RTOSとNucleus SEはこれらアクション用の3つの基本API呼び出しをそれぞれ公開します。
キューへの書き込み
RTOS APINU_Send_To_Queue()は高柔軟で、キュー満杯時の無期限サスペンドやタイムアウトを許可。Nucleus SEは同機能だがサスペンドはオプションでタイムアウト非サポート。RTOSはブロードキャスト操作もサポートするがSEでは不可。
RTOS API: NU_Send_To_Queue()
プロトタイプ:
STATUS NU_Send_To_Queue(NU_QUEUE *queue, VOID *message, UNSIGNED size, UNSIGNED suspend);
パラメータ:
- queue – ユーザー提供キュー制御ブロックへのポインタ
- message – 送信データへのポインタ
- size – UNSIGNED要素数;キューのメッセージサイズと一致必須
- suspend – NU_NO_SUSPEND、NU_SUSPEND、またはタイムアウト値
戻りコードにはNU_SUCCESS、NU_QUEUE_FULL、NU_TIMEOUT、無効ポインタやキュー状態の各種エラーコードが含まれます。
SE API: NUSE_Queue_Send()
プロトタイプ:
STATUS NUSE_Queue_Send(NUSE_QUEUE queue, ADDR *message, U8 suspend);
パラメータ:
- queue – キューインデックス(ID)
- message – エンキューするADDR値へのポインタ
- suspend – NUSE_NO_SUSPENDまたはNUSE_SUSPEND
戻り値はRTOS関数を反映するが、SEの限定的ブロッキング挙動を反映。
実装概要
ブロッキング無効時、ルーチンは単純にスペースをチェックし、値を書き込むかNUSE_QUEUE_FULLを返す。ブロッキング有効時、関数はループし、キューが満杯ならスペースが空くかリセットされるまでタスクをサスペンド。実装はNUSE_Queue_Blocking_Countでブロックタスクを追跡し、NUSE_Task_Blocking_Returnでスロット開放時にレジュームさせます。
if (NUSE_Queue_Items[queue] == NUSE_Queue_Size[queue]) { return_value = NUSE_QUEUE_FULL; } else { NUSE_Queue_Data[queue][NUSE_Queue_Head[queue]++] = *message; if (NUSE_Queue_Head[queue] == NUSE_Queue_Size[queue]) NUSE_Queue_Head[queue] = 0; NUSE_Queue_Items[queue]++; return_value = NUSE_SUCCESS; }
do { if (NUSE_Queue_Items[queue] == NUSE_Queue_Size[queue]) { if (suspend == NUSE_NO_SUSPEND) { return_value = NUSE_QUEUE_FULL; } else { NUSE_Queue_Blocking_Count[queue]++; NUSE_Suspend_Task(NUSE_Task_Active, (queue << 4) | NUSE_QUEUE_SUSPEND); return_value = NUSE_Task_Blocking_Return[NUSE_Task_Active]; if (return_value != NUSE_SUCCESS) suspend = NUSE_NO_SUSPEND; } } else { NUSE_Queue_Data[queue][NUSE_Queue_Head[queue]++] = *message; if (NUSE_Queue_Head[queue] == NUSE_Queue_Size[queue]) NUSE_Queue_Head[queue] = 0; NUSE_Queue_Items[queue]++; if (NUSE_Queue_Blocking_Count[queue] != 0) { U8 index; NUSE_Queue_Blocking_Count[queue]--; for (index = 0; index < NUSE_TASK_NUMBER; index++) { if ((LONIB(NUSE_Task_Status[index]) == NUSE_QUEUE_SUSPEND) && (HINIB(NUSE_Task_Status[index]) == queue)) { NUSE_Task_Blocking_Return[index] = NUSE_SUCCESS; NUSE_Wake_Task(index); break; } } } return_value = NUSE_SUCCESS; suspend = NUSE_NO_SUSPEND; } } while (suspend == NUSE_SUSPEND);
ループはメッセージが正常にエンキューされるか、リセットによってタスクがアンブロックされるまで継続。実装はスレッドセーフなアクセスとブロック中コンシューマの効率的なウェイクアップを保証します。
埋め込み
- 精密平面研削サービス:エキスパートプロセスと品質
- カムロック完全解説:キャビネットを目立たず確実に施錠する仕組み
- アイボルト(アイスクリュー)とは:設計と用途のプロフェッショナルガイド
- グロメット完全ガイド:種類・用途・機器保護の仕組み
- ステンレス鋼解説:組成・製造プロセス・グローバルインパクト
- Nucleus SEのメールボックス:設定と使用の実践ガイド
- Nucleus RTOSのセマフォ:ユーティリティサービスとデータ構造
- Nucleus SEのセマフォ:概要、設定、API要点
- イベントフラググループの習得:Nucleus RTOS/SEのユーティリティサービスとデータ構造
- Nucleus SEのイベントフラググループ:設定とAPI使用の入門ガイド
- C# 入出力の基礎:ユーザー入力と出力の基本をマスター