Teensy 4.1 deep sleep and watchdog

AllanJ

New member
I'm using a Teensy 4.1 with a watchdog timer set.

Code:
WDT_T4<WDT1> wdt;

I also need to have the Teensy sleep for extended periods so I'm using deepSleep from the Snooze library. The watchdog timer is causing the device to reset when it is put to sleep. Is there a way to disable the watchdog after it has been configured?

Thanks
Allan
 
Snooze has not been implemented for Teensy 4.1. Also I believe that for Teensy 4.0 wake from deep-sleep is via a Teensy Reset.
 
Snooze has not been implemented for Teensy 4.1. Also I believe that for Teensy 4.0 wake from deep-sleep is via a Teensy Reset.

Snooze::deepSleep() seems to be working fine for me. It looks like you must include an instance of SnoozeUSBSerial in the SnoozeBlock but otherwise it appears to work as expected (I'm using the 4_0 version from the hal). I couldn't get hibernate() to work - it seems to hibernate but not wake up - haven't had time to investigate.
 
That doesn't seem to work. I've tried to make a minimum example, once started I use a serial input to trigger the sleep. With the watchdog removed the sleep works fine. With the watchdog in place the sleep is interrupted and the device resets.
Code:
#include <Watchdog_t4.h>
#include <Snooze.h>

WDT_T4<WDT1> wdt;

SnoozeUSBSerial usb;
SnoozeAlarm  alarm;
SnoozeBlock config_teensy40(usb, alarm);

void setup() {
  WDT_timings_t config;
  config.lp_suspend = 1;
  wdt.begin(config);

  alarm.setRtcTimer(0, 10, 0);// hour, min, sec
  
  Serial.begin(57600);
  pinMode(LED_BUILTIN, OUTPUT);
  delay(5000);
  Serial.println("Start");
}

void loop() {
  wdt.feed();

  Serial.println("Start loop..");
 
  int who = 0;
  // Sleep when serial input received..
  if (Serial.available())
    who = Snooze.deepSleep(config_teensy40);
  
  // Just so we can see something happening..
  for (int i = 0; i < 4; ++i) {
    digitalWrite(LED_BUILTIN, HIGH);
    delay(200);
    digitalWrite(LED_BUILTIN, LOW);
    delay(200);
  }
}
 
the suspend function enables it on watchdog register but i think the deepsleep has to stop the clock it uses as well. I am not sure what clocks deepsleep turns off, or if the wdt one is still active (aka not suspended)
 
Most likely Snooze is turning off the enables for the watchdog clock. Watchdog is not something I took into account when writing the T4 sleep code. I'm sure there are other things that are getting in the way with these two libraries.

Also the system clocks that get activated in sleep modes are not ones that ever get used in non sleep code, those might not be usable for the watchdog.
 
Did you have any luck trying to find out why Teensy 4.0 freezes using Snooze and EEPROM.put?
 
I think the alarm is resetting the T4.0, I am using the timer and it is working correctly with the latest commit to WDT_T4:
Code:
https://github.com/tonton81/WDT_T4

Snooze has not been implemented for Teensy 4.1. Also I believe that for Teensy 4.0 wake from deep-sleep is via a Teensy Reset.
Teensy 4.0/4.1 is same processor, so it'll work on both.

With the code below, Teensy sees the millis() counter incrementing on a timer wakeup correctly. Using the alarm wakeup version, in about 40 seconds irregardless of alarm value set, Teensy does a complete reset.
The watchdog config.timeout is set to 1 second, and does not interfere or cause resets with the 5 second timer wakeup

Code:
#include <Watchdog_t4.h>
#include <Snooze.h>

WDT_T4<WDT1> wdt;

SnoozeUSBSerial usb;
SnoozeTimer     timer;
//SnoozeAlarm  alarm;
SnoozeBlock config_teensy40(usb, timer);

void setup() {
  WDT_timings_t config;
  config.lp_suspend = 1;
  config.timeout = 1;
  wdt.begin(config);

  //  alarm.setRtcTimer(0, 10, 0);// hour, min, sec
  timer.setTimer(5);// seconds
  Serial.begin(115200);
  pinMode(LED_BUILTIN, OUTPUT);
  delay(2000);
  Serial.println("Start");
}

void loop() {
  wdt.feed();
  Serial.println(millis());
  int who = 0;
  if (Serial.available()) {
    who = Snooze.deepSleep(config_teensy40);
    delay(500);
    Serial.println(who);
  }
  digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
  delay(200);
}

EDIT, I'll come back to this tonight don't bother, I broke something :p
 
Last edited:
Ok, I had to rush out to work today which is why I said I'll be on this later. I reverted the changes and fixed the library, watchdog is firing at 1second timeout resets if i dont feed it now so thats good, and the 5 second deep sleep does not affect the watchdog, no resets occur and 5 seconds later teensy wakes up to continue printing the millis() counter

Try the repo again with the sketch above. Let me know :)
 
