Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 2 of 2

Thread: Reboot out of control in hardfault handler

  1. #1

    Reboot out of control in hardfault handler

    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
    }

  2. #2
    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.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •