背景
初学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()函数也可以正常运行