最近因为缺芯问题,公司有一些产品在做国产替代芯片,我们选用的是华大的HCF32460系列的单片机,但是在使用过程中老是遇到一些奇怪的问题:运行一段时间死机、串口在接收长数据时死机或者异常,修改一段代码后死机,增加一行代码又恢复等等奇怪的问题。
在这个问题下,花了一天的时间解决了,具体问题定位在了堆栈溢出上,修改了堆栈大小后解决了这个问题,今天分享查找问题的经过和自己的一些总结,文笔忽略,不喜勿喷。。。
首先看一组代码截图
可以从截图中看到,我把硬件的初始化放在了主函数main()中(本人不建议这样使用,而是使用rt_thread提供的硬件初始化流程对硬件进行初始化,INIT_BOARD_EXPORT(xxx)),而
我的主函数线程堆栈大小配置为256Bytes,我的程序是在串口接收到数据后,申请一段内存,所以首先在串口接收长数据的地方打上断点,观察发现申请内存失败,跟到rt_malloc函数中,发现内存已经被破坏了
那么现在的问题就是什么导致内存被破坏了尼?
给rt_thread内存管理的地址开始的地方是0x1fff9660,观察内存变化情况,发现在释放main线程资源之前,已经出现了内存被修改的问题,那么到底是怎么回事?
在调试中观察,发现这个出错的地方正好是main线程的堆栈栈底地址,而cotex-mx内核的堆栈生长方向正好是向下生长的,至此问题基本找到了,就是堆栈溢出造成的问题,导致管理内存链被破坏,而溢出的原因也定位到了,华大的库函数里面有很多临时变量,临时变量太多,退出函数的时候,就会被压入堆栈,导致堆栈溢出。
修改了main线程大小后,一直没有出现过类似的问题了。
总结:
1)修功还要修内功,阅读rt_thread源码,并理解,如果有可能自己可以模仿写一段代码实现一些功能,对自己是很大的提高;(推荐一本好书《ARM Cortex-M3与Cortex-M4权威指南》,有时间可以自己实现一个简单的任务调度系统)
2)如果出现程序异常现象,第一个去查内存链是否被破坏?
3)如果被破坏可以断定大部分是由于堆栈分配不合理造成的;
4)尽量不要像我一样,在main线程或者其它线程中去初始化硬件相关的代码。
原作者:阿聪-聪
|