该类情况在编程的时候总是不断遇见,我将其分为三类:
一、无操作系统程序死机。
在一个极简单的程序中遇见一个情况,运行着运行着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,这个现象就没再出现了。那么也就是说,在任务中调用的函数,这个函数就会用该任务的堆栈。
出现程序死机时,可以尝试扩大任务的堆栈大小,若无死机情况了再从大往小了减。
任务堆栈在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,有没有往任务中添加什么操作。
我想最差的结果就是重写嘛,边写边调试,不要闷头写代码而不调试。