Tengo un problema al ejecutar una secuencia de vigilancia deshabilitada en un AVR ATtiny84A en realidad está restableciendo el chip incluso aunque el temporizador debería tener un montón de tiempo en él. Esto sucede de manera inconsistente y cuando se ejecuta el mismo código en muchas partes físicas; algunos se reinician cada vez, algunos se reinician a veces y otros nunca.
Para demostrar el problema, he escrito un programa simple que ...
- Habilita el watchdog con un tiempo de espera de 1 segundo
- Restablece el perro guardián
- Enciende el LED blanco durante 0.1 segundos
- Apagó el LED blanco durante 0.1 segundos
- Deshabilita el perro guardián
El tiempo total entre la habilitación y la inhabilitación del watchdog es inferior a 0,3 segundos, aunque a veces se produce un reinicio del watchdog cuando se ejecuta la secuencia de inhabilitación.
Aquí está el código:
#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.
}
}
Al inicio, el programa verifica si el reinicio anterior fue causado por un tiempo de espera de vigilancia, y si es así, enciende el LED rojo y borra el indicador de reinicio de vigilancia para indicar que ocurrió un reinicio de vigilancia. Creo que este código nunca debería ejecutarse y el LED rojo nunca debería encenderse, aunque a menudo lo hace.
¿Qué está pasando aquí?