
Das Konzept eines Problems wurde in früheren Artikeln vorgestellt. Tatsächlich ist eine Aufgabe einfach eine Reihe von Werten, die in Prozessorregister geladen werden können (damit die Aufgabe ausgeführt werden kann) oder in einem Zustand gespeichert werden können, der für die zukünftige kontextbezogene Umschaltung auf die Aufgabe bereit ist. Meistens hat eine Aufgabe einen eigenen Stapel.
Bei Verwendung des RTC-Schedulers (Run to Completion) wird die Kontextumschaltung natürlich nicht verwendet, und die Aufgabe kann nur als Wert des Programmzählers (Code-Einstiegspunkt) betrachtet werden.
Die Definition der Aufgabe enthält nicht den Code selbst. Die Task sollte den Code ausführen, gehört aber nicht dazu. Aufgaben können gemeinsame Funktionen haben. Darüber hinaus kann der gesamte Code für mehrere Aufgaben gemeinsam genutzt werden. Allgemeiner Code sollte fast immer gemäß den Wiedereintrittsanforderungen geschrieben werden. Die meisten Compiler können mit diesem Code problemlos umgehen, müssen jedoch bei Bibliotheksfunktionen vorsichtig sein, da sie möglicherweise nicht für Multitasking-Anwendungen geeignet sind.
Eine solche Definition schreibt bestimmte Regeln vor, die beim Entwickeln der in diesem Artikel beschriebenen Datenstrukturen von Aufgaben und API-Funktionen befolgt werden sollten. Ich werde die Konfiguration von Aufgaben in Nucleus SE überprüfen und einen detaillierten Überblick über Serviceaufrufe (API-Aufrufe) erhalten, die für Aufgaben in Nucleus SE und Nucleus RTOS gelten.
Frühere Artikel in der Reihe:
Artikel 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.
Aufgabenkonfiguration
Anzahl der Aufgaben
In Nucleus SE wird die Aufgabenkonfiguration hauptsächlich von den Direktiven
#define in
nuse_config.h gesteuert . Der Schlüsselparameter
NUSE_TASK_NUMBER bestimmt die Anzahl der Aufgaben, die in der Anwendung konfiguriert werden können. Der Standardwert ist 1 (d. H. Eine Aufgabe während der Ausführung) und der Maximalwert des Parameters ist 16. Ein falscher Wert führt zu einem Kompilierungsfehler, der durch Einchecken von
nuse_config_chech.h generiert wird (dies ist in
nuse_config.c enthalten , was bedeutet kompiliert mit diesem Modul), wird die
# Fehler- Direktive
ausgelöst . Dieser Parameter wird verwendet, um Datenstrukturen zu bestimmen, deren Größe von ihrem Wert abhängt.
In Nucleus SE ist es außer bei Verwendung des RTC-Schedulers wichtig, dass immer mindestens eine Aufgabe zur Ausführung bereit ist. Wenn Sie den Prioritätsplaner verwenden, müssen Sie sicherstellen, dass die Aufgabe mit der niedrigsten Priorität niemals angehalten wird. Eine solche Aufgabe sollte als "Hintergrundaufgabe" betrachtet werden.
Im Gegensatz zu einigen anderen Echtzeitkernen verwendet Nucleus SE keine "Systemaufgaben". Dies bedeutet, dass alle 16 Aufgaben für den Benutzeranwendungscode oder die Middleware verfügbar sind.
API-Parameter
Jede API-Funktion (Dienstprogrammaufruf) in Nucleus SE wird durch die Direktive
#define in
nuse_config.h aktiviert. Für Aufgaben sind diese Parameter:
- NUSE_TASK_SUSPEND
- NUSE_TASK_RESUME
- NUSE_TASK_SLEEP
- NUSE_TASK_RELINQUISH
- NUSE_TASK_CURRENT
- NUSE_TASK_CHECK_STACK
- NUSE_TASK_RESET
- NUSE_TASK_INFORMATION
- NUSE_TASK_COUNT
Standardmäßig sind alle oben genannten Parameter auf
FALSE gesetzt , wodurch jeder Serviceabruf deaktiviert und die Aufnahme von Code verhindert wird, der sie implementiert. Um Aufgaben für die Anwendung zu konfigurieren, müssen Sie die erforderlichen API-Aufrufe auswählen und die entsprechenden Zeichen auf
TRUE setzen .
Das Folgende ist ein
Ausschnitt aus der Standarddatei
nuse_config.h .

