RTThread-W25Q128的驱动基于SPI和SFUD

2023-05-16

文章目录

  • 前言
  • 一、kconfig的配置
    • 1.配置对应的SPI和SFUD
  • 二、 SFUD的使用
    • W25Q128的读写操作
  • 三.关于写入的问题

前言

本文是一个初学者的学习记录,可能有误。
SFUD是针对flash的一种通用的组件,简单来说就是使用SFUD再加上RTT的SPI驱动,基本可以兼容大多数的FLASH,而不用自己再去写驱动。

一、kconfig的配置

1.配置对应的SPI和SFUD

代码如下(示例):

menu "Onboard Peripheral Drivers"
	menuconfig  BSP_USING_SPI_FLASH
		bool "Enable SPI FLASH(W25Q128 spi2)"
		default n
		select BSP_USING_SPI
		select BSP_USING_SPI2
		select RT_USING_SFUD
		if BSP_USING_SPI_FLASH
			config SPI_FALSH_NAME
			string "spi flash device name"
			default "W25Q128"
			
			config SPI_FLASH_BUS_NAME
			string "spi flash bus name"
			default "spi2"	

			config SPI_FLASH_DEVICE_NAME
			string "spi flash device name"
			default "spi20"					
		endif  
endmenu
menu "On-chip Peripheral Drivers"

    config BSP_USING_GPIO
        bool "Enable GPIO"
        select RT_USING_PIN
        default y
    menuconfig BSP_USING_SPI
        bool "Enable SPI BUS"
        default y
        select RT_USING_SPI
        if BSP_USING_SPI
            config BSP_USING_SPI2
                bool "Enable SPI2 BUS"
                default y  
        endif	
    source "../libraries/HAL_Drivers/Kconfig"
  endmenu

并在ENV中打开对应的选项。重新生成工程。

二、 SFUD的使用

首先使用rt_hw_spi_device_attach,挂载SPI设备
使用rt_sfud_flash_probe,挂载SFUD驱动
使用INIT_COMPONENT_EXPORT自动在开机时加载运行。

int rt_hw_spi_flash_init(void)
{
    __HAL_RCC_GPIOB_CLK_ENABLE();
    rt_hw_spi_device_attach(SPI_FLASH_BUS_NAME,SPI_FLASH_DEVICE_NAME, GPIOB, GPIO_PIN_12);

    if (RT_NULL == rt_sfud_flash_probe(SPI_FALSH_NAME,SPI_FLASH_DEVICE_NAME))
    {
        return -RT_ERROR;
    };

    return RT_EOK;
}
INIT_COMPONENT_EXPORT(rt_hw_spi_flash_init);

W25Q128的读写操作

sfud_w25q_sample是sfud_w25q_sample中提供了2种操作方式,两种方式都可以进行读写。
用SFUD操作
使用rt_sfud_flash_find_by_dev_name,找到加载的SFUD设备的句柄
sfud_erase_write和sfud_read进行相应的读写
用RTT自身的驱动操作
rt_device_find,找到设备句柄
rt_device_open,打开flash设备
rt_device_control 对设备进行控制,下文中是获取了设备的基本信息
rt_device_write 写入
rt_device_read 读取
rt_device_close 关闭设备

rt_uint8_t wData[4096] = {"QSPI bus write data to W25Q flash."};
rt_uint8_t rData[4096];
static void static void sfud_w25q_sample(void)
{
    rt_spi_flash_device_t flash_dev;
    sfud_flash_t sfud_dev;
    struct rt_device_blk_geometry geometry;

    // 1- use sfud api
    rt_kprintf("\n 1 - Use SFUD API \n");

    sfud_dev = rt_sfud_flash_find_by_dev_name(SPI_FALSH_NAME);
    if(sfud_dev == RT_NULL){
        rt_kprintf("sfud can't find %s device.\n", SPI_FALSH_NAME);
    }else{
        rt_kprintf("sfud device name: %s, sector_count: %d, bytes_per_sector: %d, block_size: %d.\n", 
                    sfud_dev->name, sfud_dev->chip.capacity / sfud_dev->chip.erase_gran, 
                    sfud_dev->chip.erase_gran, sfud_dev->chip.erase_gran);

        if(sfud_erase_write(sfud_dev, 0x002000, sizeof(wData), wData) == SFUD_SUCCESS)
            rt_kprintf("sfud api write data to w25q128(address:0x2000) success.\n");

        if(sfud_read(sfud_dev, 0x002000, sizeof(rData), rData) == SFUD_SUCCESS)
            rt_kprintf("sfud api read data from w25q128(address:0x2000) is:%s\n", rData);
    }

    // 2- use rt_device api
    rt_kprintf("\n 2 - Use rt_device API \n");

    flash_dev = (rt_spi_flash_device_t)rt_device_find(SPI_FALSH_NAME);
    if(flash_dev == RT_NULL){
        rt_kprintf("rt_device api can't find %s device.\n", SPI_FALSH_NAME);
    }else{
        rt_device_open(&flash_dev->flash_device, RT_DEVICE_OFLAG_OPEN);

        if(rt_device_control(&flash_dev->flash_device, RT_DEVICE_CTRL_BLK_GETGEOME, &geometry) == RT_EOK)
            rt_kprintf("spi flash device name: %s, sector_count: %d, bytes_per_sector: %d, block_size: %d.\n", 
                    flash_dev->flash_device.parent.name, geometry.sector_count, geometry.bytes_per_sector, geometry.block_size);

        if(rt_device_write(&flash_dev->flash_device, 0x03, wData, 1) > 0)
            rt_kprintf("rt_device api write data to w25q128(address:0x3000) success.\n");

        if(rt_device_read(&flash_dev->flash_device, 0x03, rData, 1) > 0)
            rt_kprintf("rt_device api read data from w25q128(address:0x3000) is:%s\n", rData);

        rt_device_close(&flash_dev->flash_device);
    }
}

自此W25Q128Q128就可以驱动起来了

三.关于写入的问题

由于W29Q128是页写入的,所以每次写入和擦除都是按页来的,根据不同的falsh页也不同,w25Q128一页是4096字节。上述的函数会导致单写某几个字节的时候会把之前写入的全擦除。
所以当需要小段写入的时候,应该是先判断写入地址和写入的长度,如果要写的数据在一个扇区内,就读取该扇区的内容到缓存数组中,然后擦除这个扇区,把要写的数据加入到这个缓存数组,然后把缓存数组写入,如果写入的数据要跨越两个扇区,那就要按照上述操作,写第一个扇区,然后写第二个扇区。

//读出扇区,擦除扇区后写入。最大不要超过4096字节,只能跨越两个扇区
void sfud_w25q_write(rt_uint32_t wadd,rt_uint8_t *wdata,rt_uint16_t size)
{
	sfud_flash_t sfud_dev;
	uint16_t i;
	uint32_t sec_pos,sec_off,sec_remain;
	
	sec_pos = wadd / 4096;//扇区地址
	sec_off = wadd % 4096;//扇区内的偏移
	sec_remain = 4096 - sec_off; //扇区剩余空间大小   

	sfud_dev = rt_sfud_flash_find_by_dev_name(SPI_FALSH_NAME);
	if(sfud_dev == RT_NULL)
	{
			rt_kprintf("sfud can't find %s device.\n", SPI_FALSH_NAME);
	}
	else
	{   //判断扇区的剩余大小是否小于数据长度,如果小于那就说明是在一个扇区
		if(sec_remain>size)//一个扇区
		{
			sfud_read(sfud_dev,sec_pos*4096,4096,rData);//读取整个扇区的内容
			sfud_erase(sfud_dev,sec_pos*4096,4096);//擦除扇区
			for(i=0;i<size;i++)//加入要写入的数据
			{
				rData[sec_off+i] = *(wdata+i);
			}
			sfud_write(sfud_dev,sec_pos*4096,4096,rData);
		}
		else  //跨越两个扇区
		{
			sfud_read(sfud_dev,sec_pos*4096,4096,rData);//读取第一位扇区的内容
			sfud_erase(sfud_dev,sec_pos*4096,4096);//擦除扇区
			for(i=0;i<sec_remain;i++)   //加入要写入的数组前半段
			{
				rData[sec_off+i] = *(wdata+i);
			}
			sfud_write(sfud_dev,sec_pos*4096,4096,rData);//写入缓存数组
			
			sfud_read(sfud_dev,(sec_pos+1)*4096,4096,rData);//读取第二个扇区的内容
			sfud_erase(sfud_dev,(sec_pos+1)*4096,4096);//擦除扇区
			for(i=0;i<(size-sec_remain);i++)  //加入要写入的数组后半段
			{
				rData[i] = *(wdata+sec_remain+i);
			}
			sfud_write(sfud_dev,(sec_pos+1)*4096,4096,rData);//写入缓存数组
		}
	}
	
	
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

RTThread-W25Q128的驱动基于SPI和SFUD 的相关文章

  • RT-Thread Studio上使用U8G2(NUCLEO-F411RE)

    1 U8G2是嵌入式设备的单色图形库 Arduino和RT Thread都支持 包含大量的图形程序 绘画直线 方框 圆圈 支持多种语言多种字体 涵盖几乎所有流行的控制器 SSD1305 SSD1306 SSD1309 SSD1322 SSD
  • rt-thead-studio 中实现 MPU6050基于DMP中断读取数据

    rt thead studio 中实现 MPU6050基于DMP中断读取数据 目录 文章目录 rt thead studio 中实现 MPU6050基于DMP中断读取数据 目录 toc 前言 mpl高级特性库问题 一 基于开发板创建闪灯工程
  • 关于IKEv2中安全策略索引SPI的生成

    首先引入一个PF key的概念 PF KEY Key Management API 提供IKE模块和IPSec核心之间的接口 在RFC 2367中 有一个SADB GETSPI消息 这个消息就是实现允许一个进程获取SPI值 该值标识所给的s
  • RT-Thread分析-对象容器实现与作用

    目录 1 前言 2 相关数据结构 2 1 对象 1 类型 2 数据结构 2 3 容器 1 数据结构 2 容器定义 object container 2 3 对象容器链接图 3 获取对象容器 rt object get information
  • [开发过程]<RTOS>关于RT-Thread

    以前一直折腾FreeRTOS 没时间折腾RT Thread 虽然暂时对RT Thread学的不深 但是从学习难度和社区支持来看 相信多年后RT Thread会成为主流 大概是因为很多RT Thread的中文资料吧 入门还要先学FreeRTO
  • 各种通信接口的简单对比

    对比表 同步方式与异步方式的主要区别在于 是否传输时钟信号 只要是通訊前雙方需要設定相同波特率的 都是異步傳輸方式 异步传输 Asynchronous Transmission 每次异步传输的信息都以一个起始位开头 它通知接收方数据已经到达
  • RTThread:静态线程&动态线程

    一 静态线程创建 rt thread init rt err t rt thread init struct rt thread thread const char name void void parameter entry void p
  • Java SPI机制

    一 SPI机制简介 SPI的全名为Service Provider Interface java spi机制的思想 系统里抽象的各个模块 往往有很多不同的实现方案 在面向的对象的设计里 一般推荐模块之间基于接口编程 模块之间不对实现类进行硬
  • RT-Thread微秒延时?

    今天继续做之前的东西 使用了RT thread操作系统 程序中有AT24C02的相关操作AT24C02的操作的接口是IIC接口 所以又涉及到IIC 程序用的模拟的IIC IIC的时序挺严格的 有微秒的延时操作 由于模拟IIC程序中的延时操作
  • Spring Factories

    该文章转载自 https blog csdn net lvoyee article details 82017057 Spring Boot中有一种非常解耦的扩展机制 Spring Factories 这种扩展机制实际上是仿照Java中的S
  • RT-Thread之ENV工具

    快速索引 ENV工具简介 准备工作 1 Git 安装并设置环境变量 2 ENV 前往RT Thread官网下载 3 RTT源码 GitHub OSChina 云盘 ENV工具打开方式 scons 编译项目 1 进入 BSP 目录 选择 st
  • I2C与SPI通信总线协议

    仅以寄存器地址为8Bit的器件为例 例如MPU6500 LSM6DS3 I2C通信协议 I2C 的要点是了解I2C通信帧的组成部分 START起始位 STOP停止位 ACK NACK信号 从机器件地址 从机寄存器地址 I2C读的时序比较繁琐
  • 难懂?这样理解SPI与CAN很简单!

    难懂 这样理解SPI与CAN很简单 什么是串行通讯 为什么仍需使用串行通讯 SPI与CAN SPI 接口特点 CAN现场总线特点 什么是串行通讯 在正式进入主题前 我么先来介绍一下什么叫做 串行通信 串行通信是计算机的一种数据传输通信方式
  • SFUD 一款嵌入式SPI FLASH驱动组件

    SFUD 一款嵌入式SPI FLASH驱动组件 源仓库 https github com armink SFUD 移植例程仓库 https gitee com ll0 0ll Packages practice 简介 1 功能 通常要驱动S
  • RT-Thread记录(七、IPC机制之邮箱、消息队列)

    讲完了线程同步的机制 我们要开始线程通讯的学习 线程通讯中的邮箱消息队列也属于 RT Thread 的IPC机制 目录 前言 一 邮箱 1 1 邮箱控制块 1 2 邮箱操作 1 2 1 创建和删除 1 2 2 初始化和脱离 1 2 3 发送
  • rt-thread studio中新建5.0不能用

    文章目录 一 版本对比 二 文件和文件夹打斜杠 在使用RT Thread studio创建新工程5 0版本的时候 结果发现新建完成之后程序不能正常运行 但是创建4 10版本的时候却能运行 那肯定是新版本出现了BUG 一 版本对比 首先对比了
  • 中断管理学习

    中断管理 什么是中断 简单的解释就是系统正在处理某一个正常事件 忽然被另一个需要马上处理的紧急事件打断 系统转而处理这个紧急事件 待处理完毕 再恢复运行刚才被打断的事件 生活中 我们经常会遇到这样的场景 当你正在专心看书的时候 忽然来了一个
  • RT-Thread 内核基础(四)

    自动初始化机制 自动初始化机制是指初始化函数不需要被显示调用 只需要在函数定义处通过宏定义的方式进行申明 就会在系统启动过程中被执行 例如在串口驱动中调用一个宏定义告知系统初始化需要调用的函数 代码如下 int rt hw usart in
  • RT-Thread 内核基础(五)

    使用static修饰全局变量作用 限制作用域 如果全局变量前面加上 static 关键字 那么该变量的作用域将被限制在声明它的源文件中 即它将成为一个文件作用域的静态变量 其它源文件无法访问这个变量 这对于控制变量的可见性和避免命名冲突是有
  • Spidev 不使用 ioctl 同时写入/读取

    我希望找到一些帮助 即使这个问题可能更多地与硬件相关而不是与软件相关 我们将会看到 我正在开发基于 Freescales P1021 处理器 ppc e500v2 内核 的定制板 将连接外部 PCB 并可通过 SPI 进行配置 该外部 PC

随机推荐

  • 【caffe-Windows】以mnist为例lmdb格式数据

    前言 前面介绍的案例都是leveldb的格式 xff0c 但是比较流行和实用的格式是lmdb xff0c 原因从此网站摘取 它们都是键 值对 xff08 Key Value Pair xff09 嵌入式数据库管理系统编程库 虽然lmdb的内
  • 【theano-windows】学习笔记十——多层感知机手写数字分类

    前言 上一篇学习了softmax 然后更进一步就是学习一下基本的多层感知机 MLP 了 其实多层感知机同时就是w x 43 b用某个激活函数激活一下 得到的结果作为下一层神经元的输入x 类似于 o u t p u t 61 f 3 f 2
  • 【theano-windows】学习笔记二十——LSTM理论及实现

    前言 上一篇学习了RNN xff0c 也知道了在沿着时间线对上下文权重求梯度的时候 xff0c 可能会导致梯度消失或者梯度爆炸 xff0c 然后我们就得学习一波比较常见的优化方法之LSTM 国际惯例 xff0c 参考网址 xff1a LST
  • 【TensorFlow-windows】keras接口——ImageDataGenerator裁剪

    前言 Keras中有一个图像数据处理器ImageDataGenerator xff0c 能够很方便地进行数据增强 xff0c 并且从文件中批量加载图片 xff0c 避免数据集过大时 xff0c 一下子加载进内存会崩掉 但是从官方文档发现 x
  • 梯度下降法与Logistic Regression 及 Matlab 代码

    梯度下降法与Logistic Regression 及 Matlab 代码 前言Logistic回归梯度下降法例子1 xff0c 固定学习率改进1 xff1a 正则化改进2 xff1a 动态学习率查看分类效果不足完整代码 前言 本质是一个求
  • ONOS 控制器安装和app新建和编译

    1 1 ONOS 控制器编译与安装 ONOS 1 8 版本起强制使用 BUCK 构建工具 xff0c 不再使用 maven xff0c 编译和打包方式与旧版本有所区别 步骤 xff1a 配置环境 gt 下代码 gt 编译 gt 运行 配置环
  • SQLyog(navica)连接docker容器中的mysql8.0.12 报错1251或2003解决办法

    使用SQLyog xff08 navicat xff09 远程连接docker容器中的mysql8 0 12 报以下错误 解决办法 xff1a 一 在docker中启动mysql 定义端口号3306 root 64 localhost do
  • TTY 到底是个什么玩意?

    先来回答一道面试题 xff1a 我们知道在终端中有一些常用的快捷键 xff0c Ctrl 43 E 可以移动到行尾 xff0c Ctrl 43 W 可以删除一个单词 xff0c Ctrl 43 B 可以向前移动一个字母 xff0c 按上键可
  • 如何画好一份架构图

    先说答案 画架构图分四步走 xff1a 第一 xff0c 搞清楚要画的架构图的类型 xff1b 第二 xff0c 确认架构图中的关键要素 xff08 比如产品 技术 服务 xff09 xff1b 第三 xff0c 梳理关键要素之间的关联 x
  • NVIDIA Jetson Xavier NX 深度学习相关组件安装

    一 tensorflow的安装 写在前面的牢骚话 xff08 可选择直接跳过 xff09 在写安装tensorflow的教程之前 xff0c 我一定要放出当时我安装tensorflow时所遇到的那些莫名其妙的错误 xff0c 具体错误如下图
  • Python - Decorator(装饰器) - 带参数的

    我们通过以示例来看看带参数的装饰器到底怎么回事 from time import perf counter from functools import wraps def repeated times def outer fn 64 wra
  • 2020塔式起重机司机考试及塔式起重机司机考试软件

    题库来源 xff1a 安全生产模拟考试一点通公众号小程序 2020塔式起重机司机考试及塔式起重机司机考试软件 xff0c 包含塔式起重机司机考试答案解析及塔式起重机司机考试软件练习 由安全生产模拟考试一点通公众号结合国家塔式起重机司机考试最
  • 2020煤炭生产经营单位(安全生产管理人员)操作证考试及煤炭生产经营单位(安全生产管理人员)模拟考试软件

    题库来源 xff1a 安全生产模拟考试一点通公众号小程序 2020煤炭生产经营单位 xff08 安全生产管理人员 xff09 操作证考试及煤炭生产经营单位 xff08 安全生产管理人员 xff09 模拟考试软件 xff0c 包含煤炭生产经营
  • 嵌入式系统 Boot Loader 技术内幕

    内容 xff1a 1 引言 2 Boot Loader 的概念 3 Boot Loader 的主要任务与典型结构框架 4 关于串口终端 5 结束语 关于作者 对于本文的评价 在 Linux 专区还有 xff1a 教程 工具与产品 代码与组件
  • PADS VX2.8 PCB版本的降低方法

    在PCB设计过程中 xff0c 可能会遇到不同版本的PCB文件 xff0c 高版本软件可以兼容低版本 xff0c 反之则不能 为了提高兼容性 xff0c 可以将拿到的高版本PCB文件降低为低版本 xff0c 以配合使用低版本软件打开 打开P
  • Ubuntu16.04 速腾rslidar-32线激光雷达使用详细记录

    0 rslidar 32线激光雷达参数 线束 xff1a 32线波长 xff1a 905nm激光等级 xff1a class1精度 xff1a 5cm xff08 典型值 xff09 测量距离 xff1a 0 2m 200m xff08 目
  • useradd 与 adduser

    useradd 选项 用户名 参数如下 xff1a c comment 指定一段注释性描述 d 目录 指定用户主目录 xff0c 如果此目录不存在 xff0c 则同时使用 m选项 xff0c 可以创建主目录 g 用户组 指定用户所属的用户组
  • Python——sqlalchemy.exc.ArgumentError

    报错信息 xff1a sqlalchemy exc ArgumentError Mapper mapped class XmjbqZby gt xmjbq zby could not assemble any primary key col
  • VirtualBox虚拟机ping不通主机,但是主机可以ping通虚拟机

    解决VirtualBox虚拟机不能ping通宿主机的问题 问题描述 在VirtualBox虚拟中 xff0c 无法ping通宿主机 xff0c 宿主机可以ping通虚拟机 虚拟机的网络已经设置为 桥接网卡 xff0c 也可以正常上网 解决方
  • RTThread-W25Q128的驱动基于SPI和SFUD

    文章目录 前言一 kconfig的配置1 配置对应的SPI和SFUD 二 SFUD的使用W25Q128的读写操作 三 关于写入的问题 前言 本文是一个初学者的学习记录 xff0c 可能有误 SFUD是针对flash的一种通用的组件 xff0