Volatile ou pas volatile? [Résolu]

Bonjour,

J’ai un bug que je n’arrive pas à comprendre et je me pose des questions sur l’usage de volatile. Ai-je juste dans le cas ou j’ai une fonction loop et une fonction ISR qui ne réactive pas les interruptions:

Cas 1: la variable n’est utilisée que dans loop → volatile est inutile
Cas 2: la variable n’est utilisée que dans l’ISR → volatile est inutile
Cas 3: la variable est utilisée dans loop et dans ISR et est modifiée au moins dans ISR → volatile indispensable
Cas 4: la variable est utilisée dans loop et dans ISR et est modifiée uniquement dans loop → volatile est inutile. correction: c’et indispensable!

C’est surtout le cas 4 qui me préoccupe, et sur lequel j’ai des doutes. J’ai un bug qui pourrait s’expliquer si volatile est utile. J’ai l’impression que ma variable garde d’une fois sur l’autre dans l’ISR sa valeur même si loop l’a changée. Mais est-ce possible?

Je n’arrive pas vraiment à comprendre le bug, car pour suivre mon programme j’ai mis des digitalWriteFast qui ont pour effet parfois de supprimer le bug. Le fait de passer de non volatie à volatile rajoute du temps, et suffit peut être à masquer le bug.

Dans quel cas une variable non volatile modifiée dans loop et seulement lue dans une ISR, peut elle mal lue dans l’ISR?

Si une variable est utilisée dans la loop et non déclarée volatile elle peut être conservée dans un registre et donc dans l’ISR vous n’êtes pas sûr de lire la dernière valeur.

Volatile va non seulement obliger d’aller lire la case mémoire associée à la variable mais aussi à l’écrire à chaque fois,

De plus volatile ne suffit pas sur une architecture 8 bits pour des variables occupant plus d’un octet. Murphy va faire que l’interruption arrivera en plein milieu de l’écriture des octets en mémoire et l’ISR lira une valeur incongrue… donc pour les variables à plusieurs octets, pour garantir l’atomicité, il faut passer en section critique (bloquer les IRQ) quand on les lit ou quand on les écrit.

Merci, dit comme ça c’est une évidence. Pourquoi cela fait si longtemps que je bug???

Faut que je vérifie effectivement que je n’ai pas de variable multi-octets que j’utilise des deux côtés.

Je comprends mieux qui est Jackson et qui ne l’est pas.

On peut utiliser une même variable sous forme volatile ou non avec la double déclaration:

  byte variableNonVolatile;
  volatile byte &variableVolatile (variableNonVolatile);

Pour une variable qui est utilisée à la fois dans loop et dans l’ISR, on doit pouvoir utiliser la forme volatile pour loop et la forme non volatile dans l’ISR. Non?
Cela permet à l’ISR de la garder dans un registre. De toutes façon elle doit être forcément écrite avant la fin de l’ISR. Sauf si le compilateur pouvait réserver des registres que pour l’ISR.

Si le code est court et qu’il y a des registres non utilisés le compilateur pourrait conserver un registre pour une variable, rien ne l’interdit…

La référence en elle même ne peut être volatile mais elle référence un objet volatile donc même combat

Pour les pointeurs la spec dit

Any attempt to read or write to an object whose type is volatile-qualified through a non-volatile lvalue results in undefined behavior:

Donc faut pas avoir un pointeur vers une variable volatile pour y accéder

Merci, je passe tout en volatile. Faut dire aussi que si il y aura un problème je ne sais pas quand il aura lieu. C’est d’ailleurs par hasard que j’ai pu voir le bug.

oui c’est plus raisonnable, dès que l’on a une variable qui apparaît à la fois dans l’interruption et le code principal il ne faut pas se poser de question (si ce n’est sur la taille pour mettre une zone critique en plus)

au fait - il y a maintenant un bouton pour marquer résolu → choisissez la réponse que vous voulez mettre en avant et clickez sur le bouton “solution”

Compliqué, c’est plusieurs messages qui donnent plusieurs réponses à plusieurs questions…

Ok (bla bla bla - 3 caractères obligatoires)

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.