RTThread中fault定位方法
在《RTThread中HardFault_Handler分析》一文中已经分析了RTThread中对于fault中断的处理方法。接下来讲解如何根据错误输出信息对程序出现fault的位置进行定位。
rtthread_simulator_v0.1.0 工程中的main.c中的我们添加以下3行代码
void(*fp)(void) ; //1
int main(void)
{
fp = 0; //2
fp(); //3
return 0;
}
编译后按ctrl+5进入软件仿真状态,全速运行后,UART#1窗口输出如下信息
![在这里插入图片描述](https://img-blog.csdnimg.cn/20190420161206308.PNG?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3N1bnkxMjM0,size_16,color_FFFFFF,t_70)
由此可见运行时候发生了fault,通过《RTThread中HardFault_Handler分析》的内容我们可以知道,输出窗口中打印出来了各个
上述寄存器信息中,lr寄存器中的值为0x08000151 ,此值为进入fault异常中断之前的lr的值。
我们知道lr为连接寄存器里面保存的是调用子程序之前的PC的值。 因为 CM3 内部 使用了指令流水线,读 PC 时返回的值是当前指令的地址+4 ,所以进入异常之前自动加载到lr的值也为调用子程序前的指令地址+4。由于PC的最低位保存ARM/Thumb 运行状态,Cortex-M3只能运行在Thumb 状态,即LSB = 1。所以我们想要找到出错误程序的指令位置, 只需要对打印出来的lr的值减去5即可。
0x08000151 减去5后为0x0800014C 说明我们程序出错位置在PC = 0x0800014C 附近。
在Disassembly窗口下,我们找到0x0800014C 指令位置
![在这里插入图片描述](https://img-blog.csdnimg.cn/2019042016123281.PNG?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3N1bnkxMjM0,size_16,color_FFFFFF,t_70)
可以看到 0x0800014C 指令位置正好在fp()代码段内。
我们进一步分析产生错误的原因,根据打
用法 fault 状态寄存器(UFSR),地址:0xE000_ED2A
main()函数中我们将函数指针fp的值设为了0,然后去调用fp(),相当于让程序跳转到0地址处去运行。实际上真正出错的地方是0x0800014E处,这里执行了一条BLX 跳转指令,执行完将r0的值0更新到了PC,即PC=0。PC的最低位LSB被更新成了0,试图切换到ARM状态,状态寄存器(UFSR) 中的 INVSTATE 位被置位 ,因此产生了fault。