Fabrication industrielle
Internet des objets industriel | Matériaux industriels | Entretien et réparation d'équipement | Programmation industrielle |
home  MfgRobots >> Fabrication industrielle >  >> Industrial Internet of Things >> Embarqué

Sémaphores :introduction et services de base


Voir la série RTOS Revealed

Les sémaphores ont été introduits dans un article précédent. Leur utilisation principale est le contrôle d'accès aux ressources.

Utilisation de sémaphores

Dans Nucleus SE, les sémaphores sont configurés au moment de la construction. Il peut y avoir un maximum de 16 sémaphores configurés pour une application. Si aucun sémaphore n'est configuré, aucune structure de données ou code d'appel de service appartenant aux sémaphores n'est inclus dans l'application.

Un sémaphore est simplement un compteur de type U8 , dont l'accès est contrôlé afin qu'il puisse être utilisé en toute sécurité par plusieurs tâches. Une tâche peut décrémenter (obtenir) un sémaphore et l'incrémenter (libérer). Essayer d'obtenir un sémaphore ayant la valeur zéro 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.

Configuration des sémaphores

Nombre de sémaphores

Comme pour la plupart des aspects de Nucleus SE, la configuration des sémaphores est principalement contrôlée par #define déclarations dans nuse_config.h . Le paramètre de clé est NUSE_SEMAPHORE_NUMBER , qui détermine le nombre de sémaphores configurés pour l'application. Le paramètre par défaut est 0 (c'est-à-dire qu'aucun sémaphore n'est utilisé) 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) entraînant une #erreur déclaration en cours de compilation.

Le choix d'une valeur non nulle est la « validation principale » pour les sémaphores. Il en résulte que certaines structures de données sont définies et dimensionnées en conséquence, dont plus loin dans cet 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 sémaphores, ce sont :

NUSE_SEMAPHORE_OBTAIN
NUSE_SEMAPHORE_RELEASE
NUSE_SEMAPHORE_RESET
NUSE_SEMAPHORE_INFORMATION
NUSE_SEMAPHORE_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 sémaphores 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 nuse_config.h par défaut fichier.

#define NUSE_SEMAPHORE_NUMBER 0 /* Nombre de sémaphores dans le système - 0-16 */#define NUSE_SEMAPHORE_OBTAIN FALSE /* Service call enabler */#define NUSE_SEMAPHORE_RELEASE FALSE /* Service call enabler */#define NUSE_SEMAPHORE /* Service RESET FALSE activateur d'appel */#define NUSE_SEMAPHORE_INFORMATION FALSE /* activateur d'appel de service */#define NUSE_SEMAPHORE_COUNT FALSE /* activateur d'appel de service */

Une erreur de compilation se produira si une fonction API de sémaphore est activée et qu'aucun sémaphore n'est configuré (sauf pour NUSE_Semaphore_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.

Appels de service Sémaphore

Nucleus RTOS prend en charge huit appels de service qui appartiennent aux sémaphores, qui fournissent les fonctionnalités suivantes :

  • Obtenir un sémaphore. Implémenté par NUSE_Semaphore_Obtain() dans Nucleus SE.

  • Lâche un sémaphore. Implémenté par NUSE_Semaphore_Release() dans Nucleus SE.

  • Restaurer un sémaphore à l'état inutilisé, sans aucune tâche suspendue (reset). Implémenté par NUSE_Semaphore_Reset() dans Nucleus SE.

  • Fournir des informations sur un sémaphore spécifié. Implémenté par NUSE_Semaphore_Information() dans Nucleus SE.

  • Renvoyer le nombre de sémaphores (actuellement) configurés pour l'application. Implémenté par NUSE_Semaphore_Count() dans Nucleus SE.

  • Ajouter un nouveau sémaphore à l'application (créer). Non implémenté dans Nucleus SE.

  • Supprimer un sémaphore de l'application (supprimer). Non implémenté dans Nucleus SE.

  • Renvoyer des pointeurs vers tous les sémaphores (actuellement) dans l'application. 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'obtention et de publication des sémaphores

Les opérations fondamentales, qui peuvent être effectuées sur un sémaphore, sont l'obtention (décrémentation) et la libération (incrémentation) de celui-ci. Nucleus RTOS et Nucleus SE fournissent chacun deux appels d'API de base pour ces opérations, qui seront abordés ici.

Obtenir un sémaphore

L'appel de l'API Nucleus RTOS pour obtenir un sémaphore 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'obtenir un sémaphore qui a actuellement la valeur zéro. 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é.

Appel API Nucleus RTOS pour l'obtention d'un sémaphore

Prototype d'appel de service :

STATUT NU_Obtain_Semaphore(NU_SEMAPHORE *sémaphore,
                           UNSIGNÉ suspendre );

Paramètres :

sémaphore – pointeur vers le bloc de contrôle de sémaphore fourni par l'utilisateur

suspendre – 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_UNAVAILABLE – le sémaphore avait la valeur zéro

NU_INVALID_SEMAPHORE – le pointeur du sémaphore est invalide

NU_INVALID_SUSPEND – la suspension a été tentée à partir d'une non-tâche

NU_SEMAPHORE_WAS_RESET – le sémaphore a été réinitialisé alors que la tâche était suspendue

Appel API Nucleus SE pour l'obtention d'un sémaphore

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

Prototype d'appel de service :

STATUT NUSE_Semaphore_Obtain(NUSE_SEMAPHORE sémaphore,
                             U8 suspend );

Paramètres :

sémaphore – l'index (ID) du sémaphore à utiliser

suspendre – 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_UNAVAILABLE – le sémaphore avait la valeur zéro

NUSE_INVALID_SEMAPHORE – l'index sémaphore est invalide

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_SEMAPHORE_WAS_RESET – le sémaphore a été réinitialisé alors que la tâche était suspendue

Implémentation de Nucleus SE pour obtenir un sémaphore

L'essentiel du code du NUSE_Semaphore_Obtain() 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é, la logique de cet appel API est assez simple :

if (NUSE_Semaphore_Counter[semaphore] !=0) /* sémaphore disponible */{ NUSE_Semaphore_Counter[semaphore]--; return_value =NUSE_SUCCESS;}else /* sémaphore indisponible */{ return_value =NUSE_UNAVAILABLE;}

La valeur du sémaphore est testée et, si non nulle, décrémentée.

Lorsque le blocage est activé, la logique devient plus complexe :

do{ if (NUSE_Semaphore_Counter[semaphore] !=0) /* sémaphore disponible */ { NUSE_Semaphore_Counter[semaphore]--; return_value =NUSE_SUCCESS; suspendre =NUSE_NO_SUSPEND ; } else /* sémaphore indisponible */ { if (suspend ==NUSE_NO_SUSPEND) { return_value =NUSE_UNAVAILABLE; } else { /* bloquer la tâche */ NUSE_Semaphore_Blocking_Count[semaphore]++; NUSE_Suspend_Task(NUSE_Task_Active, sémaphore <<4) | NUSE_SEMAPHORE_SUSPEND); return_value =NUSE_Task_Blocking_Return[NUSE_Task_Active] ; if (valeur_retour !=NUSE_SUCCESS) { suspend =NUSE_NO_SUSPEND; } } }} while (suspend ==NUSE_SUSPEND);

Quelques explications du code peuvent être utiles :

Le code est entouré d'un do…while boucle, qui continue pendant que le paramètre suspend a la valeur NUSE_SUSPEND .

Si le sémaphore est différent de zéro, il est décrémenté. Le suspendre la variable est définie sur NUSE_NO_SUSPEND et l'appel d'API se termine avec NUSE_SUCCESS .

Si le sémaphore est à zéro et suspend est défini sur NUSE_NO_SUSPEND , l'appel d'API se termine avec NUSE_UNAVAILBLE . 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 que le sémaphore a été libéré (par opposition à une réinitialisation du sémaphore) le code revient en haut.

Lâcher un sémaphore

L'appel de l'API Nucleus RTOS pour libérer un sémaphore est assez simple; le sémaphore est incrémenté et le succès signalé. Nucleus SE fournit le même service, sauf qu'un contrôle de débordement est effectué.

Appel d'API Nucleus RTOS pour la libération d'un sémaphore

Prototype d'appel de service :

STATUT NU_Release_Semaphore(NU_SEMAPHORE *sémaphore);

Paramètres :

sémaphore – pointeur vers le bloc de contrôle de sémaphore fourni par l'utilisateur

Retours :

NU_SUCCESS – l'appel s'est terminé avec succès

NU_INVALID_SEMAPHORE – le pointeur du sémaphore est invalide

Appel API Nucleus SE pour libérer un sémaphore

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

Prototype d'appel de service :

STATUS NUSE_Semaphore_Release(NUSE_SEMAPHORE sémaphore);

Paramètres :

sémaphore – l'index (ID) du sémaphore à libérer

Retours :

NUSE_SUCCESS – l'appel s'est terminé avec succès

NUSE_INVALID_SEMAPHORE – l'index sémaphore est invalide

NUSE_UNAVAILABLE – le sémaphore a la valeur 255 et ne peut pas être incrémenté

Implémentation Nucleus SE du sémaphore de libération

Le code initial du NUSE_Semaphore_Release() La fonction API - après vérification des paramètres - est commune, que le blocage des tâches soit activé ou non. La valeur du sémaphore est vérifiée et, si elle est inférieure à 255, décrémentée.

Un code supplémentaire est sélectionné par compilation conditionnelle, si la prise en charge du blocage (suspension des tâches) des appels d'API est activée :

NUSE_CS_Enter();if (NUSE_Semaphore_Counter[semaphore] <255){ NUSE_Semaphore_Counter[semaphore]++; return_value =NUSE_SUCCESS; #if NUSE_BLOCKING_ENABLE if (NUSE_Semaphore_Blocking_Count[semaphore] !=0) { U8 index; /* vérifie si une tâche est bloquée */ /* sur ce sémaphore */ NUSE_Semaphore_Blocking_Count[semaphore]--; for (index=0; index 

Si des tâches sont suspendues sur ce sémaphore, la première est réveillée.

Le prochain article couvrira quelques appels d'API supplémentaires associés aux groupes d'indicateurs d'événement, ainsi que les structures de données pertinentes.


Colin Walls a plus de trente ans d'expérience dans l'industrie électronique, en grande partie dédiée aux logiciels embarqués. Conférencier fréquent lors de conférences et de séminaires et auteur de nombreux articles techniques et de deux livres sur les logiciels embarqués, Colin est un technologue en logiciels embarqués chez Mentor Embedded [la Mentor Graphics Embedded Software Division], et est basé au Royaume-Uni. Son blog habituel se trouve à l'adresse :http://blogs.mentor.com/colinwalls. Il peut être contacté par e-mail à [email protected]


Embarqué

  1. Une introduction aux serrures à came et à leur fonctionnement
  2. Une introduction aux vis à œil et à leur fonctionnement
  3. Une introduction à l'acier inoxydable et à sa fabrication
  4. Entrée et sortie de base C#
  5. Qu'est-ce qu'un rédacteur de service automobile et que fait-il ?
  6. Boîtes aux lettres :présentation et services de base
  7. Sémaphores :services utilitaires et structures de données
  8. Groupes d'indicateurs d'événement :services publics et structures de données
  9. Groupes d'indicateurs d'événement :introduction et services de base