mirror of https://github.com/ARMmbed/mbed-os.git
Merge pull request #5847 from SenRamakri/sen_FaultHandler
Unify fault handling and add script to show faultspull/6083/head
commit
84f42f671e
|
@ -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
|
|
@ -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
|
||||
|
||||
|
|
@ -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
|
|
@ -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
|
|
@ -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);
|
||||
|
|
@ -68,12 +68,6 @@ void NotImplemented_Handler(void)
|
|||
while (1) {};
|
||||
}
|
||||
|
||||
/** Hardware fault interrupt handler */
|
||||
void HardFault_Handler(void)
|
||||
{
|
||||
while (1) {};
|
||||
}
|
||||
|
||||
/*************************************************************************************************
|
||||
* *
|
||||
* Functions *
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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"],
|
||||
|
|
|
@ -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...
|
||||
|
|
@ -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()
|
||||
|
Loading…
Reference in New Issue