Skip to content
janscience edited this page Nov 3, 2021 · 12 revisions

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
  }
}
Clone this wiki locally