I have an application where I use the watchdog timer (WDT)for two purposes:
-
An 8 second timeout to trap the occasional lockups I suffer with the WiFiNINA WiFiserver.available() function (subject of another post).
-
512mS timer I use to force a reset after any changes to the system configuration file.
In order to know which mechanism was triggered, I have set up a flag in a 'noinit' section of memory into which I place a specific value when the WDT is enabled and can read and record to the log file during setup().
Both timeouts do as they are intended and setup() correctly traps and records the flag value. However, unless I put a delay or some other function (Serial.print() for example) between setting the flag value and enabling the WDT, the flag value doesn't get set.
The relevant elements of the code are as follows;
<
// The WDT timeout values..
#define WDT_TIMEOUT WDTO_8S
#define WDT_RESET WDTO_500MS
// The flag values..
#define WDT_REBOOT 0xF1CD
#define USER_REBOOT 0xB38F
// Declare the flag variable...
int resetFlag attribute ((section (".noinit")));
// The relevant excerpt from setup..
void setup(){
Wire.begin();
SD.begin();
eventLog.InitLog(); // Function to open up the system log file on the SD card
switch(resetFlag)
{
case WDT_REBOOT:
{
eventLog.logEvent (stsNormal, "System reset WDT timeout") ;
break;
}
case USER_REBOOT:
{
eventLog.logEvent (stsNormal, "System reset by user") ;
break;
}
default: // any other random value in memory after power up
{
eventLog.logEvent (stsNormal, "System power up") ;
}
}
resetFlag = WDT_STARTUP; // The default condition. the WDT is enabled and disabled several times during loop()
.
.
// do all of the other setup things
.
.
} // END setup()
// The function to force reset is declared in a separate code module
extern int resetFlag; // Tell the linker to go find resetFlag.
void forceReset(){
wdt_disable();
resetFlag = USER_REBOOT;
delay(1); // don't understand this delay but without it the change to resetFlag doesn't happen.
wdt_enable(WDT_RESET);
while(1);
}
/>
Initially I wrote the forceReset() function without the delay. It worked but the value of 'resetFlag' didn't change and remained at WDT_REBOOT. In order to debug the issue I added Serial.println(resetFlag); between the assignment and the call to wdt_enable() which caused the value of resetFlag to be set to the correct value, USER_REBOOT.
Removed the Serial.println() statement and it reverted to not changing the value so, instead, I added a 1mS delay and suddenly it works again.
OK, I have a working programme but can someone explain to me what is going on. The code is currently built for a Mega 2560.