Pages: [1]   Go Down
Author Topic: DUE Watchdog usage  (Read 1242 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 41
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
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?
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 41
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Just thinking further: To have a much cleaner solution with the right namespaces
Code:
void WDT_Init();
should go to wdt.h

Code:
#pragma weak WDT_Init
void WDT_Init()
{
  WDT_Disable(WDT);
}
should go to wdt.c

And finally in variant.cpp:
Code:
// 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?
« Last Edit: April 15, 2014, 02:44:47 am by gogol » Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 41
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
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:
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? 
Logged

Offline Offline
Jr. Member
**
Karma: 1
Posts: 68
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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!
Logged

Offline Offline
Full Member
***
Karma: 9
Posts: 209
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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. smiley
Logged

Please don't PM me asking for help. Ask questions in the forum.

Offline Offline
Jr. Member
**
Karma: 1
Posts: 68
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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. smiley

I found the answer here:  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:
#define __WDP_MS 2048 // edit this number accordingly
WDT_Enable ( WDT, 0x2000 | __WDP_MS | ( __WDP_MS << 16 ) );

and the you can call

Code:
WDT_Restart( WDT );

somewhere in the loop() function to avoid reboot.




Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 41
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

Offline Offline
Jr. Member
**
Karma: 1
Posts: 68
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 41
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Is it a design limitation of the SAM3X architecture ?
Yes, chapter 17.4 of the ATSAM3X8E datasheet says:
Code:
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. 
Logged

Pages: [1]   Go Up
Jump to: