4. SPI Flash 指令集:标准指令集与厂商特定指令

SPI Flash 的指令集是驱动开发的核心操作手册。本章将系统梳理标准指令集(READ、WRITE、ERASE)、厂商特定指令以及指令时序图的解析方法。掌握这些指令的编码、参数和时序约束,是编写高效、稳定驱动的基础。

4.1 标准指令集概览

标准指令集由 JEDEC 定义,是所有 SPI Flash 芯片必须支持的基础操作。下表列出了最常用的标准指令及其功能描述:

指令名称 指令码 (8-bit) 功能描述 地址字节数 数据字节数
READ 0x03 读取数据(标准速度,最高 50 MHz) 3 1~N
FAST_READ 0x0B 快速读取(含 dummy 周期,支持更高频率) 3 1~N
PAGE_PROGRAM 0x02 页编程(写入数据到页缓冲区) 3 1~256
SECTOR_ERASE 0x20 扇区擦除(4 KB 扇区) 3 0
BLOCK_ERASE_64K 0xD8 块擦除(64 KB 块) 3 0
CHIP_ERASE 0xC7 全片擦除 0 0
WRITE_ENABLE 0x06 写使能(执行写/擦除前必须发送) 0 0
READ_STATUS_REG 0x05 读取状态寄存器(检查 BUSY 位) 0 1
关键提示: 所有写操作(PAGE_PROGRAM、ERASE)之前,必须发送 WRITE_ENABLE (0x06) 指令。否则 Flash 会忽略后续操作。这是 SPI Flash 防止误写的硬件保护机制。

4.2 指令时序图解析

理解时序图是驱动开发的基本功。SPI 时序图以 CS(片选)、SCLK(时钟)、SI(数据输入)、SO(数据输出)四根信号线展示指令的完整执行过程。下面以 PAGE_PROGRAM 指令为例进行解析。

PAGE_PROGRAM 指令时序图 CS# CS 拉低,选中设备 CS 拉高,结束操作 SCLK SI 0x02 A23 A15 A7 D7 D6 D5 D4 D3 D2 D1 D0 SO 高阻态 (High-Z) 指令 24-bit 地址 数据字节 (1~256 字节) 时间轴 →
时序要点:
  • CS 拉低 启动操作,在整个指令、地址、数据发送期间必须保持低电平。
  • 指令码(如 0x02)在 SCLK 上升沿被 Flash 采样,高位在前 (MSB first)。
  • 24-bit 地址 紧随指令码,指定写入的起始地址。
  • 数据字节 连续发送,最多 256 字节(一页)。超过页边界会自动回绕到页首。
  • CS 拉高 后,Flash 开始内部编程(tPP 时间),此时 BUSY 位置 1。

4.3 扇区擦除与块擦除指令

擦除操作是 SPI Flash 写入前必须执行的步骤。Flash 只能将 1 写为 0,擦除操作将整个扇区/块恢复为全 1 (0xFF)。

擦除指令执行流程 发送 WRITE_ENABLE 发送 ERASE 指令 发送 24-bit 地址 CS 拉高 轮询 BUSY 位 (0x05) BUSY=0 表示擦除完成
擦除类型 指令码 擦除大小 典型时间 (tSE/tBE/tCE) 适用场景
SECTOR_ERASE 0x20 4 KB 30~400 ms 小范围数据更新,如配置参数存储
BLOCK_ERASE_32K 0x52 32 KB 120~1600 ms 中等数据块更新,如日志文件
BLOCK_ERASE_64K 0xD8 64 KB 250~3200 ms 大块数据更新,如固件升级
CHIP_ERASE 0xC7 整片 2~20 s 出厂初始化或全片擦除
避坑指南: 擦除操作不可中断。如果在擦除过程中掉电或复位,扇区数据可能处于部分擦除状态(非全 1 也非原数据)。建议在擦除前备份关键数据,或使用双备份策略。

4.4 厂商特定指令

除了标准指令,各厂商会扩展私有指令以实现差异化功能。下表对比了主流厂商的特定指令:

厂商 特定指令 指令码 功能描述
Winbond READ_UNIQUE_ID 0x4B 读取 64-bit 唯一芯片 ID,用于防伪或绑定
Winbond READ_SFDP 0x5A 读取串行 Flash 可发现参数(容量、时序等)
Macronix 4READ 0x13 4 字节地址模式读取(支持 >16MB 容量)
Macronix DEEP_POWER_DOWN 0xB9 进入深度休眠模式(功耗降至 1 µA)
GigaDevice READ_SECURITY_REG 0x48 读取安全寄存器(OTP 区域)
ISSI BURST_READ 0x0C 连续突发读取(无需重复发送地址)
开发建议: 在驱动初始化阶段,通过 READ_ID (0x9F) 指令获取厂商 ID 和设备 ID,然后根据 ID 动态加载对应的厂商特定指令表。这样可以实现一套驱动兼容多款 Flash 芯片。

4.5 指令集架构图

下图展示了 SPI Flash 指令集的完整架构,包括标准指令、厂商扩展指令以及它们与硬件模块的关系:

SPI Flash 指令集架构 SPI 主机 (MCU/SoC) SPI Flash 指令集 标准指令 厂商特定指令 保留/未来扩展 READ WRITE ERASE 状态/ID 唯一 ID SFDP 4 字节地址 深度休眠 Flash 内部状态机 & 存储阵列

4.6 指令集选择策略

在实际驱动开发中,选择合适的指令集需要综合考虑以下因素:

  • 兼容性优先: 优先使用标准指令(READ 0x03、PAGE_PROGRAM 0x02、SECTOR_ERASE 0x20),确保驱动在不同厂商芯片间可移植。
  • 性能优化: 当需要更高读取速度时,使用 FAST_READ (0x0B) 或 DUAL/QUAD READ 指令(如 0x3B、0x6B)。
  • 容量适配: 对于容量超过 16 MB 的 Flash,必须使用 4 字节地址模式指令(如 Macronix 的 0x13)。
  • 功耗管理: 在电池供电设备中,利用 DEEP_POWER_DOWN (0xB9) 指令降低待机功耗。
  • 安全需求: 需要防伪或设备绑定时,使用 READ_UNIQUE_ID (0x4B) 获取芯片唯一标识。
最佳实践: 在驱动代码中维护一个 flash_instruction_set 结构体,包含所有指令码的映射。初始化时通过读取 JEDEC ID 自动填充该结构体,实现驱动与芯片的解耦。
/* 指令集结构体示例 */
typedef struct {
    uint8_t read;           /* 标准读取 */
    uint8_t fast_read;      /* 快速读取 */
    uint8_t page_program