Merge pull request #5847 from SenRamakri/sen_FaultHandler

Unify fault handling and add script to show faults
pull/6083/head
Cruz Monrreal 2018-02-12 17:17:44 -06:00 committed by GitHub
commit 84f42f671e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 1064 additions and 48 deletions

View File

@ -0,0 +1,158 @@
;/*
; * 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
#ifndef __DOMAIN_NS
#define __DOMAIN_NS 1
#endif
FAULT_TYPE_HARD_FAULT EQU 0x10
FAULT_TYPE_MEMMANAGE_FAULT EQU 0x20
FAULT_TYPE_BUS_FAULT EQU 0x30
FAULT_TYPE_USAGE_FAULT EQU 0x40
PRESERVE8
THUMB
AREA |.text|, CODE, READONLY
HardFault_Handler\
PROC
EXPORT HardFault_Handler
LDR R3,=FAULT_TYPE_HARD_FAULT
B Fault_Handler
ENDP
MemManage_Handler\
PROC
EXPORT MemManage_Handler
LDR R3,=FAULT_TYPE_MEMMANAGE_FAULT
B Fault_Handler
ENDP
BusFault_Handler\
PROC
EXPORT BusFault_Handler
LDR R3,=FAULT_TYPE_BUS_FAULT
B Fault_Handler
ENDP
UsageFault_Handler\
PROC
EXPORT UsageFault_Handler
LDR R3,=FAULT_TYPE_USAGE_FAULT
B Fault_Handler
ENDP
Fault_Handler PROC
EXPORT Fault_Handler
#if (__DOMAIN_NS == 1)
IMPORT osRtxInfo
IMPORT mbed_fault_handler
IMPORT mbed_fault_context
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,=mbed_fault_context
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
LDR R3,=mbed_fault_handler ; Load address of mbedFaultHandler
MOV R0,R12
LDR R1,=mbed_fault_context
LDR R2,=osRtxInfo
BLX R3
#endif
B . ; Just in case we come back here
ENDP
#endif
END

View File

@ -0,0 +1,194 @@
/*
* 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 "except.S"
.syntax unified
#ifndef __DOMAIN_NS
#define __DOMAIN_NS 1
#endif
.equ FAULT_TYPE_HARD_FAULT, 0x10
.equ FAULT_TYPE_MEMMANAGE_FAULT, 0x20
.equ FAULT_TYPE_BUS_FAULT, 0x30
.equ FAULT_TYPE_USAGE_FAULT, 0x40
.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:
#if (__DOMAIN_NS == 1)
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,=mbed_fault_context
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
LDR R3,=mbed_fault_handler // Load address of mbedFaultHandler
MOV R0,R12
LDR R1,=mbed_fault_context
LDR R2,=osRtxInfo
BLX R3
#endif
B . // Just in case we come back here
.fnend
.size Fault_Handler, .-Fault_Handler
#endif
.end

View File

@ -0,0 +1,151 @@
;/*
; * 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 );
; *
; * -----------------------------------------------------------------------------
; */
NAME except.S
FAULT_TYPE_HARD_FAULT EQU 0x10
FAULT_TYPE_MEMMANAGE_FAULT EQU 0x20
FAULT_TYPE_BUS_FAULT EQU 0x30
FAULT_TYPE_USAGE_FAULT EQU 0x40
#ifndef MBED_FAULT_HANDLER_DISABLED
#ifndef __DOMAIN_NS
#define __DOMAIN_NS 1
#endif
PRESERVE8
SECTION .rodata:DATA:NOROOT(2)
THUMB
SECTION .text:CODE:NOROOT(2)
HardFault_Handler
EXPORT HardFault_Handler
LDR R3,=FAULT_TYPE_HARD_FAULT
B Fault_Handler
MemManage_Handler
EXPORT MemManage_Handler
LDR R3,=FAULT_TYPE_MEMMANAGE_FAULT
B Fault_Handler
BusFault_Handler
EXPORT BusFault_Handler
LDR R3,=FAULT_TYPE_BUS_FAULT
B Fault_Handler
UsageFault_Handler
EXPORT UsageFault_Handler
LDR R3,=FAULT_TYPE_USAGE_FAULT
B Fault_Handler
Fault_Handler
EXPORT Fault_Handler
#if (__DOMAIN_NS == 1)
IMPORT osRtxInfo
IMPORT mbed_fault_context
IMPORT mbed_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,=mbed_fault_context
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
LDR R3,=mbed_fault_handler ; Load address of mbedFaultHandler
MOV R0,R12
LDR R1,=mbed_fault_context
LDR R2,=osRtxInfo
BLX R3
#endif
B . ; Just in case we come back here
#endif ; #if (MBED_FAULT_HANDLER_SUPPORT == 1)
END

