2

I'm trying to use the watchdog timer to prevent the atmel from being stuck in a loop.

Right now, I have the watchdog timer in System Reset Mode, with a 8sec timer. I reset the timer in every loop while the system is active. But when it goes to sleep, it cannot clear the timer and the whole system resets. Essentially, the system sleeps > System Reset every 8 sec > goes back to sleep.

While this works, I initialize a lot of other hardware with the atmel, and doing it every 8 second seems like a waste of resources.

I want to use the watchdog interrupt somehow only to wake the system up briefly and stop the full system reset. Only if it's truly stuck, it will do a full system reboot. But i'm not sure how the ISR will work or how to reset the timer or toggle.

Here a basic rundown of what I was thinking about.

ISR(wdt_timer)
{
    how to stop the full system reboot?
    how to make the interrupt start again?
}
ISR(button_press)
{
      gotoSleep=0;
}

void watchdog_init()
{
    /* Reset the wdt. */
  wdt_reset(); //from wdt.h

  /* In order to change WDE or the prescaler, we need to
   * set WDCE (This will allow updates for 4 clock cycles).
   */
  WDTCSR |= (1<<WDCE) | (1<<WDE);

  /* set new watchdog timeout prescaler value */
  WDTCSR = 1<<WDP0 | 1<<WDP3; /* 8.0 seconds */

  /* Enable the WD interrupt (note both interrupt and reset). */
  WDTCSR |= (1<<WDIE) | (1<<WDE);
}

void main ()
{
    watchdog_init();
    //and initialize all the other hardware and power supply

    while (true) //no need to step out of this loop
    {
        reset_watchdog();

        //
        //main program
        //

        if(go_to_sleep=1)  //command received through serial
        gotoSleep();  

        //wake up here

    }

}
1
  • I think the way it goes is: at 8 sec-- interrupt triggered, at 16 second --system reset. Correct me if I'm wrong.
    – tsf144
    Sep 17, 2015 at 18:32

1 Answer 1

3

Each time the watchdog interrupt triggers, WDIE is reset. You will need to set it again in the loop if you want to continue capturing the interrupt rather than resetting the system.

Also, consider using <avr/wdt.h> and <avr/sleep.h> to handle (most of) the watchdog and sleep functionality.

EMPTY_INTERRUPT(WDT_vect);

void main ()
{
    watchdog_init();
    set_sleep_mode(SLEEP_MODE_STANDBY);
    //and initialize all the other hardware and power supply

    while (true) //no need to step out of this loop
    {
        wdt_reset()

        //
        //main program
        //

        if(go_to_sleep=1)  //command received through serial
        {
            sleep_enable();
            sleep_cpu();
            sleep_disable();
            WDTCSR |= _BV(WDIE);
        }
    }
}
4
  • the "wdt_reset()" from wdt.h only resets the time, not the WDE or WDIE, right?
    – tsf144
    Sep 17, 2015 at 19:33
  • 1
    It becomes a wdr opcode in the binary. Sep 17, 2015 at 19:34
  • 2
    if(go_to_sleep=1) ? Surely: if(go_to_sleep==1) (I realise it is pseudo-code, but still).
    – Nick Gammon
    Sep 17, 2015 at 21:04
  • @NickGammon: I'm sure it will be fixed once the pseudocode is translated to C. Sep 17, 2015 at 21:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.