Die ganze Wahrheit über RTOS. Artikel Nr. 25. Datenkanäle: Einführung und Basisdienste



Nach einer kurzen Pause veröffentlichen wir weiterhin Übersetzungen von The Whole Truth About RTOS von Colin Walls. Dieses Mal werden wir über Datenübertragungskanäle (im Folgenden als Kanäle bezeichnet) sprechen, die bereits in einem der vorherigen Artikel erwähnt wurden, nämlich in # 5 . Kanäle bieten im Vergleich zu Postfächern ( Nr. 21 und Nr. 22 ) oder Warteschlangen ( Nr. 23 und Nr. 24 ) eine flexiblere Möglichkeit, einfache Nachrichten zwischen Aufgaben zu übertragen.

Frühere Artikel in der Reihe:

Artikel 24. Warteschlangen: Nebendienstleistungen und Datenstrukturen
Artikel 23. Warteschlangen: Einführung und Grundversorgung
Artikel 22. Postfächer: Nebendienstleistungen und Datenstrukturen
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.

Kanäle verwenden


In Nucleus SE werden Kanäle während der Montagephase identifiziert. Jede Anwendung kann bis zu 16 Kanäle haben. Wenn in der Anwendung keine Kanäle konfiguriert sind, werden weder Datenstrukturen noch Serviceanrufcodes, die sich auf die Kanäle beziehen, in die Anwendung aufgenommen.

Datenübertragungskanal - Eine Reihe von Speichern, deren Größe es Ihnen ermöglicht, ein Datenelement mit einer benutzerdefinierten Länge in Bytes zu platzieren. Der Zugriff auf Daten wird so gesteuert, dass mehrere Aufgaben sie sicher verwenden können. Aufgaben können Daten in den Kanal schreiben, bis alle Bereiche voll sind. Aufgaben können Daten aus dem Kanal lesen, und die Daten werden gemäß dem FIFO-Prinzip empfangen. Der Versuch, in einen überfüllten Kanal zu schreiben oder von einem leeren Kanal zu lesen, kann abhängig von den ausgewählten API-Aufrufeinstellungen und der Nucleus SE-Konfiguration zu einem Fehler oder einer Unterbrechung der Aufgabe führen.

Kanäle und Warteschlangen


Nucleus SE unterstützt auch Warteschlangen, die in früheren Artikeln (Nr. 23 und Nr. 24) ausführlich erläutert wurden. Der Hauptunterschied zwischen Kanälen und Warteschlangen ist die Größe der Nachricht. Warteschlangen enthalten Nachrichten, die aus einer einzelnen Variablen vom Typ ADDR bestehen, normalerweise Zeiger. Der Kanal enthält Nachrichten beliebiger Größe, die für jeden Kanal in der Anwendung individuell sind und bei den Parametereinstellungen zugewiesen werden.

Kanaleinrichtung


Anzahl der Kanäle


Wie bei den meisten Nucleus SE-Objekten wird die Kanalanpassung durch die Direktiven #define in nuse_config.h gesteuert . Der Hauptparameter ist NUSE_PIPE_NUMBER , der die Anzahl der in der Anwendung konfigurierten Kanäle bestimmt. Standardmäßig ist dieser Wert Null ( dh es gibt keine Kanäle in der Anwendung) und kann Werte bis zu 16 annehmen. Ein falscher Wert führt zu einem Kompilierungsfehler, der durch Einchecken in die Datei nuse_config_check.h generiert wird (diese Datei ist in nuse_config.c enthalten und wird kompiliert zusammen mit ihm), wodurch die Direktive #error ausgelöst wird .

Die Auswahl eines Wertes ungleich Null dient als Hauptaktivator der Kanäle. Dieser Parameter wird verwendet, um Datenstrukturen zu bestimmen, und ihre Größe hängt von ihrem Wert ab (mehr dazu im nächsten Artikel). Darüber hinaus aktiviert ein Wert ungleich Null die API-Einstellungen.

