解决:程序触发看门狗或者跑飞的情况汇总分析

该类情况在编程的时候总是不断遇见,我将其分为三类:

一、无操作系统程序死机。

在一个极简单的程序中遇见一个情况,运行着运行着main()中的while(1)就不循环了,但是串口中断还能进。由于我并没有使用看门狗,所以并没有触发看门狗重启。

这个问题莫名其妙的地方在于不知道程序现在在干啥,可以通过debug中的call stack可以看到当前运行在哪个函数中,也可以看到这个函数的调用路径。这个功能帮助我们看到程序执行在哪个地方。有的时候进入hard fault的时候也可以通过call stack看到是由哪个函数的调用引发的错误中断。

根据这个方法,我看到程序停留在HAL_Delay中的while中。后来发现是由于我的串口处理函数中用到memcpy的时候长度写错了,写的非常大,导致内存溢出进而引发的。

这告诉我:当程序跑飞时,检查一下memcpy或者memset之类的有关内存操作。

修改后,程序可以正常跑了,千里之堤毁于蚁穴。

 

还有一种情况是两个485设备相连,有同时发送数据的时候,也会导致死机。

二、带操作系统的程序重启

遇见一个问题:由于我需要在界面操作一个摁键后去保存数据进nandflash中,但我知道不能在回调函数中执行时间很长的函数,所以我将保存nandflash放入任务中。但每次执行的时候总会触发看门狗。

我刚开始怀疑我写的nandflash的驱动有问题,因为我将其在while前执行也会死机。但是根据debug跟踪,却发现保存nandflash的动作本身并没有错误,但一出这个函数就会死机。

然后我知道OSSchedLock(&err)和OSSchedUnlock(&err)是需要成对出现的,而nandflash的写函数中是有关闭操作系统调用的。有没有可能是这块我没有正确使用。我将他们去掉,却发现死机提前了,并且在执行nandflash的写函数中任意操作都会死机,毫无规律可言。那还是不要去掉他们了。

也有可能是因为在锁住操作系统后又调用了操作系统有关的函数,比如等待信号量。但我检查了,并没有。

因为每次都是执行完nandflash存数据后到任务中时死机,所以我怀疑或许是不是和任务的内存有关,我看了一眼这个任务的堆栈空间,只有256u,确实有些小,我调至1024u,这个现象就没再出现了。那么也就是说,在任务中调用的函数,这个函数就会用该任务的堆栈。

出现程序死机时,可以尝试扩大任务的堆栈大小,若无死机情况了再从大往小了减。

解决:程序触发看门狗或者跑飞的情况汇总分析_第1张图片

任务堆栈在uc/os-III中是这样图示的,从高地址入栈。

三、emwin的不当操作导致的死机

emwin由于是不开源的,所以有时候不当的操作,比如没有创建窗口时就删除该窗口,就会导致死机。

所以在运用emwin的时候一定要严格遵循他要求的顺序,如果可以的话多加一下判断再删除界面。


下面是其他网站上我看到的比较好的文章,为了避免链接失效,我粘贴过来,作者是蓝天。

关于程序死机复位的一点心得

关于程序死机的一点心得

   borland c++,在uCOS-II多任务操作系统下,曾经遇到的死机复位问题,大家在编程时,如果遇到类似的问题,希望能有所帮助:

   1、频繁操作文件,容易出现死机,操作文件时,最好关闭任务,操作完成后,再打开任务;   uC/OS-II的OSSchedLock()和OSSchedUnlock()函数应成对出现,允许应用程序锁定当前任务不被其它任务抢占。使用时应当注意的是:当你调用了OSSchedLock()之后,而在调用OSSchedUnlock()之前,千万不要再调用诸如OSFlagPend()、OSMboxPend()、OSMutexPend()、OSQPend()、OSSemPend()之类的事件等待函数!而且应当确保OSSchedLock()和OSSchedUnlock()函数成对出现,特别是在有些分支条件语句中,要考虑各种分支情况,不要有遗漏!

      2、任务优先级。每个任务都必须符合事件驱动的编程模型,即uC/OS-II的应用程序都必须是“事件驱动的编程模型”。一个任务首先等待一个事件的发生,事件可以是系统中断发出的,也可以是其它任务发出的,又可以是任务自身等待的时间片。当一个事件发生了,任务再作相应处理,处理结束后又开始等待下一个事件的发生。如此周而复始的任务处理模型就是“事件驱动的编程模型”。事件驱动模型也涵盖了中断驱动模型,uC/OS-II事件归根结底来自三个方面:
     (1)中断服务函数发送的事件
     (2)系统延时时间到所引起的
    (3)其它任务发送的事件。
   其中“中断服务函数发送的事件”就是指每当有硬件中断发生,那么中断服务程序就会以事件的形式告诉任务,而等待该事件的最高优先级任务就会马上得以运行;“系统延时时间到所引起的”事件其实也是硬件中断导致的,那就是系统定时器中断。而“其它任务发送的事件”则是由任务代码自身决定的,这是完全的“软事件”。不管“软事件”还是“硬事件”,反正引起uC/OS-II任务切换的原因就是“事件”,所以用户编写应用代码的时候一定要体现出“事件驱动的编程模型”。任务的优先级也一定要分配得当;

  3、 零作为除数溢出后,死机,所以,要检查程序中是否有除零的地方;

  4、查看堆栈是否满;

   5、一些C语言函数,用到uCOS-II操作系统中,有时也可能出现问题,例如:gotoxy();printf();此项待进一步确定。

   在网上也查看到一些司机原因:

   OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL()也可以用来保护应用程序中的临界代码;然而要特别小心,如果在调用一些如OSTimeDel()之类的功能函数之前关中断,应用程序将会死机;原因是任务被挂起一段时间,直到挂起时间到,但由于中断关掉了,时钟节拍中断一直得不到服务,显然所有的挂起类调用都有这样的问题,所以要特别小心。

    需要一并提醒的是:当调用开关中断函数OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL()时也要确保成对出现,否则系统将可能崩溃!不过,在OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL()函数之间调用OSFlagPend()、OSMboxPend()、OSMutexPend()、OSQPend()、OSSemPend()之类的事件等待函数是允许的。

   希望大家把自己遇到的死机问题及解决方法写出来,供大家一起参考,我在此先谢谢了!


我觉得如果出现偶然出现程序死机的情况,首先不要慌,一定是哪里写的不严谨,或者粗心导致的。仔细查看最近改过哪些代码,有没有有关内存的操作比如memcpy或memset,有没有往任务中添加什么操作。

我想最差的结果就是重写嘛,边写边调试,不要闷头写代码而不调试。

 


 

 

你可能感兴趣的:(调试经验,嵌入式编程)