mirror of
https://github.com/oopuuu/zTC1.git
synced 2025-12-14 22:18:14 +08:00
377 lines
16 KiB
C
377 lines
16 KiB
C
/**
|
|
* UNPUBLISHED PROPRIETARY SOURCE CODE
|
|
* Copyright (c) 2016 MXCHIP Inc.
|
|
*
|
|
* The contents of this file may not be disclosed to third parties, copied or
|
|
* duplicated in any form, in whole or in part, without the prior written
|
|
* permission of MXCHIP Corporation.
|
|
*
|
|
*/
|
|
|
|
#include <common.h>
|
|
#include "platform_cmsis.h"
|
|
//#include "platform_constants.h"
|
|
#include "platform_isr.h"
|
|
//#include "platform_isr_interface.h"
|
|
#include "platform_assert.h"
|
|
|
|
/******************************************************
|
|
* Macros
|
|
******************************************************/
|
|
|
|
/******************************************************
|
|
* Constants
|
|
******************************************************/
|
|
|
|
#ifdef DEBUG
|
|
#define DEBUG_HARDFAULT
|
|
#endif /* ifdef DEBUG */
|
|
|
|
/* Bit Definitions for SCB_CFSR */
|
|
#define SCB_CFSR_IACCVIOL ((uint32_t)0x00000001)
|
|
#define SCB_CFSR_DACCVIOL ((uint32_t)0x00000002)
|
|
#define SCB_CFSR_MUNSTKERR ((uint32_t)0x00000008)
|
|
#define SCB_CFSR_MSTKERR ((uint32_t)0x00000010)
|
|
#define SCB_CFSR_MMARVALID ((uint32_t)0x00000080)
|
|
#define SCB_CFSR_IBUSERR ((uint32_t)0x00000100)
|
|
#define SCB_CFSR_PRECISERR ((uint32_t)0x00000200)
|
|
#define SCB_CFSR_IMPRECISERR ((uint32_t)0x00000400)
|
|
#define SCB_CFSR_UNSTKERR ((uint32_t)0x00000800)
|
|
#define SCB_CFSR_STKERR ((uint32_t)0x00001000)
|
|
#define SCB_CFSR_BFARVALID ((uint32_t)0x00008000)
|
|
#define SCB_CFSR_UNDEFINSTR ((uint32_t)0x00010000)
|
|
#define SCB_CFSR_INVSTATE ((uint32_t)0x00020000)
|
|
#define SCB_CFSR_INVPC ((uint32_t)0x00040000)
|
|
#define SCB_CFSR_NOCP ((uint32_t)0x00080000)
|
|
#define SCB_CFSR_UNALIGNED ((uint32_t)0x01000000)
|
|
#define SCB_CFSR_DIVBYZERO ((uint32_t)0x02000000)
|
|
|
|
/******************************************************
|
|
* Enumerations
|
|
******************************************************/
|
|
|
|
/******************************************************
|
|
* Type Definitions
|
|
******************************************************/
|
|
|
|
/******************************************************
|
|
* Structures
|
|
******************************************************/
|
|
|
|
typedef struct exception_stacked_registers_struct
|
|
{
|
|
/* Stacked registers */
|
|
uint32_t R0;
|
|
uint32_t R1;
|
|
uint32_t R2;
|
|
uint32_t R3;
|
|
uint32_t R12;
|
|
uint32_t LR;
|
|
uint32_t PC; /* (Return Address) */
|
|
uint32_t PSR;
|
|
} exception_stacked_registers_t;
|
|
|
|
typedef enum EXC_RETURN_enum
|
|
{
|
|
HANDLER_MSP_MSP = 0xF1, /* Return to Handler mode. Exception return gets state from MSP. Execution uses MSP after return. */
|
|
THREAD_MSP_MSP = 0xF9, /* Return to Thread mode. Exception return gets state from MSP. Execution uses MSP after return. */
|
|
THREAD_PSP_PSP = 0xFD /* Return to Thread mode. Exception return gets state from PSP. Execution uses PSP after return. */
|
|
} EXC_RETURN_t;
|
|
|
|
/******************************************************
|
|
* Static Function Declarations
|
|
******************************************************/
|
|
|
|
void HardFaultException_handler( uint32_t MSP, uint32_t PSP, uint32_t LR );
|
|
|
|
/******************************************************
|
|
* Variable Definitions
|
|
******************************************************/
|
|
|
|
/******************************************************
|
|
* Function Definitions
|
|
******************************************************/
|
|
OSStatus stdio_hardfault( char* data, uint32_t size );
|
|
|
|
#ifdef DEBUG_HARDFAULT
|
|
|
|
PLATFORM_DEFINE_NAKED_ISR( HardFault_Handler )
|
|
{
|
|
// __ASM("MRS R0, MSP" );
|
|
// __ASM("MRS R1, PSP" );
|
|
// __ASM("MOV R2, LR" );
|
|
// __ASM("B HardFaultException_handler");
|
|
__ASM("TST LR, #4" );
|
|
__ASM("ITE EQ" );
|
|
__ASM("MRSEQ R0, MSP" );
|
|
__ASM("MRSNE R0, PSP" );
|
|
__ASM("MOV SP, R0" );
|
|
__ASM("B hard_fault_handler_c");
|
|
|
|
}
|
|
|
|
void hard_fault_handler_c (unsigned int * hardfault_args)
|
|
{
|
|
unsigned int stacked_r0;
|
|
unsigned int stacked_r1;
|
|
unsigned int stacked_r2;
|
|
unsigned int stacked_r3;
|
|
unsigned int stacked_r12;
|
|
unsigned int stacked_lr;
|
|
unsigned int stacked_pc;
|
|
unsigned int stacked_psr;
|
|
char logString[50];
|
|
|
|
stacked_r0 = ((unsigned long) hardfault_args[0]);
|
|
stacked_r1 = ((unsigned long) hardfault_args[1]);
|
|
stacked_r2 = ((unsigned long) hardfault_args[2]);
|
|
stacked_r3 = ((unsigned long) hardfault_args[3]);
|
|
|
|
stacked_r12 = ((unsigned long) hardfault_args[4]);
|
|
stacked_lr = ((unsigned long) hardfault_args[5]);
|
|
stacked_pc = ((unsigned long) hardfault_args[6]);
|
|
stacked_psr = ((unsigned long) hardfault_args[7]);
|
|
|
|
sprintf (logString,"\n>>>>>>>>>>>>>>[");
|
|
stdio_hardfault( logString, strlen(logString)+1 );
|
|
switch(__get_IPSR())
|
|
{
|
|
case 3:
|
|
sprintf (logString, "Hard Fault");
|
|
stdio_hardfault( logString, strlen(logString)+1 );
|
|
break;
|
|
|
|
case 4:
|
|
sprintf (logString, "Memory Manage");
|
|
stdio_hardfault( logString, strlen(logString)+1 );
|
|
break;
|
|
|
|
case 5:
|
|
sprintf (logString, "Bus Fault");
|
|
stdio_hardfault( logString, strlen(logString)+1 );
|
|
break;
|
|
|
|
case 6:
|
|
sprintf (logString, "Usage Fault");
|
|
stdio_hardfault( logString, strlen(logString)+1 );
|
|
break;
|
|
|
|
default:
|
|
sprintf (logString, "Unknown Fault %ld", __get_IPSR());
|
|
stdio_hardfault( logString, strlen(logString)+1 );
|
|
break;
|
|
}
|
|
sprintf (logString, ",corrupt,dump registers]>>>>>>>>>>>>>>>>>>\n\r");
|
|
stdio_hardfault( logString, strlen(logString)+1 );
|
|
|
|
sprintf (logString, "R0 = 0x%08x\r\n", stacked_r0);
|
|
stdio_hardfault( logString, strlen(logString)+1 );
|
|
sprintf (logString, "R1 = 0x%08x\r\n", stacked_r1);
|
|
stdio_hardfault( logString, strlen(logString)+1 );
|
|
sprintf (logString, "R2 = 0x%08x\r\n", stacked_r2);
|
|
stdio_hardfault( logString, strlen(logString)+1 );
|
|
sprintf (logString, "R3 = 0x%08x\r\n", stacked_r3);
|
|
stdio_hardfault( logString, strlen(logString)+1 );
|
|
sprintf (logString, "R12 = 0x%08x\r\n", stacked_r12);
|
|
stdio_hardfault( logString, strlen(logString)+1 );
|
|
sprintf (logString, "LR [R14] = 0x%08x subroutine call return address\r\n", stacked_lr);
|
|
stdio_hardfault( logString, strlen(logString)+1 );
|
|
sprintf (logString, "PC [R15] = 0x%08X program counter\r\n", stacked_pc);
|
|
stdio_hardfault( logString, strlen(logString)+1 );
|
|
sprintf (logString, "PSR = 0x%08X\r\n", stacked_psr);
|
|
stdio_hardfault( logString, strlen(logString)+1 );
|
|
sprintf (logString, "BFAR = 0x%08lx\r\n", (*((volatile unsigned long *)(0xE000ED38))));
|
|
stdio_hardfault( logString, strlen(logString)+1 );
|
|
sprintf (logString, "CFSR = 0x%08lx\r\n", (*((volatile unsigned long *)(0xE000ED28))));
|
|
stdio_hardfault( logString, strlen(logString)+1 );
|
|
sprintf (logString, "HFSR = 0x%08lx\r\n", (*((volatile unsigned long *)(0xE000ED2C))));
|
|
stdio_hardfault( logString, strlen(logString)+1 );
|
|
sprintf (logString, "DFSR = 0x%08lx\r\n", (*((volatile unsigned long *)(0xE000ED30))));
|
|
stdio_hardfault( logString, strlen(logString)+1 );
|
|
sprintf (logString, "AFSR = 0x%08lx\r\n", (*((volatile unsigned long *)(0xE000ED3C))));
|
|
stdio_hardfault( logString, strlen(logString)+1 );
|
|
|
|
while (1);
|
|
}
|
|
|
|
#if defined( __GNUC__ ) && ( ! defined( __clang__ ) )
|
|
#pragma GCC optimize ("O0")
|
|
#endif /* if defined( __GNUC__ ) && ( ! defined( __clang__ ) ) */
|
|
|
|
void HardFaultException_handler( uint32_t MSP, uint32_t PSP, uint32_t LR )
|
|
{
|
|
exception_stacked_registers_t* stackframe;
|
|
uint32_t MMFAR = 0;
|
|
uint32_t BFAR = 0;
|
|
|
|
/* Get the Link Register value which contains the EXC_RETURN code */
|
|
EXC_RETURN_t EXC_RETURN = (EXC_RETURN_t)(LR & 0xff);
|
|
|
|
/* The location of the stack frame of the offending code is indicated by the EXC_RETURN code */
|
|
if ( ( EXC_RETURN & 0x00000004 ) != 0 )
|
|
{
|
|
stackframe = (exception_stacked_registers_t*) PSP;
|
|
}
|
|
else
|
|
{
|
|
stackframe = (exception_stacked_registers_t*) MSP;
|
|
}
|
|
(void) stackframe; /* may be unused */
|
|
|
|
/* Disable interrupts - this is so that when debugger continues, it will go to caller, not an interrupt routine */
|
|
/* This will mean the system cannot run properly when returning */
|
|
__set_PRIMASK( 0x01 );
|
|
|
|
/* Find cause of hardfault */
|
|
if ( ( SCB->HFSR & SCB_HFSR_VECTTBL_Msk ) != 0 )
|
|
{
|
|
MICO_TRIGGER_BREAKPOINT(); /* Vector Table Hard Fault - Bus fault during vector table read during exception processing. */
|
|
}
|
|
else if ( ( SCB->HFSR & SCB_HFSR_FORCED_Msk ) != 0 )
|
|
{
|
|
/* Hard Fault is an escalated fault that was not handled */
|
|
/* Need to read the other fault status registers */
|
|
|
|
|
|
if ( ( SCB->CFSR & SCB_CFSR_MMARVALID ) != 0 )
|
|
{
|
|
/* Memory Management Fault address register is valid - read it. */
|
|
MMFAR = SCB->MMFAR;
|
|
}
|
|
|
|
if ( ( SCB->CFSR & SCB_CFSR_BFARVALID ) != 0 )
|
|
{
|
|
/* Bus Fault address register is valid - read it. */
|
|
BFAR = SCB->BFAR;
|
|
}
|
|
|
|
if ( ( SCB->CFSR & SCB_CFSR_IACCVIOL ) != 0 )
|
|
{
|
|
/* Memory Management Fault */
|
|
MICO_TRIGGER_BREAKPOINT(); /* Instruction Access Violation - Attempt to execute an instruction from a region marked Execute Never */
|
|
(void) stackframe->LR; /* Check this variable for the jump instruction that jumped to an invalid region */
|
|
(void) stackframe->PC; /* Check this variable for the location that was attempted to be executed */
|
|
/* You may try stepping past the return of this handler, which may return near the location of the error */
|
|
|
|
}
|
|
else if ( ( SCB->CFSR & SCB_CFSR_DACCVIOL ) != 0 )
|
|
{
|
|
/* Memory Management Fault */
|
|
MICO_TRIGGER_BREAKPOINT(); /* Data Access Violation */
|
|
(void) stackframe->PC; /* Check this variable for the location of the offending instruction */
|
|
(void) MMFAR; /* Check this variable for the address of the attempted access */
|
|
/* You may try stepping past the return of this handler, which may return near the location of the error */
|
|
}
|
|
else if ( ( SCB->CFSR & SCB_CFSR_MUNSTKERR ) != 0 )
|
|
{
|
|
/* Memory Management Fault */
|
|
MICO_TRIGGER_BREAKPOINT(); /* Unstacking fault returning from an exception - stack possibly corrupted during exception handler */
|
|
/* New stackframe is not saved in this case */
|
|
}
|
|
else if ( ( SCB->CFSR & SCB_CFSR_MSTKERR ) != 0 )
|
|
{
|
|
/* Memory Management Fault */
|
|
MICO_TRIGGER_BREAKPOINT(); /* Stacking fault whilst entering an exception - probably a bad stack pointer */
|
|
/* Stack frame may be incorrect due to bad stack pointer */
|
|
|
|
}
|
|
else if ( ( SCB->CFSR & SCB_CFSR_IBUSERR ) != 0 )
|
|
{
|
|
/* Bus Fault */
|
|
MICO_TRIGGER_BREAKPOINT(); /* Instruction Bus Error whilst fetching an instruction*/
|
|
}
|
|
else if ( ( SCB->CFSR & SCB_CFSR_PRECISERR ) != 0 )
|
|
{
|
|
/* Bus Fault */
|
|
MICO_TRIGGER_BREAKPOINT(); /* Precise Data Bus Error - i.e. Data Bus fault at well defined location */
|
|
(void) stackframe->PC; /* Check this variable for the location of the offending instruction */
|
|
(void) BFAR; /* Check this variable for the faulting address */
|
|
/* You may try stepping past the return of this handler, which may return near the location of the error */
|
|
}
|
|
else if ( ( SCB->CFSR & SCB_CFSR_IMPRECISERR ) != 0 )
|
|
{
|
|
/* Bus Fault */
|
|
MICO_TRIGGER_BREAKPOINT(); /* Imprecise Data Bus Error - i.e. Data Bus fault occurred but details have been lost due to priorities delaying processing of the fault */
|
|
/* No fault details are available in this case*/
|
|
/* You may try stepping past the return of this handler, which may return near the location of the error */
|
|
}
|
|
else if ( ( SCB->CFSR & SCB_CFSR_UNSTKERR ) != 0 )
|
|
{
|
|
/* Bus Fault */
|
|
MICO_TRIGGER_BREAKPOINT(); /* Unstacking fault returning from an exception - stack possibly corrupted during exception handler */
|
|
/* New stackframe is not saved in this case */
|
|
}
|
|
else if ( ( SCB->CFSR & SCB_CFSR_STKERR ) != 0 )
|
|
{
|
|
/* Bus Fault */
|
|
MICO_TRIGGER_BREAKPOINT(); /* Stacking fault whilst entering an exception - probably a bad stack pointer */
|
|
/* Stack frame may be incorrect due to bad stack pointer */
|
|
|
|
}
|
|
else if ( ( SCB->CFSR & SCB_CFSR_UNDEFINSTR ) != 0 )
|
|
{
|
|
/* Usage Fault */
|
|
MICO_TRIGGER_BREAKPOINT(); /* Undefined Instruction Usage fault - probably corrupted memory in code space */
|
|
(void) stackframe->PC; /* Check this variable for the location of the offending instruction */
|
|
/* You may try stepping past the return of this handler, which may return near the location of the error */
|
|
}
|
|
else if ( ( SCB->CFSR & SCB_CFSR_INVSTATE ) != 0 )
|
|
{
|
|
/* Usage Fault */
|
|
MICO_TRIGGER_BREAKPOINT(); /* Invalid State usage fault - This is probably due to a branch with the LSB=0 - i.e. attempt to execute non-thumb code - Illegal use of EPSR was attempted */
|
|
(void) stackframe->PC; /* Check this variable for the location of the offending instruction */
|
|
/* You may try stepping past the return of this handler, which may return near the location of the error */
|
|
}
|
|
else if ( ( SCB->CFSR & SCB_CFSR_INVPC ) != 0 )
|
|
{
|
|
/* Usage Fault */
|
|
MICO_TRIGGER_BREAKPOINT(); /* Invalid PC load usage fault - the EXC_RETURN value in LR was invalid on return from an exception - possibly stack corruption in exception */
|
|
(void) stackframe->PC; /* Check this variable for the location of the offending instruction */
|
|
/* You may try stepping past the return of this handler, which may return near the location of the error */
|
|
}
|
|
else if ( ( SCB->CFSR & SCB_CFSR_NOCP ) != 0 )
|
|
{
|
|
/* Usage Fault */
|
|
MICO_TRIGGER_BREAKPOINT(); /* No Coprocessor usage fault - coprocessor instruction attempted on processor without support for them */
|
|
(void) stackframe->PC; /* Check this variable for the location of the offending instruction */
|
|
/* You may try stepping past the return of this handler, which may return near the location of the error */
|
|
}
|
|
else if ( ( SCB->CFSR & SCB_CFSR_UNALIGNED ) != 0 )
|
|
{
|
|
/* Usage Fault */
|
|
MICO_TRIGGER_BREAKPOINT(); /* Unaligned access usage fault - Unaligned access whilst UNALIGN_TRP bit of SCB_CCR is set, or any unaligned access to LDM, STM, LDRD or STRD */
|
|
(void) stackframe->PC; /* Check this variable for the location of the offending instruction */
|
|
/* You may try stepping past the return of this handler, which may return near the location of the error */
|
|
}
|
|
else if ( ( SCB->CFSR & SCB_CFSR_DIVBYZERO ) != 0 )
|
|
{
|
|
/* Usage Fault */
|
|
MICO_TRIGGER_BREAKPOINT(); /* Divide by zero usage fault */
|
|
(void) stackframe->PC; /* Check this variable for the location of the offending instruction */
|
|
/* You may try stepping past the return of this handler, which may return near the location of the error */
|
|
}
|
|
else
|
|
{
|
|
/* Unknown Fault */
|
|
MICO_TRIGGER_BREAKPOINT();
|
|
/* You may try stepping past the return of this handler, which may return near the location of the error */
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
/* Unknown Hard Fault cause */
|
|
MICO_TRIGGER_BREAKPOINT();
|
|
/* You may try stepping past the return of this handler, which may return near the location of the error */
|
|
}
|
|
|
|
(void) MMFAR; /* This is for debug usage and need not be used programmatically */
|
|
(void) BFAR; /* This is for debug usage and need not be used programmatically */
|
|
}
|
|
#if defined( __GNUC__ ) && ( ! defined( __clang__ ) )
|
|
#pragma GCC reset_options
|
|
#endif /* if defined( __GNUC__ ) && ( ! defined( __clang__ ) ) */
|
|
|
|
#endif /* ifdef DEBUG_HARDFAULT */
|
|
|