mirror of https://github.com/ARMmbed/mbed-os.git
				
				
				
			Merge pull request #12824 from kjbracey-arm/faultasm
Optimise fault handler assemblypull/13152/head
						commit
						62c2431344
					
				| 
						 | 
				
			
			@ -36,7 +36,7 @@ static mbed_error_ctx saved_error_ctx = {0};
 | 
			
		|||
void mbed_error_reboot_callback(mbed_error_ctx *error_context)
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
    TEST_ASSERT_EQUAL_UINT((uint32_t)error_context, ERROR_CONTEXT_LOCATION);
 | 
			
		||||
    TEST_ASSERT_EQUAL_PTR(error_context, &MBED_CRASH_DATA);
 | 
			
		||||
    memcpy(&saved_error_ctx, error_context, sizeof(mbed_error_ctx));
 | 
			
		||||
    mbed_reset_reboot_error_info();
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -18,11 +18,15 @@
 | 
			
		|||
#ifndef MBED_FAULT_HANDLER_H
 | 
			
		||||
#define MBED_FAULT_HANDLER_H
 | 
			
		||||
 | 
			
		||||
#include "mbed_toolchain.h"
 | 
			
		||||
#include "mbed_error.h"
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
//Fault context struct
 | 
			
		||||
#ifdef TARGET_CORTEX_M
 | 
			
		||||
//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 {
 | 
			
		||||
| 
						 | 
				
			
			@ -48,24 +52,55 @@ typedef struct {
 | 
			
		|||
    uint32_t EXC_RETURN;
 | 
			
		||||
    uint32_t CONTROL;
 | 
			
		||||
} mbed_fault_context_t;
 | 
			
		||||
#elif defined TARGET_CORTEX_A
 | 
			
		||||
// This is not currently used, but would be a plausible implementation
 | 
			
		||||
typedef struct {
 | 
			
		||||
    uint32_t R0_reg;
 | 
			
		||||
    uint32_t R1_reg;
 | 
			
		||||
    uint32_t R2_reg;
 | 
			
		||||
    uint32_t R3_reg;
 | 
			
		||||
    uint32_t R4_reg;
 | 
			
		||||
    uint32_t R5_reg;
 | 
			
		||||
    uint32_t R6_reg;
 | 
			
		||||
    uint32_t R7_reg;
 | 
			
		||||
    uint32_t R8_reg;
 | 
			
		||||
    uint32_t R9_reg;
 | 
			
		||||
    uint32_t R10_reg;
 | 
			
		||||
    uint32_t R11_reg;
 | 
			
		||||
    uint32_t R12_reg;
 | 
			
		||||
    uint32_t SP_reg;
 | 
			
		||||
    uint32_t LR_reg;
 | 
			
		||||
    uint32_t PC_reg;
 | 
			
		||||
    uint32_t CPSR;
 | 
			
		||||
    uint32_t SP_usr;
 | 
			
		||||
    uint32_t LR_usr;
 | 
			
		||||
} mbed_fault_context_t;
 | 
			
		||||
#else
 | 
			
		||||
// Dummy for mbed_crash_data_t
 | 
			
		||||
typedef struct {
 | 
			
		||||
} mbed_fault_context_t;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
//Fault type definitions
 | 
			
		||||
#ifdef TARGET_CORTEX_M
 | 
			
		||||
//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)
 | 
			
		||||
#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_fault_handler.c) to print the information without using C-lib support.
 | 
			
		||||
void mbed_fault_handler(uint32_t fault_type, const mbed_fault_context_t *mbed_fault_context_in);
 | 
			
		||||
MBED_NORETURN void mbed_fault_handler(uint32_t fault_type, const mbed_fault_context_t *mbed_fault_context_in);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Call this function to retrieve the fault context after a fatal exception which triggered a system reboot. The function retrieves the fault context stored in crash-report ram area which is preserved over reboot.
 | 
			
		||||
 * @param  fault_context        Pointer to mbed_fault_context_t struct allocated by the caller. This is the mbed_fault_context_t info captured as part of the fatal exception which triggered the reboot.
 | 
			
		||||
 * @return                      0 or MBED_SUCCESS on success.
 | 
			
		||||
 *                              MBED_ERROR_INVALID_ARGUMENT in case of invalid error_info pointer
 | 
			
		||||
 *                              MBED_ERROR_ITEM_NOT_FOUND if no reboot context is currently captured by teh system
 | 
			
		||||
 *                              MBED_ERROR_ITEM_NOT_FOUND if no reboot context is currently captured by the system
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
mbed_error_status_t mbed_get_reboot_fault_context(mbed_fault_context_t *fault_context);
 | 
			
		||||
| 
						 | 
				
			
			@ -22,141 +22,103 @@
 | 
			
		|||
; * -----------------------------------------------------------------------------
 | 
			
		||||
; */
 | 
			
		||||
#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
 | 
			
		||||
FAULT_TYPE_HARD_FAULT           EQU     0x10
 | 
			
		||||
FAULT_TYPE_MEMMANAGE_FAULT      EQU     0x20
 | 
			
		||||
FAULT_TYPE_BUS_FAULT            EQU     0x30
 | 
			
		||||
FAULT_TYPE_USAGE_FAULT          EQU     0x40
 | 
			
		||||
 | 
			
		||||
                AREA     |.text|, CODE, READONLY
 | 
			
		||||
        PRESERVE8
 | 
			
		||||
        THUMB
 | 
			
		||||
 | 
			
		||||
        AREA    |.text|, CODE, READONLY
 | 
			
		||||
 | 
			
		||||
HardFault_Handler\
 | 
			
		||||
                PROC
 | 
			
		||||
                EXPORT   HardFault_Handler
 | 
			
		||||
                LDR      R3,=FAULT_TYPE_HARD_FAULT                   
 | 
			
		||||
                B        Fault_Handler
 | 
			
		||||
                ENDP                
 | 
			
		||||
        PROC
 | 
			
		||||
        EXPORT  HardFault_Handler
 | 
			
		||||
        MOVS    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                
 | 
			
		||||
                
 | 
			
		||||
        PROC
 | 
			
		||||
        EXPORT  MemManage_Handler
 | 
			
		||||
        MOVS    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
 | 
			
		||||
        PROC
 | 
			
		||||
        EXPORT  BusFault_Handler
 | 
			
		||||
        MOVS    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
 | 
			
		||||
        PROC
 | 
			
		||||
        EXPORT  UsageFault_Handler
 | 
			
		||||
        MOVS    R3,#FAULT_TYPE_USAGE_FAULT
 | 
			
		||||
        ; Fall into Fault_Handler
 | 
			
		||||
        ENDP
 | 
			
		||||
 | 
			
		||||
Fault_Handler\
 | 
			
		||||
        PROC
 | 
			
		||||
        EXPORT  Fault_Handler
 | 
			
		||||
#if (DOMAIN_NS == 1)
 | 
			
		||||
                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
 | 
			
		||||
#if MBED_CONF_PLATFORM_CRASH_CAPTURE_ENABLED
 | 
			
		||||
#define mbed_fault_context |Image$$RW_m_crash_data$$ZI$$Base|
 | 
			
		||||
#endif
 | 
			
		||||
        IMPORT  mbed_fault_context
 | 
			
		||||
        IMPORT  mbed_fault_handler
 | 
			
		||||
 | 
			
		||||
        MOV     R12,R3
 | 
			
		||||
        PUSH    {R4-R7}
 | 
			
		||||
        ADD     R6,SP,#16
 | 
			
		||||
        MOV     R5,LR
 | 
			
		||||
        LSRS    R0,R5,#3                ; Check EXC_RETURN for bit 2
 | 
			
		||||
        BCC     Fault_Handler_Continue
 | 
			
		||||
        MRS     R6,PSP
 | 
			
		||||
 | 
			
		||||
Fault_Handler_Continue
 | 
			
		||||
                MOV      R12,R3
 | 
			
		||||
                LDR      R3,=mbed_fault_context      
 | 
			
		||||
                LDR      R1,[R3]     
 | 
			
		||||
                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
 | 
			
		||||
        LDR     R7,=mbed_fault_context
 | 
			
		||||
        LDMIA   R6!,{R0-R3}
 | 
			
		||||
        STMIA   R7!,{R0-R3}             ; Capture R0..R3
 | 
			
		||||
        POP     {R0-R3}
 | 
			
		||||
        STMIA   R7!,{R0-R3}             ; Capture R4..R7
 | 
			
		||||
        MOV     R0,R8
 | 
			
		||||
        MOV     R1,R9
 | 
			
		||||
        MOV     R2,R10
 | 
			
		||||
        MOV     R3,R11
 | 
			
		||||
        STMIA   R7!,{R0-R3}             ; Capture R8..R11
 | 
			
		||||
        LDMIA   R6!,{R0,R2-R4}          ; Load R12,LR,PC,xPSR
 | 
			
		||||
        ; Adjust stack pointer to its original value
 | 
			
		||||
        MOVS    R1,R6
 | 
			
		||||
        LSRS    R6,R4,#10               ; Check for if STK was aligned by checking bit-9 in xPSR value
 | 
			
		||||
        BCC     Fault_Handler_Continue1
 | 
			
		||||
        ADDS    R1,#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]
 | 
			
		||||
                MOV      R0,R12
 | 
			
		||||
                LDR      R3,=mbed_fault_context
 | 
			
		||||
                LDR      R1,[R3]
 | 
			
		||||
                BL       mbed_fault_handler
 | 
			
		||||
#endif                    
 | 
			
		||||
                B        .                        ; Just in case we come back here                
 | 
			
		||||
                ENDP
 | 
			
		||||
                    
 | 
			
		||||
        LSRS    R6,R5,#5                ; Check EXC_RETURN bit-4 to see if FP context was saved
 | 
			
		||||
        BCS     Fault_Handler_Continue2
 | 
			
		||||
        ADDS    R1,#0x48                ; 16 FP regs + FPCSR + 1 Reserved
 | 
			
		||||
Fault_Handler_Continue2
 | 
			
		||||
        STMIA   R7!,{R0-R4}             ; Capture R12,SP,LR,PC,xPSR
 | 
			
		||||
        MRS     R0,PSP
 | 
			
		||||
        MOV     R1,SP
 | 
			
		||||
        MRS     R6,CONTROL
 | 
			
		||||
        STMIA   R7!,{R0,R1,R5,R6}       ; Capture PSP,MSP,EXC_RETURN,CONTROL
 | 
			
		||||
        MOV     R0,R12
 | 
			
		||||
        LDR     R1,=mbed_fault_context
 | 
			
		||||
        BL      mbed_fault_handler      ; mbed_fault_handler does not return
 | 
			
		||||
#else
 | 
			
		||||
        B       .
 | 
			
		||||
#endif
 | 
			
		||||
                
 | 
			
		||||
                END
 | 
			
		||||
        ENDP
 | 
			
		||||
        ALIGN
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
        END
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -23,17 +23,17 @@
 | 
			
		|||
 */
 | 
			
		||||
#ifndef MBED_FAULT_HANDLER_DISABLED
 | 
			
		||||
 | 
			
		||||
        .file    "except.S"
 | 
			
		||||
        .syntax  unified
 | 
			
		||||
        .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
 | 
			
		||||
        .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"
 | 
			
		||||
| 
						 | 
				
			
			@ -41,159 +41,120 @@
 | 
			
		|||
 | 
			
		||||
//HardFault_Handler
 | 
			
		||||
        .thumb_func
 | 
			
		||||
        .type    HardFault_Handler, %function
 | 
			
		||||
        .global  HardFault_Handler
 | 
			
		||||
        .type   HardFault_Handler, %function
 | 
			
		||||
        .global HardFault_Handler
 | 
			
		||||
        .fnstart
 | 
			
		||||
        .cantunwind
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
HardFault_Handler:
 | 
			
		||||
        LDR      R3,=FAULT_TYPE_HARD_FAULT  
 | 
			
		||||
        B        Fault_Handler
 | 
			
		||||
        MOVS    R3,#FAULT_TYPE_HARD_FAULT
 | 
			
		||||
        B       Fault_Handler
 | 
			
		||||
 | 
			
		||||
        .fnend
 | 
			
		||||
        .size    HardFault_Handler, .-HardFault_Handler
 | 
			
		||||
        
 | 
			
		||||
//MemManage_Handler        
 | 
			
		||||
        .size   HardFault_Handler, .-HardFault_Handler
 | 
			
		||||
 | 
			
		||||
