一、单片机内存两大物理大类
1. Flash(程序存储器 / ROM 类)
- 掉电不丢数据
- 存放:程序代码 + 常量
- 速度:比 RAM 慢,擦写次数有限(几万~几十万次)
2. RAM(数据存储器,一般是 SRAM)
- 掉电数据全丢
- 存放:运行时变量、堆栈、临时数据
- 速度:快,可频繁读写
一句话:代码常量在 Flash,变量运行在 RAM
二、C 语言编译后,内存的 "逻辑分区"
不管是 STM32、GD32、ESP32,编译后都分成这几个段(Section):
1. .text 段(代码区)
- 位置:Flash
- 内容:所有函数的机器指令(main、中断服务函数、子函数...)
- 属性:只读,不可改
2. .rodata 段(只读常量区)
- 位置:Flash
- 内容:
const全局常量- 字符串常量(
"hello")
- 属性:只读,运行时不能写
3. .data 段(已初始化全局变量区)
-
位置:运行时在 RAM
-
内容:全局 / 静态变量,且初始值非 0
int g_val=100; // 进入 .data
-
启动时:Flash 里的初始值会复制到 RAM
4. .bss 段(未初始化 / 零初始化全局变量区)
-
位置:RAM
-
内容:
int g_buf[1024]; // 默认0,进 .bss
static int s_cnt; // 也是 .bss -
特点:不占 Flash ,启动时由代码自动清零
5. 栈(Stack)
- 位置:RAM
- 内容:
- 局部变量
- 函数参数
- 函数返回地址、中断现场
- 管理:自动分配 / 自动释放,大小固定(如 8KB),溢出会死机
6. 堆(Heap)
- 位置:RAM
- 内容:
malloc/free动态申请的内存 - 管理:手动申请、手动释放;不释放会内存泄漏
三、一张表
| 段名 | 物理位置 | 存放内容 | 读写 | 掉电 |
|---|---|---|---|---|
| .text | Flash | 程序代码 | 只读 | 不丢 |
| .rodata | Flash | 常量、字符串 | 只读 | 不丢 |
| .data | RAM(来自 Flash 拷贝) | 非 0 初始化全局变量 | 可读可写 | 丢失 |
| .bss | RAM | 未初始化 / 零全局变量 | 可读可写 | 丢失 |
| Stack | RAM | 局部变量、函数调用 | 读写 | 丢失 |
| Heap | RAM | 动态内存(malloc) | 读写 | 丢失 |
四、32 位单片机内存布局
Flash 空间(从低到高)
├── .text 代码
└── .rodata 常量
RAM 空间(从低到高)
├── .data 已初始化全局变量
├── .bss 零初始化全局变量
├── Heap 堆(向上生长)
└── Stack 栈(向下生长,顶在高地址