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 的相关文章

  • 基于c3c2440 Linux SPI驱动程序移植与测试

    基于c3c2440 Linux SPI驱动程序移植与测试 环境 ubuntu14 04 TQ2440开发板 linux3 0内核 linux3 0内核移植笔记点此 1 配置内核 Device Drivers gt SPI support g
  • 使用RT-Thread Studio 建立 L476 Nucleo 项目工程并完成相关功能

    使用RT Thread Studio 建立 L476 Nucleo 项目工程并完成相关功能 1 新建RTT工程 2 添加cube对应的驱动 Nucleo 板上 X2 低速时钟有 X3调整时钟无 UART2串口配置 PA2 PA3 用户按键
  • rt-thread系列文章目录

    rt thread系列文章目录 本文是rt thread系列文章目录 后续关于rt thread的更新都会添加到此文内 实战篇 rt thread 生成工程模板 rt thread fal移植 内核篇 rt thread 内存管理 内存堆
  • 沁恒CH32V307使用记录:SPI基础使用

    文章目录 目的 基础说明 使用演示 其它补充 总结 目的 SPI是单片机中比较常用的一个功能 这篇文章将对CH32V307中相关内容进行说明 本文使用沁恒官方的开发板 CH32V307 EVT R1沁恒RISC V模块MCU赤兔评估板 进行
  • 使用Linux内核里的spi屏驱动-fbtft

    Linux内核里已经提供spi接口小屏的设备驱动 在内核的配置选项 make menuconfig ARCH arm CROSS COMPILE arm linux gnueabihf Device Drivers gt Graphics
  • ArtPi 认识RTT Studio建立LED工程

    1 认识RTT Studio建立LED工程 软件IDE RT Thread Studio 版本 2 1 1 硬件平台 ART Pi CPU STM32H750XB 开发板基本外设功能实现 串口 uart4 PA0 PI9 Red LED P
  • RT-Thread分析-对象容器实现与作用

    目录 1 前言 2 相关数据结构 2 1 对象 1 类型 2 数据结构 2 3 容器 1 数据结构 2 容器定义 object container 2 3 对象容器链接图 3 获取对象容器 rt object get information
  • 【N32L40X】学习笔记14-在RT-thread系统中读取eeprom数据

    eeprom 说明 eeprom介绍 AT24C01A 1K串行EEPROM 内部组织16页8字节 1K需要一个7位数据字地址进行随机字寻址 AT24C02 2K串行EEPROM 内部组织32页8字节 2K需要一个8位数据字地址进行随机字寻
  • STM32F4 RTC-Alarm 的使用(RT-Thread操作系统)

    文章目录 1 工程的创建和配置 1 1 CubeMX 的配置 1 1 1 时钟源的选择 1 1 2 Debug 引脚配置 1 1 3 控制台串口的配置 1 1 4 RTC的配置 1 1 5 时钟树配置 1 1 6 代码生成 1 2 RT T
  • 内核7-线程间同步

    目录 1 信号量 1 1 信号量机制 1 2 信号量的使用场合 1 2 1 线程同步 1 2 2 锁 1 2 3 中断与线程的同步 1 2 4 资源计数 1 3 信号量控制块 1 4 函数 1 4 1 rt sem init 函数 1 4
  • 外设驱动库开发笔记22:ADXL345三轴数字加速度计驱动

    移动设备的广泛应用增加对移动过程中各种参数的检测需求 ADXL345三轴数字加速度计可以用来检测加速度 进而测量倾斜角度等 在这一篇中 我们将讨论ADXL345三轴数字加速度计驱动程序的设计与实现 1 功能概述 ADXL345是一款小而薄的
  • rtt下的adbd使用

    RTT 下的ADBD使用 1 引言 调试柿饼时 需要文件传输 由于智龙平台的RTT环境下USB还没有调试好 这里就使用ADB进行文件传输 找到了何元杰的帖子 并参考 rdb 建立 RTT与PC 的文件传输通道 2 使用环境 2 1 硬件平台
  • RT-Thread微秒延时?

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

    基础资料 基于Air105开发板 Air105 LuatOS 文档 上手 开发上手 LuatOS 文档 探讨重点 官方SFUD库操作 外置flash demo相关内容的学习及探讨 扩展 合宙Air103 SDIO 扩展 LuatOS SOC
  • 难懂?这样理解SPI与CAN很简单!

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

    前面耽搁了几天 今天终于把CH347 SPI接口调试好了 CH347动态库中SPI接口函数如下 typedef struct SPI CONFIG UCHAR iMode 0 3 SPI Mode0 1 2 3 UCHAR iClock 0
  • rt-thread中使用WebClient WebNet总结 http学习

    HTTP学习资料 1 需求背景 WebClient主要用来传输文件 WebNet用来支持cgi接口 需要支持get post put delete方式 2 webnet中使用 2 1 webnet存在问题 2 11 rt thread 使用
  • RTThread学习有关的Keil的两个符号 $Sub$ $main 与 $Super$ $main

    Keil的两个符号 Sub 与 Super 是其做的打 补丁 功能 具体调用方法就是程序中包含有main函数 和 Sub main Super main 两个符号 源码先放出来 re define main function int Sub
  • rt-thread studio中新建5.0不能用

    文章目录 一 版本对比 二 文件和文件夹打斜杠 在使用RT Thread studio创建新工程5 0版本的时候 结果发现新建完成之后程序不能正常运行 但是创建4 10版本的时候却能运行 那肯定是新版本出现了BUG 一 版本对比 首先对比了
  • Arm 板上有两个以上的 SPI 设备,但只支持两个?

    我们其中一块板上的 Arm 处理器有一个 spi 端口 带有两条片选线 该处理器的数据表中提到它最多可以控制两个 spi 设备 是否可以使用 GPIO 作为附加 spi 设备的从选择 如何修改现有的库 设备驱动程序以支持此更改 到目前为止

随机推荐

  • 【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