RT-Thread:SPI万能驱动 SFUD 驱动Flash W25Q64,通过 STM32CubeMX 配置 STM32 SPI 驱动

关键词:SFUD,FLASH,W25Q64,W25Q128,STM32F407

说明:RT-Thread 系统 使用 SPI万能驱动 SFUD 驱动 Flash W25Q64,通过 STM32CubeMX 配置 STM32 SPI 驱动。

提示:SFUD添加后的存储位置

1.打开RT-Thread Setting SPI SFUD

打开 SFUD ,SPI

右键-详细配置

SFUD的配置 放置于如下头文件 rtconfig.h

2.开启board.h/stm32F1xx_hal_config.h中关于SPI的宏定义

STEP 1:第一步打开RT-Thread Setting SPI SFUD 中已经操作实现。

STEP 2:定义与spi总线相关的宏,例如#define BSP_USING_SPI1

STEP 4:修改您的stm32xxxx_hal_config.h文件以支持spi外围设备。 定义与外围设备相关的宏,例如#define HAL_SPI_MODULE_ENABLED

STEP 3:将由stm32cubemx生成的stm32xxxx_hal_msp.c的spi init函数复制到board.c文件的末尾,例如void HAL_SPI_MspInit(SPI_HandleTypeDef * hspi)

如下复制过程,将由stm32cubemx生成的 SPI 驱动部分代码全部复制到 board.c文件的末尾

3.stm32cubemx SPI 驱动生成过程

如何打开 stm32cubemx 建工程的过程就不讲解,直接讲关于SPI的配置过程

根据对应的STM32芯片打开一个工程配置SPI部分

时钟配置

时钟树配置

SPI接口设置

输出项目设置

代码生成器 设置

生成代码

打开文件夹

SPI.C文件夹内便是生成的关于SPI接口的配置驱动代码

4.编译烧录后 发送命令 list_device 可以看到SPI总线 SPI1 已经注册到系统

5.SPI从设备驱动编写

SPI的总线设备已经注册完毕,接下来需要进行SPI从设备驱动编写,这里直接使用开发板板载的SPI Flash W25Q64进行测试,

新建 w25q_test.c

cpp 复制代码
#include <rtthread.h>
#include <board.h>
#include <rtdevice.h>
#include "drv_spi.h"
#include "spi_flash_sfud.h"

static int rt_hw_spi_flash_init(void)
{
    __HAL_RCC_GPIOB_CLK_ENABLE();
    rt_hw_spi_device_attach("spi1", "spi10", GPIOC, GPIO_PIN_0);// spi10 表示挂载在 spi3 总线上的 0 号设备,PC0是片选,这一步就可以将从设备挂在到总线中。

    if (RT_NULL == rt_sfud_flash_probe("W25Q64", "spi10"))  //注册块设备,这一步可以将外部flash抽象为系统的块设备
    {
        return -RT_ERROR;
    };

    return RT_EOK;
}
/* 导出到自动初始化 */
INIT_COMPONENT_EXPORT(rt_hw_spi_flash_init);

不支持 SFDP 标准的 Flash 已经在 Flash 参数信息表中定义,sfud_flash_def.h 文件有关于 flash 芯片的配置信息,配置中有的型号可以直接定义使用;配置中没有,且不支持SFDP的Flash 可以自己添加。

**注意:**上述代码中的 "W25Q64" 与下截图的型号无关,进过测试,将"W25Q64" 改为"W25Q664" 编译烧录后,串口打印的数据任然一样,打印信息是 SFUD 自动探测读出的 Flash 的信息。具体原理不清楚。

编译后烧录,串口会显示 FLASH 的注册信息

SFUD打印了 基本Flash参数表信息

cpp 复制代码
 \ | /
- RT -     Thread Operating System
 / | \     4.0.2 build Jul  3 2020
 2006 - 2019 Copyright by rt-thread team
