栈回溯调试HardFault错误

背景

初学rtos,移植rt-thread时没跑起来,一跑起来就出现错误

编译没问题,逻辑看着也没啥问题,想仿真排查问题,仿真也跑不起来。一时间不晓得程序在哪出错了,但是串口就是输出了错误。光有几个寄存器值也定位不到代码问题

问题定位

先把反汇编调了出来

fromelf  --text  -a -c --output=all.dis stm32c8t6\stm32c8t6.axf

根据串口输出的寄存器信息,在反汇编文件定位到PC寄存器的地址0x080016fc

分析反汇编,只能知道是在fputc函数中导致的错误,但是不知道这些函数的调用关系

发现调用关系的关系还是有点少,所以就采取栈回溯的方法把APP的栈寄存器给打印出来

上图的函数就是发生HardFault错误时调用的函数打印寄存器信息到串口调试器

现在需要把APP的栈给打印出来才能了解APP的调用过程,这个APP的栈就是上图这些发生错误的栈寄存器上面

上图就是APP线程的栈初始化代码,可以找到APP的sp栈顶部的地址

打印APP栈寄存器的代码

手工把栈的调用过程打印出来,继续分析反汇编。

按照我们打印的APP的栈寄存器的顺序,栈底的寄存器在右边,那么fputc函数用到的寄存器就在右边4个寄存器,小序号的寄存器在底部对应的r3寄存器就在最底部也就是上图的最右边,就可以得到fputc函数的寄存器保存的地址

得到了上图中lr寄存器保存的地址就是fputc函数执行完之后要返回的地址,查找定位到这个地址0800128f,有可能会查到不到,因为bit0表示的是使用的指令集,bit0 = 0表示使用的是ARM指令集,bit0 = 1表示的是使用的是Thumb指令集,所以查找不到的话就把0800128f改成0800128e

可以看到上图定位到0800128e地址,调用的是_printf_core函数,它使用了6个寄存器,对应的就是上图表示的寄存器位置,这个lr寄存器保存的地址就是_printf_core函数执行完之后要返回的地址,那么继续定位到08001dbb,不行就改成08001dba

这里定位到了main函数,说明是在main函数发生的错误,分析反汇编指令:上面的BL跳转指令到HAL_GPIO_TogglePin函数都没有出现问题,那么就是下一个函数跳转时出现的问题,查看main函数

对应的就是printf函数出现了问题

问题解决

把printf重新定位一下即可解决,实现一下fputc函数,程序正常执行。

或者换成RTThread的打印函数rt_kprintf()函数也可以正常运行

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值