立创梁山派--移植开源的SFUD和FATFS实现SPI-FLASH文件系统

本文主要是在sfud的基础上进行fatfs文件系统的移植,并不对sfud的移植再进行过多的讲解了哦,所以如果想了解sfud的移植过程,请参考我的另外一篇文章:传送门

正文开始咯

  • 首先我们需要先准备资料准备好,这里对于fatfs的移植,我参考的是野火的教程。所以我在文章末尾也会给出相关的教程链接。
    我们需要的东西有:一份实现了sfud库的裸机代码,这个可以从我上篇文章的文末连接中获取,这里我也将代码的链接贴出:传送门, 还有一份fatfs源码,这个为了和野火的教程保持移植,这里用的是跟野火教程版本一致的fatfs源码,这里的源码可以在文末的链接开源代码链接中获取。
  • 开始移植
    打开fatfs代码
    在这里插入图片描述
    我们将其添加到我们的工程中
    在这里插入图片描述
    添加文件路径#在这里插入图片描述

对于fatfs的介绍,野火的教程中都有详细的介绍,这里就不再赘述了。其实它的移植是比较简单的,只需要修改diskio.c文件中的相关接口函数和ffconf.h配置文件。

  • 打开diskio.c文件
    首先包含我们需要的头文件,定义我们要操作的flash
#include "bsp_spi.h"
#include "sfud.h"
const sfud_flash *flash1;#define W25Q64 0xEF16 //根据板载的spiflash来修改 /* 为每个设备定义一个物理编号 */
#define ATA			    0     // 预留SD卡使用
#define SPI_FLASH		1     // 外部SPI Flash

对需要修改的函数进行说明

//获取状态函数
DSTATUS disk_status(BYTE pdrv /* 物理编号 */
)
{DSTATUS status = STA_NOINIT;switch (pdrv){case ATA: /* SD CARD */break;case SPI_FLASH:/* SPI Flash状态检测:读取SPI Flash 设备ID */if (W25Q64 == spi4_flash_readID()){/* 设备ID读取结果正确 */status &= ~STA_NOINIT;}else{/* 设备ID读取结果错误 */status = STA_NOINIT;;}break;default:status = STA_NOINIT;}return status;
}

初始化函数

DSTATUS disk_initialize(BYTE pdrv /* 物理编号 */
)
{uint16_t i;DSTATUS status = STA_NOINIT;switch (pdrv){case ATA: /* SD CARD */break;case SPI_FLASH: /* SPI Flash */sfud_init();flash1 = sfud_get_device_table() + 0; //对应到设备表的第一个// printf("%0x\n", spi4_flash_readID());//如果不清楚设备id的话,可以在这里打印一下status = disk_status(SPI_FLASH); //获取设备状态break;default:status = STA_NOINIT;}return status;
}

读取函数

DRESULT disk_read(BYTE pdrv,    /* 设备物理编号(0..) */BYTE *buff,   /* 数据缓存区 */DWORD sector, /* 扇区首地址 */UINT count    /* 扇区个数(1..128) */
)
{DRESULT status = RES_PARERR;switch (pdrv){case ATA: /* SD CARD */break;case SPI_FLASH://这里的左移12位,等于4096,因为flash的一个扇区是4k字节sfud_read(flash1, sector << 12, count << 12, buff);status = RES_OK;break;default:status = RES_PARERR;}return status;
}

写入函数

#if _USE_WRITE
DRESULT disk_write(BYTE pdrv,        /* 设备物理编号(0..) */const BYTE *buff, /* 欲写入数据的缓存区 */DWORD sector,     /* 扇区首地址 */UINT count        /* 扇区个数(1..128) */
)
{DRESULT status = RES_PARERR;if (!count){return RES_PARERR; /* Check parameter */}switch (pdrv){case ATA: /* SD CARD */break;case SPI_FLASH:sfud_erase(flash1, sector << 12, 4096); // SPI_FLASH都是要先擦除为1才能写sfud_write(flash1, sector << 12, count << 12, (uint8_t *)buff);status = RES_OK;break;default:status = RES_PARERR;}return status;
}
#endif

设备信息函数

#if _USE_IOCTL
DRESULT disk_ioctl(BYTE pdrv, /* 物理编号 */BYTE cmd,  /* 控制指令 */void *buff /* 写入或者读取数据地址指针 */
)
{DRESULT status = RES_PARERR;switch (pdrv){case ATA: /* SD CARD */break;case SPI_FLASH:switch (cmd){//扇区数量就是例如我这里是8M的flash//那就是 8 * 1024 * 1024 (字节)/ 4096(一个扇区的大小) = 2048(扇区数)case GET_SECTOR_COUNT:*(DWORD *)buff = 2048; //这里是你的扇区数量break;/* 扇区大小  */case GET_SECTOR_SIZE:*(WORD *)buff = 4096;break;/* 同时擦除扇区个数 */case GET_BLOCK_SIZE:*(DWORD *)buff = 1;break;}status = RES_OK;break;default:status = RES_PARERR;}return status;
}
#endif

获取时间函数

//这里是获取时间函数,后续如果有需要的话,可以使用rtc的时间
__weak DWORD get_fattime(void)
{/* 返回当前时间戳 */return ((DWORD)(2015 - 1980) << 25) /* Year 2015 */| ((DWORD)1 << 21)           /* Month 1 */| ((DWORD)1 << 16)           /* Mday 1 */| ((DWORD)0 << 11)           /* Hour 0 */| ((DWORD)0 << 5)            /* Min 0 */| ((DWORD)0 >> 1);           /* Sec 0 */
}
  • 对于ffconf.h主要是修改一下宏定义即可
    在这里插入图片描述

到这里就已经是移植好啦

然后就可以开始进行测试啦
main.c文件

#include "main.h"
#include "bsp_led.h"
#include "bsp_usart.h"
#include "gd32f4xx.h"
#include "sys.h"
#include "systick.h"
#include <stdio.h>#include "bsp_spi.h"
#include <sfud.h>#include "ff.h"FATFS fs;													/* FatFs文件系统对象 */
FIL fnew;													/* 文件对象 */
FRESULT res_flash;                /* 文件操作结果 */
UINT fnum;            					  /* 文件成功读写数量 */
BYTE ReadBuffer[1024]={0};        /* 读缓冲区 */
BYTE WriteBuffer[] =              /* 写缓冲区*/
"欢迎使用野火STM32 F429开发板 今天是个好日子,新建文件系统测试文件\r\n";  /*!\brief    main function\param[in]  none\param[out] none\retval     none
*/
int main(void)
{systick_config();led_gpio_config(); // led初始化usart_gpio_config(115200U);/* SFUD initialize */
//    if (sfud_init() == SFUD_SUCCESS)
//    {
//       sfud_demo(0, sizeof(sfud_demo_test_buf), sfud_demo_test_buf);
//    }printf("****** 这是一个SPI FLASH 文件系统实验 ******\r\n");//在外部SPI Flash挂载文件系统,文件系统挂载时会对SPI设备初始化res_flash = f_mount(&fs,"1:",1);/*----------------------- 格式化测试 ---------------------------*/  /* 如果没有文件系统就格式化创建创建文件系统 */if(res_flash == FR_NO_FILESYSTEM){printf("》FLASH还没有文件系统,即将进行格式化...\r\n");/* 格式化 */res_flash=f_mkfs("1:",0,0);							if(res_flash == FR_OK){printf("》FLASH已成功格式化文件系统。\r\n");/* 格式化后,先取消挂载 */res_flash = f_mount(NULL,"1:",1);			/* 重新挂载	*/			res_flash = f_mount(&fs,"1:",1);}else{printf("《《格式化失败。》》\r\n");while(1);}}else if(res_flash!=FR_OK){printf("!!外部Flash挂载文件系统失败。(%d)\r\n",res_flash);printf("!!可能原因:SPI Flash初始化不成功。\r\n");printf("请下载 SPI—读写串行FLASH 例程测试,如果正常,在该例程f_mount语句下if语句前临时多添加一句 res_flash = FR_NO_FILESYSTEM; 让重新直接执行格式化流程\r\n");while(1);}else{printf("》文件系统挂载成功,可以进行读写测试\r\n");}/*----------------------- 文件系统测试:写测试 -----------------------------*//* 打开文件,如果文件不存在则创建它 */printf("\r\n****** 即将进行文件写入测试... ******\r\n");	res_flash = f_open(&fnew, "1:FatFs读写测试文件.txt",FA_CREATE_ALWAYS | FA_WRITE );if ( res_flash == FR_OK ){printf("》打开/创建FatFs读写测试文件.txt文件成功,向文件写入数据。\r\n");/* 将指定存储区内容写入到文件内 */res_flash=f_write(&fnew,WriteBuffer,sizeof(WriteBuffer),&fnum);if(res_flash==FR_OK){printf("》文件写入成功,写入字节数据:%d\n",fnum);printf("》向文件写入的数据为:\r\n%s\r\n",WriteBuffer);}else{printf("!!文件写入失败:(%d)\n",res_flash);}    /* 不再读写,关闭文件 */f_close(&fnew);}else{	printf("!!打开/创建文件失败。\r\n");}/*------------------- 文件系统测试:读测试 ------------------------------------*/printf("****** 即将进行文件读取测试... ******\r\n");res_flash = f_open(&fnew, "1:FatFs读写测试文件.txt", FA_OPEN_EXISTING | FA_READ); 	 if(res_flash == FR_OK){printf("》打开文件成功。\r\n");res_flash = f_read(&fnew, ReadBuffer, sizeof(ReadBuffer), &fnum); if(res_flash==FR_OK){printf("》文件读取成功,读到字节数据:%d\r\n",fnum);printf("》读取得的文件数据为:\r\n%s \r\n", ReadBuffer);	}else{printf("!!文件读取失败:(%d)\n",res_flash);}		}else{printf("!!打开文件失败。\r\n");}/* 不再读写,关闭文件 */f_close(&fnew);	/* 不再使用文件系统,取消挂载文件系统 */f_mount(NULL,"1:",1);while (1){}
}
效果如下

在这里插入图片描述
origin_url=image-4.png&pos_id=img-2thXHWxj-1721718767616)

移植成功

相关的开源代码:gitee

如果对你有所帮助的话,请给我点一个star,嘿嘿

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/50601.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【ESP32 IDF 软件模拟SPI驱动 W25Q64存储与读取数组】

目录 SPISPI介绍SPI时序代码编写&#xff08;spi&w25q64&#xff09; 代码调试 SPI SPI介绍 SPI&#xff08;Serial Peripheral Interface&#xff0c;串行外围设备接口&#xff09;是一种高速、全双工、同步的串行通信总线&#xff0c;常用于微控制器与各种外围设备&…

苍穹外卖浏览器前端界面修改

背景&#xff1a; 客户原始方案是期望做一个Spring Boot Vue的饿了么系统&#xff0c;但时间上太仓促&#xff0c;所以建议选择开源的苍穹外码目作为作业提交。 客户接受了建议的方案后&#xff0c;期望对前端页面做一些个性化的定制修改。 过程&#xff1a; 苍穹外卖简单介…

【HTML+CSS】HTML超链接:构建网页导航的基石

目录 什么是HTML超链接&#xff1f; 基本语法 示例 链接到另一个网页 链接到同一页面内的不同部分 常用属性 在Web开发的广阔世界中&#xff0c;HTML&#xff08;HyperText Markup Language&#xff09;作为网页内容的标准标记语言&#xff0c;扮演着至关重要的角色。而在…

重拾CSS,前端样式精读-函数(颜色,计算,图像和图形)

前言 本文收录于CSS系列文章中&#xff0c;欢迎阅读指正 在计算机编程中&#xff0c;函数有着重要的作用和意义&#xff0c;它可以实现封装&#xff0c;复用&#xff0c;模块化&#xff0c;参数等功能效果&#xff0c;在如何在CSS中写变量&#xff1f;一文带你了解前端样式利…

操作系统杂项(十)

目录 一、简述socket中select、epoll的使用场景和区别 1、使用场景 2、区别 二、epoll水平触发和边缘触发的区别 三、简述Reactor和Proactor模式 1、Reactor 2、Proactor 3、区别 四、简述同步和异步的区别&#xff0c;阻塞和非阻塞的区别 1、同步与异步 2、阻塞与非…

深入分析 Android ContentProvider (五)

文章目录 深入分析 Android ContentProvider (五)ContentProvider 的性能优化和实践案例1. 性能优化技巧1.1. 数据库索引优化示例&#xff1a;添加索引 1.2. 批量操作与事务管理示例&#xff1a;批量插入操作 1.3. 使用异步操作示例&#xff1a;使用 AsyncTask 进行异步查询 1.…

Linux:基础

一、安装 二、 一些组件 2.1 git管理 集中式版本控制系统:版本库是集中存放在中央服务器的,需要时要先从中央服务器取得最新的版本进行修改,修改后再推送给中央服务器。集中式版本控制系统最大的毛病就是必须联网才能工作,网速慢的话影响太大。 分布式版本控制系统:分布…

Linux网络-wget命令

作者介绍&#xff1a;简历上没有一个精通的运维工程师。希望大家多多关注我&#xff0c;我尽量把自己会的都分享给大家&#xff0c;下面的思维导图也是预计更新的内容和当前进度(不定时更新)。 Linux服务器作为一个常用的网络服务器&#xff0c;主要的作用就是向客户端提供网络…

设计模式14-享元模式

设计模式14-享元模式 由来动机定义与结构代码推导特点享元模式的应用总结优点缺点使用享元模式的注意事项 由来动机 在很多应用中&#xff0c;可能会创建大量相似对象&#xff0c;例如在文字处理器中每个字符对象。在这些场景下&#xff0c;如果每个对象都独立存在&#xff0c…

PyCharm 2024.1.4:一站式教程与新特性解析

简介 PyCharm是由JetBrains开发的一款Python集成开发环境&#xff08;IDE&#xff09;&#xff0c;自发布以来&#xff0c;凭借其强大的功能、智能的代码补全、广泛的插件支持和用户友好的界面&#xff0c;成为了Python开发者的首选工具之一。无论是数据科学、Web开发还是其他…

Redis - SpringDataRedis - RedisTemplate

目录 概述 创建项目 引入依赖 配置文件 测试代码 测试结果 数据序列化器 自定义RedisTemplate的序列化方式 测试报错 添加依赖后测试 存入一个 String 类型的数据 测试存入一个对象 优化 -- 手动序列化 测试存入一个Hash 总结&#xff1a; 概述 SpringData 是 S…

在 ArchLinux 上编译运行 axmol 引擎

本文将在 Windows 10 上安装 Arch WSL 中编译 axmol 请确保 WSL2 已正确安装 1. 在微软应用商店安装 ArchLinux 2. 打开 Arch&#xff0c;按照提示输入用户名和密码&#xff0c;尽量简单 3. 配置清华源&#xff0c;速度快的起飞&#xff0c;否则&#xff0c;各种包会安装失败…

光伏电站气象站:现代光伏系统的重要组成部分

光伏电站气象站&#xff0c;作为现代光伏系统的重要组成部分&#xff0c;集成了气象学、电子信息技术、数据处理与分析等多学科技术于一体&#xff0c;能够实时监测并记录包括温度、湿度、风速、风向、太阳辐射强度、降雨量在内的多种气象参数。这些数据不仅是评估光伏板发电效…

GLSL教程 第8章:几何着色器

目录 8.1 几何着色器的介绍 几何着色器的主要功能&#xff1a; 几何着色器的工作流程&#xff1a; 8.2 实现基本的几何变换 示例&#xff1a;将三角形扩展成多个三角形 8.3 几何着色器的高级应用 1. 粒子系统 2. 光晕效果 3. 线框模型 小结 几何着色器是图形管线中的一…

应用层自定义协议以及序列化和反序列化

文章目录 应用层自定义协议以及序列化和反序列化1、应用层自定义协议1.1、应用层1.2、协议 2、序列化和反序列化3、TCP 为什么支持全双工4、jsoncpp基础4.1、序列化4.2、反序列化 5、实现网络版计算器6、手写序列化和反序列化 应用层自定义协议以及序列化和反序列化 1、应用层…

爬取贴吧的标题和链接

免责声明 感谢您学习本爬虫学习Demo。在使用本Demo之前&#xff0c;请仔细阅读以下免责声明&#xff1a; 学习和研究目的&#xff1a;本爬虫Demo仅供学习和研究使用。用户不得将其用于任何商业用途或其他未经授权的行为。合法性&#xff1a;用户在使用本Demo时&#xff0c;应确…

智能算法驱动的爬虫平台:解锁网络数据的无限潜力

摘要 在信息爆炸的时代&#xff0c;网络数据如同深海宝藏&#xff0c;等待着有识之士发掘其无尽价值。本文将探索智能算法驱动的爬虫平台如何成为解锁这一宝库的关键&#xff0c;不仅剖析其技术优势&#xff0c;还通过实例展示它如何助力企业与开发者高效、稳定地采集数据&…

C语言 ——— 数组指针的定义 数组指针的使用

目录 前言 数组指针的定义 数组指针的使用 前言 之前有编写过关于 指针数组 的相关知识 C语言 ——— 指针数组 & 指针数组模拟二维整型数组-CSDN博客 指针数组 顾名思义就是 存放指针的数组 那什么是数组指针呢&#xff1f; 数组指针的定义 何为数组指针&#xf…

【QT】UDP

目录 核心API 示例&#xff1a;回显服务器 服务器端编写&#xff1a; 第一步&#xff1a;创建出socket对象 第二步&#xff1a; 连接信号槽 第三步&#xff1a;绑定端口号 第四步&#xff1a;编写信号槽所绑定方法 第五步&#xff1a;编写第四步中处理请求的方法 客户端…

JAVA开发工具IDEA如何连接操作数据库

一、下载驱动 下载地址&#xff1a;【免费】mysql-connector-j-8.2.0.jar资源-CSDN文库 二、导入驱动 鼠标右击下载到IDEA中的jar包&#xff0c;选择Add as Library选项 如图就导入成功 三、加载驱动 Class.forName("com.mysql.cj.jdbc.Driver"); 四、驱动管理…