
Cet article poursuit l'examen des boîtes aux lettres qui a commencé dans l'article précédent de la série «La vérité sur RTOS».
Articles précédents de la série:
Article # 21. Boîtes aux lettres: introduction et services de baseArticle # 20. Sémaphores: services auxiliaires et structures de donnéesArticle # 19. Sémaphores: introduction et services de baseArticle # 18. Groupes d'indicateurs d'événements: services d'assistance et structures de donnéesArticle # 17. Groupes de drapeaux d'événements: introduction et services de baseArticle # 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.
Services auxiliaires de boîtes aux lettres
Nucleus RTOS dispose de quatre appels d'API qui fournissent des fonctions auxiliaires liées aux boîtes aux lettres: vidage d'une boîte aux lettres, récupération d'informations sur une boîte aux lettres, récupération du nombre de boîtes aux lettres dans une application et récupération de pointeurs vers toutes les boîtes aux lettres d'une application. Les trois premières de ces fonctionnalités sont implémentées dans Nucleus SE.
Réinitialisation de la boîte aux lettres
Cet appel de service API réinitialise la boîte aux lettres à son état initial non utilisé. Le message stocké dans la boîte aux lettres sera perdu. Toutes les tâches suspendues sur la boîte aux lettres reprendront avec le code retour
NUSE_MAILBOX_WAS_RESET .
Appel pour réinitialiser une boîte aux lettres dans Nucleus RTOSPrototype d'appel de service:
STATUS NU_Reset_Mailbox (boîte aux lettres NU_MAILBOX *);Paramètres:
boîte aux lettres - un pointeur vers l'unité de contrôle de boîte aux lettres.
Valeur de retour:
NU_SUCCESS - l'appel s'est terminé avec succès;
NU_INVALID_MAILBOX - pointeur de boîte aux lettres non valide.
Appel pour réinitialiser une boîte aux lettres dans Nucleus SECet appel de service d'API prend en charge la fonctionnalité de base de l'API Nucleus RTOS.
Prototype d'appel de service:
STATUS NUSE_Mailbox_Reset (boîte aux lettres NUSE_MAILBOX);Paramètres:
boîte aux lettres - index (ID) de la boîte aux lettres vidée.
Valeur de retour:NUSE_SUCCESS - l'appel s'est terminé avec succès;
NUSE_INVALID_MAILBOX - index de boîte aux lettres non valide.
Implémenter la réinitialisation de la boîte aux lettres dans Nucleus SELe code d'option pour la fonction
NUSE_Mailbox_Reset (après vérification des paramètres) est sélectionné à l'aide de la compilation conditionnelle, selon que la prise en charge des tâches de blocage (pause) est activée ou non. Nous considérerons ces deux options.
Si le verrou n'est pas activé, le code de cette fonction API est assez simple. La boîte aux lettres est marquée comme inutilisée en définissant le paramètre
NUSE_Mailbox_Status [] sur
FALSE .
Si le verrou est activé, le code devient plus complexe:
while (NUSE_Mailbox_Blocking_Count[mailbox] != 0) { U8 index; /* check whether any tasks are blocked */ /* on this mailbox */ for (index=0; index<NUSE_TASK_NUMBER; index++) { if ((LONIB(NUSE_Task_Status[index]) == NUSE_MAILBOX_SUSPEND) && (HINIB(NUSE_Task_Status[index]) == mailbox)) { NUSE_Task_Blocking_Return[index] = NUSE_MAILBOX_WAS_RESET; NUSE_Task_Status[index] = NUSE_READY; break; } } NUSE_Mailbox_Blocking_Count[mailbox]--; } #if NUSE_SCHEDULER_TYPE == NUSE_PRIORITY_SCHEDULER NUSE_Reschedule(NUSE_NO_TASK); #endif
La boîte aux lettres est réinitialisée à l'état «Vide».
Chaque tâche suspendue dans la boîte aux lettres se voit attribuer le statut «Prêt» avec le code retour
NUSE_MAILBOX_WAS_RESET . Une fois ce processus terminé, si le planificateur de priorité est utilisé, l'appel de service
NUSE_Reschedule () est
effectué , car une ou plusieurs tâches avec une priorité plus élevée peuvent devenir prêtes et attendre la permission de s'exécuter.
Récupération des informations de boîte aux lettres
Cet appel de service fournit un ensemble d'informations sur la boîte aux lettres. L'implémentation de cet appel dans Nucleus SE diffère de Nucleus RTOS en ce qu'il renvoie moins d'informations, car la dénomination des objets et l'ordre de pause ne sont pas pris en charge et la pause de tâche peut être désactivée.
Appelez pour obtenir des informations sur la boîte aux lettres Nucleus RTOSCet appel d'API prend en charge la fonctionnalité principale de l'API Nucleus RTOS.
Prototype d'appel de service:
STATUS NU_Mailbox_Information (boîte aux lettres NU_MAILBOX *, nom CHAR *, OPTION * suspend_type, DATA_ELEMENT * message_present, UNSIGNED * tasks_waiting, NU_TASK ** first_task);Paramètres:
boîte aux lettres - pointeur vers l'unité de commande de boîte aux lettres;
nom - un pointeur de 8 caractères sur le nom de la boîte aux lettres. L'octet nul de fin est également inclus dans cette zone;
suspend_type - pointeur sur la variable dans laquelle le type de suspension de la tâche est stocké. Il peut prendre les valeurs
NU_FIFO et
NU_PRIORITY ;
message_present - un pointeur vers une variable qui prendra la valeur
NU_TRUE ou
NU_FALSE , selon que la boîte aux lettres est pleine ou non;
tasks_waiting - un pointeur sur une variable qui prendra le nombre de tâches suspendues sur cette boîte aux lettres;
first_task - un pointeur vers un pointeur de tâche qui prendra un pointeur vers la première tâche suspendue.
Valeur de retour:
NU_SUCCESS - l'appel s'est terminé avec succès;
NU_INVALID_MAILBOX - pointeur de boîte aux lettres non valide.
Appelez pour obtenir des informations sur la boîte aux lettres Nucleus SECet appel de service d'API prend en charge la fonctionnalité de base de l'API Nucleus RTOS.
Prototype d'appel de service:
STATUS NUSE_Mailbox_Information (boîte aux lettres NUSE_MAILBOX, U8 * message_present, U8 * tasks_waiting, NUSE_TASK * first_task);Paramètres:
boîte aux lettres - index de la boîte aux lettres pour laquelle des informations sont demandées;
message_present - un pointeur vers une variable qui prend la valeur
TRUE ou
FALSE , selon que la boîte aux lettres est pleine ou non;
tasks_waiting - un pointeur sur une variable qui prendra le nombre de tâches suspendues sur cette boîte aux lettres (rien n'est retourné si la suspension des tâches est désactivée);
first_task - un pointeur vers une variable de type
NUSE_TASK , qui prendra l'index de la première tâche suspendue (rien n'est retourné si la suspension de la tâche est désactivée).
Valeur de retour:
NUSE_SUCCESS - l'appel s'est terminé avec succès;
NUSE_INVALID_MAILBOX - index de boîte aux lettres non valide;
NUSE_INVALID_POINTER - un ou plusieurs paramètres de pointeur sont incorrects.
Implémentation des informations de boîte aux lettres dans Nucleus SEL'implémentation de cet appel API est assez simple:
*message_present = NUSE_Mailbox_Status[mailbox]; #if NUSE_BLOCKING_ENABLE *tasks_waiting = NUSE_Mailbox_Blocking_Count[mailbox]; if (NUSE_Mailbox_Blocking_Count[mailbox] != 0) { U8 index; for (index=0; index<NUSE_TASK_NUMBER; index++) { if ((LONIB(NUSE_Task_Status[index]) == NUSE_MAILBOX_SUSPEND) && (HINIB(NUSE_Task_Status[index]) == mailbox)) { *first_task = index; break; } } } else { *first_task = 0; } #else *tasks_waiting = 0; *first_task = 0; #endif return NUSE_SUCCESS;
La fonction renvoie l'état de la boîte aux lettres. Ensuite, si des appels de service pour bloquer des tâches sont activés, le nombre de tâches suspendues et l'index de la première sont renvoyés (sinon, ces paramètres sont définis sur 0).
Obtenir le nombre de boîtes aux lettres
Cet appel d'utilitaire renvoie le nombre de boîtes aux lettres dans l'application. Alors que dans Nucleus RTOS, leur nombre peut changer au fil du temps, et la valeur de retour montrera le nombre actuel de boîtes aux lettres, dans Nucleus SE, le nombre de boîtes aux lettres est défini au stade de la construction et ne peut pas être modifié.
Appel d'un compteur de boîtes aux lettres dans Nucleus RTOSCet appel d'API prend en charge la fonctionnalité principale de l'API Nucleus RTOS.
Prototype d'appel de service:
UNSIGNED NU_Established_Mailboxes (VOID);Paramètres:
Sont absents.
Valeur de retour:
Le nombre de boîtes aux lettres créées dans l'application.
Appel d'un compteur de boîtes aux lettres dans Nucleus SECet appel d'API prend en charge la fonctionnalité principale de l'API Nucleus RTOS.
Prototype d'appel de service:
U8 NUSE_Mailbox_Count (void);Paramètres:
Sont absents.
Valeur de retour:
Nombre de boîtes aux lettres configurées dans l'application.
Implémentation d'un compteur de boîtes aux lettres dans Nucleus SEL'implémentation de cet appel API est extrêmement simple: la valeur de la directive
#define NUSE_MAILBOX_NUMBER est
retournée .
Structures de données
Les boîtes aux lettres utilisent deux ou trois tableaux de structures de données (toutes situées dans la RAM), qui, comme les autres objets Nucleus SE, sont un ensemble de tables dont la taille dépend du nombre de boîtes aux lettres configurées et de leurs paramètres.
Je recommande fortement que le code d'application n'utilise pas un accès direct à ces structures de données, mais s'y réfère via les fonctions API fournies. Cela évite l'incompatibilité avec les futures versions de Nucleus SE et les effets secondaires indésirables, et simplifie également le portage de l'application vers Nucleus RTOS. Ce qui suit est un aperçu détaillé des structures de données pour une meilleure compréhension du fonctionnement du code d'appel de service et pour le débogage.
Données RAM
Ces données ont la structure suivante:
NUSE_Mailbox_Data [] - un tableau de type
ADDR , qui a une entrée pour chaque boîte aux lettres configurée, il stocke les données de boîte aux lettres.
NUSE_Mailbox_Status [] est un tableau
U8 qui a une entrée pour chaque boîte aux lettres configurée, il surveille l'utilisation des boîtes aux lettres. Une valeur non nulle (
TRUE ) indique que la boîte aux lettres est pleine.
NUSE_Mailbox_Blocking_Count [] - un tableau de type
U8 , il contient un compteur de tâches bloquées pour chaque boîte aux lettres. Ce tableau est créé uniquement si la fonctionnalité de blocage d'appels API est activée.
Ces structures de données sont initialisées avec des zéros dans la fonction
NUSE_Init_Mailbox () au démarrage de Nucleus SE. C'est logique, car chaque boîte aux lettres est créée vide (inutilisée).
Voici les définitions de ces structures de données du fichier
nuse_init.c .
RAM ADDR NUSE_Mailbox_Data[NUSE_MAILBOX_NUMBER]; RAM U8 NUSE_Mailbox_Status[NUSE_MAILBOX_NUMBER]; #if NUSE_BLOCKING_ENABLE RAM U8 NUSE_Mailbox_Blocking_Count[NUSE_MAILBOX_NUMBER]; #endif
Données ROM
Pour l'implémentation des boîtes aux lettres, les données en ROM ne sont pas utilisées.
La quantité de mémoire pour les boîtes aux lettres
Comme pour tous les objets du noyau Nucleus SE, la quantité de mémoire requise pour les boîtes aux lettres est connue à l'avance.
La quantité de mémoire pour les données dans la ROM pour toutes les boîtes aux lettres de l'application est de 0.
La quantité de données dans la RAM pour toutes les boîtes aux lettres de l'application (en octets) avec des appels d'API activés pour bloquer les tâches peut être calculée comme suit:
NUSE_MAILBOX_NUMBER * (taille de (ADDR) +2)Sinon:
NUSE_MAILBOX_NUMBER * (taille de (ADDR) +1)Appels d'API non réalisés
Les quatre appels d'utilitaires disponibles dans Nucleus RTOS ne sont pas implémentés dans Nucleus SE.
Créer une boîte aux lettres
Cet appel de service API crée une boîte aux lettres. Nucleus SE n'en a pas besoin, car les boîtes aux lettres sont créées statiquement.
Prototype d'appel de service:
STATUS NU_Create_Mailbox (boîte aux lettres NU_MAILBOX *, nom CHAR *, UNSIGNED OPTION suspend_type);Paramètres:
boîte aux lettres - un pointeur vers l'unité de commande de boîte aux lettres fourni par l'utilisateur; Utilisé pour gérer les boîtes aux lettres dans d'autres appels d'API
nom - pointeur vers le
nom à 7 caractères de la boîte aux lettres avec zéro octet de fin;
suspend_type - Indique le principe de la suspension d'une tâche sur une boîte aux lettres. Il peut prendre les valeurs
NU_FIFO et
NU_PRIORITY , qui désignent respectivement le principe de FIFO (First-In-First-Out) ou le principe de priorité de suspension des tâches.
Valeur de retour:
NU_SUCCESS - l'appel s'est terminé avec succès;
NU_INVALID_MAILBOX - pointeur nul vers l'unité de contrôle de boîte aux lettres (
NULL ), ou le pointeur est déjà utilisé;
NU_INVALID_SUSPEND - paramètre
suspend_type non
valide .
Supprimer une boîte aux lettres
Cet appel de service API supprime une boîte aux lettres créée précédemment. Nucleus SE n'en a pas besoin, car les boîtes aux lettres sont créées statiquement et ne peuvent pas être supprimées.
Prototype d'appel de service:
STATUS NU_Delete_Mailbox (boîte aux lettres NU_MAILBOX *);Paramètres:
boîte aux lettres - un pointeur vers l'unité de contrôle de boîte aux lettres.
Valeur de retour:
NU_SUCCESS - l'appel s'est terminé avec succès;
NU_INVALID_MAILBOX - pointeur de boîte aux lettres non valide.
Pointeurs de boîte aux lettres
Cet appel d'API constitue une liste séquentielle de pointeurs vers toutes les boîtes aux lettres du système. Nucleus SE n'en a pas besoin, car les boîtes aux lettres sont identifiées par un simple index, et non par un pointeur.
Prototype d'appel de service:
UNSIGNED NU_Mailbox_Pointers (NU_MAILBOX ** pointer_list, UNSIGNED maximum_pointers);Paramètres:
pointer_list - pointeur vers un tableau de pointeurs
NU_MAILBOX ; ce tableau sera rempli de pointeurs vers des boîtes aux lettres créées dans le système;
maximum_pointers - le nombre maximum de pointeurs dans le tableau.
Valeur de retour:
Nombre de pointeurs
NU_MAILBOX dans le tableau.
Enregistrer un message dans la boîte aux lettres pour distribution à tous les destinataires
Cet appel de service envoie un message à toutes les tâches qui attendent des messages d'une boîte aux lettres spécifique. Dans Nucleus SE, cet appel d'utilitaire n'est pas implémenté, car il ajouterait une complexité inutile.
Prototype d'appel de service:
STATUS NU_Broadcast_To_Mailbox (boîte aux lettres NU_MAILBOX *, message VOID *, suspension UNSIGNED);Paramètres:
boîte aux lettres - pointeur vers l'unité de commande de boîte aux lettres;
message - pointeur vers le message transmis;
suspend - indique s'il faut suspendre la tâche d'appel si la boîte aux lettres contient déjà un message; peut être
NU_NO_SUSPEND ,
NU_SUSPEND ou une valeur de délai d'expiration.
Valeur de retour:
NU_SUCCESS - l'appel s'est terminé avec succès;
NU_INVALID_MAILBOX - pointeur de boîte aux lettres non valide;
NU_INVALID_POINTER - pointeur nul vers un message (
NULL );
NU_INVALID_SUSPEND - tentative de suspension à partir d'un thread non lié à une tâche;
NU_MAILBOX_FULL - la boîte aux lettres contient déjà un message;
NU_TIMEOUT - une fois le délai expiré, la boîte aux lettres est toujours pleine;
NU_MAILBOX_DELETED - La boîte aux lettres a été supprimée lors de la suspension de la tâche.
NU_MAILBOX_RESET - la boîte aux lettres a été réinitialisée alors que la tâche a été suspendue.
Compatible avec Nucleus RTOS
Comme pour tous les autres objets Nucleus SE, mon objectif était de maximiser la compatibilité du code d'application avec Nucleus RTOS. Les boîtes aux lettres ne font pas exception et, du point de vue de l'utilisateur, elles sont implémentées de la même manière que dans Nucleus RTOS. Il y a aussi une certaine incompatibilité, que j'ai jugée acceptable étant donné qu'en conséquence, le code deviendra plus compréhensible et plus efficace en termes de quantité de mémoire requise. Sinon, les appels d'API Nucleus RTOS peuvent être directement portés vers Nucleus SE.
Identificateurs d'objet
Dans Nucleus RTOS, tous les objets sont décrits par des structures de données (unités de contrôle) d'un type spécifique. Un pointeur vers cette unité de contrôle sert d’identifiant à la boîte aux lettres. J'ai décidé que dans Nucleus SE, une approche différente est nécessaire pour une utilisation efficace de la mémoire: tous les objets du noyau sont décrits par un ensemble de tables en RAM et / ou ROM. La taille de ces tables est déterminée par le nombre d'objets configurés de chaque type. L'identifiant d'un objet particulier est l'index dans ce tableau. J'ai donc défini
NUSE_MAILBOX comme l'équivalent de
U8 , une variable (pas un pointeur) de ce type sert d'identifiant de la boîte aux lettres. Cette légère incompatibilité est facile à gérer si le code est porté de Nucleus SE vers Nucleus RTOS et vice versa. En règle générale, aucune opération n'est effectuée sur les identificateurs d'objet autres que le déplacement et le stockage.
Nucleus RTOS prend également en charge la dénomination des boîtes aux lettres. Ces noms sont utilisés uniquement pour le débogage. Je les ai exclus de Nucleus SE pour économiser de la mémoire.
Taille et type du message
Dans Nucleus RTOS, un message de boîte aux lettres se compose de quatre mots de 32 bits. Dans Nucleus SE, j'ai décidé de réduire cette valeur à une variable de type
ADDR . Cette modification entraîne des économies de mémoire importantes et un temps d'exécution des tâches réduit. Il suggère également que l'utilisation habituelle d'une boîte aux lettres consiste à transmettre des informations d'une tâche à une autre. Cette incompatibilité ne causera pas de gros problèmes lors du portage d'applications vers Nucleus RTOS. Nucleus SE peut être modifié si un format de message différent est nécessaire.
Appels d'API non réalisés
Nucleus RTOS prend en charge neuf appels de bureau de boîte aux lettres. Parmi ceux-ci, quatre ne sont pas implémentés dans Nucleus SE. Les détails de ces défis, ainsi que les raisons pour lesquelles ils ont été exclus de Nucleus SE, sont décrits ci-dessus.
Le prochain article examinera les files d'attente.
À 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.