☰
嵌入式内存架构:Flash、SRAM 与程序启动流程
2026/10/11 1:51:17 网站建设 项目流程

嵌入式内存架构:Flash、SRAM 与程序启动流程

视频版:嵌入式内存架构详解

嵌入式系统里真正难的不是记住“Flash 存程序、SRAM 存变量”,而是理解从断电保存、地址映射到程序运行之间的完整关系。只有把这条链串起来,才能解释变量为什么消失、程序为什么保留,以及启动代码到底在做什么。

1. 断电后,谁还记得?

程序烧写到 Flash 后,即使断电仍然存在。运行时变量通常放在 SRAM,断电后内容丢失。这是 Flash 与 SRAM 最直观的区别。

  • 非易失性:Flash、ROM、EEPROM,断电后保持;
  • 易失性:SRAM,断电后丢失。

2. 存储层级:速度、容量与成本的权衡

越靠近 CPU 的存储越快、越小、单位成本越高。典型层级包括寄存器、Cache、SRAM、Flash 和外部存储。

并不是所有 MCU 都有 Cache 或外部存储。层级只是理解访问速度和容量取舍的模型。

3. Flash 单元如何保存电荷

经典 Flash 单元利用浮栅保存电荷,通过电荷改变晶体管阈值,从而表示不同状态。

许多 MCU 可以直接从内部 Flash 取指,不必把全部代码复制到 SRAM。

4. Flash 写入规则:擦除、编程、验证

Flash 的一个关键限制是:擦除后通常读为全 1,编程可以把 1 变为 0,但要把 0 恢复为 1,必须先擦除整个擦除单元。

工程上要注意:

  • 擦除单位与编程单位各不相同;
  • 写入后最好读回验证;
  • 擦写寿命有限,频繁更新要分散到不同位置;
  • 必要时使用磨损均衡或外部 EEPROM。

5. SRAM 是运行时工作台

SRAM 用双稳态锁存器存储数据,常见单元由多个晶体管构成。持续供电时不需要像 DRAM 那样周期刷新,普通写入也不需要先擦除。

变量、缓冲区、调用栈和堆通常都放在 SRAM。断电后这些状态全部丢失。

6. ROM 与 EEPROM

  • Mask ROM:内容在制造阶段固定,适合内置启动代码等场景;
  • EEPROM:支持小量、字节级或页级电擦写,适合配置和校准参数;
  • 部分 MCU 使用 Flash 模拟 EEPROM,需要软件管理擦除与磨损。

7. 地址映射:把存储器与外设放进统一空间

内存映射给存储器、外设寄存器和系统组件分配地址。例如 STM32 中 Flash 可以从某个固定基址开始,SRAM 有独立地址段,外设寄存器也占用地址空间。

32 位地址空间可以覆盖 4 GiB,但这只是地址空间,并不代表芯片实际拥有 4 GiB 内存。

8. 链接脚本与程序分段

链接器把程序的不同段安排到不同区域:

  • .text:代码;
  • .rodata:只读常量;
  • .data:已初始化的可写全局变量;
  • .bss:零初始化全局变量;
  • 堆和栈:运行时的动态与调用空间。

典型情况下,.data的初值保存在 Flash,启动时复制到 SRAM;.bss只需清零,不必在固件镜像中保存整块零值。

9. 启动初始化:main 之前发生了什么

启动代码通常负责:

  1. 设置初始栈指针;
  2. 建立向量表;
  3. 把.data初值从 Flash 复制到 SRAM;
  4. 清零.bss;
  5. 调用运行时初始化;
  6. 进入main()。

这解释了为什么“初值为 42 的全局变量”在main中是 42,“未初始化全局变量”在main中是 0。

10. 堆栈与内存预算

函数调用通常建立栈帧,保存局部变量、返回地址和部分寄存器。堆用于动态分配。典型 Cortex-M 布局中,栈向低地址增长,堆向高地址增长,它们共享有限的 SRAM 空间。

优化内存时,要记住:

  • 把大数组改成static只减轻栈压力,不减少 SRAM 总占用;
  • 只读表通常可以留在 Flash;
  • 要测量栈峰值并保留安全余量;
  • 不要频繁写非易失性存储器;
  • 最终位置要结合链接映射文件确认。

知识链

存储类型 → 地址映射 → 程序分段 → 启动初始化 → 程序运行 → 内存预算与优化

总结

内存架构不是存储器属性表,而是程序从固件到运行的完整生命周期。理解 Flash、SRAM、地址、链接器和启动代码之间的关系,就能更清楚地分析内存溢出、数据丢失、启动失败和性能问题。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询