从本文开始,测试学习一些 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




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