The alarm one is working as well! I set the alarm for 10 seconds:

Code:
#include <Watchdog_t4.h>
#include <Snooze.h>

WDT_T4<WDT1> wdt;

SnoozeUSBSerial usb;
SnoozeTimer     timer;
SnoozeAlarm  alarm;
SnoozeBlock config_teensy40(usb, alarm);
//SnoozeBlock config_teensy40(usb, timer);

void setup() {
  WDT_timings_t config;
  config.lp_suspend = 1;
  config.timeout = 1;
  wdt.begin(config);

  alarm.setRtcTimer(0, 0, 10);// hour, min, sec
  timer.setTimer(5);// seconds
  Serial.begin(115200);
  pinMode(LED_BUILTIN, OUTPUT);
  //  delay(2000);
  Serial.println("Start");
}

void loop() {
  wdt.feed();
  Serial.println(millis());
  int who = 0;
  if (Serial.available()) {
    who = Snooze.deepSleep(config_teensy40);
    delay(500);
    Serial.println(who);
  }
  digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
  delay(200);
}
 
Hi all, I tried the above code from tonton81 without success on my T4.1.
Examples from the library don't work well too on my T4.1
The only code which works for me now is without watchdog and is the following one :

Code:
#include <Snooze.h>

SnoozeUSBSerial usb;
SnoozeAlarm  alarm;
SnoozeBlock config_teensy40(usb, alarm);

unsigned long wakeup_millis = 0;

void setup() {

  alarm.setRtcTimer(0, 0, 5); // 5 seconds
  pinMode(LED_BUILTIN, OUTPUT);

  Serial.begin(57600);
  /* there there is something really weird : if the Snooze library is active, I must put a little code line under Serial.begin()
   * otherwise the teensy won't boot. Hence the delay(1).
   */
  delay(1); 
}

void loop() {
  Serial.print("Looping - millis "); Serial.println(millis());
  Serial.flush();
 
  // Sleep a little while every 10 seconds
  if (millis() > 10000 + wakeup_millis){
    Snooze.deepSleep(config_teensy40);
    wakeup_millis = millis();
  }
  
  // Just so we can see something happening..
  for (int i = 0; i < 4; ++i) {
    digitalWrite(LED_BUILTIN, HIGH);
    delay(200);
    digitalWrite(LED_BUILTIN, LOW);
    delay(200);
  }
}

The weird thing to notice is that if I remove the delay(1) line below Serial.begin() the code won't boot. Otherwise, the teensy sleeps well.
I'm on Teensyduino 1.56 - Adruino 1.8.19
 
did you use the WDT_T4 repo version and my code tested above as was mentioned? sleep support was added to it as an update
 
Hello tonton, what do you mean by "WDT_T4 repo" ? latest repository version ? How can I be sure that the compiler would use one I would download instead of the one which is included in Teensyduino ? Or maybe I should just re-download Teensyduino ?

