SFUD
An using JEDEC's SFDP standard serial (SPI) flash universal driver library | 一款使用 JEDEC SFDP 标准的串行 (SPI) Flash 通用驱动库
Install / Use
/learn @armink/SFUDREADME
SFUD (Serial Flash Universal Driver) 串行 Flash 通用驱动库
0、SFUD 是什么
SFUD 是一款开源的串行 SPI Flash 通用驱动库。由于现有市面的串行 Flash 种类居多,各个 Flash 的规格及命令存在差异, SFUD 就是为了解决这些 Flash 的差异现状而设计,让我们的产品能够支持不同品牌及规格的 Flash,提高了涉及到 Flash 功能的软件的可重用性及可扩展性,同时也可以规避 Flash 缺货或停产给产品所带来的风险。
- 主要特点:支持 SPI/QSPI 接口、面向对象(同时支持多个 Flash 对象)、可灵活裁剪、扩展性强、支持 4 字节地址
- 资源占用
- 标准占用:RAM:0.2KB ROM:5.5KB
- 最小占用:RAM:0.1KB ROM:3.6KB
- 设计思路:
- 什么是 SFDP :它是 JEDEC (固态技术协会)制定的串行 Flash 功能的参数表标准,最新版 V1.6B (点击这里查看)。该标准规定了,每个 Flash 中会存在一个参数表,该表中会存放 Flash 容量、写粒度、擦除命令、地址模式等 Flash 规格参数。目前,除了部分厂家旧款 Flash 型号会不支持该标准,其他绝大多数新出厂的 Flash 均已支持 SFDP 标准。所以该库在初始化时会优先读取 SFDP 表参数。
- 不支持 SFDP 怎么办 :如果该 Flash 不支持 SFDP 标准,SFUD 会查询配置文件 (
/sfud/inc/sfud_flash_def.h) 中提供的 Flash 参数信息表 中是否支持该款 Flash。如果不支持,则可以在配置文件中添加该款 Flash 的参数信息(添加方法详细见 2.5 添加库目前不支持的 Flash)。获取到了 Flash 的规格参数后,就可以实现对 Flash 的全部操作。
1、为什么选择 SFUD
- 避免项目因 Flash 缺货、Flash 停产或产品扩容而带来的风险;
- 越来越多的项目将固件存储到串行 Flash 中,例如:ESP8266 的固件、主板中的 BIOS 及其他常见电子产品中的固件等等,但是各种 Flash 规格及命令不统一。使用 SFUD 即可避免,在相同功能的软件平台基础下,无法适配不同 Flash 种类的硬件平台的问题,提高软件的可重用性;
- 简化软件流程,降低开发难度。现在只需要配置好 SPI 通信,即可畅快的开始玩串行 Flash 了;
- 可以用来制作 Flash 编程器/烧写器
2、SFUD 如何使用
2.1 已支持 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 也支持双线快读。
2.2 API 说明
先说明下本库主要使用的一个结构体 sfud_flash 。其定义位于 /sfud/inc/sfud_def.h。每个 SPI Flash 会对应一个该结构体,该结构体指针下面统称为 Flash 设备对象。初始化成功后在 sfud_flash->chip 结构体中会存放 SPI Flash 的常见参数。如果 SPI Flash 还支持 SFDP ,还可以通过 sfud_flash->sfdp 看到更加全面的参数信息。以下很多函数都将使用 Flash 设备对象作为第一个入参,实现对指定 SPI Flash 的操作。
2.2.1 初始化 SFUD 库
将会调用 sfud_device_init ,初始化 Flash 设备表中的全部设备。如果只有一个 Flash 也可以只使用 sfud_device_init 进行单一初始化。
注意:初始化完的 SPI Flash 默认都 已取消写保护 状态,如需开启写保护,请使用 sfud_write_status 函数修改 SPI Flash 状态。
sfud_err sfud_init(void)
2.2.2 初始化指定的 Flash 设备
sfud_err sfud_device_init(sfud_flash *flash)
|参数 |描述| |:----- |:----| |flash |待初始化的 Flash 设备|
2.2.3 使能快速读模式(仅当 SFUD 开启 QSPI 模式后可用)
当 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 |
2.2.4 获取 Flash 设备对象
在 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 设备表中的索引值|
2.2.5 读取 Flash 数据
sfud_err sfud_read(const sfud_flash *flash, uint32_t addr, size_t size, uint8_t *data)
|参数 |描述| |:----- |:----| |flash |Flash 设备对象| |addr |起始地址| |size |从起始地址开始读取数据的总大小| |data |读取到的数据|
2.2.6 擦除 Flash 数据
注意:擦除操作将会按照 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 |从起始地址开始擦除数据的总大小|
2.2.7 擦除 Flash 全部数据
sfud_err sfud_chip_erase(const sfud_flash *flash)
|参数 |描述| |:----- |:----| |flash |Flash 设备对象|
2.2.8 往 Flash 写数据
sfud_err sfud_write(const sfud_flash *flash, uint32_t addr, size_t size, const uint8_t *data)
|参数 |描述| |:----- |:----| |flash |Flash 设备对象| |addr |起始地址| |size |从起始地址开始写入数据的总大小| |data |待写入的数据|
2.2.9 先擦除再往 Flash 写数据
注意:擦除操作将会按照 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
