0
\$\begingroup\$

I have a running application on the ATmega2560 and it is working OK. Now, I wanted to implement Watchdog feature in order to reset the chip when the application takes longer to operate for some reason.

I am using Visual Studio with Visual Micro extension. And I flash the HEX file via AVRISP mkII.

So, I have simply started with couple of samples found on the net. But, whatever WDT version I used they repeatedly restarted the chip on and on endlessly.

Here is one of them;

#include <avr/wdt.h>

int loop_count = 0;
int wdt_counter = 0;

void setup() {

    Serial.begin(9600);
    Serial.println("Starting up...");
    pinMode(10, OUTPUT);
    digitalWrite(10, HIGH);
    delay(500);
    watchdogStart();
}

void watchdogStart(void)
{
    cli();  // disable all interrupts
    wdt_reset(); // reset the WDT timer
                 /*
                 //WDTCSR configuration:
                 WDIE = 1: //Interrupt Enable
                 WDE = 1 : //Reset Enable
                 WDP3 = 0 :
                 For 2000ms Time-out WDP2 = 1 :
                 For 2000ms Time-out WDP1 = 1 :
                 For 2000ms Time-out WDP0 = 1 :
                 For 2000ms Time-out
                 */
                 // Enter Watchdog Configuration mode:
    WDTCSR |= (1 << WDCE) | (1 << WDE); // Set Watchdog settings:
    WDTCSR = (1 << WDIE) | (0 << WDE) | (0 << WDP3) | (1 << WDP2) | (1 << WDP1) | (1 << WDP0);
    sei();
}

void watchdogArm(void)
{
    cli();  // disable all interrupts
    wdt_reset(); // reset the WDT timer
                 /*
                 //WDTCSR configuration:
                 WDIE = 1: //Interrupt Enable
                 WDE = 1 : //Reset Enable
                 WDP3 = 0 :
                 For 2000ms Time-out WDP2 = 1 :
                 For 2000ms Time-out WDP1 = 1 :
                 For 2000ms Time-out WDP0 = 1 :
                 For 2000ms Time-out
                 */
                 // Enter Watchdog Configuration mode:
    WDTCSR |= (1 << WDCE) | (1 << WDE); // Set Watchdog settings:
    WDTCSR = (1 << WDIE) | (1 << WDE) | (0 << WDP3) | (1 << WDP2) | (1 << WDP1) | (1 << WDP0);
    sei();
}

void loop()
{
    for (int i = 0; i <= loop_count; i++) {
        digitalWrite(10, HIGH);
        delay(100);
        digitalWrite(10, LOW);
        delay(100);
    }
    loop_count++;
    wdt_reset();
    watchdogStart();
    wdt_counter = 0;
    Serial.print(loop_count);
    Serial.print(". Watchdog fed in approx. ");
    Serial.print(loop_count * 200);
    Serial.println(" milliseconds.");
}
/* this is called when the watchdog times out and before the reset */
ISR(WDT_vect) // Watchdog timer interrupt.
{
    if (wdt_counter == 0)
    {
        wdt_counter++;
        watchdogArm();
    }
    // Include your code here - be careful not to use functions they may cause the interrupt to hang and // prevent a reset.
}

Fuses used: Fuses used:

I am about to conclude WDT is not really working with ATmega2560. I would like to hear your opinions and most desirably a reliable working solution sample?

\$\endgroup\$
  • \$\begingroup\$ "am about to conclude WDT is not really working with ATmega2560" - there is nothing wrong with the watchdog timer in the ATmega2560. \$\endgroup\$ – Tom Carpenter Jan 14 at 16:41
  • \$\begingroup\$ By the looks of it, you are using an Arduino. Are you using the Arduino bootloader? If so, that does weird things to the watchdog timer. \$\endgroup\$ – Tom Carpenter Jan 14 at 16:41
  • \$\begingroup\$ Yes, I am using Arduino C++ code and the chip is bare metal on a custom board. After I compiled the code with Visual Studio and the Visual Micro extension, I upload the hex file using Atmel Studio. So, if I am not mistaken, there is no bootloader involvement. Arduino version is 1.8.8. \$\endgroup\$ – Sener Jan 14 at 19:59
2
\$\begingroup\$

Here's a minimal example of using WDT on ATmega2560. Fuses on default (WDTON unprogrammed).

#include <avr/io.h>

int main(void)
{
    if(MCUSR & (1<<WDRF))    // check if reset by wdt
    {
        MCUSR = 0;   // clear flags
        DDRA = 1;    // indicate reset by wdt
        PORTA = 1;
    }

    // enable watchdog system reset
    WDTCSR |= (1<<WDCE) | (1<<WDE);
    // 256K cycles ~ 2 seconds
    WDTCSR = (1<<WDE) | (1<<WDP2) | (1<<WDP1) | (1<<WDP0);

    while(1)
    {
        __asm__ __volatile__ ("wdr");    // feed wdt
    }
    return 0;
}

Comment out line __asm__ __volatile__ ("wdr"); and AVR will be reset by WDT after 2 seconds.

See the datasheet chapter 12.4 Watchdog Timer for more info.

\$\endgroup\$
  • \$\begingroup\$ If I add some lines for debugging (LED on PB7) and run your sample code, It looks work OK. The LED is ON at start and then OFF after 2 seconds. Thank you for the right direction. Now, I like to go back my most important reason to have WDT. When the wdt is not fed for some delay or hang, I like to reset the chip like pressing the reset button. I understand that your sample code is not doing this?! Otherwise my LED should be ON again as it sits on the top of the main part of the program. Do you have any pointers on that? \$\endgroup\$ – Sener Jan 15 at 9:28
  • 1
    \$\begingroup\$ You are probably using some bootloader which has a wait time of longer than 2 seconds and which is not handling correctly reset by WDT. Good bootloader should check WDRF bit and jump directly to application without waiting. If bootloader is not doing so (and waits more than watchdog time-out period), the MCU will be reset again by WDT. Try to increase time-out period to 8 seconds: WDTCSR = (1<<WDE) | (1<<WDP3) | (1<<WDP0); \$\endgroup\$ – user930473 Jan 15 at 17:37
  • \$\begingroup\$ I will check if somehow a bootloader.is used together with the HEX generated. As it is in my knowledge, if you don't use USB way of programming you don't need bootloader and I use bare metal chip and using ICSP to flash the chip. But, so far, you inputs are helpful and proofed me I can have some good WDT on ATmega2560. Thank you. \$\endgroup\$ – Sener Jan 16 at 10:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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