嵌入式变量存储空间详解(内附代码及注释)
摘要:本文以STM32G070CBT6单片机为例,详细解析了嵌入式系统中内存和变量的存储管理。128KB的内部FLASH用于存储程序代码、中断向量表和常量,支持通过特定操作进行数据写入。36KB的SRAM则分为栈(存储局部变量)、堆(动态分配内存)和静态存储区(全局变量)三个区域,并配以代码示例说明不同变量的存储位置。文章还强调了查看.map文件进行内存分配验证的重要性,为嵌入式开发者提供了实用的
目录
四、如果这篇文章能帮助到你,请点个赞鼓励一下吧ξ( ✿>◡❛)~
前言:
本例程以STM32G070CBT6单片机为例,讲解内存和嵌入式系统中变量的存储空间,这块片子具有128KB的内部FLASH,36KB的内部SRAM存储空间。

一、变量存储空间详解
这段带有注释的代码示例,说明了定义在不同区域、使用不用修饰符声明的变量的存储区域:
// 常量 var_Flash 存储在 FLASH 中的只读数据段(.rodata)
const int var_Flash = 1;
// 字符串Hello是常量,存储在内部FLASH中的只读数据段(.rodata),指针p_const是全局变量,存储在SRAM的静态存储区(.data 或 .bss)
const char* p_const = "Hello";
//var_Global在函数外定义,是全局变量,存储在SRAM的静态存储区的 .data 段(已初始化)
int var_Global = 5;
void TestCode() //示例函数
{
//var_Static是static声明的静态变量,在程序运行期间只初始化一次,存储在SRAM的静态存储区
Static int var_Static = 5;
//初始化的static变量,存储在SRAM中静态存储区的.data段,程序启动时,初始值50从内部FLASH中加载
static int value_one = 50;
//未初始化的static变量,存储在SRAM中静态存储区的.bss段,程序启动时,该区域变量自动赋零值
static int value_two;
//new申请的地址位于SRAM的堆中,大小为10*sizeof(int),但p是一个指针类型的局部变量,存储在SRAM的栈中,它指向new分配的地址
int* p = new int[10];
//new和delete要配对使用,在嵌入式系统中慎用new和malloc来进行内存分配,会导致内存碎片化
delete[] p;
if( var_Global == 5 )
{
//局部变量 var_Local 存储在SRAM的栈空间中,生命周期和if语句一致
int var_Local = 5;
}
}
二、内部FLASH区域
Keil示例图中的IROM指的就是单片机内部的FLASH区域,这部分区域严格读取,是非易失性存储器(NVM),用来存储中断向量表、程序代码、Const声明的常量等。FLASH的起始地址为0x08000000,总共0x00020000Byte大小的空间,转换为10进制就是131072Bytes,对应128KB (128 * 1024Byte) ,资源相当有限了。
如果想要长久保存一些个人定义的程序运行标志位,可以在程序运行中对FLASH进行写操作,写操作需要对FLASH进行——FLASH解锁,擦除,写入,上锁操作,将标志位写入固定的FLASH扇区内存地址中。
FLASH存储区域示例如下图所示:

图中的BootLoader区域是可选配置,用来为单片机提供在线升级,如果代码没有设置BootLoader功能的话(BootLoader小型项目一般用不到),这部分内存区域可以直接存放主程序。
三、内部SRAM区域
Keil图片中的IRAM指的就是单片机的SRAM区域,等价于我们手机电脑中的“运行内存”,这部分区域依赖系统的内存分配策略进行空间分配,存储的是程序运行过程中使用的变量,包括三个存储区域:栈,堆和静态存储区。这三个存储区域是相互独立的,用来存储不同声明类型的变量。
SRAM存储区域示例如下图所示:

栈:存储局部变量和函数形参,地址增加方向是反的,由高向低,先进先出。起始地址位于SRAM地址空间尾部,空间上和堆相邻。
例如:
int main()
{
char temp1 = 0; //temp1变量存储在SRAM的栈中,地址为0x20008FFF
char temp2 = 0; //temp2变量存储在SRAM的栈中,地址为0x20008FFE
}
堆:存储new和malloc申请的变量,地址由低向高增加,位于SRAM内存区域的中间位置,以堆地址为基准,地址减小的方向是静态存储区的位置,地址增加的方向是栈区域的位置。
例如:
int main()
{
char* p1 = new char[10]; //new申请的地址位于SRAM的堆中,数组首地址为0x20003000
char* p2 = new char[10]; //new申请的地址位于SRAM的堆中,数组首地址为0x2000300A
/*new和delete要配对使用,在嵌入式系统中慎用new和malloc来进行内存分配
,会导致内存碎片化*/
delete[] p1;
delete[] p2;
}
静态存储区:存储全局变量,Static声明的静态变量,地址位于SRAM地址起始位置,由0x20000000起,和堆相邻,详见第一部分的代码,就不单独举例了。
开发者可以通过编译后生成的.map地址映射文件来查看项目中的实际内存分配,这是嵌入式开发的黄金标准。
四、如果这篇文章能帮助到你,请点个赞鼓励一下吧ξ( ✿>◡❛)~
openvela 操作系统专为 AIoT 领域量身定制,以轻量化、标准兼容、安全性和高度可扩展性为核心特点。openvela 以其卓越的技术优势,已成为众多物联网设备和 AI 硬件的技术首选,涵盖了智能手表、运动手环、智能音箱、耳机、智能家居设备以及机器人等多个领域。
更多推荐


所有评论(0)