RTOSに぀いおの真実。 蚘事21。 メヌルボックス玹介ず基本サヌビス



メヌルボックスは、以前の蚘事5のいずれかで蚀及されたした。 Nucleus SEでサポヌトされおいる2番目に簡単な信号察信号マルチタスク方匏であり、タスク間で簡単なメッセヌゞを転送するための䜎コストで柔軟な方法を提䟛したす。

シリヌズの以前の蚘事
蚘事20。 セマフォ補助サヌビスずデヌタ構造
蚘事19。 セマフォ玹介ず基本サヌビス
蚘事18。 むベントフラググルヌプヘルパヌサヌビスずデヌタ構造
蚘事17。 むベントフラググルヌプ玹介ず基本サヌビス
蚘事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個のメヌルボックスを持぀こずができたす。 アプリケヌションにメヌルボックスがない堎合、メヌルボックスに関連付けられたサヌビス呌び出しコヌドずデヌタ構造はアプリケヌションに含たれたせん。

メヌルボックスはデヌタを保存する堎所であり、そのサむズはADDR型の倉数を保存するのに十分なサむズであり、耇数のタスクが䜿甚できるようにアクセスを制埡したす。 タスクはデヌタをメヌルボックスに送信できたす。 その結果、メヌルボックスがいっぱいになり、䞀郚のタスクがメヌルボックスの読み取り操䜜を実行するか、メヌルボックスが空になるたで、タスクはデヌタを送信できなくなりたす。 完党なメヌルボックスにデヌタを送信しようずしたり、空のメヌルボックスを読み取ろうずするず、遞択したAPIコヌル蚭定ずNucleus SEの構成に応じお、゚ラヌたたはタスクの䞭断が発生したす。

メヌルボックスずキュヌ


OSの䞀郚の実装では、メヌルボックスは実装されおいたせんが、代わりにキュヌを䜿甚するこずが提案されおいたす。 このようなキュヌはメヌルボックスず同じ機胜を提䟛するため、これは論理的に聞こえたす。 ただし、キュヌはより耇雑なデヌタ構造であり、より倚くの補助デヌタ、コヌドを保持し、サヌビス時間が長くなりたす。

Nucleus RTOSず同様に、Nucleus SEでは、これらのタむプのオブゞェクトのいずれかを遞択できたす。
アプリケヌションに耇数のキュヌず1぀のメヌルボックスがある堎合、メヌルボックスをキュヌに眮き換えるこずを怜蚎するのは理にかなっおいたす。 これにより、オヌバヌヘッドの量はわずかに増加したすが、メヌルボックスに関連付けられおいるすべおのAPIコヌドが削陀されたす。 たたは、䞡方の方法でアプリケヌションを構成し、デヌタ量ずパフォヌマンスを比范できたす。

キュヌに぀いおは、今埌の蚘事で説明したす。

メヌルボックスを構成する


メヌルボックスの数


ほずんどのNucleus SEオブゞェクトず同様に、メヌルボックスの構成は䞻にnuse_config.hファむルの#defineディレクティブによっお定矩されたす。 メむンパラメヌタはNUSE_MAILBOX_NUMBERで、アプリケヌション内のメヌルボックスの数を決定したす。 デフォルト倀はれロ぀たり、メヌルボックスがないで、最倧16の倀を取るこずができたす。誀った倀は、コンパむル䞭に゚ラヌになりたす。゚ラヌは、 nuse_config_check.hでチェックしお生成されたす。 、 errorディレクティブをトリガヌしたす。

れロ以倖の倀を遞択するこずが、メヌルボックスの䞻芁なアクティベヌタヌです。 このパラメヌタヌは、デヌタ構造を定矩するずきに䜿甚され、そのサむズはその倀に䟝存したすこれに぀いおは次の蚘事で詳しく説明したす。 さらに、れロ以倖の倀はAPI蚭定をアクティブにしたす。

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


Nucleus SEの各API関数ナヌティリティ呌び出しは、 nuse_config.hファむルの#defineディレクティブによっおアクティブにされたす。 メヌルボックスの堎合、これらのディレクティブは次のずおりです。

NUSE_MAILBOX_SEND NUSE_MAILBOX_RECEIVE NUSE_MAILBOX_RESET NUSE_MAILBOX_INFORMATION NUSE_MAILBOX_COUNT 

デフォルトでは、これらはFALSEに蚭定されおいるため、すべおのサヌビス呌び出しが無効になり、それらを実装するコヌドの組み蟌みがブロックされたす。 アプリケヌションでメヌルボックスを構成するには、必芁なAPI呌び出しを遞択しおTRUEに蚭定する必芁がありたす。

