Je n'ai regardé que cet aspect là, je n'ai pas regardé le reste... A moins que je ne me trompe sur le séquencement des tâches ne connaissant pas l'environnement, mais la fonction callback1 est appelée par la routine d'interruption (ISR).
Tes variables tapCounter et elapsedTime sont modifiées en même temps dans le main et dans l'interruption, ça fera un bug aléatoire en fonction de l'instant quand tombe ton interruption par rapport à l'exécution de ton main.
Dans l'embarqué, ce genre d'erreur ne pardonne pas (on appelle ça une erreur de débutant chez les vieux barbus de l'embarqué) mais c'est une erreur habituelle et même une inattention est vite arrivée!
Une petite explication pour ceux qui ne trouve pas celà évident au premier abord
Il faut toujours masquer les interruptions qui vont bien avant de modifier une variable partagée entre les fonctions appelées par le main et les fonctions appelées par les routines d'interruptions.
En généralisant, il faut toujours masquer les interruptions ou utiliser les services de l'os qui vont bien (sémaphores, mutex, ou autres) lorsqu'on modifie ou lorsqu'on accède à des variables partagées par des thread différents.
Un bug méchant mais qui ne semble pas évident au premier abord: sur un micro-contrôleur 8 bits, l'accès en lecture d'une variable 32 bits accédée en lecture simple par le main (même avec une variable 16 bits, ça bug aussi)
est buguée (si! si! je l'ai eut testé)! Pourquoi?
Parce que la comparaison d'un 32 bits par un micro 8 bits se fait en plusieurs coups d'horloge (la connaissance de l'assembleur aidant pour lire le code généré). Il suffit (non pas d'un signe, un matin, même s'il est tout tranquille... ) mais que l'interruption 'claque' en plein milieu de l'exécution de ces instructions, le test peut être faux et ta variable peut ne pas être remise à 0.
Il faut écrire la fonction main de la façon suivante:
Et même la fonction que je te propose peut être fausse si l'opération dans l'interruption est plus complexe et que le test dans la fonction main est aussi plus complexe. Dans ce genre de cas, il vaudrait mieux masquer les interruptions avant l'accès:
# Un bug d'accès de variables partagées en passant...
Posté par plr . En réponse au journal TapTempo sur STM32F469i-Discovery. Évalué à 3.
Salut,
Je n'ai regardé que cet aspect là, je n'ai pas regardé le reste... A moins que je ne me trompe sur le séquencement des tâches ne connaissant pas l'environnement, mais la fonction
callback1est appelée par la routine d'interruption (ISR).Tes variables
tapCounteretelapsedTimesont modifiées en même temps dans lemainet dans l'interruption, ça fera un bug aléatoire en fonction de l'instant quand tombe ton interruption par rapport à l'exécution de ton main.Dans l'embarqué, ce genre d'erreur ne pardonne pas (on appelle ça une erreur de débutant chez les vieux barbus de l'embarqué) mais c'est une erreur habituelle et même une inattention est vite arrivée!
Une petite explication pour ceux qui ne trouve pas celà évident au premier abord
Il faut toujours masquer les interruptions qui vont bien avant de modifier une variable partagée entre les fonctions appelées par le
mainet les fonctions appelées par les routines d'interruptions.En généralisant, il faut toujours masquer les interruptions ou utiliser les services de l'os qui vont bien (sémaphores, mutex, ou autres) lorsqu'on modifie ou lorsqu'on accède à des variables partagées par des
threaddifférents.Un bug méchant mais qui ne semble pas évident au premier abord: sur un micro-contrôleur 8 bits, l'accès en lecture d'une variable 32 bits accédée en lecture simple par le
main(même avec une variable 16 bits, ça bug aussi)est buguée (si! si! je l'ai eut testé)! Pourquoi?
Parce que la comparaison d'un 32 bits par un micro 8 bits se fait en plusieurs coups d'horloge (la connaissance de l'assembleur aidant pour lire le code généré). Il suffit (non pas d'un signe, un matin, même s'il est tout tranquille... ) mais que l'interruption 'claque' en plein milieu de l'exécution de ces instructions, le test peut être faux et ta variable peut ne pas être remise à 0.
Il faut écrire la fonction main de la façon suivante:
Et même la fonction que je te propose peut être fausse si l'opération dans l'interruption est plus complexe et que le test dans la fonction
mainest aussi plus complexe. Dans ce genre de cas, il vaudrait mieux masquer les interruptions avant l'accès:Ce qui n'est pas sans pouvoir causer des problèmes de temps réel car on masque les interruptions trop longtemps. Mais c'est une autre histoire...
Je viens de voir qu'ils ont implémentés des fonctions noInterrupts() et interrupts() dans l'environnement arduino.