Arduino Forum

Products => Arduino Due => Topic started by: gogol on Apr 14, 2014, 02:14 pm

Title: DUE Watchdog usage
Post by: gogol on Apr 14, 2014, 02:14 pm
When trying to use the Watchdog on the DUE, you will come over short to one finding:
Quote from: SAM3X8E Docmentation chapter 17.4

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.


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:
Code: [Select]

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?
Title: Re: DUE Watchdog usage
Post by: gogol on Apr 15, 2014, 09:42 am
Just thinking further: To have a much cleaner solution with the right namespaces
Code: [Select]
void WDT_Init();
should go to wdt.h

Code: [Select]
#pragma weak WDT_Init
void WDT_Init()
{
 WDT_Disable(WDT);
}

should go to wdt.c

And finally in variant.cpp:
Code: [Select]
// 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?
Title: Re: DUE Watchdog usage
Post by: gogol on Apr 16, 2014, 03:26 pm
Still talking only to myself :-(
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(),
Code: [Select]

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()
Code: [Select]

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? 
Title: Re: DUE Watchdog usage
Post by: bilica on Jul 14, 2014, 05:00 pm
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!
Title: Re: DUE Watchdog usage
Post by: bobcousins on Jul 15, 2014, 09:10 pm

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. :)
Title: Re: DUE Watchdog usage
Post by: bilica on Jul 15, 2014, 09:35 pm


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. :)


I found the answer here:  http://forum.arduino.cc/index.php?PHPSESSID=fg7nrj1t8i9bhajs3ebg7suij5&topic=152885.msg1149434#msg1149434 (http://forum.arduino.cc/index.php?PHPSESSID=fg7nrj1t8i9bhajs3ebg7suij5&topic=152885.msg1149434#msg1149434)

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:

Code: [Select]

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


and the you can call

Code: [Select]

WDT_Restart( WDT );


somewhere in the loop() function to avoid reboot.




Title: Re: DUE Watchdog usage
Post by: gogol on Jul 16, 2014, 09:20 am
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.
Title: Re: DUE Watchdog usage
Post by: bilica on Jul 16, 2014, 03:01 pm
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,



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.
Title: Re: DUE Watchdog usage
Post by: gogol on Jul 16, 2014, 04:23 pm
Quote

Is it a design limitation of the SAM3X architecture ?

Yes, chapter 17.4 of the ATSAM3X8E datasheet says:
Code: [Select]

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. 
Title: Re: DUE Watchdog usage
Post by: g4rb4g3 on Jan 08, 2015, 07:13 pm
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...
Code: [Select]
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'

Code: [Select]
--- 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();
Title: Re: DUE Watchdog usage
Post by: g4rb4g3 on Jan 08, 2015, 08:16 pm
I tried it now and the watchdog works perfectly!
Title: Re: DUE Watchdog usage
Post by: RayLivingston on Jan 08, 2015, 08:49 pm
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:
Code: [Select]

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?

A very nice solution to the problem!

Regards,
Ray L.
Title: Re: DUE Watchdog usage
Post by: JWScotSat on Jan 13, 2015, 10:23 am
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.
Title: Re: DUE Watchdog usage
Post by: l-mb on Jan 13, 2015, 12:32 pm
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!
Title: Re: DUE Watchdog usage
Post by: bobcousins on Jan 14, 2015, 07:58 pm
A while ago I created a pull request to get this type of functionality included in the core https://github.com/arduino/Arduino/pull/2210 (https://github.com/arduino/Arduino/pull/2210). 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.
Title: Re: DUE Watchdog usage
Post by: skaarj on Apr 15, 2015, 05:58 pm
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() {
...
}
Title: Re: DUE Watchdog usage
Post by: MorganS on Apr 16, 2015, 06:17 pm
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.
Title: Re: DUE Watchdog usage
Post by: johnf95037 on Apr 16, 2015, 11:39 pm
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
Title: Re: DUE Watchdog usage
Post by: bobcousins on Apr 17, 2015, 09:58 am
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.

Title: Re: DUE Watchdog usage
Post by: koppels on Apr 17, 2015, 01:37 pm
I had the same problem but i have it fixed

http://forum.arduino.cc/index.php?topic=314647.0
Title: Re: DUE Watchdog usage
Post by: johnf95037 on Apr 17, 2015, 05:32 pm
Hey Bob,

I did find out I needed to use the board manager to install Due support.  I'm searching my drive for the files right now.

Kopples, I take a look at your suggestions.

Thanks,
-j
Title: Re: DUE Watchdog usage
Post by: johnf95037 on Apr 17, 2015, 07:51 pm
Ok found the files.  Sheesh.  That's an obscure location.

C:\Users\DUC\AppData\Roaming\Arduino15\packages\arduino\hardware\sam\1.6.3\variants\arduino_due_x

Now to get the WDT up and working.

Cheers,
-j
Title: Re: DUE Watchdog usage
Post by: johnf95037 on Apr 21, 2015, 10:10 pm
Hey Bob,

I made the file changes and additions as per your pull.  As far as using it in setup() and loop(), what needs to be done?

Thanks,
-j
Title: Re: DUE Watchdog usage
Post by: bobcousins on Apr 21, 2015, 11:47 pm
Here is one of the test cases I used which should illustrate it's use:
Code: [Select]

// Due Watchdog test case
// - enable the watchdog and demonstrate that wdt_reset() prevents timeout

void watchdogSetup(void)
{
  watchdogEnable(1000);
}

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
  Serial.println ("start");
}

void loop() {
  // put your main code here, to run repeatedly:

  // this should not cause a watchdog timeout
  while (1){
    delay (100);
    Serial.println(millis());
    watchdogReset();
  }
 
}
Title: Re: DUE Watchdog usage
Post by: johnf95037 on Apr 22, 2015, 04:57 pm
Thank you sir.  I'll give it a try.
-j
Title: Re: DUE Watchdog usage
Post by: johnf95037 on Apr 22, 2015, 05:57 pm
It works great.  I tried a couple scenarios to force a system reset and to operate properly with the watchdog running in the background.

Thanks,
-j
Title: Re: DUE Watchdog usage
Post by: germancorrea on Jun 08, 2015, 07:24 am
koppels

I followed your instructions in http://forum.arduino.cc/index.php?topic=314647.0 and your code to test the watchdog function works fine.

Can you supply code how to use to use regulary

Thanks
Title: Re: DUE Watchdog usage
Post by: RTurner_nexus on May 29, 2017, 04:54 am
I was trying to use the great data in this thread but found at my 1.6.7 level the WDT_disable() call is no longer in the arduino_due_x\variant.cpp file.
What seems to have happened is the introduction of watchdog.cpp and watchdog.h in arduino\hardware\sam\1.6.7\cores\arduino directory.

Within the watchdog.cpp there is a watchdogSetup() defined so that it has a weak reference to a WDT_disable(WDT); call.  This stops the watchdog timer interupting sketches that dont use it.
So if you want to use the watchdog timer at this level, enable it by putting the following in your sketch.

void watchdogSetup(void) { }

This function can be empty as shown and creates a strong reference thus overiding the WDT_disable(WDT).

Then you should be able to use the "watchdog.h" or "wdt.h" calls.