当前位置: 首页 > news >正文

019 - STM32学习笔记 - Fatfs文件系统(一) - FatFs文件系统初识

019 - STM32学习笔记 - Fatfs文件系统(一) - FatFs文件系统初识

最近工作比较忙,没时间摸鱼学习,抽空学点就整理一点笔记。

1、文件系统

在之前学习Flash的时候,可以调用SPI_FLASH_BufferWrite函数,将数据内容写入到Flash芯片中,需要使用的时候,可以再从Flash中读取出来,但是我们每次写入数据的时候,有以下三点比较麻烦:

  1. 有效数据的位置不方便记录;
  2. 存储数据量大小可能随时变动,对于Flash的容量剩余大小难以确定;
  3. 存储数据类型多变,读取时不确定该以何种格式解读数据。

目前我们接触到的Windows/Linux系统就是比较常见的文件系统,我们在Windows/Linux中查找文件只需要根据文件的存储路径就可以方便的找到需要的文件,文件内容读取可以通过文件类型(例如txt、exe等)方式去通过特定的打开方式去使用。

数据文件在硬盘(以机械硬盘为例)中的存储,是将硬盘分为盘片-扇区-磁道的方式分布存储在磁道中,文件存储时,磁盘会记录文件存储的地址,当使用文件的时候,会根据地址寻址进行读取写入磁盘。

为了存储和管理数据方便,在存储介质中会建立组织结构,包含操作系统的引导区、目录和文件。常见的Windows系统下文件系统格式包括FAT32、NTFS、exFAT,我们拿到新的磁盘时,需要将磁盘格式化为上述的一种文件格式,格式化时,会在磁盘中建立一个文件分配表和目录,后续文件系统可以在文件分配表和目录中记录数据存放的地址以及剩余空间了。
在这里插入图片描述

如上图,Windows中将磁盘通过逻辑划分,将整块硬盘划分为几块,包含主引导记录分区(MBR),基本分区1-3,逻辑分区等,其中主引导分区中记录着后续几个分区的物理地址,可以通过这些物理地址找到后续分区,这里会装系统的基本都懂,就不过多阐述了,感兴趣的可以百度一下学习学习。

当使用文件系统时,数据都是以文件的方式进行存储。写入新文件时,首先要在目录中创建一个文件索引,用来指示文件存放的物理位置,然后再将文件存储到该地址中;当需要读取数据时,首先到目录中查找读取数据的文件索引,再到相应的地址中区读取数据。这期间还牵扯到逻辑地址、簇大小、不连续存储等一系列过程。

文件存储时,不仅仅是简单的向某个物理地址直接读写,需要以一定的既定格式进行读写。

在这里插入图片描述

例如在火哥的教程中举的例子,假设现在有0-99共100簇的存储空间(簇可以理解为扇区),其中第0簇是文件分配表,第1簇为目录,后续几个文件分别占用不同数量的扇区存储文件,这些文件的存储信息都在记录在第1簇的目录中。

在这里插入图片描述

目录表

在这里插入图片描述

文件分配表 - 连续存储

当需要读取文件时,根据目录相中,读取到开始簇为2,找到文件分配表中,第2簇上读取到数据为3,表示下一部分数据指向存储在第3簇上,再到第3簇记录上读到下一簇得数据指向为4,一次向后,直到最后一簇11时,发现下一个指向为FF,表示到文件末尾了,到此文件就读取完了。到这里的时候,起始发现这种指向方式很像链表,链表头指向的时数据存放的位置,链表尾,指向的是下一个数据起始位置。

上面这个表中,数据是连续存储的,假如我们对文件进行修改了,可能原来的存储单元存不下更多的数据,那么后续增加的内容可能会放到其他簇中,这样在原来的第11簇位置指向的FF就变更为后续文件存储的起始位置了。如下图

在这里插入图片描述

文件分配表 - 不连续存储

2、FatFs系统

FatFs是面向小型嵌入式系统的一种通用的FAT文件系统,由AISI C语言编写,并且完全独立于底层的I/O介质。因此它可以很容易的不加修改一直到其他处理器中。

上节中我们已经写好用SPI读写Flash,这节开始就可以将FatFs文件系统代码移植进去,就可以使用文件系统的各种函数,对Flash采用文件的方式进行读写了。

学习中使用到的FatFs文件系统官网地址:

FatFs文件系统官网

目前官网最新的FatFs版本为ff15,野火教程中使用的为ff11a,这里也就根据野火教程先进行学习,等到后面抽空再学习最新的版本。

在下载好的FatFs源码文件中,在documents目录下,有关于此源码的说明,关于接口函数的说明可以看一下说明文档,这里不做过多赘述。

在src文件夹中,有个read.txt,里面对源码中的各个文件都做了说明,感兴趣的可以看一下。

文件名功能
integer.h文件中包含了一些数值类型的定义。
diskio.c包含底层存储介质的操作函数,这些函数需要用户自己实现,主要添加底层驱动函数。
ff.cFatFs核心文件,文件管理的实现方法。该文件独立于底层介质操作文件的函数,利用这些函数实现文件的读写。
cc936.c本文件在option目录下,是简体中文支持所需要添加的文件,包含了简体中文的GBK和Unicode互相转换功能函数
ffconf.h这个头文件包含了对FatFs功能配置的宏定义,通过修改这些宏定义就可以裁剪FatFs的功能,如果需要支持简体中文,需要把ffconf.h中的_CODE_PAGE的宏改成936,并把上面的ccp36.c文件加入到工程中。

在以上几个文件中,我们需要修改的主要是diskio.c、ff.c以及ffconf.h,这里针对性的讲一下关于FatFs文件系统移植需要注意的地方。

先看一下FatFs在程序中的关系网络图:

在这里插入图片描述

这里先分析一下ff.c、diskio.c这几个文件:

diskio.c中,我们主要了解一下DRESULT disk_read (BYTE pdrv,BYTE *buff,DWORD sector,UINT count)函数

