Toute la vérité sur RTOS. Article # 25. Canaux de données: introduction et services de base



Après une courte pause, nous continuons à publier les traductions de The Whole Truth About RTOS de Colin Walls. Cette fois, nous parlerons des canaux de transmission de données (ci-après dénommés canaux), qui étaient déjà mentionnés dans l'un des articles précédents, à savoir dans le n ° 5 . Les canaux, par rapport aux boîtes aux lettres ( # 21 et # 22 ) ou aux files d'attente ( # 23 et # 24 ), offrent un moyen plus flexible de transférer des messages simples entre les tâches.

Articles précédents de la série:

Article # 24. Files d'attente: services auxiliaires et structures de données
Article # 23. Files d'attente: introduction et services de base
Article # 22. Boîtes aux lettres: services auxiliaires et structures de données
Article # 21. Boîtes aux lettres: introduction et services de base
Article # 20. Sémaphores: services auxiliaires et structures de données
Article # 19. Sémaphores: introduction et services de base
Article # 18. Groupes d'indicateurs d'événements: services d'assistance et structures de données
Article # 17. Groupes de drapeaux d'événements: introduction et services de base
Article # 16. Signaux
Article # 15. Partitions de mémoire: services et structures de données
Article # 14. Sections de mémoire: introduction et services de base
Article # 13. Structures de données de tâche et appels d'API non pris en charge
Article # 12. Services pour travailler avec des tâches
Article # 11. Tâches: configuration et introduction à l'API
Article # 10. Scheduler: fonctionnalités avancées et préservation du contexte
Article # 9. Scheduler: implémentation
Article # 8. Nucleus SE: conception interne et déploiement
Article # 7. Nucleus SE: Introduction
Article # 6. Autres services RTOS
Article # 5. Interaction et synchronisation des tâches
Article # 4. Tâches, changement de contexte et interruptions
Article # 3. Tâches et planification
Article # 2. RTOS: Structure et mode temps réel
Article # 1. RTOS: introduction.

Utilisation de canaux


Dans Nucleus SE, les canaux sont identifiés pendant la phase d'assemblage. Chaque application peut avoir jusqu'à 16 canaux. Si aucun canal n'est configuré dans l'application, ni les structures de données ni les codes d'appel de service relatifs aux canaux ne seront inclus dans l'application.

Canal de transmission de données - un ensemble de stockages, dont la taille vous permet de placer un élément de données d'une longueur spécifiée par l'utilisateur en octets. L'accès aux données est contrôlé de manière à ce que plusieurs tâches puissent les utiliser en toute sécurité. Les tâches peuvent écrire des données sur le canal jusqu'à ce que toutes les zones soient pleines. Les tâches peuvent lire les données du canal et les données sont reçues selon le principe FIFO. Tenter d'écrire sur un canal saturé ou de lire sur un canal vide peut entraîner une erreur ou une suspension de tâche, selon les paramètres d'appel API sélectionnés et la configuration de Nucleus SE.

Canaux et files d'attente


Nucleus SE prend également en charge les files d'attente qui ont été discutées en détail dans les articles précédents (# 23 et # 24). La principale différence entre les canaux et les files d'attente est la taille du message. Les files d'attente contiennent des messages constitués d'une seule variable de type ADDR, généralement des pointeurs. Le canal contient des messages de taille arbitraire, individuels pour chaque canal de l'application et attribués lors du paramétrage.

Configuration des canaux


Nombre de canaux


Comme pour la plupart des objets Nucleus SE, la personnalisation des canaux est contrôlée par les directives #define dans nuse_config.h . Le paramètre principal est NUSE_PIPE_NUMBER , qui détermine le nombre de canaux configurés dans l'application. Par défaut, cette valeur est zéro (c'est-à-dire qu'il n'y a pas de canaux dans l'application) et peut prendre des valeurs jusqu'à 16. Une valeur incorrecte entraînera une erreur de compilation, qui sera générée en archivant le fichier nuse_config_check.h (ce fichier est inclus dans nuse_config.c et compile avec elle), ce qui déclenchera la directive #error .

La sélection d'une valeur différente de zéro sert d'activateur principal des canaux. Ce paramètre est utilisé pour déterminer les structures de données et leur taille dépend de sa valeur (plus à ce sujet dans l'article suivant). 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 a une directive d'activation #define dans nuse_config.h . Pour les canaux, ces symboles sont:

NUSE_PIPE_SEND
NUSE_PIPE_RECEIVE
NUSE_PIPE_JAM
NUSE_PIPE_RESET
NUSE_PIPE_INFORMATION
NUSE_PIPE_COUNT

Par défaut, ils sont définis sur FALSE , donc tous les appels de service sont désactivés, bloquant l'inclusion de code qui les implémente. Pour configurer les canaux dans l'application, vous devez sélectionner les appels de service API nécessaires et les définir sur TRUE .

Voici un extrait de code du fichier nuse_config.h par défaut.

#define NUSE_PIPE_NUMBER 0 /* Number of pipes in the system - 0-16 */ /* Service call enablers */ #define NUSE_PIPE_SEND FALSE #define NUSE_PIPE_RECEIVE FALSE #define NUSE_PIPE_JAM FALSE #define NUSE_PIPE_RESET FALSE #define NUSE_PIPE_INFORMATION FALSE #define NUSE_PIPE_COUNT FALSE 

Si les fonctions API sont activées, mais qu'il n'y a pas de canaux dans l'application (à l'exception de NUSE_Pipe_Count () , qui est toujours activé), une erreur de compilation se produit. 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 sur le canal aérien


Nucleus RTOS prend en charge les frais généraux de dix canaux qui offrent les fonctionnalités suivantes:

  • Envoi d'un message à la chaîne. Nucleus SE est implémenté dans la fonction NUSE_Pipe_Send () .
  • Recevez des messages de la chaîne. Nucleus SE est implémenté dans la fonction NUSE_Pipe_Receive () .
  • Envoyez un message en haut de la chaîne. Nucleus SE est implémenté dans NUSE_Pipe_Jam () .
  • Restauration du canal à un état inutilisé avec la libération de toutes les tâches suspendues (réinitialisation). Dans Nucleus SE, implémenté dans NUSE_Pipe_Reset () .
  • Obtenir des informations sur une chaîne spécifique. Nucleus SE est implémenté à l'aide de NUSE_Pipe_Information () .
  • Renvoie le compteur des canaux actuellement configurés dans l'application. Nucleus SE est implémenté à l'aide de NUSE_Pipe_Count () .
  • Ajout d'un nouveau canal à l'application (création). Non implémenté dans Nucleus SE.
  • Suppression d'un canal d'une application. Non implémenté dans Nucleus SE.
  • Renvoyez des pointeurs vers tous les canaux de l'application. Non implémenté dans Nucleus SE.
  • Envoi d'un message à toutes les tâches suspendues sur la chaîne (diffusion). Non implémenté dans Nucleus SE.

Considérez la mise en œuvre de chacun de ces appels de service plus en détail.

Appels de service pour écrire et lire sur les canaux


Les opérations de base qui sont effectuées sur les canaux sont l'enregistrement (également appelé envoi) et la lecture (également appelée réception de messages). De plus, il est possible d'enregistrer des données au début du canal (brouillage). Nucleus RTOS et Nucleus SE fournissent trois appels d'API principaux pour ces opérations, qui seront discutés ci-dessous.

Enregistrement de chaîne


L'appel de l'utilitaire Nucleus RTOS API pour écrire sur le canal est très flexible, ce qui vous permet de suspendre les tâches implicitement ou avec un délai d'expiration si l'opération ne peut pas être terminée immédiatement (par exemple, lorsque vous essayez d'écrire sur un canal saturé). Nucleus SE a un défi similaire, mais la pause de tâche est facultative et un délai d'attente n'est pas implémenté.

Nucleus RTOS fournit également un service de diffusion de chaînes, mais n'est pas pris en charge sur Nucleus SE. Il sera décrit dans la section Appels d'API non réalisés du prochain article.

Appel pour envoyer des messages à un canal dans Nucleus RTOS

Prototype d'appel de service:

STATUS NU_Send_To_Pipe (canal NU_PIPE *, message VOID *, taille UNSIGNED, suspension UNSIGNED);

Paramètres:

pipe - un pointeur vers le bloc de contrôle de canal fourni par l'utilisateur;
message - pointeur sur le message à envoyer;
taille - le nombre d'octets dans le message. Si le canal prend en charge les messages de longueur variable, ce paramètre doit être inférieur ou égal à la longueur de message prise en charge par le canal. Si le canal prend en charge les messages d'une longueur fixe, ce paramètre doit être égal à la taille du message pris en charge par le canal;
suspend - la spécification de la suspension de la tâche, peut prendre les valeurs NU_NO_SUSPEND , NU_SUSPEND ou valeur de timeout.

Valeur de retour:

NUSE_SUCCESS - l'appel s'est terminé avec succès;
NU_INVALID_PIPE - pointeur non valide vers le canal;
NU_INVALID_POINTER - pointeur nul vers un message ( NULL );
NU_INVALID_SIZE - la taille du message n'est pas compatible avec la taille du message prise en charge par le canal;
NU_INVALID_SUSPEND - tentative de suspension à partir d'un thread non lié à une tâche;
NU_PIPE_FULL - le canal est plein et le type de suspension de tâche n'a pas été spécifié;
NU_TIMEOUT - le canal est plein même après la suspension de la tâche pendant une période de temps spécifiée;
NU_PIPE_DELETED - le canal a été supprimé alors que la tâche a été suspendue;
NU_PIPE_RESET - Le canal a été réinitialisé alors que la tâche était suspendue.

Appel pour envoyer des messages à un canal dans Nucleus SE

Cet appel de service d'API prend en charge la fonctionnalité de base de l'API Nucleus RTOS.

Prototype d'appel de service:

STATUS NUSE_Pipe_Send (canal NUSE_PIPE, message U8 *, suspension U8);

Paramètres:

pipe - index (ID) du canal utilisé;
message - un pointeur sur le message à envoyer (une séquence d'octets de longueur autorisée pour un canal donné);
suspend - spécification de suspension de tâche, peut prendre les valeurs NUSE_NO_SUSPEND et NUSE_SUSPEND .

Valeur de retour:

NUSE_SUCCESS - l'appel s'est terminé avec succès;
NUSE_INVALID_PIPE - index de canal invalide;
NUSE_INVALID_POINTER - pointeur nul vers un message ( NULL );
NUSE_INVALID_SUSPEND - tentative de suspension à partir d'un thread non lié à une tâche ou lorsque le verrouillage de tâche est désactivé;
NUSE_PIPE_FULL - le canal est plein et le type de suspension de tâche n'a pas été spécifié;
NUSE_PIPE_WAS_RESET - Le canal a été réinitialisé alors que la tâche était suspendue.

Implémentation de l'affichage des canaux dans Nucleus SE

La version du code de fonction API NUSE_Pipe_Send () (après vérification des paramètres) est sélectionnée à l'aide de la compilation conditionnelle selon que la prise en charge des appels API est activée pour bloquer (suspendre) les tâches ou non. Ci-dessous, nous considérons les deux options.

Si le verrou est désactivé, le code de cet appel d'API est assez simple:

 if (NUSE_Pipe_Items[pipe] == NUSE_Pipe_Size[pipe]) /* pipe full */ { return_value = NUSE_PIPE_FULL; } else /* pipe element available */ { data = &NUSE_Pipe_Data[pipe][NUSE_Pipe_Head[pipe]]; for (i=0; i<msgsize; i++) { *data++ = *message++; } NUSE_Pipe_Head[pipe] += msgsize; if (NUSE_Pipe_Head[pipe] == (NUSE_Pipe_Size[pipe] * msgsize)) { NUSE_Pipe_Head[pipe] = 0; } NUSE_Pipe_Items[pipe]++; return_value = NUSE_SUCCESS; } 

La fonction vérifie s'il y a de l'espace libre dans le canal et utilise l' index NUSE_Pipe_Head [] pour placer le message dans la zone de données du canal.

Si le verrouillage des tâches est activé, le code devient plus complexe:

 do { if (NUSE_Pipe_Items[pipe] == NUSE_Pipe_Size[pipe]) /* pipe full */ { if (suspend == NUSE_NO_SUSPEND) { return_value = NUSE_PIPE_FULL; } else { /* block task */ NUSE_Pipe_Blocking_Count[pipe]++; NUSE_Suspend_Task(NUSE_Task_Active, (pipe << 4) | NUSE_PIPE_SUSPEND); return_value = NUSE_Task_Blocking_Return[NUSE_Task_Active]; if (return_value != NUSE_SUCCESS) { suspend = NUSE_NO_SUSPEND; } } } else /* pipe element available */ { data = &NUSE_Pipe_Data[pipe][NUSE_Pipe_Head[pipe]]; for (i=0; i<msgsize; i++) { *data++ = *message++; } NUSE_Pipe_Head[pipe] += msgsize; if (NUSE_Pipe_Head[pipe] == (NUSE_Pipe_Size[pipe] * msgsize)) { NUSE_Pipe_Head[pipe] = 0; } NUSE_Pipe_Items[pipe]++; if (NUSE_Pipe_Blocking_Count[pipe] != 0) { U8 index; /* check whether a task is blocked on this pipe */ NUSE_Pipe_Blocking_Count[pipe]--; for (index=0; index<NUSE_TASK_NUMBER; index++) { if ((LONIB(NUSE_Task_Status[index]) == NUSE_PIPE_SUSPEND) && (HINIB(NUSE_Task_Status[index]) == pipe)) { NUSE_Task_Blocking_Return[index] = NUSE_SUCCESS; NUSE_Wake_Task(index); break; } } } return_value = NUSE_SUCCESS; suspend = NUSE_NO_SUSPEND; } } while (suspend == NUSE_SUSPEND); 

Certaines clarifications peuvent être utiles.

Le code est enfermé dans une boucle do ... while , qui s'exécute alors que le paramètre de pause de tâche est NUSE_SUSPEND .

Si le canal est plein et que le paramètre de suspension est NUSE_NO_SUSPEND , l'appel d'API se termine par la valeur NUSE_PIPE_FULL . Si le paramètre de suspension est NUSE_SUSPEND , la tâche se met en pause. À la fin (c'est-à-dire lorsque la tâche reprend), si la valeur de retour est NUSE_SUCCESS , c'est-à-dire que la tâche a été reprise parce que le message a été lu (et non parce que le canal a été réinitialisé), le code retourne au début de la boucle.

Si le canal n'est pas plein, le message fourni est enregistré à l'aide de l' index NUSE_Pipe_Head [] dans la zone de données du canal. Il vérifie si le canal a interrompu des tâches (messages en attente). S'il existe de telles tâches, la première d'entre elles reprend. La variable de suspension est définie sur NUSE_NO_SUSPEND et l'appel d'API se termine avec la valeur NUSE_SUCCESS .

Lecture de la chaîne


L'appel de l'utilitaire Nucleus RTOS API pour la lecture à partir du canal est très flexible, ce qui vous permet de suspendre les tâches implicitement ou avec un délai d'expiration si l'opération ne peut pas être terminée immédiatement (par exemple, lorsque vous essayez de lire un canal vide). Nucleus SE a un appel d'utilitaire similaire, mais la pause de tâche est facultative et aucun délai d'attente n'est implémenté.

Défi de lecture de canal dans Nucleus RTOS

Prototype d'appel de service:

STATUS NU_Receive_From_Pipe (canal NU_PIPE *, message VOID *, taille UNSIGNED, UNSIGNED * actual_size, suspension UNSIGNED);

Paramètres:

pipe - un pointeur vers le bloc de contrôle de canal fourni par l'utilisateur;
message - un pointeur vers la mémoire pour le message reçu;
taille - le nombre d'octets dans le message. Doit correspondre à la taille de message spécifiée lors de la création du canal;
suspend - spécification de suspension de tâche, peut prendre NU_NO_SUSPEND , NU_SUSPEND ou des valeurs de délai d'expiration.

Valeur de retour:

NU_SUCCESS - l'appel s'est terminé avec succès;
NU_INVALID_PIPE - pointeur non valide vers le canal;
NU_INVALID_POINTER - pointeur nul vers un message ( NULL );
NU_INVALID_SUSPEND - tente de suspendre une tâche à partir d'un thread non associé à la tâche;
NU_PIPE_EMPTY - le canal est vide et le type de suspension de tâche n'a pas été spécifié;
NU_TIMEOUT - le canal est vide même après la suspension de la tâche pour la valeur de temporisation spécifiée;
NU_PIPE_DELETED - le canal a été supprimé alors que la tâche a été suspendue;
NU_PIPE_RESET - Le canal a été supprimé alors que la tâche était suspendue.

Défi de lecture de canal dans Nucleus SE

Cet appel de service d'API prend en charge la fonctionnalité de base de l'API Nucleus RTOS.

Prototype d'appel de service:

STATUS NUSE_Pipe_Receive (canal NUSE_PIPE, message U8 *, suspension U8);

Paramètres:

pipe - index (ID) du canal utilisé;
message - pointeur vers la mémoire du message reçu (une séquence d'octets dont la longueur coïncide avec la taille du message de canal);
suspend - spécification de suspension de tâche, peut prendre les valeurs NUSE_NO_SUSPEND et NU_SUSPEND .

Valeur de retour:

NUSE_SUCCESS - l'appel s'est terminé avec succès;
NUSE_INVALID_PIPE - index de canal invalide;
NUSE_INVALID_POINTER - pointeur nul vers un message ( NULL );
NUSE_INVALID_SUSPEND - une tentative de suspension d'une tâche à partir d'un thread non associé à la tâche ou avec prise en charge de la suspension de tâche désactivée;
NUSE_PIPE_EMPTY - le canal est vide et le type de suspension de tâche n'a pas été spécifié;
NUSE_PIPE_WAS_RESET - Le canal a été réinitialisé alors que la tâche était suspendue.

Implémentation d'un lecteur de flux dans Nucleus SE

La version du code de fonction API NUSE_Pipe_Receive () (après vérification des paramètres) est sélectionnée par compilation conditionnelle, selon que la prise en charge des appels d'API à bloquer (suspendre les tâches) est activée ou non. Nous considérerons les deux options ci-dessous.

Si le verrou est désactivé, le code de cet appel d'API est assez simple:

 if (NUSE_Pipe_Items[pipe] == 0) /* pipe empty */ { return_value = NUSE_PIPE_EMPTY; } else { /* message available */ data = &NUSE_Pipe_Data[pipe][NUSE_Pipe_Tail[pipe]]; for (i=0; i<msgsize; i++) { *message++ = *data++; } NUSE_Pipe_Tail[pipe] += msgsize; if (NUSE_Pipe_Tail[pipe] == (NUSE_Pipe_Size[pipe] * msgsize)) { NUSE_Pipe_Tail[pipe] = 0; } NUSE_Pipe_Items[pipe]--; *actual_size = msgsize; return_value = NUSE_SUCCESS; } 

La fonction vérifie la présence d'un message dans le canal et utilise l' index NUSE_Pipe_Tail [] pour extraire le message de la zone de données du canal et renvoie des données via le pointeur de message.

Si le verrouillage des tâches est activé, le code devient plus complexe:

 do { if (NUSE_Pipe_Items[pipe] == 0) /* pipe empty */ { if (suspend == NUSE_NO_SUSPEND) { return_value = NUSE_PIPE_EMPTY; } else { /* block task */ NUSE_Pipe_Blocking_Count[pipe]++; NUSE_Suspend_Task(NUSE_Task_Active, (pipe << 4) | NUSE_PIPE_SUSPEND); return_value = NUSE_Task_Blocking_Return[NUSE_Task_Active]; if (return_value != NUSE_SUCCESS) { suspend = NUSE_NO_SUSPEND; } } } else { /* message available */ data = &NUSE_Pipe_Data[pipe][NUSE_Pipe_Tail[pipe]]; for (i=0; i<msgsize; i++) { *message++ = *data++; } NUSE_Pipe_Tail[pipe] += msgsize; if (NUSE_Pipe_Tail[pipe] == (NUSE_Pipe_Size[pipe] * msgsize)) { NUSE_Pipe_Tail[pipe] = 0; } NUSE_Pipe_Items[pipe]--; if (NUSE_Pipe_Blocking_Count[pipe] != 0) { U8 index; /* check whether a task is blocked */ /* on this pipe */ NUSE_Pipe_Blocking_Count[pipe]--; for (index=0; index<NUSE_TASK_NUMBER; index++) { if ((LONIB(NUSE_Task_Status[index]) == NUSE_PIPE_SUSPEND) && (HINIB(NUSE_Task_Status[index]) == pipe)) { NUSE_Task_Blocking_Return[index] = NUSE_SUCCESS; NUSE_Wake_Task(index); break; } } } *actual_size = msgsize; return_value = NUSE_SUCCESS; suspend = NUSE_NO_SUSPEND; } } while (suspend == NUSE_SUSPEND); 

Certaines clarifications peuvent être utiles.

Le code est enfermé dans une boucle do ... while , qui s'exécute alors que le paramètre de pause de tâche est NUSE_SUSPEND .

Si le canal est vide et que le paramètre de suspension est NUSE_NO_SUSPEND , l'appel d'API se termine par la valeur NUSE_PIPE_EMPTY . Si le paramètre de suspension est NUSE_SUSPEND , la tâche se met en pause. À la fin (c'est-à-dire lorsque la tâche reprend), si la valeur de retour est NUSE_SUCCESS , c'est-à-dire que la tâche a été reprise parce que le message a été envoyé (et non parce que le canal a été réinitialisé), le code revient au début de la boucle.

Si le canal contient des messages, le message stocké est renvoyé à l'aide de l' index NUSE_Pipe_Tail [] . Vérifie s'il y a des tâches suspendues (en attente d'être envoyées) sur ce canal. S'il existe de telles tâches, la première d'entre elles reprend. La variable de suspension est définie sur NUSE_NO_SUSPEND et l'appel API se termine avec le code NUSE_SUCCESS .

Enregistrer au début de la chaîne


L'appel de l'utilitaire Nucleus RTOS API pour écrire au début du canal est très flexible, ce qui vous permet de suspendre les tâches implicitement ou avec un délai d'attente si l'opération ne peut pas être terminée immédiatement (par exemple, lorsque vous essayez d'écrire sur un canal complet). Nucleus SE a un appel d'utilitaire similaire, mais la pause de tâche est facultative et aucun délai d'attente n'est implémenté.

Appel pour écrire au début du canal dans Nucleus RTOS

Prototype d'appel de service:

STATUS NU_Send_To_Front_Of_Pipe (canal NU_PIPE *, message VOID *, taille UNSIGNED, suspension UNSIGINED);

Paramètres:

pipe - un pointeur vers le bloc de contrôle de canal fourni par l'utilisateur;
message - pointeur sur le message à envoyer;
taille - le nombre d'octets dans le message. Si le canal prend en charge les messages de longueur variable, ce paramètre doit être égal ou inférieur à la taille du message pris en charge par le canal. Si le canal prend en charge les messages de longueur fixe, ce paramètre doit correspondre à la taille de message prise en charge par le canal;
suspend - spécification de suspension de tâche, peut prendre NU_NO_SUSPEND , NU_SUSPEND ou des valeurs de délai d'expiration.

Valeur de retour:

NU_SUCCESS - l'appel s'est terminé avec succès;
NU_INVALID_PIPE - pointeur non valide vers le canal;
NU_INVALID_POINTER - pointeur nul vers un message ( NULL );
NU_INVALID_SIZE - la taille du message est incompatible avec la taille du message prise en charge par le canal;
NU_INVALID_SUSPEND - tentative de suspension à partir d'un thread sans rapport avec la tâche;
NU_PIPE_FULL - le canal est plein et le type de suspension de tâche n'a pas été spécifié;
NU_TIMEOUT - le canal est plein même après la suspension de la tâche pendant une période de temps spécifiée;
NU_PIPE_DELETED - le canal a été supprimé alors que la tâche a été suspendue;
NU_PIPE_RESET - Le canal a été réinitialisé alors que la tâche était suspendue.

Appel pour écrire au début du canal dans Nucleus SE

Cet appel d'utilitaire prend en charge la fonctionnalité principale de l'API RTOS Nucleus.

Prototype d'appel de service:

STATUS NUSE_Pipe_Jam (canal NUSE_PIPE, message ADDR *, suspension U8);

Paramètres:

pipe - index (ID) du canal utilisé;
message - un pointeur vers le message à envoyer, qui est une séquence d'octets égale à la taille de message configurée dans le canal;
suspend - spécification de suspension de tâche, peut être NUSE_NO_SUSPEND ou NUSE_SUSPEND .

Valeur de retour:

NUSE_SUCCESS - l'appel s'est terminé avec succès;
NUSE_INVALID_PIPE - index de canal invalide;
NUSE_INVALID_POINTER - pointeur nul vers un message ( NULL );
NUSE_INVALID_SUSPEND - une tentative de suspension d'une tâche à partir d'un thread non associé à la tâche ou lorsque le verrouillage de la tâche est désactivé;
NUSE_PIPE_FULL - le canal est plein et le type de suspension de tâche n'a pas été spécifié;
NUSE_PIPE_WAS_RESET - Le canal a été réinitialisé alors que la tâche était suspendue.

Implémentation de l'enregistrement d'entrée de canal dans Nucleus SE

Le code de variante de la fonction NUSE_Pipe_Jam () est très similaire à NUSE_Pipe_Send () , sauf que l'index NUSE_Pipe_Tail [] est utilisé pour y stocker des données, donc:

 if (NUSE_Pipe_Items[pipe] == NUSE_Pipe_Size[pipe]) /* pipe full */ { return_value = NUSE_PIPE_FULL; } else /* pipe element available */ { if (NUSE_Pipe_Tail[pipe] == 0) { NUSE_Pipe_Tail[pipe] = (NUSE_Pipe_Size[pipe] - 1) * msgsize; } else { NUSE_Pipe_Tail[pipe] -= msgsize; } data = &NUSE_Pipe_Data[pipe][NUSE_Pipe_Tail[pipe]]; for (i=0; i<msgsize; i++) { *data++ = *message++; } NUSE_Pipe_Items[pipe]++; return_value = NUSE_SUCCESS; } 

Dans le prochain article, nous considérerons les appels de service supplémentaires liés aux canaux, ainsi que les structures de données correspondantes.

À 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.

Source: https://habr.com/ru/post/fr433046/


All Articles