MCU 内存栈介绍和内存段

非常好,这个问题问得特别关键 👍,因为理解「这些段的全称」和「栈在函数执行时怎么用」是彻底搞懂 MCU 内存分布的关键。

我们分两部分来讲:


🧩 一、这些段名的全称与作用

段名 全称(英文) 所在内存 主要内容 生命周期
.text text segment Flash(程序存储器) 代码(函数体、常量字符串) 永久(程序存储期间)
.rodata read-only data segment Flash 常量数据(const 修饰的变量、字符串常量) 永久
.data initialized data segment SRAM 已初始化的全局/静态变量(带初值的) 程序运行期间
.bss Block Started by Symbol SRAM 未初始化的全局/静态变量(自动清零) 程序运行期间
.heap heap segment SRAM malloc()、new 动态分配的内存 动态分配期间
.stack stack segment SRAM 函数调用时的局部变量、返回地址、寄存器 函数调用期间

🧠 二、栈(Stack)的真正含义

栈是 一个共享的内存空间 ,所有函数共用同一块区域。

它并不是"每个函数一个栈",而是每个函数在这块总栈里临时分配一部分空间。


⚙️ 举例说明:

假设你在启动文件里设置:

asm 复制代码
Stack_Size EQU 0x00018000  ; 96 KB

这就意味着:

整个系统的「主栈」空间总共有 96 KB,

所有函数调用、局部变量都在这 96 KB 里"挤着用"。


💻 举个具体例子:

c 复制代码
void foo(void)
{
    int a;               // 占 4 字节
    uint8_t buf[100];    // 占 100 字节
    bar();
}

void bar(void)
{
    uint8_t temp[200];   // 占 200 字节
}

当执行 foo() 时:

复制代码
SP ───►  [bar() 临时变量]  200B
          [bar() 返回地址]   4B
          [foo() 临时变量]  104B
          ...

bar() 退出后,它的 200B 就从栈中释放;
foo() 退出后,它的 104B 也释放。

整个过程都发生在同一块 96KB 的栈空间中。


📉 栈是「向下增长」的

  • 栈顶地址在 SRAM 的高端(如 0x2003FFFF)
  • 每次函数调用时,SP(栈指针)往低地址移动
  • 函数返回时,SP 恢复到原位置

图示:

复制代码
高地址  0x2003FFFF  ←─ 栈顶 (__initial_sp)
         ↓
         [foo 的局部变量]
         [bar 的局部变量]
         [中断上下文]
         ↓
低地址  0x20028000

🔍 三、你设置的 Stack_Size 是"最大允许空间"

比如你设 Stack_Size = 0x00018000 (96KB):

  • 这并不是每个函数 96KB,而是:

    所有函数调用层级嵌套时,总共最多可以用 96KB。

  • 如果函数嵌套很深、局部变量数组很多、或者中断嵌套多层,就会更快地消耗这块空间。


📘 四、各区域的分布(完整内存图)

以 GD32F415 为例(256KB SRAM):

复制代码
Flash (1MB) ────────────────────────────────
| .text / .rodata / 常量 / 程序代码         |
────────────────────────────────────────────
SRAM (256KB) ───────────────────────────────
| .data  (已初始化全局变量)                |
| .bss   (未初始化全局变量)                |
| .heap  (malloc 动态分配区, 向上增长)     |
| 空闲区 (heap 与 stack 缓冲)              |
| .stack (函数局部变量栈, 向下增长)       |
────────────────────────────────────────────

✅ 五、总结(一句话版)

名称 全称 作用 注意
.data Initialized Data Segment 存全局变量(有初值) 程序启动时从 Flash 拷贝到 SRAM
.bss Uninitialized Data Segment 存全局变量(无初值) 启动时自动清零
.heap Heap Segment malloc/new 动态内存 向上增长
.stack Stack Segment 函数局部变量、返回地址 向下增长
Stack_Size 最大可用栈空间 全系统共用一块 函数嵌套越深占用越多

💬 简而言之:

  • 你定义的 Stack_Size(比如 96KB)是整个系统共享的"总栈空间上限";
  • 每个函数执行时只在这块栈中"借"一点临时空间用;
  • 当函数退出,这部分空间会自动释放回去。

要不要我帮你画一张 栈增长与函数调用关系的图(SP 变化示意图) ?

看一张图就能明白栈是怎么"压入"和"弹出"的。

相关推荐
尼喃2 小时前
OVP/OCP过压过流保护芯片选型表:2A、3A、5A与10A方案怎么选
嵌入式硬件
无敌贵点大王8 小时前
嵌入式软件面试经(自用)
c语言·stm32·单片机·学习·mongodb·面试·职场和发展
NYFEA8 小时前
NF532重磅上新:高集成度13.56MHz非接触式控制器
嵌入式硬件
我是海飞8 小时前
使用杰理 AC7925B 实现 Windows电脑 USB 副屏
windows·单片机·电脑·嵌入式·杰理
我是海飞9 小时前
杰理 JL703N SDK 实现 AI 自动化调试:自动进入下载模式、下载、重启与日志抓取
人工智能·单片机·自动化·音视频·杰理
Zwawa9 小时前
PID 的三个参数之外:位置式、增量式和反馈控制
c语言·单片机·嵌入式
创界工坊工作室9 小时前
29-基于单片机的万年历设计
stm32·单片机·嵌入式硬件·proteus
木由里予9 小时前
NAND 这门生意
运维·服务器·网络·单片机
国科安芯10 小时前
在轨服务与空间机器人任务中跨飞行器CANFD互连的共模与单粒子问题综述
嵌入式硬件·机器人·canfd·低轨卫星·商业航天·抗辐射
沐欣工作室_lvyiyi10 小时前
基于STM32的社区养老控制系统设计(论文+源码)
stm32·单片机·嵌入式硬件·社区养老控制系统·保定理工学院·华德学院·淮南师范学院