【单片机开发】emwin莫名奇妙死机的原因总结以及解决方案
发布日期:2021-05-08 05:11:14 浏览次数:29 分类:精选文章

本文共 1995 字,大约阅读时间需要 6 分钟。

相关链接

(一)背景介绍

首先先谈谈我自己遇到的问题。记得在前段时间遇到了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的问题还有很多,关键还难以查。有问题以后再说吧。

上一篇:【单片机开发】stm32f429在线IAP 实现SD卡烧写程序
下一篇:【单片机开发】基于stm32的掌上游戏机设计(终章)

发表评论

最新留言

感谢大佬
[***.8.128.20]2025年04月14日 07时32分57秒