Toute la vérité sur RTOS. Article # 29. Interruptions dans Nucleus SE

Tous les microprocesseurs et microcontrôleurs modernes contiennent une sorte de mécanisme d'interruption. Ces mécanismes sont nécessaires pour fournir la réactivité requise par de nombreuses applications. Bien sûr, la réactivité et la prévisibilité sont le principal objectif lors de l'utilisation de RTOS, mais en même temps, ils sont opposés. L'utilisation d'interruptions peut perturber l'intégrité du système d'exploitation en temps réel. Ce problème et sa solution ont été mentionnés dans l'un des articles précédents (# 4 et # 6). Dans cet article, nous examinerons la stratégie de gestion des interruptions utilisée dans Nucleus SE. Dans tous les cas, les interruptions ne sont PAS contrôlées par Nucleus SE: elles sont traitées lorsqu'elles se produisent en fonction de la priorité et des vecteurs de la manière habituelle. Leur temps d'exécution est simplement «volé» au temps disponible dans le code de l'application principale et de l'ordonnanceur. De toute évidence, il s'ensuit que tous les gestionnaires d'interruptions doivent être simples, courts et rapides.



Articles précédents de la série:
Article # 28. Minuteries logicielles
Article # 27. Heure système
Article # 26. Canaux: services auxiliaires et structures de données
Article # 25. Canaux de données: introduction et services de base
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.

Interruptions régulières et contrôlées


