片外合封Flash的SFDP介绍
SFDP基本概念
SFDP (Serial Flash Discoverable Parameters) 是JEDEC组织定义的一种标准规范(JEDEC标准JESD216系列),用于自动发现和识别串行Flash存储器的特性和功能参数。这个标准最初在2010年发布,后来经历了多次修订和扩展。
SFDP的主要作用
SFDP解决了一个关键问题:随着Flash厂商、型号和功能的多样化,MCU或SoC需要一种通用方法来识别和正确操作不同的Flash芯片。SFDP提供了一种标准化机制,允许系统在启动时自动查询Flash芯片的详细参数,而非依赖硬编码信息。
SFDP工作原理
- 标准化参数表: Flash芯片内部包含一组参数表,存储在特定地址
- 标准化读取命令: 系统通过0x5A命令读取这些参数表
- 参数组织结构: 数据按照标准化格式组织,包括标题和参数描述符
SFDP包含的主要信息
SFDP参数表包含多种信息,主要有:
-
基本Flash参数:
- 存储容量信息
- 擦除命令和擦除块大小选项
- 读取指令(包括快速读取、双/四线读取等)
- 写入指令和页大小
-
高级Flash功能:
- 4-byte寻址支持与切换方法
- 扇区保护机制
- 状态寄存器位定义
- 休眠/唤醒功能
- 双/四线操作模式参数
SFDP结构体的C语言实现
根据JEDEC标准中的SFDP头结构规范,下面是对应的C语言结构体实现:
// SFDP 标头结构体
typedef struct {
uint32_t signature; // SFDP签名,固定为 0x50444653 ("SFDP"),字节顺序为"S", "F", "D", "P"
uint8_t minor_revision; // SFDP次版本号
uint8_t major_revision; // SFDP主版本号
uint8_t num_param_headers; // 参数头数量(NPH)
uint8_t access_protocol; // 访问协议
} SFDP_Header_t;
// SFDP 参数头描述符结构体
typedef struct {
uint8_t param_id_lsb; // 参数ID低字节 (例如:JEDEC基本表为0x00)
uint8_t param_minor_revision; // 参数表次版本
uint8_t param_major_revision; // 参数表主版本
uint8_t param_length; // 参数表长度(以双字(DWORD)为单位)
uint8_t param_id_msb; // 参数ID高字节 (例如:JEDEC基本表为0xFF)
uint8_t reserved[3]; // 保留字节或作为地址的一部分
uint32_t param_table_pointer; // 参数表指针(字节地址)
} SFDP_Parameter_Header_t;
// 完整SFDP结构 (包含头和参数头数组)
typedef struct {
SFDP_Header_t header;
SFDP_Parameter_Header_t param_headers[16]; // 假设最多16个参数头
} SFDP_Structure_t;
// 读取SFDP的函数示例
void Read_SFDP_Structure(QSPI_HandleTypeDef *hqspi, SFDP_Structure_t *sfdp_struct) {
uint8_t cmd = 0x5A; // SFDP读取命令
uint32_t address = 0; // SFDP起始地址
uint32_t dummy_cycles = 8; // 典型值,可能因Flash芯片而异
uint8_t data_mode = QSPI_DATA_1_LINE; // 单线读取模式
// 读取SFDP头(8字节)
HAL_QSPI_Command(hqspi, &cmd, address, dummy_cycles, data_mode);
HAL_QSPI_Receive(hqspi, (uint8_t *)&sfdp_struct->header, sizeof(SFDP_Header_t));
// 验证SFDP签名
if(sfdp_struct->header.signature != 0x50444653) {
// 签名不匹配,处理错误
return;
}
// 读取参数头
for(uint8_t i = 0; i < sfdp_struct->header.num_param_headers && i < 16; i++) {
address = 0x08 + (i * 8); // 每个参数头8字节,从地址0x08开始
HAL_QSPI_Command(hqspi, &cmd, address, dummy_cycles, data_mode);
HAL_QSPI_Receive(hqspi, (uint8_t *)&sfdp_struct->param_headers[i],
sizeof(SFDP_Parameter_Header_t));
}
}
注意事项:
- SFDP结构中有严格的字节序要求,实现时需注意字节对齐和大小端问题
- 实际参数表内容(如基本参数表、4字节地址表等)需要单独定义结构体
- 函数
Read_SFDP_Structure
是示例实现,实际应用中需要根据具体的STM32硬件和HAL库函数进行调整 - 不同版本的SFDP标准(JESD216/A/B/C/D/E/F)可能有不同的结构细节,需要灵活处理
这个结构体实现与JEDEC标准图10中的整体头结构一致,可以用于解析片外Flash存储器的SFDP信息。
SFDP的优势
- 提高兼容性: 使系统能够适应不同厂商的Flash器件
- 简化设计: 无需为每种Flash存储硬编码参数
- 自动配置: 系统可以根据读取的参数自动优化访问模式
- 支持未来扩展: 新的Flash特性可以通过扩展参数表添加
STM32平台使用SFDP
在STM32系统中,可以利用SFDP自动配置QSPI或OSPI接口通信参数,以获取最佳性能。STM32 HAL库中通常包含SFDP解析函数,可用于读取并应用Flash参数。
SFDP标准演进
JEDEC的SFDP标准已经从最初的JESD216发展到JESD216D/E/F等版本,每个版本都增加了对新Flash功能的支持,如XIP(eXecute In Place)、OPI(Octal Peripheral Interface)模式、更高速率等。
SFDP是现代片外合封Flash设计的重要组成部分,显著提升了系统设计的灵活性和兼容性。