Reboot out of control in hardfault handler

Status
Not open for further replies.

Jacob.Schultz

Active member
I have a problem with following code, the Teensy board reboots before the hardfault handler is finished printing out the message. It's like a hidden watchdog :) It seems to be a specific problem with core/teensy3 and not if i try another framework. Any suggestions.

debug.h
Code:
#ifndef DEBUG_H_
#define DEBUG_H_

#include <Arduino.h>

namespace debug {

void init(Stream & stream);
void dumpHex(uint8_t *data, int len);

// Causes all BusFaults to be precise, but cost performance.
void disableWriteBuffer(bool disabled);

} // namespace

#endif /* DEBUG_H_ */

debug.cpp
Code:
#include "debug.h"

// TODO defined in core_cm4.h but CMSIS seems to be broken.
#define SCnSCB_ACTLR 	(*(volatile uint32_t *)0xE000E008)
#define SCnSCB_ACTLR_DISDEFWBUF 2

extern "C" void HardFault_Handler();

static Stream *dout;

namespace debug {

void init(Stream & stream)
{
	dout = &stream;
	_VectorsRam[3] = HardFault_Handler;
}

void dumpHex(uint8_t *data, int len)
{
	int i, dpos = 0;
	char buf[17];

	buf[16] = '\0';
	for (i=0; i<len; i++) {
		buf[dpos] = (isprint(*data)) ? *data : '.';
		if (dpos == 0)
			dout->printf("%08x ", data);
		dout->printf("%02x ", *data++);
		if (dpos == 15) {
			dout->printf("  %s\n\r", buf);
			dpos = 0;
		}
		else
			dpos++;
	}
	if (dpos) {
		for (i=0; i<(16-dpos); i++)
			dout->print("   ");
		buf[dpos] = '\0';
		dout->printf("  %s\n\r", buf);
	}
}

void disableWriteBuffer(bool disabled)
{
	if (disabled) {
		SCnSCB_ACTLR |= SCnSCB_ACTLR_DISDEFWBUF;
	}
	else {
		SCnSCB_ACTLR &= ~SCnSCB_ACTLR_DISDEFWBUF;
	}
}

}	// namespace

extern "C" void debugHardfault(uint32_t *sp)
{
    uint32_t cfsr  = SCB_CFSR;
    uint32_t afsr  = SCB_AFAR;  // TODO Name error should be AFSR
    uint32_t dfsr  = SCB_DFSR;
    uint32_t hfsr  = SCB_HFSR;
    uint32_t mmfar = SCB_MMFAR;
    uint32_t bfar  = SCB_BFAR;
    uint32_t r0  = sp[0];
    uint32_t r1  = sp[1];
    uint32_t r2  = sp[2];
    uint32_t r3  = sp[3];
    uint32_t r12 = sp[4];
    uint32_t lr  = sp[5];
    uint32_t pc  = sp[6];
    uint32_t psr = sp[7];
    dout->println("\n\rHardFault:");
    dout->printf("SCB->CFSR  0x%08lx\n\r", cfsr);
    dout->printf("SCB->AFSR  0x%08lx\n\r", afsr);
    dout->printf("SCB->DFSR  0x%08lx\n\r", dfsr);
    dout->printf("SCB->HFSR  0x%08lx\n\r", hfsr);
    dout->printf("SCB->MMFAR 0x%08lx\n\r", mmfar);
    dout->printf("SCB->BFAR  0x%08lx\n\r", bfar);
    dout->printf("SP   0x%08lx\n\r", (uint32_t)sp);
    dout->printf("R0   0x%08lx\n\r", r0);
    dout->printf("R1   0x%08lx\n\r", r1);
    dout->printf("R2   0x%08lx\n\r", r2);
    dout->printf("R3   0x%08lx\n\r", r3);
    dout->printf("R12  0x%08lx\n\r", r12);
    dout->printf("LR   0x%08lx\n\r", lr);
    dout->printf("PC   0x%08lx\n\r", pc);
    dout->printf("PSR  0x%08lx\n\r", psr);

    dout->println("Stack:");
    debug::dumpHex(reinterpret_cast<uint8_t *>(&sp[8]), 64);
    for(;;)	{}
}

void HardFault_Handler()
{
    __asm volatile
    (
        "tst lr, #4                                 \n"
        "ite eq                                     \n"
        "mrseq r0, msp                              \n"
        "mrsne r0, psp                              \n"
        "b %0                                       \n"
    	::"i"(debugHardfault):"r0", "memory"
    );
}

main.ino
Code:
#include <Arduino.h>
#include "debug.h"

void setup()
{
	delay(1000);  // USB won't be ready for debug output immediately.
	Serial1.begin(921600);
	debug::init(Serial1);
	//debug::dumpHex(stack1, 512);

	void (*crashfunc)() = nullptr;
	crashfunc();
}

void loop(void)
{
	// Unused
}
 
I found the problem, was just too tired. I exceed the stack in the hex dump. The stream library does not appear to be reliable for debugging it never finishes the output.
 
Status
Not open for further replies.
Back
Top