uCOS タスクのメッセージ キュー関連機能について

タスクメッセージキュー: タスクメッセージキューはタスクセマフォと同様に各タスクのTCB内に存在し、その要素はOS_MSG_Q MsgQとして定義されており、別途作成する必要はなく、関連する作成関数もありません。タスクのメッセージ キューは各タスクに固有であり、タスク自体のみが自身のタスク メッセージ キューを介してメッセージを取得でき、他のタスクはこのメッセージ キューにのみメッセージを送信できます。他のタスクが取得できない場合には待つ必要はなく、他のタスクを格納するための待ちリストも必要ないため、待ちリストは存在せず、待ちリストへの入退出の操作は省略される。

タスクメッセージキューに関連する TCB の要素:

{

OS_MSG_Q MsgQ; //メッセージリスト

CPU_TS MsgQPendTime; タスクが自身のタスク メッセージ リストを待つ待ち時間。

CPU_TS MsgQPendTimeMax; タスクがタスク メッセージ リストを複数回待機する最長待機時間。

}

メッセージ構造:

構造体 os_msg {                                           

    OS_MSG *NextPtr; //次のメッセージへのポインタ                         

    void *MsgPtr; //メッセージコンテンツへのポインタ           

    OS_MSG_SIZE MsgSize; //メッセージサイズを示す変数           

    CPU_TS MsgTS; //送信されたメッセージのタイムスタンプ    

};

メッセージ キューによって送信されたメッセージのタイムスタンプは、セマフォとは異なり、メッセージ構造に格納されることに注意してください。セマフォは、セマフォが解放されたときにタイムスタンプを保存するために TCB 内の CPU_TS TS 要素に依存します

OS_MSG_Q MsgQ : 実際、OS_MSG_Q 構造体はメッセージ リスト構造体であり、メッセージ キュー構造体ではありません。カーネルのメッセージ キューの構造を振り返ると、メッセージ リストと待機リストの要素を除いて、その他はデバッグ関連の要素とメッセージ キューの名前であるためです。タスクのメッセージ キューはタスクごとに固有であるため、メッセージ キュー名を指定する必要はなく、対応するタスクを直接検索することでメッセージ キューを見つけることができ、待機リストやデバッグ リストは必要ありません。したがって、タスク メッセージ キューは、要素 OS_MSG_Q MsgQ を TCB のメッセージ リストに追加するだけです

構造体 os_msg_q {                                     

    OS_MSG *InPtr; //キューに挿入される次のメッセージへのポインタ                    

    OS_MSG *OutPtr; //キューからフェッチされる次のメッセージへのポインタ。                

    OS_MSG_QTY NbrEntriesSize; //キュー内で許可されるメッセージの最大数       

    OS_MSG_QTY NbrEntries; //キュー内の現在のメッセージ数        

    OS_MSG_QTY NbrEntriesMax; //キュー内のメッセージのピーク数                  

    CPU_INT32U MsgQID; //サードパーティのデバッガとトレーサの一意の ID                   

};

メッセージキュー送受信の仕組み: ① メッセージキューはメッセージプールからメッセージを取得してメッセージを送信し、メッセージの取得に成功すると、メッセージプール内の利用可能なメッセージ数が1つ減ります。② メッセージプール内のメッセージは、初期化時にメッセージポイントを指定しませんが、ポインタを使用することで、可変長のメッセージを指すだけでなく、実行プロセス中にユーザーが送信したいメッセージを柔軟に指すことができます。③ メッセージキュー送信機能は、メッセージ送信時にメッセージ構造体に値を代入するだけですが、タスクがメッセージを取得した場合は、メッセージポインタをクリアせず、メッセージを直接メッセージプールに返します。メッセージが送信されるたびに値が割り当てられるため、クリアする必要はありません

OSTaskQPost() : タスクメッセージキュー送信関数

