存储驱动SPI Flash读写调试与性能调优 - 第1节
1.1 SPI 总线协议概述
SPI(Serial Peripheral Interface,串行外设接口)是一种全双工、同步、主从式的串行通信总线。在嵌入式系统中,SPI 因其高速、简单、低引脚数的特点,成为连接 MCU 与 SPI Flash 芯片的首选接口。
1.1.1 物理层与信号线
标准的 SPI 总线使用 4 根信号线进行通信:
| 信号线 | 全称 | 方向 | 功能描述 |
|---|---|---|---|
| SCLK | Serial Clock | 主→从 | 由主设备产生的时钟信号,决定数据传输速率 |
| MOSI | Master Out Slave In | 主→从 | 主设备发送数据到从设备 |
| MISO | Master In Slave Out | 从→主 | 从设备发送数据到主设备 |
| CS# | Chip Select | 主→从 | 片选信号,低电平有效,选中目标从设备 |
调试要点: 在硬件调试阶段,应优先使用示波器或逻辑分析仪测量 SCLK 频率、CS# 的建立/保持时间以及 MISO 数据线上的信号完整性。SPI Flash 对时钟毛刺和 CS# 抖动非常敏感。
1.1.2 SPI 总线时序与模式
SPI 协议定义了 4 种工作模式,由时钟极性(CPOL)和时钟相位(CPHA)组合决定:
- CPOL = 0:空闲时 SCLK 为低电平
- CPOL = 1:空闲时 SCLK 为高电平
- CPHA = 0:数据在 SCLK 的第一个边沿采样(上升沿或下降沿取决于 CPOL)
- CPHA = 1:数据在 SCLK 的第二个边沿采样
绝大多数 SPI Flash 芯片默认工作在 Mode 0 (CPOL=0, CPHA=0) 或 Mode 3 (CPOL=1, CPHA=1)。驱动开发时务必核对芯片数据手册中的时序要求。
驱动开发提示: 在初始化 SPI 控制器时,需要配置时钟极性、相位、数据位宽(通常为 8 位)以及时钟分频系数。错误的模式配置会导致数据移位或 CRC 错误。
1.2 SPI Flash 存储单元结构
SPI Flash 的存储单元基于浮栅晶体管(Floating Gate Transistor)技术。每个存储单元通过控制栅极和浮栅之间的电荷存储来表征数据状态。
1.2.1 存储单元层级
从物理结构到逻辑寻址,SPI Flash 的存储层次如下:
- Cell(单元):最小的存储单位,存储 1 bit(SLC)或多 bit(MLC/TLC)。
- Page(页):由多个 Cell 组成,是读写操作的最小单位。典型大小为 256 字节 ~ 4 KB。
- Block(块):由多个 Page 组成,是擦除操作的最小单位。典型大小为 64 KB ~ 256 KB。
- Sector(扇区):某些厂商将 Block 称为 Sector,或定义 Sector 为 Block 的子集。
- Die(芯片):一个独立的硅片,包含完整的存储阵列和外围电路。
| 层级 | 操作粒度 | 典型大小 | 操作类型 |
|---|---|---|---|
| Page | 读 / 写 | 256 B ~ 4 KB | Program(编程) |
| Block | 擦除 | 64 KB ~ 256 KB | Erase(擦除) |
| Sector | 擦除(部分芯片) | 4 KB ~ 32 KB | Erase |
| Die | 整体操作 | 8 MB ~ 256 MB | Reset / 状态查询 |
常见误区: SPI Flash 不支持按字节擦除。写入前必须先擦除整个 Block 或 Sector。如果试图向非空区域写入数据,会导致数据损坏或编程失败。
1.3 NOR Flash 与 NAND Flash 的区别
SPI Flash 主要分为 NOR Flash 和 NAND Flash 两种架构。虽然它们都使用浮栅存储技术,但在电路结构、访问方式和应用场景上有本质区别。
1.3.1 核心架构差异
- NOR Flash:存储单元并联连接,每个单元可直接寻址。支持随机读取,读取速度快,适合代码执行(XIP,eXecute In Place)。
- NAND Flash:存储单元串联连接,以页为单位访问。写入和擦除速度快,存储密度高,成本低,但读取速度较慢且不支持随机字节读取。
1.3.2 详细对比表
| 对比维度 | NOR Flash | NAND Flash |
|---|---|---|
| 存储单元连接 | 并联 | 串联 |
| 读取方式 | 随机字节/字读取 | 页读取(缓冲后串行输出) |
| 写入方式 | 按字节/字编程 | 按页编程 |
| 擦除方式 | 按扇区/块擦除 | 按块擦除 |
| 读取速度 | 快(~100 ns 随机访问) | 较慢(页读取后串行输出) |
| 写入速度 | 慢(~1 MB/s) | 快(~10 MB/s) |
| 擦除速度 | 慢(~1 s/块) | 快(~2 ms/块) |
| 存储密度 | 低(通常 ≤ 256 MB) | 高(可达 1 TB+) |
| 位翻转率 | 极低 | 较高,需要 ECC 纠错 |
| 坏块管理 | 无需 | 需要坏块管理(BBM) |
| 典型应用 | BIOS/UEFI、固件存储、代码执行 | 文件系统、大容量数据存储、日志 |
选型建议: 如果系统需要直接从 Flash 执行代码(XIP),应选择 NOR Flash。如果主要存储文件系统或日志数据,且对容量要求较高,NAND Flash 是更经济的选择。部分嵌入式系统会同时使用 NOR(存引导代码)和 NAND(存文件系统)。
1.3.3 驱动开发视角的关键差异
从驱动开发和调试的角度,以下差异直接影响代码实现:
- 读取命令:NOR 使用
READ (0x03)或FAST_READ (0x0B)支持任意地址读取;NAND 需要先发送PAGE_READ (0x00)命令将页数据加载到内部缓存,再通过串行时钟输出。 - 写入前检查:NOR 写入前需要确保目标区域已擦除(全 0xFF);NAND 同样需要擦除,但擦除粒度更大。
- 状态轮询:两种 Flash 在执行写/擦除操作时都需要轮询状态寄存器(
RDSR (0x05))的 BUSY 位,但 NAND 的页编程时间通常更短。 - ECC 与坏块:NOR 驱动通常不需要 ECC 和坏块管理;NAND 驱动必须集成 ECC 算法和坏块表(BBT)管理逻辑。
调试陷阱: 在调试 NAND Flash 驱动时,如果读取数据出现大量位翻转,首先检查 ECC 是否启用以及 ECC 算法是否正确。对于 NOR Flash,如果读取数据异常,优先检查 SPI 时序和 CS# 信号完整性。