4、Flash存储器概述:NOR Flash与NAND Flash区别、SPI Flash典型型号特性
4.1 Flash存储器基础
Flash存储器是一种非易失性存储器(Non-Volatile Memory, NVM),在嵌入式系统中广泛用于存储固件、配置参数和文件系统。根据存储单元的结构和访问方式,Flash主要分为NOR Flash和NAND Flash两大类型。理解两者的区别,是正确选择SPI Flash型号和设计驱动架构的前提。
💡 核心概念:Flash存储器的基本存储单元是浮栅晶体管(Floating Gate Transistor),通过向浮栅注入电荷(编程)或释放电荷(擦除)来存储数据“0”和“1”。NOR和NAND的差异源于单元连接方式与读写策略的不同。
4.2 NOR Flash vs NAND Flash 对比
下表从接口、读写方式、容量、可靠性等关键维度对比两种Flash架构:
| 对比维度 | NOR Flash | NAND Flash |
|---|---|---|
| 存储单元连接 | 并联(每个单元独立连接位线) | 串联(多个单元组成NAND串) |
| 读取方式 | 随机访问,支持XIP(片上执行) | 页读取,不支持直接XIP |
| 写入/编程 | 按字节/字编程,速度较慢 | 按页编程(典型2KB/4KB),速度快 |
| 擦除操作 | 按扇区擦除(典型64KB) | 按块擦除(典型128KB~1MB) |
| 典型容量 | 1Mb ~ 256Mb(小容量为主) | 1Gb ~ 1Tb(大容量为主) |
| 位反转率 | 极低(< 10⁻⁹) | 较高(需ECC纠错) |
| 坏块管理 | 无需坏块管理 | 出厂含坏块,需坏块表管理 |
| 典型应用 | 固件存储、Bootloader、代码执行 | 文件系统、大容量数据存储 |
| SPI接口常见度 | 非常常见(SPI NOR Flash) | 较少(SPI NAND Flash,如GD5F系列) |
📌 驱动开发要点:本课程聚焦SPI NOR Flash,因为其接口简单、随机读取快、无需ECC和坏块管理,非常适合嵌入式MCU的固件存储和配置参数保存。SPI NAND Flash虽然容量更大,但驱动复杂度显著增加。
4.3 SPI Flash 内部架构与操作流程
SPI Flash通过SPI总线与主机通信,内部包含存储阵列、页缓冲器、状态寄存器、控制逻辑等模块。下图展示了SPI Flash的典型内部架构和读写数据流:
4.4 典型 SPI Flash 型号:W25Q64 与 MX25L
在嵌入式开发中,Winbond W25Q64 和 Macronix MX25L 系列是最常见的 SPI NOR Flash 型号。两者功能兼容,但在指令集、性能参数和时序细节上存在差异。下表对比两者的关键特性:
| 特性参数 | W25Q64JV (Winbond) | MX25L6436F (Macronix) |
|---|---|---|
| 容量 | 64 Mbit (8 MB) | 64 Mbit (8 MB) |
| 页大小 | 256 字节 | 256 字节 |
| 扇区大小 | 4 KB(小扇区) | 4 KB(小扇区) |
| 块大小 | 32 KB / 64 KB | 32 KB / 64 KB |
| 最大 SPI 时钟 | 133 MHz (Quad SPI) | 133 MHz (Quad SPI) |
| 页编程时间(典型) | 0.4 ms (256B) | 0.5 ms (256B) |
| 扇区擦除时间(典型) | 45 ms (4KB) | 60 ms (4KB) |
| 支持指令集 | 标准 SPI / Dual / Quad SPI | 标准 SPI / Dual / Quad SPI |
| 唯一 ID | 64 位唯一序列号 | 64 位唯一序列号 |
| 工作电压 | 2.7V ~ 3.6V | 2.7V ~ 3.6V |
⚠️ 驱动兼容性注意:虽然 W25Q64 和 MX25L 的指令集高度相似,但 读状态寄存器(RDSR)、写使能(WREN) 和 擦除指令 的时序要求存在细微差异。在编写通用 SPI Flash 驱动时,建议通过 JEDEC ID 读取指令(0x9F) 自动识别芯片型号,再加载对应的时序参数表。
4.5 SPI Flash 关键指令集与操作流程
SPI NOR Flash 通过标准指令集进行控制。下表列出 W25Q64 和 MX25L 共用的核心指令:
| 指令名称 | 指令码 | 功能描述 | 地址/数据长度 |
|---|---|---|---|
| WREN | 0x06 | 写使能(必须先执行) | 无地址,无数据 |
| WRDI | 0x04 | 写禁止 | 无地址,无数据 |
| RDSR | 0x05 | 读状态寄存器 | 无地址,返回1字节 |
| WRSR | 0x01 | 写状态寄存器 | 无地址,写入1字节 |
| READ | 0x03 | 标准读数据(单线) | 3字节地址,连续读 |
| FAST_READ | 0x0B | 快速读(带Dummy周期) | 3字节地址 + 1 Dummy |
| PP | 0x02 | 页编程(Page Program) | 3字节地址 + 1~256字节数据 |
| SE | 0x20 | 扇区擦除(4KB) | 3字节地址 |
| BE | 0xD8 | 块擦除(64KB) | 3字节地址 |
| CE | 0xC7 | 芯片擦除(整片) | 无地址 |
| RDID | 0x9F | 读 JEDEC ID(识别芯片) | 无地址,返回3字节 |
4.6 页编程与擦除操作流程
SPI Flash 的写入和擦除操作需要严格的指令序列。下图以 页编程(Page Program) 为例展示完整流程:
4.7 驱动开发中的关键时序参数
在编写 SPI Flash 驱动时,以下时序参数直接影响读写效率和稳定性:
- tPP(页编程时间):典型 0.4~0.5 ms,最大 3 ms(需在驱动中设置超时阈值)
- tSE(扇区擦除时间):典型 45~60 ms,最大 400 ms
- tBE(块擦除时间):典型 150~250 ms,最大 1 s
- tCE(芯片擦除时间):典型 10~20 s,最大 40 s
- tCLV(输出保持时间):至少 5 ns,确保 SPI 采样稳定
🔧 驱动实现建议:在 SPI Flash 驱动中,建议使用 状态寄存器轮询(Polling) 方式等待操作完成,而非固定延时。轮询方式能适应不同芯片的实际速度,提高整体效率。典型实现如下:
// 等待 SPI Flash 空闲(WIP 位清零)
uint8_t SPI_Flash_WaitBusy(SPI_HandleTypeDef *hspi) {
uint8_t status;
do {
// 发送 RDSR 指令 (0x05)
SPI_Flash_SendByte(hspi, 0x05);
status = SPI_Flash_ReceiveByte(hspi);
// 检查 WIP (Bit 0)
} while (status & 0x01);
return 0; // 空闲
}
4.8 本章小结
本章介绍了 Flash 存储器的基本分类,重点对比了 NOR Flash 与 NAND Flash 在架构、读写方式、可靠性和应用场景上的差异。针对嵌入式 SPI 驱动开发,详细分析了 W25Q64 和 MX25L 两款典型 SPI NOR Flash 的型号特性、指令集和时序参数。掌握这些基础知识,是后续实现 SPI 驱动、配置 DMA 传输速率和优化读写性能的前提。