TeensyDigital
Well-known member
I just spent ten days debugging a thread related crash and I am super grateful to Defragster and mjs513's help pointing me to the right tools. For future travelers also trying to troubleshoot crashes, I wanted to consolidate a few things in this thread.
The (relatively) new CrashReport capability -- as of TD1.54 -- is awesome. Instead of the board hanging, it will reboot 8 seconds after a panic and on start-up you can capture the fact that it crashed and some basic information about the crash. If you combine this with NVRAM markers that also survive a warm reboot you can get more insight into what part of your code failed. I know this is documented in many places in the forum, but below is a short sketch on how these are used together with a simple thread thrown in to show how it can span any part of your code.
On a Mac...
When CrashReport reports out it will display "Code was executed from address 0xC4". To associate the hex code with a line of code from your sketch you need to run addr2line against the sketch .elf file with the following convention: addr2line -e mySketch.elf 0xC4 (where 0xC4 is the line from CrashReport).
On a Mac running Big Sur and TD 1.56 the addr2line executable is in: /Applications/Teensyduino.app/Contents/Java/hardware/tools/arm/bin/arm-none-eabi-addr2line
To find the elf files on a Mac, open the Arduino preference file: Library/Arduino15/preferences.txt and find the value of "last.sketch.default.path". It should be a temp file path deep in /var/folders. Navigate to the folder in terminal and execute addr2line.
Happy troubleshooting!
Mike
The (relatively) new CrashReport capability -- as of TD1.54 -- is awesome. Instead of the board hanging, it will reboot 8 seconds after a panic and on start-up you can capture the fact that it crashed and some basic information about the crash. If you combine this with NVRAM markers that also survive a warm reboot you can get more insight into what part of your code failed. I know this is documented in many places in the forum, but below is a short sketch on how these are used together with a simple thread thrown in to show how it can span any part of your code.
Code:
// Example of using persistent NVRAM Words along with CrashReport to mark code for crash analysis on a T4
// This only uses one NVRAM word (NVRAM_UINT32[0]) but there are four available [1],[2].[3])
// This is a glorified version of serial.println("I made it this far :)");
#include <TeensyThreads.h>
int id_sampling;
uint32_t *NVRAM_UINT32 ((uint32_t *)0x400D4100);
elapsedMillis tSome;
volatile unsigned long lClock;
volatile byte killIt = 0;
void setup() {
SNVS_LPCR |= (1 << 24); //Enable NVRAM - documented in SDK
Serial.begin(115200);
if(CrashReport) {
Serial.print(CrashReport);
Serial.println(" ");
Serial.print("NVRAM Marker Value = ");
Serial.println( NVRAM_UINT32[0] );
while(1); // stop if crashed, but you don't have to
}
//create the thread - nothing fancy
id_sampling = threads.addThread(sample_thread);
delay(2000);
tSome = 0;
Serial.println("PRESS A KEY TO PLAY: '1':CRASH 1 '2':CRASH 2 'k':Kill Thread Crash \n");
}
void loop() {
if ( tSome >= 5000 ) {
tSome = 0;
Serial.println("Press a key, I'm still waiting to die... ");
if(millis() > (lClock + 1500)) {
Serial.print("Sorry, but the thread is dead...");
Serial.println(lClock);
}
}
while ( Serial.available() ) {
char cc = Serial.read();
if ( '1' == cc ) {
NVRAM_UINT32[0] = 1; // set marker value here
int* p = nullptr;
*p = 33; // This will force crash and burn :-O
}
else if ( '2' == cc ) {
NVRAM_UINT32[0] = 2; // set marker marker here
int* p = nullptr;
*p = 33; // This will force crash and burn :-O
}
else if ( 'k' == cc ) {
killIt = 1;
}
}
}
void sample_thread() {
elapsedMillis lSome;
lSome = 0;
while(1) {
if (lSome > 500) {
lClock = millis();
lSome = 0;
}
if(killIt == 1) {
killIt = 0;
NVRAM_UINT32[0] = 3;
int* p = nullptr;
*p = 33; // This will force crash and burn :-O
}
}
}
On a Mac...
When CrashReport reports out it will display "Code was executed from address 0xC4". To associate the hex code with a line of code from your sketch you need to run addr2line against the sketch .elf file with the following convention: addr2line -e mySketch.elf 0xC4 (where 0xC4 is the line from CrashReport).
On a Mac running Big Sur and TD 1.56 the addr2line executable is in: /Applications/Teensyduino.app/Contents/Java/hardware/tools/arm/bin/arm-none-eabi-addr2line
To find the elf files on a Mac, open the Arduino preference file: Library/Arduino15/preferences.txt and find the value of "last.sketch.default.path". It should be a temp file path deep in /var/folders. Navigate to the folder in terminal and execute addr2line.
Happy troubleshooting!
Mike