//MemManage_Handler
 | 
			
		||||
        .thumb_func
 | 
			
		||||
        .type    MemManage_Handler, %function
 | 
			
		||||
        .global  MemManage_Handler
 | 
			
		||||
        .type   MemManage_Handler, %function
 | 
			
		||||
        .global MemManage_Handler
 | 
			
		||||
        .fnstart
 | 
			
		||||
        .cantunwind
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
MemManage_Handler:
 | 
			
		||||
        LDR      R3,=FAULT_TYPE_MEMMANAGE_FAULT  
 | 
			
		||||
        B        Fault_Handler
 | 
			
		||||
        MOVS    R3,#FAULT_TYPE_MEMMANAGE_FAULT
 | 
			
		||||
        B       Fault_Handler
 | 
			
		||||
 | 
			
		||||
        .fnend
 | 
			
		||||
        .size    MemManage_Handler, .-MemManage_Handler
 | 
			
		||||
        .size   MemManage_Handler, .-MemManage_Handler
 | 
			
		||||
 | 
			
		||||
//BusFault_Handler     
 | 
			
		||||
//BusFault_Handler
 | 
			
		||||
        .thumb_func
 | 
			
		||||
        .type    BusFault_Handler, %function
 | 
			
		||||
        .global  BusFault_Handler
 | 
			
		||||
        .type   BusFault_Handler, %function
 | 
			
		||||
        .global BusFault_Handler
 | 
			
		||||
        .fnstart
 | 
			
		||||
        .cantunwind
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
BusFault_Handler:
 | 
			
		||||
        LDR      R3,=FAULT_TYPE_BUS_FAULT  
 | 
			
		||||
        B        Fault_Handler
 | 
			
		||||
        MOVS    R3,#FAULT_TYPE_BUS_FAULT
 | 
			
		||||
        B       Fault_Handler
 | 
			
		||||
 | 
			
		||||
        .fnend
 | 
			
		||||
        .size    BusFault_Handler, .-BusFault_Handler
 | 
			
		||||
        
 | 
			
		||||
//UsageFault_Handler         
 | 
			
		||||
        .size   BusFault_Handler, .-BusFault_Handler
 | 
			
		||||
 | 
			
		||||
//UsageFault_Handler
 | 
			
		||||
        .thumb_func
 | 
			
		||||
        .type    UsageFault_Handler, %function
 | 
			
		||||
        .global  UsageFault_Handler
 | 
			
		||||
        .type   UsageFault_Handler, %function
 | 
			
		||||
        .global UsageFault_Handler
 | 
			
		||||
        .fnstart
 | 
			
		||||
        .cantunwind
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
UsageFault_Handler:
 | 
			
		||||
        LDR      R3,=FAULT_TYPE_USAGE_FAULT  
 | 
			
		||||
        B        Fault_Handler
 | 
			
		||||
        MOVS    R3,#FAULT_TYPE_USAGE_FAULT
 | 
			
		||||
        // Fall into Fault_Handler
 | 
			
		||||
 | 
			
		||||
        .fnend
 | 
			
		||||
        .size    UsageFault_Handler, .-UsageFault_Handler
 | 
			
		||||
        .size   UsageFault_Handler, .-UsageFault_Handler
 | 
			
		||||
 | 
			
		||||
//Common Fault_Handler to capture the context
 | 
			
		||||
        .thumb_func
 | 
			
		||||
        .type    Fault_Handler, %function
 | 
			
		||||
        .global  Fault_Handler
 | 
			
		||||
        .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
 | 
			
		||||
#if MBED_CONF_PLATFORM_CRASH_CAPTURE_ENABLED
 | 
			
		||||
#define mbed_fault_context __CRASH_DATA_RAM_START__
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
        MOV     R12,R3
 | 
			
		||||
        PUSH    {R4-R7}
 | 
			
		||||
        ADD     R6,SP,#16
 | 
			
		||||
        MOV     R5,LR
 | 
			
		||||
        LSRS    R0,R5,#3                // Check EXC_RETURN for bit 2
 | 
			
		||||
        BCC     Fault_Handler_Continue
 | 
			
		||||
        MRS     R6,PSP
 | 
			
		||||
 | 
			
		||||
Fault_Handler_Continue:
 | 
			
		||||
        MOV      R12,R3
 | 
			
		||||
        LDR      R3,=mbed_fault_context     
 | 
			
		||||
        LDR      R1,[R3]  
 | 
			
		||||
        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
 | 
			
		||||
        
 | 
			
		||||
        LDR     R7,=mbed_fault_context
 | 
			
		||||
        LDMIA   R6!,{R0-R3}
 | 
			
		||||
        STMIA   R7!,{R0-R3}             // Capture R0..R3
 | 
			
		||||
        POP     {R0-R3}
 | 
			
		||||
        STMIA   R7!,{R0-R3}             // Capture R4..R7
 | 
			
		||||
        MOV     R0,R8
 | 
			
		||||
        MOV     R1,R9
 | 
			
		||||
        MOV     R2,R10
 | 
			
		||||
        MOV     R3,R11
 | 
			
		||||
        STMIA   R7!,{R0-R3}             // Capture R8..R11
 | 
			
		||||
        LDMIA   R6!,{R0,R2-R4}          // Load R12,LR,PC,xPSR
 | 
			
		||||
        // Adjust stack pointer to its original value
 | 
			
		||||
        MOVS    R1,R6
 | 
			
		||||
        LSRS    R6,R4,#10                // Check for if STK was aligned by checking bit-9 in xPSR value
 | 
			
		||||
        BCC     Fault_Handler_Continue1
 | 
			
		||||
        ADDS    R1,#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
 | 
			
		||||
        LSRS    R6,R5,#5                // Check EXC_RETURN bit-4 to see if FP context was saved
 | 
			
		||||
        BCS     Fault_Handler_Continue2
 | 
			
		||||
        ADDS    R1,#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]
 | 
			
		||||
        MOV      R0,R12
 | 
			
		||||
        LDR      R3,=mbed_fault_context
 | 
			
		||||
        LDR      R1,[R3]
 | 
			
		||||
        BL       mbed_fault_handler
 | 
			
		||||
        STMIA   R7!,{R0-R4}             // Capture R12,SP,LR,PC,xPSR
 | 
			
		||||
        MRS     R0,PSP
 | 
			
		||||
        MOV     R1,SP
 | 
			
		||||
        MRS     R6,CONTROL
 | 
			
		||||
        STMIA   R7!,{R0,R1,R5,R6}       // Capture PSP,MSP,EXC_RETURN,CONTROL
 | 
			
		||||
        MOV     R0,R12
 | 
			
		||||
        LDR     R1,=mbed_fault_context
 | 
			
		||||
        BL      mbed_fault_handler      // mbed_fault_handler does not return
 | 
			
		||||
#else
 | 
			
		||||
        B       .
 | 
			
		||||
#endif
 | 
			
		||||
        B        .                        // Just in case we come back here   
 | 
			
		||||
        
 | 
			
		||||
        .fnend
 | 
			
		||||
        .size    Fault_Handler, .-Fault_Handler
 | 
			
		||||
 | 
			
		||||
        .fnend
 | 
			
		||||
        .size   Fault_Handler, .-Fault_Handler
 | 
			
		||||
        .align
 | 
			
		||||
#endif
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
        .end
 | 
			
		||||
        
 | 
			
		||||
        
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -17,139 +17,101 @@
 | 
			
		|||
; *
 | 
			
		||||
; * -----------------------------------------------------------------------------
 | 
			
		||||
; *
 | 
			
		||||
; * Title:       Cortex-M Fault Exception handlers ( Common for both ARMv7M and ARMV6M ); 
 | 
			
		||||
; * 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
 | 
			
		||||
        NAME    except.S
 | 
			
		||||
 | 
			
		||||
#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)
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
 | 
			
		||||
        SECTION .text:CODE:NOROOT(2)
 | 
			
		||||
 | 
			
		||||
HardFault_Handler
 | 
			
		||||
                EXPORT  HardFault_Handler
 | 
			
		||||
                LDR     R3,=FAULT_TYPE_HARD_FAULT   
 | 
			
		||||
                B       Fault_Handler
 | 
			
		||||
                
 | 
			
		||||
        EXPORT  HardFault_Handler
 | 
			
		||||
        MOVS    R3,#FAULT_TYPE_HARD_FAULT
 | 
			
		||||
        B       Fault_Handler
 | 
			
		||||
 | 
			
		||||
MemManage_Handler
 | 
			
		||||
                EXPORT  MemManage_Handler
 | 
			
		||||
                LDR     R3,=FAULT_TYPE_MEMMANAGE_FAULT   
 | 
			
		||||
                B       Fault_Handler
 | 
			
		||||
        EXPORT  MemManage_Handler
 | 
			
		||||
        MOVS    R3,#FAULT_TYPE_MEMMANAGE_FAULT
 | 
			
		||||
        B       Fault_Handler
 | 
			
		||||
 | 
			
		||||
BusFault_Handler
 | 
			
		||||
                EXPORT  BusFault_Handler
 | 
			
		||||
                LDR     R3,=FAULT_TYPE_BUS_FAULT   
 | 
			
		||||
                B       Fault_Handler
 | 
			
		||||
                
 | 
			
		||||
        EXPORT  BusFault_Handler
 | 
			
		||||
        MOVS    R3,#FAULT_TYPE_BUS_FAULT
 | 
			
		||||
        B       Fault_Handler
 | 
			
		||||
 | 
			
		||||
UsageFault_Handler
 | 
			
		||||
                EXPORT  UsageFault_Handler
 | 
			
		||||
                LDR     R3,=FAULT_TYPE_USAGE_FAULT   
 | 
			
		||||
                B       Fault_Handler                
 | 
			
		||||
                
 | 
			
		||||
        EXPORT  UsageFault_Handler
 | 
			
		||||
        MOVS    R3,#FAULT_TYPE_USAGE_FAULT
 | 
			
		||||
        ; Fall into Fault_Handler
 | 
			
		||||
 | 
			
		||||
Fault_Handler
 | 
			
		||||
                EXPORT  Fault_Handler
 | 
			
		||||
        EXPORT  Fault_Handler
 | 
			
		||||
#if (DOMAIN_NS == 1)
 | 
			
		||||
                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
 | 
			
		||||
#if MBED_CONF_PLATFORM_CRASH_CAPTURE_ENABLED
 | 
			
		||||
#define mbed_fault_context __CRASH_DATA_RAM_START__
 | 
			
		||||
#endif
 | 
			
		||||
        IMPORT  mbed_fault_context
 | 
			
		||||
        IMPORT  mbed_fault_handler
 | 
			
		||||
 | 
			
		||||
        MOV     R12,R3
 | 
			
		||||
        PUSH    {R4-R7}
 | 
			
		||||
        ADD     R6,SP,#16
 | 
			
		||||
        MOV     R5,LR
 | 
			
		||||
        LSRS    R0,R5,#3                ; Check EXC_RETURN for bit 2
 | 
			
		||||
        BCC     Fault_Handler_Continue
 | 
			
		||||
        MRS     R6,PSP
 | 
			
		||||
 | 
			
		||||
Fault_Handler_Continue
 | 
			
		||||
                MOV     R12,R3
 | 
			
		||||
                LDR     R3,=mbed_fault_context      
 | 
			
		||||
                LDR     R1,[R3]     
 | 
			
		||||
                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
 | 
			
		||||
                
 | 
			
		||||
        LDR     R7,=mbed_fault_context
 | 
			
		||||
        LDMIA   R6!,{R0-R3}
 | 
			
		||||
        STMIA   R7!,{R0-R3}             ; Capture R0..R3
 | 
			
		||||
        POP     {R0-R3}
 | 
			
		||||
        STMIA   R7!,{R0-R3}             ; Capture R4..R7
 | 
			
		||||
        MOV     R0,R8
 | 
			
		||||
        MOV     R1,R9
 | 
			
		||||
        MOV     R2,R10
 | 
			
		||||
        MOV     R3,R11
 | 
			
		||||
        STMIA   R7!,{R0-R3}             ; Capture R8..R11
 | 
			
		||||
        LDMIA   R6!,{R0,R2-R4}          ; Load R12,LR,PC,xPSR
 | 
			
		||||
        ; Adjust stack pointer to its original value
 | 
			
		||||
        MOVS    R1,R6
 | 
			
		||||
        LSRS    R6,R4,#10               ; Check for if STK was aligned by checking bit-9 in xPSR value
 | 
			
		||||
        BCC     Fault_Handler_Continue1
 | 
			
		||||
        ADDS    R1,#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                
 | 
			
		||||
 | 
			
		||||
        LSRS    R6,R5,#5                ; Check EXC_RETURN bit-4 to see if FP context was saved
 | 
			
		||||
        BCS     Fault_Handler_Continue2
 | 
			
		||||
        ADDS    R1,#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]
 | 
			
		||||
                MOV     R0,R12
 | 
			
		||||
                LDR     R3,=mbed_fault_context
 | 
			
		||||
                LDR     R1,[R3]
 | 
			
		||||
                BL      mbed_fault_handler 
 | 
			
		||||
