从本文开始,测试学习一些 RT-Thread 常用的组件与软件包,先从刚学完的 SPI 设备开始。

前言

RT-专栏目前已更新。 从开发环境到内核再到设备模型,我们其实已经讲完了使用RT-的基础知识。 认真学习的朋友其实可以用RT-完成一些实用的小项目。

正如上一篇文章末尾提到的找sf,RT-的一大特点就是它的生态比普通RTOS更加完整。 在实际应用中,我们有很多官方或者很多开发者提供的现成的组件或者软件包。 我们可以直接导入项目来使用。

对于我们RT的实际应用,很多时候我们不仅需要了解基础理论,还需要知道如何实际“使用”它。

基于本专栏的开发环境RT-,我们将通过测试几个典型的组件和软件包来开始本文,看看它们的实际使用情况。

我们刚刚讲完了SPI设备,本文将从SFUD组件开始,这是一个与SPI设备相关的组件。

注意,对于RT-中有关组件和软件包的文章,我不打算过多谈论原理,因为我们的最终目标仍然是应用。

在讲解RT-基础知识的过程中,为了让大家更好的理解RT-和I/O设备模型,对源码进行了分析,并讲解了实现原理。 核心部分就是自己研究源码。

对于组件和软件包,我会重点记录测试使用过程,以便我们快速上手。

本RT-专栏记录的开发环境:

RT-(1. RT-版本、RT-开发环境和快速启动开发)

RT-(2.RT-启动流程-启动文件及源码分析)

RT-内核系列博文链接:

RT-(三、RT-线程操作功能及线程管理对比)

RT-录音(四、RT-时钟节拍和软件定时器)

RT-(5.RT-临界区保护)

RT-(6.IPC机制信号量、互斥量和事件集)

RT-(7.IPC机制邮箱、消息队列)

RT-记录(8.了解RT-内存管理)

RT-录制(9. RT-中断处理和阶段总结)

使用 RT 应用程序系列博客文章链接:

RT-应用-使用RT-on(1.无线温湿度传感器新建项目)

RT-应用-在网上使用RT-(二、无线温湿度传感器的配置)

RT-应用-使用RT-on(3.无线温湿度传感器的I2C通信)

RT-应用-使用RT-on(4.无线温湿度传感器的串行通信)

RT-应用—在网上使用RT-(五、无线温湿度传感器完成章节)(附源代码)

RT-设备系列博文链接:

RT-(10.全面了解RT-I/O设备模型)

RT-(11.I/O设备模型的UART设备-源码分析)

RT-(12.I/O设备模型的UART设备-使用测试)

RT-(13.I/O设备型号的PIN设备)

RT-(14.I/O设备模型的ADC设备)

RT-(15.I/O设备模型的SPI设备)

RT-组件和软件包系列博客链接:

这篇文章是之一篇

1. SFUD组件介绍

SFUD(全称Flash)是一个开源的串行SPI Flash通用驱动库。

1.1 基本介绍

基本介绍借用官方的描述:由于市面上串行Flash的种类很多,每种Flash的规格和命令都不同。 SFUD旨在解决这些Flash之间的差异,使我们的产品可以支持不同的品牌和规格。 Flash提高了涉及Flash功能的软件的复用性和可扩展性,也可以避免Flash缺货或停产给产品带来的风险。

在RT-中,SFUD组件的SPI驱动程序是基于I/O设备模型框架设计的。

使用SFUD组件,我们不需要自己编写SPI Flash驱动程序。

支持SPI/QSPI接口,面向对象(同时支持多个Flash对象),剪裁灵活,扩展性强,支持4字节地址。

☆ SFUD 是一个开源组件。 该组件真正权威的参考说明是该组件作者编写的.md文件(永远记住,之一作者的文档和官方文档永远是最有价值的参考)。 ☆

使用 RT- 打开文件,如下所示。 基本介绍、功能使用、使用说明都有。 你可以自己检查一下:

本文不深入分析源码实现原理,只是简单解释一下理论。 这里推荐几篇文章进行理论分析和解释。 在讲解理论基础时,我们还参考了以下文章:

SFUD源码简析

RT中的Flash管理-【SFUD组件和FAL驱动组件介绍】

1.2 SFUD对Flash的管理

之前我们说过,面向对象编程一般使用结构体来表示对象。 我们讲的线程、IPC机制、I/O设备都有其设备控制块结构。

对于SPI Flash设备,SFUD还定义了一个管理结构。 其位置及内容如下:

在这个对象控制块中,有一个名为chip的成员,它的类型是一个chip信息的结构体,如下所示:

在SFUD组件中,定义了一些支持的芯片信息,如下所示:

基本包含了市面上常见的SPI Flash芯片。 如果使用的flash不支持SFUD组件,可以根据文件自行添加。

这就是简要概述。 我们来看看SFUD组件提供的操作功能。

2.SFUD组件操作功能

根据SFUD组件的文档,SFUD组件提供的API框架图如下:

这里需要注意的是,上述API是SFUD外部标准的通用API,即无论使用什么系统,或者使用裸机,移植SFUD组件后都可以使用这些API。

对于我们使用的RT-来说,访问设备的函数是SFUD设备的标准API。

但对于初始化相关的部分,RT-已经官方为我们编写了标准驱动函数。

2.1 初始化相关函数

工程文件中RT初始化驱动文件如下:

它提供的函数有(对于RT-中初始化相关函数的使用,本文后面的测试部分会有详细的例子):

/**
 * Probe SPI flash by SFUD(Serial Flash Universal Driver) driver library and though SPI device.
使用 SFUD 探测 spi_dev_name 从设备,
并将 spi_dev_name 连接的 flash 初始化为块设备,名称 spi_flash_dev_name
 */
rt_spi_flash_device_t rt_sfud_flash_probe(const char *spi_flash_dev_name, const char *spi_dev_name);
/**
 * Probe SPI flash by SFUD (Serial Flash Universal Driver) driver library and though SPI device by specified configuration.
 * rt_sfud_flash_probe 调用了此函数
使得与底层 SFUD 本身的初始化文件关联起来
 */
rt_spi_flash_device_t rt_sfud_flash_probe_ex(const char *spi_flash_dev_name, const char *spi_dev_name,
        struct rt_spi_configuration *spi_cfg, struct rt_qspi_configuration *qspi_cfg);
/**
 * Delete SPI flash device
 	删除SPI SFUD 设备
 */
rt_err_t rt_sfud_flash_delete(rt_spi_flash_device_t spi_flash_dev);
/**
 * Find sfud flash device by SPI device name
通过 SPI 设备名称 找到一个 SFUD Flash 设备
 */
sfud_flash_t rt_sfud_flash_find(const char *spi_dev_name);
/**
 * Find sfud flash device by flash device name
 通过 Flash 设备名称 找到一个 SFUD Flash 设备
 */
sfud_flash_t rt_sfud_flash_find_by_dev_name(const char *flash_dev_name);

我们不会对功能进行深入分析。 每个人都需要学习使用它们。 过去有很多文章都有源码分析说明。 你可以自己查看源码。 例如,更关键的功能之一例如:

2.2 设备接入功能

设备访问功能在 SFUD 组件的文件中描述。 有关使用函数的说明可以在组件描述文件中找到。

这里将它们一起列出以供将来复制和使用:

2.2.1 读取数据

/*
参数	描述
flash	Flash 设备对象
addr	起始地址
size	从起始地址开始读取数据的总大小
data	读取到的数据
*/
sfud_err sfud_read(const sfud_flash *flash, uint32_t addr, size_t size, uint8_t *data)

2.2.2 擦除数据

部分擦除:

/*
参数	描述
flash	Flash 设备对象
addr	起始地址
size	从起始地址开始擦除数据的总大小
*/
sfud_err sfud_erase(const sfud_flash *flash, uint32_t addr, size_t size)

完全擦除:

/*
参数	描述
flash	Flash 设备对象
*/
sfud_err sfud_chip_erase(const sfud_flash *flash)

2.2.3 写入数据

写吧:

/*
参数	描述
flash	Flash 设备对象
addr	起始地址
size	从起始地址开始写入数据的总大小
data	待写入的数据
*/
sfud_err sfud_write(const sfud_flash *flash, uint32_t addr, size_t size, const uint8_t *data)

先擦掉再写:

/*
参数	描述
flash	Flash 设备对象
addr	起始地址
size	从起始地址开始写入数据的总大小
data	待写入的数据
*/
sfud_err sfud_erase_write(const sfud_flash *flash, uint32_t addr, size_t size, const uint8_t *data)

2.2.4 Flash状态相关

读取闪存状态:

/*
参数	描述
flash	Flash 设备对象
status	当前状态寄存器值
*/
sfud_err sfud_read_status(const sfud_flash *flash, uint8_t *status)

修改Flash状态:

/*
参数	描述
flash	Flash 设备对象
is_volatile	是否为易闪失的,true: 易闪失的,及断电后会丢失
status	当前状态寄存器值
*/
sfud_err sfud_write_status(const sfud_flash *flash, bool is_volatile, uint8_t status)

3、使用测试

本节介绍在 RT- 上使用 SFUD 组件的步骤,然后我们使用示例进行基本测试:

3.1 使用步骤3.1.1启用SPI设备

按照RT-(15. I/O设备模型的SPI设备)一文中“3.1 SPI设备使用步骤”的描述启用SPI总线。

注册SPI总线设备并使用查看结果:

3.1.2 启用SFUD组件包

与启用SPI设备一样,打开RT-并启用RT-中的SFUD组件,如下图:

启用完成后,我们可以在应用层直接调用上一节中的SFUD操作函数。

在该项目中,与SFUD组件相关的程序位置如下:

3.1.3 安装SFUD设备

在使用SFUD设备之前,需要先挂载它,类似于在SPI总线上挂载SPI设备。 使用以下操作:

我忘记了另一个开发板不是,所以我最后找到的是。

这里有一个小问题需要解释一下,DBG定义的问题,我稍微修改了main中的注释:

3.1.4 应用查找装置

使用或获取设备句柄:

3.1.5 使用API​​进行读写操作

完成以上步骤后,就可以根据自己的应用,使用上面介绍的SFUD组件操作函数来访问设备部分,进行Flash操作了。

例如:

3.2 读写测试

在上面的使用步骤中,我其实已经描述了我所做的所有简单测试。 下面我们先过一下部分测试代码,然后看一下测试结果:

#include 
#include "main.h"
#include "usart.h"
#include "gpio.h"
#include 
#include "board.h"
#include "drv_spi.h"
#include "spi_flash_sfud.h"
#ifndef DBG_TAG
#define DBG_TAG "main"
#endif
#ifndef DBG_LVL
#define DBG_LVL DBG_LOG
#endif
#include 
//省略...
sfud_flash *test_sfud = NULL;
const uint8_t test_data[] = "this is a test data!";
//省略...
static void key1_thread_entry(void *par){
    while(1){
        if(key1_read == 0){
            rt_thread_mdelay(10); //去抖动
            if(key1_read == 0){
                rt_kprintf("write flash ..\r\n");
//                sfud_write(test_sfud, 13, sizeof(test_data), test_data);
                sfud_erase_write(test_sfud, 13, sizeof(test_data), test_data);
             }
             while(key1_read == 0){rt_thread_mdelay(10);//去抖动
            }
        }
        rt_thread_mdelay(1);
   }
}
static void key2_thread_entry(void *par){
    uint8_t read_data[30] = {0};
//    void *str = RT_NULL;
    while(1){
        if(key2_read == 0){
            rt_thread_mdelay(10); //去抖动
            if(key2_read == 0){
                rt_kprintf("read flash ..\r\n");
//                sfud_read(test_sfud, 0, sizeof(test_data), (uint8_t *)str);
                sfud_read(test_sfud, 13, sizeof(test_data), read_data);
                rt_kprintf("%s",read_data);
             }
             while(key2_read == 0){rt_thread_mdelay(10);//去抖动
            }
        }
        rt_thread_mdelay(1);
   }
}
//省略...
int main(void)
{
//省略...
    rt_hw_spi_device_attach("spi1", "spi10", GPIOA, GPIO_PIN_4);  // CS 脚:PA4
    /* 使用 SFUD 探测 spi10 从设备,并将 spi10 连接的 flash 初始化为块设备,名称 W25Q128 */
    if (RT_NULL == rt_sfud_flash_probe("W25Q64", "spi10"))
    {
        return -RT_ERROR;
    };
//  test_sfud = rt_sfud_flash_find("spi10"); //
    test_sfud = rt_sfud_flash_find_by_dev_name("W25Q64");
    if(RT_NULL == test_sfud){
          LOG_E("find sfud_flash failed!...\n");
    }
   //省略...
    return RT_EOK;
}

检测结果:

测试详情:

测试过程中,我使用了一个关键线程来写入flash。 一开始我使用了512字节的线程栈:

使用函数会比函数占用更多的内存。

结论

在这篇文章中,我们从上一篇刚刚学习的SPI设备相关的SFUD组件开始,接触到了RT-组件和软件包。 可见使用RT-开发常用设备是多么方便。

但前提当然是你对RT-的面向对象思想、I/O设备模型等基础知识有一定的了解。 如果你只是想使用它,只需阅读一篇文章即可。 如果想要了解和掌握,还需要了解更多RT-Basic相关知识,比如博主的RT-专栏==! O(∩_∩)O哈哈~

我再说一遍,对于组件和软件包,因为它们都是由大开发人员编写的驱动程序,所以我的首选重点是学习使用它们。 该文档包含作者对每个组件或软件包的详细说明。 那么就是更好的参考资料了。

希望大家支持我! 这就是本文的内容,谢谢!

未经允许不得转载! 作者:admin,转载或复制请以超链接形式并注明出处天心神途传奇手游发布网

原文地址:《找sf RT-Thread记录(16.SFUD组件-SPI Flash读写)》发布于:2024-03-30

发表评论

表情:
验证码
评论列表 (暂无评论,63人围观)

还没有评论,来说两句吧...