I am going through datasheet of AVR2560V. In page 65 , table 12-1, it says that AVR2560 has 3 mode for watchdog
Interrupt mode - WDE = 0, WDIE = 1
Reset Mode - WDE = 1, WDIE = 0
Both - WDE = 1, WDIE = 1
This means if we want to use watchdog timer as source of Interrupt, then i should disable WDE. Am i right? Because when i disabling WDE in code, Watchdog timer is getting disabled.I had look at this link also and even he is doing the same. WDE
make sense that it need to be enabled, just that table in the datasheet is confusing me. Can anyone please help me in clearing out this doubt.
Below is the Watchdog_init function which i am using.
Watchdog_init(){
MCUSR &= ~(1<<WDRF);
WDTCSR |= (1<<WDCE) | (1<<WDE); // as per datasheet WDE should be 0?
// timeout in 8 second
WDTCSR = 1<<WDP0 | 1<<WDP3;
// watchdog interrupt enabler
WDTCSR |= _BV(WDIE);
}
2 Answers 2
You have multiple writes to WDTCSR:
- Set WDCE and WDE, leaving the rest garbage
- Set WDP0 and WDP3, and clear the rest
- Set some other bits according to the _BV macro, leaving the rest as they were
So your step 1 is getting wiped out by step 2.
I'd suggest combining all three into a single assignment.
This means if we want to use watchdog timer as source of Interrupt, then i should disable WDE. Am I right?
Correct - WDE should not be set if you want to use WD in interrupt mode.
Because when i disabling WDE in code, Watchdog timer is getting disabled.
This is not correct. WDE
stands for Watchdog System Reset Enable
. The Watchdog timer is actually always running no matter what. The WDE
and the WDIE
bits only determine what what happens when the timer hits the timeout.
Your code for setting up WD interrupt mode is basically correct, except...
- It is good practice to turn off interrupts while changing the
WDTCSR
because if an int happened in between the time when you enable changes and tried to actual make the change, then more than 4 cycles would have elapsed and the change would fail. It is slightly more efficient to set all the bits in
WDTCSR
at once.Watchdog_init() { // Just to be safe since we can not clear WDE if WDRF is set MCUSR &= ~(1<<WDRF); // disable interrupts so we do not get interrupted while doing timed sequence cli() // First step of timed sequence, we have 4 cycles after this to make changes to WDE and WD timeout WDTCSR |= (1<<WDCE) | (1<<WDE); // timeout in 8 second, disable reset mode. Must be done in one operation WDTCSR = 1<<WDP0 | 1<<WDP3; // enable global interrupts sei(); // enable watchdog interrupt only mode WDTCSR |= _BV(WDIE);
}
Other things to check:
- Make sure global interrupts are enabled or else the interrupts will happen but will not run your handler.
- Make sure that the WDTON fuse is not programmed or else you can not use interrupt mode.