MCU存储空间布局详解
mcu的存储模块
mcu的存储空间就两个模块:1. rom; 2. ram;
'rom' 的作用主要就是存储code和一些不需更改的常量,**掉电不丢失**。而 'ram' 则是用于存储运行code的中间变量,**掉电丢失**。'rom' 'ram' 打引号是因为,目前因为更新换代,它们已经不是严格意义上的rom和ram了。而是用于表示其掉电不丢失,和掉电丢失的特性。
存储空间布局示例(以 ARM Cortex-M 为例)
+---------------------+
| ROM (Flash) |
+---------------------+
| 中断向量表 | <- 0x0000_0000
| 代码区(.text) |
| 常量区(.rodata) |
| 初始化数据(.data) | -> 运行时拷贝到 RAM
+---------------------+
| RAM |
+---------------------+
| 已初始化数据(.data)| <- 拷贝自 ROM
| BSS 段(.bss) | <- 未初始化变量(清零)
| 堆(Heap) | -> 向高地址增长
| ...(空闲内存) |
| 栈(Stack) | <- 向低地址增长
+---------------------+
| 特殊功能寄存器(SFR)| <- 固定地址(如 0x4000_0000)
+---------------------+
rom(只读存储器)
作用:存储 不可变数据,掉电后数据保留。
具体分区:
代码区(Text/Code Segment):
存放编译后的机器代码(函数、指令)。
通常位于 Flash 或 ROM 的起始地址。
常量区(Constant Data):
存储 const
修饰的全局或静态常量(如 const int a = 10;
)。
部分 MCU 会将常量直接嵌入代码区。
初始化数据区(Initialized Data):
存储全局变量和静态变量的初始值(如 int global_var = 100;
)。
注意:这些变量的初始值存储在 ROM 中,但运行时会被拷贝到 RAM 的对应区域。
ram(随机存取存储器)
作用:存储 可变数据,掉电后数据丢失。
根据变量的存储周期分为静态区和动态区,1.静态区的变量在程序初始化被创建,且不会被中途释放,随着程序存在。2.动态区的变量会随着程序的运行被创建或者释放。具体分区,:
静态区(Static Storage)
BSS段(.bss):
存储类型:全局变量和静态变量(包括 static
修饰的局部变量)。
生命周期:从程序启动到结束。
注意:初始化后的该变量区域,通常会被起始文件清零,以保证变量的默认值为0。
已初始化数据(.data):
存储类型:全局变量和静态变量(包括 static
修饰的局部变量)。
生命周期:从程序启动到结束。
注意:初始化后的变量初始值从 rom 拷贝到 ram的该区域。
堆(Heap):
存储类型:用于动态内存分配(如 malloc
、new
)。
手动管理:需开发者分配和释放,否则可能导致内存泄漏。
生长方向:通常向高地址扩展(与栈相反)。
栈(Stack):
存储类型:用于存储函数调用时的局部变量、参数、返回地址等。
自动管理:由编译器自动分配和释放。
生长方向:通常向低地址扩展(与堆相反)。
其他特殊区域:
特殊功能寄存器(SFR):用于控制外设(如 GPIO、定时器)的寄存器,位于固定 RAM 地址。
保留区域(Reserved):MCU 厂商预留的 RAM 空间(如 Bootloader 专用)。
注意
-
ROM 中的“初始化数据”:
-
初始化全局变量的初始值存储在 ROM 中,程序启动时会被拷贝到 RAM 的静态区。例如:
int initialized_var = 100; // 初始值 100 存储在 ROM,运行时拷贝到 RAM
-
堆和栈的动态性:
-
堆和栈的分配是动态的,但 栈空间通常由编译器预先分配固定大小(如通过链接脚本指定),而非运行时动态扩展。
-
堆的碎片化问题:频繁的
malloc/free
可能导致内存碎片,需谨慎使用。 -
未初始化的静态区(BSS 段):
-
未初始化的全局变量和静态变量(如
int uninit_var;
)默认值为 0,存储在 RAM 的 BSS 段(Block Started by Symbol)。 -
程序启动时,BSS 段会被清零(通常由启动代码完成)。
-
代码区的特殊内容:
-
中断向量表:通常位于 ROM 的起始位置,存储中断服务程序(ISR)的入口地址。
-
启动代码(Startup Code):负责初始化 RAM(拷贝初始化数据、清零 BSS 段)、设置堆栈指针等。
-
存储映射的硬件特性:
-
哈佛架构 vs 冯·诺依曼架构:
-
哈佛架构(如多数 MCU):代码(ROM)和数据(RAM)使用独立总线,可并行访问。
-
冯·诺依曼架构:代码和数据共享总线,效率较低。
作者:bastarddd