#endif                
 | 
			
		||||
                B       .                        ; Just in case we come back here    
 | 
			
		||||
#endif                                           ; #if (MBED_FAULT_HANDLER_SUPPORT == 1) 
 | 
			
		||||
        STMIA   R7!,{R0-R4}             ; Capture R12,SP,LR,PC,xPSR
 | 
			
		||||
        MRS     R0,PSP
 | 
			
		||||
        MOV     R1,SP
 | 
			
		||||
        MRS     R6,CONTROL
 | 
			
		||||
        STMIA   R7!,{R0,R1,R5,R6}       ; Capture PSP,MSP,EXC_RETURN,CONTROL
 | 
			
		||||
        MOV     R0,R12
 | 
			
		||||
        LDR     R1,=mbed_fault_context
 | 
			
		||||
        BL      mbed_fault_handler      ; mbed_fault_handler does not return
 | 
			
		||||
#else
 | 
			
		||||
        B       .
 | 
			
		||||
#endif
 | 
			
		||||
        ALIGN
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
                END
 | 
			
		||||
        END
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -34,18 +34,16 @@
 | 
			
		|||
void print_context_info(void);
 | 
			
		||||
 | 
			
		||||
#if MBED_CONF_PLATFORM_CRASH_CAPTURE_ENABLED
 | 
			
		||||
//Global for populating the context in exception handler
 | 
			
		||||
mbed_fault_context_t *const mbed_fault_context = (mbed_fault_context_t *)(FAULT_CONTEXT_LOCATION);
 | 
			
		||||
#define mbed_fault_context MBED_CRASH_DATA.fault.context
 | 
			
		||||
#else
 | 
			
		||||
mbed_fault_context_t fault_context;
 | 
			
		||||
mbed_fault_context_t *const mbed_fault_context = &fault_context;
 | 
			
		||||
mbed_fault_context_t mbed_fault_context;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
extern bool mbed_error_in_progress;
 | 
			
		||||
 | 
			
		||||
//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.
 | 
			
		||||
void mbed_fault_handler(uint32_t fault_type, const mbed_fault_context_t *mbed_fault_context_in)
 | 
			
		||||
