程序莫名死机跑飞,不知道问题,那么下面教你回溯错误源
回溯案发现场
- 一、修改HardFault_Handler
- 1. xx.s 在启动文件,找到HardFault_Handler。并修改。
- 2. 定义HardFault_Handler_C函数。(主要是打印信息并存储Flash)
- 3. 根据回读PC和LR地址,通过MAP文件找到对应位置,判断引起硬件错误的原因。
- 二、定义DefaultISR,查看是否有中断未声明
- 三、如果使用了RTX,则需要重定义osRtxErrorNotify函数。
- 四、读取错误信息
- 举例
jianqiang.xue
一、修改HardFault_Handler
1. xx.s 在启动文件,找到HardFault_Handler。并修改。
HardFault_Handler\
PROC
EXPORT HardFault_Handler [WEAK]
MOV R0, sp
IMPORT HardFault_Handler_C
BL HardFault_Handler_C
ENDP
2. 定义HardFault_Handler_C函数。(主要是打印信息并存储Flash)
void HardFault_Handler_C(unsigned int* hardfault_args) {
HardFault_t info;
info.r0 = ((unsigned long)hardfault_args[0]);
info.r1 = ((unsigned long)hardfault_args[1]);
info.r2 = ((unsigned long)hardfault_args[2]);
info.r3 = ((unsigned long)hardfault_args[3]);
info.r12 = ((unsigned long)hardfault_args[4]);
info.lr = ((unsigned long)hardfault_args[5]);
info.pc = ((unsigned long)hardfault_args[6]);
info.psr = ((unsigned long)hardfault_args[7]);
info.BFAR = (*((volatile unsigned long*)(0xE000ED38)));
info.CFSR = (*((volatile unsigned long*)(0xE000ED28)));
info.HFSR = (*((volatile unsigned long*)(0xE000ED2C)));
info.DFSR = (*((volatile unsigned long*)(0xE000ED30)));
info.AFSR = (*((volatile unsigned long*)(0xE000ED3C)));
info.SCB_SHCSR = SCB->SHCSR;
uint8_t data[70], len = 0;
len = snprintf((char *)data,70, "\n[Hard fault handler - all num in hex] %x\r\n", *hardfault_args);
McuUartWriteString(&ble_uart, data, len);
len = snprintf((char *)data,70, "R0 = %x\r\nR1 = %x\r\nR2 = %x\r\nR3 = %x\r\n", info.r0, info.r1, info.r2, info.r3);
McuUartWriteString(&ble_uart, data, len);
len = snprintf((char *)data,70, "R12 = %x\r\n", info.r12);
McuUartWriteString(&ble_uart, data, len);
len = snprintf((char *)data,70, "LR [R14] = %x,subroutine call return address\r\n", info.lr);
McuUartWriteString(&ble_uart, data, len);
len = snprintf((char *)data,70, "PC [R15] = %x,program counter\r\n", info.pc);
McuUartWriteString(&ble_uart, data, len);
len = snprintf((char *)data,70, "PSR = %x\r\nBFAR = %lx\r\n", info.psr, (*((volatile unsigned long*)(0xE000ED38))));
McuUartWriteString(&ble_uart, data, len);
len = snprintf((char *)data,70, "CFSR = %lx\r\nHFSR = %lx\r\nDFSR = %lx\r\n",
(*((volatile unsigned long*)(0xE000ED28))), (*((volatile unsigned long*)(0xE000ED2C))), (*((volatile unsigned long*)(0xE000ED30))));
McuUartWriteString(&ble_uart, data, len);
len = snprintf((char *)data,70, "AFSR = %lx\r\nSCB_SHCSR = %x\r\n",
(*((volatile unsigned long*)(0xE000ED3C))), SCB->SHCSR);
McuUartWriteString(&ble_uart, data, len);
info.event = 0;
kv_set_env(0xFF00, &info, sizeof(HardFault_t)); // 记录到Flash
while (1);
}
3. 根据回读PC和LR地址,通过MAP文件找到对应位置,判断引起硬件错误的原因。
二、定义DefaultISR,查看是否有中断未声明
#define VECTORNUM (*(volatile uint32_t*)(0xE000ED04))
void DefaultISR(void) {
HardFault_t info;
uint8_t data[50], len;
len = sprintf((char *)data, "\n default_isr %d,%x \n", (uint8_t)VECTORNUM, (uint32_t)VECTORNUM);
McuUartWriteString(&ble_uart, data, len);
info.event = 1;
info.VECTORNUM_ADDR = VECTORNUM;
kv_set_env(0xFF00, &info, sizeof(HardFault_t)); // 记录到Flash
while(1);
}
根据打印出来的数据,判断VECTOR,是怎么原因触发中断的。查对应芯片向量表,得知导致原因。
三、如果使用了RTX,则需要重定义osRtxErrorNotify函数。
uint32_t osRtxErrorNotify(uint32_t code, void* object_id) {
HardFault_t info;
(void)object_id;
uint8_t data[100], len = 0;
switch (code) {
case osRtxErrorStackOverflow:
len = sprintf((char *)data, "\n Stack overflow detected for thread (thread_id=0x%x)\n", (uint32_t)object_id);
McuUartWriteString(&ble_uart, data, len);
// Stack overflow detected for thread (thread_id=object_id)
break;
case osRtxErrorISRQueueOverflow:
len = sprintf((char *)data, "\n ISR Queue overflow detected when inserting object 0x%x\n", (uint32_t)object_id);
McuUartWriteString(&ble_uart, data, len);
// ISR Queue overflow detected when inserting object (object_id)
break;
case osRtxErrorTimerQueueOverflow:
len = sprintf((char *)data, "\n User Timer Callback Queue overflow detected for timer (timer_id=0x%x)\n", (uint32_t)object_id);
McuUartWriteString(&ble_uart, data, len);
// User Timer Callback Queue overflow detected for timer (timer_id=object_id)
break;
case osRtxErrorClibSpace:
len = sprintf((char *)data, "\n Standard C/C++ library libspace not available: increase OS_THREAD_LIBSPACE_NUM 0x%x\n", (uint32_t)object_id);
McuUartWriteString(&ble_uart, data, len);
// Standard C/C++ library libspace not available: increase OS_THREAD_LIBSPACE_NUM
break;
case osRtxErrorClibMutex:
len = sprintf((char *)data, "\n Standard C/C++ library mutex initialization failed 0x%x\n", (uint32_t)object_id);
McuUartWriteString(&ble_uart, data, len);
// Standard C/C++ library mutex initialization failed
break;
default:
// Reserved
break;
}
info.event = 2;
info.RTX_CODE = code;
info.RTX_OBJ_ID = (uint32_t)object_id;
kv_set_env(0xFF00, &info, sizeof(HardFault_t)); // 记录到Flash
for (;;) {
}
// return 0U;
}
四、读取错误信息
采用ATCMD读取,如下
#ifdef ATCMD_EN
// 在功能模块中定义一个标准函数
static int atcmd_backtrack(atcmd_pack_t *pack) {
HardFault_t *info = NULL;
uint8_t buff[100], len;
info = kv_get_env(0xFF00);
if (info == NULL) {
strcat((char*)buff, AT_ERROR);
} else {
if (info->event == 0) {
len = snprintf((char *)buff, 100, "R0 = %x\r\nR1 = %x\r\nR2 = %x\r\nR3 = %x\r\nR12 = %x\r\n", info->r0, info->r1, info->r2, info->r3, info->r12);
pack->reply(buff, strlen((char*)buff));
len = snprintf((char *)buff, 100, "LR [R14] = %x,subroutine call return address\r\n", info->lr);
pack->reply(buff, strlen((char*)buff));
len = snprintf((char *)buff, 100, "PC [R15] = %x,program counter\r\n", info->pc);
pack->reply(buff, strlen((char*)buff));
len = snprintf((char *)buff, 100, "PSR = %x\r\nBFAR = %lx\r\n", info->psr, (*((volatile unsigned long*)(0xE000ED38))));
pack->reply(buff, strlen((char*)buff));
len = snprintf((char *)buff, 100, "CFSR = %lx\r\nHFSR = %lx\r\nDFSR = %lx\r\n",
(*((volatile unsigned long*)(0xE000ED28))), (*((volatile unsigned long*)(0xE000ED2C))), (*((volatile unsigned long*)(0xE000ED30))));
pack->reply(buff, strlen((char*)buff));
len = snprintf((char *)buff, 100, "AFSR = %lx\r\nSCB_SHCSR = %x\r\n",
(*((volatile unsigned long*)(0xE000ED3C))), SCB->SHCSR);
pack->reply(buff, strlen((char*)buff));
memset(buff, 0, 100);
} else if (info->event == 1) {
len = snprintf((char *)buff, 100, "\n default_isr %d,%x \n", (uint8_t)info->VECTORNUM_ADDR, (uint32_t)info->VECTORNUM_ADDR);
} else if (info->event == 2) {
len = snprintf((char *)buff, 100, "\n RTX_ERR CODE=0x%x, OBJ_ID=0x%x \n", (uint8_t)info->RTX_CODE, (uint32_t)info->RTX_OBJ_ID);
}
strcat((char*)buff, AT_OK);
}
pack->reply(buff, strlen((char*)buff));
return 0;
}
// 注册AT指令,传入标准函数
ATCMD_INIT("AT+BACKTRACK?", atcmd_backtrack);
#endif
举例
/********************************************************************************
* @file backtrack.c
* @author jianqiang.xue
* @Version V1.0.0
* @Date 2023-02-10
* @brief 记录错误原因,方便追溯问题源
********************************************************************************/
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include "cmsis_os2.h"
#include "os_api.h"
#include "SKEAZ1284.h"
#include "atcmd_slave.h" // 自行添加[Module\atcmd\atcmd_slave.c]
#include "kv_sys.h"
#include "mcu_uart.h"
#include "ecu_cc2642.h"
#include "edebug.h"
typedef struct __PACKED {
uint32_t event; // 0--HardFault 1--DefaultISR 2--osRtxErrorNotify
// HardFault_Handler
uint32_t r0;
uint32_t r1;
uint32_t r2;
uint32_t r3;
uint32_t r12;
uint32_t lr;
uint32_t pc;
uint32_t psr;
uint64_t BFAR;
uint64_t CFSR;
uint64_t HFSR;
uint64_t DFSR;
uint64_t AFSR;
uint64_t SCB_SHCSR;
// DefaultISR
uint32_t VECTORNUM_ADDR;
// osRtxErrorNotify
uint32_t RTX_CODE;
uint32_t RTX_OBJ_ID;
} HardFault_t;
void HardFault_Handler_C(unsigned int* hardfault_args) {
HardFault_t info;
info.r0 = ((unsigned long)hardfault_args[0]);
info.r1 = ((unsigned long)hardfault_args[1]);
info.r2 = ((unsigned long)hardfault_args[2]);
info.r3 = ((unsigned long)hardfault_args[3]);
info.r12 = ((unsigned long)hardfault_args[4]);
info.lr = ((unsigned long)hardfault_args[5]);
info.pc = ((unsigned long)hardfault_args[6]);
info.psr = ((unsigned long)hardfault_args[7]);
info.BFAR = (*((volatile unsigned long*)(0xE000ED38)));
info.CFSR = (*((volatile unsigned long*)(0xE000ED28)));
info.HFSR = (*((volatile unsigned long*)(0xE000ED2C)));
info.DFSR = (*((volatile unsigned long*)(0xE000ED30)));
info.AFSR = (*((volatile unsigned long*)(0xE000ED3C)));
info.SCB_SHCSR = SCB->SHCSR;
uint8_t data[70], len = 0;
len = snprintf((char *)data,70, "\n[Hard fault handler - all num in hex] %x\r\n", *hardfault_args);
McuUartWriteString(&ble_uart, data, len);
len = snprintf((char *)data,70, "R0 = %x\r\nR1 = %x\r\nR2 = %x\r\nR3 = %x\r\n", info.r0, info.r1, info.r2, info.r3);
McuUartWriteString(&ble_uart, data, len);
len = snprintf((char *)data,70, "R12 = %x\r\n", info.r12);
McuUartWriteString(&ble_uart, data, len);
len = snprintf((char *)data,70, "LR [R14] = %x,subroutine call return address\r\n", info.lr);
McuUartWriteString(&ble_uart, data, len);
len = snprintf((char *)data,70, "PC [R15] = %x,program counter\r\n", info.pc);
McuUartWriteString(&ble_uart, data, len);
len = snprintf((char *)data,70, "PSR = %x\r\nBFAR = %lx\r\n", info.psr, (*((volatile unsigned long*)(0xE000ED38))));
McuUartWriteString(&ble_uart, data, len);
len = snprintf((char *)data,70, "CFSR = %lx\r\nHFSR = %lx\r\nDFSR = %lx\r\n",
(*((volatile unsigned long*)(0xE000ED28))), (*((volatile unsigned long*)(0xE000ED2C))), (*((volatile unsigned long*)(0xE000ED30))));
McuUartWriteString(&ble_uart, data, len);
len = snprintf((char *)data,70, "AFSR = %lx\r\nSCB_SHCSR = %x\r\n",
(*((volatile unsigned long*)(0xE000ED3C))), SCB->SHCSR);
McuUartWriteString(&ble_uart, data, len);
info.event = 0;
kv_set_env(0xFF00, &info, sizeof(HardFault_t)); // 记录到Flash
while (1);
}
#define VECTORNUM (*(volatile uint32_t*)(0xE000ED04))
void DefaultISR(void) {
HardFault_t info;
uint8_t data[50], len;
len = sprintf((char *)data, "\n default_isr %d,%x \n", (uint8_t)VECTORNUM, (uint32_t)VECTORNUM);
McuUartWriteString(&ble_uart, data, len);
info.event = 1;
info.VECTORNUM_ADDR = VECTORNUM;
kv_set_env(0xFF00, &info, sizeof(HardFault_t)); // 记录到Flash
while(1);
}
uint32_t osRtxErrorNotify(uint32_t code, void* object_id) {
HardFault_t info;
(void)object_id;
uint8_t data[100], len = 0;
switch (code) {
case osRtxErrorStackOverflow:
len = sprintf((char *)data, "\n Stack overflow detected for thread (thread_id=0x%x)\n", (uint32_t)object_id);
McuUartWriteString(&ble_uart, data, len);
// Stack overflow detected for thread (thread_id=object_id)
break;
case osRtxErrorISRQueueOverflow:
len = sprintf((char *)data, "\n ISR Queue overflow detected when inserting object 0x%x\n", (uint32_t)object_id);
McuUartWriteString(&ble_uart, data, len);
// ISR Queue overflow detected when inserting object (object_id)
break;
case osRtxErrorTimerQueueOverflow:
len = sprintf((char *)data, "\n User Timer Callback Queue overflow detected for timer (timer_id=0x%x)\n", (uint32_t)object_id);
McuUartWriteString(&ble_uart, data, len);
// User Timer Callback Queue overflow detected for timer (timer_id=object_id)
break;
case osRtxErrorClibSpace:
len = sprintf((char *)data, "\n Standard C/C++ library libspace not available: increase OS_THREAD_LIBSPACE_NUM 0x%x\n", (uint32_t)object_id);
McuUartWriteString(&ble_uart, data, len);
// Standard C/C++ library libspace not available: increase OS_THREAD_LIBSPACE_NUM
break;
case osRtxErrorClibMutex:
len = sprintf((char *)data, "\n Standard C/C++ library mutex initialization failed 0x%x\n", (uint32_t)object_id);
McuUartWriteString(&ble_uart, data, len);
// Standard C/C++ library mutex initialization failed
break;
default:
// Reserved
break;
}
info.event = 2;
info.RTX_CODE = code;
info.RTX_OBJ_ID = (uint32_t)object_id;
kv_set_env(0xFF00, &info, sizeof(HardFault_t)); // 记录到Flash
for (;;) {
}
// return 0U;
}
#ifdef ATCMD_EN
// 在功能模块中定义一个标准函数
static int atcmd_backtrack(atcmd_pack_t *pack) {
HardFault_t *info = NULL;
uint8_t buff[100], len;
info = kv_get_env(0xFF00);
if (info == NULL) {
strcat((char*)buff, AT_ERROR);
} else {
if (info->event == 0) {
len = snprintf((char *)buff, 100, "R0 = %x\r\nR1 = %x\r\nR2 = %x\r\nR3 = %x\r\nR12 = %x\r\n", info->r0, info->r1, info->r2, info->r3, info->r12);
pack->reply(buff, strlen((char*)buff));
len = snprintf((char *)buff, 100, "LR [R14] = %x,subroutine call return address\r\n", info->lr);
pack->reply(buff, strlen((char*)buff));
len = snprintf((char *)buff, 100, "PC [R15] = %x,program counter\r\n", info->pc);
pack->reply(buff, strlen((char*)buff));
len = snprintf((char *)buff, 100, "PSR = %x\r\nBFAR = %lx\r\n", info->psr, (*((volatile unsigned long*)(0xE000ED38))));
pack->reply(buff, strlen((char*)buff));
len = snprintf((char *)buff, 100, "CFSR = %lx\r\nHFSR = %lx\r\nDFSR = %lx\r\n",
(*((volatile unsigned long*)(0xE000ED28))), (*((volatile unsigned long*)(0xE000ED2C))), (*((volatile unsigned long*)(0xE000ED30))));
pack->reply(buff, strlen((char*)buff));
len = snprintf((char *)buff, 100, "AFSR = %lx\r\nSCB_SHCSR = %x\r\n",
(*((volatile unsigned long*)(0xE000ED3C))), SCB->SHCSR);
pack->reply(buff, strlen((char*)buff));
memset(buff, 0, 100);
} else if (info->event == 1) {
len = snprintf((char *)buff, 100, "\n default_isr %d,%x \n", (uint8_t)info->VECTORNUM_ADDR, (uint32_t)info->VECTORNUM_ADDR);
} else if (info->event == 2) {
len = snprintf((char *)buff, 100, "\n RTX_ERR CODE=0x%x, OBJ_ID=0x%x \n", (uint8_t)info->RTX_CODE, (uint32_t)info->RTX_OBJ_ID);
}
strcat((char*)buff, AT_OK);
}
pack->reply(buff, strlen((char*)buff));
return 0;
}
// 注册AT指令,传入标准函数
ATCMD_INIT("AT+BACKTRACK?", atcmd_backtrack);
#endif