平湖市规划建设局网站,wordpress 页面加载,app程序开发用什么编程,连山建设局网站1.背景
1. 项目中#xff0c;调试过程或者测试中都会出现程序跑飞问题#xff0c;这个时候问题特别难查找。
2. 触发硬件错误往往是因为内存错误。这种问题特别难查找#xff0c;尤其是产品到了测试阶段#xff0c;而这个异常复现又比较难的情况下#xff0c;简直头疼。…1.背景
1. 项目中调试过程或者测试中都会出现程序跑飞问题这个时候问题特别难查找。
2. 触发硬件错误往往是因为内存错误。这种问题特别难查找尤其是产品到了测试阶段而这个异常复现又比较难的情况下简直头疼。
3. 我目前的工作完全是没有调试器的代码都是写好了通过bootloader烧写进去的。也就意味着不能在void HardFault_Handler(void)中打断点然后通过当前lr寄存器中的值查看异常地址。
参考
STM32进入HardFault_Handler的调试方法-电子工程世界 (eeworld.com.cn)
Keil环境下STM32定位hardfault位置方法和遇到的情况 - 张士玉小黑屋 (zhangshiyu.com)
还参考了很多文章, 有些写的时候都关掉了, 这里就不列出来了. 2.裸机程序触发硬件错误 裸机触发硬件错误时 R14(LR)寄存器的值为0xFFFFFFF9此时看的是MSP指针保存的栈顶地址然后在Memory Window中输入这个值0x20000738第6个值就是错误退的地址也就是我这个空指针的地址查看.map文件显然我们的0x080001D1在0x080001cdmy_test在flash的首地址和0x080001d3my_test1在flash的首地址之间。因此我们就可以定位出错误就在my_test()这个函数中。 也可以查看汇报看到地址不过这里看起来有点让人蒙圈
3.RTOS程序触发硬件错误 RTOS触发硬件错误时 R14(LR)寄存器的值为0xFFFFFFFD, 此时看的是PSP中的栈顶地址。同上分析我们最终也能通过.map定位错误发生的位置。
补充知识为什么裸机的是0xFFFFFFF99:1001而多线程的是0xFFFFFFFD(1101)如下图bit2是区别的关键后面打印错误需要用到这一点。 4.在硬件错误中断打印这些值
我们最终的目的就是在触发硬件中断的时候要将这些值打印出来从而准确定位出是哪个函数造成的错误。
typedef struct
{u32 R0;u32 R1;u32 R2;u32 R3;u32 R12;u32 LR;u32 PC;u32 xPSR;
}STACK_DATA_TYPE;
void NotOSHardFault_Handler(u32 msp_addr)
{STACK_DATA_TYPE *p; //堆栈中存储的数据printf(\r\n-----------------ERROR -----------------\r\nHardFault_Handler\r\n);p (STACK_DATA_TYPE *)msp_addr;printf(R0:0x%08X\r\n, p-R0);printf(R1:0x%08X\r\n, p-R1);printf(R2:0x%08X\r\n, p-R2);printf(R3:0x%08X\r\n, p-R3);printf(R12:0x%08X\r\n, p-R12);printf(LR:0x%08X\r\n, p-LR);printf(PC:0x%08X\r\n, p-PC);printf(xPSR:0x%08X\r\n, p-xPSR);printf(系统即将复位 ...\r\n);
}void HardFault_Handler(void)
{/* Go to infinite loop when Hard Fault exception occurs */
int msp, psp;msp __get_MSP();NotOSHardFault_Handler(msp);psp __get_PSP();NotOSHardFault_Handler(psp);while (1){}
}
当前还有一个问题需要解决, 我无法获取lr寄存器中保存的值, 也就是说我无法准确的确定是进程堆栈出错还是主堆栈出错.(我测试了发现在rtos中, 如果让错误放在main函数中, 此时MSP堆栈指向的位置是出错位置, 如果让错误放在任务中, 此时PSP堆栈指向的位置是出错位置, 如果在裸机程序中, 通过MSP查找, 当前我用的是keil编译的,我不知道IAR里面是否有__get_MSP(), __get_PSP())