
Des groupes de drapeaux d'événements ont déjà été mentionnés précédemment dans l'un des articles précédents (# 5). Dans Nucleus SE, ils sont similaires aux signaux, mais sont plus flexibles. Ils offrent un moyen peu coûteux et flexible de transférer des messages simples entre les tâches.
Articles précédents de la série:
Article # 16. SignauxArticle # 15. Partitions de mémoire: services et structures de donnéesArticle # 14. Sections de mémoire: introduction et services de baseArticle # 13. Structures de données de tâche et appels d'API non pris en chargeArticle # 12. Services pour travailler avec des tâchesArticle # 11. Tâches: configuration et introduction à l'APIArticle # 10. Scheduler: fonctionnalités avancées et préservation du contexteArticle # 9. Scheduler: implémentationArticle # 8. Nucleus SE: conception interne et déploiementArticle # 7. Nucleus SE: IntroductionArticle # 6. Autres services RTOSArticle # 5. Interaction et synchronisation des tâchesArticle # 4. Tâches, changement de contexte et interruptionsArticle # 3. Tâches et planificationArticle # 2. RTOS: Structure et mode temps réel
Article # 1. RTOS: introduction.
Utilisation de drapeaux d'événements
Dans Nucleus SE, les indicateurs d'événement sont définis pendant la phase de génération. Le nombre maximal de groupes d'indicateurs d'événements dans l'application est de 16. Si les groupes d'indicateurs d'événements ne sont pas définis, le code lié aux structures de données et aux appels de service des groupes d'indicateurs d'événements ne sera pas inclus dans l'application.
Groupe de drapeaux d'événements - un ensemble de drapeaux de huit bits, dont l'accès est réglementé afin que plusieurs tâches puissent utiliser en toute sécurité un drapeau. Une tâche peut définir ou effacer toute combinaison de drapeaux d'événements. Une autre tâche consiste à lire un groupe de drapeaux à tout moment, et il peut également attendre une certaine séquence de drapeaux (par sondage ou avec une pause).
Configuration des groupes d'indicateurs d'événements
Nombre de groupes d'indicateurs d'événements
Comme pour la plupart des objets Nucleus SE, la configuration des groupes d'indicateurs d'événements est spécifiée par les directives
#define dans
nuse_config.h . Le paramètre principal est
NUSE_EVENT_GROUP_NUMBER , qui détermine le nombre de groupes d'indicateurs d'événements qui seront définis dans l'application. Par défaut, ce paramètre est défini sur 0 (c'est-à -dire que les groupes d'indicateurs d'événements ne sont pas utilisés) et peut avoir n'importe quelle valeur jusqu'à 16. Une valeur incorrecte entraînera une erreur de compilation, qui sera générée en
archivant nuse_config_check.h (elle est activée par
nuse_config.c , ce qui signifie qu'il compile avec ce module), par conséquent, la directive
#error fonctionnera. La sélection d'une valeur différente de zéro est le principal activateur des groupes de drapeaux d'événements. Ce paramètre est utilisé lors de la définition des structures de données et leur taille dépend de sa valeur (plus d'informations à ce sujet dans les articles suivants). De plus, une valeur différente de zéro active les paramètres de l'API.
Activer les appels API
Chaque fonction API (appel d'utilitaire) dans Nucleus SE est activée par la directive
#define dans
nuse_config.h . Pour les groupes de drapeaux d'événements, ceux-ci incluent:
NUSE_EVENT_GROUP_SET
NUSE_EVENT_GROUP_RETRIEVE
NUSE_EVENT_GROUP_INFORMATION
NUSE_EVENT_GROUP_COUNT
Par défaut, ils sont définis sur
FALSE , désactivant ainsi chaque appel de service et bloquant l'inclusion de code qui les implémente. Pour configurer des groupes d'indicateurs d'événements, vous devez sélectionner les appels d'API nécessaires et définir les directives correspondantes sur
TRUE .
Ce qui suit est un extrait du fichier nuse_config.h par défaut.
#define NUSE_EVENT_GROUP_NUMBER 0 #define NUSE_EVENT_GROUP_SET FALSE #define NUSE_EVENT_GROUP_RETRIEVE FALSE #define NUSE_EVENT_GROUP_INFORMATION FALSE #define NUSE_EVENT_GROUP_COUNT FALSE
Une fonction API activée s'il n'y a pas de groupes d'indicateurs d'événements dans l'application entraînera une erreur de compilation (sauf pour
NUSE_Event_Group_Count () , qui est toujours activé). Si votre code utilise un appel d'API qui n'a pas été activé, une erreur de mise en page se produira car le code d'implémentation n'a pas été inclus dans l'application.
Appels de l'utilitaire d'appel d'événement
Nucleus RTOS prend en charge sept appels d'utilitaires qui offrent les fonctionnalités suivantes:
- Définissez des drapeaux d'événements. Nucleus SE est implémenté dans la fonction NUSE_Event_Group_Set () .
- Lecture des drapeaux d'événements. Dans Nucleus SE, implémenté dans NUSE_Event_Group_Retrieve () .
- Fournir des informations sur un groupe spécifique d'indicateurs d'événements. Dans Nucleus SE, implémenté dans NUSE_Event_Group_Information () .
- Renvoie le nombre de groupes d'indicateurs d'événements actuellement configurés dans l'application. Dans Nucleus SE, implémenté dans NUSE_Event_Group_Count () .
- Ajout d'un nouveau groupe d'indicateurs d'événements à l'application. Nucleus SE n'est pas implémenté.
- Suppression d'un groupe d'indicateurs d'événements de l'application. Nucleus SE n'est pas implémenté.
- Renvoyer des pointeurs vers tous les groupes d'indicateurs d'événements dans l'application. Nucleus SE n'est pas implémenté.
La mise en œuvre de chacun de ces appels de surcharge est discutée en détail ci-dessous.
Il convient de noter qu'il n'y a pas de fonction de réinitialisation dans Nucleus RTOS ou Nucleus SE. Cela se fait intentionnellement. La fonction de réinitialisation implique la prévalence de l'état spécial des drapeaux. Pour les groupes de drapeaux d'événements, le seul état «spécial» est de réinitialiser tous les drapeaux, ce qui peut être fait en utilisant
NUSE_Event_Group_Set () .
Appels de service pour la définition et la lecture de groupes d'indicateurs d'événements
Les opérations fondamentales qui peuvent être effectuées sur un groupe d'indicateurs d'événements sont la définition de la valeur d'un ou plusieurs indicateurs, ainsi que la lecture des valeurs d'indicateurs actuelles. Nucleus RTOS et Nucleus SE fournissent quatre appels d'API de base pour ces opérations.
Étant donné que les drapeaux d'événements sont des bits, ils sont mieux visualisés sous forme de nombres binaires. Étant donné que la norme C n'a historiquement pas pris en charge la représentation des constantes binaires (uniquement octales et hexadécimales), Nucleus SE possède un fichier d'en-tête utile
nuse_binary.h qui contient des caractères
#define comme
b01010101 pour les 256 valeurs 8 bits.
Définir des indicateurs d'événement
L'appel de l'utilitaire Nucleus RTOS API pour le marquage est très flexible et vous permet de définir et d'effacer des valeurs de drapeau à l'aide d'opérations
ET et
OU . Nucleus SE offre des fonctionnalités similaires, mais la pause de tâche est facultative.
Appel à définir des indicateurs dans Nucleus RTOSPrototype d'appel de service:
STATUS NU_Set_Events (groupe NU_EVENT_GROUP *, UNSIGNED event_flags, opération OPTION);Paramètres:
group - un pointeur vers un bloc de contrôle fourni par l'utilisateur pour un groupe de drapeaux d'événements;
event_flags - valeur du masque de bits du groupe de drapeaux;
operation - l'
opération à effectuer,
NU_OR (pour définir les indicateurs) ou
NU_AND (pour effacer les indicateurs).
Valeur de retour:
NU_SUCCESS - l'appel s'est terminé avec succès;
NU_INVALID_GROUP - pointeur non valide vers un groupe de drapeaux d'événements;
NU_INVALID_OPERATION - L'opération spécifiée est différente de
NU_OR et
NU_AND .
Appel à définir des drapeaux dans Nucleus SECet appel d'API prend en charge la fonctionnalité principale de l'API Nucleus RTOS.
Prototype d'appel de service:
STATUS NUSE_Event_Group_Set (groupe NUSE_EVENT_GROUP, U8 event_flags, opération OPTION);Paramètres:
group - l'index (ID) du groupe d'événements dont les indicateurs sont définis / effacés;
event_flags - valeur du bit maxi d'un groupe de drapeaux;
operation - l'
opération à effectuer,
NUSE_OR (pour définir les drapeaux) ou
NUSE_AND (pour effacer les drapeaux).
Valeur de retour:
NUSE_SUCCESS - l'appel s'est terminé avec succès;
NUSE_INVALID_GROUP - index non valide d'un groupe de drapeaux d'événements;
NUSE_INVALID_OPERATION - L'opération spécifiée est différente de
NUSE_OR et
NUSE_AND .
Implémentation de l'installation de drapeaux d'événements dans Nucleus SELe code initial de la fonction d'API
NUSE_Event_Group_Set () est général (après vérification des paramètres), que l'API prenne en charge les appels de blocage (suspendre les tâches) ou non. La logique est assez simple:
NUSE_CS_Enter(); if (operation == NUSE_OR) { NUSE_Event_Group_Data[group] |= event_flags; } else /* NUSE_AND */ { NUSE_Event_Group_Data[group] &= event_flags; }
Le
masque de bits event_flags est superposé (à l'aide de l'opération
AND ou
OR ) sur la valeur du groupe sélectionné de drapeaux d'événements.
Le code restant n'est activé que lorsque le verrouillage des tâches est activé:
#if NUSE_BLOCKING_ENABLE while (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)) { NUSE_Task_Blocking_Return[index] = NUSE_SUCCESS; NUSE_Task_Status[index] = NUSE_READY; break; } } NUSE_Event_Group_Blocking_Count[group]--; } #if NUSE_SCHEDULER_TYPE == NUSE_PRIORITY_SCHEDULER NUSE_Reschedule(NUSE_NO_TASK); #endif #endif NUSE_CS_Exit(); return NUSE_SUCCESS;
Si des tâches sont suspendues (pour lecture) à partir de ce groupe d'indicateurs, elles reprennent. Lorsqu'ils ont la possibilité de poursuivre l'exécution (cela dépend de l'ordonnanceur), ils peuvent déterminer si les conditions de leur reprise sont remplies ou non (voir lecture des drapeaux d'événements).
Lecture des drapeaux d'événements
Les appels à la lecture de l'utilitaire Nucleus RTOS API sont très flexibles et vous permettent de suspendre les tâches indéfiniment ou avec un délai d'expiration spécifique si l'opération ne peut pas être terminée immédiatement (par exemple, si vous essayez de lire une séquence spécifique d'indicateurs d'événements qui ne représente pas l'état actuel). Nucleus SE offre les mêmes fonctionnalités, seule la pause de tâche est facultative et le délai d'attente n'est pas implémenté.
Défi des drapeaux dans Nucleus RTOSPrototype d'appel de service:
STATUS NU_Retrieve_Events (groupe NU_EVENT_GROUP *, UNSIGNED required_events, opération OPTION, UNSIGNED * retrieved_events, UNSIGNED suspend);Paramètres:
group - un pointeur vers un bloc de contrôle fourni par l'utilisateur pour un groupe de drapeaux d'événements;
required_events - un masque de bits qui définit les drapeaux à lire;
opération - quatre
opérations sont disponibles:
NU_AND ,
NU_AND_CONSUME ,
NU_OR et
NU_OR_CONSUME . Les opérations
NU_AND et
NU_AND_CONSUME indiquent que tous les indicateurs demandés sont requis. Les opérations
NU_OR et
NU_OR_CONSUME indiquent qu'un ou plusieurs des fanions demandés sont suffisants. Le paramètre
CONSUME efface automatiquement les indicateurs existants après une requête réussie;
retrieved_events - pointeur de stockage pour les valeurs des drapeaux d'événements lus;
suspend - spécification pour
suspendre les tâches; peut prendre les valeurs
NU_NO_SUSPEND ou
NU_SUSPEND , ou la valeur de timeout en ticks du temporisateur système (de 1 à 4 294 967 293).
Valeur de retour:
NU_SUCCESS - l'appel s'est terminé avec succès;
NU_NOT_PRESENT - l'opération spécifiée n'a pas renvoyé d'événements (pas un seul événement dans le cas de NU_OR et pas tous les événements dans le cas de NU_AND);
NU_INVALID_GROUP - pointeur non valide vers un groupe de drapeaux d'événements;
NU_INVALID_OPERATION - l'opération spécifiée était incorrecte;
NU_INVALID_POINTER - pointeur nul vers le magasin de drapeaux d'événements (NULL);
NU_INVALID_SUSPEND - tentative de pause à partir d'un thread non lié à une tâche;
NU_TIMEOUT - la combinaison requise de drapeaux d'événements n'a pas été définie même après le délai spécifié;
NU_GROUP_DELETED - le groupe d'indicateurs d'événements a été supprimé alors que la tâche était suspendue.
Défi des drapeaux dans Nucleus SECet appel d'API prend en charge la fonctionnalité principale de l'API Nucleus RTOS.
Prototype d'appel de service:
STATUS NUSE_Event_Group_Retrieve (groupe NUSE_EVENT_GROUP, U8 request_events, opération OPTION, U8 * retrieved_events, U8 suspend);Paramètres:
groupe - index (ID) du groupe lu d'indicateurs d'événement;
required_events - un masque de bits qui définit les drapeaux à lire;
opération - une spécification indiquant le nombre de drapeaux nécessaires:
NUSE OR (certains drapeaux) ou
NUSE AND (tous les drapeaux);
retrieved_events - un pointeur vers le magasin pour les valeurs réelles des drapeaux d'événements lus (avec l'opération
NUSE_AND, ce sera le même que celui transmis dans le paramètre
required_events );
suspend - spécification pour
suspendre la tâche, peut prendre les valeurs
NUSE_NO_SUSPEND ou
NUSE_SUSPEND .
Valeur de retour:
NUSE_SUCCESS - l'appel s'est terminé avec succès;
NUSE_NOT_PRESENT - l'opération spécifiée n'a pas renvoyé d'événements (pas un seul événement dans le cas de
NUSE_OR et pas tous les événements dans le cas de
NUSE_AND );
NUSE_INVALID_GROUP - index non valide d'un groupe de drapeaux d'événements;
NUSE_INVALID_OPERATION - l'opération spécifiée est différente de
NUSE_OR ou
NUSE_AND ;
NUSE_INVALID_POINTER - un pointeur nul vers le magasin de drapeaux d'événements lus (
NULL );
NUSE_INVALID_SUSPEND - une tentative de pause à partir d'un flux non-tâche ou lorsque la prise en charge du blocage des appels d'API est désactivée.
Implémentation de la lecture des drapeaux d'événements dans Nucleus SELa version du code de fonction API
NUSE_Event_Group_Retrieve () (après vérification des paramètres) est sélectionnée lors de la compilation conditionnelle selon que la prise en charge des appels API pour bloquer (suspendre) les tâches est activée ou non. Examinons ces deux options séparément.
Si le verrou est désactivé, le code complet de cet appel API ressemblera à ceci:
temp_events = NUSE_Event_Group_Data[group] & requested_events; if (operation == NUSE_OR) { if (temp_events != 0) { return_value = NUSE_SUCCESS; } else { return_value = NUSE_NOT_PRESENT; } } else /* operation == NUSE_AND */ { if (temp_events == requested_events) { return_value = NUSE_SUCCESS; } else { return_value = NUSE_NOT_PRESENT; } }
Les indicateurs d'événement requis sont sélectionnés dans le groupe d'indicateurs d'événement spécifié. La valeur est comparée aux événements requis, en tenant compte de l'opération
ET / OU , ainsi que du résultat renvoyé et des valeurs immédiates des drapeaux demandés.
Si le verrouillage des tâches est activé, le code devient plus complexe:
do { temp_events = NUSE_Event_Group_Data[group] & requested_events; if (operation == NUSE_OR) { if (temp_events != 0) { return_value = NUSE_SUCCESS; } else { return_value = NUSE_NOT_PRESENT; } } else { if (temp_events == requested_events) { return_value = NUSE_SUCCESS; } else { return_value = NUSE_NOT_PRESENT; } } if (return_value == NUSE_SUCCESS) { suspend = NUSE_NO_SUSPEND; } else { if (suspend == NUSE_SUSPEND) { NUSE_Event_Group_Blocking_Count[group]++; NUSE_Suspend_Task(NUSE_Task_Active, (group << 4) | NUSE_EVENT_SUSPEND); return_value = NUSE_Task_Blocking_Return[NUSE_Task_Active]; if (return_value != NUSE_SUCCESS) { suspend = NUSE_NO_SUSPEND; } } } } while (suspend == NUSE_SUSPEND);
Le code est placé dans une
boucle do ... while , qui fonctionne lorsque le paramètre
suspend est
NUSE_SUSPEND .
Les drapeaux d'événements demandés sont lus comme s'ils étaient appelés sans blocage. Si la lecture
échoue et que le paramètre de
suspension est
NUSE_NO_SUSPEND , l'appel d'API est défini sur
NUSE_NOT_PRESENT . Si le paramètre
suspend a été défini sur
NUSE_SUSPEND , la tâche se met en pause. Lors du retour (lorsque la tâche reprend), si la valeur de retour est
NUSE_SUCCESS , indiquant que la tâche a été reprise car les indicateurs d'événement de ce groupe ont été définis ou effacés, le cycle recommence depuis le début, les indicateurs sont lus et vérifiés. Puisqu'il n'y a pas de fonction API pour réinitialiser les groupes d'indicateurs d'événements, c'est la seule raison pour que la tâche reprenne, mais le processus de vérification
NUSE_Task_Blocking_Return [] a été laissé sur le système pour la compatibilité du contrôle de verrouillage avec d'autres types d'objets.
L'article suivant décrit les appels d'API supplémentaires associés aux groupes d'indicateurs d'événements, ainsi que leurs structures de données.
À propos de l'auteur: Colin Walls travaille dans l'industrie électronique depuis plus de trente ans, consacrant la majeure partie de son temps au micrologiciel. Il est maintenant ingénieur firmware chez Mentor Embedded (une division de Mentor Graphics). Colin Walls intervient souvent lors de conférences et séminaires, auteur de nombreux articles techniques et de deux livres sur le firmware. Vit au Royaume-Uni.
Blog professionnel
de Colin , e-mail: colin_walls@mentor.com.