Anyhow, I don't think WDT_T4 is the issue, but rather Snooze. I used WDT_T4 on a previous Teensy 4.1 project without issues. And I can't actually really use Snooze : the code locks too easily when I try to add it in another code. When my teensy locks, the red led which is just aside the USB blinks and nothing else happens (terminal says teensy disconnected). I have to press the reset button on the board to upload another code to reset it.
 
I think I eventually found what is the issue, thanks to this thread :
https://forum.pjrc.com/threads/6943...any-T4-x-on-TD1-56?highlight=teensy+4.1+sleep
It seems that as from Teensyduino 1.56 there is a missing line in the file hal.c : I added FLASHMEM to TEENSY40\hal.c (Line 652)
Code:
//----------------------------------------------------------------------------------
FLASHMEM
void startup_early_hook( void ) {
    uint32_t OR_D_GPR = IOMUXC_GPR_GPR4 | IOMUXC_GPR_GPR7 | IOMUXC_GPR_GPR8 | IOMUXC_GPR_GPR12;
    if ( OR_D_GPR > 0x0 ) {
        IOMUXC_GPR_GPR1 &= ~IOMUXC_GPR_GPR1_GINT;

Now all the examples are working OK on my Teensy 4.1, and for information here is my working test code. It will put the T4.1 in sleep mode for 5 seconds every 10 seconds, and eventually reset the teensy after 30 seconds of code run thanks to the watchdog.

Code:
#include <Snooze.h>
#include <Watchdog_t4.h>

SnoozeUSBSerial usb;
SnoozeAlarm  alarm;
SnoozeBlock config_teensy40(usb, alarm);

WDT_T4<WDT1> wdt;

unsigned long wakeup_millis = 0;

void setup() {

  WDT_timings_t config;
  config.lp_suspend = 1;
  config.timeout = 5;
  wdt.begin(config);

  alarm.setRtcTimer(0, 0, 5);// hour, min, sec
  pinMode(LED_BUILTIN, OUTPUT);

  Serial.begin(57600);
 
}

void loop() {
  Serial.print("Looping - millis "); Serial.println(millis());
  Serial.flush();

  wdt.feed();
 
  // Sleep a little while every 10 seconds
  if (millis() > 10000 + wakeup_millis){
    Snooze.deepSleep(config_teensy40);
    wakeup_millis = millis();
  }
  
  // Just so we can see something happening..
  for (int i = 0; i < 4; ++i) {
    digitalWrite(LED_BUILTIN, HIGH);
    delay(200);
    digitalWrite(LED_BUILTIN, LOW);
    delay(200);
  }

  // trigger the watchdog after 30 seconds of code run
  if (millis() > 30000) delay(10000);
}
 
For anyone else finding this thread I can confirm that my Teensy4.1 draws 6mA from 5V in deep sleep, so if you also have a battery application don't waste your time.
 
Snooze::deepSleep() seems to be working fine for me. It looks like you must include an instance of SnoozeUSBSerial in the SnoozeBlock but otherwise it appears to work as expected (I'm using the 4_0 version from the hal). I couldn't get hibernate() to work - it seems to hibernate but not wake up - haven't had time to investigate.

Could you please clarify what you mean by "include an instance of SnoozeUSBSerial in the SnoozeBlock"? I am getting errors in regards to to certain undeclared identifiers in SnoozeUSBSerial.cpp and SnoozeUSBSerial.h, which I am guessing relate to what you mentioned here.
 
I've tried to use
config.lp_suspend = 1;

I have a scenario where I need to stop the watchdog when doing OTA otherwise it will restart the device which bricks it in this case.
Is there a way to disable the watchdog once it's been configured?
 
I have a scenario where I need to stop the watchdog when doing OTA otherwise it will restart the device which bricks it in this case.
Is there a way to disable the watchdog once it's been configured?
If it turns out you can't disable the watchdog, I think you could service it from within flash_move().
 
Back
Top