Le chien de garde (Watchdog Timer)

Le STM32WB55 est équipé d’un circuit appelé chien de garde indépendant (abrégé par IDWG pour « Independant Watchdog ») qui fait office de compteur-à-rebours autonome. On fixe sa valeur maximum de départ et on le démarre.
Une fois lancé l’IDWG décompte les microsecondes, de façon totalement indépendante du programme en cours d’exécution, jusqu’à atteindre la valeur zéro. Il force alors un « reset » du microcontrôleur. Il est possible d’interrompre et relancer le décompte de l’IDWG à partir de sa valeur maximum à tout moment, depuis le programme utilisateur, et d’empêcher ce reset.
On comprend l’intérêt de ce périphérique : si le programme utilisateur est « planté » (à cause d’un bug, d’un capteur défaillant, d’un module Wi-Fi qui ne se connecte pas, etc.) alors il ne « rechargera » pas l’IDWG avant la fin de son décompte, et l’IDWG forcera le système à redémarrer.
L’IDWG est implémenté dans l’API MicroPython, mais il est désigné par le terme Watchdog Timer. Ce tutoriel explique donc comment mettre en oeuvre le watchdog timer en MicroPython.

Matériel requis

La carte NUCLEO-WB55. Nous ferons clignoter la LED 1, bleue :

LEDS

Le code MicroPython

Le script présenté ci-après est disponible dans la zone de téléchargement.

Le programme présenté ci-après montre le fonctionnement du Watchdog Timer. Celui-ci est programmé pour être “nourri” toutes les 2 secondes. La boucle principale “fait un tour” toutes les secondes, faisant clignoter la LED bleue de la NUCLEO-WB55. Une routine d’interruption permet de retarder cette boucle de 2 secondes après 5 appuis successifs sur le bouton SW1. Le temps d’exécution de la boucle devient alors supérieur au temps de vie du Watchdog Timer, qui va en conséquence redémarrer (RESET software) la NUCLEO-WB55.

Éditez le script main.py contenu dans le répertoire du disque USB virtuel associé à la NUCLEO-WB55 : PYBFLASH.

# Objet du script :
# Démonstration du Watchdog Timer 
# Référence : https://docs.micropython.org/en/latest/library/machine.WDT.html
# Après 5 appuis sur le bouton SW1, le script sde met en pause pendant une durée
# qui dépasse le seuil de redémarrage imposé par le watchdog.

import pyb # pour les accès aux périphériques (GPIO, LED, etc.)
from time import sleep_ms # pour faire des pauses système

# Variable globale qui compte les appuis sur le bouton
cnt = 0

# Initialisation du bouton SW1
sw1 = pyb.Pin('SW1')
sw1.init(pyb.Pin.IN, pyb.Pin.PULL_UP, af=-1)

# Fonction de service de l'interruption pour SW1 (incrémente cnt)
def Press(line):
	global cnt
	cnt += 1

# On attache une routine de service d'interruptionà SW1
irq_1 = pyb.ExtInt(sw1, pyb.ExtInt.IRQ_FALLING, pyb.Pin.PULL_UP, Press)

# Initialisation de la LED bleue
led_bleue = pyb.LED(3) # sérigraphiée LED1 sur le PCB

# Temps d'attente (ms) avant de changer l'état de la LED
DELAY_LED = const(500)

# Temps d'attente (ms) avant que le watchdog ne rédémarre la NUCLEO-WB55
WDT_TIMEOUT = const(2000)

# Pour gérer le watchdog
from machine import WDT

# On démarre le watchdog
wdt = WDT(timeout = WDT_TIMEOUT)

while True:
	
	# On "recharge" le watchdog pour WDT_TIMEOUT millisecondes
	wdt.feed()

	if cnt == 5:
		print("Pause pendant %d secondes" %( WDT_TIMEOUT // 1000 ))
		cnt = 0
		sleep_ms(WDT_TIMEOUT)

	led_bleue.on() # Allume la LED
	sleep_ms(DELAY_LED) # Attends delai secondes

	led_bleue.off() # Eteint la LED
	sleep_ms(DELAY_LED) # Attends delai secondes

Vous pouvez lancer le script avec Ctrl + D sur le terminal PuTTY et observer que la LED clignote à une fréquence de 1 Hz (un cycle allumée - éteinte par seconde). Si vous appuyez ensuite 5 fois sur SW1, le message “Pause pendant 2 secondes” s’affiche sur votre terminal, puis vous serez déconnecté de celui-ci suite au RESET généré par la Wachdog. Vous constaterez que la LED bleue recommence à clignoter, ce qui signie que le programme contenu dans *main.py** a bien été relancé malgré la perte de la connexion série avec l’USB user.