STM32FATFS文件系统移植
STM32FATFS文件系统移植
1。 FATFS简介
FATFS文件系统是一个用于在微控制器上运行的开源文件系统,支持FAT/FATFS、NTFS、exFAT等主流文件系统,且一直保持更新。在此以FatFs官网最新版本v0.15进行移植。
2. 移植具体操作
2.1 下载FatFs源码
FATFS源码在其官网就有下载链接,下载后解压即可,官网页面如图1所示:

图1.FATFS官网页面
将其翻至最下面,就可以找到下载链接,如图2所示:

图2.FATFS下载链接
2.2 FATFS代码结构
FATFS源码解压后,其一级目录结构如图3所示:

图3.FATFS源码一级目录结构
其source文件夹下各文件作用如下所示:
source
├── 00history.txt //历史版本信息
├── 00readme.txt //FATFS简介
├── diskio.c //磁盘IO适配文件
├── diskio.h //磁盘IO适配头文件
├── ff.c //FATFS主要实现文件
├── ff.h //FATFS主要实现头文件
├── ffconf.h //FATFS配置头文件
├── ffsystem.c //系统调用适配文件
└── ffunicode.c //Unicode适配文件
在移植过程中,主要对diskio.c、ffconf.h进行修改。
2.3 修改前后文件对比
后文所有代码比对均默认左侧为原代码,右侧为修改后的代码。
2.3.1 diskio.c文件修改比对
diskio.c文件主要实现对存储介质的硬件适配,需要将FLASH读写、初始化等代码移植至此文件内的固定接口。
2.3.1.1头文件添加及宏定义变量修改对比
如图4所示:

图4.diskio.c文件头文件添加及宏定义变量修改对比
#include "Spi.h" //引用SPI初始化
#include "W25q64.h" //引用FLASH文件操作函数,文件内代码均在上篇文章中。
#define SPI_FLASH 3 //定义驱动卷名
FATFS中文件目录格式为为驱动卷名+“:”+文件名,假如说SPI_FLASH文件系统一级目录内有“aaa.txt”这个文件,那么其目录格式为"3:aaa.txt"。3就是宏定义的驱动卷名,文件系统挂载什么的如果要挂载SPIFLASH就是挂载"3:"目录,其余驱动卷或设备同理。
在C语言中上述的写法更简单,C语言支持宏定义的字符串拼接,具体示范如下列代码所示:
#define SPI_FLASH_DIR "3:"
res_flash = f_mount(&fs,SPI_FLASH_DIR,1);
res_flash = f_open(&fnew,SPI_FLASH_DIR"ABC.txt",FA_CREATE_ALWAYS | FA_WRITE);
#define SPI_FLASH_DIR 3
res_flash = f_mount(&fs,"3:",1);
res_flash = f_open(&fnew,"3:ABC.txt",FA_CREATE_ALWAYS | FA_WRITE);
这两段代码在实现效果上并无差别。
2.3.1.2 磁盘存储介质状态查询接口修改对比
如图5所示:

图5.diskio.c文件磁盘存储介质状态查询修改对比
需要将对磁盘存储介质的硬件状态查询移植至此文件内的固定接口。具体操作为在switch (pdrv) 内添加一条分支,返回值分为STATUS_NOINIT、STATUS_NODISK、STATUS_PROTECT与RES_OK四种情况,分别代表磁盘存储介质未初始化、没有对应驱动卷名、磁盘写保护与磁盘正常。
2.3.1.3 磁盘存储介质初始化接口修改对比
如图6所示:

图6.diskio.c文件磁盘存储介质初始化修改对比
需要对磁盘存储介质的硬件初始化移植至此文件内的固定接口。具体操作为在switch (pdrv) 内添加一条分支,调用SPI_FLASH_Init()函数进行初始化。可用返回值与状态查询的返回值一致,在这里我图省事,直接调用了状态查询函数。
2.3.1.4 磁盘存储介质数据读取接口修改对比
如图7所示:

图7.diskio.c文件磁盘存储介质数据读取接口修改对比
需要对磁盘存储介质的硬件数据读取移植至此文件内的固定接口。具体操作为在switch (pdrv) 内添加一条分支,调用SPI_FLASH_Read()函数进行读取。其中读取数据的存储地址为*buff,读取数据的扇区逻辑位号为sector,读取数据的扇区数量为count。
在图7中可以看到,扇区逻辑区块地址(LBA)与扇区数量均左移12位,即乘4096。然而这两个数据乘4096的原因不一样。扇区逻辑区块地址乘4096是为了将扇区逻辑区块地址转化位扇区物理地址,而扇区数量乘4096是为了将扇区数量转化为扇区数据读取数量。
PS:LBA是非常单纯的一种定址模式﹔从0开始编号来定位区块,第一区块LBA=0,第二区块LBA=1,依此类推。这种定址模式取代了原先操作系统必须面对存储设备硬件构造的方式。
2.3.1.5 磁盘存储介质数据写入接口修改对比
如图8所示:

图8.diskio.c文件磁盘存储介质数据写入接口修改对比
需要对磁盘存储介质的硬件数据写入移植至此文件内的固定接口。具体操作为在switch (pdrv) 内添加一条分支,调用SPI_FLASH_Write()函数进行写入。其中写入数据的存储地址为*buff,写入数据的扇区逻辑位号为sector,写入数据的扇区数量为count。至于为什么向左移12位,与读取数据相同,都是将扇区逻辑区块地址转化为扇区物理地址,将扇区数量转化为扇区数据写入数量。
2.3.1.6 磁盘存储介质信息接口修改对比
如图9所示:

图9.diskio.c文件磁盘存储介质信息接口修改对比
需要对磁盘存储介质的硬件信息查询移植至此文件内的固定接口。具体操作为在switch (pdrv) 内添加一条分支,在其中添加一个switch,检索传入的cmd,需要对cmd建立3条分支,分别为GET_SECTOR_COUNT、GET_SECTOR_SIZE与GET_BLOCK_SIZE,分别将物理扇区总数量、物理扇区大小与擦除块数量返回给*buff并返回RES_OK即可。
2.3.1.7 磁盘存储介质写入时间函数
在FATFS文件系统中并不附带获取时间的函数接口,但是创建文件、修改文件等操作都需要获取当前时间,因此需要添加一个获取当前时间的函数接口。具体操作为使用弱定义,定义FATFS文件系统中的获取时间函数内容
__weak DWORD get_fattime(void) // 获取时间
{
return ((DWORD)(2024-1980)<<25) // 设置年份为2024
| ((DWORD)1<<21) // 设置月份为1
| ((DWORD)1<<16) // 设置日期为1
| ((DWORD)1<<11) // 设置小时为1
| ((DWORD)1<<5) // 设置分钟为1
| ((DWORD)1<<1); // 设置秒数为1
}
FATFS采用时间戳的方式来记录时间,具体格式如图10所示:

图10.FATFS文件系统时间戳格式
2.3.2 ffconf.h文件修改对比
ffconf.h文件为FATFS文件系统配置文件,其中定义了FATFS文件系统的配置参数。
2.3.2.1 文件系统格式化宏定义修改对比
如图11所示:

图11.文件系统格式化宏定义修改对比
这个选项会打开f_mkfs()函数,允许对文件系统格式化,或在没有文件系统的情况下建立文件系统
2.3.2.2 文件系统命名格式与命名空间宏定义修改对比
如图12所示:

图12.文件系统命名格式与命名空间宏定义修改对比
由于FATFS文件系统默认命名为日文,需要将FF_CODE_PAGE的值修改,以支持中文命名。FF_USE_LEN决定了实现长文件支持所使用的内存方式,0为不使用LFN,1为使用LFN,但没有线程安全,2为使用LFN并使用堆内存,3为使用LFN并使用栈内存。
2.3.2.3 文件系统驱动卷数量与最大扇区内存修改对比
如图13所示:

图13.文件系统驱动卷数量与最大扇区内存修改对比
修改FF_VOLUMES的值,以便支持多个卷。修改FF_MAX_SS的值,以便支持更大的扇区。
2.3.2.5 文件系统时间戳宏定义修改对比
如图14所示:

图14.文件系统时间戳宏定义修改对比
FF_FS_NORTC=1表示使用时间函数,FF_FS_NORTC=-1表示不使用时间函数。
3. 移植后main文件使用演示
首先需要引用“ff.h”头文件,然后定义如下全局变量:
FATFS fs;
FIL fnew;
FRESULT res_flash;
UINT fnum;
由于FATFS文件系统的结构体都比较大,在main函数中定义会导致堆栈溢出。
然后定义一些临时变量,用于存储文件名和文件内容以及FATFS文件系统运行状态:
BYTE buffer[4096] = {0};
BYTE textFileBuffer[] = "ABCDEFG";
uint8_t c[256] = {0};
我所使用的开发板为野火STM32F103指南者开发板,驱动卷命名为"3",具体执行代码如下所示
int main()
{
HSE_SetSysClock(RCC_PLLMul_9); // 设置系统时钟为9倍,72MHz
Usart_init(); // 初始化串口
USART_SendString(USART1,"Systeam is OK.");
res_flash = f_mount(&fs,"3:",1); // 挂载文件系统
USART_SendByte(USART1,res_flash);
if(res_flash == FR_NO_FILESYSTEM) // 检测是否存在文件系统
{
res_flash = f_mkfs("3:",NULL,buffer,4096); // 创建文件系统
if(res_flash == FR_OK) // 判断是否创建成功
{
USART_SendString(USART1,"FATFS has been mkf.");
res_flash = f_mount(NULL,"3:",0); // 卸载文件系统
res_flash = f_mount(&fs,"3:",1); // 重新挂载文件系统
}
else // 创建失败
{
USART_SendString(USART1,"FATFS mkf filed.");
USART_SendByte(USART1,res_flash);
while(1) // 死循环
{
}
}
}
else if(res_flash !=FR_OK) // 挂载失败
{
USART_SendString(USART1,"mount ERROR.");
while(1) // 死循环
{
}
}
else // 挂载成功
{
USART_SendString(USART1,"mount OK.");
}
res_flash = f_open(&fnew,"3:ABC.txt",FA_CREATE_ALWAYS | FA_WRITE); // 创建文件
USART_SendByte(USART1,res_flash);
if(res_flash == FR_OK) // 判断是否创建成功
{
USART_SendString(USART1,"File open is OK.");
}
res_flash = f_write(&fnew,"ABCDEFG",7,&fnum); // 写入数据
if(res_flash == FR_OK) // 判断是否写入成功
{
USART_SendString(USART1,"File write is OK.");
}
else // 写入失败
{
USART_SendByte(USART1,res_flash);
}
f_close(&fnew); // 关闭文件
if(res_flash == FR_OK) // 判断是否关闭成功
{
USART_SendString(USART1,"File close is OK.");
}
else // 关闭失败
{
USART_SendByte(USART1,res_flash);
}
res_flash = f_unmount("3:"); // 卸载文件系统
USART_SendByte(USART1,res_flash);
res_flash = f_mount(&fs,"3:",1); // 重新挂载文件系统
USART_SendByte(USART1,res_flash); // 判断是否重新挂载成功
res_flash = f_open(&fnew,"3:ABC.txt",FA_OPEN_EXISTING | FA_READ); // 打开文件
if(res_flash == FR_OK) // 判断是否打开成功
{
USART_SendString(USART1,"File open is OK.");
USART_SendString(USART1,c);
}
else // 打开失败
{
USART_SendByte(USART1,res_flash);
}
res_flash = f_read(&fnew,c,7,&fnum); // 读取文件内容
if(res_flash == FR_OK) // 判断是否读取成功
{
USART_SendString(USART1,"File read is OK.");
USART_SendString(USART1,c);
}
else // 读取失败
{
USART_SendByte(USART1,res_flash);
}
f_close(&fnew); // 关闭文件
res_flash = f_unmount("3:"); // 卸载文件系统
USART_SendByte(USART1,res_flash);
if(res_flash == FR_OK) // 判断是否卸载成功
{
USART_SendString(USART1,"unmount OK.");
}
while(1){
}
}
烧录结果
如图15所示:

图15.烧录结果
STM32FATFS文件系统移植的更多相关文章
- 基于s5pv210嵌入式系统busybox文件系统移植
基于s5pv210嵌入式系统busybox文件系统移植 1.下载源码 busybox.net/downloads下载最新版的busybox源码,最新源码为1.21.1 2.解压源码文件 tar xvf ...
- SD卡fat文件系统移植
经过充分的研究,发现fatfs文件系统移植的比较简单!因为代码都已经被别人做好了!我们只需把io层稍稍做个处理就ok了: 至于sd卡的驱动请看我这篇博客:http://blog.csdn.net/ie ...
- 小白自制Linux开发板 三. Linux内核与文件系统移植
上一篇完成了uboot的移植,但是想要愉快的在开发板上玩耍还需要移植Linux内核和文件系统. 1.Linux内核 事实上对于F1C100S/F1C200S,Linux官方源码已经对licheepi ...
- linux2.6.30.4内核移植(3)——yaffs文件系统移植
内核源码:linux2.6.30.4 交叉编译工具:3.4.5 移植linux内核至:TQ2440 工作基础:http://www.cnblogs.com/nufangrensheng/p/36696 ...
- RTT下spi flash+elm fat文件系统移植小记
背景: MCU:STM32F207 SPI flash: Winbond W25Q16BV OS: RTT V1.1.1 bsp: STM32F20x 1 将spi_core.c,spi_dev.c及 ...
- UBI 文件系统移植 sys 设备信息【转】
转自:http://blog.chinaunix.net/uid-25304914-id-3058647.html cat /sys/class/misc/ubi_ctrl/dev --------- ...
- Linux内核,文件系统移植过程中出现的一些问题与解决办法
1.bootm地址和load address一样 此种情况下,bootm不会对uImage header后的zImage进行memory move的动作,而会直接go到entry point开始执行. ...
- uboot 、内核、文件系统移植
1. 参考下面博客: http://blog.csdn.net/andylauren/article/details/51448353 2.查看u盘: $ sudo fdisk -l 3. 格式化u盘 ...
- STM32 FATFS文件系统移植
http://www.360doc.com/content/11/1221/10/7736891_173820469.shtml
- 关于linux下的嵌入式文件系统以及flash文件系统选择
嵌入式linux下常见的文件系统 • RomFS:只读文件系统,可以放在ROM空间,也 可以在系统的RAM中,嵌入式linux中常用来作 根文件系统 • RamFS:利用VFS自身结构而形成的内存文件 ...
随机推荐
- 【如何提高IT运维效率】深度解读京东云基于NLP的运维日志异常检测AIOps落地实践
作者:京东科技 张宪波.张静.李东江 基于NLP技术对运维日志聚类,从日志角度快速发现线上业务问题 日志在IT行业中被广泛使用,日志的异常检测对于识别系统的运行状态至关重要.解决这一问题的传统方法需 ...
- 【小测试】fastcgo 调用 c 代码
作者:张富春(ahfuzhang),转载时请注明作者和引用链接,谢谢! cnblogs博客 zhihu Github 公众号:一本正经的瞎扯 找到了一个项目 https://github.com/pe ...
- 【JS 逆向百例】cnki 学术翻译 AES 加密分析
关注微信公众号:K哥爬虫,QQ交流群:808574309,持续分享爬虫进阶.JS/安卓逆向等技术干货! 声明 本文章中所有内容仅供学习交流,抓包内容.敏感网址.数据接口均已做脱敏处理,严禁用于商业用途 ...
- Unity Editor自定义菜单排序(MenuItem Order)
扩展Unity的菜单MenuItem MenuItem 属性用于向主菜单和检视面板上下文菜单添加菜单项. 该 MenuItem 属性能够将任何静态函数转变为菜单命令,仅静态函数可使用 MenuItem ...
- 我为什么从Windows转到Linux?
本文来自读者投稿! 大家好!我是 Guide 哥,Java 后端开发.一个会一点前端,喜欢烹饪的自由少年. 如果文章有任何需要改善和完善的地方,欢迎在评论区指出,共同进步! 喔,看到这个标题千万不要以 ...
- 人工智能的新篇章:深入了解大型语言模型(LLM)的应用与前景
人工智能的新篇章:深入了解大型语言模型(LLM)的应用与前景 LLM(Large Language Model)技术是一种基于深度学习的自然语言处理技术,旨在训练能够处理和生成自然语言文本的大型模型. ...
- 深度学习应用篇-自然语言处理-命名实体识别[9]:BiLSTM+CRF实现命名实体识别、实体、关系、属性抽取实战项目合集(含智能标注)
深度学习应用篇-自然语言处理-命名实体识别[9]:BiLSTM+CRF实现命名实体识别.实体.关系.属性抽取实战项目合集(含智能标注) 1.命名实体识别介绍 命名实体识别(Named Entity R ...
- PID 控制在医学麻醉过程血压控制中的应用|期末课程设计|PID控制器|自动控制原理
前言 那么这里博主先安利一些干货满满的专栏了! 首先是博主的高质量博客的汇总,这个专栏里面的博客,都是博主最最用心写的一部分,干货满满,希望对大家有帮助. 高质量博客汇总https://blog.cs ...
- USACO 2022 Cu 题解
USACO 2022 Cu 题解 AK用时:$ 3 $ 小时 $ 30 $ 分钟. A - Cow College 原题 Farmer John 计划为奶牛们新开办一所大学! 有 $ N $($ 1 ...
- Matrix【未完成】
Matrix The fitrst thing we do,let's kill all the language lawyers. -- Henry VI, Part II The "pr ...