Wenn Ihr Code einen API-Aufruf verwendet, der nicht aktiviert wurde, wird beim Verknüpfen ein Fehler angezeigt, da der Implementierungscode nicht in der Anwendung enthalten war.
Funktionsparameter
Nucleus SE kann einige Aufgabenfunktionen hinzufügen. Die erforderlichen Parameter befinden sich wiederum in der Datei
nuse_config.h :
Mit NUSE_SUSPEND_ENABLE können
Sie Aufgaben
anhalten . Wenn diese Option nicht ausgewählt ist, warten alle Aufgaben ständig auf die Planung. Die Aktivierung dieses Parameters ist erforderlich, wenn der Prioritätsplaner verwendet wird.
Mit NUSE_BLOCKING_ENABLE können
Sie Aufgaben für mehrere Funktions-API-Aufrufe
anhalten . Wenn diese Option aktiviert ist, muss auch
NUSE_SUSPEND_ENABLE aktiviert sein.
Mit NUSE_INITIAL_TASK_STATE_SUPPORT können
Sie den Anfangszustand der Aufgabe festlegen. Wenn diese Option nicht ausgewählt ist, werden alle Aufgaben unmittelbar nach der Erstellung zum Scheduler hinzugefügt.
Utility-Task-Aufrufe
Nucleus RTOS unterstützt 16 Service Calls (APIs) für die Arbeit mit Aufgaben, die die folgenden Funktionen bieten:
Funktionsbeschreibung | Nucleus RTOS | Nucleus SE |
---|
Unterbrechen Sie eine Aufgabe | NU_Suspend_Task () | NUSE_Task_Suspend () |
Aufgabe fortsetzen | NU_Resume_Task () | NUSE_Task_Resume () |
Unterbrechen Sie eine Aufgabe für eine bestimmte die Periode | NU_Sleep () | NUSE_Task_Sleep () |
CPU-Steuerungsfreigabe | NU_Relinquish () | NUSE_Task_Relinquish () |
Abrufen der ID der aktuellen Aufgabe | NU_Current_Task_Pointer () | NUSE_Task_Current () |
Überprüfen der verfügbaren Stapelgröße | NU_Check_Stack () | NUSE_Task_Check_Stack () |
Aufgabe auf unbenutzt zurücksetzen Zustand (zurücksetzen) | NU_Reset_Task () | NUSE_Task_Reset () |
Bereitstellung von Informationen zu einer bestimmten Aufgabe | NU_Task_Information () | NUSE_Task_Information () |
Konfigurierter Zähler Aufgaben (im Moment) in der Anwendung | NU_Established_Tasks () | NUSE_Task_Count () |
Hinzufügen einer neuen Aufgabe zur Anwendung (Erstellung) | NU_Create_Task () | Nicht implementiert. |
Entfernen einer Aufgabe aus der Anwendung | NU_Delete_Task () | Nicht implementiert. |
Zeiger auf alle Aufgaben zurückgeben im Anhang | NU_Task_Pointers () | Nicht implementiert. |
Extrusionsalgorithmus ändern | NU_Change_Preemption () | Nicht implementiert. |
Ändern Sie die Aufgabenpriorität | NU_Change_Priority () | Nicht implementiert. |
Ändern Sie das Zeitquantum einer Aufgabe | NU_Change_Time_Slice () | Nicht implementiert. |
Aufgabenerfüllung | NU_Terminate_Task () | Nicht implementiert. |
Die Implementierung jedes der oben genannten Serviceaufrufe wird nachstehend sowie in den folgenden Artikeln zu RTOS ausführlich erläutert.
Aufgabenverwaltungsdienste
Grundlegende Vorgänge mit Aufgaben: Halten Sie eine Aufgabe auf unbestimmte Zeit an, setzen Sie sie fort, halten Sie eine Aufgabe für eine bestimmte Zeit an, geben Sie den Prozessor frei. Nucleus RTOS und Nucleus SE bieten vier grundlegende API-Aufrufe, um diese Operationen auszuführen, die ich unten beschreiben werde.
Unterbrechen Sie eine Aufgabe
Nucleus PLUS bietet einen einfachen API-Aufruf, mit dem Sie eine bestimmte Aufgabe auf unbestimmte Zeit anhalten können. Nucleus SE hat einen Büroanruf mit ähnlicher Funktionalität.
Unterbrechen Sie eine Aufgabe in Nucleus RTOSPrototyp eines Serviceabrufs:
STATUS NU_Suspend_Task (NU_TASK * -Aufgabe);Parameter:
task - Ein Zeiger auf die Steuereinheit der angehaltenen Task (die möglicherweise aktuell ist und deren ID mit
NU_Current_Task_Pointer () abgerufen werden
kann , mehr im nächsten Artikel).
Rückgabewert:
NU_SUCCESS - Der Anruf wurde erfolgreich abgeschlossen.
NU_INVALID_TASK - ungültiger Zeiger auf die Aufgabe;
NU_INVALID_SUSPEND - Die angegebene Aufgabe hat den Status
NU_FINISHED oder
NU_TERMINATED .
Pause der Herausforderungsaufgabe in Nucleus SEDieser API-Aufruf unterstützt die Kernfunktionalität der Nucleus PLUS-API.
Prototyp eines Serviceabrufs:
STATUS NUSE_Task_Suspend (NUSE_TASK-Task);Parameter:
task - Der Index (ID) der angehaltenen Task (der aktuell sein kann und dessen ID mit
NUSE_Task_Current () abgerufen werden
kann - mehr im nächsten Artikel).
Rückgabewert:
NUSE_SUCCESS - Der Anruf wurde erfolgreich abgeschlossen.
NUSE_INVALID_TASK - ungültiger Aufgabenindex.
Implementieren Sie die Unterbrechung einer Aufgabe in Nucleus SEDie Hauptfunktionalität der API-Funktion ist recht einfach:

Tatsächlich wird in dieser Implementierung die Scheduler-Funktion
NUSE_Suspend_Task () mit dem Parameter "Unbedingter Stopp" (
NUSE_PURE_SUSPEND )
aufgerufen . Diese Funktion ruft den Scheduler auf, wenn die angehaltene Aufgabe ausgeführt wird.
Aufgabe fortsetzen
Nucleus RTOS bietet einen einfachen API-Aufruf, mit dem Sie eine Aufgabe fortsetzen können, die zuvor auf unbestimmte Zeit angehalten wurde. Nucleus SE hat einen Büroanruf mit ähnlicher Funktionalität.
Herausforderung Wiederaufnahme Aufgabe in Nucleus RTOSPrototyp eines Serviceabrufs:
STATUS NU_Resume_Task (NU_TASK * Aufgabe);Parameter:
task - ein Zeiger auf die Steuereinheit der erneuerten Task.
Rückgabewert:
NUSE_SUCCESS - Der Anruf wurde erfolgreich abgeschlossen.
NUSE_INVALID_TASK - ungültiger Zeiger auf die Aufgabe;
NUSE_INVALID_RESUME - Die Aufgabe wurde nicht unbedingt angehalten.
Fordern Sie die Aufgaben in Nucleus SE wieder aufDieser API-Aufruf unterstützt die Kernfunktionalität der Nucleus RTOS-API.
Prototyp eines Serviceabrufs:
STATUS NUSE_Task_Resume (NUSE_TASK-Task);Parameter:
Task - Index (ID) der erneuerten Task.
Rückgabewert:
NUSE_SUCCESS - Der Anruf wurde erfolgreich abgeschlossen.
NUSE_INVALID_TASK - ungültiger Aufgabenindex;
NUSE_INVALID_RESUME - Die Aufgabe wurde nicht unbedingt angehalten.
Implementieren von Lebenslaufaufgaben in Nucleus SEDie Hauptfunktionalität der API-Funktion ist recht einfach:

Tatsächlich wird in dieser Implementierung die Scheduler-Funktion
NUSE_Wake_Task () aufgerufen. Diese Funktion ruft den Scheduler auf, wenn der Prioritätsplaner verwendet wird und die erneuerte Aufgabe eine höhere Priorität als die aktuelle Aufgabe hat.
Anhalten einer Aufgabe für einen bestimmten Zeitraum
Nucleus RTOS bietet einen einfachen API-Aufruf, um die aktuelle Aufgabe für einen bestimmten Zeitraum anzuhalten. Nucleus SE hat einen Büroanruf mit ähnlicher Funktionalität.
Rufen Sie Suspend-Tasks für einen bestimmten Zeitraum auf. Nucleus RTOSPrototyp eines Serviceabrufs:
VOID NU_Sleep (UNSIGNED Ticks);Parameter:
Ticks - Zeitraum, für den die Aufgabe angehalten werden soll (in Echtzeit-
Ticks ).
Rückgabewert:
Nein.
Fordern Sie eine Aufgabenpause für einen bestimmten Zeitraum heraus. Nucleus SEDieser API-Aufruf unterstützt die Kernfunktionalität der Nucleus RTOS-API.
Prototyp eines Serviceabrufs:
void NUSE_Task_Sleep (U16-Ticks);Parameter:
Ticks - Zeitraum, für den die Aufgabe angehalten werden soll (in Echtzeit-
Ticks ).
Rückgabewert:
Nein.
Implementieren einer Unterbrechung einer Aufgabe für einen bestimmten Zeitraum in Nucleus SEDie Hauptfunktionalität der API-Funktion ist recht einfach:

Dieser Code lädt den Verzögerungswert in den aktuellen
Taskparameter in
NUSE_Task_Timeout_Counter [] . Danach wird die Aufgabe mit
NUSE_Suspend_Task () mit dem Suspendierungszeitraum (
NUSE_SLEEP_SUSPEND )
angehalten .
Der Timeout-Wert wird vom Echtzeit-Clock-Interrupt-Handler verwendet. Der Code wird unten gezeigt und in einem zukünftigen Artikel ausführlicher behandelt.

CPU-Freigabe
Nucleus PLUS bietet einen einfachen API-Aufruf, mit dem die Prozessorsteuerung auf alle ausführbaren Aufgaben mit derselben Priorität basierend auf dem Round Robin-Algorithmus übertragen werden kann. Nucleus SE hat einen Büroanruf mit sehr ähnlichen Funktionen. Es kann jedoch nicht mit dem Prioritätsplaner verwendet werden, da mehrere Aufgaben mit derselben Priorität nicht unterstützt werden. Der Versuch, diesen API-Aufruf mit dem Prioritätsplaner zu verwenden, führt zu einem Fehler. Ein Dienstprogrammaufruf funktioniert mit den Schedulern Round Robin und Time Slice. Mit dem Scheduler Run To Completion ist dieser API-Aufruf ineffizient.
Aufruf zur Freigabe des Nucleus RTOS-ProzessorsDieser API-Aufruf unterstützt die Kernfunktionalität der Nucleus PLUS-API.
Prototyp eines Serviceabrufs:
VOID NU_Relinquish (VOID);Parameter:
Sind abwesend.
Rückgabewert:
Nein.
Aufruf zur Freigabe des Nucleus SE-ProzessorsDieser API-Aufruf unterstützt die Kernfunktionalität der Nucleus PLUS-API.
Prototyp eines Serviceabrufs:
void NUSE_Task_Relinquish (void);Parameter:
Sind abwesend.
Rückgabewert:
Nein.
Implementierung der Nucleus SE-ProzessorfreigabeDie Hauptfunktionalität der API-Funktion:

Im Wesentlichen ruft diese Implementierung die Scheduler-Funktion
NUSE_Reschedule () auf . Diese Funktion weist den Scheduler einfach an, die nächste Aufgabe abzuschließen.
In den nächsten beiden Artikeln werden weiterhin aufgabenbezogene RTOS-Dienstprogrammaufrufe anhand der Beispiele für Nucleus RTOS und Nucleus SE behandelt.
Ü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.
Über die Übersetzung: Diese Artikelserie schien insofern interessant zu sein, als der Autor trotz der an einigen Stellen veralteten beschriebenen Ansätze den schlecht ausgebildeten Leser in die Funktionen des Echtzeit-Betriebssystems einführt. Ich selbst gehöre zu dem Team von Entwicklern des
russischen RTOS , das wir
kostenlos machen wollen , und ich hoffe, dass der Zyklus für unerfahrene Entwickler nützlich sein wird.