【单片机开发】emwin莫名奇妙死机的原因总结以及解决方案

本文围绕emwin死机问题展开。作者在项目中遇到emwin翻页后死机情况,经排查发现死机原因包括堆栈不够、内存申请不足、硬件问题、界面初始化错误以及从回调函数直接退出等,针对从回调函数直接退出导致的死机,可通过设置标志位解决。

相关链接
项目总结

(一)背景介绍

首先先谈谈我自己遇到的问题。记得在前段时间遇到了emwin在翻页两三次后死机的处理上,我在翻阅了大量博客后找到了一个通过增大堆栈的解决方案,可以让界面不至于轻易死机。然而后面又遇到问题了,对于复杂的界面你来回89次依然会死机,简单的界面十几次也会死机,而且次数是固定的。然后我又把所有的网站的有关博客翻了个遍,起初以为是内存没有释放的原因导致GUI申请不到内存,然后我就开始做测试。

(二)问题解决

因为是使用了外部内存我直接将GUI的内存量开到了16M,可发现还是会固定死机。那么问题就来了,一个界面最多十几K怎么可能搞个几次就把内存搞爆了呢,这也太不科学了。于是我在程序做了相关测试,发现内存虽然有泄露但是相对于内存真的不多,按道理搞个几千次都没问题,怎么就死机了呢。这应该不是内存的原因。我猜测还是在堆栈上。
我查了一些关于堆栈的信息:

一个由C/C++编译的程序占用的内存分为以下几个部分
1、栈区(stack)— 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。
2、堆区(heap) — 一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 。注意它与数据结构中的堆是两回事,分配方式倒是类似于链表。
3、全局区(静态区)(static)— 全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域, 未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。程序结束后由系统释放。
4、文字常量区 — 常量字符串就是放在这里的,程序结束后由系统释放 。
5、程序代码区 — 存放函数体的二进制代码。

我猜测问题在于回调机制上。我在回调函数中直接退出界面会不会让堆栈无法 回收呢,然后我又去查了关于回调函数的信息:

A “callback” is any function that is called by another function which takes the first function as a parameter。

也就是说,函数 F1 调用函数 F2 的时候,函数 F1 通过参数给 函数 F2 传递了另外一个函数 F3 的指针,在函数 F2 执行的过程中,函数F2 调用了函数 F3,这个动作就叫做回调(Callback),而先被当做指针传入、后面又被回调的函数 F3 就是回调函数。到此应该明白回调函数的定义了吧?

乍一看,回调似乎只是函数间的调用,和普通函数调用没啥区别,但仔细一看,可以发现两者之间的一个关键的不同:在回调中,主程序把回调函数像参数一样传入库函数。这样一来,只要我们改变传进库函数的参数,就可以实现不同的功能,这样有没有觉得很灵活?并且丝毫不需要修改库函数的实现,这就是解耦。再仔细看看,主函数和回调函数是在同一层的,而库函数在另外一层,想一想,如果库函数对我们不可见,我们修改不了库函数的实现,也就是说不能通过修改库函数让库函数调用普通函数那样实现,那我们就只能通过传入不同的回调函数了,这也就是在日常工作中常见的情况。现在再把main()、Library()和Callback()函数套回前面 F1、F2和F3函数里面,是不是就更明白了?

我因为不了解回调函数直接将回调作为主函数的一部分来看,直接从回调函数中退出,我想问题可能就是出在你从回调函数直接退出的时候,回调函数内的东西被压栈了而且得不到释放,来回几次肯定是会溢出的。那我不在回调里面出来不就行了吗。于是我通过在回调函数中设置标志位然后在父窗口的循环中做检验退出不就行了嘛,试了一下果然有效,确实不再死机了。

可这也带来了一个麻烦,我之前写程序的时候根本没有父子窗口的概念。于是每个都有一个循环,而刚才那个过程发现只能在父窗口中执行。问题大发了,整个结构都得改。而且我发现搞来搞去我也只能搞个三层好在已经够用了。还有就是窗口复用的问题,一个儿子只能有一个爸爸,没办法,笨办法,要服用的窗口都给他搞两个,虽然代码量大了好在问题解决了。

搞了这么就,emwin死机大致有如下几点:

1. 堆栈不够,表现为界面来回两三次就死机,而且所有控件直接失效。

2. 内存申请不够,经常表现为开机就死机。

3. 硬件问题,在LCD与emwin内存设置上出现访问冲突。此外在自己搭建emwin开发平台时,一定注意SDRAM一点错误都不能有,所以每次请先检查SDRAM有无异常能否进行数据读取。

4. 界面初始化错误,在进入某一界面时必然死机,其他正常。这种错误通常在于自己的粗心出现控件重叠,控件句柄多用这种问题多检查就好了。

5. 还有就是我刚才说的从回调函数直接退出的问题,很容易导致死机。想要避免就直接通过标志位来解决。

emwin的问题还有很多,关键还难以查。有问题以后再说吧。

评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

与光同程

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值