Nucleus SE propose deux façons de gérer les interruptions: «native» ou «régulière» (Native), dans lesquelles les interruptions n'ont rien de spécial et ont dans une certaine mesure une interaction limitée avec le système d'exploitation (au moins lors de l'utilisation du planificateur de priorité), et « Géré, dans lequel vous pouvez accéder à un nombre beaucoup plus élevé d'appels d'API à partir du gestionnaire d'interruption.

À l'aide des macros d'E / S, le gestionnaire d'interruption Nucleus SE peut être utilisé en mode standard ou géré.

Interruptions du personnel


Les interruptions de personnel de Nucleus SE sont le gestionnaire d'interruption standard et peuvent être considérées comme "non gérées". Ils sont généralement utilisés lorsqu'une interruption peut survenir à une fréquence élevée et nécessite un traitement avec une faible utilisation des ressources informatiques. Un tel gestionnaire est probablement écrit en C, car de nombreux compilateurs intégrés modernes prennent en charge le développement de gestionnaires d'interruptions à l'aide du mot-clé interruption. Seules les informations contextuelles que le compilateur juge nécessaires sont stockées. Cela conduit à des limitations importantes sur ce que les gestionnaires d'interruption standard peuvent faire, ce que nous verrons bientôt.

Pour créer un gestionnaire d'interruption régulier dans Nucleus SE, il suffit d'écrire simplement un gestionnaire d'interruption régulier, y compris en appelant la macro NUSE_NISR_Enter () au début et en appelant NUSE_NISR_Exit () à la fin. Ces macros sont définies dans le fichier nuse_types. h et définissez la variable globale NUSE_Task_State sur NUSE_NISR_CONTEXT .

Interruptions guidées


Si vous avez besoin de plus de flexibilité pour les opérations du gestionnaire d'interruptions, les interruptions gérées par Nucleus SE peuvent être la solution. La principale différence par rapport à l'interruption standard est le maintien du contexte. Au lieu de permettre au compilateur d'enregistrer plusieurs registres sur la pile, une interruption contrôlée enregistre le contexte entier de la tâche (dans son propre bloc de contexte) à l'entrée. Le contexte de la tâche en cours est ensuite restauré à partir du bloc de contexte en sortie. Cela permet de modifier la tâche en cours grâce au travail du code du gestionnaire d'interruption, ce qui est possible lors de l'utilisation du planificateur de priorité. Une description complète de la préservation et de la restauration du contexte dans Nucleus SE a été fournie dans un article précédent ( # 10 ).

Évidemment, la pleine conservation du contexte entraîne une augmentation de l'utilisation des ressources informatiques par rapport au stockage de plusieurs registres sur la pile, ce qui se produit lors d'une interruption standard. Ce prix doit être payé pour une flexibilité supplémentaire, et c'est la raison pour laquelle un choix d'approche de gestion des interruptions est proposé.

Une interruption gérée est générée à l'aide de la macro NUSE_MANAGED_ISR () décrite dans nuse_types.h . Cette macro crée une fonction qui contient les actions suivantes:

  • maintenir le contexte de la tâche;
  • Affectation de NUSE_Task_State à NUSE_MISR_CONTEXT ;
  • code de fonction du gestionnaire d'interruption fourni par l'utilisateur;
  • restaurer NUSE_Task_State à son état précédent;
  • restaurer le contexte de la tâche.

La macro prend deux paramètres: le nom d'interruption utilisé comme nom de fonction pour le gestionnaire généré et le nom de la fonction qui contient la logique utilisateur pour le gestionnaire d'interruption.

Appels API du gestionnaire d'interruption


L'ensemble des fonctions API pouvant être appelées à partir d'un gestionnaire d'interruption standard ou géré dépend du planificateur utilisé. De manière générale, l'utilisation du planificateur de priorité offre de nombreuses options pour accéder au planificateur via un appel de fonction API, ce qui est difficile lors de l'utilisation du gestionnaire d'interruption standard.

Appels d'API au gestionnaire d'interruption standard lors de l'utilisation du planificateur de priorité

Lorsque vous utilisez le planificateur de priorité, un nombre limité d'appels de fonction API à partir du gestionnaire d'interruption standard sont autorisés. Cette limitation est le résultat de la flexibilité de l'API Nucleus SE: de nombreux appels peuvent rendre la tâche prête et le planificateur peut ne pas être appelé par le gestionnaire d'interruption standard (car le contexte de la tâche n'est pas enregistré). La désactivation des verrous de tâche offre encore plus de flexibilité.

Les appels d'API suivants sont toujours autorisés:

NUSE_Task_Current() NUSE_Task_Check_Stack() NUSE_Task_Information() NUSE_Task_Count() NUSE_Partition_Pool_Information() NUSE_Partition_Pool_Count() NUSE_Mailbox_Information() NUSE_Mailbox_Count() NUSE_Queue_Information() NUSE_Queue_Count() NUSE_Pipe_Information() NUSE_Pipe_Count() NUSE_Semaphore_Information() NUSE_Semaphore_Count() NUSE_Event_Group_Information() NUSE_Event_Group_Count() NUSE_Signals_Send() NUSE_Timer_Control() NUSE_Timer_Get_Remaining() NUSE_Timer_Reset() NUSE_Timer_Information() NUSE_Timer_Count() NUSE_Clock_Set() NUSE_Clock_Retrieve() NUSE_Release_Information() 

Cependant, seul NUSE_Signals_Send () leur est utile, car il fournit un moyen pratique d'indiquer à la tâche qu'une action est requise.

Si le verrou est désactivé, c'est-à-dire que les tâches ne peuvent pas être mises dans un état prêt par de nombreux appels d'API, des appels d'API supplémentaires deviennent disponibles:

 NUSE_Partition_Allocate() NUSE_Partition_Deallocate() NUSE_Mailbox_Send() NUSE_Mailbox_Receive() NUSE_Mailbox_Reset() NUSE_Queue_Send() NUSE_Queue_Receive() NUSE_Queue_Jam() NUSE_Queue_Reset() NUSE_Pipe_Send() NUSE_Pipe_Receive() NUSE_Pipe_Jam() NUSE_Pipe_Reset() NUSE_Semaphore_Obtain() NUSE_Semaphore_Release() NUSE_Semaphore_Reset() NUSE_Event_Group_Set() NUSE_Event_Group_Retrieve() 

Certains appels d'API sont toujours inaccessibles aux gestionnaires d'interruption standard, car ils nécessiteront inévitablement le travail d'un planificateur:
 NUSE_Task_Suspend() NUSE_Task_Resume() NUSE_Task_Sleep() NUSE_Task_Relinquish() NUSE_Task_Reset() NUSE_Signals_Receive() 

Appels d'API au gestionnaire d'interruption géré ou au gestionnaire d'interruption standard lors de l'utilisation d'un planificateur autre que le planificateur prioritaire

De nombreuses autres fonctions API peuvent être appelées à partir du gestionnaire d'interruption lors de l'utilisation des planificateurs Run to Completion, Round Robin ou Time Slice. Si un planificateur de priorité est utilisé, les gestionnaires d'interruption gérés ont un ensemble de fonctions similaire. En effet, les appels sont autorisés, ce qui peut conduire à planifier une autre tâche. Cette fonctionnalité est fournie par le code NUSE_Reschedule () , qui détecte le contexte d'appel dans le gestionnaire d'interruption et supprime le changement de contexte (lui permettant de se produire à la fin du gestionnaire d'interruption). Une analyse complète du travail de l'ordonnanceur a été donnée dans l'un des articles précédents ( # 9 ).

La principale exigence est que les appels d'API à l'intérieur du gestionnaire d'interruptions ne doivent pas conduire à une suspension de la tâche en cours, par exemple, en attendant de libérer une ressource.

En d'autres termes, ces appels doivent être effectués avec l' option de pause NUSE_NO_SUSPEND .

Dans cet esprit, les appels d'API suivants peuvent être utilisés:

 NUSE_Task_Current() NUSE_Task_Check_Stack() NUSE_Task_Information() NUSE_Task_Count() NUSE_Task_Suspend() NUSE_Task_Resume() NUSE_Task_Reset() NUSE_Partition_Allocate() NUSE_Partition_Deallocate() NUSE_Partition_Pool_Information() NUSE_Partition_Pool_Count() NUSE_Mailbox_Send() NUSE_Mailbox_Receive() NUSE_Mailbox_Reset() NUSE_Mailbox_Information() NUSE_Mailbox_Count() NUSE_Queue_Send() NUSE_Queue_Receive() NUSE_Queue_Jam() NUSE_Queue_Reset() NUSE_Queue_Information() NUSE_Queue_Count() NUSE_Pipe_Send() NUSE_Pipe_Receive() NUSE_Pipe_Jam() NUSE_Pipe_Reset() NUSE_Pipe_Information() NUSE_Pipe_Count() NUSE_Semaphore_Obtain() NUSE_Semaphore_Release() NUSE_Semaphore_Reset() NUSE_Semaphore_Information() NUSE_Semaphore_Count() NUSE_Event_Group_Set() NUSE_Event_Group_Retrieve() NUSE_Event_Group_Information() NUSE_Event_Group_Count() NUSE_Signals_Send() NUSE_Timer_Control() NUSE_Timer_Get_Remaining() NUSE_Timer_Reset() NUSE_Timer_Information() NUSE_Timer_Count() NUSE_Clock_Set() NUSE_Clock_Retrieve() NUSE_Release_Information() 

Certains appels sont toujours interdits, car ils se rapportent directement à la tâche en cours:
 NUSE_Task_Relinquish() NUSE_Signals_Receive() NUSE_Task_Sleep() 

Gestionnaire d'interruption d'horloge en temps réel


Le gestionnaire d'interruption RTC (Real Time Clock) est le seul gestionnaire d'interruption complet dans Nucleus SE. En plus de fournir toutes les fonctionnalités nécessaires à la gestion du temps dans Nucleus SE, il sert également d'exemple d'écriture d'un gestionnaire d'interruption géré.

Opérations du gestionnaire d'interruption RTC


Les fonctions fournies par le gestionnaire d'interruption RTC ont été répertoriées dans l'un des articles précédents, qui traitaient du vaste sujet de l'heure système dans Nucleus SE ( # 27 ). La fonctionnalité décrite est facultative selon la configuration de l'application.

Voici le code complet du gestionnaire d'interruption RTC.
 #if NUSE_TIMER_NUMBER != 0 { U8 timer; for (timer=0; timer<NUSE_TIMER_NUMBER; timer++) { if (NUSE_Timer_Status[timer]) { if (--NUSE_Timer_Value[timer] == 0) { NUSE_Timer_Expirations_Counter[timer]++; #if NUSE_TIMER_EXPIRATION_ROUTINE_SUPPORT || NUSE_INCLUDE_EVERYTHING if (NUSE_Timer_Expiration_Routine_Address[timer] != NULL) { ((PF1)NUSE_Timer_Expiration_Routine_Address[timer]) NUSE_Timer_Expiration_Routine_Parameter[timer]); } #endif /* reschedule? */ if (NUSE_Timer_Reschedule_Time[timer] != 0) { /* yes: set up time */ NUSE_Timer_Value[timer] = NUSE_Timer_Reschedule_Time[timer]; } else { /* no: disable */ NUSE_Timer_Status[timer] = FALSE; } } } } } #endif #if NUSE_SYSTEM_TIME_SUPPORT || NUSE_INCLUDE_EVERYTHING NUSE_Tick_Clock++; #endif #if NUSE_TASK_SLEEP || NUSE_INCLUDE_EVERYTHING { U8 task; for (task=0; task<NUSE_TASK_NUMBER; task++) { if (NUSE_Task_Timeout_Counter[task] != 0) { NUSE_Task_Timeout_Counter[task]--; if (NUSE_Task_Timeout_Counter[task] == 0) { NUSE_Wake_Task(task); } } } } #endif #if NUSE_SCHEDULER_TYPE == NUSE_TIME_SLICE_SCHEDULER if (--NUSE_Time_Slice_Ticks == 0) { NUSE_Reschedule(); } #endif 


Ensuite, nous examinons quatre principaux domaines de fonctionnalité pour le gestionnaire d'interruption RTC.

Minuteries
Si les temporisateurs d'application sont configurés, le gestionnaire d'interruption passe en boucle pour traiter chaque temporisateur en diminuant son compteur de 1. Si le temporisateur termine le comptage (c'est-à-dire que le compteur atteint 0), deux actions sont possibles:

  • si le gestionnaire de fin de temporisation est configuré et que le temporisateur a un pointeur de fonction correct (non NULL ) (dans NUSE_Timer_Expiration_Routine_Address [] ), le gestionnaire est exécuté en prenant un paramètre de NUSE_Timer_Expiration_Routine_Parameter [] ;
  • si le temporisateur est configuré pour s'initialiser après la fin (c'est-à-dire que NUSE_Timer_Reschedule_Time [] a une valeur non nulle), le temporisateur se recharge avec cette valeur.

Les temporisateurs d'application ont été décrits en détail dans un article précédent (# 28).

Horloge système
Si un temporisateur système est configuré, la valeur de NUSE_Tick_Cloc k augmente simplement de 1. Plus d'informations peuvent être trouvées dans l'article # 28.

Suspendre une tâche (veille de tâche)
Si la prise en charge des tâches de pause est activée (c'est-à-dire que l'API NUSE_Task_Sleep () est configuré), le compteur de délai d'attente de chaque tâche (la valeur dans NUSE_Task_Timeout_Counter [] ) est vérifié, et s'il n'est pas égal à zéro, diminue de 1. S'il atteint zéro, la tâche correspondante reprend. .

Planification des tranches de temps
Si un planificateur de tranche de temps est utilisé, le compteur du planificateur ( NUSE_Time_Slice_Ticks ) est décrémenté. S'il atteint zéro, l'ordonnanceur est appelé. L'appel à NUSE_Reschedule () est responsable de la réinitialisation du compteur.

Interruption contrôlée


Il est nécessaire d'expliquer pourquoi le gestionnaire d'interruption RTC est contrôlable, car dans certaines circonstances, l'utilisateur peut décider de le réécrire en tant qu'interruption standard pour réduire l'utilisation des ressources informatiques. Par exemple, si une seule fonction d'heure système est utilisée (c'est-à-dire qu'il n'y a pas de temporisation d'application, pas de suspension de tâche et pas de planificateur de tranche horaire), une interruption régulière fonctionnera. Une interruption guidée est requise dans les cas suivants:

  • si des temporisateurs sont utilisés et que des gestionnaires pour leur exécution sont configurés, car ces gestionnaires peuvent effectuer des appels API (à partir du contexte d'interruption), ce qui entraînera une nouvelle planification. Ils ont les mêmes limitations que les appels d'API effectués à partir de gestionnaires d'interruptions (voir plus haut dans cet article);
  • si un planificateur de priorité est utilisé, l'achèvement d'une suspension de tâche peut nécessiter de réveiller une tâche avec une priorité plus élevée;
  • si le planificateur de tranche de temps est utilisé, il sera appelé à partir du gestionnaire d'interruption RTC, par conséquent, une interruption contrôlée est requise.

Compatible avec Nucleus RTOS


Étant donné que la mise en œuvre des interruptions Nucleus SE est très différente de Nucleus RTOS, vous ne devez pas vous attendre à une compatibilité à cet égard. Nucleus RTOS a un schéma d'interruption standard / bas niveau / haut niveau, qui est un peu comme le schéma d'interruption standard / contrôlé dans Nucleus SE.

Gestionnaires d'interruption de bas et de haut niveau


Gestionnaires d'interruption de bas niveau
Un routage de service d'interruption de bas niveau (LISR) est exécuté de la même manière qu'un gestionnaire ordinaire, y compris en utilisant la pile actuelle. Nucleus RTOS maintient le contexte jusqu'à ce que le gestionnaire d'interruption de bas niveau soit appelé et restaure le contexte une fois le gestionnaire terminé. Par conséquent, un gestionnaire d'interruption de bas niveau peut être écrit en C et peut appeler d'autres gestionnaires en C. Cependant, seuls quelques services Nucleus RTOS sont disponibles pour le gestionnaire de bas niveau. Si la gestion des interruptions nécessite des services Nucleus RTOS supplémentaires, vous devez activer un gestionnaire d'interruption de haut niveau. Nucleus RTOS prend en charge l'utilisation de plusieurs gestionnaires d'interruption de bas niveau.

Gestionnaire d'interruption de haut niveau
Les routines de service d'interruption de haut niveau (HISR) sont créées et supprimées dynamiquement. Chaque processeur de haut niveau possède son propre espace de pile et sa propre unité de contrôle. La mémoire est allouée par l'application. Et, bien sûr, un gestionnaire d'interruption de haut niveau doit être créé avant qu'un gestionnaire d'interruption de bas niveau puisse l'activer.

Étant donné que le gestionnaire d'interruption de haut niveau possède sa propre pile et unité de contrôle, il peut être temporairement bloqué s'il essaie d'accéder à la structure de données Nucleus RTOS actuellement utilisée.

Il existe trois niveaux de priorité disponibles pour un gestionnaire d'interruption de haut niveau. Si un gestionnaire de niveau supérieur avec une priorité plus élevée est activé pendant le travail d'un gestionnaire avec une priorité inférieure, un gestionnaire avec une priorité inférieure sera exécuté à la fin de la tâche. Les gestionnaires d'interruption de haut niveau avec la même priorité sont exécutés dans l'ordre où ils sont activés. Tous les gestionnaires d'interruption de haut niveau activés doivent être terminés avant de continuer à planifier des tâches en mode normal.

L'utilitaire Nucleus RTOS API appelle à une interruption


Nucleus RTOS dispose de plusieurs appels API pour prendre en charge les interruptions. Aucun d'eux n'est implémenté dans Nucleus SE.

Pour les interruptions standard, les appels d'API fournissent les fonctions suivantes:

  • contrôle (activation / désactivation) de l'interruption (localement et globalement);
  • définir le vecteur d'interruption.

Pour les interruptions de bas niveau:

  • enregistrer un gestionnaire d'interruption de bas niveau dans le noyau.

Pour les interruptions de haut niveau:

  • création / suppression d'interruptions de haut niveau;
  • activation d'interruption de haut niveau;
  • obtenir le nombre d'interruptions de haut niveau dans l'application (pour le moment);
  • obtenir des pointeurs pour contrôler les unités de toutes les interruptions de haut niveau;
  • obtenir des pointeurs pour contrôler les unités de l'interruption de haut niveau actuelle;
  • Obtenir des informations d'interruption de haut niveau.

Contrôle global des interruptions

Cet appel active ou désactive les interruptions quelle que soit la tâche. Par conséquent, l'interruption désactivée par cet appel le restera jusqu'à ce qu'elle soit activée en réutilisant cet appel.

Prototype d'appel de service:

 INT NU_Control_Interrupts (INT new_level); 

Paramètres:

new_level - un nouveau niveau d'interruption pour le système. Il peut toujours prendre les valeurs NU_DISABLE_INTERRUPTS (désactive toutes les interruptions) et NU_ENABLE_INTERRUPTS (active toutes les interruptions). D'autres valeurs peuvent être disponibles selon l'architecture.

Valeur de retour:

Cet appel de service renvoie le niveau précédent d'interruptions activées.

Contrôle d'interruption local

Cet appel de service vous permet d'activer ou de désactiver des interruptions en fonction de la tâche. Cet appel modifie le registre d'état à la valeur spécifiée. Le registre d'état sera retourné à la valeur spécifiée par le dernier appel à NU_Control_Interrupts () la prochaine fois que le contexte sera modifié.

Prototype d'appel de service:

 INT NU_Local_Control_Interrupts (INT new_level); 

Paramètres:

new_level - un nouveau niveau d'interruption pour la tâche en cours. Il peut toujours prendre les valeurs NU_DISABLE_INTERRUPTS (désactive toutes les interruptions) et NU_ENABLE_INTERRUPTS (active toutes les interruptions). D'autres valeurs peuvent être disponibles selon l'architecture.

Valeur de retour:
Cet appel de service renvoie le niveau précédent d'interruptions activées.

Définition du vecteur d'interruption

Cette surcharge remplace le vecteur d'interruption spécifié par le vecteur contrôlé par le gestionnaire d'interruption.

Prototype d'appel de service:

 VOID *NU_Setup_Vector (INT vector, VOID *new); 

Paramètres:

vecteur - vecteur d' interruption pour lequel l'interruption sera enregistrée;
new est le gestionnaire d'interruption écrit pour le vecteur.

Valeur de retour:

Cet appel d'utilitaire renvoie un pointeur sur le gestionnaire d'interruption précédemment enregistré pour le vecteur d'interruption.

Journalisation des interruptions de bas niveau

Cette surcharge appelle la fonction du gestionnaire d'interruption de bas niveau avec le vecteur d'interruption. Le contexte système est automatiquement enregistré avant l'appel du gestionnaire d'interruption de bas niveau spécifié et restauré une fois le gestionnaire d'interruption terminé.

Prototype d'appel de service:

 STATUS NU_Register_LISR (INT vector, VOID (*lisr_entry) (INT), VOID (**old_lisr) (INT); 

Paramètres:

vecteur - vecteur d' interruption pour lequel l'interruption sera enregistrée;
lisr_entry - la fonction qui sera enregistrée pour le vecteur, la valeur NU_NULL effacera le vecteur;
old_lisr est une fonction précédemment enregistrée pour le vecteur spécifié.

Valeur de retour:

NU_SUCCESS - l'appel s'est terminé avec succès;
NU_INVALID_VECTOR - vecteur invalide;
NU_NOT_Rector - au moment où le vecteur n'est pas enregistré, car le désenregistrement a été spécifié dans l isr_entry ;
NO_MORE_LISRS - Le nombre maximal de gestionnaires d'interruption de bas niveau enregistrés a été atteint.

Création d'un gestionnaire d'interruption de haut niveau
Cet appel d'utilitaire crée un gestionnaire d'interruption de haut niveau.

Prototype d'appel de service:

 STATUS NU_Create_HISR (NU_HISR *hisr, CHAR *name, VOID (*hisr_entry) (VOID), OPTION priority, VOID *stack_pointer, UNSIGNED stack_size); 

Paramètres:

hisr - un pointeur vers un bloc de contrôle fourni par l'utilisateur pour un gestionnaire d'interruption de haut niveau;
nom - pointeur vers un nom à 7 caractères pour un gestionnaire d'interruption de haut niveau avec un zéro de fin;
hisr_entry - le point d'entrée de la fonction de gestionnaire d'interruption de haut niveau;
priorité - il existe trois priorités pour les gestionnaires d'interruption de haut niveau (0-2); la priorité 0 est la plus élevée;
stack_pointer - pointeur vers la zone de pile du gestionnaire d'interruption de haut niveau;
stack_size - le nombre d'octets dans la pile du gestionnaire d'interruption de haut niveau.

Valeur de retour:

NU_SUCCESS - l'appel s'est terminé avec succès;
NU_INVALID_HISR - un pointeur nul vers l'unité de contrôle du gestionnaire d'interruption de haut niveau ( NULL ) ou l'unité de contrôle est déjà en cours d'utilisation;
NU_INVALID_ENTRY - un pointeur nul vers le point d'entrée d'un gestionnaire d'interruption de haut niveau ( NULL );
NU_INVALID_PRIORITY - priorité incorrecte pour un gestionnaire d'interruption de haut niveau;
NU_INVALID_MEMORY - pointeur de pile invalide;
NU_INVALID_SIZE - la taille de la pile est trop petite.

Suppression d'un gestionnaire d'interruption de haut niveau
Cet appel d'utilitaire supprime le gestionnaire d'interruption de haut niveau précédemment créé.

Prototype d'appel de service:

 STATUS NU_Delete_HISR (NU_HISR *hisr); 

Paramètres:

hisr est un pointeur sur le bloc de contrôle du gestionnaire d'interruption de haut niveau fourni par l'utilisateur.

Valeur de retour:

NU_SUCCESS - l'appel s'est terminé avec succès;
NU_INVALID_HISR - Pointeur non valide vers un gestionnaire d'interruption de haut niveau.

Activation d'un gestionnaire d'interruption de haut niveau

Cet appel d'utilitaire active un gestionnaire d'interruption de haut niveau. Si le gestionnaire d'interruption de haut niveau spécifié est en cours d'exécution, la demande d'activation n'est pas exécutée jusqu'à ce que le gestionnaire cesse de fonctionner. Un gestionnaire d'interruption de haut niveau est exécuté une fois pour chaque demande d'activation.

Prototype d'appel de service:

 STATUS NU_Activate_HISR (NU_HISR *hisr); 

Paramètres:

hisr est un pointeur sur le bloc de contrôle d'un gestionnaire d'interruption de haut niveau.
Valeur de retour:
NU_SUCCESS - l'appel s'est terminé avec succès;
NU_INVALID_HISR - pointeur non valide vers l'unité de contrôle d'un gestionnaire d'interruption de haut niveau.

Obtention du nombre de gestionnaires d'interruption de haut niveau dans un système
Cet appel d'utilitaire renvoie le nombre de gestionnaires d'interruption de haut niveau installés. Tous les gestionnaires d'interruption de haut niveau créés sont considérés comme installés. Les gestionnaires d'interruption de haut niveau à distance ne sont pas considérés comme installés.

Prototype d'appel de service:

 UNSIGNED NU_Established_HISRs(VOID); 

Paramètres:
Sont absents.

Valeur de retour:
Cet appel d'utilitaire renvoie le nombre de gestionnaires d'interruption de haut niveau installés dans le système.

Obtenir des pointeurs pour contrôler les blocs de gestionnaires d'interruption de haut niveau

Cet appel de service forme une liste séquentielle de pointeurs vers tous les gestionnaires d'interruption de haut niveau installés dans le système.

Prototype d'appel de service:

 UNSIGNED NU_HISR_Pointers(NU_HISR **pointer_list, UNSIGNED maximum_pointers); 

Paramètres:

pointer_list - pointeur vers un tableau de pointeurs NU_HISR ; ce tableau sera rempli de pointeurs vers les gestionnaires d'interruption de haut niveau installés dans le système;
maximum_pointers - le nombre maximum de pointeurs NU_HISR pouvant être placés dans le tableau; il est généralement égal à la taille du tableau pointer_list .

Valeur de retour:
Cet appel d'utilitaire renvoie le nombre de gestionnaires d'interruption de haut niveau actifs dans le système.

Obtention d'un pointeur vers le gestionnaire d'interruption de haut niveau actuel
Cet appel d'utilitaire renvoie un pointeur sur le gestionnaire d'interruption de haut niveau en cours d'exécution.

Prototype d'appel de service:

 NU_HISR *NU_Current_HISR_Pointer(VOID); 

Paramètres:
Sont absents.

Valeur de retour:
Cet appel de service renvoie un pointeur vers l'unité de contrôle du gestionnaire d'interruption de haut niveau en cours d'exécution. Si un gestionnaire d'interruption non de haut niveau appelle cette fonction, NU_NULL est renvoyé.

Obtention d'informations sur un gestionnaire d'interruption de haut niveau
Cet appel d'utilitaire renvoie diverses informations sur le gestionnaire d'interruption de haut niveau spécifié.

Prototype d'appel de service:

 STATUS NU_HISR_Information(NU_HISR *hisr, char *name, UNSIGNED *scheduled_count, DATA_ELEMENT *priority, VOID **stack_base, UNSIGNED *stack_size, UNSIGNED *minimum_stack); 

Paramètres:

hisr - un pointeur vers un gestionnaire d'interruption de haut niveau;
nom - pointeur vers la région à 8 caractères pour le nom du gestionnaire d'interruption de haut niveau, y compris le zéro de fin;
schedule_count - pointeur sur une variable pour le nombre total de fois que ce gestionnaire d'interruption de haut niveau a été planifié;
priorité - un pointeur sur une variable pour stocker la priorité d'un gestionnaire d'interruption de haut niveau;
stack_base - pointeur vers un pointeur pour stocker le pointeur d'origine dans la pile; il s'agit du même pointeur qui a été transmis lors de la création du gestionnaire d'interruption de haut niveau;
stack_size - un pointeur vers une variable pour stocker la taille totale de la pile d'un gestionnaire d'interruption de haut niveau;
minimum_stack - un pointeur vers une variable pour stocker la quantité minimale d'espace de pile disponible détectée lors de l'exécution d'un gestionnaire d'interruption de haut niveau.

Valeur de retour:

NU_SUCCESS - l'appel s'est terminé avec succès;
NU_INVALID_HISR - pointeur non valide vers un gestionnaire d'interruption de haut niveau.

Appels API des gestionnaires d'interruption


Appel d'API à partir de gestionnaires d'interruption de bas niveau Un gestionnaire d'interruption de bas niveau
ne peut utiliser que les fonctionnalités Nucleus RTOS suivantes:

 NU_Activate_HISR() NU_Local_Control_Interrupts() NU_Current_HISR_Pointer() NU_Current_Task_Pointer() NU_Retrieve_Clock() 

Appels de service API à partir de gestionnaires d'interruption de haut niveau Les gestionnaires d'interruption de
haut niveau ont accès à la plupart des fonctions Nucleus RTOS, à l'exception des fonctions à pause automatique, puisqu'un gestionnaire d'interruption de haut niveau ne peut pas suspendre la fonction Nucleus RTOS, le paramètre doit toujours être NU_NO_SUSPEND .

Le prochain article de cette série couvrira les procédures d'initialisation et de démarrage de Nucleus SE.

À propos de l'auteur:Colin Walls travaille dans l'industrie électronique depuis plus de trente ans, passant la plupart de son temps sur le firmware. 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/fr458770/


All Articles