Re-enable bootloader interrupts after a hard fault [Teensy 4.1]

Again I know very little about what allows or does not allow different system faults, or even if the access of a non-clock enabled subsystems registers, will error?

Looking through some Arm M7 docs. I see that some of the 16 system interrupts have their priorities are curious about their settings:
Serial.printf("SCB_SHPRx: %x %x %x SHCSR:%x\n", SCB_SHPR1, SCB_SHPR2, SCB_SHPR3, SCB_SHCSR);
Output: SCB_SHPRx: 0 0 20200000 SHCSR:0

From: https://developer.arm.com/documenta...ock/system-handler-priority-registers?lang=en
Looks like SHPR1 has UsageFault, BusFault, memManage
SHPR2: SVCall
SHPR3: SysTick, PendSV - Which are the only ones that are not set 0...

Again not sure if this has any meaning to this...

Edit: Other note: I also now printed out: SCB_CFSR: 0

screenshot.jpg
So it looks like some of the these fault are probably not enabled (memo
 
Last edited:
Cleaned up the Fault printing with showMyFault( sz ), and put '5' back condensed as it was.
> also added if (Serial()) check before having CrashReport auto clear.
Anyone else notice the '2' coprocessor Faults and Restarts ... but doesn't do CrashReport on restart? Pretty sure it used to show up??? Did a 15s Restore and that didn't change anything.

Code:
#include <SD.h>
#include <SPI.h>
// Found a couple of Faults to force here :: https://interrupt.memfault.com/blog/cortex-m-fault-debug
void showMyFault( const char * sz );
int illegal_instruction_execution(void);

void setup() {
  pinMode( LED_BUILTIN, OUTPUT );
  digitalWrite( LED_BUILTIN, 1 );
  Serial.begin(115200);
  while (!Serial && millis() < 4000 );
  Serial.println("\n" __FILE__ " " __DATE__ " " __TIME__);
  Serial.printf(" millis() now %u\n", millis() );
  if ( CrashReport ) {
    if (SD.begin(BUILTIN_SDCARD)) {
      File dataFile = SD.open("crashlog.txt", FILE_WRITE); // FILE_WRITE append if file already exists
      if (dataFile) {
        dataFile.print(CrashReport);
        dataFile.close();
      }
    } else [B]if ( Serial ) {
      Serial.print(CrashReport);[/B]
    }
    Serial.print("\n\tRECOVERED from Crash !");
  }

  delay ( 100 );
  digitalWrite( LED_BUILTIN, 0 );
  delay ( 1000 );
  digitalWrite( LED_BUILTIN, 1 );
}

void loop() {
  if ( Serial.available()) {
    char cc = Serial.read();
    digitalWrite( LED_BUILTIN, 0 );
    delay ( 50 );
    if ( cc == '0' ) {
      [B]showMyFault("illegal_instruction_execution()"); [/B]
      illegal_instruction_execution();
    }
    else if ( cc == '1' ) {
      showMyFault("Bad Address Read at 0xbadcafe");
      uint32_t ff = *(volatile uint32_t *)0xbadcafe;
      Serial.print(ff);
    }
    else if ( cc == '2' ) {
      showMyFault("Coprocessor Fault - turn off FPU");
      __asm volatile(
        "ldr r0, =0xE000ED88 \n"
        "mov r1, #0 \n"
        "str r1, [r0] \n"
        "dsb \n"
        "vmov r0, s0 \n"
      );
    }
    else if ( cc == '3' ) {
      showMyFault("bad_addr_double_word_write at 0x30000000");
      volatile uint64_t *buf = (volatile uint64_t *)0x30000000;
      *buf = 0x1122334455667788;
    }
    else if ( cc == '4' ) {
      showMyFault("Divide by Zero (not enabled?)");
      cc = cc - '4';
      cc /= cc;
    }
    else if ( cc == '5' ) {
      showMyFault("Try FlexIO : Locks up");
      // CCM_CCGR5 |= CCM_CCGR5_FLEXIO1(CCM_CCGR_ON);
      IMXRT_FLEXIO_t *p = &IMXRT_FLEXIO1_S;
      Serial.printf("%x\n", (uint32_t)p); Serial.flush();
      Serial.printf("VERID:%x PARAM:%x CTRL:%x PIN: %x\n", p->VERID, p->PARAM, p->CTRL, p->PIN); Serial.flush();
      Serial.printf("SHIFTSTAT:%x SHIFTERR=%x TIMSTAT=%x\n", p->SHIFTSTAT, p->SHIFTERR, p->TIMSTAT); Serial.flush();
      Serial.printf("SHIFTSIEN:%x SHIFTEIEN=%x TIMIEN=%x\n", p->SHIFTSIEN, p->SHIFTEIEN, p->TIMIEN); Serial.flush();
      Serial.printf("SHIFTSDEN:%x SHIFTSTATE=%x\n", p->SHIFTSDEN, p->SHIFTSTATE); Serial.flush();
      Serial.printf("SHIFTCTL:%x %x %x %x\n", p->SHIFTCTL[0], p->SHIFTCTL[1], p->SHIFTCTL[2], p->SHIFTCTL[3]); Serial.flush();
      Serial.printf("SHIFTCFG:%x %x %x %x\n", p->SHIFTCFG[0], p->SHIFTCFG[1], p->SHIFTCFG[2], p->SHIFTCFG[3]); Serial.flush();
      Serial.printf("TIMCTL:%x %x %x %x\n", p->TIMCTL[0], p->TIMCTL[1], p->TIMCTL[2], p->TIMCTL[3]); Serial.flush();
      Serial.printf("TIMCFG:%x %x %x %x\n", p->TIMCFG[0], p->TIMCFG[1], p->TIMCFG[2], p->TIMCFG[3]); Serial.flush();
      Serial.printf("TIMCMP:%x %x %x %x\n", p->TIMCMP[0], p->TIMCMP[1], p->TIMCMP[2], p->TIMCMP[3]); Serial.flush();
      Serial.println("made it through");
    }
    else if ( cc == '6' ) {
      showMyFault("Fault using device not enabled");
      LPUART3_CTRL = 0; // did not enable the clock for this    }
    }
    else if ( cc == 't' ) {
      Serial.printf( "\tdeg  C=%f\t F_CPU=%u\n" , tempmonGetTemp(), F_CPU_ACTUAL );
      while ( Serial.available()) Serial.read();
    }
    else { // default fault on Serial with no other fault ... from 'Enter'
      showMyFault("NULL pointer write");
      uint32_t *y = 0; y[0] = 5;
    }
  }
  delay ( 2 );
  digitalWrite( LED_BUILTIN, 0 );
  delay ( 40 );
  digitalWrite( LED_BUILTIN, 1 );
}

void showMyFault( const char * sz ) {
      Serial.printf("\nIt's your fault! > %s\n", sz );
      Serial.flush();
      delay(10);
}
int illegal_instruction_execution(void) {
  int (*bad_instruction)(void) = (void *)0xE0000000;
  return bad_instruction();
}
 
@Paul:

What do you think of this direction as a change for startup.c.
No longer wait 8 secs before restart so Teensy back on USB sooner and ready

Changed the restart loop to 8 ticks for a test - long enough for USB writes to exit:
Code:
void unused_interrupt_vector(void)
// ...
	while (1) {
		if (PIT_TFLG0) {
			//GPIO7_DR_TOGGLE = (1 << 3); // blink LED
			PIT_TFLG0 = 1;
			[B]if (++count >= 8) break;  // reboot after 8 seconds :: NOT[/B]
		}
		usb_isr();
	}

Then a new func call before setup - except for needing a "C" interface to get bool CrashReport:
Code:
[B][COLOR="#FF0000"]#define CrashReport 0[/COLOR][/B] // Called from "C" needs access to class or dupe the DMAMEM test code
void startup_default_userCrashReport(void) {
    if ( CrashReport ) {
      uint32_t crWait = millis();
		while ( millis() - crWait < 8000) yield();
   	}
}
void userCrashReport(void)		__attribute__ ((weak, alias("startup_default_userCrashReport")));

Called here:
Code:
void ResetHandler(void)
{
// ...
	startup_late_hook();
	while (millis() < 300) ; // wait at least 300ms before calling user code
	//printf("before C++ constructors\n");
	__libc_init_array();
	//printf("after C++ constructors\n");
	//printf("before setup\n");
  	[B][COLOR="#FF0000"]userCrashReport();[/COLOR][/B]
	main();
	
	while (1) asm("WFI");
}

And then replaceable sketch code - that wouldn't need to wait and could Stream anywhere:
Code:
void userCrashReport() {
  if ( CrashReport ) {
    elapsedMillis crWait = 0;
    while ( crWait < 8000 && !Serial ) {
      yield();
    }
    Serial.print(CrashReport);
    while ( crWait < 8000) {
      yield();
    }
    Serial.print("\nuserCrashReport()\tRECOVERED from Crash !");
  }
}
 
@Paul : also saw it noted that once a Fault occurs the MCU sees it basically as interrupt Pri -1 so all interrupts are then ignored.
That was when I pulled that code for T_3.6 - not sure it applies to 1062 and if it matters regarding the steps taken to manually stop all interrupts.

Regarding post #128 and added userCrashReport().

With that working when calling this on FAST restart :: if ( CrashReport ) {
<< This with EEPROM may work after CRASH in unused_interrupt_vector() - but that seems risky so not tried >>

It could do this in \cores\teensy4\CrashReport.cpp so that Crash reporting survives across power loss, once it gets restarted:
Code:
CrashReportClass::operator bool()
{
	struct arm_fault_info_struct *info = (struct arm_fault_info_struct *)0x2027FF80;
	if (isvalid(info)) {
	  [B]EEPROM.put( EEPROM.end()-(1+sizeof(info)), info );[/B] // save dup[licate of 'info' to EEPROM "last LEN DWORDS"
	  return true;
	}
	return false;
}

So if 'STREAM" was not available at that time. The next time it is:
Code:
size_t CrashReportClass::printTo(Print& p) const
{
  struct arm_fault_info_struct *info = (struct arm_fault_info_struct *)0x2027FF80;

  int good = 0;
  if (isvalid(info)) good = 1;
[B]  else {
    EEPROM.get( EEPROM.end()-(1+sizeof(info)), info );
    if (isvalid(info)) good = 2;
  }
[/B]  if (good)
  {
    p.println("CrashReport ... Hello World");	
// ...

And then all is wiped with with:
Code:
void CrashReportClass::clear()
{
  struct arm_fault_info_struct *info = (struct arm_fault_info_struct *)0x2027FF80;
  info->len = 0;
// ...
  info->crc = 0;
  arm_dcache_flush_delete(info, sizeof(*info));
  SRC_SRSR = SRC_SRSR; // zeros all write-1-to-clear bits
  SRC_GPR5 = 0;
  EEPROM.put( EEPROM.end()-(1+sizeof(info)), info );
}

So ugly thing #1 is calling the Crash class from startup.c as noted in post #128
And #2 is this ??? :: #include <..\..\libraries\EEPROM\EEPROM.h>
And #3 it takes last 44 bytes of EEPROM at : EEPROM.end()-(1+sizeof(info))
 
Have you tested an Instruction access violation?
if you want to add it to your tests, here his how to force it:
Code:
    void (*iav)(void) = (void (*)(void))(0x00000000);
    iav();

(and yes, it works)

Now looking how to produce a bus fault..
 
Bus fault:

*(uint32_t *)0x4039C010 = 0;

Works after setting SCB_SHCSR |= (1<<18) | (1<<17) | (1<<16);

Just testing this now
Code:
// Enable all exception handlers
 #define SCB_SHCSR_MEMFAULTENA_Msk (1UL << 16)
#define SCB_SHCSR_BUSFAULTENA_Msk (1UL << 17)
 #define SCB_SHCSR_USGFAULTENA_Msk          (1UL << 18)

SCB_SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk | SCB_SHCSR_BUSFAULTENA_Msk | SCB_SHCSR_USGFAULTENA_Msk;

// Enable divide by zero and unaligned access faults
#define 	SCB_CCR_UNALIGN_TRP_Msk   (1UL << 3)
#define 	SCB_CCR_DIV_0_TRP_Msk     (1UL << 4)

SCB_CCR |= SCB_CCR_DIV_0_TRP_Msk | SCB_CCR_UNALIGN_TRP_Msk;
 
We can test the faults for div/zero and unaligned accesses - but i woudn't activate them for "production".[/QUOTE

I just found that if I activate unaligned it t154.b8 with your fault handler it hangs the T41. So I commented it out for testing 154b11 testing.

Did you put it in the sketch or where in startup.c did you put it?

EDIT:
Testes Unaligned access in beta11 and it just continually reboots before crash report printed/

Added note: if I power off and on it clears and prints the crash report showing unaligned access.
 
I used a short program:
Code:
#include "crashreport.h"

void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
  delay(1000);
  Serial.print(CrashReport);
  Serial.println("ready");
  SCB_SHCSR |= (1<<18) | (1<<17) | (1<<16);
  asm("dsb");
  asm("isb");
  digitalWriteFast(LED_BUILTIN, HIGH);
  *(uint32_t *)0x4039C000 = 0;
  Serial.println("ready");
}

void loop() {}
I don't know where your sketch is.
 
Whew, so many messages yesterday!

About design decisions, I believe it's important to accept we have many conflicting goals. Decisions and trade-offs have to be made. No particular default behavior can be perfect for all circumstances.

The most consequential decision is whether to automatically reboot, and if so, how quickly. On Teensy 3.x the fault handler doesn't reboot. But maybe it should? Or maybe the job of automatically rebooting after something goes wrong should be exclusively the responsibility of watchdog timers? Certainly any safety critical application, like the flamethrower or motorcycle mentioned yesterday would be designed with a watchdog timer, which assumes a software defect will result in the CPU getting "stuck".

I'm willing to consider changing the behavior. Now is the time, since after 1.54 releases we will have a lot of people who expect the behavior to remain forever consistent.

One fault behavior I will not consider as default is an immediate or quick reboot. This can lead to an infinite reboot loop where USB enumeration never completes. While certain type of errors can completely cause USB to stop, the default design needs to attempt to make USB work as much as possible, as that is the primary way users observe what happens.
 
@Mike: Oh, if it crashed, we should probably turn on "unaligned" after all.

That was with previous release with your fault handler. With the TD1.54beta11 it just keeps rebooting until you turn power on and back on the the crash report showed up for some reason - still experimenting so don't hold it may have been caused by div/0
 
Whew, so many messages yesterday!

About design decisions, I believe it's important to accept we have many conflicting goals. Decisions and trade-offs have to be made. No particular default behavior can be perfect for all circumstances.

The most consequential decision is whether to automatically reboot, and if so, how quickly. On Teensy 3.x the fault handler doesn't reboot. But maybe it should? Or maybe the job of automatically rebooting after something goes wrong should be exclusively the responsibility of watchdog timers? Certainly any safety critical application, like the flamethrower or motorcycle mentioned yesterday would be designed with a watchdog timer, which assumes a software defect will result in the CPU getting "stuck".

I'm willing to consider changing the behavior. Now is the time, since after 1.54 releases we will have a lot of people who expect the behavior to remain forever consistent.

One fault behavior I will not consider as default is an immediate or quick reboot. This can lead to an infinite reboot loop where USB enumeration never completes. While certain type of errors can completely cause USB to stop, the default design needs to attempt to make USB work as much as possible, as that is the primary way users observe what happens.

I agree with you Paul. With tempmon it just reboots continually unless I clear the panic alarm bit and do something. Not crazy about not seeing errors on screen for debugging. So watchdog timers yes as Frank said. But user should be responsible in critical applications.
 
I used a short program:
Code:
#include "crashreport.h"

void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
  delay(1000);
  Serial.print(CrashReport);
  Serial.println("ready");
  SCB_SHCSR |= (1<<18) | (1<<17) | (1<<16);
  asm("dsb");
  asm("isb");
  digitalWriteFast(LED_BUILTIN, HIGH);
  *(uint32_t *)0x4039C000 = 0;
  Serial.println("ready");
}

void loop() {}
I don't know where your sketch is.

Oh it was in an earlier post, here is what I am using now to experiment with enabling faults:
Code:
// Found a couple of Faults to force here :: https://interrupt.memfault.com/blog/cortex-m-fault-debug
int illegal_instruction_execution(void) {
  int (*bad_instruction)(void) = (void *)0xE0000000;
  return bad_instruction();
}

#include <SD.h>
#include <SPI.h>

void setup() {
// Enable all exception handlers
SCB_SHCSR |= (1UL << 16) | (1UL << 17) | (1UL << 18);
// Enable divide by zero and unaligned access faults
SCB_CCR |= (1UL << 3) | (1UL << 4);

  pinMode( LED_BUILTIN, OUTPUT );
  digitalWrite( LED_BUILTIN, 1 );
  Serial.begin(115200);
  while (!Serial && millis() < 4000 );
  Serial.println("\n" __FILE__ " " __DATE__ " " __TIME__);
  Serial.printf(" millis() now %u\n", millis() );
  if ( CrashReport ) {
    if (SD.begin(BUILTIN_SDCARD)) {
      File dataFile = SD.open("crashlog.txt", FILE_WRITE); // FILE_WRITE append if file already exists
      if (dataFile) {
        dataFile.print(CrashReport);
        dataFile.close();
      }
    } else {
      Serial.print(CrashReport);
    }
    Serial.print("\n\tRECOVERED from Crash !");
  }

  delay ( 100 );
  digitalWrite( LED_BUILTIN, 0 );
  delay ( 1000 );
  digitalWrite( LED_BUILTIN, 1 );
}

void loop() {
  if ( Serial.available()) {
    char cc = Serial.read();
    digitalWrite( LED_BUILTIN, 0 );
    Serial.println("\nIt's your fault!\n");
    delay ( 50 );
    if ( cc == '0' ) {
      illegal_instruction_execution();
    }
    else if ( cc == '1' ) { // Bad Address Read
      uint32_t ff = *(volatile uint32_t *)0xbadcafe;
      Serial.print(ff);
    }
    else if ( cc == '2' ) { // Coprocessor Fault - turn off FPU
      __asm volatile(
        "ldr r0, =0xE000ED88 \n"
        "mov r1, #0 \n"
        "str r1, [r0] \n"
        "dsb \n"
        "vmov r0, s0 \n"
      );
    }
    else if ( cc == '3' ) { // bad_addr_double_word_write
      volatile uint64_t *buf = (volatile uint64_t *)0x30000000;
      *buf = 0x1122334455667788;
    }
    else if ( cc == '4' ) { // Divide by Zero (not enabled?)
      cc = cc - '4';
      cc /= cc;
    }
    else if ( cc == '5' ) {
      Serial.println("Try FlexIO"); Serial.flush();
      // CCM_CCGR5 |= CCM_CCGR5_FLEXIO1(CCM_CCGR_ON);
      IMXRT_FLEXIO_t *p = &IMXRT_FLEXIO1_S;
      Serial.printf("%x\n", (uint32_t)p); Serial.flush();
      Serial.printf("VERID:%x PARAM:%x CTRL:%x PIN: %x\n", p->VERID, p->PARAM, p->CTRL, p->PIN); Serial.flush();
      Serial.printf("SHIFTSTAT:%x SHIFTERR=%x TIMSTAT=%x\n", p->SHIFTSTAT, p->SHIFTERR, p->TIMSTAT); Serial.flush();
      Serial.printf("SHIFTSIEN:%x SHIFTEIEN=%x TIMIEN=%x\n", p->SHIFTSIEN, p->SHIFTEIEN, p->TIMIEN); Serial.flush();
      Serial.printf("SHIFTSDEN:%x SHIFTSTATE=%x\n", p->SHIFTSDEN, p->SHIFTSTATE); Serial.flush();
      Serial.printf("SHIFTCTL:%x %x %x %x\n", p->SHIFTCTL[0], p->SHIFTCTL[1], p->SHIFTCTL[2], p->SHIFTCTL[3]); Serial.flush();
      Serial.printf("SHIFTCFG:%x %x %x %x\n", p->SHIFTCFG[0], p->SHIFTCFG[1], p->SHIFTCFG[2], p->SHIFTCFG[3]); Serial.flush();
      Serial.printf("TIMCTL:%x %x %x %x\n", p->TIMCTL[0], p->TIMCTL[1], p->TIMCTL[2], p->TIMCTL[3]); Serial.flush();
      Serial.printf("TIMCFG:%x %x %x %x\n", p->TIMCFG[0], p->TIMCFG[1], p->TIMCFG[2], p->TIMCFG[3]); Serial.flush();
      Serial.printf("TIMCMP:%x %x %x %x\n", p->TIMCMP[0], p->TIMCMP[1], p->TIMCMP[2], p->TIMCMP[3]); Serial.flush();
      Serial.println("made it through");
    }
    else if ( cc == '6' ) {
    }
    else if ( cc == 't' ) {
      Serial.printf( "\tdeg  C=%f\t F_CPU=%u\n" , tempmonGetTemp(), F_CPU_ACTUAL );
      while ( Serial.available()) Serial.read();
    }
    else { // default fault on Serial with no other fault ... from 'Enter'
      uint32_t *y = 0; y[0] = 5;
    }
  }
  delay ( 3 );
  digitalWrite( LED_BUILTIN, 0 );
  delay ( 40 );
  digitalWrite( LED_BUILTIN, 1 );
}
I still can not get @KurtE's test "5" to trip anything without hanging.
 
@Frank B and all
Unaligned access is an interesting issue. On loading the sketch with unaligned fault turned on it goes into an infinite reboot loop without a crash report being printed. But when I commented it out and reload the test sketch it printed it had a unaligned access fault?
Code:
D:\Users\Merli\Documents\Arduino\CrashRepot_example\CrashRepot_example.ino Jun 24 2021 07:54:40
 millis() now 358
CrashReport ... Hello World
  Fault occurred at: 07:54:35
  Temperature and System Clock at time of fault: 
    Temp = 43.918919 deg C,  Sys Clock = 600 Mhz
  length: 11
  IPSR: 6
  CFSR: 1000000
[B]	(UNALIGNED) Unaligned access UsageFault
[/B]  MMFAR: 0
  BFAR: 0
  return address: 61B4
  XPSR: 21010000
  crc: 6942EB0

	RECOVERED from Crash
Interesting huh.
 
There is probably an unaligned access in startup..
Unaligned accesses are allowed on our cortex-m7. There are only some registers where it is forbidden. I'll try to find one to see if, and in which cases we get a fault.
 
Good Early Morning (for at least me and Paul and Tim) all:

Quick note: I think with the enable of additional exceptions... Did not appear to help so far for accessing registers of subsystems where we did not enable the clock...
I added additional debug code to the '5' test:
Code:
    else if ( cc == '5' ) {
      Serial.println("Print out top of Vector table");
      for (uint8_t i = 0; i < 32; i++) Serial.printf("%u:%x\n", i, (uint32_t)_VectorsRam[i]);
      Serial.printf("SCB_SHPRx: %x %x %x SHCSR:%x\n", SCB_SHPR1, SCB_SHPR2, SCB_SHPR3, SCB_SHCSR);
      // Enable all exception handlers
      #define SCB_SHCSR_MEMFAULTENA_Msk (1UL << 16)
      #define SCB_SHCSR_BUSFAULTENA_Msk (1UL << 17)
      #define SCB_SHCSR_USGFAULTENA_Msk          (1UL << 18)
      SCB_SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk | SCB_SHCSR_BUSFAULTENA_Msk | SCB_SHCSR_USGFAULTENA_Msk;      SCB_CFSR = 0x70000; // see if we enable the other faults...
      Serial.printf("SCB_SHCSR: %x\n", (uint32_t)SCB_SHCSR);
      Serial.println("Try FlexIO"); Serial.flush();
      // CCM_CCGR5 |= CCM_CCGR5_FLEXIO1(CCM_CCGR_ON);
      IMXRT_FLEXIO_t *p = &IMXRT_FLEXIO1_S;
      Serial.printf("%x\n", (uint32_t)p); Serial.flush();
      Serial.printf("VERID:%x PARAM:%x CTRL:%x PIN: %x\n", p->VERID, p->PARAM, p->CTRL, p->PIN); Serial.flush();
      Serial.printf("SHIFTSTAT:%x SHIFTERR=%x TIMSTAT=%x\n", p->SHIFTSTAT, p->SHIFTERR, p->TIMSTAT); Serial.flush();
      Serial.printf("SHIFTSIEN:%x SHIFTEIEN=%x TIMIEN=%x\n", p->SHIFTSIEN, p->SHIFTEIEN, p->TIMIEN); Serial.flush();
      Serial.printf("SHIFTSDEN:%x SHIFTSTATE=%x\n", p->SHIFTSDEN, p->SHIFTSTATE); Serial.flush();
      Serial.printf("SHIFTCTL:%x %x %x %x\n", p->SHIFTCTL[0], p->SHIFTCTL[1], p->SHIFTCTL[2], p->SHIFTCTL[3]); Serial.flush();
      Serial.printf("SHIFTCFG:%x %x %x %x\n", p->SHIFTCFG[0], p->SHIFTCFG[1], p->SHIFTCFG[2], p->SHIFTCFG[3]); Serial.flush();
      Serial.printf("TIMCTL:%x %x %x %x\n", p->TIMCTL[0], p->TIMCTL[1], p->TIMCTL[2], p->TIMCTL[3]); Serial.flush();
      Serial.printf("TIMCFG:%x %x %x %x\n", p->TIMCFG[0], p->TIMCFG[1], p->TIMCFG[2], p->TIMCFG[3]); Serial.flush();
      Serial.printf("TIMCMP:%x %x %x %x\n", p->TIMCMP[0], p->TIMCMP[1], p->TIMCMP[2], p->TIMCMP[3]); Serial.flush();
      Serial.println("made it through");
    }
Code:
C:\Users\kurte\Documents\Arduino\Teensy Tests\Test_CrashReport\Test_CrashReport.ino Jun 24 2021 05:09:15
 millis() now 486

It's your fault!

Print out top of Vector table
0:677d
1:677d
2:677d
3:677d
4:677d
5:677d
6:677d
7:677d
8:677d
9:677d
10:677d
11:677d
12:677d
13:677d
14:809d
15:80a1
16:677d
17:677d
18:677d
19:677d
20:677d
21:677d
22:677d
23:677d
24:677d
25:677d
26:677d
27:677d
28:677d
29:677d
30:677d
31:677d
SCB_SHPRx: 0 0 20200000 SHCSR:0
SCB_SHCSR: 70000
Try FlexIO
401ac000
So The 3 bits are set. Note: the Interrupt priorities are still 0 for them.
Still hung.
 
Good Morning :)
It works for lpspi3.

0 is highest priority.
:D - Yep - But was not sure if that was good or bad in this case... That is being priority 0 did it precluded other things like USB...

As for LPSPI3 registers and sometimes with some LPUART it did not fault... Other times it did?
 
@Paul : also saw it noted that once a Fault occurs the MCU sees it basically as interrupt Pri -1 so all interrupts are then ignored.
That was when I pulled that code for T_3.6 - not sure it applies to 1062 and if it matters regarding the steps taken to manually stop all interrupts.

Regarding post #128 and added userCrashReport().

With that working when calling this on FAST restart :: if ( CrashReport ) {
<< This with EEPROM may work after CRASH in unused_interrupt_vector() - but that seems risky so not tried >>

It could do this in \cores\teensy4\CrashReport.cpp so that Crash reporting survives across power loss, once it gets restarted:
Code:
CrashReportClass::operator bool()
{
	struct arm_fault_info_struct *info = (struct arm_fault_info_struct *)0x2027FF80;
	if (isvalid(info)) {
	  [B]EEPROM.put( EEPROM.end()-(1+sizeof(info)), info );[/B] // save dup[licate of 'info' to EEPROM "last LEN DWORDS"
	  return true;
	}
	return false;
}
...
}[/CODE]

So ugly thing #1 is calling the Crash class from startup.c as noted in post #128
And #2 is this ??? :: #include <..\..\libraries\EEPROM\EEPROM.h>
And #3 it takes last 44 bytes of EEPROM at : EEPROM.end()-(1+sizeof(info))
I was wondering similar when I mentioned earlier wonder if we can keep it elsewhere...
Again wonder in two different ways:

Printed report after reboot - As example show we could detect !Serial and then see if SD available, or LFS...

Or something like EEPROM sort of as you mentioned, but was also thinking alternative, like maybe like reserve one (or more) Flash sectors, Just before EEPROM, that You write out the crash data. Probably walk your way down sector, writing each new crash so you don't have to erase... But probably still too much stuff to have to do in order to write a sector?
 
Back
Top