#define ATA		0	/* 硬盘设备标号为0 */
#define MMC		1	/* MMC/SD设备标号为1 */
#define USB		2	/* USB设备标号为2 */
DRESULT disk_read (BYTE pdrv,BYTE *buff,DWORD sector,UINT count)
{DRESULT res;int result;switch (pdrv) {case ATA :// translate the arguments hereresult = ATA_disk_read(buff, sector, count);// translate the reslut code herereturn res;case MMC :// translate the arguments hereresult = MMC_disk_read(buff, sector, count);// translate the reslut code herereturn res;case USB :// translate the arguments hereresult = USB_disk_read(buff, sector, count);// translate the reslut code herereturn res;}return RES_PARERR;
}

disk_read函数是Fatfs与底层程序对接的接口,在这里可以实现对硬盘、SD卡、USB等设备的读写,在程序中,实际上预留了给用户改写自己实现的底层程序,例如这里,我们可以将我们在之前学习I2C读写EEPROM或者SPI读写Flash的函数放在这里实现,例如改写后:

#define FLASH		3	/* FLASH设备标号为3 */
//以上省略case FLASH ://这里采用我们之前实现的额SPI读取Flash的函数,使用前需要在文件前#include "bsp_spi_flash.h"result = SPI_Flash_ReadDate(buff, sector, count);return res;
//以下省略

在diskio.c中还有disk_write,同样我们也可以采用跟读方式相同的办法用我们自己实现的写函数进行改写。

这里改写完成后,再到ff.c中看一下,这里我们就可以使用学习C语言是学到的文件操作函数了,例如f_open()、f_read()、f_write()等。

FRESULT f_read (FIL* fp, 		/* Pointer to the file object */void* buff,		/* Pointer to data buffer */UINT btr,		/* Number of bytes to read */UINT* br		/* Pointer to number of bytes read */
)
{
//---------------------------篇幅原因省略----------------------------------------//if (csect + cc > fp->fs->csize)	/* Clip at cluster boundary */cc = fp->fs->csize - csect;if (disk_read(fp->fs->drv, rbuff, sect, cc) != RES_OK)ABORT(fp->fs, FR_DISK_ERR);
//---------------------------篇幅原因省略----------------------------------------//
}

在以上程序中,f_read函数又调用了disk_read函数,从而实现文件的读取。

因此在使用FatFs文件系统时,我们只需要去修改diskio.c文件基本就可以完成对设备的读写等操作了。ff.c、ff.h、integer.h以及diskio.h这四个文件基本不需要改动。

另外在说一下ffconf.h文件,关于FatFs文件系统所具备的功能,基本上跟我们在PC系统上操作硬盘、文件夹、文件等操作一致,因此我们使用FatFs文件系统时,可以根据实际需要对其功能进行裁剪,野火的教程中对内容进行了总结,这里就直接附到下面各位可以根据实际需求进行裁剪。

在这里插入图片描述

关于FatFs文件系统的相关内容,可以在官网或者帮助文档中看看相关的介绍。

相关文章:

019 - STM32学习笔记 - Fatfs文件系统(一) - FatFs文件系统初识

019 - STM32学习笔记 - Fatfs文件系统(一) - FatFs文件系统初识 最近工作比较忙,没时间摸鱼学习,抽空学点就整理一点笔记。 1、文件系统 在之前学习Flash的时候,可以调用SPI_FLASH_BufferWrite函数,将数…...

Selenium开发环境搭建

1.下载Python https://www.python.org/downloads/ 下载下来选择自己创建的路径进行安装,然后配置环境变量 cmd命令框查看 2.安装selenium cmd命令框输入: pip install selenium3.下载pycharm https://www.jetbrains.com/pycharm/download/#sec…...

解决 The ‘more_itertools‘ package is required

在使用爬虫获取维基百科数据时看到了一个很好的项目: 博客:https://blog.51cto.com/u_15919249/5962100 项目地址:https://github.com/wjn1996/scrapy_for_zh_wiki 但在使用过程中遇到若干问题,记录一下: The more_it…...

手把手教你在云环境炼丹(部署Stable Diffusion WebUI)

前几天写了一篇《手把手教你在本机安装Stable Diffusion秋叶整合包》的文章,有些同学反映对硬件的要求太高,显卡太TM贵了。今天我再分享一个云服务器炼丹的方法,方便大家快速入门上手,这个云服务不需要特殊网络设置,能…...

pytorch-gpu 极简安装

1、进入pytoch官网:PyTorch 找到pytorch-gpu版本,看到CUDA11.8、11.7、CPU,这里我选择安装CUDA11.8 2、下载CUDA Toolkit:CUDA Toolkit 11.8 Downloads | NVIDIA Developer 3、下载CUDANN:cuDNN Download | NVIDIA D…...

有道云笔记迁移到自建服务器Joplin

当前有道云笔记各项业务开始逐渐向会员靠拢,如一开始不受限的多端同步现在非会员限制成了两个终端,估计以后会有越来越多的免费内容会逐渐的向会员转移,因此博主开始考虑自建服务器来搞一个云笔记服务端。 因博主已有黑群晖,并且有…...

qt源码--事件系统之QAbstractEventDispatcher

1、QAbstractEventDispatcher内容较少,其主要是定义了一些注册接口,如定时器事件、socket事件、注册本地事件、自定义事件等等。其源码如下: 其主要定义了大量的纯虚函数,具体的实现会根据不同的系统平台,实现对应的方…...

深入了解Python中的os.path.join函数

深入了解Python中的os.path.join函数 1. 引言 在Python中,处理文件和目录路径是常见的任务。为了简化路径的拼接和操作,Python提供了os.path模块,其中的join函数是一个非常重要且常用的函数。本文将深入介绍os.path.join函数的用法和注意事…...

Node.js:execSync执行一个shell命令

默认输出是Buffer对象 const { execSync } require(child_process)let out execSync("echo hi") console.log(out); // <Buffer 68 69 0a>需要转为字符串 const { execSync } require(child_process)let out execSync("echo hi") console.log(…...

《入门级-Cocos2d 4.0塔防游戏开发》---第二课:游戏加载界面开发

目录 一、开发环境介绍 二、开发内容 2.1 修改窗口的大小。 2.2 添加加载场景相关代码 2.3 添加资源 三、显示效果 四、知识点 4.1 Sprite 4.2 定时器 一、开发环境介绍 操作系统&#xff1a;UOS1060专业版本。 cocos2dx:版本 环境搭建教程&#xff1a; 统信UOS下配…...

打卡力扣题目十二

#左耳听风 ARST 打卡活动重启# 目录 一、问题 二、解题方法一 三、解题方法二 关于 ARTS 的释义 —— 每周完成一个 ARTS&#xff1a; ● Algorithm: 每周至少做一个 LeetCode 的算法题 ● Review: 阅读并点评至少一篇英文技术文章 ● Tips: 学习至少一个技术技巧 ● Share: …...

QT服务器练习

#include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this);//给服务器指针实例化空间server new QTcpServer(this); }Widget::~Widget() {delete ui; }//启动服务器按钮对…...

Vcenter 创建 虚拟机配置 Thin Provision 模式 disk

介绍 在vCenter中选择虚拟磁盘格式通常也取决于您的需求和使用情况。 vSphere支持多种虚拟磁盘格式&#xff0c;以下是一些常见的格式&#xff1a; Thick Provision Lazy Zeroed&#xff1a;这是vSphere中的默认格式。它会预分配虚拟磁盘所需的存储空间&#xff0c;但只有在虚…...

初识mysql数据库之事务的概念及操作

目录 一、数据库多客户端访问问题 1. 数据库的CURD无限制带来的问题 2. 如何解决CURD导致的问题 二、事务的概念 1. 什么是事务 2. 事务的四个属性 3. mysql对事务的管理 4. 为什么会有事务 5. 事务的版本支持 三、事务的操作 1. 事务提交方式 2. 事务操作的准备工…...

MPL-2.0(Mozilla Public License 2.0)

MPL-2.0&#xff08;Mozilla Public License 2.0&#xff09;是一种开源软件许可证&#xff0c;由 Mozilla 组织于2012年发布&#xff0c;用于授权开源项目。MPL-2.0 是 MPL-1.1 许可证的继任版本&#xff0c;旨在更好地适应现代开源软件的发展和使用。 MPL-2.0 许可证的主要特…...

Qt+OpenCV+VTK在VS2017中配置路径

QtOpenCVVTK在VS2017中配置路径 《Qt环境配置》《OpenCV环境配置》《VTK环境配置》 《Qt环境配置》 包含目录&#xff1a; D:\Qt\Qt5.12.11\5.12.11\msvc2017_64\include D:\Qt\Qt5.12.11\5.12.11\msvc2017_64\include\QtWidgets D:\Qt\Qt5.12.11\5.12.11\msvc2017_64\include…...

线性代数(应用篇):第五章:特征值与特征向量、第六章:二次型

文章目录 第5章 特征值与特征向量、相似矩阵(一) 特征值与特征向量1.定义2.性质3.求解(1)具体型矩阵试根法、多项式带余除法&#xff1a;三阶多项式分解因式 (2)抽象型矩阵 (二) 相似1.矩阵相似(1)定义(2)性质 2.相似对角化(1)定义(2)相似对角化的条件&#xff08;n阶矩阵A可相…...

Java8实战-总结9

Java8实战-总结9 Lambda表达式把Lambda付诸实践&#xff1a;环绕执行模式第1步&#xff1a;记得行为参数化第2步&#xff1a;使用函数式接口来传递行为第3步&#xff1a;执行一个行为第4步&#xff1a;传递Lambda 使用函数式接口PredicateConsumerFunction原始类型特化 Lambda表…...

大数据开发面试必问:Hive调优技巧系列一

Hive必问调优 Hive 调优拆解:Hive SQL 几乎是每一位互联网分析师的必备技能&#xff0c;相信很多小伙伴都有被面试官问到 Hive 优化问题的经历。所以掌握扎实的 HQL 基础尤为重要&#xff0c;hive优化也是小伙伴应该掌握的一项技能&#xff0c;本篇文章具体从hive建表优化、HQ…...

Jupyter Notebook 7重磅发布,新增多个特性!

本文分享Jupyter Notebook大版本v7.0.0更新亮点&#xff0c;及简单测试&#xff01; 近日&#xff0c;Jupyter Notebook大版本v7.0.0更新&#xff0c;Jupyter Notebook 7基于JupyterLab&#xff0c;因此它包含了过去几年JupyterLab中添加的许多新功能和改进&#xff0c;部分亮…...

装饰模式(Decorator Pattern)重构java邮件发奖系统实战

前言 现在我们有个如下的需求&#xff0c;设计一个邮件发奖的小系统&#xff0c; 需求 1.数据验证 → 2. 敏感信息加密 → 3. 日志记录 → 4. 实际发送邮件 装饰器模式&#xff08;Decorator Pattern&#xff09;允许向一个现有的对象添加新的功能&#xff0c;同时又不改变其…...

利用ngx_stream_return_module构建简易 TCP/UDP 响应网关

一、模块概述 ngx_stream_return_module 提供了一个极简的指令&#xff1a; return <value>;在收到客户端连接后&#xff0c;立即将 <value> 写回并关闭连接。<value> 支持内嵌文本和内置变量&#xff08;如 $time_iso8601、$remote_addr 等&#xff09;&a…...

解决Ubuntu22.04 VMware失败的问题 ubuntu入门之二十八

现象1 打开VMware失败 Ubuntu升级之后打开VMware上报需要安装vmmon和vmnet&#xff0c;点击确认后如下提示 最终上报fail 解决方法 内核升级导致&#xff0c;需要在新内核下重新下载编译安装 查看版本 $ vmware -v VMware Workstation 17.5.1 build-23298084$ lsb_release…...

转转集团旗下首家二手多品类循环仓店“超级转转”开业

6月9日&#xff0c;国内领先的循环经济企业转转集团旗下首家二手多品类循环仓店“超级转转”正式开业。 转转集团创始人兼CEO黄炜、转转循环时尚发起人朱珠、转转集团COO兼红布林CEO胡伟琨、王府井集团副总裁祝捷等出席了开业剪彩仪式。 据「TMT星球」了解&#xff0c;“超级…...

tree 树组件大数据卡顿问题优化

问题背景 项目中有用到树组件用来做文件目录&#xff0c;但是由于这个树组件的节点越来越多&#xff0c;导致页面在滚动这个树组件的时候浏览器就很容易卡死。这种问题基本上都是因为dom节点太多&#xff0c;导致的浏览器卡顿&#xff0c;这里很明显就需要用到虚拟列表的技术&…...

NPOI Excel用OLE对象的形式插入文件附件以及插入图片

static void Main(string[] args) {XlsWithObjData();Console.WriteLine("输出完成"); }static void XlsWithObjData() {// 创建工作簿和单元格,只有HSSFWorkbook,XSSFWorkbook不可以HSSFWorkbook workbook new HSSFWorkbook();HSSFSheet sheet (HSSFSheet)workboo…...

【Android】Android 开发 ADB 常用指令

查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...

C# 表达式和运算符(求值顺序)

求值顺序 表达式可以由许多嵌套的子表达式构成。子表达式的求值顺序可以使表达式的最终值发生 变化。 例如&#xff0c;已知表达式3*52&#xff0c;依照子表达式的求值顺序&#xff0c;有两种可能的结果&#xff0c;如图9-3所示。 如果乘法先执行&#xff0c;结果是17。如果5…...

第7篇:中间件全链路监控与 SQL 性能分析实践

7.1 章节导读 在构建数据库中间件的过程中&#xff0c;可观测性 和 性能分析 是保障系统稳定性与可维护性的核心能力。 特别是在复杂分布式场景中&#xff0c;必须做到&#xff1a; &#x1f50d; 追踪每一条 SQL 的生命周期&#xff08;从入口到数据库执行&#xff09;&#…...

Golang——7、包与接口详解

包与接口详解 1、Golang包详解1.1、Golang中包的定义和介绍1.2、Golang包管理工具go mod1.3、Golang中自定义包1.4、Golang中使用第三包1.5、init函数 2、接口详解2.1、接口的定义2.2、空接口2.3、类型断言2.4、结构体值接收者和指针接收者实现接口的区别2.5、一个结构体实现多…...