前言
在这里会较为详细的阐述各种类型的存储器的特点及其之间的差别,以及我们会在STM32单片机上面使用一种超级便捷的方式来管理我们所使用到的内存。
理清 xxRAM、xxROM、xxFlash 的核心作用
三种不同存储器:RAM、ROM、Flash
这三个总的概括,就使用一个表格来说明吧,表格如下:
内存 | 存储类型 | 核心功能 | 数据保持 | 单片机对应硬件 | 典型存储内容 |
---|---|---|---|---|---|
RAM | 易失性 | 存放动态数据、临时变量 | 掉电丢失 | DTCM/AXI SRAM / 普通 SRAM | 全局变量、局部变量、栈 / 堆 |
ROM(概念) | 非易失性 | 只读存储(功能) | 掉电不丢 | 由 Flash 实现 | 无独立硬件,功能同 Flash |
Flash | 非易失性 | 存放程序代码、常量 | 掉电不丢 | 片上 Flash(一般0x08000000 起) | 代码段、const 常量、复位向量表 |
四种 RAM:DRAM、SRAM、SDRAM、MRAM
DRAM
(Dynamic RAM,动态随机存取存储器)
- 原理: 利用电容存储电荷来表示数据(0/1),但电容会漏电,需要定期 "刷新"(每隔几毫秒充电一次)才能保持数据。
- 特点: 结构简单(一个晶体管 + 一个电容),密度高(相同体积下容量更大);速度中等(比 SRAM 慢),功耗较高(刷新需要耗电);价格便宜(单位容量成本低)。
- 应用 : PC 的内存(DDR4/DDR5 都是 DRAM 的改进型)、智能手机的运行内存(RAM)等需要大容量临时存储的场景。
SRAM
(Static RAM,静态随机存取存储器)
- 原理: 利用触发器(由多个晶体管组成)存储数据,无需刷新,只要供电就能保持数据。
- 特点: 速度极快(访问时间纳秒级,比 DRAM 快 10~100 倍);结构复杂(一个 bit 需要 6~8 个晶体管),密度低(容量小);价格高(单位容量成本是 DRAM 的几倍),功耗中等(无需刷新但晶体管本身耗电)。
- 应用 : CPU 内部的高速缓存(L1/L2/L3 Cache)、STM32 片上 RAM(如 DTCM、SRAM1~4 都是 SRAM)等需要高速访问的场景。
SDRAM
(Synchronous DRAM,同步动态随机存取存储器)
- 原理: 属于 DRAM 的一种,工作时与 CPU 时钟同步(数据读写按时钟节拍进行),需要定期刷新。
- 特点: 速度比传统异步 DRAM 快,容量大(常见 128MB~2GB);需外部控制器(如 STM32 的 FMC 接口),时序配置复杂。
- 应用 : 嵌入式系统扩展大容量临时存储,如 STM32 H7 系列外接 SDRAM 用于存放视频帧、大型缓存数据等。
MRAM
(Magnetoresistive RAM,磁阻式随机存取存储器)
- 原理: 利用磁阻效应存储数据(通过磁场变化改变电阻状态表示 0/1),非易失性,无需刷新。
- 特点: 速度接近 SRAM,容量接近 DRAM,非易失性(掉电不丢数据);功耗低(无需刷新和电荷维持),寿命长(理论无限次擦写);成本高(目前还未大规模普及)。
- 应用 : 高端嵌入式系统(如工业控制、汽车电子)需要 "高速 + 非易失" 的场景,替代部分 SRAM 和 Flash 的组合使用
对比
特性 | DRAM | SRAM | SDRAM | MRAM |
---|---|---|---|---|
易失性 | 掉电丢失 | 掉电丢失 | 掉电丢失 | 掉电不丢失 |
速度 | 中等(几十纳秒) | 极快(几纳秒,接近 CPU 速度) | 比 DRAM 快(同步时钟优化) | 接近 SRAM(几纳秒) |
大小 | GB 级 | MB 级 | 数百 MB~ 数 GB | 目前可达 GB 级,逐步提升 |
功耗 | 较高 | 中等 | 略低于 DRAM | 低 |
成本 | 低 | 高 | 与 DRAM 接近 | 高(未大规模普及) |
应用 | 早期 PC 内存、低端嵌入式设备 | CPU 缓存、STM32 片内 RAM | 嵌入式扩展内存 | 工业控制、汽车电子 |
两种 Flash:NAND Flash、NOR Flash
NOR Flash
(或非闪存)
原理: 同样基于浮栅晶体管,非易失性,但内部结构与 NAND 不同。
特点: 随机访问速度快(可直接 "按地址读取",类似 RAM),支持 "代码在 Flash 中直接运行"(XIP,eXecute In Place);密度低(容量小),价格高(单位容量成本高),擦写速度慢(尤其大容量擦除)。
应用: 嵌入式系统的 "程序存储器",如 STM32 片上 Flash 几乎都是 NOR Flash(用于存储程序代码、启动程序),路由器、交换机的固件存储等;STM32 中片内 Flash(如 0x08000000 起始地址的存储区域)均为 NOR Flash,支持程序直接在 Flash 中运行(无需加载到 RAM)。
NAND Flash
(与非闪存)
原理: 基于浮栅晶体管存储电荷,通过电荷是否存在表示数据,属于非易失性存储(掉电不丢数据)。
特点: 结构简单,密度极高(相同体积下容量远大于 NOR Flash);读写速度 "页级快、随机慢"(适合连续读写,随机访问速度差);价格低(单位容量成本是 NOR Flash 的 1/5~1/10),但有 "坏块" 和 "擦写次数限制"(通常 10 万次以上)。
应用: 大容量存储场景,如 U 盘、SD 卡、固态硬盘(SSD)、嵌入式系统的 "硬盘"(如存储固件、日志、用户数据);STM32 中部分型号支持外接 NAND Flash(如 F4/F7/H7 系列),用于扩展大容量非易失性存储。
对比
特性 | NOR Flash | NAND Flash |
---|---|---|
存储结构 | 并行结构,地址线可直接寻址单个字节 | 串行 / 页式结构,需按 "块 - 页" 层级寻址 |
速度 | 随机访问快(10~100ns),支持按地址读单个字节;连续读写速度慢 | 随机访问慢(需先找块、再找页);连续读写快(页级操作,几十 MB/s) |
执行能力 | 支持 XIP(就地执行):程序可直接在 Flash 中运行,无需加载到 RAM | 不支持 XIP:代码需先加载到 RAM 才能运行 |
擦写特性 | 支持小粒度擦除(扇区级,如 4KB/8KB),部分支持字节级修改 | 必须 "先擦除再写入",擦除粒度大(块级,如 128KB/256KB),仅支持页级写入 |
容量与密度 | 密度低,单芯片容量小(通常 1MB~1GB) | 密度高,单芯片容量大(通常 8GB~1TB,甚至更高) |
成本 | 单位容量成本高(约为 NAND 的 5~10 倍) | 单位容量成本低,性价比高 |
引脚与接口 | 引脚多(需地址线、数据线分离),接口复杂 | 引脚少(地址 / 数据复用),接口简单(如 SPI/NAND、ONFI 接口) |
应用 | 小型嵌入式设备的程序存储、交换机 | 硬盘、手机、平板的内置存储 |
EEPROM
原理: 通过电信号擦除和写入数据,非易失性,可字节级擦写(无需按块擦除)。
特点: 擦写方便(支持单个字节修改,无需整块擦除);容量小(通常 KB 级,最大几 MB),速度慢(擦写时间毫秒级),寿命有限(通常 10 万次擦写)。
应用: 存储少量需要频繁修改的非易失性数据,如设备参数(波特率、地址)、校准数据(传感器零点)、用户配置等;STM32 中部分型号内置 EEPROM(如 F1/F4 系列),或通过 "Flash 模拟 EEPROM" 功能实现类似效果(如 H7 系列无独立 EEPROM,需用 Flash 特定区域模拟)。
H7 系列内存详解
参考文章:[ST] STM32H7的TCM,SRAM等五块内存基础知识
H7的内部内存分为了ITCM,DTCM,AXI SRAM,SRAM1,SRAM2,SRAM3,SRAM4和备份SRAM。下图中分为了三个域:D1 Domain,D2 Domain和D3 Domain。

