有时,在写ARM时会遇到经常死机的情况,莫名其妙,在这里我总结了一些单片机/ARM死机或者跑飞的一些常见的查找方法和我对此的一些拙见希望对大家有帮助。
“死机”和“跑飞”
随着单片机在能源领域中的广泛应用,单片机的抗干扰问题越来越突出,煤矿井下环境一般比较恶劣,这便会为单片机控制系统带来各种干扰,以致系统不能正常工作。单片机应用系统的抗干扰性能主要取决于硬件的抗干扰设计,但软件抗干扰设计作为硬件抗干扰的完善和补充,作用也非常重要,因为大量的干扰通常并不能影响系统内硬件的运作,却常会使系统的软件无法正常运行,单片机应用的一个突出问题,便是单片机运行过程中经常出现的程序跑飞现象。
在单片机系统中,因为干扰的原因,在非预期的情况下,使得程序计数器PC 的值发生随机的变化,从而使得程序的流向指向不确定区域,这便是程序的跑飞。程序跑飞后或者会使指令的地址码和操作码发生改变,PC 把操作数当作指令来执行;或者PC值指向一条不合逻辑关系的指令甚或是非程序区,运行结果常常会使单片机进入死循环———便是大家常说的“死机”。为确保在无人当值的情况下,单片机“死机”后能自动恢复过来,通常采用软件陷阱,外部WDT 电路,以及软件控制的WATCHDOG 等方法,使系统恢复正常(后两种俗称“看门狗”)。
出错原因分析
那在程序运行出现这些错误时,我们要从哪些方面进行分析呢?
1、意外中断。
确认下是否打开了某个中断,但是没有响应和**中端标志,导致程序一直进入中断,造成死机假象。
2、 中断变量处理不妥。
若定义某些会在中断中修改的全局变量,这时要注意两个问题:首先为了防止编译器优化中断变量,要在这些变量定义时前加 volatile,其次在主循环中读取中断变量前应该首先关闭全局中断,防止读到一半被中断给修改了,读完之后再打开全局中断;否则出现造成数据乱套。
3、地址溢出,常见错误为指针操作错误。
我要着重说的是数组下标使用循环函数中循环变量,如果循环变量没控制好则会出现数组下标越界,意外修改系统的寄存器造成死机,这种情况下如果死机说明运气好,否则后面不知道发生什么头疼的事。
4、 无条件的死循环。
比如使用while(x);等待电平变化,正常情况下x都会变成0,就怕万一,因此最好加上时间限制;
5、看门狗没有关闭。
有的单片机即使没使用看门狗开机时也有可能意外自动开启了最小周期的看门狗,导致软件不断复位,造成死机,这个要看芯片手册,最好在程序复位后首先应该显式**看门狗再关闭看门狗;
6、 堆栈溢出。
最难查找的问题,对于容量小的单片机,尽量减少函数调用层级,减少局部变量,从而减少压栈的时候所需的空间。当你把以上几条都试过不能解决问 题,试一试把你的被调用少函数直接内置到调用的地方并且把占用RAM大的局部变量改成全局变量,试一试说不定就可以了。
处理方法
找出原因后,我们要怎么处理呢?
死机是指CPU的程序指针进入一个死循环,无法执行正常的程序流程。其外在表现常常是:正常功能丧失,按键无响应,显示凝固。单片机死机后,只有复全才能走出死循环,执行正常的程序流程。众所属知,克服死机的最有效手段是加看门狗(WatchDog)。
目前用得最广泛的看门狗实际上是一个特殊的定时器DogTimer。DogTimer按固定速率计时,计满预定时间就发出溢出脉冲使单片机复位。如果每次在DogTimer溢出前强行让DogTimer清零,就不会发出溢出脉冲。清零脉冲由CPU发出,在单片机程序中每隔一段语句放一个清DogTimer的语句——FeedDog语句,以保证程序正常运行时DogTimer不会溢出。一旦程序进入一个不含FeedDog语句的死循环,DogTimer将溢出,导致单片机复位,跳出这个死循环。本文称这种看门狗为典型看门狗,典型看门狗已被集成比,如MAX706、MAX791等[1];还有许多单片机本身集成了这种看门狗,如PIC16C57、MC68HC705等,
有一个错误观点:加了看门狗,单片机就不会死机。实际上,看门狗有时间会完全失效。当程序进入某个死循环,而这个死循环中又包含FeedDog语句,这时DogTimer始终不会溢出,单片机始终得不到复位信号,程序也就始终跳不出这个死循环。针对这一弊端,笔者设计了双对限看门狗和定时复位看门狗。
双时限看门狗有两个定时器;一个为短定时器,一个为长定时器。短定时器定时为T1,长定时器定时为T2,0 。这样,当程序进入某个死循环,如果这个死循环包含短定时器FeedDog语句而不包含长定时器FeedDog语句,那么长定时顺终将溢出,使单片机复位。巧妙安排长定时器FeedDog语句的位置,可保证出现死机的概率根低。
目前几乎所有的看门狗都是依赖于CPU(依赖于CPU FeedDog)。这可以比作:一个保险设备能否起到保险作用还依赖于被它保护的对象的行为。显然,依赖于CPU的看门狗是不能保证单片机在分之百不死机的。
在绝对不允许死机的装置中,笔者设计了一种完全不依赖于CPU的看门狗——定时复位看门狗。定时复位看门狗的主体也是一个定时器,到预定时间就发出溢出脉冲,此溢出脉冲使单片机强行复位。定时复位看门狗不需要CPU FeedDog。
简言之,定时复位看门狗就是定时地让单片机强行复位。这样,即使装置死机,其最大死机时间也不会大于定时器定时时间。显然,只要硬件完好,这种看门狗百分之百地保证了单片机不会长时间死机。在智能电表(包括IC卡电能表、复费率电能表、多功能电能表)中采用了定时复位看门狗,每1秒让CPU强行复位,迄今数十万电表运行了近五年,无一例死机报告。