-
Notifications
You must be signed in to change notification settings - Fork 5
The Watchdog timer
This library exists to show use of Teensy 4.x watchdog timers with examples: Teensy 4 Watchdog library
For Teensy 3.x (and 4.x?) there is this library: Teensy 3 Watchdog library
This PJRC Forum post https://forum.pjrc.com/threads/67649-Non-volatile-data-for-debugging-RTWDOG-reset?p=282962&viewfull=1#post282962
Shows another manually created WDOG created on Teensy 4.x and also notes how the persistent ( while powered ) nature of the RAM2/DMAMEM can retain data values in use before the watchdog restart can be present on restart after the watchdog time out.
DMAMEM byte myWarmRam[13]; // This array will be in RAM2 and present with prior values on restart.
When allocated this way it will reside at a specific location between restarts, and this memory is not zero initialized or otherwise overwritten - unless new code upload has it moved during the build.
arm_dcache_flush(myWarmRam, sizeof(myWarmRam)); // In the watchdog expired restart code having the cache flushed to physical RAM
If the code restarts without the cache flushed, RAM won't hold the most recent values.
This example stops on user input - and the CallBack() stores the incoming data to print on restart:
#include "Watchdog_t4.h"
WDT_T4<WDT3> wdt;
// DMAMEM causes allocation in 'static' RAM2 on Teensy using 1062 processor
// It is not initialized and will retain value while powered
// BUT - it writes through a cache that must be flushed to assure it is current
// This works for any DMAMEM allocation of any variable type or structure
DMAMEM uint32_t loopCnt;
DMAMEM uint32_t feedCnt;
DMAMEM char szLast[32];
void myCallback() {
arm_dcache_flush(&loopCnt, sizeof(loopCnt));
arm_dcache_flush(&feedCnt, sizeof(feedCnt));
uint ii = 1;
while ( ii < (sizeof(szLast) - 1) && Serial.available() ) {
szLast[ii++] = Serial.read();
}
szLast[ii] = 0;
szLast[0] = 42;
arm_dcache_flush(szLast, sizeof(szLast));
Serial.println("YOU DIDNT FEED THE DOG, 255 CYCLES TILL RESET...");
}
void setup() {
Serial.begin(1);
delay(600);
Serial.println("Begin......");
Serial.print("\tPRIOR Loop Count = ");
Serial.println(loopCnt);
loopCnt = 0;
arm_dcache_flush(&loopCnt, sizeof(loopCnt));
Serial.print("\tPRIOR Feed Count = ");
Serial.println(feedCnt);
feedCnt = 0;
arm_dcache_flush(&feedCnt, sizeof(feedCnt));
if ( szLast[0] == 42 && szLast[1] != 0 ) {
Serial.print("\tLast User input text : ");
Serial.println(&szLast[1]);
}
szLast[0] = 0;
arm_dcache_flush(szLast, sizeof(szLast));
if ( Serial && CrashReport )
{ // Make sure Serial is alive and there is a CrashReport stored.
Serial.print(CrashReport); // Once called any crash data is cleared
// In this case USB Serial is used - but any Stream capable output will work : SD Card or other UART Serial
}
WDT_timings_t config;
config.window = 3000; /* in seconds, 32ms to 522.232s, must be smaller than timeout */
config.timeout = 10000; /* in seconds, 32ms to 522.232s */
config.callback = myCallback;
wdt.begin(config);
}
void loop() {
static uint32_t feed = millis();
loopCnt++;
/* set to below 3000 to demonstrate windowMode effect for feeding the dog too fast */
/* set to 3100 to demonstrate proper processing */
/* set to 12000 to demonstrate an actual non-feeding reset */
if ( millis() - feed > 3100 ) {
feed = millis();
wdt.feed();
feedCnt++;
}
if ( Serial.available() ) { // Any Serial input will HALT the loop() here causing WD Timeout
Serial.println("Hungry Dog ahead ...... code stopped here restart pending ...");
while ( Serial.available() );
Serial.println("Too late - but callback emptied the queued data!"); // this prints if the timing is right - then restart
}
}
Teensy is a PJRC trademark. Notes here are for reference and will typically refer to the ARM variants unless noted.