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

细说STM32单片机SPI-Flash芯片的FatFS移植

目录

1、SPI-Flash芯片硬件电路

2、CubeMX项目基础设置

(1)RCC、SYS、Code Generator、USART3、TIM6、GPIO、NVIC

(2)RTC

(3)SPI2

(4)FatFS模式

(5)FatFS参数设置概述

1) Version组

2) Function Parameters组

3) Locale and Namespace Parameters组

4) Physical Driver Parameters组

5) System Parameters组

3、Function Parameters组参数设置

(1)参数FS_READONLY

(2)参数S_MINIMIZE

(3)参数USE_STRFUNC

4、Locale and Namespace Parameters组参数设置

(1)参数USE_LFN

(2)参数STRF_ENCODE

(3)参数FS_RPATH

5、Physical Driver Parameters组参数设置

6、System Parameters组参数设置

(1)参数FS_NORTC

(2)参数FS_REENTRANT

7、项目软件设计


        本文以开发板上的SPI-Flash芯片W25Q16媒介详细介绍CubeMX中FatFS各个参数的意义和设置,分析生成的代码中FatFS各个文件的作用和关联,完成针对W25Q16的硬件访问层的移植。

        继续使用旺宝红龙开发板STM32F407ZGT6 KITV1.0。相关原理图如下:

 1、SPI-Flash芯片硬件电路 

        开发板上有一个SPI-Flash存储芯片W25Q16,它与STM32F407的SPI2接口连接,W25Q16总容量是2M字节,存储空间参数如下。

  • 总共32个块(block),每个块64KB。
  • 每个块又分为16个扇区,共512个扇区,每个扇区4KB。
  • 每个扇区又分为16个页(page),共8192个页,每个页256B。

2、CubeMX项目基础设置

        本文创建一个示例针对SPI-Flash存储芯片W25Q16进行FatFS移植,使用FatFS进行文件读写等操作。此外,使用RTC为FatFS提供时间戳数据。

(1)RCC、SYS、Code Generator、USART3、GPIO、NVIC

        参数设置可以本文作者发布的其他文章文章。

(2)RTC

  • 启用RTC的时钟源和日历,设置初始日期和时间,其他功能无须开启。在示例中读取RTC的当前日期和时间。
  • 在RCC组件中启用LSE在时钟树上,使用LSE作为RTC的时钟源

(3)SPI2

  • 设置HCLK为168MHzPCLK1的频率为42MHzSPI2是挂在APB1总线上的,这样是为方便计算SPI2的波特率。
  • SPI2的模式设置为Full-Duplex Master不使用硬件NSS信号,分频系数(Prescaler)设置为8波特率为5.25Mbit/s。数据传输是MSB先行,CPOL和CPHA的组合是SPI时序模式3。

(4)FatFS模式

        模式设置就是选择FatFS应用的存储介质,有以下4个选项。

 

  • External SRAM外部SRAM存储器。例如,开发板上有一个外部SRAM芯片IS62WV51216可以将此芯片的一部分或全部存储区域用作文件系统,使用FatFS管理SRAM上的文件,实现内存上的高速文件读写。
  • SD Card,SD卡。此项需要启用SDIO接口后才可以选择。
  • USB Disk,U盘。需要将USB-OTG-FS或USB-OTG-HS组件的模式设置为Host-Only(仅作为主机),并且将Middleware分组中的USB_HOST组件的IP类型设置为MassStorage Host Class(大容量存储主机类)之后,此项才可以选择。
  • User-defined,用户定义器件。除以上3项之外的其他存储介质,例如,开发板上连接在SPI2接口上的Flash存储芯片W25Q16。

        使用前3种存储介质时,CubeMX生成的代码里有FatFS完整的移植程序,因此用户无须再编程实现硬件层的Disk IO函数。使用用户定义器件时,CubeMX生成的代码里有FatFS移植代码框架,用户需要自己编程实现器件的Disk IO函数。本文的示例使用的存储介质是连接在SPI2接口上的Flash存储芯片W25Q16属于用户定义器件。通过这个示例,详细地了解FatFS程序移植的原理。

(5)FatFS参数设置概述

        设置FatFS参数。这些参数分为多个组,大多数与FatFS配置文件ffconf.h中的宏定义对应,用于设置FatFS的一些参数,以及进行功能裁剪。

1) Version组

        只有一个参数,显示了FatFS的版本。图中显示的版本为R0.12c。

2) Function Parameters组

        用于配置是否包含某些函数,就是FatFS的功能裁剪。

3) Locale and Namespace Parameters组

        本地化和名称空间参数,例如,设置代码页、是否使用长文件名等。

4) Physical Driver Parameters组

        物理驱动器参数,包括卷的个数、扇区大小等。

5) System Parameters组

        系统参数,一些系统级的参数定义,如是否支持exFAT文件系统。在设置参数时,用户可以单击参数设置界面右上方的显示描述信息的小按钮,这样就可以让每个参数的描述信息显示出来,例如参数设置的数值范围等。

3、Function Parameters组参数设置

        Function Parameters组参数,第一列是参数名称,对应于源文件中的宏,宏的名称就是参数名称前加“_”,例如,参数FS_READONLY对应的宏是_FS_READONLY,参数USE_FIND对应的宏是_USE_FIND。第二列是参数值,这些参数一般是逻辑值,Disabled表示设置为0,Enabled表示设置为1。

        这些参数有的用于定义系统的特性,如FS_MINIMIZE定义系统最小化级别,会影响多个函数;有的用于裁剪某个功能,可同时影响多个函数,如USE_FIND影响函数f_findfirst()和f_findnext();有的参数只影响一个函数,如USE_CHMOD只控制是否使用函数f_chmod()。

参数

默认值

可设置内容和影响的函数

FS_READONLY

Disabled

只能设置为Disabled表示不使用只读功能

FS_MINIMIZE

Disabled

最小化级别,可设置为0、1、2、3等4种级别

USE_STRFUNC

2

是否使用字符串函数,可设置为0、1或2

USE_FIND

Disabled

是否使用查找函数f_findfirst()和f_findnext()

USE_MKFS

Enabled

是否使用函数f_mkfs()

USE_FASTSEEK

Enabled

是否使用快速寻找功能,无具体影响函数

USE_EXPAND

Disabled

是否使用函数f_expand()

USE_CHMOD

Disabled

是否使用函数f_chmod()

USE_LABEL

Disabled

是否使用获取和设置卷标签的函数f_getlable()和f_setlabel()

USE_FORWARD

Disabled

是否使用函数f_forward()

(1)参数FS_READONLY

        在CubeMX中,参数FS_READONLY只能设置为Disabled,表示不使用只读功能。若在代码中设置_FS_READONLY为1,表示系统为只读系统,将移除用于写操作的函数,包括f_write()、f_sync()、f_unlink()、f_mkdir()、f_chmod()、f_rename()和f_truncate(),并且函数f_getfree()将变得无用。

(2)参数S_MINIMIZE

        参数S_MINIMIZE设置系统的最小化级别,有如下4种选项。

  • Disabled:对应级别0,启用所有基本函数。
  • Enabled with 6 functions removed:对应级别1,移除函数f_stat()、f_getfree()、f_unlink()、f_mkdir()、f_truncate()和f_rename()。
  • Enabled with 9 functions removed:对应级别2,在级别1的基础上,再移除函数f_opendir()、f_readdir()和f_closedir()。
  • Enabled with 10 functions removed:对应级别3,在级别2的基础上,再移除函数f_lseek()。

(3)参数USE_STRFUNC

        参数USE_STRFUNC设置是否使用字符串相关函数,以及如何使用,有如下3种选项。

  • Disabled:对应值0,不使用字符串相关的函数,如f_gets()、f_putc()、f_puts()等。
  • Enabled without LF->CRLF conversion:对应值1,使用字符串相关函数,但不使用LF->CRLF转换。
  • Enabled with LF->CRLF conversion:对应值2,使用字符串相关函数,并且使用LF->CRLF转换,也就是字符串中的'\n'会被转换为\r¹+'n'。

4、Locale and Namespace Parameters组参数设置

        Locale and Namespace Parameters组参数用于设置本地语言代码页,是否使用长文件名等。

参数

默认值

可设置内容和功能描述

CODE_PAGE

Latin 1

设置目标系统上使用的OEM编码页,编码页如果选择不正常,可能
导致打开文件失败。如果要支持中文,应该选择Simplified Chinese
(DBCS),对应的_CODE_PAGE参数值是936

USE_LFN

Disabled

是否使用长文件名(LFN)

MAX_LFN

255

设定值范围为12至255,是LFN的最大长度

LFN_UNICODE

ANSI/OEM

是否将FatFS API中的字符编码切换为Unicode。当USE_LFN设置为
Enabled时, LFN_UNICODE才可以设置为1(Unicode)。当USE_LFN
设置为Disabled时, LFN_UNICODE只能设置为ANSI/OEM

STRF_ENCODE

UTF-8

启用Unicode后,FatFSAPI中的字符编码都需要转换为Unicode。这
个参数用于选择字符串操作相关函数在读写文件时使用的编码

FS_RPATH

Disabled

是否使用相对路径,以及使用相对路径时的特性

(1)参数USE_LFN

        参数USE_LFN控制是否使用LFN(Long File Name,长文件名),有如下4种选项。

  • 0=Disabled:不使用LFN,参数MAX_LFN无影响。
  • 1=Enable LFN with static working buffer on the BSS:使用LFN,且使用BSS段的静态工作缓冲区。这种情况下,LFN工作缓冲区是BSS段上的静态变量,总是不可重入的,即不是线程安全的。
  • 2=Enable LFN with dynamic working buffer on the STACK:使用LFN,且在栈空间为LFN分配动态工作缓冲区。
  • 3=Enable LFN with dynamic working buffer on the HEAP:使用LFN,且在堆空间为LFN分配动态工作缓冲区。

        要使用LFN功能,请务必将处理Unicode的函数ff_convert()和f_wtoupper()添加到项目中。LFN工作缓冲区占用(MAX_LFN+1)×2字节。当使用栈空间作为LFN工作缓冲区时,要注意栈溢出问题。使用堆空间作为LFN工作缓冲区时,需要将内存管理函数ff_memalloc()和ff_memfree()添加到项目中。

        如果不使用LFN,即参数USE_LFN设置为Disabled时,不含后缀的文件名的长度不能超过8个ASCII字符,后缀为3个ASCII字符。如果在嵌入式设备上使用LFN,最好也不要在文件名中使用汉字,即LFN_UNICODE不要设置为Unicode,而是设置为ANSI/OEM。本示例暂时不使用LFN,所以将USE_LFN设置为Disabled。但是FatFS需要能支持中文,所以CODE_PAGE设置为Simplified Chinese(DBCS)。

(2)参数STRF_ENCODE

        参数STRF_ENCODE用于设置字符串的编码。当LFN_UNICODE设置为0(ANSI/OEM)时,这个参数无效。当LFN_UNICODE设置为1(Unicode)时,FatFS API中的字符编码都需要转换为Unicode。这个参数用于选择字符串操作相关函数,如f_gets()、f_putc()、f_puts()、f_printf()等,在读写文件时使用的编码,有如下几种选项。

  • 0=ANSI/OEM。
  • 1=UTF-16LE。
  • 2=UTF-16BE。
  • 3=UTF-8。

        其中,UTF-8是最常用的汉字编码,需要使用汉字时,就将此参数设置为UTF-8。

(3)参数FS_RPATH

        参数FS_RPATH用于设置是否使用相对路径,以及使用相对路径时的特性,有如下3种选项。

  • 0=Disabled,不使用相对路径,移除相关函数。
  • 1=Enabled without f_getcwd,使用相对路径,可使用函数f_chdrive()和f_chdir()。
  • 2=Enabled with f_getcwd,在选项1的基础上,增加可使用函数f_getcwd()。

        读取目录的函数f_readdir()的返回结果与此选项有关。

5、Physical Driver Parameters组参数设置

        Physical Driver Parameters组参数用于设置系统内卷的个数、扇区的大小、是否有多个分区等。

 

参数

默认值

可设置内容和功能描述

VOLUMES

1

使用的逻辑驱动器的个数,设置范围为1~9

MAX_SS

512

最大扇区大小(字节数)只能设置为512、1024、2048或4096,比如使用的Flash存储芯片W25Q128的扇区大小为4096字节,所
以设置为4096。当MAX_SS大于512时,在disk_ioctl()函数中需要
实现GET_SECTOR_SIZE指令

MIN_SS

512

最小扇区大小(字节数),只能设置为512、1024、2048或4096

MULTI_PARTITION

Disabled

设置为Disabled时,每个卷与相同编号的物理驱动器绑定,只会挂
载第一个分区。设置为Enabled时,每个卷与分区表VolToPart[]关联

USE_TRIM

Disabled

是否使用ATA_TRIM特性。要想使用Trim特性,需要在disk_ioctl()
函数中实现CTRL_TRIM指令

FS_NOFSINFO

0

