DUE Watchdog usage

When trying to use the Watchdog on the DUE, you will come over short to one finding:

As variant.cpp contains the line WDT_Disable(WDT); in its init() function, the watchdog is disabled forever. So you need solutions, to prevent the disabling. I added now the following lines in variants.cpp before the init() function:

void WDT_Init();

#pragma weak WDT_Init
void WDT_Init()
{
  WDT_Disable(WDT);
}

And replaced WDT_Disable(WDT); with *WDT_Init(); * in the init() function.

That is now first hand a neutral solution, but gives you the ability to define a strong version of *WDT_Init(); * in your program. That can either be an empty-function, which leaves the Watchdog configured as from startup, or any other code, which changes the Watchdog to call the ISR WDT_Handler() or change any other settings.

Do I miss something in my thoughts or should this go into the main code?

Just thinking further: To have a much cleaner solution with the right namespaces

void WDT_Init();

should go to wdt.h

#pragma weak WDT_Init
void WDT_Init()
{
  WDT_Disable(WDT);
}

should go to wdt.c

And finally in variant.cpp:

// WDT_Disable(WDT);
WDT_Init(); // add this line instead of WDT_Disable(WDT);

As soon as the function WDT_Init() gets redefined in the application, this strong version will be used and you are free to configure WDT.

Anything I may have forgotten to think about?

Still talking only to myself :frowning:
Comparing the Arduino hardware/arduino/sam/system/libsam/[source|include]/wdt.[c|h]
with the Atmel Framework version of wdt.[c|h]
I see, that Atmel provides already an wdt_init(),

uint32_t wdt_get_timeout_value(uint32_t ul_us, uint32_t ul_sclk);
void wdt_init(Wdt *p_wdt, uint32_t ul_mode, uint16_t us_counter, 
		uint16_t us_delta);
void wdt_disable(Wdt *p_wdt);
void wdt_restart(Wdt *p_wdt);
uint32_t wdt_get_status(Wdt *p_wdt);
uint32_t wdt_get_us_timeout_period(Wdt *p_wdt, uint32_t ul_sclk);

whereas Arduino provides as counterpart WDT_Enable()

extern void WDT_Enable( Wdt* pWDT, uint32_t dwMode ) ;
extern void WDT_Disable( Wdt* pWDT ) ;
extern void WDT_Restart( Wdt* pWDT ) ;
extern uint32_t WDT_GetStatus( Wdt* pWDT ) ;
extern uint32_t WDT_GetPeriod( uint32_t dwMs ) ;

So I think, that the new weak function should be named WDT_Initialze(), to avoid confusion.

Are there any readers here, which work on the that layer of libraries?

Hi!

I just can't make WDT work on my Arduino Due!

Do you have any simple code for testing/verifying that WDT works ?

Thanks in advance!

gogol:
So I think, that the new weak function should be named WDT_Initialze(), to avoid confusion.

Are there any readers here, which work on the that layer of libraries?

I don't, but I think that would be a very useful patch! I'd like to use the watchdog in some code I am doing.

I guess to get it included requires a git pull request and some polite badgering on the Arduino dev list. :slight_smile:

bobcousins:

gogol:
So I think, that the new weak function should be named WDT_Initialze(), to avoid confusion.

Are there any readers here, which work on the that layer of libraries?

I don't, but I think that would be a very useful patch! I'd like to use the watchdog in some code I am doing.

I guess to get it included requires a git pull request and some polite badgering on the Arduino dev list. :slight_smile:

I found the answer here: Reset the Arduino Due board using the watchdog - #3 by system - Arduino Due - Arduino Forum

You have first to edit the variants.cpp file in the Arduino core and comment the line "WDT_disable(WDT);" inside the init function.

Then, you are able to set the WDT again (which can be set only once) using:

#define __WDP_MS 2048 // edit this number accordingly
WDT_Enable ( WDT, 0x2000 | __WDP_MS | ( __WDP_MS << 16 ) );

and the you can call

WDT_Restart( WDT );

somewhere in the loop() function to avoid reboot.

That exactly is the reason, why I am proposing this patch!
If you change variants.cpp by commenting out the WDT_disable(WDT); line, you break the core libraries for many other programs, as the watchdog is always active

If you do that, you have to edit variants.cpp for each program, depending if you need watchdog in your program or not.
The other way would be copying all the files to a second board, how it is done for the DigiX. But that needs twice the space on disk and constant sync of both directories for new versions of the IDE. VERY BAD!!

