Files d'attente :introduction et services de base
Voir la série RTOS Revealed
Les files d'attente ont été introduites dans un article précédent. Ils offrent un moyen plus flexible de transmettre des messages simples entre les tâches que les boîtes aux lettres.
Utilisation des files d'attente
Dans Nucleus SE, les files d'attente sont configurées au moment de la création. Il peut y avoir un maximum de 16 files d'attente configurées pour une application. Si aucune file d'attente n'est configurée, aucune structure de données ou code d'appel de service appartenant aux files d'attente n'est inclus dans l'application.
Une file d'attente est simplement un ensemble d'emplacements de stockage, chacun suffisamment grand pour contenir un seul élément de données de type ADDR , dont l'accès est contrôlé afin qu'il puisse être utilisé en toute sécurité par plusieurs tâches. Les tâches peuvent écrire dans une file d'attente à plusieurs reprises jusqu'à ce que tous les emplacements soient pleins. Les tâches peuvent être lues à partir d'une file d'attente et les données sont normalement reçues sur la base du premier entré, premier sorti (FIFO). Essayer d'envoyer à une file d'attente pleine ou de lire à partir d'une file vide peut entraîner une erreur ou une suspension de tâche, selon les options sélectionnées dans l'appel d'API et la configuration Nucleus SE.
Files d'attente et tuyaux
Nucleus SE prend également en charge les tuyaux, qui ont également été introduits dans un article précédent et sont traités en détail dans un prochain article. La principale différence entre les files d'attente et les canaux est la taille du message. Les files d'attente transportent des messages comprenant un seul ADDR – ceux-ci seraient généralement des pointeurs. Un tube transporte des messages d'un nombre arbitraire d'octets; la taille est fixée pour chaque tuyau dans l'application et définie au moment de la configuration.
Configuration des files d'attente
Nombre de files d'attente
Comme pour la plupart des aspects de Nucleus SE, la configuration des files d'attente est principalement contrôlée par #define déclarations dans nuse_config.h . Le paramètre de clé est NUSE_QUEUE_NUMBER , qui détermine le nombre de files d'attente configurées pour l'application. Le paramètre par défaut est 0 (c'est-à-dire qu'aucune file d'attente n'est utilisée) et vous pouvez le définir sur n'importe quelle valeur jusqu'à 16. Une valeur erronée entraînera une erreur de temps de compilation, qui est générée par un test dans nuse_config_check.h (ceci est inclus dans nuse_config.c et donc compilé avec ce module) résultant en une #error déclaration en cours de compilation.
Le choix d'une valeur différente de zéro est la « validation principale » pour les files d'attente. Il en résulte que certaines structures de données sont définies et dimensionnées en conséquence, dont plus dans le prochain article. Il active également les paramètres d'activation de l'API.
Activation de l'API
Chaque fonction API (appel de service) dans Nucleus SE a un #define d'activation symbole dans nuse_config.h . Pour les files d'attente, ce sont :
NUSE_QUEUE_SEND
NUSE_QUEUE_RECEIVE
NUSE_QUEUE_JAM
NUSE_QUEUE_RESET
NUSE_QUEUE_INFORMATION
NUSE_QUEUE_COUNT
Par défaut, tous ces éléments sont définis sur FALSE , désactivant ainsi chaque appel de service et empêchant l'inclusion de tout code d'implémentation. Pour configurer des files d'attente pour une application, vous devez sélectionner les appels d'API que vous souhaitez utiliser et définir leurs symboles d'activation sur TRUE .
Voici un extrait du fichier nuse_config.h par défaut.
#define NUSE_QUEUE_NUMBER 0 /* Nombre de files d'attente dans le
système - 0-16 * /
/ * habilitants appels de service * / define
NUSE_QUEUE_SEND FAUX FAUX #define NUSE_QUEUE_RECEIVE
#define NUSE_QUEUE_JAM FAUX
#define NUSE_QUEUE_RESET FALSE
#define NUSE_QUEUE_INFORMATION FALSE
#define NUSE_QUEUE_COUNT FALSE
Une erreur de compilation se produira si une fonction API de file d'attente est activée et qu'aucune file d'attente n'est configurée (sauf pour NUSE_Queue_Count() ce qui est toujours autorisé). Si votre code utilise un appel API, qui n'a pas été activé, une erreur de temps de liaison se produira, car aucun code d'implémentation n'aura été inclus dans l'application.
File d'attente d'appels
Nucleus RTOS prend en charge dix appels de service qui appartiennent aux files d'attente, qui fournissent les fonctionnalités suivantes :
Envoyer un message à une file d'attente. Implémenté par NUSE_Queue_Send() dans Nucleus SE.
Recevoir un message d'une file d'attente. Implémenté par NUSE_Queue_Receive() dans Nucleus SE.
Envoyer un message au début d'une file d'attente. Implémenté par NUSE_Queue_Jam() dans Nucleus SE.
Restaurer une file d'attente à l'état inutilisé, sans aucune tâche suspendue (réinitialisation). Implémenté par NUSE_Queue_Reset() dans Nucleus SE.
Fournir des informations sur une file d'attente spécifiée. Implémenté par NUSE_Queue_Information() dans Nucleus SE.
Renvoyer le nombre de files d'attente (actuellement) configurées pour l'application. Implémenté par NUSE_Queue_Count() dans Nucleus SE.
Ajouter une nouvelle file d'attente à l'application (créer). Non implémenté dans Nucleus SE.
Supprimer une file d'attente de l'application (supprimer). Non implémenté dans Nucleus SE.
Renvoyer des pointeurs vers toutes les files d'attente (actuellement) dans l'application. Non implémenté dans Nucleus SE.
Envoyer un message à toutes les tâches suspendues dans une file d'attente (diffusion). Non implémenté dans Nucleus SE.
La mise en œuvre de chacun de ces appels de service est examinée en détail.
Services d'écriture et de lecture de file d'attente
Les opérations fondamentales, qui peuvent être effectuées sur une file d'attente, consistent à y écrire des données - ce qui est parfois appelé envoi – et en lire les données – ce qui est également appelé réception . Il est également possible d'écrire des données au début d'une file d'attente - ce qui est également appelé brouillage . Nucleus RTOS et Nucleus SE fournissent chacun trois appels d'API de base pour ces opérations, qui seront abordés ici.
Écrire dans une file d'attente
L'appel de l'API Nucleus RTOS pour l'écriture dans une file d'attente est très flexible, vous permettant de suspendre indéfiniment, ou avec un délai d'attente, si l'opération ne peut pas être terminée immédiatement ; c'est-à-dire que vous essayez d'écrire dans une file d'attente pleine. Nucleus SE fournit le même service, sauf que la suspension des tâches est facultative et que le délai d'expiration n'est pas implémenté.
Nucleus RTOS offre également une fonction de diffusion vers une file d'attente, mais cela n'est pas pris en charge par Nucleus SE. Il est décrit sous API non implémentées dans l'article suivant.
Appel d'API Nucleus RTOS pour l'envoi à une file d'attente
Prototype d'appel de service :
STATUS NU_Send_To_Queue(NU_QUEUE *file d'attente, VOID *message,
NON-SIGNÉ taille, NON-SIGNÉ suspension );
Paramètres :
file d'attente – pointeur vers le bloc de contrôle de file d'attente fourni par l'utilisateur
message – un pointeur vers le message à envoyer
taille – le nombre de UNSIGNÉ éléments de données dans le message. Si la file d'attente prend en charge les messages de longueur variable, ce paramètre doit être inférieur ou égal à la taille de message prise en charge par la file d'attente. Si la file d'attente prend en charge les messages de taille fixe, ce paramètre doit être exactement le même que la taille de message prise en charge par la file d'attente.
suspend – spécification pour la suspension de la tâche; peut être NU_NO_SUSPEND ou NU_SUSPEND ou une valeur de délai d'attente
Retours :
NU_SUCCESS – l'appel s'est terminé avec succès
NU_INVALID_QUEUE – le pointeur de file d'attente est invalide
NU_INVALID_POINTER – le pointeur de message est NULL
NU_INVALID_SIZE – la taille du message est incompatible avec la taille du message supportée par la file d'attente
NU_INVALID_SUSPEND – la suspension a été tentée à partir d'un thread sans tâche
NU_QUEUE_FULL – la file d'attente est pleine et la suspension n'a pas été spécifiée
NU_TIMEOUT – la file d'attente est toujours pleine même après une suspension pour la valeur de délai d'attente spécifiée
NU_QUEUE_DELETED – la file d'attente a été supprimée alors que la tâche était suspendue
NU_QUEUE_RESET – la file d'attente a été réinitialisée alors que la tâche était suspendue
Appel API Nucleus SE pour l'envoi à une file d'attente
Cet appel d'API prend en charge la fonctionnalité clé de l'API Nucleus RTOS.
Prototype d'appel de service :
STATUS NUSE_Queue_Send(file d'attente NUSE_QUEUE, ADDR *message,
U8 suspend);
Paramètres :
file d'attente – l'index (ID) de la file d'attente à utiliser
message – un pointeur vers le message à envoyer, qui est une variable unique de type ADDR
suspend – spécification pour la suspension de la tâche; peut être NUSE_NO_SUSPEND ou NUSE_SUSPEND
Retours :
NUSE_SUCCESS – l'appel s'est terminé avec succès
NUSE_INVALID_QUEUE – l'index de la file d'attente n'est pas valide
NUSE_INVALID_POINTER – le pointeur de message est NULL
NUSE_INVALID_SUSPEND – la suspension a été tentée à partir d'un thread sans tâche ou lorsque le blocage des appels d'API n'était pas activé
NUSE_QUEUE_FULL – la file d'attente est pleine et la suspension n'a pas été spécifiée
NUSE_QUEUE_WAS_RESET – la file d'attente a été réinitialisée alors que la tâche était suspendue
Implémentation Nucleus SE de la file d'attente ASend
La majeure partie du code du NUSE_Queue_Send() La fonction API - après vérification des paramètres - est sélectionnée par compilation conditionnelle, selon que la prise en charge du blocage (suspension des tâches) des appels API est activée. Nous allons examiner les deux variantes séparément ici.
Si le blocage n'est pas activé, le code de cet appel API est assez simple :
if (NUSE_Queue_Items[queue] ==NUSE_Queue_Size[queue]) /* file d'attente pleine */{ return_value =NUSE_QUEUE_FULL;}else /* élément de file d'attente disponible */{ NUSE_Queue_Data[queue][NUSE_Queue_Head[queue]++] =*message; if (NUSE_Queue_Head[queue] ==NUSE_Queue_Size[queue]) { NUSE_Queue_Head[queue] =0; } NUSE_Queue_Items[file d'attente]++ ; return_value =NUSE_SUCCESS;}
La fonction vérifie simplement qu'il y a de la place dans la file d'attente et utilise le NUSE_Queue_Head[] index pour stocker le message dans la zone de données de la file d'attente.
Lorsque le blocage est activé, le code devient plus complexe :
do{ if (NUSE_Queue_Items[queue] ==NUSE_Queue_Size[queue]) /* file d'attente pleine */ { if (suspend ==NUSE_NO_SUSPEND) { return_value =NUSE_QUEUE_FULL; } else { /* bloquer la tâche */ NUSE_Queue_Blocking_Count[queue]++; NUSE_Suspend_Task(NUSE_Task_Active, (file d'attente <<4) | NUSE_QUEUE_SUSPEND); return_value =NUSE_Task_Blocking_Return[NUSE_Task_Active] ; if (valeur_retour !=NUSE_SUCCESS) { suspend =NUSE_NO_SUSPEND; } } } else { /* élément de file d'attente disponible */ NUSE_Queue_Data[queue][NUSE_Queue_Head[queue]++] =*message; if (NUSE_Queue_Head[queue] ==NUSE_Queue_Size[queue]) { NUSE_Queue_Head[queue] =0; } NUSE_Queue_Items[file d'attente]++ ; if (NUSE_Queue_Blocking_Count[file d'attente] !=0) { indice U8 ; /* vérifie si une tâche est bloquée sur cette file d'attente */ NUSE_Queue_Blocking_Count[queue]--; for (index=0; indexQuelques explications du code peuvent être utiles :
Le code est entouré d'un do…while boucle, qui continue tant que le paramètre suspend a la valeur NUSE_SUSPEND .
Si la file d'attente est pleine et suspendez est défini sur NUSE_NO_SUSPEND , l'appel d'API se termine avec NUSE_QUEUE_FULL . Si la suspension a été définie sur NUSE_SUSPEND , la tâche est suspendue. Au retour (c'est-à-dire au réveil de la tâche), si la valeur de retour est NUSE_SUCCESS , indiquant que la tâche a été réveillée parce qu'un message a été lu (par opposition à une réinitialisation de la file d'attente), le code revient en haut.
Si la file d'attente n'est pas pleine, le message fourni est stocké à l'aide de NUSE_Queue_Head[] index pour stocker le message dans la zone de données de la file d'attente. Une vérification est effectuée pour savoir si des tâches sont suspendues (en attente de réception) dans la file d'attente. S'il y a des tâches en attente, la première est réveillée. Le suspendre la variable est définie sur NUSE_NO_SUSPEND et l'appel d'API se termine avec NUSE_SUCCESS .
La plate-forme open source cible l'IoT avec Linux intégré Pilotes de périphérique Linux intégrés :écriture d'un pilote de périphérique de noyau
Embarqué
- Une introduction aux serrures à came et à leur fonctionnement
- Une introduction aux vis à œil et à leur fonctionnement
- Une introduction aux œillets et à leur fonctionnement
- Une introduction à l'acier inoxydable et à sa fabrication
- Entrée et sortie de base C#
- Boîtes aux lettres :présentation et services de base
- Sémaphores :services utilitaires et structures de données
- Sémaphores :introduction et services de base
- Groupes d'indicateurs d'événement :services publics et structures de données