[SFUD] (../rt-thread/components/drivers/spi/sfud/src/sfud.c:862) The flash device manufacturer ID is 0xEF, memory type ID is 0x40, capacity ID is 0x17.
[SFUD] (../rt-thread/components/drivers/spi/sfud/src/sfud_sfdp.c:132) Check SFDP header is OK. The reversion is V1.5, NPN is 0.
[SFUD] (../rt-thread/components/drivers/spi/sfud/src/sfud_sfdp.c:175) Check JEDEC basic flash parameter header is OK. The table id is 0, reversion is V1.5, length is 16, parameter table pointer is 0x000080.
[SFUD] (../rt-thread/components/drivers/spi/sfud/src/sfud_sfdp.c:203) JEDEC basic flash parameter table info:
[SFUD] (../rt-thread/components/drivers/spi/sfud/src/sfud_sfdp.c:204) MSB-LSB  3    2    1    0
[SFUD] (../rt-thread/components/drivers/spi/sfud/src/sfud_sfdp.c:207) [0001] 0xFF 0xF9 0x20 0xE5
[SFUD] (../rt-thread/components/drivers/spi/sfud/src/sfud_sfdp.c:207) [0002] 0x03 0xFF 0xFF 0xFF
[SFUD] (../rt-thread/components/drivers/spi/sfud/src/sfud_sfdp.c:207) [0003] 0x6B 0x08 0xEB 0x44
[SFUD] (../rt-thread/components/drivers/spi/sfud/src/sfud_sfdp.c:207) [0004] 0xBB 0x42 0x3B 0x08
[SFUD] (../rt-thread/components/drivers/spi/sfud/src/sfud_sfdp.c:207) [0005] 0xFF 0xFF 0xFF 0xFE
[SFUD] (../rt-thread/components/drivers/spi/sfud/src/sfud_sfdp.c:207) [0006] 0x00 0x00 0xFF 0xFF
[SFUD] (../rt-thread/components/drivers/spi/sfud/src/sfud_sfdp.c:207) [0007] 0xEB 0x40 0xFF 0xFF
[SFUD] (../rt-thread/components/drivers/spi/sfud/src/sfud_sfdp.c:207) [0008] 0x52 0x0F 0x20 0x0C
[SFUD] (../rt-thread/components/drivers/spi/sfud/src/sfud_sfdp.c:207) [0009] 0x00 0x00 0xD8 0x10
[SFUD] (../rt-thread/components/drivers/spi/sfud/src/sfud_sfdp.c:215) 4 KB Erase is supported throughout the device. Command is 0x20.
[SFUD] (../rt-thread/components/drivers/spi/sfud/src/sfud_sfdp.c:234) Write granularity is 64 bytes or larger.
[SFUD] (../rt-thread/components/drivers/spi/sfud/src/sfud_sfdp.c:245) Target flash status register is non-volatile.
[SFUD] (../rt-thread/components/drivers/spi/sfud/src/sfud_sfdp.c:271) 3-Byte only addressing.
[SFUD] (../rt-thread/components/drivers/spi/sfud/src/sfud_sfdp.c:305) Capacity is 8388608 Bytes.
[SFUD] (../rt-thread/components/drivers/spi/sfud/src/sfud_sfdp.c:312) Flash device supports 4KB block erase. Command is 0x20.
[SFUD] (../rt-thread/components/drivers/spi/sfud/src/sfud_sfdp.c:312) Flash device supports 32KB block erase. Command is 0x52.
[SFUD] (../rt-thread/components/drivers/spi/sfud/src/sfud_sfdp.c:312) Flash device supports 64KB block erase. Command is 0xD8.
[SFUD] Find a Winbond flash chip. Size is 8388608 bytes.
[SFUD] (../rt-thread/components/drivers/spi/sfud/src/sfud.c:840) Flash device reset success.
[SFUD] W25Q64 flash device is initialize success.
[SFUD] Probe SPI flash W25Q64 by SPI device spi10 success.
msh >

6.SFUD命令介绍

通过串口发送 sf 命令,可以查到关于 SFUD 系统的命令,可以通过命令对Flash进行读写、擦除等操作。

cpp 复制代码
msh >sf
Usage:
sf probe [spi_device]           - probe and init SPI flash by given 'spi_device'
sf read addr size               - read 'size' bytes starting at 'addr'
sf write addr data1 ... dataN   - write some bytes 'data' to flash starting at 'addr'
sf erase addr size              - erase 'size' bytes starting at 'addr'
sf status [<volatile> <status>] - read or write '1:volatile|0:non-volatile' 'status'
sf bench                        - full chip benchmark. DANGER: It will erase full chip!
cpp 复制代码
sf probe [spi_device]           - 探测命令:使用如 sf probe spi10 ,就能探测到挂载的spi10设备
sf read addr size               - 读flash:使用如 sf read 00 100 ,表示从地址00开始读100个字节
sf write addr data1 ... dataN   - 写flash:使用如 sf write 17 01 02 03 04 05 06 07 08 09 10 11 ,表示从17地址开始写入后面这些数据
sf erase addr size              - 擦除命令:
sf status [<volatile> <status>] - 查询状态:查询状态寄存器的值
                        - 全芯片基准测试。 危险:它将擦除整个芯片!

7.SFUD 测试程序

cpp 复制代码
#include "user_cfg.h"

/*
W25Q128介绍
W25Q128是华邦公司推出的大容量SPI FLASH产品,W25Q128的容量为128M bit,该系列还有W25Q80/16/32/64等。
W25Q128将16M的容量分为256个块(Block),每个块大小为64K字节,每个块又分为16个扇区(Sector),每个扇区4K个字节。
W25Q128的最小擦除单位为一个扇区,也就是每次必须擦除4K个字节。这样我们需要给W25Q128开辟一个至少4K的缓存区,这样对SRAM要求比较高,要求芯片必须有4K以上SRAM才能很好的操作。
W25Q128的擦写周期多达10W次,具有20年的数据保存期限,支持电压为2.7~3.6V,
W25Q128支持标准的SPI,还支持双输出/四输出的SPI,最大SPI时钟可以到80Mhz(双输出时相当于160Mhz,四输出时相当于320M),更多的W25Q128的介绍,请参考W25Q128的DATASHEET。
 */


/* SPI Flash 驱动 */
static int rt_hw_spi_flash_init(void)
{
    //__HAL_RCC_GPIOB_CLK_ENABLE();
    /* 往总线 spi1 上挂载一个 spi10 从设备 */
    rt_hw_spi_device_attach("spi1", "spi10", GPIOA, GPIO_PIN_4);/*spi10 表示挂载在 spi3 总线上的 0 号设备,PC0是片选,这一步就可以将从设备挂在到总线中。*/

    /* 使用 SFUD 探测 spi10 从设备,并将 spi10 连接的 flash 初始化为块设备,名称 W25Q64DW */
    if (RT_NULL == rt_sfud_flash_probe("W25Q128JV", "spi10"))  /* 注册块设备,这一步可以将外部flash抽象为系统的块设备*/
    {
        return -RT_ERROR;
    };

    return RT_EOK;
}
/* 导出到自动初始化 */
INIT_COMPONENT_EXPORT(rt_hw_spi_flash_init);



void W25Q_Flash_test(void)
{
    sfud_err result;
    uint8_t *read_data;  // 读取到的数据
    uint8_t *write_data; // 将要写入的数据
    sfud_flash *sfud_dev = NULL;

    sfud_dev = rt_sfud_flash_find("spi10"); // 获取 sfud_dev
    // 或者 sfud_dev = rt_sfud_flash_find_by_dev_name("W25Q128");

    /*擦除 Flash 数据;flash: Flash 设备对象;addr:起始地址;size:从起始地址开始擦除数据的总大小*/
    sfud_erase(sfud_dev, 0, 1024);           // 擦除从 0 开始的 4096 字节

    write_data = rt_malloc(4096);              // 内存申请,函数会从系统堆空间中找到合适大小的内存块,然后把内存块可用地址返回给用户。
    rt_memset(write_data, 1, 4096);            // 作用是在一段内存块中填充某个给定的值,将  write_data 32 个地址填入1

    /*往 Flash 写数据:flash:Flash 设备对象;addr:起始地址;size:从起始地址开始写入数据的总大小;data:待写入的数据*/
    sfud_write(sfud_dev, 0, 4096, write_data); // 将数据 32 字节的 write_data 从 0 开始写入 flash

    read_data = rt_malloc(4096);
    rt_memset(read_data, 0, 4096);
    for (uint16_t var = 0; var < 4096; ++var)
    {
        rt_kprintf("var = %d ,data = %d \n",var,read_data[var]) ;
    }

    /*读取 Flash 数据; flash: Flash 设备对象 ;addr: 起始地址;size:从起始地址开始读取数据的总大小;data:读取到的数据*/
    sfud_read(sfud_dev, 0, 4096, read_data);   // 读取从 0 开始的 32 字节,存入 read_data

    for (uint16_t var = 0; var < 4096; ++var)
    {
        rt_kprintf("var = %d ,data = %d \n",var,read_data[var]) ;
    }
}
相关推荐
智商偏低3 小时前
单片机之helloworld
单片机·嵌入式硬件
青牛科技-Allen4 小时前
GC3910S:一款高性能双通道直流电机驱动芯片
stm32·单片机·嵌入式硬件·机器人·医疗器械·水泵、
森焱森6 小时前
无人机三轴稳定控制(2)____根据目标俯仰角,实现俯仰稳定化控制,计算出升降舵输出
c语言·单片机·算法·架构·无人机
白鱼不小白6 小时前
stm32 USART串口协议与外设(程序)——江协教程踩坑经验分享
stm32·单片机·嵌入式硬件
S,D7 小时前
MCU引脚的漏电流、灌电流、拉电流区别是什么
驱动开发·stm32·单片机·嵌入式硬件·mcu·物联网·硬件工程
芯岭技术10 小时前
PY32F002A单片机 低成本控制器解决方案,提供多种封装
单片机·嵌入式硬件
youmdt10 小时前
Arduino IDE ESP8266连接0.96寸SSD1306 IIC单色屏显示北京时间
单片机·嵌入式硬件
嘿·嘘11 小时前
第七章 STM32内部FLASH读写
stm32·单片机·嵌入式硬件
Meraki.Zhang11 小时前
【STM32实践篇】:I2C驱动编写
stm32·单片机·iic·驱动·i2c
几个几个n13 小时前
STM32-第二节-GPIO输入(按键,传感器)
单片机·嵌入式硬件