SFUD之W25Q16

(一)裸机使用

1. SFUD SFDP

在这里插入图片描述
SFUD :SPI通用驱动库
SFDP : 固态技术协会技术标准

2. 宏配置 占用大小

在这里插入图片描述
两个宏定义都打开,但是优先支持SFDP。
18864 + 3060 = 21924

关闭#define SFUD_USING_SFDP
Program Size: Code=15708 RO-data=2036 RW-data=104 ZI-data=2568
15708 + 2036 = 17744
比上面少了4180

关闭#define SFUD_USING_FLASH_INFO_TABLE
Program Size: Code=15568 RO-data=1312 RW-data=104 ZI-data=2568
15568 + 1312 = 16880
比上面少了864

#ifndef _SFUD_CFG_H_
#define _SFUD_CFG_H_

// 调试模式
#define SFUD_DEBUG_MODE

//SFUD会对支持SFDP的标准FLASH进行初始化
//支持SFDP的FLASH设备会把'S'、'F'、'D'、'P'这四个字符以及SFDP的版本号按顺序放在FLASH的某8个字节空间里
//#define SFUD_USING_SFDP

//是否使用该库自带的 Flash 参数信息表
//SFUD会根据用户在sfud_flash_def中SFUD_FLASH_CHIP_TABLE中定义的FLASH参数表来完成对FLASH的初始化
#define SFUD_USING_FLASH_INFO_TABLE

// QSPI 模式
//#define SFUD_USING_QSPI

//FLASH设备表
enum {
    SFUD_W25_DEVICE_INDEX = 0,
};

#define SFUD_FLASH_DEVICE_TABLE                                                \
{                                                                              \
    [SFUD_W25_DEVICE_INDEX] = {.name = "W25Q16", .spi.name = "SPI1"},       \
}

#endif /* _SFUD_CFG_H_ */

3. 信息表内容

使用的W25Q16信息

读ID(0x9F),这里可以读出三种ID,第一个是制造商ID,第二个是存储器类型ID,第三个是容量ID

| 名称 | 制造商 ID | 类型 ID | 容量 ID | 容量 | 写模式 | 擦除粒度(擦除的最小单位) | 擦除粒度对应的命令 | 。

SFUD_WM_PAGE_256B = 1 << 0,                            /**< write 1 to 256 bytes per page */
#define SFUD_MF_ID_WINBOND                             0xEF
{"W25Q16BV", SFUD_MF_ID_WINBOND, 0x40, 0x15, 2L*1024L*1024L, SFUD_WM_PAGE_256B, 4096, 0x20},

0xEF 0X40 0X15

4. 移植注意:

  1. sfud_port.c 里面的接口文件
    移植文件位于 /sfud/port/sfud_port.c ,文件中的 sfud_err sfud_spi_port_init(sfud_flash *flash) 方法是库提供的移植方法,在里面完成各个设备 SPI 读写驱动(必选)、重试次数(必选)、重试接口(可选)及 SPI 锁(可选)的配置。更加详细的移植内容,可以参考 demo 中的各个平台的移植文件
  2. sfud_cfg.h 里面的宏定义开关

主函数初始化和使用

    /* SFUD initialize */
    if (sfud_init() == SFUD_SUCCESS) {
        sfud_demo(0, sizeof(sfud_demo_test_buf), sfud_demo_test_buf);
    }

注意这个,第一次读ID之前需要判断是否繁忙

        /* read JEDEC ID include manufacturer ID, memory type ID and flash capacity ID */
		//读ID之前判断忙
    	wait_busy(flash);
        result = read_jedec_id(flash);

接口文件里实现的读写

    	switch (flash->index) {
    	case SFUD_W25_DEVICE_INDEX: {

    			/* 同步 Flash 移植所需的接口及数据 */
    			flash->spi.wr = spi_write_read;
    			flash->spi.lock = spi_lock;
    			flash->spi.unlock = spi_unlock;
    			flash->spi.user_data = &user_spi;
    			/* about 100 microsecond delay */
    			flash->retry.delay = retry_delay_nop;
    			/* adout 60 seconds timeout */
    			flash->retry.times = 60 * 10000;

    			break;
    		}
        }

用户延时函数

/*  delay */
static void retry_delay_nop(void) {
    uint32_t delay1 = 1000*1000;

    while(delay1--)
    {
		__NOP();
    }
}

片选拉低后需要给点时间

	HAL_GPIO_WritePin(spi_dev->cs_gpiox, spi_dev->cs_gpio_pin, GPIO_PIN_RESET);
	retry_delay_nop();

更改上面两个文件后可以使用

实际使用

未添加工程 10.7K
添加SFUD初始化和读写 21.54K
可以看到这个占用还是很大的
这个容量在BOOT中是不接受的
成功放弃

使用普通的自定义驱动函数
实现读写擦除等 14.66K
4K左右
可以接受
使用这种方式

关于DSPI QSPI

SPI : 4线,MOSI MISO 输出输入
DSPI : 4线, MOSI MISO 两个可做输出也可做输入, 例如输出+输出
QSPI: 6线,WP和HOLD线,也变成了数据线,
参考链接
链接地址

(二) RT_thread使用

  1. 配置软件包参数
    在这里插入图片描述
  2. 在CUBEMX配置SPI 1的参数,使用软件片选,片选引脚不配置
  3. 在board.h中配置开启 #define BSP_USING_SPI1
  4. 在drv_spi.c中看到SPI的配置
    在这里插入图片描述
    在RTthread资源文件目录使用文件搜索工具
    找一个spi_config.h的文件添加到工程里面
    在这里插入图片描述
  5. 在开机初始化时候会调用rt_hw_spi_init
    函数中主要将spi1 注册到spi_bus中
  6. 在drv_spi.c中还有rt_hw_spi_device_attach函数。
  7. 这个函数需要传入总线名称、设备名称、SPI的CS脚信息
    总结:先注册spi1 总线设备,然后注册spi中层设备,然后设置片选引脚
    然后把spi1总线和spi中层设备绑定
    最后使用SFUD把spi中层设备绑定
    第一层 spi设备
    第二层 spi使用设备
    第三层 SFUD
rt_sfud_flash_probe("W25Q", "spi1.0"))
>
rt_sfud_flash_probe_ex
>
/* initialize SFUD device */
if (sfud_device_init(sfud_dev) != SFUD_SUCCESS) 
>
hardware_init
>
sfud_spi_port_init
>

  1. sfud_init
  2. sfud_device_init(&flash_table[i]);
  3. hardware_init(flash);+ software_init(flash);
  4. sfud_spi_port_init(flash);
   	case SFUD_W25_DEVICE_INDEX: {

   			/* 同步 Flash 移植所需的接口及数据 */
   			flash->spi.wr = spi_write_read;
   			flash->spi.lock = spi_lock;
   			flash->spi.unlock = spi_unlock;
   			flash->spi.user_data = &user_spi;
   			/* about 100 microsecond delay */
   			flash->retry.delay = retry_delay_nop;
   			/* adout 60 seconds timeout */
   			flash->retry.times = 60 * 10000;

   			break;
   		}
  • 13
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值