Teensy 4.0 Sleep with CAN wakeup

I ran the CrashReport and it found something, I have no Idea what it means though, from what I can tell, the Teensy wakes up but never runs any code after the sleep instructions so I can't even try to detach the interrupt. Doesn't seem to matter either if I just send one CAN frame or the entire network at it while trying wake, same result, current jumps up to ~50mA for 8-10 seconds and then it reboots itself. Again if I manually ground any of the RX pins it wakes up properly, it definitely does not like either the fast/short CAN pulses or the ton of pulses it gets so quickly.

Code:
CrashReport:
  A problem occurred at (system time) 17:48:9
  Code was executing from address 0x0
  CFSR: 1
    (IACCVIOL) Instruction Access Violation
  Temperature inside the chip was 41.85 °C
  Startup CPU clock speed is 600MHz
  Reboot was caused by auto reboot after fault or bad interrupt detected
@ifrythings: Is the CrashReport repeated/reported every 8-10 seconds, or is it only reported once when a message wake-up is attempted ??

Mark J Culross
KD5RXT
 
@ifrythings: Is the CrashReport repeated/reported every 8-10 seconds, or is it only reported once when a message wake-up is attempted ??

Mark J Culross
KD5RXT
Only once when wake up is detected.

I tried this without the CAN library and it’s doing the same thing so it’s something in the snooze library I believe.
 
The story so far?:

It was not waking up at all
Doing pinMode and attachInterrupt before sleep allowed wake

Now when it wakes it crashes?

-----
Maybe Snooze wasn't seeing the interrupts before to wake, but it does on wake when the Rx port is flickering data
Now MUX'd as "INPUT" - The CAN hardware is no longer as it was on waking.
Can the CAN_#.enable_XYZ()'s be disabled before sleep? or a CAN_#.end?

Then repeat those setup(){ // Setup CAN_# } commands to reenable?
 
If you use the CrashReport's breadcrumbs feature, can you tell if the Teensy is actually waking up and in control, however briefly, before it crashes by trying to execute from address 0x0?

Also, it might be a plan to reset keep_awake immediately on wake-up, otherwise there's a risk that a super-short wake-up pulse (shorter than the time required to wake) will result in immediately going back to sleep.

C++:
#include <Snooze.h>

SnoozeDigital digital;
SnoozeUSBSerial usb;
SnoozeBlock config(usb, digital);

uint32_t keep_awake;      // Timer For System Sleep

void setup() {
  pinMode(23, INPUT_PULLUP);
  digital.pinMode(23, INPUT_PULLUP, FALLING); // Set Wake Up Pin
  CrashReport.breadcrumb(1,0); // setup done
}

uint32_t loopCount;
void loop() {
  CrashReport.breadcrumb(2,loopCount++); // how many loops executed
  CrashReport.breadcrumb(4,millis());      // time of last loop
  if(!digitalRead(23)) keep_awake = millis();
  if(millis() - keep_awake >= 5000)  // Put System To Sleep
  {
      CrashReport.breadcrumb(1,1);             // before sleep
      CrashReport.breadcrumb(3,loopCount);     // loop count at sleep
      CrashReport.breadcrumb(5,millis());     // time at sleep
      Snooze.deepSleep(config);
      CrashReport.breadcrumb(1,2); // after sleep     
      keep_awake = millis(); // ensure we keep awake for at least 5s after waking
      CrashReport.breadcrumb(1,3); // keep_awake set
  }
}
 
Also, it might be a plan to reset keep_awake immediately on wake-up, otherwise there's a risk that a super-short wake-up pulse (shorter than the time required to wake) will result in immediately going back to sleep.
This was the issues right here, I ran your code and it never faulted so I started removing stuff till it did and when I removed keep_awake = millis() it gave me the fault code.

Now this works good with this basic sketch, when I try it in the basic CAN sketch it faulted again.
I found if I didn't try to use more than one digital.pinMode(CAN#_RX, INPUT, FALLING) AND only ONE pinMode(CAN#_RX, INPUT) it works fine, more than one digital.pinMode(CAN#_RX, INPUT, FALLING) and I get this error still:
Code:
CrashReport:
  A problem occurred at (system time) 2:27:11
  Code was executing from address 0x0
  CFSR: 1
    (IACCVIOL) Instruction Access Violation
  Temperature inside the chip was 61.30 °C
  Startup CPU clock speed is 600MHz
  Reboot was caused by auto reboot after fault or bad interrupt detected

If I do two pinMode(CAN#_RX, INPUT) the current draw shoots up to 60mA and it just sits there unresponsive to everything including the Teensy loader till I hit the program button. I don't understand why using more than one pinMode before sleep causes problems.

I haven't found anything in the FlexCAN_T4 that can turn off CAN, they say in the keywords file that there is an "end" but it doesn't exists and fails on compiling.

Here is the current sketch that works only on one CAN bus, there has to be something that's causing issues when trying to use more than one bus wake up, I'm trying to avoid extra hardware if possible (diode ORing into another pin).

Note: moving digital.pinMode(CAN#_RX, INPUT, FALLING) from setup to just before sleep doesn't make any difference so I left it in setup, also the transceivers keep the RX pins high so I don't need the internal pullups.
Code:
#include <FlexCAN_T4.h>
#include <Snooze.h>

#define CAN1_STB 7      // Transceiver Standby Pin
#define CAN2_STB 12     // Transceiver Standby Pin
#define CAN3_STB 13     // Transceiver Standby Pin
#define CAN1_RX 23      // Transceiver RX Pin
#define CAN2_RX 0       // Transceiver RX Pin
#define CAN3_RX 30      // Transceiver RX Pin

FlexCAN_T4<CAN1, RX_SIZE_256, TX_SIZE_16> CAN_1;
FlexCAN_T4<CAN2, RX_SIZE_256, TX_SIZE_16> CAN_2;
FlexCAN_T4<CAN3, RX_SIZE_256, TX_SIZE_16> CAN_3;

SnoozeDigital digital;
SnoozeUSBSerial usb;
SnoozeBlock config(usb, digital);

uint32_t keep_awake;

void CAN_INT(){
  // Setup CAN_1
  CAN_1.begin();
  CAN_1.setClock(CLK_60MHz);
  CAN_1.setBaudRate(500000);
  CAN_1.enableFIFO();
  CAN_1.enableFIFOInterrupt();
  CAN_1.onReceive(CAN1_receive);
 
  // Setup CAN_2
  CAN_2.begin();
  CAN_2.setClock(CLK_60MHz);
  CAN_2.setBaudRate(500000);
  CAN_2.enableFIFO();
  CAN_2.enableFIFOInterrupt();
  CAN_2.onReceive(CAN2_receive);
 
  // Setup CAN_3
  CAN_3.begin();
  CAN_3.setClock(CLK_60MHz);
  CAN_3.setBaudRate(500000);
  CAN_3.enableFIFO();
  CAN_3.enableFIFOInterrupt();
  CAN_3.onReceive(CAN3_receive);
  }

void setup(){
  if(CrashReport) Serial.print(CrashReport);
  pinMode(CAN1_STB, OUTPUT);
  pinMode(CAN2_STB, OUTPUT);
  pinMode(CAN3_STB, OUTPUT);
  digital.pinMode(CAN1_RX, INPUT, FALLING);
  //digital.pinMode(CAN2_RX, INPUT, FALLING);
  //digital.pinMode(CAN3_RX, INPUT, FALLING);
  CAN_INT();
  }

void CAN1_receive(const CAN_message_t &msg){
  keep_awake = millis();      // Keep System Awake If CAN Traffic
  }

void CAN2_receive(const CAN_message_t &msg){
  keep_awake = millis();      // Keep System Awake If CAN Traffic
  }

void CAN3_receive(const CAN_message_t &msg){
  keep_awake = millis();      // Keep System Awake If CAN Traffic
  }

void TRX(uint8_t mode){
  digitalWrite(CAN1_STB, mode);
  digitalWrite(CAN2_STB, mode);
  digitalWrite(CAN3_STB, mode);
  }

void loop(){
  if(millis() - keep_awake >= 5000){
    TRX(HIGH);                // Put Transceivers In Standby Mode
    pinMode(CAN1_RX, INPUT);  // Set Wake Up Pin
    //pinMode(CAN2_RX, INPUT);  // Set Wake Up Pin
    //pinMode(CAN3_RX, INPUT);  // Set Wake Up Pin
    Snooze.deepSleep(config); // Put System To Sleep
    keep_awake = millis();    // Reset Sleep Timer
    CAN_INT();                // Reinitialize CAN Driver
    TRX(LOW);                 // Put Transceivers In Active Mode
    }
  CAN_1.events();
  CAN_2.events();
  CAN_3.events();
}
 
@h4yn0nnym0u5e

I tried the very basic sketch but with 3 wakeups and I get the same error but your breadcrumb is doing something, I'm not sure what it means yet though

Code:
CrashReport:
  A problem occurred at (system time) 2:54:11
  Code was executing from address 0x0
  CFSR: 1
    (IACCVIOL) Instruction Access Violation
  Temperature inside the chip was 54.81 °C
  Startup CPU clock speed is 600MHz
  Reboot was caused by auto reboot after fault or bad interrupt detected
  Breadcrumb #1 was 3 (0x3)
  Breadcrumb #2 was 52846567 (0x3265FE7)
  Breadcrumb #3 was 52729581 (0x32496ED)
  Breadcrumb #4 was 42227 (0xA4F3)
  Breadcrumb #5 was 42134 (0xA496)

and the code I ran
Code:
#include <Snooze.h>

SnoozeDigital digital;
SnoozeUSBSerial usb;
SnoozeBlock config(usb, digital);

uint32_t keep_awake;      // Timer For System Sleep

void setup() {
  if(CrashReport) Serial.print(CrashReport);
  pinMode(23, INPUT_PULLUP);
  pinMode(0, INPUT_PULLUP);
  pinMode(30, INPUT_PULLUP);
  digital.pinMode(23, INPUT_PULLUP, FALLING); // Set Wake Up Pin
  digital.pinMode(0, INPUT_PULLUP, FALLING); // Set Wake Up Pin
  digital.pinMode(30, INPUT_PULLUP, FALLING); // Set Wake Up Pin
  CrashReport.breadcrumb(1,0); // setup done
}

uint32_t loopCount;
void loop() {
  CrashReport.breadcrumb(2,loopCount++); // how many loops executed
  CrashReport.breadcrumb(4,millis());      // time of last loop
  if(!digitalRead(23)) keep_awake = millis();
  if(!digitalRead(0)) keep_awake = millis();
  if(!digitalRead(30)) keep_awake = millis();
  if(millis() - keep_awake >= 5000)  // Put System To Sleep
  {
      CrashReport.breadcrumb(1,1);             // before sleep
      CrashReport.breadcrumb(3,loopCount);     // loop count at sleep
      CrashReport.breadcrumb(5,millis());     // time at sleep
      Snooze.deepSleep(config);
      CrashReport.breadcrumb(1,2); // after sleep     
      keep_awake = millis(); // ensure we keep awake for at least 5s after waking
      CrashReport.breadcrumb(1,3); // keep_awake set
  }
}
 
Ok, I understand you not wanting to add additional hardware, but if you have 3 spare pins you could wire each CAN Rx pin to another i/p pin and try using that (those) for wakeup purposes. Using the individual pins would tell you which CAN channel was causing the wake-up.
 
breadcrumb is doing something, I'm not sure what it means yet though

Code:
CrashReport:
A problem occurred at (system time) 2:54:11
Code was executing from address 0x0
CFSR: 1
(IACCVIOL) Instruction Access Violation
Temperature inside the chip was 54.81 °C
Startup CPU clock speed is 600MHz
Reboot was caused by auto reboot after fault or bad interrupt detected
Breadcrumb #1 was 3 (0x3)
Breadcrumb #2 was 52846567 (0x3265FE7)
Breadcrumb #3 was 52729581 (0x32496ED)
Breadcrumb #4 was 42227 (0xA4F3)
Breadcrumb #5 was 42134 (0xA496)
So if you read the code, it's
  • entering deepSleep at 42134ms, after 52729581 iterations of loop()
  • exiting deepSleep OK, and setting keep_alive to the current millisecond time
  • running a further 52846567 - 52729581 = 116986 loop iterations taking 42227 - 42134 = 93ms
  • crashing due to trying to execute from address 0x0
It looks like the Snooze library doesn't tidy up properly after waking up, so a wakeup pin transition is triggering an invalid interrupt vector. I'll dig deeper...
 
OK, haven't got to the bottom of it yet, but if you disable GPIO interrupts after waking up, then it does seem to prevent the Code was executing from address 0x0 crash. This is obviously a complete no-no as a long-term solution, because there may be other pins you want to use as interrupts.
C++:
#include <Snooze.h>

SnoozeDigital digital;
SnoozeUSBSerial usb;
SnoozeBlock config(usb, digital);

uint32_t keep_awake;      // Timer For System Sleep

void setup() {
  if(CrashReport) Serial.print(CrashReport);
  pinMode(23, INPUT_PULLUP);
  pinMode(0, INPUT_PULLUP);
  pinMode(30, INPUT_PULLUP);
  digital.pinMode(23, INPUT_PULLUP, FALLING); // Set Wake Up Pin
  digital.pinMode(0, INPUT_PULLUP, FALLING); // Set Wake Up Pin
  digital.pinMode(30, INPUT_PULLUP, FALLING); // Set Wake Up Pin
  CrashReport.breadcrumb(1,0); // setup done
}

uint32_t loopCount;
void loop() {
  CrashReport.breadcrumb(2,loopCount++); // how many loops executed
  CrashReport.breadcrumb(4,millis());      // time of last loop
  if(!digitalRead(23)) keep_awake = millis();
  if(!digitalRead(0)) keep_awake = millis();
  if(!digitalRead(30)) keep_awake = millis();
  if(millis() - keep_awake >= 5000)  // Put System To Sleep
  {
      CrashReport.breadcrumb(1,1);             // before sleep
      CrashReport.breadcrumb(3,loopCount);     // loop count at sleep
      CrashReport.breadcrumb(5,millis());     // time at sleep
      Snooze.deepSleep(config);
      
      NVIC_DISABLE_IRQ( IRQ_GPIO6789 ); // ***** add this *****
      
      CrashReport.breadcrumb(1,2); // after sleep     
      keep_awake = millis(); // ensure we keep awake for at least 5s after waking
      CrashReport.breadcrumb(1,3); // keep_awake set
  }
}
 
OK, haven't got to the bottom of it yet, but if you disable GPIO interrupts after waking up, then it does seem to prevent the Code was executing from address 0x0 crash. This is obviously a complete no-no as a long-term solution, because there may be other pins you want to use as interrupts.
C++:
#include <Snooze.h>

SnoozeDigital digital;
SnoozeUSBSerial usb;
SnoozeBlock config(usb, digital);

uint32_t keep_awake;      // Timer For System Sleep

void setup() {
  if(CrashReport) Serial.print(CrashReport);
  pinMode(23, INPUT_PULLUP);
  pinMode(0, INPUT_PULLUP);
  pinMode(30, INPUT_PULLUP);
  digital.pinMode(23, INPUT_PULLUP, FALLING); // Set Wake Up Pin
  digital.pinMode(0, INPUT_PULLUP, FALLING); // Set Wake Up Pin
  digital.pinMode(30, INPUT_PULLUP, FALLING); // Set Wake Up Pin
  CrashReport.breadcrumb(1,0); // setup done
}

uint32_t loopCount;
void loop() {
  CrashReport.breadcrumb(2,loopCount++); // how many loops executed
  CrashReport.breadcrumb(4,millis());      // time of last loop
  if(!digitalRead(23)) keep_awake = millis();
  if(!digitalRead(0)) keep_awake = millis();
  if(!digitalRead(30)) keep_awake = millis();
  if(millis() - keep_awake >= 5000)  // Put System To Sleep
  {
      CrashReport.breadcrumb(1,1);             // before sleep
      CrashReport.breadcrumb(3,loopCount);     // loop count at sleep
      CrashReport.breadcrumb(5,millis());     // time at sleep
      Snooze.deepSleep(config);
    
      NVIC_DISABLE_IRQ( IRQ_GPIO6789 ); // ***** add this *****
    
      CrashReport.breadcrumb(1,2); // after sleep   
      keep_awake = millis(); // ensure we keep awake for at least 5s after waking
      CrashReport.breadcrumb(1,3); // keep_awake set
  }
}

Can you try my bugfix and see if it works for you? On this branch.
Using this sketch and branch, it works with all 3 inputs, you can even omit the pinMode(#, INPUT_PULLUP) for all three of them and it still works.

But unfortunately it does not work with the FlexCAN_T4 library, if I only put in one pinMode(#, INPUT_PULLUP) and one digital.pinMode(CAN#_RX, INPUT, FALLING) it works, pinMode(#, INPUT_PULLUP) has to be before sleep or it crashes, digital.pinMode(CAN#_RX, INPUT, FALLING) can be in either setup() or just before sleep and works (only one though).

When I use more than one input, it doesn't "crash" but the current goes up to ~70mA and it does nothing, can't even program it without hitting the programming button.

This is the crash report if I don't enable any pinMode(#, INPUT_PULLUP) lines, this maybe useless and I just need to enable these codes.
Code:
CrashReport:
  A problem occurred at (system time) 23:39:7
  Code was executing from address 0x5254
  Temperature inside the chip was 52.87 °C
  Startup CPU clock speed is 600MHz
  Reboot was caused by auto reboot after fault or bad interrupt detected
  Breadcrumb #1 was 1 (0x1)
  Breadcrumb #2 was 10305988 (0x9D41C4)
  Breadcrumb #3 was 10305989 (0x9D41C5)
  Breadcrumb #4 was 9301 (0x2455)
  Breadcrumb #5 was 9306 (0x245A)

Here's the code with CAN and one wake up that works.
Code:
#include <FlexCAN_T4.h>
#include <Snooze.h>

#define CAN1_STB 7      // Transceiver Standby Pin
#define CAN2_STB 12     // Transceiver Standby Pin
#define CAN3_STB 13     // Transceiver Standby Pin
#define CAN1_RX 23      // Transceiver RX Pin
#define CAN2_RX 0       // Transceiver RX Pin
#define CAN3_RX 30      // Transceiver RX Pin

FlexCAN_T4<CAN1, RX_SIZE_256, TX_SIZE_16> CAN_1;
FlexCAN_T4<CAN2, RX_SIZE_256, TX_SIZE_16> CAN_2;
FlexCAN_T4<CAN3, RX_SIZE_256, TX_SIZE_16> CAN_3;

SnoozeDigital digital;
SnoozeUSBSerial usb;
SnoozeBlock config(usb, digital);

uint32_t keep_awake;

void CAN_INT(){
  // Setup CAN_1
  CAN_1.begin();
  CAN_1.setClock(CLK_60MHz);
  CAN_1.setBaudRate(500000);
  CAN_1.enableFIFO();
  CAN_1.enableFIFOInterrupt();
  CAN_1.onReceive(CAN1_receive);
 
  // Setup CAN_2
  CAN_2.begin();
  CAN_2.setClock(CLK_60MHz);
  CAN_2.setBaudRate(500000);
  CAN_2.enableFIFO();
  CAN_2.enableFIFOInterrupt();
  CAN_2.onReceive(CAN2_receive);
 
  // Setup CAN_3
  CAN_3.begin();
  CAN_3.setClock(CLK_60MHz);
  CAN_3.setBaudRate(500000);
  CAN_3.enableFIFO();
  CAN_3.enableFIFOInterrupt();
  CAN_3.onReceive(CAN3_receive);
  }

void setup(){
  Serial.println("booting...");
  if(CrashReport) Serial.print(CrashReport);
  pinMode(CAN1_STB, OUTPUT);
  pinMode(CAN2_STB, OUTPUT);
  pinMode(CAN3_STB, OUTPUT);
  digital.pinMode(CAN1_RX, INPUT, FALLING);
  //digital.pinMode(CAN2_RX, INPUT, FALLING);
  //digital.pinMode(CAN3_RX, INPUT, FALLING);
  CAN_INT();
  CrashReport.breadcrumb(1,0); // setup done
  }

void CAN1_receive(const CAN_message_t &msg){
  keep_awake = millis();      // Keep System Awake If CAN Traffic
  Serial.println("CAN- 1");
  }

void CAN2_receive(const CAN_message_t &msg){
  keep_awake = millis();      // Keep System Awake If CAN Traffic
  Serial.println("CAN- 2");
  }

void CAN3_receive(const CAN_message_t &msg){
  keep_awake = millis();      // Keep System Awake If CAN Traffic
  Serial.println("CAN- 3");
  }

uint32_t loopCount;
void loop(){
  CrashReport.breadcrumb(2,loopCount++);  // how many loops executed
  CrashReport.breadcrumb(4,millis());     // time of last loop
  if(millis() - keep_awake >= 5000){
    Serial.println("sleeping...");
    delay(5);
    pinMode(CAN1_RX, INPUT);  // Set Wake Up Pin
    //pinMode(CAN2_RX, INPUT);  // Set Wake Up Pin
    //pinMode(CAN3_RX, INPUT);  // Set Wake Up Pin
    CrashReport.breadcrumb(1,1);          // before sleep
    CrashReport.breadcrumb(3,loopCount);  // loop count at sleep
    CrashReport.breadcrumb(5,millis());   // time at sleep
    Snooze.deepSleep(config);             // Put System To Sleep
    NVIC_DISABLE_IRQ( IRQ_GPIO6789 );     // ***** add this *****
    CrashReport.breadcrumb(1,2);          // after sleep    
    keep_awake = millis();                // Reset Sleep Timer
    CrashReport.breadcrumb(1,3);          // keep_awake set
    CAN_INT();                            // Reinitialize CAN Driver
    }
  CAN_1.events();
  CAN_2.events();
  CAN_3.events();
}
 
Apologies, I should probably have made it clearer that you should now be able to remove the NVIC_DISABLE_IRQ( IRQ_GPIO6789 ); bodge. I doubt it will make a difference to your CAN wake-up issues, though.

Interesting change if you leave out the INPUT_PULLUP - we now have a non-zero execution address when the crash happens.

I need to probe into the Snooze library a bit deeper. My very superficial understanding is that the SnoozeBlock "understands" how to put specific peripherals to sleep, and configure them to cause a wake-up. However, CAN isn't one of the options, so it may be necessary to invent a CAN_DEINIT() function to run just before sleep. I think @tonton81 is the library author, maybe they could suggest some wisdom?
 
Snooze originated and current TeensyDuino included: https://github.com/duff2013/Snooze

@duff

Joined Jan 30, 2013
Last seen May 16, 2024

But last github update 5 years past for T_4.0 release:
Code:
Updated (10/10/20 v6.3.9) Updated T4 SPI driver. Changed Button Hold example pin to 6. Updated start early hook in T4.

Updated (4/20/20 v6.3.8)
Maintenance release.
Added new examples.
Fixed all sketchs to work now, hopefully:).
Teensy 4.0 should work now, many fixes.
More code clean ups.

Updated (4/15/20 v6.3.7)
Maintenance release.
Added v1 Teensy 4.0 support.
Updated and fixed examples.
Updated docs.
 
It's interesting (and very confusing...) that the version of Snooze included with Teensyduino is not the same as the one in Paul's master branch. It looks as if he's releasing the examples_build branch.

I looked at the original repo, the author hasn't touched anything in github for about 3 years, and the Snooze library is unchanged for 5 years. 29 issues, 2 pending PRs. Sounds a familiar story.
 
The IDE 1.8.19 install of 1.60 Beta 5 here shows it matching the linked github.
"...\arduino-1.8.19\hardware\teensy\avr\libraries\Snooze\library.properties"

@duff did years of good work - but has gone offline :( - as noted has not visited the forum in 1.5 years.
 
The library.properties files on all Paul’s branches are exactly the same - you need to compare other files. The master branch doesn’t even compile with Teensyduino 1.59 or 1.60b5 🤬 The Audio library.properties hasn’t changed in 9 years, despite many updates being made in that time.
 
Note that the version included with Teensyduino has an altered hal.c which allows it to compile and work with T4.x. The version on Duff's Github page DOES NOT incorporate this modification.
See my post #12.
 
Last edited:
Note that the version included with Teensyduino has an altered hal.c which allows it to compile and work with T4.x. The version on Duff's Github page DOES NOT incorporate this modification.
See my post #12.
That's pretty much what I was saying in posts #40 and #42... The still-open issue your linked in #12 only refers to part of the needed changes.

My real issue with Paul's fork is that it's totally unclear where to start from if you're trying to do a bug fix. It's not unreasonable to keep master in sync with the upstream repo, but in that case surely it would be good practice to have a Teensyduino branch so one could see where to start modifications. He's also been inconsistent on at least one other occasion - his SdFat fork keeps the Teensyduino modifications on the master branch.
 
Snooze originated and current TeensyDuino included: https://github.com/duff2013/Snooze

@duff

Joined Jan 30, 2013
Last seen May 16, 2024

But last github update 5 years past for T_4.0 release:
Code:
Updated (10/10/20 v6.3.9) Updated T4 SPI driver. Changed Button Hold example pin to 6. Updated start early hook in T4.

Updated (4/20/20 v6.3.8)
Maintenance release.
Added new examples.
Fixed all sketchs to work now, hopefully:).
Teensy 4.0 should work now, many fixes.
More code clean ups.

Updated (4/15/20 v6.3.7)
Maintenance release.
Added v1 Teensy 4.0 support.
Updated and fixed examples.
Updated docs.
NOT without 1 change, see my post #12, now incorporated into Teensyduino.
NOTE:
Although the files shipped with Teensyduino incorporate the required change, it is not incorporated into the file in https://github.com/PaulStoffregen/Snooze/blob/master/src/hal/TEENSY_40/hal.c. Look at line 652, it's missing the required FLASHMEM.
 
Last edited:
Another change pushed to my bugfix/digital-wakeup branch. It looks as if there can be residual pending wakeup interrupts (despite the fact that they're supposedly masked...). If those fire during the wakeup process after the vector has been reset to the value before deepSleep() was called, i.e. typically unused_interrupt_vector(), that will cause a reboot and CrashReport.

As a sort-of fix I've simply masked interrupts while all the vector fiddling is ongoing, rather than piecemeal as happened before. There might be some consequences if a separate pin interrupt has been attached, not part of the Snooze. If this works for @ifrythings then I'll see if I can do a slightly less sledgehammer solution.
 
Another change pushed to my bugfix/digital-wakeup branch. It looks as if there can be residual pending wakeup interrupts (despite the fact that they're supposedly masked...). If those fire during the wakeup process after the vector has been reset to the value before deepSleep() was called, i.e. typically unused_interrupt_vector(), that will cause a reboot and CrashReport.

As a sort-of fix I've simply masked interrupts while all the vector fiddling is ongoing, rather than piecemeal as happened before. There might be some consequences if a separate pin interrupt has been attached, not part of the Snooze. If this works for @ifrythings then I'll see if I can do a slightly less sledgehammer solution.
I had a quick minute to try this and it didn't change anything with the CAN library, if I enable more than one wake input, the Teensy wakes up but doesn't resume executing code. I think when it does this its stuck in an endless loop as the current shoots up to about 70mA (normal 90mA with 3 CAN transceivers on, this 70mA is with no transceivers on) and the chip temperature shoots up pretty good.
 
Here's a minimal set of changes to your code from post #37 (I made more extensive ones to debug). This is working for me, but as I don't have CAN hardware I'm just using push switches to wake the Teensy. Hence I've needed to use INPUT_PULLUP - you may not need to do this, or it might be what's making some of the difference.

C++:
#include <FlexCAN_T4.h>
#include <Snooze.h>

#define CAN1_STB 7      // Transceiver Standby Pin
#define CAN2_STB 12     // Transceiver Standby Pin
#define CAN3_STB 13     // Transceiver Standby Pin
#define CAN1_RX 23      // Transceiver RX Pin
#define CAN2_RX 0       // Transceiver RX Pin
#define CAN3_RX 30      // Transceiver RX Pin

FlexCAN_T4<CAN1, RX_SIZE_256, TX_SIZE_16> CAN_1;
FlexCAN_T4<CAN2, RX_SIZE_256, TX_SIZE_16> CAN_2;
FlexCAN_T4<CAN3, RX_SIZE_256, TX_SIZE_16> CAN_3;

SnoozeDigital digital;
SnoozeUSBSerial usb;
SnoozeBlock config(usb, digital);

uint32_t keep_awake;

void CAN_INT() {
  // Setup CAN_1
  CAN_1.begin();
  CAN_1.setClock(CLK_60MHz);
  CAN_1.setBaudRate(500000);
  CAN_1.enableFIFO();
  CAN_1.enableFIFOInterrupt();
  CAN_1.onReceive(CAN1_receive);

  // Setup CAN_2
  CAN_2.begin();
  CAN_2.setClock(CLK_60MHz);
  CAN_2.setBaudRate(500000);
  CAN_2.enableFIFO();
  CAN_2.enableFIFOInterrupt();
  CAN_2.onReceive(CAN2_receive);

  // Setup CAN_3
  CAN_3.begin();
  CAN_3.setClock(CLK_60MHz);
  CAN_3.setBaudRate(500000);
  CAN_3.enableFIFO();
  CAN_3.enableFIFOInterrupt();
  CAN_3.onReceive(CAN3_receive);
}

void setup() 
{
  Serial.println("booting...");
  if (CrashReport) Serial.print(CrashReport);
  pinMode(CAN1_STB, OUTPUT);
  pinMode(CAN2_STB, OUTPUT);
  pinMode(CAN3_STB, OUTPUT);
  digital.pinMode(CAN1_RX, INPUT_PULLUP, FALLING);
  digital.pinMode(CAN2_RX, INPUT_PULLUP, FALLING);
  digital.pinMode(CAN3_RX, INPUT_PULLUP, FALLING);
  CAN_INT();
  CrashReport.breadcrumb(1, 0); // setup done
}

void CAN1_receive(const CAN_message_t &msg) {
  keep_awake = millis();      // Keep System Awake If CAN Traffic
  Serial.println("CAN- 1");
}

void CAN2_receive(const CAN_message_t &msg) {
  keep_awake = millis();      // Keep System Awake If CAN Traffic
  Serial.println("CAN- 2");
}

void CAN3_receive(const CAN_message_t &msg) {
  keep_awake = millis();      // Keep System Awake If CAN Traffic
  Serial.println("CAN- 3");
}


uint32_t loopCount;
void loop() 
{
  CrashReport.breadcrumb(2, loopCount++); // how many loops executed
  CrashReport.breadcrumb(4, millis());    // time of last loop
  if (millis() - keep_awake >= 5000) {
    Serial.println("sleeping...");
    delay(5);
    //pinMode(CAN1_RX, INPUT);  // Set Wake Up Pin
    //pinMode(CAN2_RX, INPUT);  // Set Wake Up Pin
    //pinMode(CAN3_RX, INPUT);  // Set Wake Up Pin
    CrashReport.breadcrumb(1, 1);         // before sleep
    CrashReport.breadcrumb(3, loopCount); // loop count at sleep
    CrashReport.breadcrumb(5, millis());  // time at sleep
    Snooze.deepSleep(config);             // Put System To Sleep
    // NVIC_DISABLE_IRQ( IRQ_GPIO6789 );     // ***** remove this now *****
    CrashReport.breadcrumb(1, 2);         // after sleep
    keep_awake = millis();                // Reset Sleep Timer
    CrashReport.breadcrumb(1, 3);         // keep_awake set
    CAN_INT();                            // Reinitialize CAN Driver
  }
  CAN_1.events();
  CAN_2.events();
  CAN_3.events();
}
 
Here's a minimal set of changes to your code from post #37 (I made more extensive ones to debug). This is working for me, but as I don't have CAN hardware I'm just using push switches to wake the Teensy. Hence I've needed to use INPUT_PULLUP - you may not need to do this, or it might be what's making some of the difference.
This one turned into a bit of a mind game, the code you posted is pretty much the same as mine but NVIC_DISABLE_IRQ( IRQ_GPIO6789 ) was definitely messing up CAN 1 on mine which I was solely using for testing. I also noticed that pinMode(CAN#_RX, INPUT) isn't needed anymore and could of been also causing issues before. The other thing I found is if I only have one other device on the CAN bus (teensy + other CAN) it wouldn't wake up, if I put another CAN device who's only purpose is to ACK CAN frames everything works correctly.

I have all 3 busses waking up and sending a CAN frame to the other busses (waking those devices up) and everything appears to be working correctly now, well besides the USB/serial monitor doesn't seem to wake up correctly which I'm not using so not worried about that.

Teensy going to sleep with all transceivers turned off, the sleep current is 9mA. Still fairly high but way better than 100+mA, current protype board just has a 7805 reg, final board will have a switching reg to hopefully reduce power consumption and heat, that 7805 gets pretty hot at vin 14v.

Thanks for the help everyone!

Current code that is working so far.
Note: Moved CAN 3 transceiver standby pin off of D13 to D14 to prevent the LED on D13 from turning on and increasing the current draw by a few mA.
Code:
#include <FlexCAN_T4.h>
#include <Snooze.h>

#define CAN1_STB 7      // Transceiver Standby Pin
#define CAN2_STB 12     // Transceiver Standby Pin
#define CAN3_STB 14     // Transceiver Standby Pin
#define CAN1_RX 23      // Transceiver RX Pin
#define CAN2_RX 0       // Transceiver RX Pin
#define CAN3_RX 30      // Transceiver RX Pin

FlexCAN_T4<CAN1, RX_SIZE_256, TX_SIZE_16> CAN_1;
FlexCAN_T4<CAN2, RX_SIZE_256, TX_SIZE_16> CAN_2;
FlexCAN_T4<CAN3, RX_SIZE_256, TX_SIZE_16> CAN_3;

SnoozeDigital digital;
SnoozeUSBSerial usb;
SnoozeBlock config(usb, digital);

uint32_t keep_awake;

void CAN_INT(){
  // Setup CAN_1
  CAN_1.begin();
  CAN_1.setClock(CLK_60MHz);
  CAN_1.setBaudRate(500000);
  CAN_1.enableFIFO();
  CAN_1.enableFIFOInterrupt();
  CAN_1.onReceive(CAN1_receive);
 
  // Setup CAN_2
  CAN_2.begin();
  CAN_2.setClock(CLK_60MHz);
  CAN_2.setBaudRate(500000);
  CAN_2.enableFIFO();
  CAN_2.enableFIFOInterrupt();
  CAN_2.onReceive(CAN2_receive);
 
  // Setup CAN_3
  CAN_3.begin();
  CAN_3.setClock(CLK_60MHz);
  CAN_3.setBaudRate(500000);
  CAN_3.enableFIFO();
  CAN_3.enableFIFOInterrupt();
  CAN_3.onReceive(CAN3_receive);
  }

void TRX(uint8_t mode){
  digitalWrite(CAN1_STB, mode);
  digitalWrite(CAN2_STB, mode);
  digitalWrite(CAN3_STB, mode);
  }

void setup(){
  pinMode(CAN1_STB, OUTPUT);
  pinMode(CAN2_STB, OUTPUT);
  pinMode(CAN3_STB, OUTPUT);
  digital.pinMode(CAN1_RX, INPUT, FALLING);
  digital.pinMode(CAN2_RX, INPUT, FALLING);
  digital.pinMode(CAN3_RX, INPUT, FALLING);
  CAN_INT();
  }

void CAN1_receive(const CAN_message_t &msg){
  keep_awake = millis();      // Keep System Awake If CAN Traffic
  CAN_message_t t; t.id = 0x100;
  CAN_1.write(t);
  CAN_2.write(t);
  CAN_3.write(t);
  }

void CAN2_receive(const CAN_message_t &msg){
  keep_awake = millis();      // Keep System Awake If CAN Traffic
  CAN_message_t t; t.id = 0x200;
  CAN_1.write(t);
  CAN_2.write(t);
  CAN_3.write(t);
  }

void CAN3_receive(const CAN_message_t &msg){
  keep_awake = millis();      // Keep System Awake If CAN Traffic
  CAN_message_t t; t.id = 0x300;
  CAN_1.write(t);
  CAN_2.write(t);
  CAN_3.write(t);
  }

void loop(){
  if(millis() - keep_awake >= 5000){
    TRX(HIGH);                            // Put Transceivers In Standby Mode
    Snooze.deepSleep(config);             // Put System To Sleep
    keep_awake = millis();                // Reset Sleep Timer
    TRX(LOW);                             // Put Transceivers In Active Mode
    CAN_INT();                            // Reinitialize CAN Driver
    }
  CAN_1.events();
  CAN_2.events();
  CAN_3.events();
  }
 
Last edited:
loop() code has gone AWOL in your post :unsure:

Yes, the NVIC_DISABLE_IRQ( IRQ_GPIO6789 ) was only ever a stop-gap, when it became apparent the Snooze library wasn’t doing it correctly. Apologies if that wasn’t as clear as it should have been…

So I’m taking it from
everything appears to be working correctly now
that the immediate issues are resolved for you? If so, I’ll put in a PR for my fixes, though without any real hope they’ll get pulled in…
 
Back
Top