串行FLASH文件系统FatFs-移植过程

news2024/11/26 13:33:10

目录

串行FLASH文件系统FatFs-移植过程

准备工作及移植前说明

底层disk接口程序API配置

中间层API功能实现及常用文件操作函数使用

 文件系统偏移

中文文件名和长文件名


串行FLASH文件系统FatFs-移植过程

准备工作及移植前说明

我们需要在SPI——读写串行FLASH的基础驱动程序上进行FatFs文件系统的移植。

首先我们将FatFS的src文件夹复制到STM32 FLASH工程下的USER目录,并重命名为FATFS

我们移植文件系统主要就是实现底层disk函数的具体功能

底层disk接口程序API配置

1、首先将diskio.c和ff.c包含到工程中

2、添加完成之后,点击编译,报错找不到头文件,我们需要将diskio.c官方测试样例的三个头文件注释掉

3、将diskio.c中的result = ATA_disk_status();、result = MMC_disk_status();和result = USB_disk_status();注释

4、注释完之后,再次编译,找不到get_fattime

我们需要手动将get_fattime()函数添加到文件中

get_fattime()函数需要返回一个时间值,我们暂时先不管,让值返回0

5、我们可以发现diskio.h中官方已经定义了三个物理存储介质编号ATA、MMC和USB,diskio中的所有存储介质操作函数通过传入参数判断区分具体操作哪个存储介质

我们将其都注释掉,然后自定以两个存储介质SD_CARD和SPI_FLASH,并将所有底层操作函数中所有的switch case中的原存储介质替换掉

6、首先我们来看disk_initialize函数,只有一个参数用于传入存储设备编号,编号用于区分操作的存储器,返回值返回当前的存储器状态。该函数用于初始化存储设备,并使设备进入读写可用的状态,初始化完之后用于返回一个状态值来告诉上层的调用者。

该函数用于被FatFs module(中间层)调用,不能直接使用,需要使用中间层的f_mount挂载函数来调用(我们初始化文件系统都通过使用f_mount来实现)

(1)首先将SPI_FLASH_Init();函数添加到“case SPI_FLASH :”中。

(2)接着要返回一个状态,但我们仅仅通过SPI_FLASH_Init()不知道是否初始化FLASH成功。因此我们通过SPI_FLASH_ReadID()函数通过判断读取设备号是否成功来判断。

将SPI_FLASH_ReadID()放在“DSTATUS disk_status (BYTE pdrv){}”状态读取函数中

(3)状态读取函数共有三种状态返回值,分别表示设备初始化失败、未发现设备、设备写保护三种。通过低三位的状态标志位来确定设备状态。

一般来说我们的FLASH不存在写保护的状态,而我们判断FLASH是否初始化成功是通过读取ReadID和sFLASH_ID这个宏是否相等来确定的。因此结果只有两种状态,所以我们初始化状态正常就直接返回0(将所有位都置0),而初始化状态失败就返回STA_NOINIT或者STA_NODISK。

通过返回值,上层就可以知道设备初始化成功或者失败、或者物理设备不存在,并出现提醒的错误。

(4)如果我们不确定FLASH是否处于低功耗模式,我们需要在init后面添加SPI_Flash_WAKEUP()函数来确保FLASH处于正常功耗模式(因为FLASH在低功耗状态下,无法正常工作)

7、继续我们来配置disk_read()函数

disk_read()用于读取扇区(一个或者多个),第一个参数为设备号;第二个参数为读取扇区的起始地址,读取完数据后通过指针返回给上层,具体传入数组或指针由上层定义;第三个参数为开始的扇区号;第四个个参数为读取的扇区个数

返回值要注意其中的RES_PARERR表示输入的参数不支持(sector超出范围等导致)

通过调用void SPI_FLASH_BufferRead(u8* pBuffer, u32 ReadAddr, u16 NumByteToRead);函数来实现扇区的读取。通过disk_read()中的sector扇区号来计算出ReadAddr起始地址,通过count扇区个数来算出NumByteToRead要读取多少个字节。

这里回忆一下知识点:一个扇区4096Byte(4KB),一个块有16个扇区

通过调用SPI_FLASH_BufferRead()函数,并算出对应参数。默认读取成功,返回值为RES_OK

8、接着配置disk_write()函数

参数与disk_read()相同

对于写入,我们的SPI-FLASH没有检测是否写入的功能,因此直接返回RES_OK

注意使用写功能,必须将_FS_READONLY置0,否则只支持只读

9、再来配置disk_ioctl函数,

在初始化设备前,必须将存储设备进行格式化,建立好文件信息结构,从而才能实现对设备存储内容以文件格式进行读写。

第一个参数为设备号;第二个参数为cmd命令号,文件系统通过命令号来告诉底层,比如获取当前设备的容量,某个文件的大小等等(底层通过switch...case...来确定不同的返回值);第三个参数buff既可以作为输入也可以作为输出

具体的cmd命令如下

具体命令使用需要配置对应条件

(1)开始对FLASH进行配置

(2)这里以常用三个命令进行配置为例

返回值默认成功,res = RES_OK。

(3)先看GET_SECTOR_COUNT

根据注释需要将扇区个数赋值给buff从而传给上层,需要将buff强制转换成DWORD*

同理GET_SECTOR_SIZE和GET_BLOCK_SIZE,也需要赋值给buff,并强转为对应指针变量类型

注:buff原来为void*类型

配置完成如下:

10、最后看get_fattime,返回当前时间,值为32bit

具体手动配置固定时间可配置如下

如果想实现动态标准时间,可以配置RTC,再配置该函数

至此diskio.c配置完成,接下来配置ffconfig.h

11、需要使用文件系统的时候,我们只需要添加ff.h头文件包含即可

中间层API功能实现及常用文件操作函数使用

在使用文件系统时,首先要调用f_mount()函数进行文件系统挂载,从而配置和初始化文件系统

1、f_mount()函数

 

第一个参数为文件系统句柄,其中drv为之前在diskio.c中定义的设备号,csize为簇(表示多个扇区),ssize为每个扇区的大小,最后一个成员win[_MAX_SS]为文件系统的缓冲区

由于文件系统句柄变量所占空间很大,我们定义放在全局区,每一个存储设备需要单独定义文件系统句柄。

如果传入参数为NULL,表示取消挂载,释放当前程序的所有文件系统空间。

第二个参数path,我们设置为"0:"就代表选择第一个存储设备,由于我们刚刚设置的FLASH设备号为1,所以设置"1:"

第三个参数设置为0,表示稍后挂载;设置为1,表示立即挂载。我们一般都设置为1

f_mount()返回值为FRESULT,如下所示

2、烧写程序

返回值为11,表示设备号不可用

我们将_VOLUMES值设置为2,支持两个设备可以使用

3、继续烧写,这次出现硬件卡死

这是因为我们的FLASH每个扇区为4096字节,刚刚在diskio.c中刚配置完

我们将配置文件中的_MAX_SS改为4096,从而支持扇区最大为4096(512在SD卡应用较多)

4、再次烧写,res返回值为13,表示未找到文件系统,这是因为我们还没有创建(格式化)文件系统

5、使用f_mkfs()函数创建文件系统(注意格式化会将存储设备原来所有内容全部删除)

第一个参数为设备路径

第二个参数,如果为FDISK表示SD卡、FLASH这一类存储设备,SFD表示使用软盘。这里我们使用FDISK

第三个参数,表示每个簇的大小,我们之间设置为自动分配

返回值也为FRESULT

 

我们设置为如果res返回值为FR_NO_FILESYSTEM,就初始化设备,否则不初始化

但是编译报错出现无法识别f_mkfs函数,这是因为官方默认进行了文件系统的裁剪,不可用使用格式化。

因此我们再ffconf.h中将_USE_MKFS配置为1,支持文件系统初始化

6、重新烧入程序,再次复位还是找不到设备

这是因为我们在使用f_mkfs函数进行写入文件系统的信息结构之前,没有擦除FLASH,这就会导致信息写入不进去,就无法格式化成功。

因此在disk_write()函数中添加擦除扇区函数

再次烧写,格式化成功

7、注意在格式化之后如果要使用文件系统,必须先取消挂载,再重新挂载文件系统

8、打开或者创建一个文件要使用f_open函数,与C库函数类似,不作过多解释

第一个参数为文件句柄(不是文件系统句柄)

第二个参数为文件路径,如"1:test.txt"

第三个参数为文件模式

文件句柄具体内容如下

我们创建一个test.txt文件

9、使用f_write向文件写入内容,写入的内容可以为中文(即使没有配置中文编码页也行,但是没有中文编码页会导致文件名和存储路径不可用为中文)

10、使用f_read进行读取文件内容

第三个参数btr表示要读取的内容大小,我们可以使用f_size函数来获取文件的大小,通过第四个参数和第三个参数比较,我们可以判断是否读取到文件末尾

在读取文件前,我们要使用f_lseek()函数定位文件指针到文件开头

首先定义两个变量,一个用来获取已读取内容大小,一个用来存储读取内容

然后进行文件内容读取

烧入程序,读写内容成功

我们可以将_USE_FASTSEEK定义为1,进行快速定位

如果将_FS_MINIMIZE配置为3,就不支持定位了

11、最后读写完文件,一定要记得关闭,否则无法数据还在缓冲区内,无法真正存入文件。

 

 文件系统偏移

1、文件系统向后偏移2MB

只需要修改diskio.c中的disk_read、disk_write、disk_ioctl即可

分别修改如下:(增加红色部分即可,其它不变)

中文文件名和长文件名

添加中文编码页和实现长文件名

首先添加cc936.c文件

 然后修改_CODE_PAGE为936,支持中文编码

修改_USE_LFN为非0值,从而支持长文件名,设置为1,存储在全局区

更多功能可以深入探索。

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

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

相关文章

winform打印机控制程序记录

1.Invoke 跨线程访问 有些回调函数不能直接访问控件的属性,这时就需要用到这个。 用法: Invoke(new Action(() >{//正常代码receiveCount;tb_recvCount.Text Convert.ToString(receiveCount);}));2.控制打印机打印 2.1.绘制表格 准备一个 panel …

Redis---缓存双写一致性

目录 一、什么是缓存双写一致性呢? 1.1 双检加锁机制 二、数据库和缓存一致性的更新策略 2.1、先更新数据库,后更新缓存 2.2 、先更新缓存,后更新数据库 2.3、先删除缓存,在更新数据库 延时双删的策略: 2.4.先更新数…

手把手一起完成Python上位机与下位机USB通信

前言 最近在使用Python设计上位机,下位机是ZYNQ7000,两者通过USB进行数据传输。该文章是USB通信过程的踩坑记录 一、安装所需库 首先,安装pyusb和libusb两个库,命令如下: pip install pyusbpip install libusb如图…

CUDA笔记2

1.硬件理解 1.1对应 1.2 不一定是同时执行 例如只有13个sm,每个sm有128个core,而我们创建了1百万个threads,就要同步执行 因此&#xff0c;我们倾向于在block的x维设置为32的倍数,防止浪费warp warp id打印 #include <stdio.h> #include <stdlib.h>#include &qu…

Acwing 849. Dijkstra求最短路 I

Acwing 849. Dijkstra求最短路 I 链接:849. Dijkstra求最短路 I - AcWing题库 /*题解:dijkstra算法模板对于单源最短路径dijkstra1.每次找到当前距离源最近的节点 作为确定距离的点2.通过这个点看能否让其他的节点来松弛其他点到源的距离重复12操作*/ #include<algorithm&g…

完美解决win10系统cmd命令无法使用ssh

最近我在远程访问服务器的时候&#xff0c;在winR运行cmd的时候&#xff0c;输入ssh来获得本地和服务器映射&#xff0c;无法实现。提示&#xff1a;’SSH’ 不是内部或外部命令&#xff0c;也不是可运行的程序 或批处理文件。 下面的方法可以完美解决这个问题&#xff1a; 目…

四大运营商的优缺点,你的选择是对的吗?

随着2022年中国广电获得基础运营商服务牌照&#xff0c;中国从三大运营商变成了四大运营商&#xff1a;中国移动&#xff0c;中国联通&#xff0c;中国电信&#xff0c;中国广电。这四大运营商到底都有什么优缺点呢&#xff1f;大家一直在用的运营商手机卡&#xff0c;大家了解…

REE刷TLB时会把安全的TLB刷掉吗

思考: REE刷TLB时会把安全的TLB刷掉吗? TEE刷TLB时能否刷安全的TLB?例如页表管理着的共享内存,它的翻译缓存到了TLB. 首先,纠正一下用词,这里的"刷",来自某些操作系统中的"flush",在TLB底层的操作指令中,是没有flush或clean的,关于TLB的操作指令…

基于linux下的高并发服务器开发(第一章)- 静态库的使用1.5

1、创建lesson05文件夹&#xff0c;mkdir lesson05,然后创建子文件夹calc和library 在calc文件夹下有文件add.c&#xff0c;div.c&#xff0c;mult.c &#xff0c; sub.c &#xff0c;head.h&#xff0c;main.c在library文件夹下有文件夹include&#xff0c;lib&#xff0c;sr…

目标跟踪基础:数据关联算法

本文来自公众号“AI大道理” —————— 数据关联是多目标跟踪任务中的关键步骤&#xff0c;其目的主要是为了进行帧与帧之间的多个目标的匹配。 1、数据关联 数据关联其实就是一个沿着时间轴&#xff0c;将来自同一个物体的不同时刻的信号串联起来的过程。 数据关联通常在…

探索基于300W-LP的3D人脸关键点检测

目录 前言一、&#xff13;D 关键点可视化二、使用步骤1.300W-LP转为YOLO数据格式2.修改数据入口3.开始训练 总结 前言 300WLP数据集提供来丰富的人脸线索&#xff0c;包括&#xff12;D或&#xff13;D的关键点信息&#xff0c;Head Angle和&#xff13;DMM的参数等&#xff…

【岗位】IT行业岗位知识图谱--大数据工程师、机器学习、嵌入式、架构师

目录 1. 大数据工程师技能图谱2. 机器学习技能图谱3. 架构师技能图谱4. 嵌入式开发必备技能5. 嵌入式体系结构 1. 大数据工程师技能图谱 2. 机器学习技能图谱 3. 架构师技能图谱 4. 嵌入式开发必备技能 5. 嵌入式体系结构 **点赞、关注、评论、收藏哦**

7.7.8clip/简单量化

一、 clip函数&#xff1a;限制一个array的上下界 给定一个范围[min, max]&#xff0c;数组中值不在这个范围内的&#xff0c;会被限定为这个范围的边界。如给定范围[0, 1]&#xff0c;数组中元素值小于0的&#xff0c;值会变为0&#xff0c;数组中元素值大于1的&#xff0c;要…

【云存储】主流分布式文件系统介绍

目录 1、引言 2、云存储与分布式文件系统 2.1、云存储 2.2、分布式文件系统 3、Google的三大云计算与云存储论文 3.1、The Google File System&#xff08;谷歌文件系统&#xff09; 3.2、MapReduce&#xff1a;Simplified Data Processing on Large Clusters&#xff0…

云原生之深入解析Kubernetes CNI插件的选型和应用场景

一、常见网络插件 在学习容器网络的时候&#xff0c;肯定都听说过 Docker 的 bridge 网络、Vethpair、VxLAN 等术语&#xff0c;从 Docker 到 Kubernetes 后&#xff0c;学习 Flannel、Calico 等主流网络插件&#xff0c;分别代表了 Overlay 和 Underlay 的两种网络传输模式&a…

【VirtualBox】安装 VirtualBox 提示 needsthe Microsoft Visual C++ 2019

概述 一个好的文章能够帮助开发者完成更便捷、更快速的开发。书山有路勤为径&#xff0c;学海无涯苦作舟。我是秋知叶i、期望每一个阅读了我的文章的开发者都能够有所成长。 一、开发环境 开发环境&#xff1a;windows10虚拟机&#xff1a;VirtualBox 7.0.8 二、报错 ubun…

多条件见多值查询的 Excel 公式和 python 函数

问题 Python草堂 群的一位群友问&#xff1a;excel 数据表&#xff0c;用 vlookup 函数怎样实现多条件查询多值&#xff0c;多值排到一行上。如下图所示&#xff1a; 左边是数据清单&#xff0c;希望根据两个条件&#xff1a;产品、日期&#xff0c;查询数量&#xff0c;列到…

Element-UI el-table属性row-class-name用法

文章目录 前言官方示例自定义条件样式设置背景颜色样式stripe属性 设置背景颜色样式设置字体颜色总结 前言 可以通过指定 Table 组件的 row-class-name 属性来为 Table 中的某一行添加 class&#xff0c;表明该行处于某种状态。 官方示例 代码如下&#xff1a; <el-table…

体验版小程序为何无法访问云端服务器后端接口(请求失败...(已完美解决附加图片))?

文章目录 前言解决方案一解决方案二第一步第二步 前言 体验版小程序访问不到后端&#xff0c;接口请求失败&#xff0c;这个及其头疼的今天这个坑被我踩到了&#xff0c;呜呜呜~ 今天再发体验版小程序时&#xff0c;在微信开发者工具上面是可以正常访问后端的&#xff0c;但是线…

【sql注入-堆叠注入】多语句执行、结合其他注入

目录 堆叠注入 一、语法介绍 二、漏洞示例 三、常见形式 网络安全O 堆叠注入 一、语法介绍&#xff1a; 版本&#xff1a; 可以影响几乎所有的关系型数据库 原理&#xff1a; 将多条语句堆叠在一起进行查询&#xff0c;且可以执行多条SQL语句 语句之间以分号(;)隔开&#…