WDIE is wronly cleared on interrupt in Interrupt Mode
WGH- opened this issue · 4 comments
WDIE
should be only cleared in "Interrupt and System Reset Mode".
The fix is to add && avr_regbit_get(avr, p->wde)
condition.
simavr/simavr/sim/avr_watchdog.c
Lines 172 to 188 in a56b550
I think I'll submit a PR (unless someone does that first) once I get access to hardware to double-check the tests on.
Hi @WGH-
I have applied your fix suggestion to my simavr fork and now I can use WDT and Arduino_freeRTOS without any problems.
I recommend you do a PR. Thanks for the info.
@lcgamboa just to clarify, Arduino_freeRTOS depends on the correct behaviour of WDIE
auto-clearing, doesn't work correctly on simavr, and my suggested change fixes it?
Yes, I tested some examples from the Arduino_freeRTOS library and they all worked after the fix you suggested.
I was having issues with the watchdog timer interrupts and I'm glad to find this issue. Here's a simple example code for testing purposes. it uses the watchdog timer to blink an LED.
The watchdog timer interrupt only works once and then stops. I updated the interrupt clearing line with the following line of code as an interim solution.
Current: WDTCSR |= (1 << WDIF);
Temporary Solution: WDTCSR |= (1 << WDIE) | (1 << WDIF);
#include <avr/io.h>
#include <avr/wdt.h>
#include <avr/interrupt.h>
ISR(WDT_vect)
{
// Clear interrupt flag by writing 1 to it.
WDTCSR |= (1 << WDIF);
// Toggle LED.
PORTB ^= _BV(PB5);
}
int main()
{
// Set LED as output.
DDRB |= _BV(DDB5);
// Enable watchdog timer.
WDTCSR |= (1 << WDCE) | (1 << WDE);
WDTCSR = (1 << WDIE);
// Toggle LED.
PORTB ^= _BV(PB5);
// Enable global interrupts.
sei();
// Loop forever.
while (1)
{
_NOP();
}
}