STM32 的"内存划分"要分两层看:
- 芯片厂商规定的 地址映射表(4 GB 空间划成 8 大段,每段 512 MB);
- 用户程序里的 运行时分区 (代码段、数据段、堆、栈、FreeRTOS 任务栈等)。
把两张图叠在一起,就能快速定位"我的变量/代码/外设到底落在哪条总线、哪块物理区域"。
一、4 GB 地址映射(ARM Cortex-M 统一规范)
| 地址范围 | 官方名字 | 实际内容(以 F1/F4 为例) |
|---|---|---|
| 0x0000 0000 -- 0x1FFF FFFF | Code | 别名区:BOOT 后重映射到 Flash/SRAM/SystemMemory |
| 0x0800 0000 -- 0x080F FFFF | 内部 Flash | 真正放用户代码、常量、中断向量表 |
| 0x1000 0000 -- 0x1FFF FFFF | 片上额外 RAM | CCM(F4)、ITCM/DTCM(H7)、系统 BootROM、OTP |
| 0x2000 0000 -- 0x3FFF FFFF | SRAM | 主 SRAM1/2/3、备份 SRAM(电池保持) |
| 0x4000 0000 -- 0x5FFF FFFF | 外设寄存器 | APB1、APB2、AHB1、AHB2......所有外设寄存器 |
| 0x6000 0000 -- 0x9FFF FFFF | FSMC/FMC | 外部 NOR/NAND/PSRAM/SDRAM |
| 0xA000 0000 -- 0xDFFF FFFF | 保留 | 某些型号接 Quad-SPI、LCD 控制器 |
| 0xE000 0000 -- 0xFFFF FFFF | 系统级 | Cortex-M 内核外设 NVIC、SysTick、MPU、调试器 |
注:BOOT0/BOOT1 引脚决定 0x0000 0000 这条 512 MB 段到底"影子"到谁身上------Flash、系统 BootROM 还是 SRAM。
二、用户程序运行时"五段"落在上面哪一区
| 段名 | 存放内容 | 存储介质 | 地址举例 |
|---|---|---|---|
| .text | 代码、常量、向量表 | 内部 Flash | 0x0800 0000 起 |
| .rodata | 只读字符串、const | 内部 Flash | 紧接代码后 |
| .data | 已初始化全局变量 | 启动时从 Flash 拷贝到 SRAM | SRAM 低地址 |
| .bss | 未初始化全局/静态 | 直接清零在 SRAM | 接在 .data 后 |
| heap | malloc/new 动态区 | SRAM | _end ~ 栈底 |
| stack | 局部变量、中断现场 | SRAM | 栈顶向下长 |
| FreeRTOS 任务栈 | TCB+任务私有栈 | 在 heap_4 方案下属于 heap 区,即也在 SRAM |
栈向低地址"倒长",堆向高地址"长",二者中间剩余空间就是动态内存最大可用值。
三、快速记忆口诀
"4 G 八段 512,
Code 别名可重影;
Flash 代码常量坐,
SRAM 数据堆栈行;
外设寄存 4 开头,
6 9 外存接大屏;
E 段系统不可动,
调试内核藏性命。"
四、开发时最常问的 3 个"在哪"
-
全局变量/静态变量
→ 编译后落在 .data/.bss,运行期在 SRAM(0x2000 0000 起)。
-
malloc/free→ 堆区,仍在 SRAM,大小由启动文件里的
_heap_size决定。 -
外设寄存器
→ 0x4000 0000 开始,APB1 低速、APB2 高速、AHB 更高速,手册里查偏移即可。
把这张"两层图"印在脑子里,STM32 任何一段代码、变量、寄存器都能秒说出它走在哪条总线、位于哪块物理区域。