From 60445fbed3d440ba1dc769103e95e5c3c2130944 Mon Sep 17 00:00:00 2001 From: Matthew Kennedy Date: Thu, 5 Jan 2023 16:56:28 -0800 Subject: [PATCH] catch faults --- firmware/Makefile | 2 +- firmware/main.cpp | 100 ++++++++++++++++++++++++++++++++++ firmware/main_hardfault_asm.S | 35 ++++++++++++ 3 files changed, 136 insertions(+), 1 deletion(-) create mode 100644 firmware/main_hardfault_asm.S diff --git a/firmware/Makefile b/firmware/Makefile index 8f17205..ee7c9f9 100644 --- a/firmware/Makefile +++ b/firmware/Makefile @@ -164,7 +164,7 @@ CPPSRC = $(ALLCPPSRC) \ ASMSRC = $(ALLASMSRC) # List ASM with preprocessor source files here. -ASMXSRC = $(ALLXASMSRC) +ASMXSRC = $(ALLXASMSRC) main_hardfault_asm.S # Inclusion directories. INCDIR = $(CONFDIR) \ diff --git a/firmware/main.cpp b/firmware/main.cpp index b37f97e..010f1aa 100644 --- a/firmware/main.cpp +++ b/firmware/main.cpp @@ -15,6 +15,8 @@ #include "wideband_config.h" +#include + using namespace wbo; /* @@ -77,3 +79,101 @@ int main() { } } } + +typedef enum { + Reset = 1, + NMI = 2, + HardFault = 3, + MemManage = 4, + BusFault = 5, + UsageFault = 6, +} FaultType; + +#define bkpt() __asm volatile("BKPT #0\n") + +extern "C" void HardFault_Handler_C(void* sp) { + //Copy to local variables (not pointers) to allow GDB "i loc" to directly show the info + //Get thread context. Contains main registers including PC and LR + struct port_extctx ctx; + memcpy(&ctx, sp, sizeof(struct port_extctx)); + + //Interrupt status register: Which interrupt have we encountered, e.g. HardFault? + FaultType faultType = (FaultType)__get_IPSR(); + (void)faultType; + //For HardFault/BusFault this is the address that was accessed causing the error + uint32_t faultAddress = SCB->BFAR; + + //Flags about hardfault / busfault + //See http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0552a/Cihdjcfc.html for reference + bool isFaultPrecise = ((SCB->CFSR >> SCB_CFSR_BUSFAULTSR_Pos) & (1 << 1) ? true : false); + bool isFaultImprecise = ((SCB->CFSR >> SCB_CFSR_BUSFAULTSR_Pos) & (1 << 2) ? true : false); + bool isFaultOnUnstacking = ((SCB->CFSR >> SCB_CFSR_BUSFAULTSR_Pos) & (1 << 3) ? true : false); + bool isFaultOnStacking = ((SCB->CFSR >> SCB_CFSR_BUSFAULTSR_Pos) & (1 << 4) ? true : false); + bool isFaultAddressValid = ((SCB->CFSR >> SCB_CFSR_BUSFAULTSR_Pos) & (1 << 7) ? true : false); + (void)isFaultPrecise; + (void)isFaultImprecise; + (void)isFaultOnUnstacking; + (void)isFaultOnStacking; + (void)isFaultAddressValid; + + //Cause debugger to stop. Ignored if no debugger is attached + bkpt(); + NVIC_SystemReset(); +} + +extern "C" void UsageFault_Handler_C(void* sp) { + //Copy to local variables (not pointers) to allow GDB "i loc" to directly show the info + //Get thread context. Contains main registers including PC and LR + struct port_extctx ctx; + memcpy(&ctx, sp, sizeof(struct port_extctx)); + + //Interrupt status register: Which interrupt have we encountered, e.g. HardFault? + FaultType faultType = (FaultType)__get_IPSR(); + (void)faultType; + //Flags about hardfault / busfault + //See http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0552a/Cihdjcfc.html for reference + bool isUndefinedInstructionFault = ((SCB->CFSR >> SCB_CFSR_USGFAULTSR_Pos) & (1 << 0) ? true : false); + bool isEPSRUsageFault = ((SCB->CFSR >> SCB_CFSR_USGFAULTSR_Pos) & (1 << 1) ? true : false); + bool isInvalidPCFault = ((SCB->CFSR >> SCB_CFSR_USGFAULTSR_Pos) & (1 << 2) ? true : false); + bool isNoCoprocessorFault = ((SCB->CFSR >> SCB_CFSR_USGFAULTSR_Pos) & (1 << 3) ? true : false); + bool isUnalignedAccessFault = ((SCB->CFSR >> SCB_CFSR_USGFAULTSR_Pos) & (1 << 8) ? true : false); + bool isDivideByZeroFault = ((SCB->CFSR >> SCB_CFSR_USGFAULTSR_Pos) & (1 << 9) ? true : false); + (void)isUndefinedInstructionFault; + (void)isEPSRUsageFault; + (void)isInvalidPCFault; + (void)isNoCoprocessorFault; + (void)isUnalignedAccessFault; + (void)isDivideByZeroFault; + + bkpt(); + NVIC_SystemReset(); +} + +extern "C" void MemManage_Handler_C(void* sp) { + //Copy to local variables (not pointers) to allow GDB "i loc" to directly show the info + //Get thread context. Contains main registers including PC and LR + struct port_extctx ctx; + memcpy(&ctx, sp, sizeof(struct port_extctx)); + + //Interrupt status register: Which interrupt have we encountered, e.g. HardFault? + FaultType faultType = (FaultType)__get_IPSR(); + (void)faultType; + //For HardFault/BusFault this is the address that was accessed causing the error + uint32_t faultAddress = SCB->MMFAR; + + //Flags about hardfault / busfault + //See http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0552a/Cihdjcfc.html for reference + bool isInstructionAccessViolation = ((SCB->CFSR >> SCB_CFSR_MEMFAULTSR_Pos) & (1 << 0) ? true : false); + bool isDataAccessViolation = ((SCB->CFSR >> SCB_CFSR_MEMFAULTSR_Pos) & (1 << 1) ? true : false); + bool isExceptionUnstackingFault = ((SCB->CFSR >> SCB_CFSR_MEMFAULTSR_Pos) & (1 << 3) ? true : false); + bool isExceptionStackingFault = ((SCB->CFSR >> SCB_CFSR_MEMFAULTSR_Pos) & (1 << 4) ? true : false); + bool isFaultAddressValid = ((SCB->CFSR >> SCB_CFSR_MEMFAULTSR_Pos) & (1 << 7) ? true : false); + (void)isInstructionAccessViolation; + (void)isDataAccessViolation; + (void)isExceptionUnstackingFault; + (void)isExceptionStackingFault; + (void)isFaultAddressValid; + + bkpt(); + NVIC_SystemReset(); +} diff --git a/firmware/main_hardfault_asm.S b/firmware/main_hardfault_asm.S new file mode 100644 index 0000000..bd7f6eb --- /dev/null +++ b/firmware/main_hardfault_asm.S @@ -0,0 +1,35 @@ +.syntax unified +.cpu cortex-m3 +.thumb +.align 2 +.thumb_func + +.type HardFault_Handler, %function +.type UsageFault_Handler, %function +.type MemManage_Handler, %function + +.global HardFault_Handler +.global BusFault_Handler +HardFault_Handler: +BusFault_Handler: + tst LR, #4 + ite EQ + mrseq R0, MSP + mrsne R0, PSP + b HardFault_Handler_C + +.global UsageFault_Handler +UsageFault_Handler: + tst LR, #4 + ite EQ + mrseq R0, MSP + mrsne R0, PSP + b UsageFault_Handler_C + +.global MemManage_Handler +MemManage_Handler: + tst LR, #4 + ite EQ + mrseq R0, MSP + mrsne R0, PSP + b MemManage_Handler_C