volatile

Description :

volatile est un mot-clé appelé qualificatif de variable , il est généralement utilisé avant le type de données d’une variable, pour modifier la manière dont le compilateur et le programme suivant traitent la variable.

La déclaration d’une variable volatile est une directive au compilateur. Le compilateur est un logiciel qui traduit votre code C/C++ en code machine, qui sont les véritables instructions pour la puce Atmega dans l’Arduino.

Plus précisément, il ordonne au compilateur de charger la variable depuis la RAM et non depuis un registre de stockage, qui est un emplacement de mémoire temporaire où les variables du programme sont stockées et manipulées. Dans certaines conditions, la valeur d’une variable stockée dans des registres peut être inexacte.

Une variable doit être déclarée volatile chaque fois que sa valeur peut être modifiée par quelque chose hors du contrôle de la section de code dans laquelle elle apparaît, comme un thread s’exécutant simultanément. Dans l’Arduino, le seul endroit où cela est susceptible de se produire est dans les sections de code associées aux interruptions, appelées routine de service d’interruption.

int ou long volatiles :

Si la volatile variable est plus grande qu’un octet (par exemple un entier 16 bits ou une longueur 32 bits), alors le microcontrôleur ne peut pas la lire en une seule étape, car il s’agit d’un microcontrôleur 8 bits. Cela signifie que pendant que votre section de code principale (par exemple votre boucle) lit les 8 premiers bits de la variable, l’interruption peut déjà changer les 8 derniers bits. Cela produira des valeurs aléatoires pour la variable.

Remède:

Pendant que la variable est lue, les interruptions doivent être désactivées, afin qu’elles ne puissent pas perturber les bits pendant qu’elles sont lues. Il y a plusieurs moyens de le faire:

  1. noInterrupts
  2. utilisez la macro ATOMIC_BLOCK. Les opérations atomiques sont des opérations MCU uniques – la plus petite unité possible.

 

Exemple de code :

Le volatile modificateur garantit que les modifications apportées à la variable state  sont immédiatement visibles dans loop() . Sans le modificateur volatile , la variable state peut être chargée dans un registre lors de l’entrée dans la fonction et ne serait plus mise à jour jusqu’à la fin de la fonction.

// Clignote la LED pendant 1 s si l'entrée a changé
// dans la seconde précédente.

volatile byte changed = 0;

void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
  attachInterrupt(digitalPinToInterrupt(2), toggle, CHANGE);
}

void loop() {
  if (changed == 1) {
    // toggle() a été appelé à partir d'interruptions !

    // Réinitialiser changé à 0
    changed = 0;

    // LED clignotante pendant 200 ms
    digitalWrite(LED_BUILTIN, HIGH);
    delay(200);
    digitalWrite(LED_BUILTIN, LOW);
  }
}

void toggle() {
  changed = 1;
}

 

Pour accéder à une variable dont la taille est supérieure au bus de données 8 bits du microcontrôleur, utilisez la macro ATOMIC_BLOCK. La macro garantit que la variable est lue dans une opération atomique, c’est-à-dire que son contenu ne peut pas être modifié pendant sa lecture.

#include <util/atomic.h> // cette bibliothèque comprend la macro ATOMIC_BLOCK.
volatile int input_from_interrupt;

// Quelque part dans le code, e.g. à l'intérieur du loop()
  ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
    // code avec interruptions bloquées (les opérations atomiques consécutives ne seront pas interrompues)
    int result = input_from_interrupt;
  }

 


 

Source : https://www.arduino.cc/reference/en/language/variables/variable-scope-qualifiers/volatile/

 

Laisser un commentaire