TCM 区
(Tightly-Coupled Memory 紧密耦合内存)
- ITCM:用于运行指令,也就是程序代码。
- DTCM:用于数据存取,特点是跟内核速度一样,而片上RAM的速度基本都达不到这个速度,所以有降频处理。
AXI SRAM 区
位于D1域,数据带宽是64bit,挂在A线上。除了D3域中的BDMB主控不能访问,其它都可以访问此RAM区。
AXI SRAM
地址:0x2400 0000。
速度:200MHz。
大小:512KB。
用途:用途不限,可以用于用户应用数据存储或者LCD显存。
SRAM1,SRAM2和SRAM3 区
位于D2域,数据带宽是32bit,挂在AHB总线上。除了D3域中的BDMB主控不能访问这三块SRAM,其它都可以访问这几个RAM区。
SRAM1
地址:0x3000 0000。
速度:200MHz。
大小:128KB。
用途:用途不限,可用于D2域中的DMA缓冲,也可以当D1域断电后用于运行程序代码。
SRAM2地址:0x3002 0000。
速度:200MHz。
大小:128KB。
用途:用途不限,可用于D2域中的DMA缓冲,也可以用于用户数据存取。
SRAM3地址:0x3004 0000。
速度:200MHz。
大小:32KB。
用途:用途不限,主要用于以太网和USB的缓冲。
SRAM4 区
位于D3域,数据带宽是32bit,挂在AHB总线上,大部分主控都能访这块SRAM区。
地址:0x3800 0000。
速度:200MHz。
大小:64KB。
用途:用途不限,可以用于D3域中的DMA缓冲,也可以当D1和D2域进入DStandby待机方式后,继续保存用户数据。
Backup SRAM 区
备份RAM区,位于D3域,数据带宽是32bit,挂在AHB总线上,大部分主控都能访问这块SRAM区。
SRAM4
地址:0x3880 0000。
速度:200MHz。
大小:4KB。
用途:用途不限,主要用于系统进入低功耗模式后,继续保存数据(Vbat引脚外接电池)。
内存时钟问题
AXI SRAM,SRAM4,ITCM和DTCM可以在上电后直接使用。而SRAM1,SRAM2,SRAM3是需要使能的,但是实际测试发现,不使能也可以正常使用。不过,建议用到时候开启下时钟,防止意想不到的问题发生。

RAM 的 DMA 问题
Bus Master总线主控端和Bus Slave设备端的控制互联:

加粗字体是64位总线(ITCM,DTCM,Flash A,Flash,AXI SRAM,FMC等),普通字体是32位总线。
访问通路(每个小方块里面的字符)
任何有数字的表示有访问通路。
短横杠"-"表示不可访问。
有灰色阴影的表示有实用价值的访问通路。
表格中具体数值所代表的含义
D=direct,
1=via AXI bus matrix,
2=via AHB bus matrix in D2,
3=via AHB bus matrix in D3,
4=via AHB/APB bridge in D1,
5=via AHB/APB bridge in D2,
6=via AHB/APB bridge in D3,
7=via AHBS bus of Cortex-M7,
多个数值组合 = 互连路径以数字的顺序经过多个矩阵或/和桥。
总线访问类型
普通字体表示32位总线。
斜体表示32位总线主机端/ 64位总线从机端。
粗体表示64位总线。
超便捷的内存区域管理方法
参考文章:【STM32H7教程】第26章 STM32H7的TCM,SRAM等五块内存的超方便使用方式
一般的内存管理方式
不太注意的话,一般都是在"target dialog"这里简单管理内存。这种情况下,所有管理工作都是编译来处理的。

分散加载式管理内存区域
使用分散加载的方式来管理内存,会超级灵活,想用哪一块就用哪一块。下面就是超级教程:
在魔术棒的"OutPut"配置中,会生成一个相同名字的 .sct 文件,这个就是这个方法的关键,找到它。

