J'ai un problème lorsque l'exécution d'une séquence de surveillance désactivée sur un AVR ATtiny84A réinitialise réellement la puce, même si la minuterie doit disposer de suffisamment de temps. Cela se produit de manière incohérente et lorsque vous exécutez le même code sur de nombreuses parties physiques. certains réinitialisent à chaque fois, d'autres parfois, et d'autres jamais.
Pour démontrer le problème, j'ai écrit un programme simple qui ...
- Active le chien de garde en 1 seconde
- Réinitialise le chien de garde
- Fait clignoter la LED blanche pendant 0,1 seconde
- La LED blanche s'est éteinte pendant 0,1 seconde
- Désactive le chien de garde
Le temps total entre l'activation et la désactivation du chien de garde est inférieur à 0,3 seconde. Cependant, une réinitialisation du chien de garde se produit parfois lorsque la séquence de désactivation est exécutée.
Voici le code:
#define F_CPU 1000000 // Name used by delay.h. We are running 1Mhz (default fuses)
#include <avr/io.h>
#include <util/delay.h>
#include <avr/wdt.h>
// White LED connected to pin 8 - PA5
#define WHITE_LED_PORT PORTA
#define WHITE_LED_DDR DDRA
#define WHITE_LED_BIT 5
// Red LED connected to pin 7 - PA6
#define RED_LED_PORT PORTA
#define RED_LED_DDR DDRA
#define RED_LED_BIT 6
int main(void)
{
// Set LED pins to output mode
RED_LED_DDR |= _BV(RED_LED_BIT);
WHITE_LED_DDR |= _BV(WHITE_LED_BIT);
// Are we coming out of a watchdog reset?
// WDRF: Watchdog Reset Flag
// This bit is set if a watchdog reset occurs. The bit is reset by a Power-on Reset, or by writing a
// logic zero to the flag
if (MCUSR & _BV(WDRF) ) {
// We should never get here!
// Light the RED led to show it happened
RED_LED_PORT |= _BV(RED_LED_BIT);
MCUCR = 0; // Clear the flag for next time
}
while(1)
{
// Enable a 1 second watchdog
wdt_enable( WDTO_1S );
wdt_reset(); // Not necessary since the enable macro does it, but just to be 100% sure
// Flash white LED for 0.1 second just so we know it is running
WHITE_LED_PORT |= _BV(WHITE_LED_BIT);
_delay_ms(100);
WHITE_LED_PORT &= ~_BV(WHITE_LED_BIT);
_delay_ms(100);
// Ok, when we get here, it has only been about 0.2 seconds since we reset the watchdog.
wdt_disable(); // Turn off the watchdog with plenty of time to spare.
}
}
Au démarrage, le programme vérifie si la réinitialisation précédente a été provoquée par un délai d'attente du chien de garde et, le cas échéant, allume le voyant rouge et efface l'indicateur de réinitialisation du chien de garde pour indiquer qu'une réinitialisation du chien de garde s'est produite. Je crois que ce code ne doit jamais être exécuté et que le voyant rouge ne doit jamais s'allumer, mais c'est souvent le cas.
Qu'est-ce qui se passe ici?