diff --git a/Src/stm32f4xx_it.c b/Src/stm32f4xx_it.c index dc33684..44d9362 100644 --- a/Src/stm32f4xx_it.c +++ b/Src/stm32f4xx_it.c @@ -34,6 +34,10 @@ /* Private typedef -----------------------------------------------------------*/ /* USER CODE BEGIN TD */ +#define HardFault_Handler(x) __attribute__((weak)) HardFault_Handler(x) +#define MemManage_Handler(x) __attribute__((weak)) MemManage_Handler(x) +#define BusFault_Handler(x) __attribute__((weak)) BusFault_Handler(x) +#define UsageFault_Handler(x) __attribute__((weak)) UsageFault_Handler(x) /* USER CODE END TD */ diff --git a/lib/fault.c b/lib/fault.c new file mode 100644 index 0000000..880c4a0 --- /dev/null +++ b/lib/fault.c @@ -0,0 +1,161 @@ +/* + * fault.c + * + * Created on: Oct 1, 2019 + * Author: abody + * -c "tpiu config internal uart off " + */ +#include +//#include +#include "stm32f4xx.h" +#include "strutil.h" + +#define HARD_FAULT 1 +#define MEMMANAGE_FAULT 2 +#define BUS_FAULT 3 +#define USAGE_FAULT 4 + + +typedef struct { + uint32_t R0; + uint32_t R1; + uint32_t R2; + uint32_t R3; + uint32_t R4; + uint32_t R5; + uint32_t R6; + uint32_t R7; + uint32_t R8; + uint32_t R9; + uint32_t R10; + uint32_t R11; + uint32_t R12; + uint32_t SP; + uint32_t LR; + uint32_t PC; + uint32_t xPSR; + uint32_t PSP; + uint32_t MSP; + uint32_t EXC_RETURN; + uint32_t CONTROL; +} fault_context_t; + +fault_context_t g_faultContext; + +void SwoSendStr(char const *str, uint8_t len, uint8_t port) +{ + while(len) { + if (((ITM->TCR & ITM_TCR_ITMENA_Msk) != 0UL) && // ITM enabled + ((ITM->TER & (1UL << port) ) != 0UL) ) // ITM Port enabled + { + // Wait until shift register is free + while (ITM->PORT[port].u32 == 0UL) { + __ASM volatile ("nop"); + } + if(len >= 4) { + ITM->PORT[port].u32 = *(uint32_t*)(str); + str += 4; + len -= 4; + } else if(len >= 2) { + ITM->PORT[port].u16 = *(uint16_t*)(str); + str += 2; + len -= 2; + } else { + ITM->PORT[port].u8 = *(uint8_t*)(str); + ++str; + --len; + } + } else + break; + } +} + +void fault_print_str(char *fmtstr, uint32_t *values) +{ + char hex_str[9]={0}; + char *nextChunk = fmtstr; + + while(*fmtstr) { + if(*fmtstr == '%') { + SwoSendStr(nextChunk, fmtstr-nextChunk, 0); + uitohex(hex_str, *values++, 8); + SwoSendStr(hex_str, 8, 0); + nextChunk = fmtstr +1; + } + ++fmtstr; + } + if(nextChunk != fmtstr) + SwoSendStr(nextChunk, fmtstr-nextChunk, 0); +} + + + +__attribute__((noreturn)) void FaultHandler(uint32_t type, fault_context_t *context) +{ + uint32_t FSR[9] = { + SCB->HFSR, + 0xff & SCB->CFSR, + (0xff00 & SCB->CFSR) >> 8, + (0xffff0000 & SCB->CFSR) >> 16, + SCB->DFSR, + SCB->AFSR, + SCB->SHCSR, + SCB->MMFAR, + SCB->BFAR + }; + + while(1) { + fault_print_str("\n++ Fault Handler ++\n\nFaultType: ",NULL); + switch( type ) { + case HARD_FAULT: + fault_print_str("HardFault",NULL); + break; + case MEMMANAGE_FAULT: + fault_print_str("MemManageFault",NULL); + break; + case BUS_FAULT: + fault_print_str("BusFault",NULL); + break; + case USAGE_FAULT: + fault_print_str("UsageFault",NULL); + break; + default: + fault_print_str("Unknown Fault",NULL); + break; + } + + fault_print_str("\n\nContext:",NULL); + + fault_print_str( "\nR0 : %" + "\nR1 : %" + "\nR2 : %" + "\nR3 : %" + "\nR4 : %" + "\nR5 : %" + "\nR6 : %" + "\nR7 : %" + "\nR8 : %" + "\nR9 : %" + "\nR10 : %" + "\nR11 : %" + "\nR12 : %" + "\nSP : %" + "\nLR : %" + "\nPC : %" + "\nxPSR : %" + "\nPSP : %" + "\nMSP : %", (uint32_t *)context); + + //Capture CPUID to get core/cpu info + fault_print_str("\nCPUID: %",(uint32_t *)&SCB->CPUID); + + fault_print_str("\nHFSR : %" + "\nMMFSR: %" + "\nBFSR : %" + "\nUFSR : %" + "\nDFSR : %" + "\nAFSR : %" + "\nSHCSR: %",FSR); + } +} + diff --git a/lib/fault_asm.s b/lib/fault_asm.s new file mode 100644 index 0000000..4474bd7 --- /dev/null +++ b/lib/fault_asm.s @@ -0,0 +1,190 @@ +/* + * Copyright (c) 2014-2018 ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ----------------------------------------------------------------------------- + * + * Title: Cortex-M Fault Exception handlers ( Common for both ARMv7M and ARMV6M ) + * + * ----------------------------------------------------------------------------- + */ +#ifndef MBED_FAULT_HANDLER_DISABLED + + .file "fault_asm.S" + .syntax unified + + .equ FAULT_TYPE_HARD_FAULT, 1 + .equ FAULT_TYPE_MEMMANAGE_FAULT, 2 + .equ FAULT_TYPE_BUS_FAULT, 3 + .equ FAULT_TYPE_USAGE_FAULT, 4 + + .thumb + .section ".text" + .align 2 + +//HardFault_Handler + .thumb_func + .type HardFault_Handler, %function + .global HardFault_Handler + .fnstart + .cantunwind + +HardFault_Handler: + LDR R3,=FAULT_TYPE_HARD_FAULT + B Fault_Handler + + .fnend + .size HardFault_Handler, .-HardFault_Handler + +//MemManage_Handler + .thumb_func + .type MemManage_Handler, %function + .global MemManage_Handler + .fnstart + .cantunwind + +MemManage_Handler: + LDR R3,=FAULT_TYPE_MEMMANAGE_FAULT + B Fault_Handler + + .fnend + .size MemManage_Handler, .-MemManage_Handler + +//BusFault_Handler + .thumb_func + .type BusFault_Handler, %function + .global BusFault_Handler + .fnstart + .cantunwind + +BusFault_Handler: + LDR R3,=FAULT_TYPE_BUS_FAULT + B Fault_Handler + + .fnend + .size BusFault_Handler, .-BusFault_Handler + +//UsageFault_Handler + .thumb_func + .type UsageFault_Handler, %function + .global UsageFault_Handler + .fnstart + .cantunwind + +UsageFault_Handler: + LDR R3,=FAULT_TYPE_USAGE_FAULT + B Fault_Handler + + .fnend + .size UsageFault_Handler, .-UsageFault_Handler + +//Common Fault_Handler to capture the context + .thumb_func + .type Fault_Handler, %function + .global Fault_Handler + .fnstart + .cantunwind + +Fault_Handler: + MRS R0,MSP + LDR R1,=0x4 + MOV R2,LR + TST R2,R1 // Check EXC_RETURN for bit 2 + BEQ Fault_Handler_Continue + MRS R0,PSP + +Fault_Handler_Continue: + MOV R12,R3 + LDR R1,=g_faultContext + LDR R2,[R0] // Capture R0 + STR R2,[R1] + ADDS R1,#4 + LDR R2,[R0,#4] // Capture R1 + STR R2,[R1] + ADDS R1,#4 + LDR R2,[R0,#8] // Capture R2 + STR R2,[R1] + ADDS R1,#4 + LDR R2,[R0,#12] // Capture R3 + STR R2,[R1] + ADDS R1,#4 + STMIA R1!,{R4-R7} // Capture R4..R7 + MOV R7,R8 // Capture R8 + STR R7,[R1] + ADDS R1,#4 + MOV R7,R9 // Capture R9 + STR R7,[R1] + ADDS R1,#4 + MOV R7,R10 // Capture R10 + STR R7,[R1] + ADDS R1,#4 + MOV R7,R11 // Capture R11 + STR R7,[R1] + ADDS R1,#4 + LDR R2,[R0,#16] // Capture R12 + STR R2,[R1] + ADDS R1,#8 // Add 8 here to capture LR next, we will capture SP later + LDR R2,[R0,#20] // Capture LR + STR R2,[R1] + ADDS R1,#4 + LDR R2,[R0,#24] // Capture PC + STR R2,[R1] + ADDS R1,#4 + LDR R2,[R0,#28] // Capture xPSR + STR R2,[R1] + ADDS R1,#4 + // Adjust stack pointer to its original value and capture it + MOV R3,R0 + ADDS R3,#0x20 // Add 0x20 to get the SP value prior to exception + LDR R6,=0x200 + TST R2,R6 // Check for if STK was aligned by checking bit-9 in xPSR value + BEQ Fault_Handler_Continue1 + ADDS R3,#0x4 + +Fault_Handler_Continue1: + MOV R5,LR + LDR R6,=0x10 // Check for bit-4 to see if FP context was saved + TST R5,R6 + BNE Fault_Handler_Continue2 + ADDS R3,#0x48 // 16 FP regs + FPCSR + 1 Reserved + +Fault_Handler_Continue2: + MOV R4,R1 + SUBS R4,#0x10 // Set the location of SP in ctx + STR R3,[R4] // Capture the adjusted SP + MRS R2,PSP // Get PSP + STR R2,[R1] + ADDS R1,#4 + MRS R2,MSP // Get MSP + STR R2,[R1] + ADDS R1,#4 + MOV R2,LR // Get current LR(EXC_RETURN) + STR R2,[R1] + ADDS R1,#4 + MRS R2,CONTROL // Get CONTROL Reg + STR R2,[R1] + LDR R3,=FaultHandler // Load address of mbedFaultHandler + MOV R0,R12 + LDR R1,=g_faultContext + BLX R3 + B . // Just in case we come back here + + .fnend + .size Fault_Handler, .-Fault_Handler + +#endif + + .end