Compréhension du code de fonction lié au sémaphore de tâche uCOS

Insistez sur l'idée du sémaphore de tâche : ① Le sémaphore de tâche n'est qu'un signe. Le succès signifie soustraire la valeur du compteur du sémaphore de 1 ; relâcher signifie ajouter 1 à la valeur du compteur du sémaphore (la valeur du compteur reste inchangée en cas de débordement). ② Pour obtenir le sémaphore, il faut déterminer si le sémaphore est disponible (supérieur à 0). S'il est disponible, cela signifie que l'acquisition sera réussie (les nombres supérieurs à 0 peuvent être décrémentés de 1 ou >= 0), vous pouvez alors obtenir l'horodatage actuel et la dernière version avant. La différence d'horodatage est utilisée comme temps d'attente pour le sémaphore (enregistré dans l'élément SemPendTime dans TCB). ③ Dans la fonction release, parce que la release ne considère pas si le sémaphore de tâche est disponible, la release est une opération pour augmenter le nombre de sémaphores disponibles. Par conséquent, si une série de contrôles de sécurité et de paramètres est normale, cela signifie qu'elle peut être libéré, et vous pouvez l'obtenir à ce moment-là. L'horodatage actuel est utilisé comme horodatage du sémaphore de tâche publié cette fois (enregistré dans l'élément TS du TCB).

Éléments du TCB liés aux sémaphores de tâches :

{

CPU_TS SemPendTime ; Le temps d'attente nécessaire à une tâche pour attendre son propre sémaphore de tâche.

CPU_TS SemPendTimeMax ; Le temps d'attente le plus long pour qu'une tâche attende plusieurs fois le sémaphore de la tâche.

OS_SEM_CTR SemCtr ; valeur du nombre de sémaphores de tâche.

CPU_TS TS ; L'horodatage de la libération/libération du sémaphore de la tâche.

CPU_INT08U SemiID ; ID unique pour les débogueurs et traceurs tiers.

}

OSTaskSemPend : fonction d'acquisition de sémaphore de tâche

{

Idée de fonction : Obtenir le sémaphore de la tâche, c'est obtenir le sémaphore de la tâche elle-même. Si le nombre de ses propres sémaphores est supérieur à 0 (disponibles), il réussira ; sinon, il faut juger s'il est bloqué et s'il faut attendre le sémaphore de tâche.

4 paramètres d'entrée : timeout ; options ; timestamp renvoyé (l'horodatage de la dernière libération du sémaphore de la tâche); type d'erreur renvoyé.

Retour : valeur du nombre de sémaphores de tâches

Processus fonctionnel : ① Tout d'abord, vérifiez la sécurité, les paramètres, les options, etc., et ne peuvent pas être appelés dans les interruptions ; les options incluent OS_OPT_PEND_BLOCKING et OS_OPT_PEND_NON_BLOCKING. ② Si la valeur du nombre de sémaphores de la tâche (OSTCBCurPtr->SemCtr) est supérieure à 0, cela indique que le sémaphore de la tâche est disponible et que le sémaphore peut être obtenu. Le nombre de sémaphores de la tâche est réduit de 1 ; l'horodatage de la dernière version du sémaphore de tâche (OSTCBCurPtr->TS), la différence avec l'horodatage actuel est la dernière heure d'attente du sémaphore de tâche ; et par rapport à OSTCBCurPtr->SemPendTimeMax, la valeur de SemPendTimeMax est mise à jour. ③ Si le sémaphore de la tâche n'est pas disponible, il doit entrer en blocage pour attendre que le sémaphore soit libéré. Si l'utilisateur sélectionne OS_OPT_PEND_NON_BLOCKING et n'attend pas le blocage, alors le type d'erreur qui doit attendre le blocage sera renvoyé et la valeur du nombre de sémaphores renvoyée sera 0. ④ Si le sémaphore n'est pas disponible, mais que vous choisissez d'entrer en blocage. Ensuite, déterminez d'abord si le planificateur est verrouillé. Parce que le planificateur est verrouillé, la tâche ne peut pas être planifiée et, naturellement, le statut de la tâche ne peut pas être modifié . S'il n'y a pas de planificateur de verrouillage, appelez OS_CRITICAL_ENTER_CPU_EXIT() pour verrouiller le planificateur, car l'étape suivante consiste à effectuer une opération de blocage sur la tâche, et l'opération est TCB, qui est une variable globale. En tant que ressource de section critique, elle doit être protégé . Appelez OS_Pend() pour bloquer la tâche. Remarque : Le sémaphore de tâche ici n'est pas un objet du noyau, les paramètres d'entrée de fonction sont donc (OS_PEND_DATA *)0 et (OS_PEND_OBJ *)0. Étant donné que le sémaphore de la tâche n'a pas de liste d'attente, le blocage consiste simplement à appeler OS_TaskBlock() pour supprimer la tâche de la liste prête et l'insérer dans la liste de base de temps.(Si le délai d'attente n'est pas 0). Appelez ensuite OSSched() pour le changement de tâche. ⑤ Atteindre cette étape signifie que le délai d'attente est terminé, a été abandonné ou qu'une tâche a libéré le sémaphore de tâche, que le sémaphore de tâche est disponible et que la tâche a attendu que le sémaphore de tâche soit atteint. De nombreuses situations sont liées à l'état de la tâche, donc le cas de changement est basé sur l'état de la tâche. S'il s'agit de OS_STATUS_PEND_OK, cela signifie attendre normalement le sémaphore de la tâche. Effectuez l'étape ② pour mettre à jour les éléments liés au temps SemPendTime et SemPendTimeMax dans le TCB en attente du sémaphore de la tâche. S'il s'agit de OS_STATUS_PEND_ABORT, cela signifie que l'attente est interrompue et que l'horodatage de la dernière libération du sémaphore de la tâche et le type d'erreur correspondant sont renvoyés. Si le sémaphore OS_STATUS_PEND_TIMEOUT n'est pas attendu dans le délai d'expiration, l'horodatage de la dernière libération du sémaphore de tâche et le type d'erreur correspondant sont renvoyés. ⑥ Enfin, renvoyez la valeur de comptage actuelle du sémaphore de tâche.

}

OSTaskSemPost : fonction de libération du sémaphore de tâche .

{

Bien qu'une tâche ne puisse attendre que son propre sémaphore de tâche, toutes les autres tâches ou interruptions peuvent libérer des sémaphores pour la tâche.

Différents paramètres : Le nombre de paramètres d'entrée de la fonction de libération du sémaphore de tâche est le même que celui du sémaphore du noyau, qui est également de 3. C'est juste que le sémaphore de la tâche est destiné à la tâche, donc le premier paramètre est le pointeur TCB pointant vers la tâche cible , et le sémaphore du noyau est un pointeur vers le sémaphore créé.

Return : Renvoie le nombre de sémaphores de tâches. S'il est appelé depuis un ISR, il sera 0 ; s'il déborde, il retournera également 0 ; de plus, si le paramètre est illégal, il retournera également 0. Par conséquent, si vous effectuez une opération complexe lors de l'implémentation d'une fonction et renvoyez 0 ; ou si l'opération renvoie 0 de manière incorrecte, vous devez déterminer de quelle situation il s'agit par le type d'erreur renvoyé (p_err).

Processus : À l'exception de quelques différences de paramètres, les processus sont similaires aux sémaphores du noyau. ① Obtenez d'abord l'horodatage actuel comme horodatage de la dernière version du sémaphore de tâche. Cet horodatage sera attribué à l'élément TS dans la tâche TCB utilisé pour enregistrer l'horodatage de la sortie du sémaphore de tâche ultérieurement dans p_tcb->TS = ts;. ( Étant donné que le sémaphore de tâche n'est qu'une marque de comptage, tant que la fonction de libération du sémaphore de tâche est appelée, le sémaphore de tâche sera inévitablement libéré lorsqu'une série de contrôles de sécurité et de paramètres sera normal, et la valeur du nombre de sémaphores de tâche augmentera de 1 normalement, ou cela ne changera pas, car l'ajout de 1 débordera. Par conséquent, après avoir vérifié normalement, le code doit obtenir l'horodatage actuel et l'utiliser comme horodatage de la dernière version du sémaphore de tâche) . ② Si la publication différée par interruption est activée et que cette fonction est appelée dans une interruption, appelez OS_IntQPost() pour publier le sémaphore de tâche dans la file d'attente des messages d'interruption. ③ Si vous envoyez une tâche, appelez la fonction OS_TaskSemPost().

--Appelez OS_TaskSemPost() :

{

Processus : Le sémaphore de tâche étant une tâche spécifique, chaque tâche définit uniquement une variable de 32 bits pour compter le sémaphore de tâche, et il n'y a pas de liste d'attente dans la structure du sémaphore du noyau. La tâche est bloquée et n'entre pas sur la liste d'attente. Lorsque nous libérons le sémaphore de tâche, nous déterminons si la tâche attend le sémaphore de tâche en fonction de l'état de la tâche cible pointée par le sémaphore de tâche . Une fois le sémaphore de tâche libéré, le sémaphore de tâche est disponible et d'autres opérations sont similaires : si la tâche est bloquante, débloquez la tâche et la tâche obtient le sémaphore. Si aucune tâche n'est en attente, augmentez le nombre de sémaphores de tâches de 1.

① Si le pointeur du paramètre TCB cible est vide, laissez le TCB cible pointer vers le TCB actuel et libérez le sémaphore de la tâche en cours. ② Si l'état de la tâche n'a pas d'état d'attente (en attente), cela signifie que la tâche cible n'a pas besoin d'obtenir le sémaphore de la tâche pour le moment, ou que le sémaphore de la tâche disponible est suffisant, la tâche cible l'a déjà obtenu, et il n'y a pas besoin d'attendre ; aucune tâche n'attend le sémaphore de la tâche, alors passez sizeof(OS_SEM_CTR), détermine si le sémaphore de la tâche va déborder. S'il déborde, le type d'erreur "OS_ERR_SEM_OVF" sera renvoyé et la tâche la valeur du nombre de sémaphores sera 0 ; sinon, la valeur du nombre de sémaphores de la tâche sera augmentée de 1. ③ Si l'état de la tâche est en attente et que la tâche attend le sémaphore de la tâche, appelez OS_Post() pour envoyer le sémaphore de la tâche à la tâche en attente. Cette fonction insérera la tâche dans la liste prête. Puisque le nombre de tâches dans la liste prête a changé, puis appelez immédiatement pour déterminer si opt sélectionne OS_OPT_POST_NO_SCHED, déterminant ainsi s'il faut appeler OSSched(). ④ Si la tâche est en attente, mais n'attend pas le sémaphore de la tâche, passez à l'étape ②. ⑤ Enfin, renvoyez la valeur actuelle du nombre de sémaphores de tâche.

}

}

おすすめ

転載: blog.csdn.net/m0_43443861/article/details/126373440