Die ganze Wahrheit über RTOS. Artikel # 18. Ereignis-Flag-Gruppen: Hilfsdienste und Datenstrukturen

Ursprünglicher Autor: Colin Walls
  • Übersetzung


Dieser Artikel beschreibt weiterhin Gruppen von Ereignisflags.

Vorherige Artikel in der Serie:

Artikel # 17. Event-Flag-Gruppen: Einführung und Basisdienste
Artikel # 16. Signalisiert
Artikel 15. Speicherbereiche: Dienste und Datenstrukturen
Artikel # 14. Speicherabschnitte: Einführung und Grunddienste
Artikel # 13. Aufgabendatenstrukturen und nicht unterstützte API-Aufrufe
Artikel 12. Aufgabendienste
Artikel 11. Aufgaben: Konfiguration und Einführung in den API-
Artikel # 10. Scheduler: Zusätzliche Funktionen und Speichern des Kontext-
Artikels 9. Scheduler: Implementierung
Artikel 8. Nucleus SE: Internes Design und Bereitstellung
Artikel 7. Nucleus SE: Einführungsartikel
Nr. 6. Andere RTOS-Dienste
Artikel # 5. Interaktion zwischen Aufgaben und Synchronisation
Artikel 4. Aufgaben, Kontextwechsel und Interrupts
Artikel 3. Aufgaben und Planung
Artikel 2. RTOS: Struktur und Echtzeitmodus
Artikel 1. RTOS: Einführung.


Zusatzdienste für Gruppen von Ereignisflaggen


Nucleus RTOS verfügt über drei API-Aufrufe, die Hilfsfunktionen für Gruppen von Ereignisflags bereitstellen: Informationen über eine Gruppe abrufen, Informationen zur Anzahl der Gruppen von Ereignisflags in einer Anwendung erhalten und Zeiger auf alle Gruppen von Ereignisflags abrufen. Die ersten beiden Aufrufe werden in der Nucleus SE implementiert.

Informationen über eine Gruppe von Ereignisflags abrufen


Dieser Serviceabruf gibt Informationen zu einer Gruppe von Ereignisflags zurück. Die Implementierung dieses Aufrufs im Nucleus SE unterscheidet sich von der Implementierung im Nucleus RTOS darin, dass weniger Informationen zurückgegeben werden, da die Benennung von Objekten und die Reihenfolge der Suspendierung von Tasks nicht unterstützt werden und das Suspendieren von Tasks selbst deaktiviert werden kann.

Aufruf für Informationen zur Ereignisgruppe in Nucleus RTOS
Service Call Prototyp:
STATUS NU_Event_Group_Information (NU_EVENT_GROUP * -Gruppe, CHAR * Name, UNSIGNED * Event_flags, UNSIGNED * Aufgaben_waiting, NU_TASK ** first_task);

Parameter:
group - ein Zeiger auf eine vom Benutzer bereitgestellte Steuereinheit für eine Gruppe von Ereignisflags;
Name- Zeiger auf das achtstellige Feld für den Namen der Gruppe von Ereignisflags, zu dem auch die abschließende Null gehört;
event_flags - ein Zeiger auf eine Variable, die den aktuellen Wert der angegebenen Gruppe von Ereignisflags akzeptiert.
task_waiting - Zeiger auf eine Variable, die die Anzahl der angehaltenen Aufgaben in dieser Gruppe von Ereignisflags erhält;
first_task - Ein Zeiger auf eine Variable vom Typ NU_TASK , die einen Zeiger auf die erste angehaltene Task nimmt.

Rückgabewert:
NU_SUCCESS - Der Aufruf wurde erfolgreich abgeschlossen.
NU_INVALID_GROUP - falscher Zeiger auf eine Gruppe von Ereignisflags.

Informieren Sie sich über eine Gruppe von Ereignissen in der Nucleus SE
Dieser Aufruf unterstützt die Kernfunktionalität der Nucleus RTOS-API.

Dienstaufruf-Prototyp:
STATUS NUSE_Event_Group_Information (Gruppe NUSE_EVENT_GROUP, U8 * event_flags, U8 * task_waiting, NUSE_TASK * first_task);

