RT-THREAD的SFUD驱动简介基于W25Q128
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