在MCU程序开发调试过程中,总会发现很多的程序bug。有一些bug是逻辑问题,规格书理解问题,笔误问题等,以上列出的这些问题,通过断点,单步等调试手段,很容易发现并解决问题。但是有一些程序的bug就比较难通过常规手段定位出问题的地点和原因,例如:芯片不定时跑飞和复位。
以下总结了芯片不定时跑飞和复位的5大原因
1、看门狗复位
原因:程序中使用了看门狗,但是没有及时清看门狗,从而导致看门狗复位,使程序直接跳到复位位置。
解决方法:通过读或写RSTSTAT寄存器,在程序中清看门狗。
示例:
A.程序中写RSTSTAT寄存器清看门狗。
2、中断服务程序缺失
原因:程序中打开了某个中断,但是没有相应的中断服务程序,从而导致在中断发生后,找不到中断服务程序入口,从而导致程序跑飞。
解决方法:检查程序中是否存在打开了某个中断,但是没有相对应的中断服务程序。
示例:
A.使能外部中断0,并且屏蔽外部中断0服务程序。
B.下降沿触发外部中断0后,程序跑到地址0x0003处(INT0向量地址为0x0003),由于没有中断服务程序,该地址的指令被编译器填充为初始化程序,因此导致程序跑飞。
3、 中断服务程序没有对bank压栈和出栈
原因:主程序在操作bank1寄存器时,进入中断没有对bank1压栈,此时切换到bank0对寄存器操作,退出中断后由于没有保存bank1的状态,导致主程序在bank0中对bank1的寄存器操作,误改bank0寄存器的值,程序可能会运行异常。
解决方法:进入中断服务程序后,对bank进行压栈,退出中断之前对bank进行出栈,这样无论主程序在操作bank0还是bank1,中断里面都会保存进中断之前bank状态,退出中断后会还原bank状态,这样就不会因为切换bank导致寄存器的值被误改。
示例:
A.在主循环操作bank1寄存器,定时器Timer3中断里面不进行压栈和出栈操作,直接操作bank0寄存器。
B.退出中断后此时程序状态为bank0,下一步返回主程序,本来应该改变的是P5_0的值,由于没有切换到bank1,所以在bank0中将相同地址的寄存器P0_0的值误改,同时导致P5_0的值修改无效。
4、数组越界
原因:程序中定义的数组元素的个数小于程序中实际使用的数组元素的个数,数组使用循环函数时,如果循环变量没控制好则会出现数组越界,意外修改其他变量值可能会导致程序异常。
解决方法:检查函数中调用的数组是否存在越界的情况。
示例:
A.定义SendBuffer和RecBuffer两个数组变量,数组长度为5,初值均为0。
B.主程序中对数组SendBuffer[0]~ SendBuffer[4]赋值,此时SendBuffer[5]和SendBuffer[6]也被意外赋值,从watch窗口可以看出,这两个值改变了原来RecBuffer[0]和RecBuffer[1]的值,可能会造成程序异常。
5、堆栈溢出
原因:函数嵌套太深或者局部变量太多导致超出堆栈空间,正常数据被改写。
解决方法:尽量减少函数调用层级,局部变量不要使用太多,尤其是局部大数组,从而减少压栈的时候所需的空间。
示例:
A.定义4个全局变量和1个局部变量数组,总共占用RAM空间为249个字节
B.计算程序中所需的堆栈大小,主程序中调用Delay()函数,占用2个字节,中断服务函数占用16个字节,中断嵌套调用leddisplay()函数,占用2个字节,总共需要20个字节堆栈空间,由A可知,系统只剩下6个字节堆栈空间,所以程序运行后,堆栈一定会溢出。
C.运行程序,正常现象为P40端口一直翻转,TestData变量值始终为0,触发外部中断0,进入中断服务程序后,可以看到SP堆栈指针已经溢出,同时将R7寄存器的值压栈到0x08的地址上,通过.m51文件可以查到0x08正好是TestData变量地址,所以TestData的值被误改为0x01,导致主程序中条件判断出错,程序异常。
在调试MCU程序过程中,由于程序书写的不规范产生程序漏洞,跑飞现象比较常见,如果我们提前了解程序可能跑飞的原因,对于快速定位问题有很大帮助,从而提高分析和解决问题的效率,减少产品的开发周期,加速产品的上市时间。
来源:中颖电子
免责声明:本文为转载文章,转载此文目的在于传递更多信息,版权归原作者所有。本文所用视频、图片、文字如涉及作品版权问题,请联系小编进行处理
审核编辑 黄宇
-
mcu
+关注
关注
146文章
16977浏览量
350215
发布评论请先 登录
相关推荐
评论