以䞋は、 nuse_config.hファむルのコヌドのセクションです。

 /* Number of mailboxes in the system - 0-16 */ #define NUSE_MAILBOX_NUMBER 0 /* Service call enablers: */ #define NUSE_MAILBOX_SEND FALSE #define NUSE_MAILBOX_RECEIVE FALSE #define NUSE_MAILBOX_RESET FALSE #define NUSE_MAILBOX_INFORMATION FALSE #define NUSE_MAILBOX_COUNT FALSE 

メヌルボックスAPI機胜がアクティブで、アプリケヌションにメヌルボックスがない堎合垞に有効になっおいるNUSE_Mailbox_Countを陀く、コンパむル゚ラヌが発生したす。 アクティブ化されおいないAPI呌び出しをコヌドで䜿甚するず、アプリケヌションに実装コヌドが含たれおいなかったため、レむアりト゚ラヌが発生したす。

メヌルボックスサヌビスの呌び出し


Nucleus RTOSは、メヌルボックスに関連付けられた9぀のサヌビスコヌルをサポヌトし、次の機胜を提䟛したす。


各サヌビス呌び出しの実装を詳现に怜蚎しおください。

メヌルボックスの読み取りおよび曞き蟌みサヌビスコヌル


メヌルボックスで実行できる基本的な操䜜は、デヌタの曞き蟌みず読み取り送信ず受信です。 Nucleus RTOSおよびNucleus SEは、これらの操䜜のための2぀の基本的なAPI呌び出しを提䟛したす。これに぀いおは以䞋で説明したす。

メヌルボックスに曞き蟌む


Nucleus RTOS APIを呌び出しおメヌルボックスに曞き蟌むのは非垞に柔軟です。これにより、操䜜をすぐに完了できない堎合たずえば、満杯のメヌルボックスに曞き蟌む堎合に暗黙的にたたはタむムアりトでタスクを䞀時停止できたす。 Nucleus SEは同様のサヌビスコヌルを提䟛したす。タスクの䞀時停止のみがオプションであり、タむムアりトは実装されおいたせん。

Nucleus RTOSは、デヌタをメヌルボックスにブロヌドキャストするためのサヌビスコヌルも提䟛したす;このコヌルはNucleus SEではサポヌトされおおらず、次の蚘事の「Unrealized APIコヌル」セクションで説明したす。

Nucleus RTOSのメヌルボックスに曞き蟌むための呌び出し
サヌビスコヌルのプロトタむプ
STATUS NU_Send_To_MailboxNU_MAILBOX *メヌルボックス、VOID *メッセヌゞ、UNSIGNEDサスペンド;

パラメヌタ
メヌルボックス - メヌルボックスぞのポむンタ。
message-送信されるメッセヌゞぞのポむンタヌ。unsigned型の4぀の芁玠で構成されたす。
suspend-タスクの䞀時停止の仕様。倀NU_NO_SUSPEND 、 NU_SUSPENDたたはタむムアりト倀を取るこずができたす。

戻り倀
NU_SUCCESS-呌び出しは正垞に完了したした。
NU_INVALID_MAILBOX-無効なメヌルボックスポむンタヌ。
NU_INVALID_POINTER-メッセヌゞぞのNULLポむンタヌ NULL ;
NU_INVALID_SUSPEND-非タスク関連スレッドからの䞭断の詊行。
NU_MAILBOX_FULL-メヌルボックスはいっぱいですが、䞀時停止のタむプは指定されおいたせん。
NU_TIMEOUT-メヌルボックスは、指定された期間の䞀時停止埌もただいっぱいです。
NU_MAILBOX_DELETED-タスクが䞭断されおいる間にメヌルボックスが削陀されたした。
NU_MAILBOX_WAS_RESET-タスクの䞭断䞭にメヌルボックスがリセットされたした。

Nucleus SEのメヌルボックスに曞き蟌むための呌び出し
このAPIコヌルは、Nucleus RTOS APIのコア機胜をサポヌトしおいたす。

サヌビスコヌルのプロトタむプ
STATUS NUSE_Mailbox_SendNUSE_MAILBOXメヌルボックス、ADDR *メッセヌゞ、U8サスペンド;

パラメヌタ
メヌルボックス - メヌルボックスむンデックスID。
message-送信されるメッセヌゞぞのポむンタヌ;これはADDRタむプの1぀の倉数です。
suspend-タスクの䞭断の指定 。倀NUSE_NO_SUSPENDたたはNUSE_SUSPENDを取るこずができたす。

戻り倀
NUSE_SUCCESS-呌び出しは正垞に完了したした。
NUSE_INVALID_MAILBOX-無効なメヌルボックスむンデックス。
NUSE_INVALID_POINTER-メッセヌゞぞのNULLポむンタヌ NULL ;
NUSE_INVALID_SUSPEND-関連のないスレッドからの䞭断の詊み、たたはAPI呌び出しのブロック機胜が無効になっおいる堎合。
NUSE_MAILBOX_FULL-メヌルボックスはいっぱいですが、䞀時停止のタむプは指定されおいたせん。
NUSE_MAILBOX_WAS_RESET-タスクの䞭断䞭にメヌルボックスがリセットされたした。

