An using JEDEC's SFDP standard serial (SPI) flash universal driver library | 一款使用 JEDEC SFDP 标准的串行 (SPI) Flash 通用驱动库
An using JEDEC's SFDP standard serial (SPI) flash universal driver library | 一款使用 JEDEC SFDP 标准的串行 (SPI) Flash 通用驱动库
SFUD 是一款开源的串行 SPI Flash 通用驱动库。由于现有市面的串行 Flash 种类居多,各个 Flash 的规格及命令存在差异, SFUD 就是为了解决这些 Flash 的差异现状而设计,让我们的产品能够支持不同品牌及规格的 Flash,提高了涉及到 Flash 功能的软件的可重用性及可扩展性,同时也可以规避 Flash 缺货或停产给产品所带来的风险。
/sfud/inc/sfud_flash_def.h ) 中提供的 Flash 参数信息表 中是否支持该款 Flash。如果不支持,则可以在配置文件中添加该款 Flash 的参数信息(添加方法详细见 2.5 添加库目前不支持的 Flash)。获取到了 Flash 的规格参数后,就可以实现对 Flash 的全部操作。下表为所有已在 Demo 平台上进行过真机测试过的 Flash。显示为 不支持 SFDP 标准的 Flash 已经在 Flash 参数信息表中定义,更多不支持 SFDP 标准的 Flash 需要大家以后 共同来完善和维护 (Github|OSChina|Coding) 。
如果觉得这个开源项目很赞,可以点击 项目主页 右上角的 Star ,同时把它推荐给更多有需要的朋友。
| 型号 | 制造商 | 容量 | 最高速度 | SFDP 标准 | QSPI 模式 | 备注 |
|---|---|---|---|---|---|---|
| W25Q40BV | Winbond | 4Mb | 50Mhz | 不支持 | 双线 | 已停产 |
| W25Q80DV | Winbond | 8Mb | 104Mhz | 支持 | 双线 | |
| W25Q16BV | Winbond | 16Mb | 104Mhz | 不支持 | 双线 | by slipperstree |
| W25Q16CV | Winbond | 16Mb | 104Mhz | 支持 | 未测试 | |
| W25Q16DV | Winbond | 16Mb | 104Mhz | 支持 | 未测试 | by slipperstree |
| W25Q32BV | Winbond | 32Mb | 104Mhz | 支持 | 双线 | |
| W25Q64CV | Winbond | 64Mb | 80Mhz | 支持 | 四线 | |
| W25Q128BV | Winbond | 128Mb | 104Mhz | 支持 | 四线 | |
| W25Q256FV | Winbond | 256Mb | 104Mhz | 支持 | 四线 | |
| MX25L3206E | Macronix | 32Mb | 86MHz | 支持 | 双线 | |
| MX25L3233F | Macronix | 32Mb | 133MHz | 支持 | 未测试 | by JiapengLi |
| KH25L4006E | Macronix | 4Mb | 86Mhz | 支持 | 未测试 | by JiapengLi |
| KH25L3206E | Macronix | 32Mb | 86Mhz | 支持 | 双线 | |
| SST25VF016B | Microchip | 16Mb | 50MHz | 不支持 | 不支持 | SST 已被 Microchip 收购 |
| M25P40 | Micron | 4Mb | 75Mhz | 不支持 | 未测试 | by redocCheng |
| M25P80 | Micron | 8Mb | 75Mhz | 不支持 | 未测试 | by redocCheng |
| M25P32 | Micron | 32Mb | 75Mhz | 不支持 | 不支持 | |
| EN25Q32B | EON | 32Mb | 104MHz | 不支持 | 未测试 | |
| GD25Q16B | GigaDevice | 16Mb | 120Mhz | 不支持 | 未测试 | by TanekLiang |
| GD25Q32C | GigaDevice | 32Mb | 120Mhz | 不支持 | 未测试 | by gaupen1186 |
| GD25Q64B | GigaDevice | 64Mb | 120Mhz | 不支持 | 双线 | |
| S25FL216K | Cypress | 16Mb | 65Mhz | 不支持 | 双线 | |
| S25FL032P | Cypress | 32Mb | 104Mhz | 不支持 | 未测试 | by yc_911 |
| S25FL164K | Cypress | 64Mb | 108Mhz | 支持 | 未测试 | |
| A25L080 | AMIC | 8Mb | 100Mhz | 不支持 | 双线 | |
| A25LQ64 | AMIC | 64Mb | 104Mhz | 支持 | 支持 | |
| F25L004 | ESMT | 4Mb | 100Mhz | 不支持 | 不支持 | |
| PCT25VF016B | PCT | 16Mb | 80Mhz | 不支持 | 不支持 | SST 授权许可,会被识别为 SST25VF016B |
| AT45DB161E | ADESTO | 16Mb | 85MHz | 不支持 | 不支持 | ADESTO 收购 Atmel 串行闪存产品线 |
| NM25Q128EV | Nor_Mem | 128Mb | 未测试 | 不支持 | 未测试 | SFDP可能会读取到信息后识别为超过32Gb |
| P25D40H | PUYA | 4Mb | 未测试 | 支持 | 未测试 | by Shan |
| P25Q80H | PUYA | 8Mb | 未测试 | 支持 | 未测试 | by Shan |
注:QSPI 模式中,双线表示支持双线快读,四线表示支持四线快读。
一般情况下,支持四线快读的 FLASH 也支持双线快读。
先说明下本库主要使用的一个结构体 sfud_flash 。其定义位于 /sfud/inc/sfud_def.h。每个 SPI Flash 会对应一个该结构体,该结构体指针下面统称为 Flash 设备对象。初始化成功后在 sfud_flash->chip 结构体中会存放 SPI Flash 的常见参数。如果 SPI Flash 还支持 SFDP ,还可以通过 sfud_flash->sfdp 看到更加全面的参数信息。以下很多函数都将使用 Flash 设备对象作为第一个入参,实现对指定 SPI Flash 的操作。
将会调用 sfud_device_init ,初始化 Flash 设备表中的全部设备。如果只有一个 Flash 也可以只使用 sfud_device_init 进行单一初始化。
注意:初始化完的 SPI Flash 默认都 已取消写保护 状态,如需开启写保护,请使用 sfud_write_status 函数修改 SPI Flash 状态。
sfud_err sfud_init(void)sfud_err sfud_device_init(sfud_flash *flash)| 参数 | 描述 |
|---|---|
| flash | 待初始化的 Flash 设备 |
当 SFUD 开启 QSPI 模式后,SFUD 中的 Flash 驱动支持使用 QSPI 总线进行通信。相比传统的 SPI 模式,使用 QSPI 能够加速 Flash 数据的读取,但当数据需要写入时,由于 Flash 本身的数据写入速度慢于 SPI 传输速度,所以 QSPI 模式下的数据写入速度提升并不明显。
所以 SFUD 对于 QSPI 模式的支持仅限于快速读命令。通过该函数可以配置 Flash 所使用的 QSPI 总线的实际支持的数据线最大宽度,例如:1 线(默认值,即传统的 SPI 模式)、2 线、4 线。
设置后,SFUD 会去结合当前设定的 QSPI 总线数据线宽度,去 QSPI Flash 扩展信息表 中匹配最合适的、速度最快的快速读命令,之后用户在调用 sfud_read() 时,会使用 QSPI 模式的传输函数发送该命令。
sfud_err sfud_qspi_fast_read_enable(sfud_flash *flash, uint8_t data_line_width)| 参数 | 描述 |
|---|---|
| flash | Flash 设备 |
| data_line_width | QSPI 总线支持的数据线最大宽度,例如:1、2、4 |
在 SFUD 配置文件中会定义 Flash 设备表,负责存放所有将要使用的 Flash 设备对象,所以 SFUD 支持多个 Flash 设备同时驱动。设备表的配置在 /sfud/inc/sfud_cfg.h 中 SFUD_FLASH_DEVICE_TABLE 宏定义,详细配置方法参照 2.3 配置方法 Flash)。本方法通过 Flash 设备位于设备表中索引值来返回 Flash 设备对象,超出设备表范围返回 NULL 。
sfud_flash *sfud_get_device(size_t index)| 参数 | 描述 |
|---|---|
| index | Flash 设备位于 FLash 设备表中的索引值 |
sfud_err sfud_read(const sfud_flash *flash, uint32_t addr, size_t size, uint8_t *data)| 参数 | 描述 |
|---|---|
| flash | Flash 设备对象 |
| addr | 起始地址 |
| size | 从起始地址开始读取数据的总大小 |
| data | 读取到的数据 |
注意:擦除操作将会按照 Flash 芯片的擦除粒度(详见 Flash 数据手册,一般为 block 大小。初始化完成后,可以通过
sfud_flash->chip.erase_gran查看)对齐,请注意保证起始地址和擦除数据大小按照 Flash 芯片的擦除粒度对齐,否则执行擦除操作后,将会导致其他数据丢失。
sfud_err sfud_erase(const sfud_flash *flash, uint32_t addr, size_t size)| 参数 | 描述 |
|---|---|
| flash | Flash 设备对象 |
| addr | 起始地址 |
| size | 从起始地址开始擦除数据的总大小 |
sfud_err sfud_chip_erase(const sfud_flash *flash)| 参数 | 描述 |
|---|---|
| flash | Flash 设备对象 |
sfud_err sfud_write(const sfud_flash *flash, uint32_t addr, size_t size, const uint8_t *data)| 参数 | 描述 |
|---|---|
| flash | Flash 设备对象 |
| addr | 起始地址 |
| size | 从起始地址开始写入数据的总大小 |
| data | 待写入的数据 |
注意:擦除操作将会按照 Flash 芯片的擦除粒度(详见 Flash 数据手册,一般为 block 大小。初始化完成后,可以通过
sfud_flash->chip.erase_gran查看)对齐,请注意保证起始地址和擦除数据大小按照 Flash 芯片的擦除粒度对齐,否则执行擦除操作后,将会导致其他数据丢失。
sfud_err sfud_erase_write(const sfud_flash *flash, uint32_t addr, size_t size, const uint8_t *data)| 参数 | 描述 |
|---|---|
| flash | Flash 设备对象 |
| addr | 起始地址 |
| size | 从起始地址开始写入数据的总大小 |
| data | 待写入的数据 |
sfud_err sfud_read_status(const sfud_flash *flash, uint8_t *status)| 参数 | 描述 |
|---|---|
| flash | Flash 设备对象 |
| status | 当前状态寄存器值 |
sfud_err sfud_write_status(const sfud_flash *flash, bool is_volatile, uint8_t status)| 参数 | 描述 |
|---|---|
| flash | Flash 设备对象 |
| is_volatile | 是否为易闪失的,true: 易闪失的,及断电后会丢失 |
| status | 当前状态寄存器值 |
所有配置位于 /sfud/inc/sfud_cfg.h ,请参考下面的配置介绍,选择适合自己项目的配置。
打开/关闭 SFUD_DEBUG_MODE 宏定义
打开/关闭 SFUD_USING_SFDP 宏定义
注意:关闭后只会查询该库在
/sfud/inc/sfud_flash_def.h中提供的 Flash 信息表。这样虽然会降低软件的适配性,但减少代码量。
打开/关闭 SFUD_USING_FAST_READ 宏定义。许多Flash的读模式可能并不能满足较高的SPI频率(具体可查阅各Flash的数据手册交流特性部分),此时需要使能快速读模式。
注意:由于快速读模式在读时插入了默认一个空字节,在SPI速率较慢时可能相较于读模式速度更慢。
打开/关闭 SFUD_USING_FLASH_INFO_TABLE 宏定义
注意:关闭后该库只驱动支持 SFDP 规范的 Flash,也会适当的降低部分代码量。另外 2.3.2 及 2.3.3 这两个宏定义至少定义一种,也可以两种方式都选择。
为了进一步降低代码量,SFUD_USING_SFDP 与 SFUD_USING_FLASH_INFO_TABLE 也可以 都不定义 。
此时,只要在定义 Flash 设备时,指定好 Flash 参数,之后再调用 sfud_device_init 对该设备进行初始化。参考如下代码:
sfud_flash sfud_norflash0 = {
.name = "norflash0",
.spi.name = "SPI1",
.chip = { "W25Q64FV", SFUD_MF_ID_WINBOND, 0x40, 0x17, 8L * 1024L * 1024L, SFUD_WM_PAGE_256B, 4096, 0x20 } };
......
sfud_device_init(&sfud_norflash0);
......如果产品中存在多个 Flash ,可以添加 Flash 设备表。修改 SFUD_FLASH_DEVICE_TABLE 这个宏定义,示例如下:
暂无开放 Issues,或尚未同步最近议题。