<< The Fribotte Homepage >>
Un club de passionnés en robotique participant à la coupe de France E=M6.
[Accueil] [Qui sommes-nous ?] [Robots] [Coupe e=m6] [BD Technique] [Forum] [Reportages] [Liens] [WiKiFri]

Fribotte

 

La Programmation des pics
par Bigonoff
Premiere partie - pic 16f84 - Révision 5

Téléchargement des fichiers originels ici
Publié le 27/02/2002

15. Le watchdog

Index coursIndex du cours
Chapitre précédent14. Les accès en mémoire " eeprom " (Suite)
Chapitre suivant16. Le mode Sleep

 

15. Le watchdog

Le watchdog, ou chien de garde est un mécanisme de protection de votre programme. Il sert à surveiller si celui-ci s’exécute toujours dans l’espace et dans le temps que vous lui avez attribués.

15.1 Le principe de fonctionnement

La mise en service ou l’arrêt du watchdog se décide au moment de la programmation de votre PIC, à l’aide de la directive _CONFIG. Si vous précisez le paramètre " _WDT_OFF " est précisé, le watchdog ne sera pas en service. Si au contraire vous précisez " _WDT_ON ", le watchdog sera actif.

IL N’EST DONC PAS POSSIBLE DE METTRE EN OU HORS SERVICE LE WATCHDOG DURANT L’EXECUTION DE VOTRE PROGRAMME.

Le fonctionnement du watchdog est lié à un timer interne spécifique, qui n’est pas synchronisé au programme, ni à un événement extérieur. La durée spécifique de débordement de ce timer est approximativement de 18ms. Cette valeur est à prendre avec précaution, car elle varie en fonction de différents paramètres comme la tension d’alimentation ou la température. La valeur minimale de 7ms est celle que vous devrez utiliser dans la pratique.

Chaque fois que l’instruction clrwdt est envoyé à la PIC, le timer du watchdog est remis à 0, ainsi que la valeur contenue dans son prédiviseur. Si par accident cette instruction n’est pas reçue dans le délai prévu, la PIC est redémarrée à l’adresse 0x00 et le bit TO du registre STATUS est mis à 0. En lisant ce bit au démarrage, vous avez donc la possibilité de détecter si la PIC vient d’être mise sous tension, ou si ce démarrage est du à un " plantage " de votre programme.

15.2 Le prédiviseur et le watchdog

Nous avons vu dans les leçons précédentes que le prédiviseur pouvait être affecté au tmr0 ou au watchdog, via le bit PSA du registre OPTION. Si nous décidons de mettre le prédiviseur sur le watchdog (PSA = 1) , le tableau de la page 16 nous donnera les valeurs du prédiviseur obtenues suivant les bits PS0/PS2. En réalité, pour le watchdog, il s’agit d’un postdiviseur, mais cela ne concerne que l’électronique interne de la PIC. Vous n’avez pas à vous tracasser pour cette différence.

Ce prédiviseur multiplie le temps de débordement du timer du watchdog. Par exemple, avec un prédiviseur de 2, vous obtenez un temps minimal de 7ms*2 = 14ms. Donc, avec un quartz de 4MHz, cela vous oblige à envoyer l’instruction clrwdt au moins une fois tous les 14.000 cycles d'instructions. Dans la plupart des cas, le reset s'effectuera en réalité après 18ms*2 = 36ms, soit 36.000 cycles d’instructions.

15.3 Les rôles du watchdog

Le watchdog est destiné à vérifier que votre programme ne s’est pas " égaré " dans une zone non valide de votre programme (parasite sur l’alimentation par exemple), ou s’il n’est pas bloqué dans une boucle sans fin (bug du programme). Il sert également à réveiller une PIC placée en mode " sleep ", ce que nous verrons plus tard.

15.4 Utilisation correcte du watchdog

La première chose à faire, si vous désirez profiter de cette protection intégrée, est de paramètrer la _CONFIG pour la mise en service du watchdog. La première chose à constater, c’est que si vous indiquez " _WDT_ON " pour un programme qui ne gère pas le watchdog, celui-ci redémarrera sans arrêt, et donc ne fonctionnera pas, car il ne contiendra aucune instruction " clrwdt ".

C’est une erreur fréquente pour ceux qui ne maîtrisent pas les bits de configuration de leur programmateur. Les bits de configurations indiqués dans le fichier sont en effet modifiables sur la plupart des softs de programmation, qui sont capables de forcer une valeur de _CONFIG différente de celle prévue par le concepteur du logiciel. 

Ensuite, vous devez placer une ou plusieurs instructions " clrwdt " dans votre programme en vous arrangeant pour qu’une instruction " clrwdt " soit reçue dans les délais requis par votre PIC. A ce propos, ne tenez pas compte du temps nominal de 18ms, mais plutôt du temps de la situation la plus défavorable. Ce temps est de minimum 7ms. En prenant ce temps comme temps maximum autorisé, vous êtes certain que vote programme fonctionnera dans toutes les conditions.

15.5 Ce qu’il ne faut pas faire

