[嵌入式系统-250]:MCU的内存空间分布
为了让你对 MCU 的内存布局有一个上帝视角的理解我们需要把物理地址空间CPU 看到的完整地图和逻辑数据分布程序编译后的实际落位结合起来看。在经典的 ARM Cortex-M 架构如 STM32中内存通常被映射到一个4GB的地址空间里。我们可以把这个空间想象成一栋大楼不同的住户代码、数据、外设住在不同的楼层。️ MCU 全局物理地址分布从低到高这张图展示了 CPU 视角的完整地址空间。请注意ROM、RAM 和外设寄存器通常位于不连续的地址块中。地址数值 (32位) 区域名称 物理介质 ----------------------- | 0x0000 0000 | | | ... | 代码存储区 | -- 通常映射 Flash (ROM) | 0x1FFF FFFF | (Code Memory) | (低位地址区域) ----------------------- | 0x2000 0000 | | | ... | SRAM 区 | -- 真正的 RAM | 0x3FFF FFFF | (SRAM) | (中位地址区域) ----------------------- | 0x4000 0000 | | | ... | 外设区 | -- 寄存器映射区 | 0x5FFF FFFF | (Peripherals) | (高位地址区域) ----------------------- | 0xE000 0000 | | | ... | 内核外设 | -- 中断控制器、SysTick | 0xFFFF FFFF | (Core Periph) | ----------------------- 详细内部布局ROM 与 RAM接下来我们放大看ROM和RAM内部代码段、数据段、堆、栈具体是如何摆放的。1. ROM (Flash) 区域 —— 代码的“家”地址方向从低地址向高地址排列。这里存放的是静态的固件镜像。低位地址 (起始处)中断向量表这是 Flash 的开头如0x0800 0000。它存放着“栈顶指针初始值”和“复位中断服务程序地址”。CPU 上电后第一件事就是读这里。中间部分Code 段 (.text)存放编译后的机器指令函数体。RO-data 段 (.rodata)存放const修饰的常量如const int a 10;和字符串字面量如Hello。高位地址 (结束处)RW-data 的初始值这是一个容易被忽略的区域。虽然.data变量运行在 RAM 里但它们的初始值如int b 5;中的5必须保存在 Flash 的末尾。程序启动时启动代码会把这部分数据搬运到 RAM 中。2. RAM (SRAM) 区域 —— 数据的“舞台”地址方向静态变量从低往高栈从高往低。这里存放的是运行时的动态数据。低位地址 (起始处)RW-data 段 (.data)紧挨着 RAM 起始地址。这里存放已初始化且非零的全局/静态变量。程序一运行这里就有了从 Flash 搬过来的值。BSS 段 (.bss / ZI)紧挨着.data。这里存放未初始化或初始化为 0 的全局/静态变量。启动时会被硬件或软件清零。中间部分 (动态生长区)堆 (Heap)紧挨着 BSS 段向高地址方向生长。用于malloc或new动态分配内存。高位地址 (顶端)栈 (Stack)位于 RAM 的最高地址处向低地址方向生长栈底在高地址栈顶指针往下减。用于存放函数局部变量、函数参数、返回地址。关键点堆和栈中间是空闲内存。如果堆向上长太大或者栈向下溢出太深两者就会“相撞”导致程序崩溃Stack Overflow 或 Heap Corruption。 总结表各段在 RAM/ROM 中的位置表格内存段物理位置逻辑位置地址增长/方向备注CodeROM低地址向上紧接向量表RO-dataROM中地址向上紧接 CodeRW-data (初值)ROM高地址向上位于 ROM 末端RW-data (变量)RAM低地址向上启动时从 ROM 复制而来BSSRAM低地址向上紧接 RW-data启动时清零HeapRAM中地址向上动态分配易碎片化StackRAM高地址向下位于 RAM 顶端易溢出一句话口诀“Flash 低址存代码向量领头常量随RAM 低址存变量堆往上长栈往下坠。”