参数取值为0、1、2或3它设置了函数f_getfree()的运行特性

        FatFS可以支持多个卷,这多个卷可以是多个不同的存储介质,例如,一个嵌入式设备上同时有Flash存储芯片和SD卡。存储介质的扇区大小是固定的,但不同存储介质的扇区大小不一样,例如,SD卡的扇区大小是512字节,而Flash存储芯片W25Q16的扇区大小是4096字节。

        参数FS_NOFSINFO是两位二进制的数[bit1,bit0],组成的参数值是0、1、2或3,用于设置函数f_getfree()的运行特性。函数f_getfree()用于获取一个卷的剩余簇个数。如果bit0=0,在卷挂载后,首次执行函数f_getfree()时,会强制进行完整的FAT扫描,得到的剩余簇个数会记录到返回的FATFS对象的free_clst变量中,bit1根据bit0的设置控制最后分配的簇编号,也就是结构体FATFS中的成员变量last_clst。结构体FATFS中的成员变量free_clst和last_clst称为FSINFO,也就是剩余空间信息(free space information)。

  • bit0=0:使用FSINFO中的剩余簇个数,即成员变量free_clst。
  • bit0=1:不要相信FSINFO中的剩余簇个数,因为不会进行完全的FAT扫描。
  • bit1=0:使用FSINFO中的最后分配簇编号,即成员变量last_clst。
  • bit1=1:不要相信FSINFO中的最后分配簇编号。

        参数FS_NOFSINFO影响f_getfree()的运行效果。在后面的示例中,我们会讲到如何用函数f_getfree()获取存储介质空间信息。

6、System Parameters组参数设置

        System Parameters组参数用于设置FatFS的一些系统级别信息。

参数

默认值

可设置内容和功能描述

FS_TINY

Disabled

微小缓冲区模式,如果设置为Enabled每个文件对象(FIL)可减少
内存占用512字节

FS_EXFAT

Disabled

是否支持exFAT文件系统,当_USE_LFN设置为0时,这个参数只
能设置为Disabled

FS_NORTC

Dynamic
timestamp

如果系统有RTC提供实时的时间,就设置为Dynamic timestamp;如
果系统没有RTC提供实时的时间,就设置为Fixed timestamp

FS_REENTRANT

Disabled

设置FatFS的可重入性,在CubeMX里如果没有启用FreeRTOS,这
个参数只能设置为Disabled,如果启用了FreeRTOS这个参数只能
设置为Enabled

FS_TIMEOUT

1000

超时设置,单位是节拍数。FS_REENTRANT设置为Disabled时,这
个参数无效

FS_LOCK

2

如果要启用文件锁定功能,设定FS_LOCK的值大于或等于1表示
可同时打开的文件个数。设定值范围为0~255

(1)参数FS_NORTC

        参数FS_NORTC用于设置是否有RTC为FatFS提供时间戳。如果系统有RTC提供实时的时间,就设置为Dynamic timestamp,在移植时,实现硬件层访问函数get_fattime(),读取RTC的当前时间作为文件的时间戳。如果系统没有RTC提供实时的时间,就设置为Fixedtimestamp,会出现NORTC_YEAR(年)、NORTC_MON(月)和NORTC_MDAY(日)这3个参数,用于设置一个固定的时间戳数据。

(2)参数FS_REENTRANT

        参数FS_REENTRANT用于设置FatFS的可重入性。可重入性表示是否线程安全,在使用RTOS时,才有可重入性问题。所以,在CubeMX里如果没有启用FreeRTOS,这个参数只能设置为Disabled;如果启用了FreeRTOS,这个参数只能设置为Enabled。

        如果FS_REENTRANT设置为Enabled,会出现参数SYNC_t和USE_MUTEX。其中,SYNC_t是用于同步的对象类型。当USE_MUTEX设置为Disabled时,SYNC_t固定为oSSemaphoreld_t,即使用信号量;当USE_MUTEX设置为Enabled时,SYNC_t固定为osMutexId_t,即使用互斥量。

        如果设置为可重入的,还需要在FatFS中移植函数ff_req_grant()、ff_rel_grant()、ff_del_syncobj()和ff_cre_syncobj()。

 7、项目中FatFS的文件组成 

        完成设置后,CubeMX会自动生成代码。在CubeIDE中打开项目,将KEY_LED驱动程序目录添加到项目搜索路径。在本示例中,用到W25Q16芯片,其驱动程序FLASH目录也添加到项目搜索路径。

        项目中FatFS相关的文件是自动加入的。使用CubeMX生成的FatFS的文件组成(对比:全手工移植的FatFS文件组成,两者区别很大)。Middlewares目录下加入的FatFS的源代码文件,这些是不允许用户修改的FatFS源程序文件,各个文件的作用描述如下。

  • 文件integer.h:包含FatFS中用到的各种基础数据类型的定义。
  • 文件ff.h和ff.c:这是FatFS应用程序接口API函数所在的文件,是与具体硬件无关的软件模块。
  • 文件diskio.h和diskio.c:这是存储介质Disk IO访问通用接口函数所在的文件。在CubeMX生成的项目代码中,与具体存储介质相关的Disk IO函数在另外的文件里实现,例如,本示例使用的存储介质是User-defined,会自动生成用户程序文件user_diskio.h和user_diskio.c。文件diskio.c中的函数只是调用文件user_diskio.c中定义的具体Disk IO函数。
  • 文件ff_gen_drv.h和ff_gen_drv.c:实现驱动器列表管理功能的文件,这些功能包括链接一个驱动器,或解除一个驱动器的链接。FatFS初始化时,就调用其中的函数FATFS_LinkDriver()链接驱动器。
  • option子目录下的文件syscall.c:包含在使用RTOS系统时需要实现的一些函数的示例代码,如果使用FreeRTOS,需要重新实现这些函数。

        与具体存储介质相关,可以由用户修改的FatFS相关文件在目录\FATFS下。这些文件的功能描述如下。

  • 文件fatfs.h和fatfs.c:是用户的FatFS初始化程序文件。其中有FatFS初始化函数MX_FATFS_Init()、几个全局变量的定义,以及需要重新实现的获取RTC时间作为文件系统时间戳的函数get_fattime()。
  • 文件ffconf.h,FatFS的配置文件,包含很多的宏定义,与CubeMX里的FatFS设置对应。
  • 文件user_diskio.h和user_diskio.c,是user-defined存储介质的Disk IO函数的程序文件,自动生成了各个函数的框架,只需针对SPI-Flash芯片编写具体的函数代码即可。

        FatFS相关文件的层次和关系如下图所示:

  • 文件fatfs.h中包含CubeMX生成的FatFS初始化函数MX_FATFS_Init(),在主程序中进行外设初始化时,会调用这个函数。
  • 函数MX_FATFS_Init()会调用文件ff_gen_drv.h中的函数FATFS_LinkDriver(),将文件user_diskio.h中定义的驱动器对象USER_Driver链接到FatFS管理的驱动器列表里,相当于完成了驱动器的注册。
  • 文件user_diskio.c中实现了针对W25Q16芯片的Disk IO访问函数。文件user_diskio.h中定义了驱动器对象USER_Driver,并且使用函数指针将diskio.h中的Disk IO通用函数指向文件user_diskio.c中实现的针对W25Q16芯片的Diok IO函数。
  • 在文件user_diskio.c中实现W25Q16芯片的Disk IO访问函数时,需要用到W25Q16芯片的驱动程序文件w25flash.b/.c,而这个驱动程序使用SPI接口的HAL驱动程序实现对W25Q16芯片的访问。

 

相关文章:

  • Kafka Connect生产实践:性能优化与高可用架构构建
  • 基于深度学习的智能图像增强技术:原理、实现与应用
  • 2024 CKS题库+详尽解析| 5. 日志审计
  • 卷积神经网络(CNN)图像识别基础教程
  • 计算机网络-----详解网络原理TCP/IP(下)
  • UDP访问DNS
  • FPGA基础 -- Verilog语言要素之系统任务和系统函数
  • C++11 User-Defined Literals:从入门到精通
  • java 设计模式_行为型_22模板模式
  • web项目部署配置HTTPS遇到的问题解决方法
  • 【友加畅捷】T1飞跃版账套隐藏设置
  • 数据赋能(280)——过程管理——反馈机制
  • Spring 框架核心功能全解
  • 计算机网络期末速成 网络层 判断及单选题
  • 深度学习实战111-基于神经网络的A股、美股、黄金对冲投资策略(PyTorch LSTM)
  • MyBatis 模糊查询终极教程:安全高效的搜索实现
  • NLP学习路线图(五十一):PyTorch/TensorFlow
  • 论文笔记:Repetition Improves Language Model Embeddings
  • 人工智能100问☞第48问:GPT是怎么生成文本的?
  • Attention Backend的认识
  • 网站免费源码大全/seo有什么作用
  • 做愛的网站動漫/百度怎样发布信息
  • 做网站和淘宝美工 最低电脑/企业seo优化
  • 怀化市建设局门户网站/西安seo霸屏
  • 网站专题效果图怎么做/seo职业培训班
  • 实验教学网站的建设研究/苏州旺道seo