uCOS公式ミューテックス関数(stm32F4)のミューテックス関数OSMutexPend()の実装コードの取得についての質問

OSMutexPend() : ミューテックス関数の取得

{

機能アイデア: タスクはミューテックスの排他的所有権を持ちます。ミューテックスは常に 1 つのタスクによってのみ保持できます。ミューテックスがロック解除状態にある場合、ミューテックスを取得したタスクはミューテックスを正常に取得します。ミューテックスの使用権; ミューテックスがロック状態の場合、ミューテックスを取得したタスクはミューテックスを取得できなくなり、タスクは中断されます。タスクが中断される前に優先度の継承が行われます。現在のタスクの優先度がミューテックスを保持しているタスクの優先度より高い場合、ミューテックスを保持しているタスクの優先度が一時的に上がります

5 つのエントリ パラメータ: ミューテックスへのポインタ、タイムアウト、オプション、解放時のタイムスタンプ (0 は、ミューテックスが作成後に取得および解放されていないことを意味します。または、ミューテックスが他のタスクによって占有されており、タスクがミューテックスの取得に失敗したことを意味します)タイムアウト); 戻りエラーの種類

機能処理:①セキュリティチェック、パラメータオプションチェック等 オプションは OS_OPT_PEND_BLOCKING と OS_OPT_PEND_NON_BLOCKING の 2 つだけです。これらは、ミューテックスが他のタスクによって保持されている場合にタスクをブロックするかどうかを指定します。② クリティカル セクションに入り、ミューテックスが利用可能 (ロック解除状態) (OwnerNestingCtr 値が 0) の場合、ミューテックス要素 OwnerTCBPtr の値を変更し、現在の TCB をそれに割り当てます。その後、OwnerNestingCtr を 1 増やして、ミューテックスがロックされていないことを示します。ロックされたステータス; 返されたタイムスタンプをミューテックスのタイムスタンプ要素の値に割り当てます; OS_MutexGrpAdd() を呼び出してミューテックスを保持するタスクのリンク リストにミューテックスを追加し、クリティカル セクションを終了します; エラーのないタイプを返します。そしてリターンリターン。③ 現在のタスクが再びミューテックスを取得する場合は、ミューテックスの OwnerNestingCtr 要素を変更して値を 1 増やし、タイムスタンプを返し、クリティカル セクションを終了し、エラー タイプ "OS_ERR_MUTEX_OWNER" を返してリターンする必要があります。④ ミューテックスが他のタスクによって占有されており、オプションタイプが OS_OPT_PEND_NON_BLOCKING の場合、エラー「OS_ERR_PEND_WOULD_BLOCK」を返しリターンします。(タスクが「ノンブロッキング」を選択している場合、この戻り値の型を使用して、ミューテックスが他のタスクによって占有されているかどうかを判断できます。) ⑤ ミューテックスが他のタスクによって占有されている場合、オプションタイプが「OS_OPT_PEND_BLOCKING」の場合、まずスケジューラがロックされているかどうかを確認します(タスクを待機リストに追加する必要があるため、スケジューラがロックされている場合、タスクの操作は実行できません)); ロックされていない場合は、OS_CRITICAL_ENTER_CPU_EXIT() を呼び出してスケジューラをロックしますが、割り込みを有効にします; 現在のタスクの優先度がミューテックスを取得するタスクの優先度よりも高い場合は、OS_TaskChangePrio() を呼び出して、ミューテックスの優先度を変更します。ミューテックスを取得するタスク; OS_Pend() を呼び出してタスクをミューテックスの待機リストに追加; OS_CRITICAL_EXIT_NO_SCHED() を呼び出してスケジューラのロックを解除し、切り替えません; 次に OSSched() を呼び出して切り替えます (ここでのタスクはミューテックスの待機リストに入っているため)とブロックされているため、切り替えてください)。⑥ 切り替え後にコンテキストが保存されますが、ここで再度実行する場合は、タスクがブロッキング状態から復帰してからスケジューリングを継続する必要があるため、タスクの状態に応じて待機するかどうかを判断する必要があります。ミューテックスの復元やタイムアウトの回復など。タスクのステータスが「OS_STATUS_PEND_OK」の場合は、ミューテックスを取得したことを意味し、タイムスタンプを返し、エラーはありません。タスクのステータスが「OS_STATUS_PEND_ABORT」の場合は、終了待ちのタイムスタンプと「終了待ち」のエラーを返します。 「OS_STATUS_PEND_TIMEOUT」の場合、戻りタイムスタンプは 0 で、ミューテックスが取得されていないことを示し、「待機タイムアウト」エラーが返されます。「OS_STATUS_PEND_DEL」の場合、ミューテックスが削除されたことを示すエラーが返されます。その他待機に関係のない状態は無効です。

- OS_TaskChangePrio() を呼び出します

注意: ① タスクがミューテックスを保持している限り、そのタスクが所有権を持っているため、タスクがミューテックスを解放する関数を呼び出すのを待つだけでミューテックスが利用可能になります。したがって、タスクは、ミューテックス解放関数を呼び出す前に、準備完了状態など、さまざまな状態になる可能性があります。タスクの作成後、タスクは準備完了リストに挿入されます。挿入が成功すると、タスクのステータスは準備完了に変更されます。タスクの実行処理中に、タスクの状態変化を伴う関数が呼び出された場合、タスクの状態は準備完了状態になります。たとえば、遅延状態では、ブロッキング遅延関数がその中で呼び出されると、タスクは準備完了リストから削除され、タイムベースリストに挿入され、挿入は成功し、ステータスが遅延状態に変更されます。状態; タスクがミューテックスを解放する前に呼び出された場合、タスクは遅延状態になります。したがって、タスクのステータスに応じてタスクの優先度を変更する必要があります② 本関数は、ミューテックスを取得する関数 OSMutexPend()内で呼び出されていますが、この関数を呼び出す前にOS_CRITICAL_ENTER_CPU_EXIT()を呼び出してスケジューラをロックし、タスクの切り替えや状態変更(タイムベースリスト、ウェイティングリストの挿入など)を防止します。等。)。③ 優先度を変更した後、タスクは対応する優先度の下で準備完了リストに挿入されます。

2 つのエントリ パラメータ: ミューテックスを保持するタスク TCB へのポインタ、置き換えられる優先度

関数処理: do-while ループであり、ループ条件は TCB ポインタが空でないことです。ループの本体は、タスクのステータスと優先度を変更するために実行される操作に従ってタスクの優先度を変更することです。(ここでの do-while ループの目的は、他のミューテックスによって保護されているリソースにアクセスするときに、ミューテックスを保持しているタスクが他のミューテックスの待機リストでブロックされるという問題を解決することです)① 準備完了状態の場合は、タスクがまだ実行中、またはタスクに切り替わっていないことを意味しますタスクの優先度が変更されたときにタスクの実行ステータスが変更されないようにするには、まず OS_RdyListRemove() を呼び出して実行可能リストからタスクを削除します (削除後にこの優先度の下にタスクがない場合、この関数は対応する優先度をクリアします)タスクの優先度を変更した後、OS_PrioInsert() を呼び出して、対応する優先度テーブルの位置に 1 を設定します。この関数は または アルゴリズムを使用して 1 を設定するため、重複を心配する必要はありません。他の位置に影響を与える; 準備完了状態には 2 つの状況があります:タスクが実行中であるため、優先度を変更した後、実行を継続できるようにタスクを準備完了リストの先頭に挿入する必要があります; 2 つ目の状況は、まだ切り替えられていない可能性があります (ただし、ミューテックスを保持しており、(解放されていない)、現在のタスクがミューテックスを保持しているタスクと等しくない場合、ミューテックスを保持しているタスクが準備完了リストの最後に挿入されます。優先度が上がるため、他の優先度の高いタスクをヘッドに挿入できなくなり、タスクの実行待ち時間が長くなります。② タスクの状態が遅延、一時停止、遅延+一時停止の場合は、タスクがこれらの状態にあるときは実行可能リストから削除され優先度が変更されるため、ミューテックスを保持しているタスクの優先度のみが変更されます。準備完了状態に切り替わると、優先順位に従って準備完了リストに自動的に挿入されます。③待機中、タイムアウト待機、待機+ハング、タイムアウト待機+ハングの場合は、レディリストからも削除されるため、②と同様に優先度を変更する他に、タスクのpendon要素にアクセスして確認する必要があります。タスクが何を待っているのか。ミューテックスを待機していない場合 (セマフォやメッセージ キューなどを待機している場合など)、待機リストは一方向であるため、OS_PendListChangePrio() を呼び出して待機リスト内のタスクの位置を変更する必要があります。タスクの優先度に応じて連結されたリンク リスト 変更されたタスクの優先度は、もちろんリンク リスト内で変更する必要があります。④ タスクは複数のミューテックスを保持し、複数の保護されたリソースにアクセスできるため、タスクがミューテックスを待機している場合は、タスクが他のミューテックスにあるため、OS_PendListChangePrio() を呼び出してミューテックス待機リスト内のタスクの位置を変更する必要があります。ミューテックス待ちリストの優先度が高くなったので、別のミューテックスタスクの優先度を上げる必要があるかどうかを判断する必要があります。この関数はミューテックスを保持しているタスクの優先度を変更するために使用されるため、必要に応じて上記のプロセスを繰り返す必要がありますが、そうでない場合は上記のプロセスを繰り返してループを終了する必要はありません必要な状況は 1 つだけです。待機リスト内のタスクの優先度が、ミューテックスを保持しているタスクの優先度よりも高いということです。しかし、uCOS関係者は以下のような判定コードを書いていません。

OS_TaskChangePrio() 関数は、優先度を高いレベルに変更するだけでなく、優先度を低いレベルに変更することもでき、ミューテックスを保持するタスクの優先度を変更するだけではないため、他のタスクもこの関数を呼び出して、優先度を変更することができます。走行中の優先レベルを設定しますここでミューテックス関数 OSMutexPend() を取得し、OS_TaskChangePrio() を呼び出して優先度を継承し、優先度をより大きな値に変更するだけです。したがって、uCOS は正式に 2 つの状況を区別します: 1 つは優先度をより小さい値 (prio_cur > prio_new) に変更すること、もう 1 つは変更しないで維持するか、より大きな値に変更することです

しかし、私は依然として公式のロジックが間違っていると考えています

私のロジックを投稿しますので、アドバイスをいただければ幸いです。

おすすめ

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