
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 DatenstrukturenArtikel 23. Warteschlangen: Einführung und GrundversorgungArtikel 22. Postfächer: Nebendienstleistungen und DatenstrukturenArtikel 21. Postfächer: Einführung und BasisdiensteArtikel Nr. 20. Semaphoren: Nebendienstleistungen und DatenstrukturenArtikel Nr. 19. Semaphoren: Einführung und GrundversorgungArtikel Nr. 18. Ereignisflag-Gruppen: Hilfsdienste und DatenstrukturenArtikel Nr. 17. Ereignisflag-Gruppen: Einführung und BasisdiensteArtikel 16. SignaleArtikel Nr. 15. Speicherpartitionen: Dienste und DatenstrukturenArtikel # 14. Speicherbereiche: Einführung und GrundversorgungArtikel Nr. 13. Aufgabendatenstrukturen und nicht unterstützte API-AufrufeArtikel 12. Dienstleistungen für die Arbeit mit AufgabenArtikel 11. Aufgaben: Konfiguration und Einführung in die APIArtikel 10. Scheduler: Erweiterte Funktionen und KontexterhaltungArtikel 9. Scheduler: ImplementierungArtikel 8. Nucleus SE: Internes Design und BereitstellungArtikel 7. Nucleus SE: EinführungArtikel 6. Andere RTOS-DiensteArtikel 5. Aufgabeninteraktion und SynchronisationArtikel 4. Aufgaben, Kontextwechsel und InterruptsArtikel 3. Aufgaben und PlanungArtikel 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_SENDNUSE_PIPE_RECEIVENUSE_PIPE_JAMNUSE_PIPE_RESETNUSE_PIPE_INFORMATIONNUSE_PIPE_COUNTStandardmäß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 sendenPrototyp 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 sendenDieser 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 SEDie 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 RTOSPrototyp 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 SEDieser 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 SEDie 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 schreibenPrototyp 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 schreibenDieser 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 SEDer 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.