View File

@ -0,0 +1,228 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2018 ARM Limited
*
* 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
*
* http://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.
*/
#include "rtx_os.h"
#include "mbed_rtx.h"
#include "mbed_rtx_fault_handler.h"
#include "hal/serial_api.h"
#ifndef MBED_FAULT_HANDLER_DISABLED
//Global for populating the context in exception handler
mbed_fault_context_t mbed_fault_context;
//Structure to capture the context
void fault_print_init(void);
void fault_print_str(char *fmtstr, uint32_t *values);
void hex_to_str(uint32_t value, char *hex_star);
void print_context_info(void);
void print_threads_info(osRtxThread_t *);
void print_thread(osRtxThread_t *thread);
void print_register(char *regtag, uint32_t regval);
#if DEVICE_SERIAL
extern int stdio_uart_inited;
extern serial_t stdio_uart;
#endif
//This is a handler function called from Fault handler to print the error information out.
//This runs in fault context and uses special functions(defined in mbed_rtx_fault_handler.c) to print the information without using C-lib support.
__NO_RETURN void mbed_fault_handler (uint32_t fault_type, void *mbed_fault_context_in, void *osRtxInfoIn)
{
fault_print_init();
fault_print_str("\n++ MbedOS Fault Handler ++\n\nFaultType: ",NULL);
switch( fault_type ) {
case HARD_FAULT_EXCEPTION:
fault_print_str("HardFault",NULL);
break;
case MEMMANAGE_FAULT_EXCEPTION:
fault_print_str("MemManageFault",NULL);
break;
case BUS_FAULT_EXCEPTION:
fault_print_str("BusFault",NULL);
break;
case USAGE_FAULT_EXCEPTION:
fault_print_str("UsageFault",NULL);
break;
default:
fault_print_str("Unknown Fault",NULL);
break;
}
fault_print_str("\n\nContext:",NULL);
print_context_info();
fault_print_str("\n\nThread Info:\nCurrent:",NULL);
print_thread(((osRtxInfo_t *)osRtxInfoIn)->thread.run.curr);
fault_print_str("\nNext:",NULL);
print_thread(((osRtxInfo_t *)osRtxInfoIn)->thread.run.next);
fault_print_str("\nWait Threads:",NULL);
osRtxThread_t *threads = ((osRtxInfo_t *)osRtxInfoIn)->thread.wait_list;
print_threads_info(threads);
fault_print_str("\nDelay Threads:",NULL);
threads = ((osRtxInfo_t *)osRtxInfoIn)->thread.delay_list;
print_threads_info(threads);
fault_print_str("\nIdle Thread:",NULL);
threads = ((osRtxInfo_t *)osRtxInfoIn)->thread.idle;
print_threads_info(threads);
fault_print_str("\n\n-- MbedOS Fault Handler --\n\n",NULL);
/* Just spin here, we have already crashed */
for (;;) {}
}
void print_context_info()
{
//Context Regs
fault_print_str( "\nR0 : %"
"\nR1 : %"
"\nR2 : %"
"\nR3 : %"
"\nR4 : %"
"\nR5 : %"
"\nR6 : %"
"\nR7 : %"
"\nR8 : %"
"\nR9 : %"
"\nR10 : %"
"\nR11 : %"
"\nR12 : %"
"\nSP : %"
"\nLR : %"
"\nPC : %"
"\nxPSR : %"
"\nPSP : %"
"\nMSP : %", (uint32_t *)&mbed_fault_context);
//Capture CPUID to get core/cpu info
fault_print_str("\nCPUID: %",(uint32_t *)&SCB->CPUID);
#if !defined(TARGET_M0) && !defined(TARGET_M0P)
//Capture fault information registers to infer the cause of exception
uint32_t FSR[7] = {0};
FSR[0] = SCB->HFSR;
//Split/Capture CFSR into MMFSR, BFSR, UFSR
FSR[1] = 0xFF & SCB->CFSR;//MMFSR
FSR[2] = (0xFF00 & SCB->CFSR) >> 8;//BFSR
FSR[3] = (0xFFFF0000 & SCB->CFSR) >> 16;//UFSR
FSR[4] = SCB->DFSR;
FSR[5] = SCB->AFSR;
FSR[6] = SCB->SHCSR;
fault_print_str("\nHFSR : %"
"\nMMFSR: %"
"\nBFSR : %"
"\nUFSR : %"
"\nDFSR : %"
"\nAFSR : %"
"\nSHCSR: %",FSR);
//Print MMFAR only if its valid as indicated by MMFSR
if(FSR[1] & 0x80) {
fault_print_str("\nMMFAR: %",(uint32_t *)&SCB->MMFAR);
}
//Print BFAR only if its valid as indicated by BFSR
if(FSR[2] & 0x80) {
fault_print_str("\nBFAR : %",(uint32_t *)&SCB->BFAR);
}
#endif
}
/* Prints thread info from a list */
void print_threads_info(osRtxThread_t *threads)
{
while(threads != NULL) {
print_thread( threads );
threads = threads->thread_next;
}
}
/* Prints info of a thread(using osRtxThread_t struct)*/
void print_thread(osRtxThread_t *thread)
{
uint32_t data[5];
data[0]=thread->state;
data[1]=thread->thread_addr;
data[2]=thread->stack_size;
data[3]=(uint32_t)thread->stack_mem;
data[4]=thread->sp;
fault_print_str("\nState: % EntryFn: % Stack Size: % Mem: % SP: %", data);
}
/* Initializes std uart for spitting the info out */
void fault_print_init()
{
#if DEVICE_SERIAL
if (!stdio_uart_inited) {
serial_init(&stdio_uart, STDIO_UART_TX, STDIO_UART_RX);
}
#endif
}
/* Limited print functionality which prints the string out to
stdout/uart without using stdlib by directly calling serial-api
and also uses less resources
The fmtstr contains the format string for printing and for every %
found in that it fetches a uint32 value from values buffer
and prints it in hex format.
*/
void fault_print_str(char *fmtstr, uint32_t *values)
{
#if DEVICE_SERIAL
int i = 0;
int idx = 0;
int vidx = 0;
char hex_str[9]={0};
while(fmtstr[i] != '\0') {
if(fmtstr[i] == '\n' || fmtstr[i] == '\r') {
serial_putc(&stdio_uart, '\r');
} else {
if(fmtstr[i]=='%') {
hex_to_str(values[vidx++],hex_str);
for(idx=7; idx>=0; idx--) {
serial_putc(&stdio_uart, hex_str[idx]);
}
} else {
serial_putc(&stdio_uart, fmtstr[i]);
}
}
i++;
}
#endif
}
/* Converts a uint32 to hex char string */
void hex_to_str(uint32_t value, char *hex_str)
{
char hex_char_map[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
int i = 0;
//Return without converting if hex_str is not provided
if(hex_str == NULL) return;
for(i=7; i>=0; i--) {
hex_str[i] = hex_char_map[(value & (0xf << (i * 4))) >> (i * 4)];
}
}
#endif //MBED_FAULT_HANDLER_SUPPORT

View File

@ -0,0 +1,52 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2018 ARM Limited
*
* 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
*
* http://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.
*/
//Fault context struct
//WARNING: DO NOT CHANGE THIS STRUCT WITHOUT MAKING CORRESPONDING CHANGES in except.S files.
//Offset of these registers are used by fault handler in except.S
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;
} mbed_fault_context_t;
//Fault type definitions
//WARNING: DO NOT CHANGE THESE VALUES WITHOUT MAKING CORRESPONDING CHANGES in except.S files.
#define HARD_FAULT_EXCEPTION (0x10) //Keep some gap between values for any future insertion/expansion
#define MEMMANAGE_FAULT_EXCEPTION (0x20)
#define BUS_FAULT_EXCEPTION (0x30)
#define USAGE_FAULT_EXCEPTION (0x40)
//This is a handler function called from Fault handler to print the error information out.
//This runs in fault context and uses special functions(defined in mbed_rtx_fault_handler.c) to print the information without using C-lib support.
__NO_RETURN void mbed_fault_handler (uint32_t fault_type, void *mbed_fault_context_in, void *osRtxInfoIn);

View File

@ -68,12 +68,6 @@ void NotImplemented_Handler(void)
while (1) {};
}
/** Hardware fault interrupt handler */
void HardFault_Handler(void)
{
while (1) {};
}
/*************************************************************************************************
* *
* Functions *

View File

@ -236,11 +236,3 @@ uint8_t SetSysClock_PLL_HSI(void)
return 1; // OK
}
/******************************************************************************/
/* Hard Fault Handler */
/******************************************************************************/
void HardFault_Handler(void)
{
debug("Hard Fault\n");
NVIC_SystemReset();
}

View File

@ -236,11 +236,3 @@ uint8_t SetSysClock_PLL_HSI(void)
return 1; // OK
}
/******************************************************************************/
/* Hard Fault Handler */
/******************************************************************************/
void HardFault_Handler(void)
{
debug("Hard Fault\n");
NVIC_SystemReset();
}

View File

@ -238,11 +238,3 @@ uint8_t SetSysClock_PLL_HSI(void)
return 1; // OK
}
/******************************************************************************/
/* Hard Fault Handler */
/******************************************************************************/
void HardFault_Handler(void)
{
debug("Hard Fault\n");
NVIC_SystemReset();
}

View File

@ -249,12 +249,4 @@ uint8_t SetSysClock_PLL_HSI(void)
return 1; // OK
}
/******************************************************************************/
/* Hard Fault Handler */
/******************************************************************************/
void HardFault_Handler(void)
{
debug("Hard Fault\n");
NVIC_SystemReset();
}

View File

@ -249,12 +249,4 @@ uint8_t SetSysClock_PLL_HSI(void)
return 1; // OK
}
/******************************************************************************/
/* Hard Fault Handler */
/******************************************************************************/
void HardFault_Handler(void)
{
debug("Hard Fault\n");
NVIC_SystemReset();
}

View File

@ -3718,7 +3718,7 @@
}
},
"inherits": ["Target"],
"macros": ["CMSIS_VECTAB_VIRTUAL", "CMSIS_VECTAB_VIRTUAL_HEADER_FILE=\"cmsis_nvic.h\""],
"macros": ["CMSIS_VECTAB_VIRTUAL", "CMSIS_VECTAB_VIRTUAL_HEADER_FILE=\"cmsis_nvic.h\"","MBED_FAULT_HANDLER_DISABLED"],
"device_has": ["ANALOGIN", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", "STDIO_MESSAGES", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH"],
"release_versions": ["5"],
"device_name": "NANO130KE3BN"
@ -3756,7 +3756,7 @@
"inherits": ["Target"],
"detect_code": ["4600"],
"extra_labels": ["Realtek", "AMEBA", "RTL8195A"],
"macros": ["__RTL8195A__","CONFIG_PLATFORM_8195A","CONFIG_MBED_ENABLED","PLATFORM_CMSIS_RTOS"],
"macros": ["__RTL8195A__","CONFIG_PLATFORM_8195A","CONFIG_MBED_ENABLED","PLATFORM_CMSIS_RTOS","MBED_FAULT_HANDLER_DISABLED"],
"supported_toolchains": ["GCC_ARM", "ARM", "IAR"],
"device_has": ["ANALOGIN", "ANALOGOUT", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SPI", "TRNG", "EMAC", "FLASH"],
"features": ["LWIP"],

View File

@ -0,0 +1,79 @@
## Crash Log Parser Tool
This post-processing tool can be used to parse crash log generated by Mbed-OS when an exception happens.
## Capturing crash log
When an exception happens Mbed-OS will print out the crash information to STDOUT.
The crash information contains register context at the time exception and current threads in the system.
The information printed out to STDOUT will be similar to below. Registers captured depends on specific
Cortex-M core you are using. For example, if your target is using Cortex-M0, some registers like
MMFSR, BFSR, UFSR may not be available and will not appear in the crash log.
++ MbedOS Fault Handler ++
FaultType: HardFault
Context:
R0 : 0000AAA3
R1 : 20002070
R2 : 00009558
R3 : 00412A02
R4 : E000ED14
R5 : 00000000
R6 : 00000000
R7 : 00000000
R8 : 00000000
R9 : 00000000
R10 : 00000000
R11 : 00000000
R12 : 0000BCE5
SP : 20002070
LR : 00009E75
PC : 00009512
xPSR : 01000000
PSP : 20002008
MSP : 2002FFD8
CPUID: 410FC241
HFSR : 40000000
MMFSR: 00000000
BFSR : 00000000
UFSR : 00000100
DFSR : 00000008
AFSR : 00000000
SHCSR: 00000000
Thread Info:
Current:
State: 00000002 EntryFn: 0000ADF5 Stack Size: 00001000 Mem: 20001070 SP: 20002030
Next:
State: 00000002 EntryFn: 0000ADF5 Stack Size: 00001000 Mem: 20001070 SP: 20002030
Wait Threads:
State: 00000083 EntryFn: 0000AA1D Stack Size: 00000300 Mem: 20000548 SP: 200007D8
Delay Threads:
Idle Thread:
State: 00000001 EntryFn: 00009F59 Stack Size: 00000200 Mem: 20000348 SP: 20000508
-- MbedOS Fault Handler --
To generate more information copy and save this crash information to a text file and run the crash_log_parser.py tool as below.
NOTE: Make sure you copy the section with text "MbedOS Fault Handler" as the this tool looks for that header.
## Running the Crash Log Parser
crash_log_parser.py <Path to Crash log> <Path to Elf/Axf file of the build> <Path to Map file of the build>
For example:
crashlogparse.py crash.log C:\MyProject\BUILD\k64f\arm\mbed-os-hf-handler.elf C:\MyProject\BUILD\k64f\arm\mbed-os-hf-handler.map
An example output from running crash_log_parser is shown below.
Parsed Crash Info:
Crash location = zero_div_test() [0000693E]
Caller location = $Super$$main [00009E99]
Stack Pointer at the time of crash = [20001CC0]
Target/Fault Info:
Processor Arch: ARM-V7M or above
Processor Variant: C24
Forced exception, a fault with configurable priority has been escalated to HardFault
Divide by zero error has occurred
Done parsing...

View File

@ -0,0 +1,200 @@
#!/usr/bin/env python
"""
mbed SDK
Copyright (c) 2017-2019 ARM Limited
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
http://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.
LIBRARIES BUILD
"""
from __future__ import print_function
from os import path
import re
import bisect
from subprocess import check_output
import sys
#arm-none-eabi-nm -nl <elf file>
_NM_EXEC = "arm-none-eabi-nm"
_OPT = "-nlC"
_PTN = re.compile("([0-9a-f]*) ([Tt]) ([^\t\n]*)(?:\t(.*):([0-9]*))?")
class ElfHelper(object):
def __init__(self, elf_file, map_file):
op = check_output([_NM_EXEC, _OPT, elf_file.name])
self.maplines = map_file.readlines()
self.matches = _PTN.findall(op)
self.addrs = [int(x[0], 16) for x in self.matches]
def function_addrs(self):
return self.addrs
def function_name_for_addr(self, addr):
i = bisect.bisect_right(self.addrs, addr)
funcname = self.matches[i-1][2]
return funcname
def print_HFSR_info(hfsr):
if int(hfsr, 16) & 0x80000000:
print("\t\tDebug Event Occured")
if int(hfsr, 16) & 0x40000000:
print("\t\tForced exception, a fault with configurable priority has been escalated to HardFault")
if int(hfsr, 16) & 0x2:
print("\t\tVector table read fault has occurred")
def print_MMFSR_info(mmfsr, mmfar):
if int(mmfsr, 16) & 0x20:
print("\t\tA MemManage fault occurred during FP lazy state preservation")
if int(mmfsr, 16) & 0x10:
print("\t\tA derived MemManage fault occurred on exception entry")
if int(mmfsr, 16) & 0x8:
print("\t\tA derived MemManage fault occurred on exception return")
if int(mmfsr, 16) & 0x2:
if int(mmfsr, 16) & 0x80:
print("\t\tData access violation. Faulting address: %s"%(str(mmfar)))
else:
print("\t\tData access violation. WARNING: Fault address in MMFAR is NOT valid")
if int(mmfsr, 16) & 0x1:
print("\t\tMPU or Execute Never (XN) default memory map access violation on an instruction fetch has occurred")
def print_BFSR_info(bfsr, bfar):
if int(bfsr, 16) & 0x20:
print("\t\tA bus fault occurred during FP lazy state preservation")
if int(bfsr, 16) & 0x10:
print("\t\tA derived bus fault has occurred on exception entry")
if int(bfsr, 16) & 0x8:
print("\t\tA derived bus fault has occurred on exception return")
if int(bfsr, 16) & 0x4:
print("\t\tImprecise data access error has occurred")
if int(bfsr, 16) & 0x2:
if int(bfsr,16) & 0x80:
print("\t\tA precise data access error has occurred. Faulting address: %s"%(str(bfar)))
else:
print("\t\tA precise data access error has occurred. WARNING: Fault address in BFAR is NOT valid")
if int(bfsr, 16) & 0x1:
print("\t\tA bus fault on an instruction prefetch has occurred")
def print_UFSR_info(ufsr):
if int(ufsr, 16) & 0x200:
print("\t\tDivide by zero error has occurred")
if int(ufsr, 16) & 0x100:
print("\t\tUnaligned access error has occurred")
if int(ufsr, 16) & 0x8:
print("\t\tA coprocessor access error has occurred. This shows that the coprocessor is disabled or not present")
if int(ufsr, 16) & 0x4:
print("\t\tAn integrity check error has occurred on EXC_RETURN")
if int(ufsr, 16) & 0x2:
print("\t\tInstruction executed with invalid EPSR.T or EPSR.IT field( This may be caused by Thumb bit not being set in branching instruction )")
if int(ufsr, 16) & 0x1:
print("\t\tThe processor has attempted to execute an undefined instruction")
def print_CPUID_info(cpuid):
if (int(cpuid, 16) & 0xF0000) == 0xC0000:
print("\t\tProcessor Arch: ARM-V6M")
else:
print("\t\tProcessor Arch: ARM-V7M or above")
print("\t\tProcessor Variant: %X" % ((int(cpuid,16) & 0xFFF0 ) >> 4))
def parse_line_for_register(line):
_, register_val = line.split(":")
return register_val.strip()
def main(crash_log, elfhelper):
mmfar_val = 0
bfar_val = 0
lines = iter(crash_log.readlines())
for eachline in lines:
if "++ MbedOS Fault Handler ++" in eachline:
break
else:
print("ERROR: Unable to find \"MbedOS Fault Handler\" header")
return
for eachline in lines:
if "-- MbedOS Fault Handler --" in eachline:
break
elif eachline.startswith("PC"):
pc_val = parse_line_for_register(eachline)
pc_name = elfhelper.function_name_for_addr(int(pc_val, 16))
elif eachline.startswith("LR"):
lr_val = parse_line_for_register(eachline)
lr_name = elfhelper.function_name_for_addr(int(lr_val, 16))
elif eachline.startswith("SP"):
sp_val = parse_line_for_register(eachline)
elif eachline.startswith("HFSR"):
hfsr_val = parse_line_for_register(eachline)
elif eachline.startswith("MMFSR"):
mmfsr_val = parse_line_for_register(eachline)
elif eachline.startswith("BFSR"):
bfsr_val = parse_line_for_register(eachline)
elif eachline.startswith("UFSR"):
ufsr_val = parse_line_for_register(eachline)
elif eachline.startswith("CPUID"):
cpuid_val = parse_line_for_register(eachline)
elif eachline.startswith("MMFAR"):
mmfar_val = parse_line_for_register(eachline)
elif eachline.startswith("BFAR"):
bfar_val = parse_line_for_register(eachline)
print("\nCrash Info:")
print("\tCrash location = %s [0x%s] (based on PC value)" % (pc_name.strip(), str(pc_val)))
print("\tCaller location = %s [0x%s] (based on LR value)" % (lr_name.strip(), str(lr_val)))
print("\tStack Pointer at the time of crash = [%s]" % (str(sp_val)))
print("\tTarget and Fault Info:")
print_CPUID_info(cpuid_val)
print_HFSR_info(hfsr_val)
print_MMFSR_info(mmfsr_val, mmfar_val)
print_BFSR_info(bfsr_val, bfar_val)
print_UFSR_info(ufsr_val)
if __name__ == '__main__':
import argparse
parser = argparse.ArgumentParser(description='Analyse mbed-os crash log. This tool requires arm-gcc binary utilities to be available in current path as it uses \'nm\' command')
# specify arguments
parser.add_argument(metavar='CRASH LOG', type=argparse.FileType('rb', 0),
dest='crashlog',help='path to crash log file')
parser.add_argument(metavar='ELF FILE', type=argparse.FileType('rb', 0),
dest='elffile',help='path to elf file')
parser.add_argument(metavar='MAP FILE', type=argparse.FileType('rb', 0),
dest='mapfile',help='path to map file')
# get and validate arguments
args = parser.parse_args()
elfhelper = ElfHelper(args.elffile, args.mapfile)
# parse input and write to output
main(args.crashlog, elfhelper)
#close all files
args.elffile.close()
args.mapfile.close()
args.crashlog.close()