API-Aufrufe aktivieren


Jede API-Funktion (Dienstprogrammaufruf) in Nucleus SE verfügt über die Direktive #define enable in nuse_config.h . Für Kanäle sind diese Symbole:

NUSE_PIPE_SEND
NUSE_PIPE_RECEIVE
NUSE_PIPE_JAM
NUSE_PIPE_RESET
NUSE_PIPE_INFORMATION
NUSE_PIPE_COUNT

Standardmäßig sind sie auf FALSE gesetzt , sodass alle Serviceaufrufe deaktiviert sind und die Aufnahme von Code, der sie implementiert, blockiert wird. Um Kanäle in der Anwendung zu konfigurieren, müssen Sie die erforderlichen API-Dienstaufrufe auswählen und auf TRUE setzen .

Das Folgende ist ein Codeausschnitt aus der Standarddatei nuse_config.h .

#define NUSE_PIPE_NUMBER 0 /* Number of pipes in the system - 0-16 */ /* Service call enablers */ #define NUSE_PIPE_SEND FALSE #define NUSE_PIPE_RECEIVE FALSE #define NUSE_PIPE_JAM FALSE #define NUSE_PIPE_RESET FALSE #define NUSE_PIPE_INFORMATION FALSE #define NUSE_PIPE_COUNT FALSE 

Wenn die API-Funktionen aktiviert sind, aber keine Kanäle in der Anwendung vorhanden sind (außer NUSE_Pipe_Count () , das immer aktiviert ist), tritt ein Kompilierungsfehler auf. Wenn Ihr Code einen API-Aufruf verwendet, der nicht aktiviert wurde, tritt ein Layoutfehler auf, da der Implementierungscode nicht in der Anwendung enthalten war.

Overhead-Kanalanrufe


Nucleus RTOS unterstützt zehn Kanal-Overheads mit folgenden Funktionen:

  • Senden einer Nachricht an den Kanal. Nucleus SE ist in der Funktion NUSE_Pipe_Send () implementiert.
  • Empfangen Sie Nachrichten vom Kanal. Nucleus SE ist in der Funktion NUSE_Pipe_Receive () implementiert.
  • Senden Sie eine Nachricht an den oberen Rand des Kanals. Nucleus SE ist in NUSE_Pipe_Jam () implementiert.
  • Wiederherstellen des nicht verwendeten Kanals des Kanals mit Freigabe aller angehaltenen Aufgaben (Zurücksetzen). In Nucleus SE, implementiert in NUSE_Pipe_Reset () .
  • Informationen zu einem bestimmten Kanal abrufen. Nucleus SE wird mit NUSE_Pipe_Information () implementiert.
  • Gibt den Zähler der aktuell konfigurierten Kanäle in der Anwendung zurück. Nucleus SE wird mit NUSE_Pipe_Count () implementiert.
  • Hinzufügen eines neuen Kanals zur Anwendung (Erstellung). Nicht in Nucleus SE implementiert.
  • Kanal aus einer Anwendung entfernen. Nicht in Nucleus SE implementiert.
  • Zeiger auf alle Kanäle in der Anwendung zurückgeben. Nicht in Nucleus SE implementiert.
  • Senden einer Nachricht an alle auf dem Kanal angehaltenen Aufgaben (Broadcast). Nicht in Nucleus SE implementiert.

Betrachten Sie die Implementierung jedes dieser Serviceaufrufe genauer.

Serviceaufrufe zum Schreiben und Lesen von Kanälen


Die grundlegenden Vorgänge, die auf Kanälen ausgeführt werden, sind Aufzeichnen (auch Senden genannt) und Lesen (auch als Empfangen von Nachrichten bezeichnet). Zusätzlich ist es möglich, Daten am Anfang des Kanals aufzuzeichnen (Jamming). Nucleus RTOS und Nucleus SE bieten drei Haupt-API-Aufrufe für diese Operationen, die nachfolgend erläutert werden.

Kanalaufnahme


Der Aufruf des Nucleus RTOS API-Dienstprogramms zum Schreiben in den Kanal ist sehr flexibel. Dadurch können Sie Aufgaben implizit oder mit einer Zeitüberschreitung anhalten, wenn der Vorgang nicht sofort abgeschlossen werden kann (z. B. wenn Sie versuchen, in einen überfüllten Kanal zu schreiben). Nucleus SE hat eine ähnliche Herausforderung, aber die Task-Pause ist optional und ein Timeout ist nicht implementiert.

Nucleus RTOS bietet auch einen Channel-Broadcast-Dienst, wird jedoch von Nucleus SE nicht unterstützt. Es wird im Abschnitt Nicht realisierte API-Aufrufe des nächsten Artikels beschrieben.

Rufen Sie an, um Nachrichten an einen Kanal in Nucleus RTOS zu senden

Prototyp eines Serviceabrufs:

STATUS NU_Send_To_Pipe (NU_PIPE * -Pipe, VOID * -Nachricht, UNSIGNED-Größe, UNSIGNED-Suspend);

Parameter:

Pipe - ein Zeiger auf den vom Benutzer bereitgestellten Kanalsteuerblock;
message - Zeiger auf die zu sendende Nachricht;
Größe - Die Anzahl der Bytes in der Nachricht. Wenn der Kanal Nachrichten mit variabler Länge unterstützt, muss dieser Parameter gleich oder kleiner als die vom Kanal unterstützte Nachrichtenlänge sein. Wenn der Kanal Nachrichten fester Länge unterstützt, muss dieser Parameter der Größe der vom Kanal unterstützten Nachricht entsprechen.
suspend - Die Angabe der Suspendierung der Aufgabe kann die Werte NU_NO_SUSPEND , NU_SUSPEND oder Timeout-Wert annehmen .

Rückgabewert:

NUSE_SUCCESS - Der Anruf wurde erfolgreich abgeschlossen.
NU_INVALID_PIPE - ungültiger Zeiger auf den Kanal;
NU_INVALID_POINTER - Nullzeiger auf eine Nachricht ( NULL );
NU_INVALID_SIZE - Die Nachrichtengröße ist nicht mit der vom Kanal unterstützten Nachrichtengröße kompatibel.
NU_INVALID_SUSPEND - Versuch, einen nicht aufgabenbezogenen Thread auszusetzen;
NU_PIPE_FULL - Der Kanal ist voll und die Art der Taskunterbrechung wurde nicht angegeben.
NU_TIMEOUT - Der Kanal ist auch dann voll, wenn die Aufgabe für einen bestimmten Zeitraum angehalten wurde.
NU_PIPE_DELETED - Der Kanal wurde gelöscht, während die Aufgabe angehalten wurde.
NU_PIPE_RESET - Der Kanal wurde zurückgesetzt, während die Aufgabe angehalten wurde.

Rufen Sie an, um Nachrichten an einen Kanal in Nucleus SE zu senden

Dieser API-Serviceaufruf unterstützt die Kernfunktionalität der Nucleus RTOS-API.

Prototyp eines Serviceabrufs:

STATUS NUSE_Pipe_Send (NUSE_PIPE-Pipe, U8 * -Nachricht, U8-Suspend);

Parameter:

Pipe - Index (ID) des verwendeten Kanals;
message - ein Zeiger auf die zu sendende Nachricht (eine Folge von Bytes mit einer Länge, die für einen bestimmten Kanal zulässig ist);
suspend - Die Task-Suspendierungsspezifikation kann die Werte NUSE_NO_SUSPEND und NUSE_SUSPEND annehmen .

Rückgabewert:

NUSE_SUCCESS - Der Anruf wurde erfolgreich abgeschlossen.
NUSE_INVALID_PIPE - ungültiger Kanalindex ;
NUSE_INVALID_POINTER - Nullzeiger auf eine Nachricht ( NULL );
NUSE_INVALID_SUSPEND - Versuch, einen nicht aufgabenbezogenen Thread anzuhalten oder wenn die Aufgabensperre deaktiviert ist;
NUSE_PIPE_FULL - Der Kanal ist voll und die Art der Taskunterbrechung wurde nicht angegeben.
NUSE_PIPE_WAS_RESET - Der Kanal wurde zurückgesetzt, während die Aufgabe angehalten wurde.

Implementierung der Kanalbuchung in Nucleus SE

Die Version des API-Funktionscodes NUSE_Pipe_Send () (nach Überprüfung der Parameter) wird mithilfe der bedingten Kompilierung ausgewählt, je nachdem, ob die Unterstützung für API-Aufrufe aktiviert ist, um Aufgaben zu blockieren (anzuhalten) oder nicht. Nachfolgend betrachten wir beide Optionen.

Wenn die Sperre deaktiviert ist, ist der Code für diesen API-Aufruf ziemlich einfach:

 if (NUSE_Pipe_Items[pipe] == NUSE_Pipe_Size[pipe]) /* pipe full */ { return_value = NUSE_PIPE_FULL; } else /* pipe element available */ { data = &NUSE_Pipe_Data[pipe][NUSE_Pipe_Head[pipe]]; for (i=0; i<msgsize; i++) { *data++ = *message++; } NUSE_Pipe_Head[pipe] += msgsize; if (NUSE_Pipe_Head[pipe] == (NUSE_Pipe_Size[pipe] * msgsize)) { NUSE_Pipe_Head[pipe] = 0; } NUSE_Pipe_Items[pipe]++; return_value = NUSE_SUCCESS; } 

Die Funktion prüft, ob im Kanal freier Speicherplatz vorhanden ist, und verwendet den Index NUSE_Pipe_Head [] , um die Nachricht im Kanaldatenbereich zu platzieren.

Wenn die Task-Sperre aktiviert ist, wird der Code komplexer:

 do { if (NUSE_Pipe_Items[pipe] == NUSE_Pipe_Size[pipe]) /* pipe full */ { if (suspend == NUSE_NO_SUSPEND) { return_value = NUSE_PIPE_FULL; } else { /* block task */ NUSE_Pipe_Blocking_Count[pipe]++; NUSE_Suspend_Task(NUSE_Task_Active, (pipe << 4) | NUSE_PIPE_SUSPEND); return_value = NUSE_Task_Blocking_Return[NUSE_Task_Active]; if (return_value != NUSE_SUCCESS) { suspend = NUSE_NO_SUSPEND; } } } else /* pipe element available */ { data = &NUSE_Pipe_Data[pipe][NUSE_Pipe_Head[pipe]]; for (i=0; i<msgsize; i++) { *data++ = *message++; } NUSE_Pipe_Head[pipe] += msgsize; if (NUSE_Pipe_Head[pipe] == (NUSE_Pipe_Size[pipe] * msgsize)) { NUSE_Pipe_Head[pipe] = 0; } NUSE_Pipe_Items[pipe]++; if (NUSE_Pipe_Blocking_Count[pipe] != 0) { U8 index; /* check whether a task is blocked on this pipe */ NUSE_Pipe_Blocking_Count[pipe]--; for (index=0; index<NUSE_TASK_NUMBER; index++) { if ((LONIB(NUSE_Task_Status[index]) == NUSE_PIPE_SUSPEND) && (HINIB(NUSE_Task_Status[index]) == pipe)) { NUSE_Task_Blocking_Return[index] = NUSE_SUCCESS; NUSE_Wake_Task(index); break; } } } return_value = NUSE_SUCCESS; suspend = NUSE_NO_SUSPEND; } } while (suspend == NUSE_SUSPEND); 