Souvenez-vous qu’une interruption interrompt le programme et branche à l’adresse 0x04. Une fois l’interruption terminée, le programme est reconnecté à l’endroit où il se trouvait, même si c’est hors de votre zone normale de programme.

Donc, si vous placez une instruction " clrwdt " dans une routine d’interruption, cette instruction risque de s’exécuter même si votre programme est planté. C’est donc le contraire du but recherché. En conséquence :

IL NE FAUT JAMAIS UTILISER L’INSTRUCTION CLRWDT DANS UNE ROUTINE D’INTERRUPTION.

15.6 Mesure du temps réel du watchdog

Effectuez un copier/coller de votre fichier " Led_cli.asm ". Renommez ce fichier en " wdt.asm " et créez un nouveau projet. [ NDLR : Fichiers exemples ici ]

Dans un premier temps, ne touchez pas à la _CONFIG

Modifiez la valeur du registres OPTION

OPTIONVAL EQU B'10001111' ; Valeur registre option
      ; Résistance pull-up OFF
      ; préscaler Wdt = 128

Ensuite, supprimez la variable cmpt3 et modifiez la routine tempo pour enlever la boucle extérieure.

;*********************************************************************
; SOUS-ROUTINE DE TEMPORISATION
;*********************************************************************
;--------------------------------------------------------------------------------------------------------
; Cette sous-routine introduit un retard de 250ms.
; Elle ne reçoit aucun paramètre et n'en retourne aucun
;--------------------------------------------------------------------------------------------------------
tempo      
  clrf cmpt2 ; effacer compteur2
boucle2      
  clrf cmpt1 ; effacer compteur1
boucle1      
  nop   ; perdre 1 cycle
  decfsz cmpt1 , f ; décrémenter compteur1
  goto boucle1 ; si pas 0, boucler
  decfsz cmpt2 , f ; si 0, décrémenter compteur 2
  goto boucle2 ; si cmpt2 pas 0, recommencer boucle1
  return   ; retour de la sous-routine

Ajoutons la ligne :

  clrwdt   ; effacer watchdog

Juste après l’étiquette init pour être bien sûr de remettre le watchdog à 0 (en réalité, inutile).

Modifions pour finir le programme principal pour qu’il allume la LED après 250ms :

;*********************************************************************
; PROGRAMME PRINCIPAL
;*********************************************************************
start      
  call tempo ; on attends 250ms
  bsf LED ; allumer la LED
loop      
  goto loop ; on reste ici
       
  END   ; directive fin de programme

Compilez le programme, chargez-le dans votre PIC, et alimentez votre platine.

Que se passe-t-il ? Et bien, après approximativement ¼ seconde, la LED s’allume, et c’est tout. C’est bien ce que nous avions prévu.

Modifiez maintenant la ligne _CONFIG pour mettre le watchdog en service :

  __CONFIG _CP_OFF & _WDT_ON & _PWRTE_ON & _HS_OSC

Recompilez votre programme, et rechargez-le dans votre PIC. Alimentez votre montage.

Que se passe-t-il ? Et bien maintenant la LED clignote. Vous constaterez probablement que le temps séparant deux extinctions (ou deux allumages) est approximativement 2secondes.

Explication

Et bien, notre watchdog n’a pas été remis à zéro depuis le démarrage de la PIC. Donc, une fois le temps : " durée de base * prédiviseur " atteint, un reset est provoqué qui entraîne une extinction de la LED et un redémarrage sans fin du cycle.

Pour connaître la base de temps de notre watchdog personnel dans les circonstances actuelles de tension et de température, nous devons donc diviser le temps entre 2 extinctions (ou allumage) par le prédiviseur, c’est à dire 128.

Personnellement, j’ai chronométré 2,2 secondes. Donc, mon watchdog travaille avec un temps de base de : 2200ms / 128 = 17,2 ms. On est donc bien dans les environs des 18ms typiques annoncées.

15.7 Simulation du plantage d’un programme

Effectuez de nouveau une copie de votre fichier " Led_cli.asm" et renommez cette copie " secur.asm ". Créez un nouveau projet.

Changez la ligne de configuration :

OPTIONVAL EQU H'000F' ; Valeur registre option
      ; Résistance pull-up ON
      ; préscaler Wdt = 128

et le DEFINE (vu que nous avons modifié notre platine)

#DEFINE BOUTON PORTB,0 ; bouton-poussoir

Modifiez ensuite votre programme principal :

start      
  bsf LED ; allumer la LED
  call tempo ; appeler la tempo de 0.5s
  bcf LED ; éteindre LED (LED OFF)
  call tempo ; appeler la tempo de 0.5s
  btfsc BOUTON ; tester bouton-poussoir
  goto start ; pas pressé, boucler
plante      
  goto plante ; le programme n'est pas sensé
      ; arriver ici
      ; simulation de plantage
  END   ; directive fin de programme

De cette manière, une pression du bouton-poussoir envoie le programme dans une zone que nous avons créée et qui simule un plantage du programme sous forme d’une boucle sans fin.

Compilez le programme et chargez-le dans votre PIC. Alimentez le montage : la LED clignote.

Maintenez un instant le bouton-poussoir enfoncé, la LED s’arrête de clignoter, le programme est dans une boucle sans fin qui simule dans notre cas le plantage suite, par exemple, à un parasite qui a éjecté notre programme hors de sa zone de fonctionnement normal.

15.7.1 Correction avec utilisation du watchdog

Modifions maintenant notre programme. Tout d’abord, nous mettons le watchdog en service, comme vu précédemment dans la _CONFIG. Nous allons ensuite nous arranger pour remettre notre watchdog à 0 à intervalles réguliers.

Voici donc notre programme principal modifié :

start      
  bsf LED ; allumer la LED
  clrwdt   ; effacer watchdog
  call tempo ; appeler la tempo de 0.5s
  bcf LED ; éteindre LED (LED OFF)
  clrwdt   ; effacer watchdog
  call tempo ; appeler la tempo de 0.5s
  btfsc BOUTON ; tester bouton-poussoir
  goto start ; pas pressé, boucler
plante      
  goto plante ; le programme n'est pas sensé
      ; arriver ici
      ; simulation de plantage
  END   ; directive fin de programme

Nous avions programmé notre watchdog avec un prédiviseur de 128, ce qui nous impose d’envoyer une commande clrwdt toutes les 7*128 ms, soit toutes les 896ms. Comme l’appel à notre tempo prend 500ms, nous devrons donc envoyer clrwdt avant ou après chaque appel de tempo, pour ne pas dépasser ce temps.

Nous aurions pu, au lieu de ces 2 instructions, utiliser un seul " clrwdt " dans la sous-routine " tempo ".

Recompilons notre programme, et rechargeons la PIC. Lançons l’alimentation. La LED clignote toujours.

Pressez le bouton quelques instants, la LED s’arrête de clignoter un instant, puis recommence de nouveau. La watchdog a récupéré le plantage de votre programme.

15.8 Choix de la valeur du prédiviseur

En général, il faut essayer de calculer le prédiviseur de façon à ne pas devoir placer de commande clrwdt en de trop nombreux endroits.

Il faut également tenir compte du temps de réaction obtenu en augmentant le prédiviseur. Si une récupération de plantage en 2 secondes vous convient ou si votre programme nécessite une récupération en 18ms max conditionnera la valeur du prédiviseur à utiliser. Tout est donc histoire de compromis.

Vous n’aurez cependant pas toujours le choix. Si votre prédiviseur est déjà occupé pour le timer0, par exemple, il ne vous restera pas d’autres choix que d’envoyer une commande clrwdt toutes les 7ms.

Dans le cas présent, vous auriez du placer une instruction de ce type au cœur de la routine de temporisation, car celle-ci dure plus de 7ms.

Rappelez-vous de ne pas utiliser cette instruction dans une routine d’interruption, car cela est contraire au principe même du watchdog (sauf cas très spéciaux). Vous pouvez par contre utiliser clrwdt dans une sous-routine sans aucun problème.

15.9 Temps typique, minimal, et maximum

Nous avons vu apparaître plusieurs notions de temps de watchdog. Il est important de bien effectuer la distinction entre les différentes valeurs :

  • Le temps typique (18ms) est le temps que met EN GENERAL le watchdog pour provoquer le reset de votre programme en cas de plantage. C'est donc le " temps de réaction " normal (ou typique) du watchdog
  • Le temps minimal (7ms), c'est le délai maximum dont vous disposez entre 2 instructions " clrwdt " pour éviter un reset de votre programme non désiré.
  • Le temps maximum (33ms), c'est le temps de réaction du watchdog dans le cas le plus défavorable en fonction du composant et des conditions d'utilisation. Microchip vous garantit ici que le reset s'effectuera au maximum en 33 ms.
15.10 Conclusion

Vous êtes maintenant en mesure de créer des programmes résistants aux plantages classiques, pour peu que vous utilisiez judicieusement le watchdog.

En général, il est préférable de faire l’effort de l’utiliser, car le surplus de travail est négligeable en contrepartie de la sécurité de fonctionnement obtenue.

ATTENTION : Le watchdog utilisé en protection dans le cas d'une programmation correcte et d'une carte bien conçue ne devrait jamais entrer en fonctionnement. Il n'agira donc en général que dans de très rares occasions (parasites violents, orage). Il ne doit pas servir à masquer une erreur de conception de votre programme. Celui-ci doit pouvoir fonctionner sans le secours du watchdog (vérifiez en le mettant hors-service durant vos essais).
 

 

Index cours
Index du cours
Chapitre précédent
14. Les accès en mémoire " eeprom " (Suite)
Chapitre suivant
16. Le mode Sleep

 


Complétez cette page, posez vos questions et remarques ici : WiKiFri

Page http://fribotte.free.fr/bdtech/cours/pic16f84/PART1_cours15.html modifiée le 14/10/2002.
Copyright fribotte@free.fr, libre de droit pour toute utilisation non commerciale.
Reproduction autorisée par simple mail