第一步
- 取消勾选"Use Memiry Layout from Target Dialog"。
- 点击"..."找到与输出文件同名的 .sct 文件(假如你这里没有显示的话)。
- 点击"Edit"打开这个 .sct 文件。

第二步
使用 STM32H7 系列的可以直接将以下程序复制进去。其他系列的单片机则需要稍加修改。
假如不同,你需要修改的有:
- 内存(ROM 或者 RAM)首地址
- 内存大小
点击查看代码
; *************************************************************
; *** Scatter-Loading Description File generated by uVision ***
; *************************************************************
; 定义加载区域LR_IROM1:起始地址0x08000000,大小0x00200000(2MB)
; 这是整个程序的加载区域,通常对应Flash存储器
LR_IROM1 0x08000000 0x00200000 { ; load region size_region
; 定义执行区域ER_IROM1:起始地址与加载地址相同(0x08000000),大小2MB
; 存放程序的只读代码和常量
ER_IROM1 0x08000000 0x00200000 { ; load address = execution address
*.o (RESET, +First) ; 所有目标文件的RESET段,放在最前面(复位向量)
*(InRoot$$Sections) ; 根区域必要的特殊段(如异常向量表)
.ANY (+RO) ; 任何文件的只读代码和常量(RO段)
.ANY (+XO) ; 任何文件的可执行代码(XO段)
}
; 定义DTCM内存区域:起始地址0x20000000,大小0x00020000(128KB)
; DTCM是内核紧密耦合的数据存储器,访问速度快
RW_DTCM_IRAM 0x20000000 0x00020000 { ; RW data
.ANY (+RW +ZI) ; 任何文件的读写数据(RW)和未初始化数据(ZI)
;*(.RAM_D0) ;段选择器,若不手动选择,则完全不会被分配到此
}
; 定义AXI SRAM区域:起始地址0x24000000,大小0x00080000(512KB)
; AXI接口的SRAM,通常用于高性能数据访问
RW_AXI_SRAM_IRAM 0x24000000 0x00080000 {
.ANY (+RW +ZI) ; 任何文件的读写数据和未初始化数据
;*(.RAM_D1) ;段选择器,若不手动选择,则完全不会被分配到此
}
; 定义SRAM1~SRAM3区域:起始地址0x30000000,大小0x00080000(512KB)
; 片上静态存储器区域1-3
RW_SRAM_1_3_IRAM 0x30000000 0x00080000 {
.ANY (+RW +ZI) ; 任何文件的读写数据和未初始化数据
;*(.RAM_D2) ;段选择器,若不手动选择,则完全不会被分配到此
}
; 定义SRAM4区域:起始地址0x38000000,大小0x00010000(64KB)
; 片上静态存储器区域4
RW_SRAM_4_IRAM 0x38000000 0x00010000 {
.ANY (+RW +ZI) ; 任何文件的读写数据和未初始化数据
;*(.RAM_D3) ;段选择器,若不手动选择,则完全不会被分配到此
}
}
; 段选择器使用案例:
; __attribute__((section (".RAM_D1"))) uint32_t AXISRAMBuf[10];
; __attribute__((section (".RAM_D2"))) uint16_t AXISRAMCount;
;
; 若没有使用段选择器,那么就会按照分散加载文件中内存区域的定义顺序依次分配,
; 直到前面的区域被占满后才会 "溢出" 到后面的区域。
可以看出,RW区也是要存储到ROM/Flash里面的,在执行映像之前,必须将已初始化的 RW 数据从 ROM 中复制到 RAM 中的执行地址并创建ZI Section(初始化为0的变量区)。
上面的程序注释中已经详细说明了这一段程序的作用,其中的加载区域就是程序在Flash中的实际存储,而运行区域是芯片上电后的运行状态,通过下面的框图可以有一个感性的认识:
