simavr icon indicating copy to clipboard operation
simavr copied to clipboard

WDIE is wronly cleared on interrupt in Interrupt Mode

Open WGH- opened this issue 4 years ago • 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.

https://github.com/buserror/simavr/blob/a56b550872906a971ac128002772d90c9e30377d/simavr/sim/avr_watchdog.c#L172-L188

I think I'll submit a PR (unless someone does that first) once I get access to hardware to double-check the tests on.

WGH- avatar Jul 19 '21 03:07 WGH-

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 avatar Dec 10 '21 01:12 lcgamboa

@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?

WGH- avatar Dec 10 '21 01:12 WGH-

Yes, I tested some examples from the Arduino_freeRTOS library and they all worked after the fix you suggested.

lcgamboa avatar Dec 10 '21 01:12 lcgamboa

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();
    }
}

itopaloglu83 avatar Dec 10 '21 19:12 itopaloglu83