RT-THREAD的SFUD驱动简介基于W25Q128

发布时间 2023-06-19 17:34:13作者: cau_par

SFUD简介

SFUD是一款开源的串行 SPI Flash 通用驱动库。
详细介绍可查看官方说明,作为一个通用的中间套件,帮用户屏蔽了底层的FLASH操作,也方便用户使用不同的FLASH时进行移植。
只需要配置好SPI就可以完成驱动的移植。

FLASH特点

FLASH写的时候,只能从1写到0,而不能从0写到1。因此写之前必须使先写要写地址的字节先重置为FF(即擦除操作),才可以写入数据。
同时擦除的最小单位通常是页(PAGE)或者段(sector),一次写入多为一页,若超过一页需要重新输入页地址后,才可以继续写入数据。
读数据的时候,是可以跨页读取的
相对于EEPROM,FLASH的最大可写次数较小,需要配合软件方法来延长寿命。

W25Q128

容量128M-bit / 16M-byte
65536页(page),每一页包括256-byte
擦除最小单位有三种 4KB(16 Pages), 32KB(128 Pages), 64KB(256 Pages),会根据输入的地址,自动计算出最小分块起始地址进行擦除,并不能指定4K区间的随意起始地址
写操作前,都要需写入写使能操作命令,才可以进写操作(包括擦除)

具体命令(十六进制)

指令 指令码
Write Enable 06h
Write Disable 04h
Read Status Register 05h
Chip Erase C7h/60h
Page Program 02h
Sector Erase(4KB) 20h
Block Erase(32KB) 52h
Block Erase(64KB) D8h
Read Data(32KB) 03h
Fast Read 0Bh
Manufacturer/Device ID 90h
JEDEC ID 9Fh

Read Data与Fast Read的写入地址有些区别,Fast Read需要多写一位dummy数据

读取ID时,不同命令返回的值有些许区别,具体返回值如下图

移植

RT-THREAD STM32环境

在RT-THREAD的项目中,将spi_flash_sfud.c,sfud.c,sfud_sfdp.c这三个文件添加至工程,这个三文件是SFUD的实现,SFUD的底层还要去调用SPI的实现
即spi_core.c与spi_dev.c这两个SPI实现
配置rtconfig.h中使能SPI,还要使用SFUD,同时使能INFO_TABLE,不然初始化的时候SFUD会出错

配置

#define RT_USING_SPI
#define BSP_USING_SPI1

#define RT_USING_SFUD
//#define RT_DEBUG_SFUD
//#define RT_SFUD_USING_SFDP
#define RT_SFUD_USING_FLASH_INFO_TABLE

初始化

由于配置了SPI1,在SPI1初始化之后,先邦定CS引脚,再进行注册(使用rt_sfud_flash_probe),之后就可以使用

  rt_spi_flash_device_t pFlashDev;
  __HAL_RCC_GPIOA_CLK_ENABLE();
  rt_hw_spi_device_attach("spi1", W25Q128_SPI_NAME, GPIOA, GPIO_PIN_4);
  pFlashDev = rt_sfud_flash_probe(W25Q128_DEVICE_NAME, W25Q128_SPI_NAME);

读操作

sfud_flash_t pSfudDev = rt_sfud_flash_find(W25Q128_SPI_NAME);
sfud_read(pSfudDev, tmpAddr, 1, output);

写操作

sfud_flash_t pSfudDev = rt_sfud_flash_find(W25Q128_SPI_NAME);
sfud_write(pSfudDev, tmpAddr, 1, &tmpAddr);

RT-THREAD本身已经很好的支持SFUD,用户只需进行配置就可以使用,帮助用户屏蔽了底层的具体FLASH操作,不过此时用户还要进行分配地址,以及规划如何擦除

非RTOS裸机

部分API讲解

初始化函数,也可以通过其他方式来初始化,像RT-THREAD初始时就没有调用这个接口

sfud_err sfud_init(void);

另一个初始化函数接口,也可以调用这个接口来实现初始化

sfud_err sfud_device_init(sfud_flash *flash);

读数据

sfud_err sfud_read(const sfud_flash *flash, uint32_t addr, size_t size, uint8_t *data);

擦除sector,具体的擦除大小在CHIP_INFO表中已经写了

sfud_err sfud_erase(const sfud_flash *flash, uint32_t addr, size_t size);

写数据,在页面擦除好的基础上,可以直接跨页写,具体的实现已由SFUD来实现了

sfud_err sfud_write(const sfud_flash *flash, uint32_t addr, size_t size, const uint8_t *data);

小结

SFUD移植方便,同时屏蔽了很多底层具体的实现使应用层的代码更加的清晰
不过这个通用驱动库并没有包括FLASH均衡损耗的代码,需要其他的操作来实现这个功能以延长使用寿命,相当于在SFUD上面,再架一层FLASH的管理套件,像EasyFlash