MM查找HardFault方法和步骤
实际环境中,由于测试高压等产品常常无法连接调试器,故需要代码来定位目标语句地址,并通过一定手段保存:
在MM32F0130中,需先修改启动文件startup_mm32f013x.s:
HardFault_Handler\
PROC
IMPORThard_fault_handler_c;函数声明
MOVS r0, #4 ;判断主栈指针还是进程栈指针
MOV r1, LR
TST r0, r1
BEQ stacking_used_MSP ;如果是主栈指针
MRS R0, PSP ;否则是进程栈指针,把进程栈指针地址付给 R0
B get_LR_and_branch ;跳转到 HardFault 中断程序
stacking_used_MSP
MRS R0, MSP ;把主栈指针地址赋给 R0
get_LR_and_branch
MOV R1, LR
BL hard_fault_handler_c
ENDP
该段代码会判断当前堆栈使用的是MSP或PSP,然后将堆栈参数传递给hard_fault_handler_c函数,该函数定义如下:
void hard_fault_handler_c(unsigned int * hardfault_args, unsigned lr_value)
{
unsigned int stacked_r0; //压栈的 r0
unsigned int stacked_r1; //压栈的 r1
unsigned int stacked_r2; //压栈的 r2
unsigned int stacked_r3; //压栈的 r3
unsigned int stacked_r12; //压栈的 r12
unsigned int stacked_lr; //压栈的 lr
unsigned int stacked_pc; //压栈的 pc
unsigned int stacked_psr; //压栈的 psr
stacked_r0 = ((unsigned int) hardfault_args);
stacked_r1 = ((unsigned int) hardfault_args);
stacked_r2 = ((unsigned int) hardfault_args);
stacked_r3 = ((unsigned int) hardfault_args);
stacked_r12 = ((unsigned int)hardfault_args);
stacked_lr = ((unsigned int) hardfault_args);
stacked_pc = ((unsigned int) hardfault_args);
stacked_psr = ((unsigned int) hardfault_args);
while(1)
{
printf("\r\n");
printf("R0 = %x\r\n", stacked_r0);
printf("R1 = %x\r\n", stacked_r1);
printf("R2 = %x\r\n", stacked_r2);
printf("R3 = %x\r\n", stacked_r3);
printf("R12 = %x\r\n", stacked_r12);
printf("Stacked LR = %x\r\n", stacked_lr);
printf("Stacked PC = %x\r\n", stacked_pc);
printf("Stacked PSR = %x\r\n", stacked_psr);
printf("SCB_SHCSR=%x\r\n",SCB->SHCSR);
printf("Current LR = %x\r\n", lr_value);
}
}
处理器进入到HardFault,将R0~R3、R12、LR、PC信息通过串口打印,根据寄存器信息排查问题代码。
当处理器处理异常时,除非异常是一个末尾连锁异常或迟来的异常,否则,处理器把信息都压入到当前堆栈中入栈(stacking),8个数据字的结构被称为栈帧(stack frame),栈按照双字地址对齐方式。
入栈后,堆栈指针立刻指向栈帧的最低地址单元。栈包含返回地址,这是被中止的程序中下条指令的地址。这个值在异常返回时返还给 PC,使被中止的程序恢复执行。
如下图连接仿真器查看汇编的地址可以找到是程序问题,根据PC指针地址,在程序生成的.map中查找出问题函数。
非常不错的故障排除法 在硬件故障发生时,程序会判断当前使用的是 主栈指针还是 进程栈指针 查找HardFault方法和步骤 HardFault 常见的原因之一是非法的内存访问,如访问未分配的内存、越界访问数组等。检查代码中所有的内存访问操作,确保没有错误。 通过调试串口输出调试信息,将程序的运行状态和错误信息实时发送到计算机。这样可以在不影响程序运行的情况下,获取更多的调试信息。 报hardfualt错误,一般都是变量操作不当导致内存溢出。 可以在容易出现hardfualt的地方添加调试打印或日志记录。 尝试简化代码,逐步排除可能导致HardFault的部分,以缩小问题范围。
页:
[1]