RTOS(ucosII)在KEIL环境下的内存分配管理知识——编译器优化等级的影响
第一次写技术文章,不知道如何表述才能更好的和大家交流,试着慢慢写,希望可以坚持下去。写这个的原因有很多,主要还是自己困惑,其次想和大家交流下心得。如有不对的地方,欢迎指正。
PS:简单自我介绍,感兴趣可以上知乎 https://zhuanlan.zhihu.com/p/150905017
对于嵌入式设备来说,举例STM32这类,RAM区一般不超过512kbyte,Flash最多2Mb,咱们这篇文章,主要是关注内存(即RAM区)。所有代码,都里不开内存,但由于嵌入式芯片处于成本考虑,内存都不会太大,所以,在使用过程中,对内存资源的把控尤为关键,如果设计不好,导致内存爆满那软件也没法继续设计下去,如果操作不当,导致内存溢出,那么情节不严重的造成数据紊乱,情节严重的是系统奔溃。
那么,我们怎么样来管理内存呢?如何确定我们的内存设计是最优的呢?首先,我们要知其所以然,那就是内存到底是个什么东西?我敲了多年代码,没有太去深究这个问题,这次有机会,我觉得是时候去了解真相了[—_—]
基本概念:
本篇文章是以STM32嵌入UCOSII系统为例作为讲解,其他也是类似。
每个芯片的空间都不一样,但起始地址都是一致的,RAM从0x02000000开始,内部FLASH从0x08000000开始,具体分区、地址映射之类的信息网上查一下,很多讲解的。
我们在写代码的过程中,会进行很多数据定义,频率最高的如下:
全局变量:const/static/一般定义;
局部变量:const/static/一般定义;
在整个RAM中,又被分为以下区域:
.data区 |
任务栈区 |
.bss区 |
系统HEAP |
系统STACK |
被初始化的数据存放区: 全局变量初始化后存放区域; 局部static变量初始化后存放区域; |
任务自身数据的存放; 任务运行中局部变量的空间 |
和data性质有点相反: 全局变量没有初始化存放区域; 局部static变量没有初始化存放区域; |
需要使用malloc来进行分配。如果整个程序中未使用malloc,此空间可以设置为0. |
任务切换时系统数据;
|
编译器优化规则的影响:
△单独每个.c里面的变量在KEIL编译时,RO RW ZI是怎么新增的?
1.首先,本函数.c文件的全局变量如果一个都没有被引用,则本文件中所有全局变量会被优化removing掉。此时查看Map文件,该文件的RO RW ZI数值均为0.
2.在本文件中,被调用的函数里应用其中一个全局变量,此时编译后RO RW ZI会根据整个文件定义的全局变量数量进行相应变化。但是,这里有个细节,如果定义在文件中的全局变量字节数大于8个字节,同时没被引用,此时,该变量会整体被removing掉。有兴趣可以调试观察一下,会出现定义数据数量和map对应不上的结果。具体原因,是keil优化规则的问题。
测试源码如下:
uint8_t g_waterSensorInfo[9];
TDateTime doorActionTime; //7字节
TDateTime waterActionTime; //7字节
char g_BleMac[2];
uint8_t test[1024] = {1};
void AppTaskBle (void *p_arg)
{
while (DEF_TRUE)
{
memset(test,1,1024);
OS_TimeDlyMs(20);
}
}
3.在此稍微深究一下,找到KEIL优先级调整界面,我原来的等级是LEVEL0,最低优化等级;
此时编译后的map信息:
4.将优先级直接调整到最高级Level3后,map信息如下:
5.整个测试工程的优化效果,对比如下:
Program Size: Code=27566 RO-data=1198 RW-data=1172 ZI-data=38988 优化等级level0
Program Size: Code=19348 RO-data=1080 RW-data=1148 ZI-data=38820 优化等级level3
可以很明显的对比出来,在Level3的优化强度下,code量大幅缩小,RO RW ZI也有小幅的缩减。所以,我们在调整或者切换开发工具时,注意优化等级是否有变化,优化程度有可能会导致出现奇怪问题。解决办法暂时没碰到也没深究,可以先把所有告警解决掉试试。