HardFault_Handler\
PROC
IMPORT hard_fault_handler_c
TST LR, #4
ITE EQ
MRSEQ R0, MSP
MRSNE R0, PSP
B hard_fault_handler_c
ENDP
2.添加处理函数
hard_fault_handler_c,并且将crash log同步保存到了flash上,即使掉电重启也不会丢失。注意在写flash之前需要先确保文件系统是否写完整,这个非常关键,低概率下会出现,死机的时候,正在写文件,如果此时死机重启,可能会破坏文件系统,导致系统起不来,这点也是往往开发过程中,容易忽视的地方。如果crash的时候,发现文件正在写,就等文件写完再保存死机log,然后才能重启。
/*****************************************************************************
FUNCTION NAME: hard_fault_handler_c
DESCRIPTION: Print hard_fault handler info on the HyperTerminal.
PARAMETERS:
hardfault_args: hard fault args in sp
RET VALUES:
None
*****************************************************************************/
void hard_fault_handler_c(uint32* hardfault_args)
{
uint8* pBuff = (uint8*)OsMalloc(MEM_POOL_1_BLOCK_SIZE);
uint8 Len = FillBuffwithCurrTime(pBuff);//打印死机时间
uint16 i;
IsCrashed = TRUE;
HaltLogInit();//初始化log区域,同步保存到flash,以便重新开机也能读取到死机log
ArmCoreRegs.r0 = ((uint32) hardfault_args[0]);
ArmCoreRegs.r1 = ((uint32) hardfault_args[1]);
ArmCoreRegs.r2 = ((uint32) hardfault_args[2]);
ArmCoreRegs.r3 = ((uint32) hardfault_args[3]);
ArmCoreRegs.r12 = ((uint32) hardfault_args[4]);
/*R14 is return address*/
ArmCoreRegs.lr = ((uint32) hardfault_args[5]);
ArmCoreRegs.pc = ((uint32) hardfault_args[6]);
ArmCoreRegs.psr = ((uint32) hardfault_args[7]);
ArmCoreRegs.sp = ((uint32) hardfault_args);
ArmCoreRegs.CPUID = SCB->CPUID; /*CPUID Base Register */
ArmCoreRegs.ICSR = SCB->ICSR; /*Interrupt Control and State Register */
ArmCoreRegs.SCR = SCB->SCR; /*System Control Register */
ArmCoreRegs.CCR = SCB->CCR; /*Configuration Control Register */
ArmCoreRegs.SHCSR = SCB->SHCSR; /*System Handler Control and State Register */
ArmCoreRegs.CFSR = SCB->CFSR; /*Configurable Fault Status Registers */
ArmCoreRegs.HFSR = SCB->HFSR; /*HardFault Status Register */
ArmCoreRegs.DFSR = SCB->DFSR; /*Debug Fault Status Register */
ArmCoreRegs.MMFAR = SCB->MMFAR; /*MemManage Fault Address Register */
ArmCoreRegs.BFAR = SCB->BFAR; /*BusFault Address Register */
Debug_IOP_BufQ_Output();
HAL_UART_ResetState(GetUartHandle(DEBUG_UART));
Serial_PutString(pBuff, Len);
OsFree(pBuff);
Critical_printf("hard_fault_handler:\r\n");
Critical_printf("---------------------------------------------------------------------------------------------\r\n");
Critical_printf("r0 = 0x%08x \tr1 = 0x%08x \tr2 = 0x%08x \tr3 = 0x%08x\r\n",
ArmCoreRegs.r0,ArmCoreRegs.r1,ArmCoreRegs.r2,ArmCoreRegs.r3);
Critical_printf("r12 = 0x%08x \tlr = 0x%08x \tpc = 0x%08x \tpsr = 0x%08x\r\n",
ArmCoreRegs.r12,ArmCoreRegs.lr,ArmCoreRegs.pc,ArmCoreRegs.psr);
Critical_printf("sp = 0x%08x\r\n\r\n", ArmCoreRegs.sp);
Critical_printf("CPUID = 0x%08x\tICSR = 0x%08x\tSCR = 0x%08x\tCCR = 0x%08x\r\n",
ArmCoreRegs.CPUID,ArmCoreRegs.ICSR,ArmCoreRegs.SCR,ArmCoreRegs.CCR);
Critical_printf("SHCSR = 0x%08x\tCFSR = 0x%08x\tHFSR = 0x%08x\tDFSR = 0x%08x\r\n",
ArmCoreRegs.SHCSR,ArmCoreRegs.CFSR,ArmCoreRegs.HFSR,ArmCoreRegs.DFSR);
Critical_printf("MMFAR = 0x%08x\tBFAR = 0x%08x\r\n",
ArmCoreRegs.MMFAR,ArmCoreRegs.BFAR);
Critical_printf("---------------------------------------------------------------------------------------------\r\n");
Critical_printf("hard fault Task stack:\r\n");
for(i=0; i< CUR_TASK_PRINTF_DUMP_SIZE; i++)
{
Critical_printf("0x%08x ", *((uint32*)ArmCoreRegs.sp + i));
if((i+1)%8 == 0)
Critical_printf("\r\n");
}
Critical_printf("---------------------------------------------------------------------------------------------\r\n\r\n");
CheckFsmLastOptAtCrash();
FreeRtosStatusDebug();
HaltLogWriteEnd();
NAL_System_Reset();
while(1);
}
/*****************************************************************************
FUNCTION NAME: CheckFsmLastOptAtCrash
DESCRIPTION: check the fsm whether is writing when crash.
PARAMETERS:
None
RET VALUES:
None
*****************************************************************************/
void CheckFsmLastOptAtCrash(void)
{
if(IsSpiFlashInWriting())
{
Critical_printf("Spi flash filesystem is in writing while halt, will finish it...\r\n");
HwdSpiFlashReInitWhenCrash();
SpiFlash_write_NO_Int();
Critical_printf("Spi flash filesystem write end\r\n");
}
}
对于task堆栈的打印,在st提供的库上修改:
#if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) )
void vTaskList( char * pcWriteBuffer )
{
TaskStatus_t *pxTaskStatusArray;
volatile UBaseType_t uxArraySize, x, i;
char cStatus;
TCB_t *xTCB;
TCB_t *currTCB;
uint16 Dump_Size;
pcWriteBuffer = pcWriteBuffer;
/*
* PLEASE NOTE:
*
* This function is provided for convenience only, and is used by many
* of the demo applications. Do not consider it to be part of the
* scheduler.
*
* vTaskList() calls uxTaskGetSystemState(), then formats part of the
* uxTaskGetSystemState() output into a human readable table that
* displays task names, states and stack usage.
*
* vTaskList() has a dependency on the sprintf() C library function that
* might bloat the code size, use a lot of stack, and provide different
* results on different platforms. An alternative, tiny, third party,
* and limited functionality implementation of sprintf() is provided in
* many of the FreeRTOS/Demo sub-directories in a file called
* printf-stdarg.c (note printf-stdarg.c does not provide a full
* snprintf() implementation!).
*
* It is recommended that production systems call uxTaskGetSystemState()
* directly to get access to raw stats data, rather than indirectly
* through a call to vTaskList().
*/
/* Make sure the write buffer does not contain a string. */
//*pcWriteBuffer = 0x00;
currTCB = pxCurrentTCB;
Critical_printf("Current running Task:%s \r\n", currTCB->pcTaskName);
Critical_printf("---------------------------------------------------------------------------------------------\r\n");
/* Take a snapshot of the number of tasks in case it changes while this
function is executing. */
uxArraySize = uxCurrentNumberOfTasks;
/* Allocate an array index for each task. */
pxTaskStatusArray = pvPortMalloc( uxCurrentNumberOfTasks * sizeof( TaskStatus_t ) );
if( pxTaskStatusArray != NULL )
{
/* Generate the (binary) data. */
uxArraySize = uxTaskGetSystemState( pxTaskStatusArray, uxArraySize, NULL );
/* Create a human readable table from the binary data. */
for( x = 0; x < uxArraySize; x++ )
{
xTCB = pxTaskStatusArray[ x ].xHandle;
Critical_printf("task name:%s\r\n",xTCB->pcTaskName);
Critical_printf("---------------------------------------------------------------------------------------------\r\n");
Critical_printf("Stack = 0x%x, TopOfStack = 0x%x\r\n", xTCB->pxStack, xTCB->pxTopOfStack);
if(xTCB == currTCB)
Dump_Size = CUR_TASK_PRINTF_DUMP_SIZE;
else
Dump_Size = TASK_PRINTF_DUMP_SIZE;
for(i=0; i< Dump_Size; i++)
{
Critical_printf("0x%08x ", (uint32)*(xTCB->pxTopOfStack + i));
if((i+1)%8 == 0)
Critical_printf("\r\n");
}
Critical_printf("---------------------------------------------------------------------------------------------\r\n\r\n");
}
Critical_printf("---------------------------------------------------------------------------------------------\r\n");
Critical_printf(" task_name\tstatus\tPriotity\tMinFreeStack(U32)\ttask_Num\r\n");
Critical_printf("---------------------------------------------------------------------------------------------\r\n");
/* Create a human readable table from the binary data. */
for( x = 0; x < uxArraySize; x++ )
{
switch( pxTaskStatusArray[ x ].eCurrentState )
{
case eReady: cStatus = tskREADY_CHAR;
break;
case eBlocked: cStatus = tskBLOCKED_CHAR;
break;
case eSuspended: cStatus = tskSUSPENDED_CHAR;
break;
case eDeleted: cStatus = tskDELETED_CHAR;
break;
default: /* Should not get here, but it is included
to prevent static checking errors. */
cStatus = 0x00;
break;
}
/* Write the task name to the string, padding with spaces so it
can be printed in tabular form more easily. */
//pcWriteBuffer = prvWriteNameToBuffer( pcWriteBuffer, pxTaskStatusArray[ x ].pcTaskName );
Critical_printf("%16s",pxTaskStatusArray[ x ].pcTaskName);
/* Write the rest of the string. */
Critical_printf("\t%c\t%u\t\t%u\t\t\t%u\r\n", cStatus, ( unsigned int ) pxTaskStatusArray[ x ].uxCurrentPriority, ( unsigned int ) pxTaskStatusArray[ x ].usStackHighWaterMark, ( unsigned int ) pxTaskStatusArray[ x ].xTaskNumber );
}
Critical_printf("---------------------------------------------------------------------------------------------\r\n");
/* Free the array again. */
vPortFree( pxTaskStatusArray );
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
#endif /* ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) ) */
参考文献:
网易云大礼包:https://www.163yun.com/gift
本文来自网易实践者社区,经作者刘国建授权发布