MBED_NORETURN void mbed_fault_handler(uint32_t fault_type, const mbed_fault_context_t *mbed_fault_context_in)
 | 
			
		||||
{
 | 
			
		||||
    mbed_error_status_t faultStatus = MBED_SUCCESS;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -94,7 +92,7 @@ MBED_NOINLINE void print_context_info(void)
 | 
			
		|||
{
 | 
			
		||||
    //Context Regs
 | 
			
		||||
    for (int i = 0; i < 13; i++) {
 | 
			
		||||
        mbed_error_printf("\nR%-4d: %08" PRIX32, i, ((uint32_t *)(mbed_fault_context))[i]);
 | 
			
		||||
        mbed_error_printf("\nR%-4d: %08" PRIX32, i, (&mbed_fault_context.R0_reg)[i]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    mbed_error_printf("\nSP   : %08" PRIX32
 | 
			
		||||
| 
						 | 
				
			
			@ -102,8 +100,8 @@ MBED_NOINLINE void print_context_info(void)
 | 
			
		|||
                      "\nPC   : %08" PRIX32
 | 
			
		||||
                      "\nxPSR : %08" PRIX32
 | 
			
		||||
                      "\nPSP  : %08" PRIX32
 | 
			
		||||
                      "\nMSP  : %08" PRIX32, mbed_fault_context->SP_reg, mbed_fault_context->LR_reg, mbed_fault_context->PC_reg,
 | 
			
		||||
                      mbed_fault_context->xPSR, mbed_fault_context->PSP, mbed_fault_context->MSP);
 | 
			
		||||
                      "\nMSP  : %08" PRIX32, mbed_fault_context.SP_reg, mbed_fault_context.LR_reg, mbed_fault_context.PC_reg,
 | 
			
		||||
                      mbed_fault_context.xPSR, mbed_fault_context.PSP, mbed_fault_context.MSP);
 | 
			
		||||
 | 
			
		||||
    //Capture CPUID to get core/cpu info
 | 
			
		||||
    mbed_error_printf("\nCPUID: %08" PRIX32, SCB->CPUID);
 | 
			
		||||
| 
						 | 
				
			
			@ -129,12 +127,12 @@ MBED_NOINLINE void print_context_info(void)
 | 
			
		|||
#endif
 | 
			
		||||
 | 
			
		||||
    //Print Mode
 | 
			
		||||
    if (mbed_fault_context->EXC_RETURN & 0x8) {
 | 
			
		||||
    if (mbed_fault_context.EXC_RETURN & 0x8) {
 | 
			
		||||
        mbed_error_printf("\nMode : Thread");
 | 
			
		||||
        //Print Priv level in Thread mode - We capture CONTROL reg which reflects the privilege.
 | 
			
		||||
        //Note that the CONTROL register captured still reflects the privilege status of the
 | 
			
		||||
        //thread mode eventhough we are in Handler mode by the time we capture it.
 | 
			
		||||
        if (mbed_fault_context->CONTROL & 0x1) {
 | 
			
		||||
        if (mbed_fault_context.CONTROL & 0x1) {
 | 
			
		||||
            mbed_error_printf("\nPriv : User");
 | 
			
		||||
        } else {
 | 
			
		||||
            mbed_error_printf("\nPriv : Privileged");
 | 
			
		||||
| 
						 | 
				
			
			@ -144,7 +142,7 @@ MBED_NOINLINE void print_context_info(void)
 | 
			
		|||
        mbed_error_printf("\nPriv : Privileged");
 | 
			
		||||
    }
 | 
			
		||||
    //Print Return Stack
 | 
			
		||||
    if (mbed_fault_context->EXC_RETURN & 0x4) {
 | 
			
		||||
    if (mbed_fault_context.EXC_RETURN & 0x4) {
 | 
			
		||||
        mbed_error_printf("\nStack: PSP");
 | 
			
		||||
    } else {
 | 
			
		||||
        mbed_error_printf("\nStack: MSP");
 | 
			
		||||
| 
						 | 
				
			
			@ -158,7 +156,7 @@ mbed_error_status_t mbed_get_reboot_fault_context(mbed_fault_context_t *fault_co
 | 
			
		|||
    if (fault_context == NULL) {
 | 
			
		||||
        return MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_INVALID_ARGUMENT);
 | 
			
		||||
    }
 | 
			
		||||
    memcpy(fault_context, mbed_fault_context, sizeof(mbed_fault_context_t));
 | 
			
		||||
    *fault_context = mbed_fault_context;
 | 
			
		||||
    status = MBED_SUCCESS;
 | 
			
		||||
#endif
 | 
			
		||||
    return status;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -17,6 +17,9 @@
 | 
			
		|||
#ifndef MBED_CRASH_DATA_INFO_H
 | 
			
		||||
#define MBED_CRASH_DATA_INFO_H
 | 
			
		||||
 | 
			
		||||
#include "platform/internal/mbed_fault_handler.h"
 | 
			
		||||
#include "platform/mbed_error.h"
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -25,25 +28,28 @@ extern "C" {
 | 
			
		|||
/** \ingroup mbed-os-internal */
 | 
			
		||||
/** \addtogroup platform-internal-api */
 | 
			
		||||
/** @{*/
 | 
			
		||||
#if defined(__ARMCC_VERSION)
 | 
			
		||||
extern uint32_t Image$$RW_m_crash_data$$ZI$$Base[];
 | 
			
		||||
extern uint32_t Image$$RW_m_crash_data$$ZI$$Size;
 | 
			
		||||
#define __CRASH_DATA_RAM_START__    Image$$RW_m_crash_data$$ZI$$Base
 | 
			
		||||
#elif defined(__ICCARM__)
 | 
			
		||||
extern uint32_t __CRASH_DATA_RAM_START__[];
 | 
			
		||||
extern uint32_t __CRASH_DATA_RAM_END__[];
 | 
			
		||||
#elif defined(__GNUC__)
 | 
			
		||||
extern uint32_t __CRASH_DATA_RAM_START__[];
 | 
			
		||||
extern uint32_t __CRASH_DATA_RAM_END__[];
 | 
			
		||||
#endif /* defined(__CC_ARM) */
 | 
			
		||||
// Any changes here must be reflected in except.S if they affect the fault handler.
 | 
			
		||||
// The fault context is first to keep it simple for the assembler.
 | 
			
		||||
typedef struct mbed_crash_data {
 | 
			
		||||
    union {
 | 
			
		||||
        mbed_fault_context_t context;
 | 
			
		||||
        int pad[32];
 | 
			
		||||
    } fault;
 | 
			
		||||
    union {
 | 
			
		||||
        mbed_error_ctx context;
 | 
			
		||||
        int pad[32];
 | 
			
		||||
    } error;
 | 
			
		||||
} mbed_crash_data_t;
 | 
			
		||||
 | 
			
		||||
/* Offset definitions for context capture */
 | 
			
		||||
#define FAULT_CONTEXT_OFFSET    (0x0)
 | 
			
		||||
#define FAULT_CONTEXT_SIZE      (0x80 / 4)    //32 words(128 bytes) for Fault Context
 | 
			
		||||
#define ERROR_CONTEXT_OFFSET    (FAULT_CONTEXT_OFFSET + FAULT_CONTEXT_SIZE)
 | 
			
		||||
#define ERROR_CONTEXT_SIZE      (0x80 / 4)    //32 words(128 bytes) bytes for Error Context
 | 
			
		||||
#define FAULT_CONTEXT_LOCATION  (__CRASH_DATA_RAM_START__ + FAULT_CONTEXT_OFFSET)
 | 
			
		||||
#define ERROR_CONTEXT_LOCATION  (__CRASH_DATA_RAM_START__ + ERROR_CONTEXT_OFFSET)
 | 
			
		||||
#if defined(__ARMCC_VERSION)
 | 
			
		||||
#define MBED_CRASH_DATA Image$$RW_m_crash_data$$ZI$$Base
 | 
			
		||||
#elif defined(__ICCARM__)
 | 
			
		||||
#define MBED_CRASH_DATA __CRASH_DATA_RAM_START__
 | 
			
		||||
#elif defined(__GNUC__)
 | 
			
		||||
#define MBED_CRASH_DATA __CRASH_DATA_RAM_START__
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
extern mbed_crash_data_t MBED_CRASH_DATA;
 | 
			
		||||
/**@}*/
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -26,7 +26,7 @@
 | 
			
		|||
#include "platform/mbed_interface.h"
 | 
			
		||||
#include "platform/mbed_power_mgmt.h"
 | 
			
		||||
#include "platform/mbed_stats.h"
 | 
			
		||||
#include "platform/source/TARGET_CORTEX_M/mbed_fault_handler.h"
 | 
			
		||||
#include "platform/internal/mbed_fault_handler.h"
 | 
			
		||||
#include "drivers/MbedCRC.h"
 | 
			
		||||
#include "mbed_rtx.h"
 | 
			
		||||
#ifdef MBED_CONF_RTOS_PRESENT
 | 
			
		||||
| 
						 | 
				
			
			@ -62,8 +62,7 @@ static mbed_error_hook_t error_hook = NULL;
 | 
			
		|||
static mbed_error_status_t handle_error(mbed_error_status_t error_status, unsigned int error_value, const char *filename, int line_number, void *caller);
 | 
			
		||||
 | 
			
		||||
#if MBED_CONF_PLATFORM_CRASH_CAPTURE_ENABLED
 | 
			
		||||
//Global for populating the context in exception handler
 | 
			
		||||
static mbed_error_ctx *const report_error_ctx = (mbed_error_ctx *)(ERROR_CONTEXT_LOCATION);
 | 
			
		||||
#define report_error_ctx MBED_CRASH_DATA.error.context
 | 
			
		||||
static bool is_reboot_error_valid = false;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -122,9 +121,15 @@ static bool mbed_error_is_handler(const mbed_error_ctx *ctx)
 | 
			
		|||
    bool is_handler = false;
 | 
			
		||||
    if (ctx && mbed_error_is_hw_fault(ctx->error_status)) {
 | 
			
		||||
        mbed_fault_context_t *mfc = (mbed_fault_context_t *)ctx->error_value;
 | 
			
		||||
#ifdef TARGET_CORTEX_M
 | 
			
		||||
        if (mfc && !(mfc->EXC_RETURN & 0x8)) {
 | 
			
		||||
            is_handler = true;
 | 
			
		||||
        }
 | 
			
		||||
#elif defined TARGET_CORTEX_A
 | 
			
		||||
        if (mfc && (mfc->CPSR & 0x1F) != 0x10) {
 | 
			
		||||
            is_handler = true;
 | 
			
		||||
        }
 | 
			
		||||
#endif
 | 
			
		||||
    }
 | 
			
		||||
    return is_handler;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -183,11 +188,11 @@ static mbed_error_status_t handle_error(mbed_error_status_t error_status, unsign
 | 
			
		|||
 | 
			
		||||
    //Capture the first system error and store it
 | 
			
		||||
    if (error_count == 1) { //first error
 | 
			
		||||
        memcpy(&first_error_ctx, ¤t_error_ctx, sizeof(mbed_error_ctx));
 | 
			
		||||
        first_error_ctx = current_error_ctx;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //copy this error to last error
 | 
			
		||||
    memcpy(&last_error_ctx, ¤t_error_ctx, sizeof(mbed_error_ctx));
 | 
			
		||||
    last_error_ctx = current_error_ctx;
 | 
			
		||||
 | 
			
		||||
#if MBED_CONF_PLATFORM_ERROR_HIST_ENABLED
 | 
			
		||||
    //Log the error with error log
 | 
			
		||||
| 
						 | 
				
			
			@ -223,25 +228,25 @@ mbed_error_status_t mbed_error_initialize(void)
 | 
			
		|||
    uint32_t crc_val = 0;
 | 
			
		||||
 | 
			
		||||
    //Just check if we have valid value for error_status, if error_status is positive(which is not valid), no need to check crc
 | 
			
		||||
    if (report_error_ctx->error_status < 0) {
 | 
			
		||||
        crc_val = mbed_tiny_compute_crc32(report_error_ctx, offsetof(mbed_error_ctx, crc_error_ctx));
 | 
			
		||||
    if (report_error_ctx.error_status < 0) {
 | 
			
		||||
        crc_val = mbed_tiny_compute_crc32(&report_error_ctx, offsetof(mbed_error_ctx, crc_error_ctx));
 | 
			
		||||
        //Read report_error_ctx and check if CRC is correct, and with valid status code
 | 
			
		||||
        if ((report_error_ctx->crc_error_ctx == crc_val) && (report_error_ctx->is_error_processed == 0)) {
 | 
			
		||||
        if ((report_error_ctx.crc_error_ctx == crc_val) && (report_error_ctx.is_error_processed == 0)) {
 | 
			
		||||
            is_reboot_error_valid = true;
 | 
			
		||||
 | 
			
		||||
            //Call the mbed_error_reboot_callback, this enables applications to do some handling before we do the handling
 | 
			
		||||
            mbed_error_reboot_callback(report_error_ctx);
 | 
			
		||||
            mbed_error_reboot_callback(&report_error_ctx);
 | 
			
		||||
 | 
			
		||||
            //We let the callback reset the error info, so check if its still valid and do the rest only if its still valid.
 | 
			
		||||
            if (report_error_ctx->error_reboot_count > 0) {
 | 
			
		||||
            if (report_error_ctx.error_reboot_count > 0) {
 | 
			
		||||
 | 
			
		||||
                report_error_ctx->is_error_processed = 1;//Set the flag that we already processed this error
 | 
			
		||||
                crc_val = mbed_tiny_compute_crc32(report_error_ctx, offsetof(mbed_error_ctx, crc_error_ctx));
 | 
			
		||||
                report_error_ctx->crc_error_ctx = crc_val;
 | 
			
		||||
                report_error_ctx.is_error_processed = 1;//Set the flag that we already processed this error
 | 
			
		||||
                crc_val = mbed_tiny_compute_crc32(&report_error_ctx, offsetof(mbed_error_ctx, crc_error_ctx));
 | 
			
		||||
                report_error_ctx.crc_error_ctx = crc_val;
 | 
			
		||||
 | 
			
		||||
                //Enforce max-reboot only if auto reboot is enabled
 | 
			
		||||
#if MBED_CONF_PLATFORM_FATAL_ERROR_AUTO_REBOOT_ENABLED
 | 
			
		||||
                if (report_error_ctx->error_reboot_count >= MBED_CONF_PLATFORM_ERROR_REBOOT_MAX) {
 | 
			
		||||
                if (report_error_ctx.error_reboot_count >= MBED_CONF_PLATFORM_ERROR_REBOOT_MAX) {
 | 
			
		||||
                    mbed_halt_system();
 | 
			
		||||
                }
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -299,10 +304,10 @@ WEAK MBED_NORETURN mbed_error_status_t mbed_error(mbed_error_status_t error_stat
 | 
			
		|||
 | 
			
		||||
#if MBED_CONF_PLATFORM_CRASH_CAPTURE_ENABLED
 | 
			
		||||
    uint32_t crc_val = 0;
 | 
			
		||||
    crc_val = mbed_tiny_compute_crc32(report_error_ctx, offsetof(mbed_error_ctx, crc_error_ctx));
 | 
			
		||||
    crc_val = mbed_tiny_compute_crc32(&report_error_ctx, offsetof(mbed_error_ctx, crc_error_ctx));
 | 
			
		||||
    //Read report_error_ctx and check if CRC is correct for report_error_ctx
 | 
			
		||||
    if (report_error_ctx->crc_error_ctx == crc_val) {
 | 
			
		||||
        uint32_t current_reboot_count = report_error_ctx->error_reboot_count;
 | 
			
		||||
    if (report_error_ctx.crc_error_ctx == crc_val) {
 | 
			
		||||
        uint32_t current_reboot_count = report_error_ctx.error_reboot_count;
 | 
			
		||||
        last_error_ctx.error_reboot_count = current_reboot_count + 1;
 | 
			
		||||
    } else {
 | 
			
		||||
        last_error_ctx.error_reboot_count = 1;
 | 
			
		||||
| 
						 | 
				
			
			@ -312,15 +317,15 @@ WEAK MBED_NORETURN mbed_error_status_t mbed_error(mbed_error_status_t error_stat
 | 
			
		|||
    last_error_ctx.crc_error_ctx = mbed_tiny_compute_crc32(&last_error_ctx, offsetof(mbed_error_ctx, crc_error_ctx));
 | 
			
		||||
    //Protect report_error_ctx while we update it
 | 
			
		||||
    core_util_critical_section_enter();
 | 
			
		||||
    memcpy(report_error_ctx, &last_error_ctx, sizeof(mbed_error_ctx));
 | 
			
		||||
    report_error_ctx = last_error_ctx;
 | 
			
		||||
    core_util_critical_section_exit();
 | 
			
		||||
    //We need not call delete_mbed_crc(crc_obj) here as we are going to reset the system anyway, and calling delete while handling a fatal error may cause nested exception
 | 
			
		||||
#if MBED_CONF_PLATFORM_FATAL_ERROR_AUTO_REBOOT_ENABLED && (MBED_CONF_PLATFORM_ERROR_REBOOT_MAX > 0)
 | 
			
		||||
#ifndef NDEBUG
 | 
			
		||||
    mbed_error_printf("\n= System will be rebooted due to a fatal error =\n");
 | 
			
		||||
    if (report_error_ctx->error_reboot_count >= MBED_CONF_PLATFORM_ERROR_REBOOT_MAX) {
 | 
			
		||||
    if (report_error_ctx.error_reboot_count >= MBED_CONF_PLATFORM_ERROR_REBOOT_MAX) {
 | 
			
		||||
        //We have rebooted more than enough, hold the system here.
 | 
			
		||||
        mbed_error_printf("= Reboot count(=%" PRIi32") reached maximum, system will halt after rebooting =\n", report_error_ctx->error_reboot_count);
 | 
			
		||||
        mbed_error_printf("= Reboot count(=%" PRIi32") reached maximum, system will halt after rebooting =\n", report_error_ctx.error_reboot_count);
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
    system_reset();//do a system reset to get the system rebooted
 | 
			
		||||
| 
						 | 
				
			
			@ -348,7 +353,7 @@ mbed_error_status_t mbed_reset_reboot_error_info()
 | 
			
		|||
#if MBED_CONF_PLATFORM_CRASH_CAPTURE_ENABLED
 | 
			
		||||
    //Protect for thread safety
 | 
			
		||||
    core_util_critical_section_enter();
 | 
			
		||||
    memset(report_error_ctx, 0, sizeof(mbed_error_ctx));
 | 
			
		||||
    memset(&report_error_ctx, 0, sizeof(mbed_error_ctx));
 | 
			
		||||
    core_util_critical_section_exit();
 | 
			
		||||
#endif
 | 
			
		||||
    return MBED_SUCCESS;
 | 
			
		||||
| 
						 | 
				
			
			@ -361,10 +366,10 @@ mbed_error_status_t mbed_reset_reboot_count()
 | 
			
		|||
    if (is_reboot_error_valid) {
 | 
			
		||||
        uint32_t crc_val = 0;
 | 
			
		||||
        core_util_critical_section_enter();
 | 
			
		||||
        report_error_ctx->error_reboot_count = 0;//Set reboot count to 0
 | 
			
		||||
        report_error_ctx.error_reboot_count = 0;//Set reboot count to 0
 | 
			
		||||
        //Update CRC
 | 
			
		||||
        crc_val = mbed_tiny_compute_crc32(report_error_ctx, offsetof(mbed_error_ctx, crc_error_ctx));
 | 
			
		||||
        report_error_ctx->crc_error_ctx = crc_val;
 | 
			
		||||
        crc_val = mbed_tiny_compute_crc32(&report_error_ctx, offsetof(mbed_error_ctx, crc_error_ctx));
 | 
			
		||||
        report_error_ctx.crc_error_ctx = crc_val;
 | 
			
		||||
        core_util_critical_section_exit();
 | 
			
		||||
        return MBED_SUCCESS;
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -379,7 +384,7 @@ mbed_error_status_t mbed_get_reboot_error_info(mbed_error_ctx *error_info)
 | 
			
		|||
#if MBED_CONF_PLATFORM_CRASH_CAPTURE_ENABLED
 | 
			
		||||
    if (is_reboot_error_valid) {
 | 
			
		||||
        if (error_info != NULL) {
 | 
			
		||||
            memcpy(error_info, report_error_ctx, sizeof(mbed_error_ctx));
 | 
			
		||||
            *error_info = report_error_ctx;
 | 
			
		||||
            status = MBED_SUCCESS;
 | 
			
		||||
        } else {
 | 
			
		||||
            status = MBED_ERROR_INVALID_ARGUMENT;
 | 
			
		||||
| 
						 | 
				
			
			@ -392,14 +397,14 @@ mbed_error_status_t mbed_get_reboot_error_info(mbed_error_ctx *error_info)
 | 
			
		|||
//Retrieve the first error context from error log
 | 
			
		||||
mbed_error_status_t mbed_get_first_error_info(mbed_error_ctx *error_info)
 | 
			
		||||
{
 | 
			
		||||
    memcpy(error_info, &first_error_ctx, sizeof(first_error_ctx));
 | 
			
		||||
    *error_info = first_error_ctx;
 | 
			
		||||
    return MBED_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//Retrieve the last error context from error log
 | 
			
		||||
mbed_error_status_t mbed_get_last_error_info(mbed_error_ctx *error_info)
 | 
			
		||||
{
 | 
			
		||||
    memcpy(error_info, &last_error_ctx, sizeof(mbed_error_ctx));
 | 
			
		||||
    *error_info = last_error_ctx;
 | 
			
		||||
    return MBED_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue