最近在gd32上使用freertos进行项目开发时碰到内存不够的情况,发现了我缺乏对于操作系统的内存及其空间的分配的知识,经常会被flash、ROM、RAM、bss段、data段、text段、堆、栈、Code、Ro-data、 ZI-data、RW-data这些搞混,故写下该文章进行学习总结。
一、 C/C++语言内存分区
C/C++语言内存分区示意图如下:
1. 栈区(stack)
- 存放临时创建的局部变量和const定义的局部变量。
- 存放函数调用和返回时,其入口参数和返回值。
2.堆区(heap)
- 由程序员使用malloc和free分配内存和释放。
3.1全局/静态区-bss段
- 未初始化的全局变量和未初始化的静态变量存放在.bss段。
- 初始化为0的全局变量和初始化为0的静态变量存放在.bss段。
3.2全局/静态区-data段
- 已初始化的全局变量存放在.data段。
- 已初始化的静态变量存放在.data段。
4.常量区(constdata段)
- 字符串、数字等常量存放在常量区。
- const修饰的全局变量存放在常量区。
5.代码区(text段)
- 程序执行代码存放在代码区,其值不能修改。
- 字符串常量和define定义的常量也有可能存放在代码区。
二、Keil MDK中GD32内存分区
上面说到C/C++中分为栈(stack)、堆(heap)、bss、data、text段
而mdk中可以分为Code、RO-data、RW-data、ZI-data四个区域
1.RAM:RAM就是运行内存,掉电数据就丢失。具体包含的内存段如下图:
2.ROM:在GD32中Flash相当于ROM,掉电数据不会丢失。具体包含的内存段如下图:
ROM内存中除了存放只读数据和程序代码外,还会包含RW读写数据,因为RAM会掉电会丢失,在启动时是没有数据的,系统启动需要从ROM中将RW数据加载到RAM区。
三、map文件分析
此处以GD32芯片为例,Flash大小为128KB,RAM大小为16KB,配置如下
在startup_gd32f3x0.s文件中给系统分配的栈空间、堆空间均为0x400
给FreeRTOS分配堆空间为如下
编译后信息如下:
查看map文件
上面可以看到分别对应我们分配的栈区、堆区、FreeRTOS堆区的大小,都是位于RAM内存中
这里其实就是告诉我们GD32中ROM和RAM的使用情况
Flash = Code + RO-data + RW Data;
RAM = RW-data+ZI-data;
四、总结
结合上面所说,后续在项目开发中,当出现内存不够的情况,我们可以首先去分析是ROM还是RAM内存不够,再去分析map文件,例如RAM空间不足,我们就可以通过map文件找到哪些.c文件中占用的内存比较多,针对性的去查看有没有可以优化的变量等,从而达到减少对RAM内存的占用。后续后继续总结一篇关于FreeRTOS堆和任务空间分配相关的笔记。
参考文章:
C语言:内存分配---栈区、堆区、全局区、常量区和代码区_根号五的博客-CSDN博客_c 栈区
stm32堆栈,rom,flash详细理解 - 且将新火试新茶 - 博客园
stm32中堆、栈、flash、ROM、RAM、bss段、data段、text段、Code、Ro-data、 ZI-data、RW-data简介_StarLish0715的博客-CSDN博客