Watchdog timer

Hi,

I think it's not possible to use Watchdog timer on Arduino Duo (with Arduino framework), regarding data sheet (17.4, p.268):

"The Watchdog Mode Register (WDT_MR) can be written only once. Only a processor reset
resets it. Writing the WDT_MR register reloads the timer with the newly programmed mode
parameters."

and watchdog is disabled at startup in init() function:

"// Disable watchdog
WDT_Disable(WDT);"

This makes it impossible to turn it again. It would be nice to have possibility to turn it on, for now it's some limitation here.

Regards

Hi,
I think it would be possible, but you have to modify init() in
arduino-1.5.2\hardware\arduino\sam\variants\arduino_due_x\variant.cpp
replacing instruction WDT_Disable(WDT); by somes calls to fonctions of wdt.c in
arduino-1.5.2\hardware\arduino\sam\system\libsam\source\wdt.c

May be the most easy would be to skip instruction WDT_Disable(WDT); and configure watchdog at the beginning your setup().
According to comment at the beginning of wdt.c you have 16 seconds to perform this configuration. Would it be enough for reprogramming the Due in order to modify your sketch?

Personally, I am not the valiant enough to try it :astonished:

See the following topic: http://arduino.cc/forum/index.php/topic,152885.0.html

Kind Regards.

First, it is necessary to comment line 353 of file variant.cpp in subdirectory *arduino-1.5.2\hardware\arduino\sam\variants\arduino_due_x*

  // Disable watchdog
  // WDT_Disable(WDT);

Second, insert at the beginning of the loop() function a call to function WDT_Restart() in order to restart the watchdog' timer each time the loop is executed.
An example:

int waitTime = 0;

void setup()
{
  Serial.begin( 9600 );
}

void loop()
{
  // Restart watchdog
  WDT_Restart( WDT );
  Serial.print( "Following function last " );
  Serial.print( waitTime );
  Serial.println( " seconds" );
  delay( waitTime * 1000 );
  waitTime ++;
}

By default, watchdog period is set to its maximum value, 16 seconds.
So, when variable waitTime reach the value of 16, watchdog' counter reach 0 before the delay() function finish and a reset occurs.

Optionally, you can reduce the period of the watchdog with a call to WDT_Enable(). This function modify the Watchdog Timer Mode Register. This can be done only once after reset and the maximum value 4096 is equivalent to 4096 / 256 = 16 seconds.
In the following example, the variable waitTime would never reach a value higher than 5:

int waitTime = 0;

void setup()
{
  // Variable wdp_ms hold the periode in 256 th of seconds of watchdog
  // It must be greater than 3 et less or equal to 4096
  // The following value set a periode of 4,5 seconds (256 x 4,5 = 1152)
  uint32_t wdp_ms = 1152 ;
  WDT_Enable( WDT, 0x2000 | wdp_ms | ( wdp_ms << 16 ));
  Serial.begin( 9600 );
}

void loop()
{
  // Restart watchdog
  WDT_Restart( WDT );
  Serial.print( "Following function last " );
  Serial.print( waitTime );
  Serial.println( " seconds" );
  delay( waitTime * 1000 );
  waitTime ++;
}

On the other hand, once you have modified the file variant.cpp, you have to insert a call to WDT_Disable() at the beginning of your sketches than don't use the watchdog:

void setup()
{
  // Disable watchdog
  WDT_Disable( WDT );
  ....
}

gallegojm nice explanation :wink:

THANKS xD GREAT POST

Guys, I'm having a problem of my due sometimes freezing, (guess due to I2C hardware). I'm intended to use the watchdog timer in order to restart my controller. The problem, is that it seems that the latest version of Arduino IDE at :
C:\Users\SLAVA\AppData\Local\Arduino15\packages\arduino\hardware\sam\1.6.9\variants
the variants.cpp is changed and there is no line that disables the watchdog, I'm trying to use WOD_Enable() like this:

void init( void )
{
SystemInit();
//======================================================================
//EDITED REGION
WDT_Enable( WDT );

But it seems not to give any result, is the procedure of enabling the watchdog the same in current version of Arduino ?

I guess I just cant find where the watchdog is being disabled now.

Hello slawa92,

In the 1.6.7 version this is the code I use to enable watchdog, and I guess it works for later versions :

#define WDT_KEY (0xA5)
/********************************************************************************
  extern "C" void _watchdogDefaultSetup (void) { WDT_Disable (WDT); }

  void watchdogSetup (void) __attribute__ ((weak, alias("_watchdogDefaultSetup")));
*********************************************************************************/

/*This function is called from init(). If the user does not provide
  this function, then the default action is to disable watchdog.
  This function has to be overriden, otherwise watchdog won't work !! */

void watchdogSetup(void) {
  /*** watchdogDisable (); ***/
}



void setup()
{
  // Enable watchdog.
  WDT->WDT_MR = WDT_MR_WDD(0xFFF)
                | WDT_MR_WDRPROC
                | WDT_MR_WDRSTEN
                | WDT_MR_WDV(256 * 2); // Watchdog triggers a reset after 2 seconds if underflow
                                       // 2 seconds equal 84000000 * 2 = 168000000 clock cycles
  /* Slow clock is running at 32.768 kHz
    watchdog frequency is therefore 32768 / 128 = 256 Hz
    WDV holds the periode in 256 th of seconds  */

  Serial.begin(250000);
  uint32_t status = (RSTC->RSTC_SR & RSTC_SR_RSTTYP_Msk) >> 8; // Get status from the last Reset
  Serial.print("RSTTYP = 0b"); Serial.println(status, BIN);  // Should be 0b010 after first watchdog reset
}

void loop()
{

  //Restart watchdog
  WDT->WDT_CR = WDT_CR_KEY(WDT_KEY)
                | WDT_CR_WDRSTT;

  Serial.println("Enter the main loop : Restart watchdog");
  delay(500);

  while (true)
  {
    Serial.println("the software becomes trapped in a deadlock !");
    delay(500);
    /* If the software becomes trapped in a deadlock,
       watchdog triggers a reset and software restarts with stored values
       in General Purpose Back up Registers*/
  }
}