Einige Erläuterungen können hilfreich sein.

Der Code ist in einer do ... while-Schleife eingeschlossen , die ausgeführt wird, während der Parameter für die Taskpause NUSE_SUSPEND lautet .

Wenn der Kanal voll ist und der Suspend-Parameter NUSE_NO_SUSPEND lautet , endet der API-Aufruf mit dem Wert NUSE_PIPE_FULL . Wenn der Suspend- Parameter NUSE_SUSPEND lautet , wird die Task angehalten . Nach Abschluss ( dh wenn die Aufgabe fortgesetzt wird), wenn der Rückgabewert NUSE_SUCCESS ist, dh die Aufgabe wurde fortgesetzt, weil die Nachricht gelesen wurde (und nicht, weil der Kanal zurückgesetzt wurde), kehrt der Code zum Anfang der Schleife zurück.

Wenn der Kanal nicht voll ist, wird die bereitgestellte Nachricht mithilfe des Index NUSE_Pipe_Head [] im Kanaldatenbereich gespeichert. Es wird überprüft, ob der Kanal Aufgaben angehalten hat (ausstehende Nachrichten). Wenn es solche Aufgaben gibt, wird die erste von ihnen fortgesetzt. Die Suspend- Variable wird auf NUSE_NO_SUSPEND gesetzt , und der API-Aufruf wird mit dem Wert NUSE_SUCCESS abgeschlossen .

Lesen aus dem Kanal


Der Aufruf des Nucleus RTOS API-Dienstprogramms zum Lesen aus dem Kanal ist sehr flexibel. Sie können Aufgaben implizit oder mit einer Zeitüberschreitung anhalten, wenn der Vorgang nicht sofort abgeschlossen werden kann (z. B. wenn Sie versuchen, einen leeren Kanal zu lesen). Nucleus SE hat einen ähnlichen Dienstprogrammaufruf, aber die Taskpause ist optional und ein Timeout ist nicht implementiert.

Channel Read Challenge in Nucleus RTOS

Prototyp eines Serviceabrufs:

STATUS NU_Receive_From_Pipe (NU_PIPE * -Pipe, VOID * -Nachricht, UNSIGNED-Größe, UNSIGNED * actual_size, UNSIGNED-Suspend);

Parameter:

Pipe - ein Zeiger auf den vom Benutzer bereitgestellten Kanalsteuerblock;
Nachricht - ein Zeiger auf den Speicher für die empfangene Nachricht;
Größe - Die Anzahl der Bytes in der Nachricht. Muss mit der beim Erstellen des Kanals angegebenen Nachrichtengröße übereinstimmen.
suspend - Task-Suspendierungsspezifikation, kann NU_NO_SUSPEND- , NU_SUSPEND- oder Timeout-Werte annehmen .

Rückgabewert:

NU_SUCCESS - Der Anruf wurde erfolgreich abgeschlossen.
NU_INVALID_PIPE - ungültiger Zeiger auf den Kanal;
NU_INVALID_POINTER - Nullzeiger auf eine Nachricht ( NULL );
NU_INVALID_SUSPEND - Versuch, eine Aufgabe von einem Thread anzuhalten, der der Aufgabe nicht zugeordnet ist;
NU_PIPE_EMPTY - Der Kanal ist leer und die Art der Taskunterbrechung wurde nicht angegeben.
NU_TIMEOUT - Der Kanal ist auch dann leer, wenn die Task für den angegebenen Zeitlimitwert angehalten wurde.
NU_PIPE_DELETED - Der Kanal wurde gelöscht, während die Aufgabe angehalten wurde.
NU_PIPE_RESET - Der Kanal wurde gelöscht, während die Aufgabe angehalten wurde.

Channel Read Challenge in Nucleus SE

Dieser API-Serviceaufruf unterstützt die Kernfunktionalität der Nucleus RTOS-API.

Prototyp eines Serviceabrufs:

STATUS NUSE_Pipe_Receive (NUSE_PIPE-Pipe, U8 * -Nachricht, U8-Suspend);

Parameter:

Pipe - Index (ID) des verwendeten Kanals;
Nachricht - ein Zeiger auf den Speicher für die empfangene Nachricht (eine Folge von Bytes, deren Länge mit der Größe der Kanalnachricht übereinstimmt);
suspend - Die Task-Suspendierungsspezifikation kann die Werte NUSE_NO_SUSPEND und NU_SUSPEND annehmen .

Rückgabewert:

NUSE_SUCCESS - Der Anruf wurde erfolgreich abgeschlossen.
NUSE_INVALID_PIPE - ungültiger Kanalindex ;
NUSE_INVALID_POINTER - Nullzeiger auf eine Nachricht ( NULL );
NUSE_INVALID_SUSPEND - Ein Versuch, eine Aufgabe in einem Thread anzuhalten, der nicht der Aufgabe zugeordnet ist oder dessen Unterstützung für die Aussetzung der Aufgabe deaktiviert ist
NUSE_PIPE_EMPTY - Der Kanal ist leer und die Art der Taskunterbrechung wurde nicht angegeben.
NUSE_PIPE_WAS_RESET - Der Kanal wurde zurückgesetzt, während die Aufgabe angehalten wurde.

Implementierung des Feed Readers in Nucleus SE

Die Version des API-Funktionscodes NUSE_Pipe_Receive () (nach Überprüfung der Parameter) wird durch bedingte Kompilierung ausgewählt, je nachdem, ob die API-Unterstützung für Sperraufrufe (Task-Suspendierung) aktiviert ist oder nicht. Wir werden beide Optionen unten betrachten.

Wenn die Sperre deaktiviert ist, ist der Code für diesen API-Aufruf ziemlich einfach:

 if (NUSE_Pipe_Items[pipe] == 0) /* pipe empty */ { return_value = NUSE_PIPE_EMPTY; } else { /* message available */ data = &NUSE_Pipe_Data[pipe][NUSE_Pipe_Tail[pipe]]; for (i=0; i<msgsize; i++) { *message++ = *data++; } NUSE_Pipe_Tail[pipe] += msgsize; if (NUSE_Pipe_Tail[pipe] == (NUSE_Pipe_Size[pipe] * msgsize)) { NUSE_Pipe_Tail[pipe] = 0; } NUSE_Pipe_Items[pipe]--; *actual_size = msgsize; return_value = NUSE_SUCCESS; } 

Die Funktion prüft, ob eine Nachricht im Kanal vorhanden ist, und verwendet den Index NUSE_Pipe_Tail [] , um die Nachricht aus dem Kanaldatenbereich abzurufen , und gibt Daten über den Nachrichtenzeiger zurück.

Wenn die Task-Sperre aktiviert ist, wird der Code komplexer:

 do { if (NUSE_Pipe_Items[pipe] == 0) /* pipe empty */ { if (suspend == NUSE_NO_SUSPEND) { return_value = NUSE_PIPE_EMPTY; } else { /* block task */ NUSE_Pipe_Blocking_Count[pipe]++; NUSE_Suspend_Task(NUSE_Task_Active, (pipe << 4) | NUSE_PIPE_SUSPEND); return_value = NUSE_Task_Blocking_Return[NUSE_Task_Active]; if (return_value != NUSE_SUCCESS) { suspend = NUSE_NO_SUSPEND; } } } else { /* message available */ data = &NUSE_Pipe_Data[pipe][NUSE_Pipe_Tail[pipe]]; for (i=0; i<msgsize; i++) { *message++ = *data++; } NUSE_Pipe_Tail[pipe] += msgsize; if (NUSE_Pipe_Tail[pipe] == (NUSE_Pipe_Size[pipe] * msgsize)) { NUSE_Pipe_Tail[pipe] = 0; } NUSE_Pipe_Items[pipe]--; if (NUSE_Pipe_Blocking_Count[pipe] != 0) { U8 index; /* check whether a task is blocked */ /* on this pipe */ NUSE_Pipe_Blocking_Count[pipe]--; for (index=0; index<NUSE_TASK_NUMBER; index++) { if ((LONIB(NUSE_Task_Status[index]) == NUSE_PIPE_SUSPEND) && (HINIB(NUSE_Task_Status[index]) == pipe)) { NUSE_Task_Blocking_Return[index] = NUSE_SUCCESS; NUSE_Wake_Task(index); break; } } } *actual_size = msgsize; return_value = NUSE_SUCCESS; suspend = NUSE_NO_SUSPEND; } } while (suspend == NUSE_SUSPEND); 

Einige Erläuterungen können hilfreich sein.

Der Code ist in einer do ... while-Schleife eingeschlossen , die ausgeführt wird, während der Parameter für die Taskpause NUSE_SUSPEND lautet .

Wenn der Kanal leer ist und der Suspend-Parameter NUSE_NO_SUSPEND lautet , endet der API-Aufruf mit dem Wert NUSE_PIPE_EMPTY . Wenn der Suspend-Parameter NUSE_SUSPEND lautet , wird die Task angehalten . Wenn der Rückgabewert nach Abschluss ( dh wenn die Aufgabe fortgesetzt wird) NUSE_SUCCESS lautet, dh die Aufgabe wurde fortgesetzt, weil die Nachricht gesendet wurde (und nicht, weil der Kanal zurückgesetzt wurde), kehrt der Code zum Anfang der Schleife zurück.

Wenn der Kanal Nachrichten enthält, wird die gespeicherte Nachricht mithilfe des NUSE_Pipe_Tail [] -Index zurückgegeben. Überprüft, ob auf diesem Kanal angehaltene (wartende) Aufgaben vorhanden sind. Wenn es solche Aufgaben gibt, wird die erste von ihnen fortgesetzt. Die Suspend-Variable wird auf NUSE_NO_SUSPEND gesetzt , und der API-Aufruf wird mit dem Code NUSE_SUCCESS beendet.

Nehmen Sie am Anfang des Kanals auf


Der Aufruf des Nucleus RTOS API-Dienstprogramms zum Schreiben an den Anfang des Kanals ist sehr flexibel, sodass Sie Aufgaben implizit oder mit einer Zeitüberschreitung anhalten können, wenn der Vorgang nicht sofort abgeschlossen werden kann (z. B. wenn Sie versuchen, in einen vollständigen Kanal zu schreiben). Nucleus SE hat einen ähnlichen Dienstprogrammaufruf, aber die Taskpause ist optional und ein Timeout ist nicht implementiert.

Rufen Sie auf, um in Nucleus RTOS an den Anfang des Kanals zu schreiben

Prototyp eines Serviceabrufs:

STATUS NU_Send_To_Front_Of_Pipe (NU_PIPE * -Pipe, VOID * -Nachricht, UNSIGNED-Größe, UNSIGINED-Suspend);

Parameter:

Pipe - ein Zeiger auf den vom Benutzer bereitgestellten Kanalsteuerblock;
message - Zeiger auf die zu sendende Nachricht;
Größe - Die Anzahl der Bytes in der Nachricht. Wenn der Kanal Nachrichten mit variabler Länge unterstützt, muss dieser Parameter gleich oder kleiner als die Größe der vom Kanal unterstützten Nachricht sein. Wenn der Kanal Nachrichten mit fester Länge unterstützt, muss dieser Parameter mit der vom Kanal unterstützten Nachrichtengröße übereinstimmen.
suspend - Task-Suspendierungsspezifikation, kann NU_NO_SUSPEND- , NU_SUSPEND- oder Timeout-Werte annehmen .

Rückgabewert:

NU_SUCCESS - Der Anruf wurde erfolgreich abgeschlossen.
NU_INVALID_PIPE - ungültiger Zeiger auf den Kanal;
NU_INVALID_POINTER - Nullzeiger auf eine Nachricht ( NULL );
NU_INVALID_SIZE - Die Nachrichtengröße ist nicht mit der vom Kanal unterstützten Nachrichtengröße kompatibel.
NU_INVALID_SUSPEND - Versuch, einen Thread auszusetzen, der nicht mit der Aufgabe zusammenhängt;
NU_PIPE_FULL - Der Kanal ist voll und die Art der Taskunterbrechung wurde nicht angegeben.
NU_TIMEOUT - Der Kanal ist auch dann voll, wenn die Aufgabe für einen bestimmten Zeitraum angehalten wurde.
NU_PIPE_DELETED - Der Kanal wurde gelöscht, während die Aufgabe angehalten wurde.
NU_PIPE_RESET - Der Kanal wurde zurückgesetzt, während die Aufgabe angehalten wurde.

Rufen Sie an, um an den Anfang des Kanals in Nucleus SE zu schreiben

Dieser Dienstprogrammaufruf unterstützt die Kernfunktionalität der Nucleus RTOS-API.

Prototyp eines Serviceabrufs:

STATUS NUSE_Pipe_Jam (NUSE_PIPE-Pipe, ADDR * -Nachricht, U8-Suspend);

Parameter:

Pipe - Index (ID) des verwendeten Kanals;
message - ein Zeiger auf die zu sendende Nachricht, bei der es sich um eine Folge von Bytes handelt, die der konfigurierten Nachrichtengröße im Kanal entspricht;
suspend - Die Spezifikation für die Task-Suspendierung kann NUSE_NO_SUSPEND oder NUSE_SUSPEND sein .

Rückgabewert:

NUSE_SUCCESS - Der Anruf wurde erfolgreich abgeschlossen.
NUSE_INVALID_PIPE - ungültiger Kanalindex ;
NUSE_INVALID_POINTER - Nullzeiger auf eine Nachricht ( NULL );
NUSE_INVALID_SUSPEND - ein Versuch, eine Aufgabe von einem Thread aus anzuhalten , der der Aufgabe nicht zugeordnet ist oder wenn die Aufgabensperre deaktiviert ist;
NUSE_PIPE_FULL - Der Kanal ist voll und die Art der Taskunterbrechung wurde nicht angegeben.
NUSE_PIPE_WAS_RESET - Der Kanal wurde zurückgesetzt, während die Aufgabe angehalten wurde.

Implementieren der Kanaleintragsaufzeichnung in Nucleus SE

Der Variantencode der Funktion NUSE_Pipe_Jam () ist NUSE_Pipe_Send () sehr ähnlich, außer dass der Index NUSE_Pipe_Tail [] zum Speichern von Daten darin verwendet wird.

 if (NUSE_Pipe_Items[pipe] == NUSE_Pipe_Size[pipe]) /* pipe full */ { return_value = NUSE_PIPE_FULL; } else /* pipe element available */ { if (NUSE_Pipe_Tail[pipe] == 0) { NUSE_Pipe_Tail[pipe] = (NUSE_Pipe_Size[pipe] - 1) * msgsize; } else { NUSE_Pipe_Tail[pipe] -= msgsize; } data = &NUSE_Pipe_Data[pipe][NUSE_Pipe_Tail[pipe]]; for (i=0; i<msgsize; i++) { *data++ = *message++; } NUSE_Pipe_Items[pipe]++; return_value = NUSE_SUCCESS; } 

Im nächsten Artikel werden wir zusätzliche Serviceanrufe in Bezug auf Kanäle sowie die entsprechenden Datenstrukturen betrachten.

Ü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/de433046/


All Articles