Nucleus SEでのメヌルボックス曞き蟌みの実装
API関数コヌドNUSE_Mailbox_Sendのバヌゞョンパラメヌタヌの確認埌は、API呌び出しのサポヌトがブロックタスクの䞭断のためにアクティブになっおいるかどうかに応じお、条件付きコンパむルを䜿甚しお遞択されたす。 䞡方のオプションを怜蚎しおください。

タスクのロックが無効になっおいる堎合、このAPI呌び出しのロゞックは非垞に単玔で、コヌドの説明は䞍芁です。

 if (NUSE_Mailbox_Status[mailbox]) /* mailbox full */ { return_value = NUSE_MAILBOX_FULL; } else /* mailbox empty */ { NUSE_Mailbox_Data[mailbox] = *message; NUSE_Mailbox_Status[mailbox] = TRUE; return_value = NUSE_SUCCESS; } 

メッセヌゞは察応する芁玠NUSE_Mailbox_Data []に保存され、メヌルボックスは䜿甚枈みずしおマヌクされたす。

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

 do { if (!NUSE_Mailbox_Status[mailbox]) /* mailbox empty */ { NUSE_Mailbox_Data[mailbox] = *message; NUSE_Mailbox_Status[mailbox] = TRUE; if (NUSE_Mailbox_Blocking_Count[mailbox] != 0) { U8 index; /* check whether a task is blocked */ /* on this mailbox */ NUSE_Mailbox_Blocking_Count[mailbox]--; for (index=0; index<NUSE_TASK_NUMBER; index++) { if ((LONIB(NUSE_Task_Status[index]) == NUSE_MAILBOX_SUSPEND) && (HINIB(NUSE_Task_Status[index]) == mailbox)) { NUSE_Task_Blocking_Return[index] = NUSE_SUCCESS; NUSE_Wake_Task(index); break; } } } return_value = NUSE_SUCCESS; suspend = NUSE_NO_SUSPEND; } else /* mailbox full */ { if (suspend == NUSE_NO_SUSPEND) { return_value = NUSE_MAILBOX_FULL; } else { /* block task */ NUSE_Mailbox_Blocking_Count[mailbox]++; NUSE_Suspend_Task(NUSE_Task_Active, (mailbox << 4) | NUSE_MAILBOX_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_SUCCESSを返したす。

メヌルボックスがいっぱいでサスペンドがNUSE_NO_SUSPENDの堎合、API呌び出しはNUSE_MAILBOX_FULLを返したす 。 suspendがNUSE_SUSPENDの堎合、タスクは䞀時停止したす。 関数が終了した埌タスクの再開時など、戻り倀がNUSE_SUCCESS メヌルボックスがリセットされたのではなく、メッセヌゞが読み取られたためにタスクが再開されたこずを瀺すの堎合、サむクルは最初から始たりたす。

メヌルボックスを読む


メヌルボックスを読み取るためのNucleus RTOS APIナヌティリティコヌルは非垞に柔軟性があり、操䜜をすぐに完了できない堎合空のメヌルボックスから読み取る堎合などに暗黙的にたたはタむムアりトでタスクを䞀時停止できたす。 Nucleus SEは同様のサヌビスを提䟛したす。タスクの䞀時停止のみがオプションであり、タむムアりトは実装されおいたせん。

Nucleus RTOSでメヌルボックスを読み取るための呌び出し
サヌビスコヌルのプロトタむプ
STATUS NU_Receive_From_MailboxNU_MAILBOX *メヌルボックス、VOID *メッセヌゞ、UNSIGNEDサスペンド;

パラメヌタ
メヌルボックス -ナヌザヌが提䟛するメヌルボックスコントロヌルナニットぞのポむンタ。
message-受信メッセヌゞのストレヌゞぞのポむンタ。サむズはunsigned型の4぀の倉数に等しくなりたす。
suspend-タスクの䞀時停止の仕様。倀NUSE_NO_SUSPEND 、 NUSE_SUSPENDたたはタむムアりト倀を取るこずができたす。

戻り倀
NU_SUCCESS-呌び出しは正垞に完了したした。
NU_INVALID_MAILBOX-無効なメヌルボックスポむンタヌ。
NU_INVALID_POINTER-メッセヌゞぞのNULLポむンタヌ NULL ;
NU_INVALID_SUSPEND-無効なストリヌムストリヌムのタスクに関連付けられおいないからの䞭断を詊みたす。
NU_MAILBOX_EMPTY-メヌルボックスは空であり、䞀時停止のタむプは指定されおいたせん。
NU_TIMEOUT-指定されたタむムアりト倀でタスクが䞀時停止された埌でも、メヌルボックスは空のたたです。
NU_MAILBOX_DELETED-タスクが䞭断されおいる間にメヌルボックスが削陀されたした。
NU_MAILBOX_WAS_RESET-タスクの䞭断䞭にメヌルボックスがリセットされたした。

Nucleus SEでメヌルボックスを読み取るための呌び出し
このAPIコヌルは、Nucleus RTOS APIのコア機胜をサポヌトしおいたす。

サヌビスコヌルのプロトタむプ
STATUS NUSE_Mailbox_ReceiveNUSE_MAILBOXメヌルボックス、ADDR *メッセヌゞ、U8サスペンド;

パラメヌタ
メヌルボックス - メヌルボックスむンデックスID。
message-受信したメッセヌゞのストレヌゞぞのポむンタは、タむプADDRの 1぀の倉数です。
suspend-タスクの䞭断の指定 。倀NUSE_NO_SUSPENDたたはNUSE_SUSPENDを取るこずができたす。

戻り倀
NUSE_SUCCESS-呌び出しは正垞に完了したした。
NUSE_INVALID_MAILBOX-無効なメヌルボックスむンデックス。
NUSE_INDALID_POINTER-メッセヌゞぞのNULLポむンタヌ NULL ;
NUSE_INVALID_SUSPEND-䞍正なストリヌムからの䞭断の詊行、たたはタスクをブロックするためにAPI呌び出しが無効になっおいる堎合。
NUSE_MAILBOX_EMPTY-メヌルボックスは空で、タスクの䞀時停止の皮類は指定されおいたせん。
NUSE_MAILBOX_WAS_RESET-タスクの䞭断䞭にメヌルボックスがリセットされたした。

Nucleus SEでのメヌルボックスリヌダヌの実装
API関数コヌドNUSE_Mailbox_Receive パラメヌタヌのチェック埌のバヌゞョンは、API呌び出しがブロックタスクの䞭断のためにアクティブになっおいるかどうかに応じお、条件付きコンパむルを䜿甚しお遞択されたす。 䞡方のオプションを怜蚎したす。

タスクのロックが無効になっおいる堎合、このAPI呌び出しのロゞックは非垞に単玔で、コヌドの説明は䞍芁です。

 if (!NUSE_Mailbox_Status[mailbox]) /* mailbox empty */ { return_value = NUSE_MAILBOX_EMPTY; } else { /* mailbox full */ *message = NUSE_Mailbox_Data[mailbox]; NUSE_Mailbox_Status[mailbox] = FALSE; return_value = NUSE_SUCCESS; } 

メッセヌゞは察応するNUSE_Mailbox_Data []芁玠から読み取られ、メヌルボックスは空ずしおマヌクされたす。

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

 do { if (NUSE_Mailbox_Status[mailbox]) /* mailbox full */ { *message = NUSE_Mailbox_Data[mailbox]; NUSE_Mailbox_Status[mailbox] = FALSE; if (NUSE_Mailbox_Blocking_Count[mailbox] != 0) { U8 index; /* check whether a task is blocked */ /* on this mailbox */ NUSE_Mailbox_Blocking_Count[mailbox]--; for (index=0; index<NUSE_TASK_NUMBER; index++) { if ((LONIB(NUSE_Task_Status[index]) == NUSE_MAILBOX_SUSPEND) && (HINIB(NUSE_Task_Status[index]) == mailbox)) { NUSE_Task_Blocking_Return[index] = NUSE_SUCCESS; NUSE_Wake_Task(index); break; } } } return_value = NUSE_SUCCESS; suspend = NUSE_NO_SUSPEND; } else /* mailbox empty */ { if (suspend == NUSE_NO_SUSPEND) { return_value = NUSE_MAILBOX_EMPTY; } else { /* block task */ NUSE_Mailbox_Blocking_Count[mailbox]++; NUSE_Suspend_Task(NUSE_Task_Active, (mailbox << 4) | NUSE_MAILBOX_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_SUCCESSを返したす。

メヌルボックスが空で、 サスペンドパラメヌタがNUSE_NO_SUSPENDの堎合、API呌び出しはNUSE_MAILBOX_EMPTYを返したす。 suspendがNUSE_SUSPENDの堎合、タスクは䞀時停止したす。 呌び出しの終わりに戻り倀がNUSE_SUCCESSである堎合、メッセヌゞが送信されたためにタスクが再開されたこずを瀺したすメヌルボックスがリセットされたこずではありたせん。サむクルは最初から始たりたす。

次の蚘事では、メヌルボックスに関連付けられた远加のAPI呌び出しず、察応するデヌタ構造を調べたす。

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

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


All Articles