That exactly was the situation, where I came to the solution for my patch!

Read the entry post of that thread! I replace the line you are disabling with a line calling a new weak function WDT_Initialze(). This function does primarly the same, as the current line and is disabling WDT.

HOWEVER: A weak function can be redefined somewhere through a strong version. When the linker finds a function with the same name, this function will be used instead of the weak one.

That means: Once my patch is included in the CORE files nothing changes at all, as reset is still disabled. So we are backwards compatible.

But as soon, as you are creating a STRONG function WDT_Initialze() in your code, which will call WDT_Enable() instead of WDT_Disable() you can use WDT, where you need.

This workaround is needed, as the ARDUINO-architecture gives you no way, to influence main() before setup() is called.

Thanks gogol!

I will do it as you suggest it. Much better.

Do you know why we can only change WDT status only once per boot ? Is it a design limitation of the SAM3X architecture ?

Thanks again,

gogol:
That exactly is the reason, why I am proposing this patch!
If you change variants.cpp by commenting out the WDT_disable(WDT); line, you break the core libraries for many other programs, as the watchdog is always active

If you do that, you have to edit variants.cpp for each program, depending if you need watchdog in your program or not.
The other way would be copying all the files to a second board, how it is done for the DigiX. But that needs twice the space on disk and constant sync of both directories for new versions of the IDE. VERY BAD!!

That exactly was the situation, where I came to the solution for my patch!

Read the entry post of that thread! I replace the line you are disabling with a line calling a new weak function WDT_Initialze(). This function does primarly the same, as the current line and is disabling WDT.

HOWEVER: A weak function can be redefined somewhere through a strong version. When the linker finds a function with the same name, this function will be used instead of the weak one.

That means: Once my patch is included in the CORE files nothing changes at all, as reset is still disabled. So we are backwards compatible.

But as soon, as you are creating a STRONG function WDT_Initialze() in your code, which will call WDT_Enable() instead of WDT_Disable() you can use WDT, where you need.

This workaround is needed, as the ARDUINO-architecture gives you no way, to influence main() before setup() is called.

Is it a design limitation of the SAM3X architecture ?

Yes, chapter 17.4 of the ATSAM3X8E datasheet says:

After a Processor Reset, the value of WDV is 0xFFF, corresponding to the maximum value of
the counter with the external reset generation enabled (field WDRSTEN at 1 after a Backup
Reset). This means that a default Watchdog is running at reset, i.e., at power-up. The user must
either disable it (by setting the WDDIS bit in WDT_MR) if he does not expect to use it or must
reprogram it to meet the maximum Watchdog period the application requires.
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.

Its always a good thing reading the datasheets of the controllers (even when you understand only 5%). but you might get an idea, what the controller is able to.

Thanks for this, i've created a diff file to apply these changes easy.
But somehow I get a warning if I compile a sketch without the WDT_Initialze function...

variant.cpp.o: In function `init':
C:\Program Files (x86)\Arduino\arduino-1.5.7\hardware\arduino\sam\variants\arduino_due_x/variant.cpp:378: warning: undefined reference to `WDT_Initialze'
--- arduino-1.5.8\hardware\arduino\sam\system\libsam\include\wdt.h	Thu Jan 8 17:33:06 2015 UTC
+++ arduino-1.5.8\hardware\arduino\sam\system\libsam\include\wdt.h	Thu Jan 8 17:33:06 2015 UTC
@@ -66,6 +66,8 @@
 
 extern uint32_t WDT_GetPeriod( uint32_t dwMs ) ;
 
+void WDT_Initialze();
+
 #ifdef __cplusplus
 }
 #endif
--- arduino-1.5.8\hardware\arduino\sam\system\libsam\source\wdt.c	Thu Jan 8 17:33:09 2015 UTC
+++ arduino-1.5.8\hardware\arduino\sam\system\libsam\source\wdt.c	Thu Jan 8 17:33:09 2015 UTC
@@ -130,3 +130,13 @@
     }
     return ((dwMs << 8) / 1000) ;
 }
+
+/**
+* \brief default arduino behaviour -> disable the watchdog.
+* watchdog can be enabled from a sketch
+*/
+#pragma weak WDT_Initialze
+void WDT_Initialze()
+{
+ WDT_Disable(WDT);
+}
--- arduino-1.5.8\hardware\arduino\sam\variants\arduino_due_x\variant.cpp	Thu Jan 8 17:33:14 2015 UTC
+++ arduino-1.5.8\hardware\arduino\sam\variants\arduino_due_x\variant.cpp	Thu Jan 8 17:33:14 2015 UTC
@@ -374,7 +374,8 @@
   }
 
   // Disable watchdog