{

5 つのエントリ パラメータ: ターゲット TCB を指すポインタ p_tcb、メッセージ コンテンツを指すポインタ p_void、メッセージ サイズ msg_size、オプション opt、返されたエラー タイプ p_err。

機能処理: ① まずセキュリティチェックとパラメータオプションチェックを行います。オプションには主に OS_OPT_POST_FIFO と OS_OPT_POST_LIFO、および OS_OPT_POST_NO_SCHED との組み合わせが含まれます。② メッセージキューを送信した時点のタイムスタンプを取得します。③ 割り込み遅延パブリッシングが有効で、この関数が割り込みで呼び出された場合は、OS_IntQPost()を呼び出し、まずメッセージを割り込みメッセージキューに送信してリターンします。④ それ以外の場合は、OS_TaskQPost()を呼び出してメッセージを直接送信します。

--OS_TaskQPost() を呼び出します

6 つのエントリ パラメータ: ターゲット TCB を指すポインタ p_tcb、メッセージ コンテンツを指すポインタ p_void、メッセージ サイズ変数 msg_size、オプション opt、タイムスタンプ ts、返されたエラー タイプ p_err。

関数処理: ① uCOS では空の TCB ポインタを指定することができ、TCB ポインタが空の場合、メッセージは他のタスクではなく自タスクに送信されます。タスクにメッセージを送信する場合、タスクがブロックされてメッセージを待っている場合と、メッセージを待っているタスクが存在しない場合の 2 つの状況が存在するためです。タスクのメッセージキューはタスク固有のキューであり、待ちリストを持たないため、タスクがメッセージを待っているかどうかは対象タスクの状態に基づいて判断されますターゲット TCB のステータスが待機状態でない場合は、タスクがメッセージ キューを待っていないことを意味し、OS_MsgQPut() を呼び出してメッセージをメッセージ リストに挿入します。③ ターゲット TCB のステータスが待機状態から変化した場合、それがタスクのメッセージ キューを待っているかどうかによって異なります。メッセージ キューを待っている場合は、OS_Post() を呼び出してターゲット TCB にメッセージを送信します (実際には値を割り当てます)。) ; 次に、タスクのスケジューリングのために OSSched() を呼び出す必要があるかどうかを判断します。タスクのメッセージキューを待っていない場合は、送信したメッセージもメッセージリストに挿入する必要があるので、手順②を実行し、OS_MsgQPut()を呼び出してメッセージリストにメッセージを挿入します。

OS_MsgQPut() はメッセージ リストに対して動作します。したがって、カーネルメッセージキューとタスクメッセージキューの動作は同じです。ただし、パラメータのうち、カーネル メッセージ キューはカーネル メッセージ キュー構造内のメッセージ リストを操作し、タスク メッセージ キューは TCB 構造内のメッセージ リスト要素を操作します。

}  

OSTaskQPend() : タスクメッセージキュー取得関数

{

5 つのエントリ パラメータ: タイムアウト timeout、オプション opt、メッセージ サイズへのポインタ p_msg_size、メッセージが公開されたときにタイムスタンプ p_ts を返し、エラー タイプ p_err を返します。

Return : この関数はポインタ関数であり、本質的には関数であり、戻り値は void * 型です。返されるポインタは、メッセージのコンテンツへのポインタです。

関数処理: ①セキュリティ、パラメータ、オプション、割り込みの不正な呼び出しをチェックします。② メッセージキュー取得機能は、まずタスクメッセージリストに待機中のメッセージがあるかどうかを確認します。OS_MsgQGet() を通じてメッセージ リスト内のメッセージを取得します。返されたエラー タイプが OS_ERR_NONE の場合は、メッセージ リストにメッセージが存在することを意味し、メッセージへのポインタ p_void が取得され、現在のタイムスタンプとメッセージが発行されたときのタイムスタンプの差が取得され、待機中のタイムスタンプが取得されます。メッセージの時刻、必要に応じて MsgQPendTimeMax を更新し、最後にメッセージへのポインタ p_void を返します。③ OS_MsgQGet() は 2 つのエラーのみを返します: 1 つは OS_ERR_NONE で、メッセージ リストにメッセージがあることを示します。もう 1 つは OS_ERR_Q_EMPTY で、メッセージ リストに正午にメッセージがあることを示します。メッセージがない場合は、メッセージ待ちのオプションに従ってタスクがブロックに入るようにユーザーが指定するかどうかを判断する必要があります。ユーザーがブロックしないことを選択した場合は、OS_ERR_PEND_WOULD_BLOCK エラー タイプが返され、null ポインタが返されます。 。(実際には、ここで意図的にノンブロッキング オプションを選択し、エラーの種類によってタスクがメッセージを取得したかどうかを判断できます。メッセージが取得された場合は、メッセージへのポインタが返されているため、次のステップが実行されます)ブロックするかどうかの判定は行わず、そうでない場合は null ポインタを返す、ブロックする必要があるエラーの種類など)。④ メッセージリストに利用可能なメッセージがなく、ユーザーがブロックして待つことを選択した場合、そのタスクを準備完了リストから削除する必要がありますが、このとき、スケジューラがロックされているかどうかを判断する必要があります。ロックされていない場合は、OS_Pend() を呼び出してタスクをブロックします。つまり、タスクを準備完了リストから削除し、タイムベース リストに追加します (タイムアウトが 0 でない場合)。最後に、タスクを切り替えるために OSSched() を呼び出します。⑤ プログラムがここまで実行されると、タスクは準備完了リストに追加され、メッセージを取得するか、中止されるか、メッセージを取得するためにタイムアウトするなどのいずれかの処理を行う必要があります。したがって、タスクの状況に応じて対応する処理を行う必要があります。OS_STATUS_PEND_OK メッセージが表示されるまで待機した場合は、メッセージへのポインタとメッセージのサイズを取得し、メッセージへのポインタを返します。それ以外の場合、メッセージ コンテンツへのポインタは null で、メッセージ サイズは 0 です。

}

おすすめ

転載: blog.csdn.net/m0_43443861/article/details/126373515