第四章 嵌入式存储系统:Flash、SRAM、DRAM、EEPROM、存储映射与启动过程
嵌入式系统的存储体系是软件运行与硬件协同的物理基础。理解各类存储介质的电气特性、时序要求、寿命限制以及在系统内存映射中的位置,是进行嵌入式软硬件设计的前提。本章将围绕存储介质分类、存储映射机制以及Bootloader启动流程三个核心维度展开,帮助读者建立从“芯片手册”到“系统运行”的完整认知链路。
4.1 存储介质核心原理与选型判断
嵌入式系统中,存储介质的选择直接决定系统的成本、功耗、启动速度与数据安全性。理解每种存储器的内部结构与访问特性,是进行存储系统设计的第一步。
4.1.1 核心原理
- SRAM(静态随机存储器):使用6T锁存器结构存储数据,无需刷新,访问速度快(纳秒级),但集成度低、成本高。常用于MCU内部RAM、Cache。
- DRAM(动态随机存储器):使用1T1C结构,需要周期性刷新(通常64ms),集成度高、成本低,但访问时序复杂。SDRAM/DDR均属此类,常用于大容量内存。
- NOR Flash:支持随机读取,可字节寻址,适合代码直接执行(XIP),但写入速度慢、容量较小。常用于Bootloader存储。
- NAND Flash:页/块访问,写入速度快、容量大,但存在坏块管理问题,不支持随机读取。常用于大容量数据存储。
- EEPROM:可字节擦写,寿命长(百万次),但容量小、速度慢。常用于参数保存。
4.1.2 判断方法
| 对比维度 | SRAM | DRAM | NOR Flash | NAND Flash | EEPROM |
|---|---|---|---|---|---|
| 访问单位 | 字节 | 字节(突发) | 字节(随机) | 页(2KB+) | 字节 |
| 读速度 | 极快(1-5ns) | 快(10-50ns) | 快(80-150ns) | 较快(页读) | 慢(us级) |
| 写速度 | 极快 | 快(需刷新) | 慢(ms级) | 快(页写) | 慢(ms级) |
| 擦除寿命 | 无限 | 无限 | 10万次 | 100万次 | 100万次 |
| 典型容量 | KB-MB | MB-GB | 1-64MB | 128MB-1TB | KB级 |
| 掉电保持 | 丢失 | 丢失 | 10年+ | 10年+ | 10年+ |
4.2 存储映射与地址空间设计
存储映射决定了CPU如何访问各类存储器与外设。Cortex-M系列采用统一编址方式,所有存储器和外设寄存器共享同一地址空间,简化了编程模型。
4.2.1 典型Cortex-M存储映射
0x0000_0000 - 0x1FFF_FFFF : 代码区(Flash, 512MB)
0x2000_0000 - 0x3FFF_FFFF : SRAM区(512MB)
0x4000_0000 - 0x5FFF_FFFF : 外设区(512MB)
0x6000_0000 - 0x9FFF_FFFF : 外部RAM/外设(1GB)
0xE000_0000 - 0xFFFF_FFFF : 系统区(私有外设)
4.2.2 存储映射设计要点
- 向量表位置:Cortex-M上电后从0x0000_0000读取初始SP,从0x0000_0004读取复位向量。若Bootloader重映射向量表,需设置VTOR寄存器。
- 内存保护单元(MPU):可配置区域属性(Cache策略、访问权限),防止关键代码区被非法写入。
- 外部存储控制器(FMC/EXMC):支持NOR/SRAM/PSRAM接口,可扩展外部存储映射到固定地址区间。
4.3 启动过程与Bootloader设计
Bootloader是系统上电后最先执行的代码,负责硬件初始化和引导应用程序。其设计质量直接影响系统的可靠性与可维护性。
4.3.1 启动流程详解
- 上电复位:CPU从复位向量取出PC初值,从0x0000_0000取出SP初值。
- 时钟初始化:配置PLL,将系统时钟从低速内部RC切换到高速外部晶振。
- 关键外设初始化:至少初始化Flash控制器、SDRAM控制器、串口(用于调试)。
- 代码搬运:若App存储在NAND Flash或外部存储,需将其复制到RAM或SDRAM中执行。
- 跳转准备:关闭全局中断,设置VTOR指向App向量表,设置PSP/MSP,跳转至App的Reset_Handler。
4.3.2 案例拆解:基于STM32F4的Bootloader设计
背景与约束:某工业控制器需支持通过UART升级固件,Bootloader占用32KB Flash(0x08000000-0x08007FFF),App从0x08008000开始。系统主频168MHz,外部25MHz晶振。
关键参数:Flash扇区大小16KB(前4个扇区),App最大支持512KB。升级协议采用YMODEM,每包128字节。
实现步骤:
// 1. 跳转函数(关键代码)
typedef void (*pFunction)(void);
void JumpToApp(uint32_t app_addr) {
uint32_t sp_val = *(volatile uint32_t*)app_addr;
uint32_t reset_val = *(volatile uint32_t*)(app_addr + 4);
// 关闭全局中断
__disable_irq();
// 设置向量表偏移
SCB->VTOR = app_addr;
// 设置MSP并跳转
__set_MSP(sp_val);
pFunction jump = (pFunction)reset_val;
jump();
}
结果对比:优化前Bootloader跳转后App死机,原因是没有关闭SysTick中断。增加SysTick->CTRL = 0;后跳转成功。此外,跳转前需将外设时钟恢复默认状态,避免App初始化时冲突。
4.4 常见误区与设计总结
| 误区 | 后果 | 正确做法 |
|---|---|---|
| 忽略Flash擦写寿命 | 频繁写入导致坏块 | 磨损均衡、减少写次数 |
| SRAM使用过多 | 编译链接失败 | 使用静态分析工具检查RAM占用 |
| DRAM刷新配置错误 | 随机数据错误 | 严格按手册配置刷新周期 |
| Bootloader未关中断跳转 | App启动异常 | 跳转前关闭所有中断源 |
| 向量表未重映射 | 中断无法响应 | 设置VTOR寄存器 |
嵌入式存储系统设计需要综合考虑容量、速度、成本、寿命和启动可靠性。建议在项目初期绘制存储映射图,明确各区域用途;在Bootloader中实现完整的升级与回滚机制;在硬件调试阶段使用内存测试工具验证存储系统稳定性。通过本章学习,读者应能独立完成存储选型、映射设计和Bootloader开发。