Home > Back-end >  Why watchdog in interrupt mode still causes a reset in the device?
Why watchdog in interrupt mode still causes a reset in the device?

Time:01-10

Environment

I am using an Arduino Mega 2560, here is the source code:

#ifndef F_CPU
#define F_CPU 16000000L
#endif

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/wdt.h>

void start_system_timer(void)
{
    cli();
    
    // Avoid eternal loop of time-out resets by clearing WDRF
    MCUSR &= ~(1<<WDRF);
    // Reset watchdog timer
    wdt_reset();
    // Enable WD timer configuration mode
    WDTCSR |= 1 << WDCE | 1 << WDE;
    // Reset WD timer
    WDTCSR = 0;
    // Configure period
    wdt_enable(WDTO_1S);
    // Use WD timer in interrupt mode 
    WDTCSR |= 1 << WDIE;

    sei();
}

int main(void)
{
    // Define digital pin PORTB7 as an output and turn on the led
    DDRB |= (1<<PB7);
    PORTB |= (1<<PB7);
    
    
    start_system_timer();
    sei();

    while (1)
    {
    }
}

ISR (WDT_vect, ISR_NAKED)
{
    // Turn off LED
    PORTB &= ~(1<<PB7);
    
    // Re-enable watchdog timer interrupt to avoid reset
    WDTCSR |= 1 << WDIE;
    
    reti();
}

Question

If I set watchdog timer to operate in interrupt mode and I don't reset the timer inside the interrupt handler then it resets the board.

According to the datasheet if it is on reset mode it should not go to system reset mode.

enter image description here

Also tried to clear WDIE bit after setting interrupt mode using WDTCSR &= ~(1<<WDIE);, just in case was set to 1 but didnt work either.

CodePudding user response:

I had that problem before. My mistake was setting the WDTON fuse bit. I thought its purpose was to "turn on the watchdog" (Watch Dog Timer On). But in reality, it forces the the timer to interrupt mode, no matter what bits you use in WDE and WDIE. Use a enter image description here

Edit: WDTON written to 1 is disabled 0 is enabled! So you need to write it to 1

Edit2: As AterLux said, refer to this post for using reti().

CodePudding user response:

According to datasheet:

If WDE is set, the Watchdog Timer is in Interrupt and System Reset Mode. The first time-out in the Watchdog Timer will set WDIF. Executing the corresponding interrupt vector will clear WDIE and WDIF automatically by hardware (the Watchdog goes to System Reset Mode).

So after each interrupt changes mode to System Reset Mode and that's why needs to be re-enabled using WDTCSR |= 1 << WDIE;.

  • Related