Die ganze Wahrheit über RTOS. Artikel 22. Postfächer: Nebendienstleistungen und Datenstrukturen



Dieser Artikel setzt die Überprüfung der Postfächer fort, die im vorherigen Artikel in der Reihe „Die Wahrheit über RTOS“ begonnen haben.

Frühere Artikel in der Reihe:

Artikel 21. Postfächer: Einführung und Basisdienste
Artikel Nr. 20. Semaphoren: Nebendienstleistungen und Datenstrukturen
Artikel Nr. 19. Semaphoren: Einführung und Grundversorgung
Artikel Nr. 18. Ereignisflag-Gruppen: Hilfsdienste und Datenstrukturen
Artikel Nr. 17. Ereignisflag-Gruppen: Einführung und Basisdienste
Artikel 16. Signale
Artikel Nr. 15. Speicherpartitionen: Dienste und Datenstrukturen
Artikel # 14. Speicherbereiche: Einführung und Grundversorgung
Artikel Nr. 13. Aufgabendatenstrukturen und nicht unterstützte API-Aufrufe
Artikel 12. Dienstleistungen für die Arbeit mit Aufgaben
Artikel 11. Aufgaben: Konfiguration und Einführung in die API
Artikel 10. Scheduler: Erweiterte Funktionen und Kontexterhaltung
Artikel 9. Scheduler: Implementierung
Artikel 8. Nucleus SE: Internes Design und Bereitstellung
Artikel 7. Nucleus SE: Einführung
Artikel 6. Andere RTOS-Dienste
Artikel 5. Aufgabeninteraktion und Synchronisation
Artikel 4. Aufgaben, Kontextwechsel und Interrupts
Artikel 3. Aufgaben und Planung
Artikel 2. RTOS: Struktur und Echtzeitmodus
Artikel 1. RTOS: Einführung.


Zusätzliche Postfachdienste


Nucleus RTOS verfügt über vier API-Aufrufe, die Zusatzfunktionen für Postfächer bereitstellen: Speichern eines Postfachs, Abrufen von Informationen zu einem Postfach, Abrufen der Anzahl von Postfächern in einer Anwendung und Abrufen von Zeigern auf alle Postfächer in einer Anwendung. Die ersten drei dieser Funktionen sind in Nucleus SE implementiert.

Mailbox zurückgesetzt


Dieser API-Serviceaufruf setzt das Postfach auf seinen ursprünglichen, nicht verwendeten Status zurück. Die in der Mailbox gespeicherte Nachricht geht verloren. Alle an der Mailbox angehaltenen Aufgaben werden mit dem Rückkehrcode NUSE_MAILBOX_WAS_RESET fortgesetzt .

Rufen Sie an, um eine Mailbox in Nucleus RTOS zurückzusetzen
Prototyp eines Serviceabrufs:
STATUS NU_Reset_Mailbox (NU_MAILBOX * Mailbox);

Parameter:
Mailbox - Ein Zeiger auf die Mailbox-Steuereinheit.

Rückgabewert:
NU_SUCCESS - Der Anruf wurde erfolgreich abgeschlossen.
NU_INVALID_MAILBOX - ungültiger Postfachzeiger.

Rufen Sie an, um eine Mailbox in Nucleus SE zurückzusetzen
Dieser API-Serviceaufruf unterstützt die Kernfunktionalität der Nucleus RTOS-API.

Prototyp eines Serviceabrufs:
STATUS NUSE_Mailbox_Reset (NUSE_MAILBOX-Postfach);

Parameter:
Postfach - Index (ID) des ausgegebenen Postfachs.

Rückgabewert:
NUSE_SUCCESS - Der Anruf wurde erfolgreich abgeschlossen.
NUSE_INVALID_MAILBOX - Ungültiger Postfachindex.

Implementieren Sie das Zurücksetzen der Mailbox in Nucleus SE
Die Variante des Funktionscodes NUSE_Mailbox_Reset (nach Überprüfung der Parameter) wird mithilfe der bedingten Kompilierung ausgewählt, je nachdem, ob die Unterstützung für das Blockieren (Anhalten) von Aufgaben aktiviert ist oder nicht. Wir werden beide Optionen in Betracht ziehen.

Wenn die Sperre nicht aktiviert ist, ist der Code für diese API-Funktion ziemlich einfach. Das Postfach wird als nicht verwendet markiert, indem der Parameter NUSE_Mailbox_Status [] auf FALSE gesetzt wird .

Wenn die Sperre aktiviert ist, wird der Code komplexer:

while (NUSE_Mailbox_Blocking_Count[mailbox] != 0) { U8 index; /* check whether any tasks are blocked */ /* on this 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_MAILBOX_WAS_RESET; NUSE_Task_Status[index] = NUSE_READY; break; } } NUSE_Mailbox_Blocking_Count[mailbox]--; } #if NUSE_SCHEDULER_TYPE == NUSE_PRIORITY_SCHEDULER NUSE_Reschedule(NUSE_NO_TASK); #endif 

Das Postfach wird auf den Status "Leer" zurückgesetzt.

Jeder angehaltenen Aufgabe in der Mailbox wird der Status "Bereit" mit dem Rückkehrcode NUSE_MAILBOX_WAS_RESET zugewiesen . Wenn nach Abschluss dieses Vorgangs der Prioritätsplaner verwendet wird, wird der Dienstaufruf NUSE_Reschedule () ausgeführt , da eine oder mehrere Aufgaben mit einer höheren Priorität bereit sein und auf die Ausführung der Berechtigung warten können.

Mailbox-Informationen abrufen


Dieser Serviceabruf enthält eine Reihe von Postfachinformationen. Die Implementierung dieses Aufrufs in Nucleus SE unterscheidet sich von Nucleus RTOS darin, dass weniger Informationen zurückgegeben werden, da die Objektbenennung und die Pausenreihenfolge nicht unterstützt werden und die Aufgabenpause deaktiviert werden kann.

Rufen Sie an, um Informationen zur Nucleus RTOS-Mailbox zu erhalten
Dieser API-Aufruf unterstützt die Kernfunktionalität der Nucleus RTOS-API.

Prototyp eines Serviceabrufs:
STATUS NU_Mailbox_Information (NU_MAILBOX * Mailbox, CHAR * Name, OPTION * Suspend_Type, DATA_ELEMENT * Message_present, UNSIGNED * Tasks_waiting, NU_TASK ** first_task);

Parameter:

Mailbox - Zeiger auf die Mailbox-Steuereinheit;
name - ein 8-stelliger Zeiger auf den Postfachnamen. Das abschließende Nullbyte ist ebenfalls in diesem Bereich enthalten.
suspend_type - Zeiger auf die Variable, in der der Suspensionstyp der Aufgabe gespeichert ist. Es kann die Werte NU_FIFO und NU_PRIORITY annehmen .
message_present - ein Zeiger auf eine Variable, die den Wert NU_TRUE oder NU_FALSE annimmt , je nachdem, ob das Postfach voll ist oder nicht;
task_waiting - ein Zeiger auf eine Variable, die die Anzahl der in diesem Postfach angehaltenen Aufgaben übernimmt;
first_task - Ein Zeiger auf einen Aufgabenzeiger, der einen Zeiger auf die erste angehaltene Aufgabe nimmt.

Rückgabewert:

NU_SUCCESS - Der Anruf wurde erfolgreich abgeschlossen.
NU_INVALID_MAILBOX - ungültiger Postfachzeiger.

Rufen Sie an, um Informationen zur Nucleus SE-Mailbox zu erhalten
Dieser API-Serviceaufruf unterstützt die Kernfunktionalität der Nucleus RTOS-API.

Prototyp eines Serviceabrufs:

STATUS NUSE_Mailbox_Information (Postfach NUSE_MAILBOX, U8 * message_present, U8 *asks_waiting, NUSE_TASK * first_task);

Parameter:

Postfach - Index des Postfachs, über das Informationen angefordert werden;
message_present - ein Zeiger auf eine Variable, die den Wert TRUE oder FALSE annimmt, je nachdem, ob das Postfach voll ist oder nicht;
task_waiting - ein Zeiger auf eine Variable, die die Anzahl der in diesem Postfach angehaltenen Aufgaben übernimmt (bei deaktivierter Aufgabenaussetzung wird nichts zurückgegeben);
first_task - Ein Zeiger auf eine Variable vom Typ NUSE_TASK , die den Index der ersten angehaltenen Aufgabe übernimmt (nichts wird zurückgegeben, wenn die Aufgabe angehalten ist).

Rückgabewert:

NUSE_SUCCESS - Der Anruf wurde erfolgreich abgeschlossen.
NUSE_INVALID_MAILBOX - ungültiger Postfachindex;
NUSE_INVALID_POINTER - Ein oder mehrere Zeigerparameter sind falsch.

Implementieren von Postfachinformationen in Nucleus SE

Die Implementierung dieses API-Aufrufs ist recht einfach:

 *message_present = NUSE_Mailbox_Status[mailbox]; #if NUSE_BLOCKING_ENABLE *tasks_waiting = NUSE_Mailbox_Blocking_Count[mailbox]; if (NUSE_Mailbox_Blocking_Count[mailbox] != 0) { U8 index; for (index=0; index<NUSE_TASK_NUMBER; index++) { if ((LONIB(NUSE_Task_Status[index]) == NUSE_MAILBOX_SUSPEND) && (HINIB(NUSE_Task_Status[index]) == mailbox)) { *first_task = index; break; } } } else { *first_task = 0; } #else *tasks_waiting = 0; *first_task = 0; #endif return NUSE_SUCCESS; 

Die Funktion gibt den Status der Mailbox zurück. Wenn dann Dienstaufrufe zum Blockieren von Aufgaben aktiviert werden, werden die Anzahl der angehaltenen Aufgaben und der Index der ersten zurückgegeben (andernfalls werden diese Parameter auf 0 gesetzt).

Abrufen der Anzahl der Postfächer


Dieser Dienstprogrammaufruf gibt die Anzahl der Postfächer in der Anwendung zurück. Während sich in Nucleus RTOS die Anzahl im Laufe der Zeit ändern kann und der Rückgabewert die aktuelle Anzahl der Postfächer anzeigt, wird in Nucleus SE die Anzahl der Postfächer in der Erstellungsphase festgelegt und kann nicht geändert werden.

Aufrufen eines Postfachzählers in Nucleus RTOS
Dieser API-Aufruf unterstützt die Kernfunktionalität der Nucleus RTOS-API.

Prototyp eines Serviceabrufs:
UNSIGNED NU_Established_Mailboxes (VOID);

Parameter:
Sind abwesend.

Rückgabewert:
Die Anzahl der in der Anwendung erstellten Postfächer.

Aufrufen eines Postfachzählers in Nucleus SE
Dieser API-Aufruf unterstützt die Kernfunktionalität der Nucleus RTOS-API.

Prototyp eines Serviceabrufs:
U8 NUSE_Mailbox_Count (void);

Parameter:
Sind abwesend.

Rückgabewert:
Die Anzahl der konfigurierten Postfächer in der Anwendung.

Implementieren eines Postfachzählers in Nucleus SE
Die Implementierung dieses API-Aufrufs ist äußerst einfach: Der Wert der Direktive #define NUSE_MAILBOX_NUMBER wird zurückgegeben .

Datenstrukturen


Postfächer verwenden zwei oder drei Arrays von Datenstrukturen (die sich alle im RAM befinden), die wie andere Nucleus SE-Objekte eine Reihe von Tabellen sind, deren Größe von der Anzahl der konfigurierten Postfächer und ihren Parametern abhängt.

Ich empfehle dringend, dass der Anwendungscode keinen direkten Zugriff auf diese Datenstrukturen verwendet, sondern über die bereitgestellten API-Funktionen auf sie verweist. Dies vermeidet Inkompatibilität mit zukünftigen Versionen von Nucleus SE und unerwünschte Nebenwirkungen und vereinfacht auch die Portierung der Anwendung auf Nucleus RTOS. Im Folgenden finden Sie eine detaillierte Übersicht über Datenstrukturen, um die Funktionsweise des Serviceabrufcodes und das Debuggen besser zu verstehen.

RAM-Daten


Diese Daten haben folgende Struktur:

NUSE_Mailbox_Data [] - Ein Array vom Typ ADDR , das einen Eintrag für jedes konfigurierte Postfach enthält und Postfachdaten speichert.
NUSE_Mailbox_Status [] ist ein U8- Array mit einem Eintrag für jedes konfigurierte Postfach. Es überwacht die Verwendung von Postfächern. Ein Wert ungleich Null ( TRUE ) zeigt an, dass das Postfach voll ist.
NUSE_Mailbox_Blocking_Count [] - Ein Array vom Typ U8 , das einen Zähler für blockierte Aufgaben für jedes Postfach enthält. Dieses Array wird nur erstellt, wenn die API-Aufrufblockierungsfunktion aktiviert ist.

Diese Datenstrukturen werden beim Start von Nucleus SE in der Funktion NUSE_Init_Mailbox () mit Nullen initialisiert. Dies ist logisch, da jedes Postfach leer (nicht verwendet) erstellt wird.

Im Folgenden finden Sie die Definitionen dieser Datenstrukturen aus der Datei nuse_init.c .

 RAM ADDR NUSE_Mailbox_Data[NUSE_MAILBOX_NUMBER]; RAM U8 NUSE_Mailbox_Status[NUSE_MAILBOX_NUMBER]; #if NUSE_BLOCKING_ENABLE RAM U8 NUSE_Mailbox_Blocking_Count[NUSE_MAILBOX_NUMBER]; #endif 

ROM-Daten


Für die Implementierung von Postfächern werden keine Daten im ROM verwendet.

Die Speichermenge für Postfächer


Wie bei allen Nucleus SE-Kernelobjekten ist die für Postfächer erforderliche Speichermenge im Voraus bekannt.

Der Speicherplatz für Daten im ROM für alle Postfächer in der Anwendung beträgt 0.

Die Datenmenge im RAM für alle Postfächer in der Anwendung (in Byte) mit aktivierten API-Aufrufen zum Blockieren von Aufgaben kann wie folgt berechnet werden:
NUSE_MAILBOX_NUMBER * (Größe von (ADDR) +2)

Sonst:
NUSE_MAILBOX_NUMBER * (Größe von (ADDR) +1)

Nicht realisierte API-Aufrufe


Die vier Dienstprogrammaufrufe in Nucleus RTOS sind in Nucleus SE nicht implementiert.

Mailbox erstellen


Dieser API-Serviceaufruf erstellt ein Postfach. Nucleus SE benötigt es nicht, da Postfächer statisch erstellt werden.

Prototyp eines Serviceabrufs:
STATUS NU_Create_Mailbox (NU_MAILBOX * Mailbox, CHAR * Name, UNSIGNED OPTION suspend_type);

Parameter:

Postfach - ein Zeiger auf die vom Benutzer bereitgestellte Postfachsteuereinheit; Wird zum Verwalten von Postfächern in anderen API-Aufrufen verwendet
name - Zeiger auf den 7-stelligen Namen der Mailbox mit null Abschlussbyte;
suspend_type - Gibt das Prinzip an, eine Aufgabe in einem Postfach anzuhalten . Es kann die Werte NU_FIFO und NU_PRIORITY annehmen , die das Prinzip des FIFO (First-In-First-Out) bzw. das Prinzip der Priorität der Aussetzung von Aufgaben bedeuten.

Rückgabewert:

NU_SUCCESS - Der Anruf wurde erfolgreich abgeschlossen.
NU_INVALID_MAILBOX - Nullzeiger auf die Postfachsteuereinheit ( NULL ) oder der Zeiger wird bereits verwendet;
NU_INVALID_SUSPEND - ungültiger suspend_type- Parameter.

Löschen Sie eine Mailbox


Dieser API-Serviceaufruf löscht ein zuvor erstelltes Postfach. Nucleus SE benötigt dies nicht, da Postfächer statisch erstellt werden und nicht gelöscht werden können.

Prototyp eines Serviceabrufs:

STATUS NU_Delete_Mailbox (NU_MAILBOX * Mailbox);

Parameter:

Mailbox - Ein Zeiger auf die Mailbox-Steuereinheit.

Rückgabewert:

NU_SUCCESS - Der Anruf wurde erfolgreich abgeschlossen.
NU_INVALID_MAILBOX - ungültiger Postfachzeiger.

Mailbox-Zeiger


Dieser API-Aufruf erstellt eine sequentielle Liste von Zeigern auf alle Postfächer im System. Nucleus SE benötigt es nicht, da Postfächer durch einen einfachen Index und nicht durch einen Zeiger identifiziert werden.

Prototyp eines Serviceabrufs:

UNSIGNED NU_Mailbox_Pointers (NU_MAILBOX ** Zeigerliste, UNSIGNED Maximum_Pointers);

Parameter:

pointer_list - Zeiger auf ein Array von Zeigern NU_MAILBOX ; Dieses Array wird mit Zeigern auf Postfächer gefüllt, die im System erstellt wurden.
Maximum_Pointers - Die maximale Anzahl von Zeigern im Array.

Rückgabewert:

Die Anzahl der NU_MAILBOX- Zeiger im Array.

Notieren Sie eine Nachricht in der Mailbox zur Zustellung an alle Empfänger


Dieser Serviceabruf sendet eine Nachricht an alle Aufgaben, die auf Nachrichten aus einem bestimmten Postfach warten. In Nucleus SE ist dieser Dienstprogrammaufruf nicht implementiert, da dies zu unnötiger Komplexität führen würde.

Prototyp eines Serviceabrufs:

STATUS NU_Broadcast_To_Mailbox (NU_MAILBOX * Mailbox, VOID * Nachricht, UNSIGNED Suspend);

Parameter:

Mailbox - Zeiger auf die Mailbox-Steuereinheit;
Nachricht - Zeiger auf die übertragene Nachricht;
suspend - Gibt an, ob die aufrufende Aufgabe angehalten werden soll, wenn das Postfach bereits eine Nachricht enthält. kann NU_NO_SUSPEND , NU_SUSPEND oder ein Timeout-Wert sein.

Rückgabewert:

NU_SUCCESS - Der Anruf wurde erfolgreich abgeschlossen.
NU_INVALID_MAILBOX - ungültiger Postfachzeiger;
NU_INVALID_POINTER - Nullzeiger auf eine Nachricht ( NULL );
NU_INVALID_SUSPEND - Versuch, einen nicht aufgabenbezogenen Thread auszusetzen;
NU_MAILBOX_FULL - Das Postfach enthält bereits eine Nachricht.
NU_TIMEOUT - Nach Ablauf des Zeitlimits ist das Postfach noch voll.
NU_MAILBOX_DELETED - Das Postfach wurde gelöscht, während die Aufgabe angehalten wurde.
NU_MAILBOX_RESET - Das Postfach wurde zurückgesetzt, während die Aufgabe angehalten wurde.

Nucleus RTOS-kompatibel


Wie bei allen anderen Nucleus SE-Objekten war es mein Ziel, die Kompatibilität des Anwendungscodes mit Nucleus RTOS zu maximieren. Postfächer sind keine Ausnahme und werden aus Anwendersicht auf die gleiche Weise wie in Nucleus RTOS implementiert. Es gibt auch eine gewisse Inkompatibilität, die ich als akzeptabel angesehen habe, da der Code dadurch verständlicher und effizienter in Bezug auf den erforderlichen Speicher wird. Andernfalls können Nucleus RTOS-API-Aufrufe direkt auf Nucleus SE portiert werden.

Objektkennungen


In Nucleus RTOS werden alle Objekte durch Datenstrukturen (Steuereinheiten) eines bestimmten Typs beschrieben. Ein Zeiger auf diese Steuereinheit dient als Kennung für die Mailbox. Ich entschied, dass in Nucleus SE ein anderer Ansatz für die effiziente Nutzung des Speichers erforderlich ist: Alle Kernelobjekte werden durch eine Reihe von Tabellen im RAM und / oder ROM beschrieben. Die Größe dieser Tabellen wird durch die Anzahl der konfigurierten Objekte jedes Typs bestimmt. Die Kennung eines bestimmten Objekts ist der Index in dieser Tabelle. Also habe ich NUSE_MAILBOX als das Äquivalent von U8 definiert . Eine Variable (kein Zeiger) dieses Typs dient als Kennung des Postfachs. Diese leichte Inkompatibilität ist leicht zu handhaben, wenn der Code von Nucleus SE nach Nucleus RTOS und umgekehrt portiert wird. In der Regel werden keine anderen Operationen an Objektkennungen als Verschieben und Speichern ausgeführt.

Nucleus RTOS unterstützt auch die Benennung von Postfächern. Diese Namen werden nur zum Debuggen verwendet. Ich habe sie von Nucleus SE ausgeschlossen, um Speicherplatz zu sparen.

Nachrichtengröße und -typ


In Nucleus RTOS besteht eine Postfachnachricht aus vier 32-Bit-Wörtern. In Nucleus SE habe ich beschlossen, diesen Wert auf eine Variable vom Typ ADDR zu reduzieren. Diese Änderung führt zu erheblichen Speichereinsparungen und einer kürzeren Ausführungszeit für Aufgaben. Es wird auch vorgeschlagen, dass die übliche Verwendung eines Postfachs darin besteht, Informationen von einer Aufgabe an eine andere weiterzuleiten. Diese Inkompatibilität verursacht keine großen Probleme beim Portieren von Anwendungen auf Nucleus RTOS. Nucleus SE kann geändert werden, wenn ein anderes Nachrichtenformat benötigt wird.

Nicht realisierte API-Aufrufe


Nucleus RTOS unterstützt neun Postfachanrufe. Von diesen sind vier nicht in Nucleus SE implementiert. Die Details dieser Herausforderungen sowie die Gründe, warum sie von Nucleus SE ausgeschlossen wurden, sind oben beschrieben.

Der nächste Artikel befasst sich mit Warteschlangen.

Über den Autor: Colin Walls ist seit über dreißig Jahren in der Elektronikindustrie tätig und widmet sich die meiste Zeit der Firmware. Heute ist er Firmware-Ingenieur bei Mentor Embedded (einer Abteilung von Mentor Graphics). Colin Walls spricht häufig auf Konferenzen und Seminaren, Autor zahlreicher technischer Artikel und zweier Bücher über Firmware. Lebt in Großbritannien. Colins professioneller Blog , E-Mail: colin_walls@mentor.com.

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


All Articles