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 here
		result = ATA_disk_read(buff, sector, count);
		// translate the reslut code here
		return res;
	case MMC :
		// translate the arguments here
		result = MMC_disk_read(buff, sector, count);
		// translate the reslut code here
		return res;
	case USB :
		// translate the arguments here
		result = USB_disk_read(buff, sector, count);
		// translate the reslut code here
		return 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文件系统的相关内容,可以在官网或者帮助文档中看看相关的介绍。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

四步从菜鸟到高手,Python编程真的很简单(送书第一期:文末送书2本)

🍁博主简介 🏅云计算领域优质创作者   🏅华为云开发者社区专家博主   🏅阿里云开发者社区专家博主 💊交流社区:运维交流社区 欢迎大家的加入! 🐋 希望大家多多支持,我…

临床医学怎样翻译比较 好

近年来,随着不同国家之间医药行业形成的共同研究趋势,临床翻译对于来自不同国家的医疗人员的合作至关重要。那么,临床医学怎样翻译比较 好,北京哪个翻译公司比较专业? 据了解,临床医学翻译包含患者病历记录…

Linux之 Vim 搜索方式

方式一:快速搜索(字符串完全匹配,区分大小写) 格式: / 关键词 or ? 关键词 /内容 #按回车键搜索 从上到下查找 ?内容 #按回车键搜索 从下到上查找 优点:快速定位到该关键字 回车之后&…

【Lua学习笔记】Lua进阶——Require,三目运算

文章目录 Require短路判断实现三目运算符 Require 这是文件aaa.lua的内容 aaa.lua: a 10 local b 20 print("我是aaa")这是文件example.lua的内容 example.lua: a 100 print(a) require("aaa") --require调用其他脚本文件 print(a) print(b) print(&…

Psim 2022仿真软件的安装--Psim电力仿真实战教程

文章目录 Psim 2022 仿真软件安装及使用教程软件介绍1.下载psim 2022安装软件,有需要的亲请联系作者。2.点击安装文件3.点击进行安装:4.安装完成,打开软件,开始仿真5.仿真模型介绍5.1.单相全控整流电路仿真5.2 三相PFC可控整流电路…

【点选验证码】生成点选验证码图片

生成点选验证码图片 参考博客:https://blog.csdn.net/sinat_39629323/article/details/121989609 from tqdm import tqdm from PIL import Image, ImageDraw, ImageFont, ImageOps import shutil,os import numpy as np import cv2 import math import random fil…

Mysql的增删改查

一.增加数据(insert) insert into 表名(列名1,列名2,列名3,.....列名n)values(值,值,值,....值) insert into userinfo(id,name,age) values(&quo…

CSS3 实现边框圆角渐变色渐变文字效果

.boder-txt {width: 80px;height: 30px; line-height: 30px;padding: 5px;text-align: center;border-radius: 10px;border: 6rpx solid transparent;background-clip: padding-box, border-box;background-origin: padding-box, border-box;/*第一个linear-gradient表示内填充…

二级制部署kubernetes(1.20)

😘作者简介:一名运维工作人员。 👊宣言:人生就是B(birth)和D(death)之间的C(choise),做好每一个选择。 🙏创作不易,动动小…

RISC-V公测平台发布 · 第一个WEB Server “Hello RISC-V world!”

RISC-V公测平台Web Server地址:http://175.8.161.253:8081 一、前言 Web Server是互联网应用的基础设施,无论是用户访问网站,还是后端服务提供商和开发者构建各种应用程序,Web Server都在其中扮演着至关重要的角色。 显而易见…

服务器 Docker Alist挂载到本地磁盘(Mac版)夸克网盘

1.服务器下载alist 默认有docker环境 docker pull xhofe/alist2.生成容器 -v /home/alist:/opt/alist/data 这段意思是alist中的数据映射到docker 主机的文件夹,/home/alist就是我主机的文件夹,这个文件夹必须先创建 docker run -d --restartalways…

Node.js 安装与版本管理(nvm 的使用)

安装 Node.js Node.js 诞生于 2009 年 5 月,截至今天(2022 年 3 月 26 号)的最新版本为 16.14.2 LTS 和 17.8.0 Current,可以去官网下载合适的版本。 其中,LTS(Long Term Support) 是长期维护…

【Matter】基于Ubuntu 22.04 编译chip-tool工具

前言 编译过程有点曲折,做下记录,过程中,有参考别人写的博客,也看github 官方介绍,终于跑通了~ 环境说明: 首先需要稳定的梯子,可以访问“外网”ubuntu 环境,最终成功实验在Ubunt…

Unity XML3——XML序列化

一、XML 序列化 ​ 序列化:把对象转化为可传输的字节序列过程称为序列化,就是把想要存储的内容转换为字节序列用于存储或传递 ​ 反序列化:把字节序列还原为对象的过程称为反序列化,就是把存储或收到的字节序列信息解析读取出来…

iOS中的一些锁

多线程在日常开发中能起到性能优化的作用,但是一旦没用好就会造成线程不安全,本文就来讲讲如何保证线程安全 锁 线程安全 当一个线程访问数据的时候,其他的线程不能对其进行访问,直到该线程访问完毕。简单来讲就是在同一时刻&a…

智能垃圾桶

1.树莓派3B引脚图 2. 原理图 3.舵机线图 搜了这个这么多3b的资料,自己只是想解决如何下程序和运行程序的博客,网上搜集的资料全是讲如何通过SSH或者网线连接树莓派,通过直接连接屏幕的教程较少。 遇到问题:不论是舵机还是其他传…

Fragment的基本用法、Fragment和活动间的通信、Fragment的生命周期、动态加载布局的技巧

一、Fragment的简单用法 1、制作Fragment 1.1 新建一个布局文件left_fragment.xml <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas.android.com/apk/res/android"android:orientation"ve…

Ansible 自动化运维工具

目录 Ansible 简介Ansible 特性&#xff1a;Ansible 工作机制 Ansible 环境安装部署管理端安装 ansibleansible 目录结构配置主机清单配置密钥对验证ansible 命令行模块1&#xff0e;command 模块2&#xff0e;shell 模块3&#xff0e;cron 模块4&#xff0e;user 模块5&#x…

无GPS下的自动驾驶系统解决方案

摘要&#xff1a; 随着自动驾驶技术的发展&#xff0c;在未知环境中智能汽车的定位技术成为该领域研究的核心。目前定位技术主要的解决方案是基于全球定位系统&#xff08;GPS&#xff09;&#xff0c;但是在某些特殊的环境中如下车库&#xff0c;没有 GPS 信号如何解决定位问…

机器学习 day30(正则化参数λ对模型的影响)

λ对Jcv和Jtrain的影响 假设该模型为四阶多项式当λ很大时&#xff0c;在最小化J的过程中&#xff0c;w会很小且接近0&#xff0c;此时模型f(x)近似于一个常数&#xff0c;所以此时模型欠拟合&#xff0c;Jtrain和Jcv都很大当λ很小时&#xff0c;表示模型几乎没有正则化&…