Problema con el temporizador de vigilancia - AVR ATmega324PA

Estaba usando ATmega32A antes y ahora estoy migrando a ATmega324PA solo para mejorar la administración de energía. Ahora estoy probando el nuevo controlador en todos los aspectos. Este es un código simple para verificar el temporizador de vigilancia, pero sigue reiniciando el controlador.

Código:

int main(void)
{
  uart_init();
  PORTA|=(1<<PORTA1);
  _delay_ms(1500);
  PORTA&=~(1<<PORTA1);
  _delay_ms(2000);
  uart_array("FFFFFFFFFFFFFFFFFF");
  wdt_enable(WDTO_2S);
  _delay_ms(5000);
}

void uart_init()
{
 /*set PinA1 as output for LED*/
 DDRA|=(1<<1);

 /*set PinD3 as output for UART*/
 DDRD|=(1<<3);

 /*set pinD2 as input for UART*/
 DDRD&=~(1<<2);

 /*enabling TX and RX*/
 UCSR1B |=(1<<TXEN1) | (1<<RXEN1);

 /*asynchronous mode selection*/
 UCSR1C&=~(1<<UMSEL11);
 UCSR1C&=~(1<<UMSEL10);

 /*setting data format to 8 bit*/
 UCSR1B &=~(1<<UCSZ12);
 UCSR1C|=(1<<UCSZ11)|(1<<UCSZ10);

 /* setting one bit as stop bit*/
 UCSR1C &=~(1<<USBS1);

 /*Disabling parity*/
 UCSR1C &= ~((1<<UPM11) | (1<<UPM10));

 /* loading 8 LSB to UBRRL*/
 UBRR1L = UBRRL_VALUE;

 /* loading 4 MSB to UBRRH*/
 UBRR1H = UBRRH_VALUE;
}

El código funciona bien por primera vez, pero después de eso, el LED sigue parpadeando.

Nota: el bit de fusible de vigilancia (WDTON) está deshabilitado.

Respuestas (2)

Sí, eso se debe a que después de que se dispara el perro guardián, debe restablecer el indicador correspondiente antes de que main comience de nuevo (hay un registro donde puede leer qué causó el reinicio) y desactivar el perro guardián para que no se dispare una y otra vez.

Este código solucionará su problema:

    // This function is called upon a HARDWARE RESET:
void reset(void) __attribute__((naked)) __attribute__((section(".init3")));

/*! Clear SREG_I on hardware reset. */
void reset(void)
{
     cli();
    // Note that for newer devices (any AVR that has the option to also
    // generate WDT interrupts), the watchdog timer remains active even
    // after a system reset (except a power-on condition), using the fastest
    // prescaler value (approximately 15 ms). It is therefore required
    // to turn off the watchdog early during program startup.
    MCUSR = 0; // clear reset flags
    wdt_disable();
}

Esta .init3cosa es una sección de código especial donde puede poner el código que se ejecuta antes de que se inicie la principal. Aquí hay un enlace que lo describe, pero no debe preocuparse demasiado por eso, el código anterior funcionará bien cuando se coloque en el archivo main.c.

Funcionó sin agregar cosas .init3... Muchas gracias
¿Qué quieres decir, sin cosas de inicio? ¿Acabas de poner el código al principio de main? Si es así, eso es un poco inseguro, ya que no sabe cuánto tiempo llevará ingresar a main (hay algunos otros inicios que hacen algo antes de main), por lo que es mejor que lo ponga lo más adelante posible. Esto asegura que no obtenga un comportamiento inesperado.
Después de wdt_enable, verifiqué el valor de interrupción del perro guardián. Solo ha sido deshabilitado. Entonces, ¿de dónde vino el reinicio continuo?
¿A qué te refieres con el valor de interrupción de wdt? De todos modos: el perro guardián permanece habilitado después de un reinicio de wdt, ¡pero el tiempo después del cual se activará se establece en 15 ms! Por lo tanto, debe desactivarlo muy rápido, de lo contrario, se activará una y otra vez. Entonces, el camino a seguir es deshabilitarlo antes de main y habilitarlo como desee que funcione en main.

Más allá de los consejos de funciones anteriores reset(), debe deshabilitar el perro guardián en el gestor de arranque (si se usa, por supuesto). Hay/había, por ejemplo, un error conocido del gestor de arranque Arduino original que no deshabilitó el perro guardián.