[TUTO] Utiliser le watchdog de l'Arduino Due

Les cartes Arduino, les platines

[TUTO] Utiliser le watchdog de l'Arduino Due

Message non lude gallegojm » Mar 12 Mar 2013 23:41

Le watchdog est un mécanisme implanté dans les microprocesseurs pour éviter qu'un système ne reste gelé après un plantage du software.
On considère que le software « plante » si celui-ci ne repasse pas par un certain point avant un délai pré-établi.
En cas de plantage, on redémarre le microprocesseur et (facultativement) le reste du système, ce qui est préférable à un système qui reste inopérant.
Avec les Arduinos antérieurs au Due, il était délicat d'utiliser le watchdog, pourtant présent dans les microprocesseurs Atmega, sans modifier le bootloader des platines.
Ce n'est plus le cas avec l'Arduino Due et son microprocesseur SAM3X.
Voici un petit tuto en 6 étapes pour vous initier à l'utilisation du watchdog

Etape 1

Chargez et exécutez le sketch suivant :
Code: Tout sélectionner
void setup()
{
  Serial.begin( 9600 );
}

void loop()
{
  Serial.println( millis() );
}

Ouvrez la console de l'IDE et regardez-la pendant au moins 20 secondes. Le temps nécessaire pour vous convaincre de toute la beauté de ce programme... qui nous indique scrupuleusement depuis combien de millisecondes il s'exécute.

Etape 2

Sauvegardez le sketch précédant
Fermez l'IDE
Ouvrez, avec votre éditeur préféré (j'utilise Notepad++) le fichier variant.cpp qui se trouve dans le répertoire arduino-1.5.2\hardware\arduino\sam\variants\arduino_due_x\
Commentez la ligne 353:
Code: Tout sélectionner
  // Disable watchdog
  // WDT_Disable(WDT);

Sauvez le fichier et redémarrez l'IDE
Chargez de nouveau le sketch précédant dans l'Arduino Due et ouvrez la console. Regardez de nouveau le résultat pendant une vingtaine de secondes...
Chaque fois que le nombre de millisecondes approche 18000, celui-ci repart à zéro. Que se passe-t-il ?
D'une part, l'instruction que nous avons supprimée appartient au code exécuté au démarrage du microprocesseur, avant même l'exécution de la fonction init() de notre sketch.
D'autre part, le reste de l'explication est dans le fichier wdt.c (celui-ci se trouve dans le répertoire arduino-1.5.2\hardware\arduino\sam\system\libsam\source\) ou, en plus complet, dans le manuel du SAM3X, à la page 267 http://www.atmel.com/Images/doc11057.pdf
Nous avons supprimé l'appel à la fonction qui invalide le watchdog. Donc c'est sa configuration après le reset du microprocesseur qui est active : le watchdog est alors actif et sa période est fixée au maximum, soit FFF hexa = 4096 coups d'horloge cadencée à 32768 / 128. Soit théoriquement 16 secondes exactes (la différence entre la théorie et la pratique a une explication que nous verrons plus tard).
Donc, si rien n'est fait pour réinitialiser le compteur du watchdog avant qu'il n'arrive à zéro, un reset se produit et notre programme s'exécute à nouveau depuis le début

Etape 3

Il est donc nécessaire de réinitialiser périodiquement le compteur du watchdog . En général, il suffit d'un appel à la fonction WDT_Restart() au début de la fonction loop()
Code: Tout sélectionner
void setup()
{
  Serial.begin( 9600 );
}

void loop()
{
  WDT_Restart( WDT );
  Serial.println( millis() );
}

Ce programme donne le même résultat que celui de l'étape 1

Etape 4

On peut vouloir diminuer la période au bout de laquelle le watchdog émet un reset. Par exemple lorsqu'on ne peut se permettre qu'un système reste planté pendant les 16 secondes de la configuration par défault. Il faut bien sûr vérifier qu'on est capable d'insérer dans la ou les différentes boucle du programme des appels à la fonction WDT_Restart() dans des délais inférieurs à une certaine valeur.
Une fois cette valeur connue, il faut modifier le registre Watchdog Timer Mode Register du microprocesseur (détails de ce registre à la page 272 du manuel)
Pour des raisons de sécurité, on ne peut modifier qu'une seule fois ce registre après un reset.
Donc cette modification se fait dans la fonction setup()
Voici un exemple :
Code: Tout sélectionner
void setup()
{
  // La variable wdp_ms renseigne la période en 256 ième de seconde du watchdog
  // Elle doit être supérieur à 3 et inférieur ou égal à 4096
  // La valeur suivante correspond à une période de 1 seconde
  uint32_t wdp_ms = 256 ;
  WDT_Enable( WDT, 0x2000 | wdp_ms | ( wdp_ms << 16 ));
  Serial.begin( 9600 );
}

void loop()
{
  //WDT_Restart( WDT );
  Serial.println( millis() );
}

Le nombre de millisecondes affichés dans la console ne devrait pas dépassé 1000 (en pratique le reset s'effectue après 1077 avec ma platine).

Etape 5

Peut-être travaillez-vous sur plusieurs sketchs. Pour certains vous utilisez le watchdog, pour d'autres non.
Pour ne pas avoir à modifier continuellement le fichier variant.cpp et être obligé de redémarrer l'IDE, insérez un appel à la fonction WDT_Disable() en début de setup() dans les sketchs qui n'utilisent pas le watchdog.
Code: Tout sélectionner
void setup()
{
  WDT_Disable( WDT );
  Serial.begin( 9600 );
  .....
}

void loop()
{
  .....
}


Etape 6

Un dernier exemple :
Code: Tout sélectionner
int delai = 0;

void setup()
{
  // Période du watchdog fixée à 4,5 secondes
  uint32_t wdp_ms = 1152 ;  // = 256 x 4,5
  WDT_Enable( WDT, 0x2000 | wdp_ms | ( wdp_ms << 16 ));
  Serial.begin( 9600 );
}

void loop()
{
  // Réinitialisation du watchdog
  WDT_Restart( WDT );
  Serial.print( "La fonction suivante s'exécute en " );
  Serial.print( delai );
  Serial.println( " secondes" );
  delay( delai * 1000 );
  delai ++;
}

Lorsque la valeur de la variable delai atteint 5, le compteur du watchdog atteint 0 avant d'être réinitialisé par un nouvel appel à WDT_Restart() puisque la boucle dure plus de 4,5 secondes.
gallegojm
 
Messages: 33
Inscription: Jeu 13 Sep 2012 15:23

Retourner vers Arduino

Qui est en ligne

Utilisateurs parcourant ce forum: Aucun utilisateur enregistré et 3 invités

cron