-  WDT_Disable(WDT);
+  // WDT_Disable(WDT);
+  WDT_Initialze(); // instead of the line above to allow enabling the watchdog from a sketch
 
   // Initialize C library
   __libc_init_array();

I tried it now and the watchdog works perfectly!

gogol:
When trying to use the Watchdog on the DUE, you will come over short to one finding:
As variant.cpp contains the line WDT_Disable(WDT); in its init() function, the watchdog is disabled forever. So you need solutions, to prevent the disabling. I added now the following lines in variants.cpp before the init() function:

void WDT_Init();

#pragma weak WDT_Init
void WDT_Init()
{
  WDT_Disable(WDT);
}




And replaced <strong>*WDT_Disable(WDT);*</strong> with <strong>*WDT_Init(); *</strong> in the init() function.

That is now first hand a neutral solution, but gives you the ability to define a strong version of <strong>*WDT_Init(); *</strong> in your program. That can either be an empty-function, which leaves the Watchdog configured as from startup, or any other code, which changes the Watchdog to call the ISR WDT_Handler() or change any other settings.

Do I miss something in my thoughts or should this go into the main code?

A very nice solution to the problem!

Regards,
Ray L.

I like the idea of an easy call for the WatchDog. Have you considered creating a function

Watchdog.begin()

This would be in-keeping with the "arduino" way and makes it very clear in the code that you intend to start a watch dog timer.

I'd love to have this included so that I can make my µC projects more reliable and able to auto-restart. The ability to have a watchdog timer is quite crucial. Good proposal!

A while ago I created a pull request to get this type of functionality included in the core Add watchdog routines for Due. by bobc · Pull Request #2210 · arduino/Arduino · GitHub. I forget where it got to, I think there was some cosmetic changes required, but otherwise just needs a "push" to get into the core I think.

It's been kinda low on my list of priorities.

Allright, I have been digging for a few weeks so I will not post a stupid question in this topic.

I'm trying to modify a library written by some incompetents for a wireless networking shield - the FT1076M from futura electronics (open-electronics.org store). Those dudes just pretend the Sam3X controllers do not exist and in conclusion the library (MWifi) is written for the older avr architecture. The watchdog handling functions are included in avr/wdt.h. People pay money and are deceived because they lack the proper documentation so I wish to fix this problem.

As I wish to solve this for arduino due, first I would like to compile a sketch with some basic WDT functions.
Bur surprise - I cannot include the sam3x wdt.h because it is nowhere to be found in the include search path. And I am stuck in windows - in BSD it is easy to modify the include path.

Now, I respectfully ask you for help. A sketch has a setup() and a loop() but I see nothing on this post. What are you compiling and what are you including? There is nothing clear. Before the setup, the sketch can include stuff. #include <wdt.h> does not work (unable to locate wdt.h) and the avr/wdt.h is not acceptable because the controller is sam3x.

How can I include the wdt.h for sam3x? I'm using the arduino 1.5.8a framework.

The sketch should look like this:

#include <wdt.h> //unable to locate it unless I include the full path, but the dependencies in this case are not included

void setup() {
....
}

void loop() {
...
}

I thought it's fairly obvious from Bob's pull request. Just modify your own installation of Arduino.h, main.cpp etc. as per the files that he modified. Since it's not part of the core yet, this must be done manually on each computer you expect to use to compile sketches. (Teensyduino does exactly this in a slightly more automated way.)

It can't be done as a regular library that's #included in a sketch.

I may be overlooking something, but I can't find variant.cpp or variant.h for IDE 1.6.3. I can find it in my IDE 1.5.8 install.

For the 1.5.8 install, they are in: \Documents\Arduino\hardware\arduino\sam\variants\arduino_due_x

For the 1.6.3 install, I don't have don't have a path to sam\variants\arduino_due_x

I just have: C:\Program Files (x86)\Arduino\hardware\arduino\

And the only selection in the hardware\arduino directory is avr

Thanks,
-j

Unfortunately, after the sudden and badly thought out release of the board and library manager, I've no idea where these files are now. The location is likely to change until Arduino figure out the right place to put them, which is probably where they were in the first place.

In 1.6.3, they are probably under "My Documents" somewhere. Obviously you need to install support for the Due in the Board Manager first.

I had the same problem but i have it fixed

http://forum.arduino.cc/index.php?topic=314647.0