存储驱动SPI Flash读写调试与性能调优工程 - 第1节

1. SPI Flash基础

SPI(Serial Peripheral Interface,串行外设接口)是一种全双工、同步、主从式的串行通信总线。在嵌入式系统中,SPI 因其高速、简单、低引脚数的特点,成为连接 MCU 与 SPI Flash 芯片的首选接口。

1.1.1 物理层与信号线

标准的 SPI 总线使用 4 根信号线进行通信:

信号线全称方向功能描述
SCLKSerial Clock主→从由主设备产生的时钟信号,决定数据传输速率
MOSIMaster Out Slave In主→从主设备发送数据到从设备
MISOMaster 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 错误。
SPI 总线主从连接拓扑 主设备 MCU / SoC SPI 控制器 SPI Flash 从设备 1 SPI Flash 从设备 2 SCLK / MOSI / MISO CS# 独立片选 每个从设备独占一根 CS# 线,SCLK/MOSI/MISO 共享

1.2 SPI Flash 存储单元结构

SPI Flash 的存储单元基于浮栅晶体管(Floating Gate Transistor)技术。每个存储单元通过控制栅极和浮栅之间的电荷存储来表征数据状态。

1.2.1 存储单元层级

从物理结构到逻辑寻址,SPI Flash 的存储层次如下:

  1. Cell(单元):最小的存储单位,存储 1 bit(SLC)或多 bit(MLC/TLC)。
  2. Page(页):由多个 Cell 组成,是读写操作的最小单位。典型大小为 256 字节 ~ 4 KB。
  3. Block(块):由多个 Page 组成,是擦除操作的最小单位。典型大小为 64 KB ~ 256 KB。
  4. Sector(扇区):某些厂商将 Block 称为 Sector,或定义 Sector 为 Block 的子集。
  5. Die(芯片):一个独立的硅片,包含完整的存储阵列和外围电路。
层级操作粒度典型大小操作类型
Page读 / 写256 B ~ 4 KBProgram(编程)
Block擦除64 KB ~ 256 KBErase(擦除)
Sector擦除(部分芯片)4 KB ~ 32 KBErase
Die整体操作8 MB ~ 256 MBReset / 状态查询
常见误区: SPI Flash 不支持按字节擦除。写入前必须先擦除整个 Block 或 Sector。如果试图向非空区域写入数据,会导致数据损坏或编程失败。
SPI Flash 存储层级结构 Die(芯片) Block 0 Block 1 Page 0 Page 1 Page 2 Page 0 Page 1 Page 2 每个 Page 包含多个存储单元(Cell),SLC 每单元 1 bit,MLC 每单元 2 bit

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 FlashNAND 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(存文件系统)。
NOR Flash 与 NAND Flash 存储单元结构对比 NOR Flash 结构 单元并联,可独立寻址 支持随机字节读取 NAND Flash 结构 单元串联,共享位线 以页为单位访问 NOR 适合代码执行(XIP),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# 信号完整性。