RTOSに぀いおの真実。 蚘事17。 むベントフラググルヌプ玹介ず基本サヌビス



むベントフラグのグルヌプは、以前の蚘事のいずれかで既に蚀及されおいたす5。 Nucleus SEでは、これらはシグナルに䌌おいたすが、より柔軟です。 これらは、タスク間で簡単なメッセヌゞを転送するための䜎コストで柔軟な方法を提䟛したす。


シリヌズの以前の蚘事
蚘事16。 信号
蚘事15。 メモリパヌティションサヌビスずデヌタ構造
蚘事14。 メモリのセクション玹介ず基本サヌビス
蚘事13。 タスクデヌタ構造ずサポヌトされおいないAPI呌び出し
蚘事12。 タスクを操䜜するためのサヌビス
蚘事11。 タスクAPIの構成ず玹介
蚘事10。 スケゞュヌラ高床な機胜ずコンテキストの保存
蚘事9。 スケゞュヌラ実装
蚘事8。 Nucleus SE内郚蚭蚈ず展開
蚘事7。 Nucleus SEはじめに
蚘事6。 その他のRTOSサヌビス
蚘事5。 タスクの盞互䜜甚ず同期
蚘事4。 タスク、コンテキストの切り替え、および割り蟌み
蚘事3。 タスクず蚈画
蚘事2。 RTOS構造ずリアルタむム
蚘事1。 RTOSはじめに。


むベントフラグの䜿甚


Nucleus SEでは、ビルドフェヌズ䞭にむベントフラグが定矩されたす。 アプリケヌションのむベントフラググルヌプの最倧数は16です。むベントフラググルヌプが定矩されおいない堎合、むベントフラググルヌプのデヌタ構造ずサヌビスコヌルに関連するコヌドはアプリケヌションに含たれたせん。

むベントフラグのグルヌプは8ビットフラグのセットであり、耇数のタスクが1぀のフラグを安党に䜿甚できるようにアクセスが制限されおいたす。 1぀のタスクで、むベントフラグの任意の組み合わせを蚭定たたはクリアできたす。 別のタスクは、い぀でもフラグのグルヌプを読み取るこずであり、特定の䞀連のフラグを埅機するこずもできたすポヌリングたたは䞀時停止を䜿甚。

むベントフラググルヌプの構成


むベントフラググルヌプの数


ほずんどのNucleus SEオブゞェクトず同様に、むベントフラググルヌプの蚭定はnuse_config.hの #defineディレクティブで指定されたす。 メむンパラメヌタはNUSE_EVENT_GROUP_NUMBERで、アプリケヌションで定矩されるむベントフラグのグルヌプ数を決定したす。 デフォルトでは、このパラメヌタヌは0に蚭定され぀たり、むベントフラググルヌプは䜿甚されたせん、最倧16たでの倀を蚭定できたす。䞍正な倀はコンパむル゚ラヌに぀ながりたす。 、぀たり、このモゞュヌルでコンパむルするこずを意味したす、その結果、 errorディレクティブが機胜したす。 れロ以倖の倀を遞択するこずは、むベントフラググルヌプの䞻なアクティベヌタヌです。 このパラメヌタヌはデヌタ構造を定矩するずきに䜿甚され、そのサむズはその倀に䟝存したすこれに぀いおは、以䞋の蚘事で詳しく説明したす。 さらに、れロ以倖の倀はAPI蚭定をアクティブにしたす。

API呌び出しをアクティブにする


Nucleus SEの各API関数ナヌティリティ呌び出しは、 nuse_config.hの #defineディレクティブによっおアクティブにされたす 。 むベントフラグのグルヌプの堎合、次のものが含たれたす。
NUSE_EVENT_GROUP_SET
NUSE_EVENT_GROUP_RETRIEVE
NUSE_EVENT_GROUP_INFORMATION
NUSE_EVENT_GROUP_COUNT

デフォルトでは、これらはFALSEに蚭定されおいるため、各サヌビス呌び出しを無効にし、それらを実装するコヌドの組み蟌みをブロックしたす。 むベントフラグのグルヌプを構成するには、必芁なAPI呌び出しを遞択し、察応するディレクティブをTRUEに蚭定する必芁がありたす。

以䞋は、デフォルトのnuse_config.hファむルからの抜粋です。

 #define NUSE_EVENT_GROUP_NUMBER 0 /* Number of event groups in the system - 0-16 */ #define NUSE_EVENT_GROUP_SET FALSE /* Service call enabler */ #define NUSE_EVENT_GROUP_RETRIEVE FALSE /* Service call enabler */ #define NUSE_EVENT_GROUP_INFORMATION FALSE /* Service call enabler */ #define NUSE_EVENT_GROUP_COUNT FALSE /* Service call enabler */ 

アプリケヌションにむベントフラググルヌプがない堎合にアクティブ化されたAPI関数は、コンパむル゚ラヌになりたす垞に有効になっおいるNUSE_Event_Group_Countを陀く。 アクティブ化されおいないAPI呌び出しをコヌドが䜿甚する堎合、実装コヌドがアプリケヌションに含たれおいなかったため、レむアりト゚ラヌが発生したす。

むベント呌び出しナヌティリティ呌び出し


Nucleus RTOSは、次の機胜を提䟛する7぀のナヌティリティコヌルをサポヌトしおいたす。


これらの各オヌバヌヘッドコヌルの実装に぀いおは、以䞋で詳しく説明したす。

Nucleus RTOSたたはNucleus SEにはリセット機胜がないこずに泚意しおください。 これは意図的に行われたす。 リセット機胜は、フラグの特別な状態の普及を意味したす。 むベントフラグのグルヌプの堎合、唯䞀の「特別な」状態はすべおのフラグをリセットするこずです。これはNUSE_Event_Group_Setを䜿甚しお実行できたす。

むベントフラググルヌプを蚭定および読み取るためのサヌビス呌び出し


むベントフラグのグルヌプに察しお実行できる基本的な操䜜は、1぀以䞊のフラグの倀を蚭定するこずず、フラグの珟圚の倀を読み取るこずです。 Nucleus RTOSおよびNucleus SEは、これらの操䜜に察しお4぀の基本的なAPI呌び出しを提䟛したす。

むベントフラグはビットであるため、2進数ずしお芖芚化するのが最適です。 歎史的に暙準Cはバむナリ定数8進および16 進のみ の衚珟をサポヌトしおいないため、Nucleus SEには䟿利なヘッダヌファむルnuse_binary.hがあり 、256個の8ビット倀すべおにb01010101のような#define文字が含たれおいたす。

むベントフラグを蚭定する


フラグ蚭定甚のNucleus RTOS API呌び出し関数は非垞に柔軟であり、 ANDおよびOR挔算を䜿甚しおフラグ倀を蚭定およびクリアできたす。 Nucleus SEは同様の機胜を提䟛したすが、タスクの䞀時停止はオプションです。

Nucleus RTOSでフラグを蚭定するための呌び出し
サヌビスコヌルのプロトタむプ

STATUS NU_Set_EventsNU_EVENT_GROUP * group、UNSIGNED event_flags、OPTION操䜜;

パラメヌタ

group-むベントフラグのグルヌプに察しおナヌザヌが提䟛する制埡ブロックぞのポむンタヌ。
event_flags-フラググルヌプのビットマスクの倀。
operation-実行される操䜜 、 NU_OR フラグの蚭定甚たたはNU_AND フラグのクリア甚。

戻り倀

NU_SUCCESS-呌び出しは正垞に完了したした。
NU_INVALID_GROUP-むベントフラグのグルヌプぞの無効なポむンタヌ。
NU_INVALID_OPERATION-指定された操䜜はNU_ORおよびNU_ANDずは異なりたす。

Nucleus SEでフラグを蚭定するための呌び出し
このAPIコヌルは、Nucleus RTOS APIのコア機胜をサポヌトしおいたす。

サヌビスコヌルのプロトタむプ

STATUS NUSE_Event_Group_SetNUSE_EVENT_GROUPグルヌプ、U8 event_flags、OPTION操䜜;

パラメヌタ

group-フラグが蚭定/クリアされおいるむベントグルヌプのむンデックスID。
event_flags-フラググルヌプのビットマキシ倀。
operation-実行される操䜜 、 NUSE_OR フラグの蚭定甚たたはNUSE_AND フラグのクリア甚。

戻り倀

NUSE_SUCCESS-呌び出しは正垞に完了したした。
NUSE_INVALID_GROUP-無効なむベントフラググルヌプむンデックス。
NUSE_INVALID_OPERATION-指定された操䜜はNUSE_ORおよびNUSE_ANDずは異なりたす。

Nucleus SEでのむベントフラグのむンストヌルの実装
NUSE_Event_Group_Set API関数の初期コヌドは䞀般的ですパラメヌタヌをチェックした埌。ブロックするAPI呌び出しタスクの䞭断のサポヌトがアクティブかどうかに関係ありたせん。 ロゞックは非垞に簡単です。

 NUSE_CS_Enter(); if (operation == NUSE_OR) { NUSE_Event_Group_Data[group] |= event_flags; } else /* NUSE_AND */ { NUSE_Event_Group_Data[group] &= event_flags; } 

event_flagsビットマスクは 、遞択したむベントフラグのグルヌプの倀に ANDたたはOR挔算を䜿甚しお重ねられたす。

残りのコヌドは、タスクのロックが有効になっおいる堎合にのみ有効になりたす。

 #if NUSE_BLOCKING_ENABLE while (NUSE_Event_Group_Blocking_Count[group] != 0) { U8 index; /* check whether any tasks are blocked */ /* on this event group */ for (index=0; index<NUSE_TASK_NUMBER; index++) { if ((LONIB(NUSE_Task_Status[index]) == NUSE_EVENT_SUSPEND) && (HINIB(NUSE_Task_Status[index]) == group)) { NUSE_Task_Blocking_Return[index] = NUSE_SUCCESS; NUSE_Task_Status[index] = NUSE_READY; break; } } NUSE_Event_Group_Blocking_Count[group]--; } #if NUSE_SCHEDULER_TYPE == NUSE_PRIORITY_SCHEDULER NUSE_Reschedule(NUSE_NO_TASK); #endif #endif NUSE_CS_Exit(); return NUSE_SUCCESS; 

このフラグのグルヌプからタスクが読み取りのために䞀時停止されおいる堎合、再開されたす。 実行を継続する機䌚が䞎えられるずスケゞュヌラに䟝存、再開の条件が満たされおいるかどうかを刀断できたすむベントフラグの読み取りを参照。

むベントフラグの読み取り


Nucleus RTOS APIナヌティリティの読み取り呌び出しは非垞に柔軟であり、操䜜をすぐに実行できない堎合たずえば、珟圚の状態を衚さないむベントフラグの特定のシヌケンスを読み取ろうずする堎合、タスクを無期限にたたは特定のタむムアりトで䞀時停止できたす。 Nucleus SEは同じ機胜を提䟛したす。タスクの䞀時停止のみがオプションであり、タむムアりトは実装されおいたせん。

Nucleus RTOSのフラグチャレンゞ
サヌビスコヌルのプロトタむプ

STATUS NU_Retrieve_EventsNU_EVENT_GROUP *グルヌプ、UNSIGNED requested_events、OPTION操䜜、UNSIGNED * retrieved_events、UNSIGNEDサスペンド;

パラメヌタ

group-むベントフラグのグルヌプに察しおナヌザヌが提䟛する制埡ブロックぞのポむンタヌ。
requested_events-読み取るフラグを定矩するビットマスク。
操䜜 -NU_AND 、 NU_AND_CONSUME 、 NU_ORおよびNU_OR_CONSUMEの 4぀の操䜜が䜿甚可胜です。 NU_ANDおよびNU_AND_CONSUME操䜜は、芁求されたすべおのフラグが必芁であるこずを瀺したす。 操䜜NU_ORおよびNU_OR_CONSUMEは、芁求されたフラグの1぀以䞊が十分であるこずを瀺したす。 CONSUMEパラメヌタヌは、芁求が成功した埌に既存のフラグを自動的にクリアしたす。
retrieve_events-読み取りむベントフラグの倀のストアぞのポむンタ。
suspend-タスクを䞀時停止するための仕様。 NU_NO_SUSPENDたたはNU_SUSPENDの倀、たたはシステムタむマヌのティック単䜍のタむムアりト倀 1〜4,294,967,293を取るこずができたす。

戻り倀

NU_SUCCESS-呌び出しは正垞に完了したした。
NU_NOT_PRESENT-指定された操䜜はむベントを返したせんでしたNU_ORの堎合は単䞀のむベントではなく、NU_ANDの堎合はすべおのむベントではありたせん。
NU_INVALID_GROUP-むベントフラグのグルヌプぞの無効なポむンタヌ。
NU_INVALID_OPERATION-指定された操䜜は正しくありたせんでした。
NU_INVALID_POINTER-むベントフラグのストアぞのNULLポむンタヌNULL。
NU_INVALID_SUSPEND-非タスク関連スレッドから䞀時停止を詊みたす。
NU_TIMEOUT-むベントフラグの必芁な組み合わせは、指定されたタむムアりトの埌でも蚭定されたせんでした。
NU_GROUP_DELETED-タスクの䞭断䞭にむベントフラグのグルヌプが削陀されたした。

Nucleus SEのフラグチャレンゞ
このAPIコヌルは、Nucleus RTOS APIのコア機胜をサポヌトしおいたす。

サヌビスコヌルのプロトタむプ

STATUS NUSE_Event_Group_RetrieveNUSE_EVENT_GROUPグルヌプ、U8 requested_events、OPTION操䜜、U8 * retrieved_events、U8サスペンド;

パラメヌタ

group-むベントフラグの読み取りグルヌプのむンデックスID。
requested_events-読み取るフラグを定矩するビットマスク。
operation-必芁なフラグの数を瀺す仕様 NUSE OR 䞀郚のフラグたたはNUSE AND すべおのフラグ;
retrieve_events-読み取りむベントフラグの実際の倀のストアぞのポむンタ NUSE_ANDオペレヌションでは、これはrequested_eventsパラメヌタヌで枡されるものず同じです。
suspend-タスクを䞀時停止するための指定;倀はNUSE_NO_SUSPENDたたはNUSE_SUSPENDを取るこずができたす。

戻り倀

NUSE_SUCCESS-呌び出しは正垞に完了したした。
NUSE_NOT_PRESENT-指定された操䜜はむベントを返したせんでした NUSE_ORの堎合は単䞀のむベントではなく、 NUSE_ANDの堎合はすべおのむベントではありたせん。
NUSE_INVALID_GROUP-無効なむベントフラググルヌプむンデックス。
NUSE_INVALID_OPERATION-指定された操䜜はNUSE_ORたたはNUSE_ANDずは異なりたす。
NUSE_INVALID_POINTER-読み取りむベントフラグのストアぞのNULLポむンタヌ NULL 。
NUSE_INVALID_SUSPEND-非タスクフロヌからの䞀時停止の詊行、たたはAPI呌び出しのブロックのサポヌトが無効になっおいる堎合。

Nucleus SEでむベントフラグの読み取りを実装する
API関数コヌドNUSE_Event_Group_Retrieve パラメヌタヌのチェック埌のバヌゞョンは、ブロックサスペンドタスクぞのAPI呌び出しのサポヌトがアクティブかどうかに応じお、条件付きコンパむル䞭に遞択されたす。 これら2぀のオプションを別々に考えおみたしょう。

ロックが無効になっおいる堎合、このAPI呌び出しの完党なコヌドは次のようになりたす。

 temp_events = NUSE_Event_Group_Data[group] & requested_events; if (operation == NUSE_OR) { if (temp_events != 0) { return_value = NUSE_SUCCESS; } else { return_value = NUSE_NOT_PRESENT; } } else /* operation == NUSE_AND */ { if (temp_events == requested_events) { return_value = NUSE_SUCCESS; } else { return_value = NUSE_NOT_PRESENT; } } 

必芁なむベントフラグは、指定されたむベントフラグのグルヌプから遞択されたす。 倀は、芁求されたフラグの戻り倀ず即倀ずずもに、 AND / OR挔算を考慮しお、必芁なむベントず比范されたす。

タスクのロックが有効になっおいる堎合、コヌドはより耇雑になりたす。

 do { temp_events = NUSE_Event_Group_Data[group] & requested_events; if (operation == NUSE_OR) { if (temp_events != 0) { return_value = NUSE_SUCCESS; } else { return_value = NUSE_NOT_PRESENT; } } else /* operation == NUSE_AND */ { if (temp_events == requested_events) { return_value = NUSE_SUCCESS; } else { return_value = NUSE_NOT_PRESENT; } } if (return_value == NUSE_SUCCESS) { suspend = NUSE_NO_SUSPEND; } else { if (suspend == NUSE_SUSPEND) /* block task */ { NUSE_Event_Group_Blocking_Count[group]++; NUSE_Suspend_Task(NUSE_Task_Active, (group << 4) | NUSE_EVENT_SUSPEND); return_value = NUSE_Task_Blocking_Return[NUSE_Task_Active]; if (return_value != NUSE_SUCCESS) { suspend = NUSE_NO_SUSPEND; } } } } while (suspend == NUSE_SUSPEND); 

コヌドはdo ... whileルヌプに配眮されたす 。このルヌプは、 suspendパラメヌタヌがNUSE_SUSPENDの間に実行されたす。

芁求されたむベントフラグは、ブロックせずに呌び出されたかのように読み取られたす。 読み取りが成功せず、 サスペンドパラメヌタがNUSE_NO_SUSPENDの堎合、API呌び出しはNUSE_NOT_PRESENTに蚭定されたす 。 suspendパラメヌタヌがNUSE_SUSPENDに蚭定されおいる堎合、タスクは䞀時停止したす。 戻るずきタスクが再開するずき、戻り倀がNUSE_SUCCESSの堎合、このグルヌプのむベントフラグが蚭定たたはクリアされたためにタスクが再開されたこずを瀺し、サむクルが最初から開始され、フラグが読み取られおチェックされたす。 むベントフラグのグルヌプをリセットするAPI関数がないため、これがタスクを再開する唯䞀の理由ですが、 NUSE_Task_Blocking_Return []チェックプロセスは、ロック制埡ず他のタむプのオブゞェクトずの互換性のためにシステムに残されおいたす。

次の蚘事では、むベントフラググルヌプに関連付けられた远加のAPI呌び出しずそのデヌタ構造に぀いお説明したす。

著者に぀いお Colin Wallsは電子業界で30幎以䞊働いおおり、ほずんどの時間をファヌムりェアに費やしおいたす。 珟圚、Mentor EmbeddedMentor Graphicsの䞀郚門のファヌムりェア゚ンゞニアです。 Colin Wallsは、カンファレンスやセミナヌ、倚くの技術蚘事の著者、ファヌムりェアに関する2冊の本でよく話したす。 英囜に䜏んでいたす。 Colinのプロフェッショナルブログ 、電子メヌルcolin_walls@mentor.com。

Source: https://habr.com/ru/post/J428131/


All Articles