Parameter:
group - Der Index der Gruppe von Ereignis-Flags, über die Informationen angefordert werden.
event_flags - ein Zeiger auf eine Variable, die den aktuellen Wert der angegebenen Gruppe von Ereignisflags akzeptiert.
task_waiting - Zeiger auf die Variable, die die Anzahl der ausgesetzten Tasks in dieser Gruppe von Ereignisflags akzeptiert (nichts wird zurückgegeben, wenn die Taskaussetzung deaktiviert ist);
first_task - Ein Zeiger auf eine Variable vom Typ NUSE_TASKdie den Index der ersten angehaltenen Aufgabe akzeptiert (nichts wird zurückgegeben, wenn die Aussetzung von Aufgaben deaktiviert ist).

Rückgabewert:
NUSE_SUCCESS - Der Aufruf wurde erfolgreich abgeschlossen.
NUSE_INVALID_GROUP - falscher Index der Gruppe der Ereignisflags.

Informationen zu einer Gruppe von Ereignissen in Nucleus SE
implementieren Die Implementierung dieses API-Aufrufs ist recht einfach:

*event_flags = NUSE_Event_Group_Data[group];
#if NUSE_BLOCKING_ENABLE
    *tasks_waiting = NUSE_Event_Group_Blocking_Count[group];
    if (NUSE_Event_Group_Blocking_Count[group] != 0)
    {
        U8 index;
        for (index=0; index<NUSE_TASK_NUMBER; index++)
        {
            if ((LONIB(NUSE_Task_Status[index]) ==
                 NUSE_EVENT_SUSPEND)
                && (HINIB(NUSE_Task_Status[index]) == group))
            {
                *first_task = index;
                break;
            }
        }
    }
    else
    {
        *first_task = 0;
    }
#else
    *tasks_waiting = 0;
    *first_task = 0;
#endifreturn NUSE_SUCCESS;

Die Funktion gibt den Wert der Gruppe der Ereignisflags zurück. Wenn die Taskblockierungs-API-Aufrufe aktiviert werden, werden die Anzahl der anstehenden Tasks und der Index der ersten Task zurückgegeben (andernfalls wird diesen beiden Parametern ein Nullwert zugewiesen).

Abrufen der Anzahl der Gruppen von Ereignisflags


Dieser Serviceaufruf gibt die Anzahl der Gruppen von Ereignisflags in der Anwendung zurück. In Nucleus RTOS ändert sich dieser Wert im Laufe der Zeit, und der Rückgabewert zeigt die aktuelle Anzahl der Gruppen. In Nucleus SE wird dieser Wert zum Erstellungszeitpunkt bestimmt und ändert sich nicht mit der Zeit.

Aufruf des Ereignismarkierungsgruppenzählers in Nucleus RTOS
Service Call Prototyp:
UNSIGNED NU_Establised_Event_Groups (VOID);

Parameter:
Keine.

Rückgabewert:
Die aktuelle Anzahl der erstellten Ereignisflaggruppen.

Aufruf des Ereignismarkierungsgruppenzählers im Nucleus SE- Serviceabruf
Prototyp:
U8 NUSE_Event_Group_Count (void);

Parameter:
Keine.

Rückgabewert:
Die Anzahl der konfigurierten Ereignisflaggruppen.

Implementieren des Ereignisflaggruppenzählers in Nucleus SE Die
Implementierung dieses API-Aufrufs ist ziemlich trivial: Der Wert des Symbols #define NUSE_EVENT_GROUP_NUMBER wird zurückgegeben .

Datenstrukturen


Wie alle Nucleus SE-Objekte verwenden Gruppen von Ereignisflags ein oder zwei Arrays von Datenstrukturen (beide befinden sich im RAM). Die Größe der Arrays hängt von der Anzahl der in den Einstellungen definierten Gruppen ab.

Ich empfehle dringend, dass der Anwendungscode nicht direkt auf diese Datenstrukturen, sondern über die bereitgestellten API-Funktionen zugreift. Dadurch werden Inkompatibilitäten mit zukünftigen Versionen des Nucleus SE und unerwünschte Nebenwirkungen vermieden und die Portierung der Anwendung auf das Nucleus RTOS vereinfacht. Zum besseren Verständnis der Funktionsweise des Serviceabrufcodes und zum Debuggen wird nachstehend eine detaillierte Übersicht der Datenstrukturen bereitgestellt.

Daten in RAM


Diese Daten haben die folgende Struktur:
NUSE_Event_Group_Data [] - ein Datenfeld vom Typ U8 mit einem Eintrag für jede konfigurierte Gruppe von Flags; Es speichert Ereignisflagdaten.
NUSE_Event_Group_Blocking_Count [] ist ein Array vom Typ U8, das den Zähler blockierter Aufgaben in jeder Gruppe von Ereignisflags enthält. Dieses Array ist nur vorhanden, wenn die Sperrfunktion in der API aktiviert ist.

Diese Datenstrukturen werden in der Funktion NUSE_Init_Event_Group () beim Start der Nucleus SE mit Nullen initialisiert . Einer der folgenden Artikel enthält eine vollständige Beschreibung der Startprozeduren von Nucleus SE.

Im Folgenden werden diese Datenstrukturen in der Datei nuse_init.c beschrieben :

RAM U8 NUSE_Event_Group_Data[NUSE_EVENT_GROUP_NUMBER];
#if NUSE_BLOCKING_ENABLE
    RAM U8 NUSE_Event_Group_Blocking_Count[NUSE_EVENT_GROUP_NUMBER];
#endif

Daten im ROM


Für die Implementierung von Gruppen von Ereignisflags werden keine Daten im ROM verwendet.

Speichergröße für Gruppen von Ereignisflags


Wie bei allen Nucleus SE-Kernobjekten ist der für Gruppen von Ereignisflags erforderliche Speicher vorhersehbar.

Die Datenmenge im ROM für alle Gruppen von Ereignisflags in der Anwendung beträgt 0.

Die Größe des Arbeitsspeichers im RAM für alle Gruppen von Ereignisflags bei aktivierter API- Sperrfunktion ist NUSE_EVENT_GROUP_NUMBER * 2 .

Ansonsten ist es NUSE_EVENT_GROUP_NUMBER .

Nicht realisierte API-Aufrufe


Drei API-Aufrufe für Ereignis-Flag-Gruppen, die im Nucleus-RTOS gefunden werden können, wurden nicht in Nucleus SE implementiert.

Erstellen einer Gruppe von Ereignisflags


Dieser API-Aufruf erstellt eine Gruppe von Ereignisflags. In Nucleus SE ist dieser Aufruf nicht erforderlich, da Gruppen von Ereignisflags statisch erstellt werden.

Prototyp
eines Serviceabrufs : STATUS NU_Create_Event_Group (NU_EVENT_GROUP * -Gruppe, CHAR * Name);

Parameter:

group - ein Zeiger auf eine vom Benutzer bereitgestellte Steuereinheit für eine Gruppe von Ereignisflags; wird als Deskriptor zur Steuerung von Gruppen von Ereignisflags in anderen API-Aufrufen verwendet;
name ist ein Zeiger auf den achtstelligen Namen der Gruppe von Ereignisflags, wobei das abschließende Null-Byte in diesem Bereich enthalten ist.

Rückgabewert:

NU_SUCCESS - Der Aufruf wurde erfolgreich abgeschlossen.
NU_INVALID_GROUP - Nullzeiger auf die Steuereinheit der Gruppe der Ereignisflags (NULL ) oder bereits verwendet.

Löschen einer Gruppe von Ereignisflags


Dieser API-Aufruf entfernt die zuvor erstellte Gruppe von Ereignisflags. In Nucleus SE ist dieser Aufruf nicht erforderlich, da Gruppen von Ereignisflags statisch erstellt werden und nicht gelöscht werden können.

Prototyp des

Serviceaufrufs : STATUS NU_Delete_Event_Group (NU_EVENT_GROUP * -Gruppe);

Parameter:

group - Ein Zeiger auf eine Steuereinheit für eine Gruppe von Ereignisflags.

Rückgabewert:

NU_SUCCESS - Der Aufruf wurde erfolgreich abgeschlossen.
NU_INVALID_GROUP - falscher Zeiger auf eine Gruppe von Ereignisflags.

Event-Flag-Gruppenzeiger


Dieser API-Aufruf erstellt eine sequentielle Liste von Zeigern auf alle Gruppen von Ereignisflags im System. In Nucleus SE ist dieser Aufruf nicht erforderlich, da die Ereignisflaggruppen einfache Indizes und keine Zeiger haben.

Dienstaufruf-Prototyp:

UNSIGNED NU_Event_Group_Pointers (NU_EVENT_GROUP * pointer_list, UNSIGNED Maximum_pointers);

Parameter:

pointer_list - Ein Zeiger auf ein Array von Zeigern. NU_EVENT_GROUP . Dieses Array ist mit Zeigern auf Gruppen von Ereignisflags gefüllt, die im System erstellt werden.
maximum_pointers - die maximale Anzahl von Zeigern im Array.

Rückgabewert: Die

Anzahl der NU_EVENT_GROUP- Zeiger im Array.

RTOS-Kompatibilität von Nucleus


Bei der Entwicklung des Nucleus SE war es mein Ziel, die Codekompatibilität mit Nucleus RTOS auf höchstem Niveau zu gewährleisten. Gruppen von Event-Flags waren keine Ausnahme, und aus der Sicht des Entwicklers werden sie fast genauso implementiert wie im Nucleus RTOS. Es gibt einige Inkompatibilitäten, die ich für akzeptabel hielt, da der endgültige Code in Bezug auf die benötigte Speichermenge verständlicher und effizienter wird. Ansonsten können Nucleus RTOS-API-Aufrufe fast direkt als Nucleus SE-Aufrufe verwendet werden.

Objekt-IDs


In Nucleus RTOS werden alle Objekte durch Datenstrukturen (Steuereinheiten) eines bestimmten Typs beschrieben. Ein Zeiger auf diese Steuereinheit dient als Kennung für eine Gruppe von Ereignisflags. Ich entschied, dass in Nucleus SE ein anderer Ansatz für die effektive Verwendung des Speichers erforderlich ist: Alle Kernelobjekte werden durch mehrere Tabellen im RAM und / oder ROM beschrieben. Die Größe dieser Tabellen wird durch die Anzahl der konfigurierten Objekte jedes Typs bestimmt. Die spezifische Objektkennung ist ein Index in dieser Tabelle. Also habe ich NUSE_EVENT_GROUP als Äquivalent zu U8 definiertEine Variable dieses Typs (kein Zeiger) dient als Kennung für eine Gruppe von Ereignisflags. Diese geringe Inkompatibilität ist einfach zu handhaben, wenn der Code vom Nucleus SE zum Nucleus RTOS und umgekehrt übertragen wird. Normalerweise werden keine Vorgänge für Objektkennungen ausgeführt, außer zum Verschieben und Speichern.

Nucleus RTOS unterstützt auch die Benennung von Gruppen von Ereignisflags. Diese Namen werden nur zum Debuggen verwendet. Ich habe sie aus dem Nucleus SE ausgeschlossen, um Speicher zu sparen.

Die Anzahl der Flags in der Gruppe


In Nucleus RTOS enthalten Gruppen von Event-Flags jeweils 32 Flags, in Nucleus SE reduzierte ich deren Anzahl auf acht, da dies für einfache Anwendungen ausreicht und Sie RAM sparen können. Nucleus SE kann leicht modifiziert werden, wenn größere Gruppen von Ereignisflags erforderlich sind.

Flag-Absorptionsfunktion


In Nucleus RTOS gibt es eine Funktion zum Löschen (Aufnehmen) von Event-Flags nach dem Lesen. Ich habe mich entschieden, diese Funktion von Nucleus SE auszuschließen, um das System zu vereinfachen, da die Absorption (Löschung) von Flags auftritt, wenn alle gesperrten Aufgaben Flags zum Lesen erhalten, was schwer zu implementieren wäre. Falls erforderlich, kann die Task, die die Flags liest, diese immer mit einem separaten API-Aufruf löschen.

Nicht realisierte API-Aufrufe


Nucleus RTOS unterstützt sieben Serviceaufrufe für das Arbeiten mit Gruppen von Ereignisflags. Davon sind drei nicht im Nucleus SE implementiert. Die Details dieser Aufrufe sowie die Entscheidung, sie von Nucleus SE auszuschließen, wurden oben beschrieben.
Der nächste Artikel befasst sich mit Semaphoren.

Über den Autor: Colin Walls ist seit über dreißig Jahren in der Elektronikbranche tätig und verbrachte viel Zeit mit eingebetteter Software. Er ist jetzt ein Embedded Software Engineer in Mentor Embedded (einer Abteilung von Mentor Graphics). Colin Walls spricht häufig auf Konferenzen und Seminaren, Autor zahlreicher Fachartikel und zwei Bücher über eingebettete Software. Lebt in Großbritannien. Colins professioneller Blog , E-Mail: colin_walls@mentor.com.

Jetzt auch beliebt: