STM32移植最新版FATFS

FATFS源码下载

http://elm-chan.org/fsw/ff/00index_e.html

添加 FATFS 源码到工程

  1. 解压下载的 FATFS 源码包,将ff.cff.hffsystem.hffconf.hdiskio.h复制到工程目录下的一个新文件夹(例如FatFS)中。

  2. keil中添加源文件和路径,省略

编译并修改错误

完成上述操作,对整个工程代码进行编译后,出现了如下13个报错信息,通过定位报错信息可以得知,主要是由于文件系统diskio.c中对MMC、RAM、USB设备的初始化、读、写、状态获取API未定义和ff.c中对文件时间戳未定义。

因此,接下来对文件系统的移植操作主要是针对报错信息进行处理,将diskio.c文件中的硬件设备初始化、读、写、状态获取API及ff.c文件时间戳进行适配、定义实现。

这个错误是默认FATFS是使能RTC功能的,这里可以将其关闭

在"ffconf.h"配置文件中将这个宏设为1即可

实现diskio.c文件

diskio.c文件包含了 FATFS 与底层存储设备的接口函数,需要根据实际使用的存储设备进行实现。以下是一些常见的接口函数:

disk_status

这个函数的功能是获取设备的状态,只有一个参数pdrv,表示物理编号。因暂时只使用了SD卡,因此除了SD卡返回正常状态,其它类型设备全部返回的是非正常状态。

复制代码
/*-----------------------------------------------------------------------*/
/* Get Drive Status                                                      */
/*-----------------------------------------------------------------------*/

DSTATUS disk_status (
        BYTE pdrv                /* Physical drive nmuber to identify the drive */
)
{
        DSTATUS stat;
        int result;

        switch (pdrv) {
        case DEV_SD :
                 return SD_disk_status(pdrv);
        }
        return STA_NOINIT;
}

disk_initialize

disk_initialize函数是设备初始化接口,也是有一个参数pdrv,用来指定设备物理编号。因只有一个SD设备,除了SD状态中调用了SD_Init()对SD卡进行了初始化设置,其它类型全部返回了未初始化。

复制代码
/*-----------------------------------------------------------------------*/
/* Inidialize a Drive                                                    */
/*-----------------------------------------------------------------------*/

DSTATUS disk_initialize (
        BYTE pdrv                                /* Physical drive nmuber to identify the drive */
)
{
        DSTATUS stat;
        int result;

        switch (pdrv) {
        case DEV_SD :
                return SD_disk_initialize(pdrv);
        }
        return STA_NOINIT;
}

disk_read

disk_read函数有四个形参。pdrv为设备物理编号。buff是一个BYTE类型指针变量,buff指向用来存放读取到数据的存储区首地址。 sector是一个DWORD类型变量,指定要读取数据的扇区首地址。count是一个UINT类型变量,指定扇区数量。

BYTE类型实际是unsigned char类型,DWORD类型实际是unsigned long类型, UINT类型实际是 unsigned int类型,类型定义在ff.h文件中。

复制代码
/*-----------------------------------------------------------------------*/
/* Read Sector(s)                                                        */
/*-----------------------------------------------------------------------*/

DRESULT disk_read (
        BYTE pdrv,                /* Physical drive nmuber to identify the drive */
        BYTE *buff,                /* Data buffer to store read data */
        LBA_t sector,        /* Start sector in LBA */
        UINT count                /* Number of sectors to read */
)
{
        DRESULT res;
        int result;

        switch (pdrv) {
        case DEV_SD :
                return SD_disk_read(pdrv, buff, sector, count);         
        }

        return RES_PARERR;
}

disk_write

disk_write函数有四个形参,pdrv为设备物理编号。buff指向待写入扇区数据的首地址。sector,指定要读取数据的扇区首地址。 count指定扇区数量

复制代码
/*-----------------------------------------------------------------------*/
/* Write Sector(s)                                                       */
/*-----------------------------------------------------------------------*/

#if FF_FS_READONLY == 0

DRESULT disk_write (
        BYTE pdrv,                        /* Physical drive nmuber to identify the drive */
        const BYTE *buff,        /* Data to be written */
        LBA_t sector,                /* Start sector in LBA */
        UINT count                        /* Number of sectors to write */
)
{
        DRESULT res;
        int result;

        switch (pdrv) {
        case DEV_SD :
                return SD_disk_write(pdrv, buff, sector, count);         
        }

        return RES_PARERR;
}

#endif

disk_ioctl

disk_ioctl函数有三个形参,pdrv为设备物理编号,cmd为控制指令,包括发出同步信号、获取扇区数目、获取扇区大小、 获取擦除块数量等等指令,buff为指令对应的数据指针。

对于SD卡,为支持格式化功能,需要用到获取扇区数量(GET_SECTOR_COUNT)指令和获取块尺寸(GET_BLOCK_SIZE)。另外,SD卡扇区大小为512字节, 串行Flash芯片一般设置扇区大小为4096字节,所以需要用到获取扇区大小(GET_SECTOR_SIZE)指令。

复制代码
/*-----------------------------------------------------------------------*/
/* Miscellaneous Functions                                               */
/*-----------------------------------------------------------------------*/

DRESULT disk_ioctl (
        BYTE pdrv,                /* Physical drive nmuber (0..) */
        BYTE cmd,                /* Control code */
        void *buff                /* Buffer to send/receive control data */
)
{
        DRESULT res;
        int result;

        switch (pdrv) {
        case DEV_SD :
                return SD_disk_ioctl(pdrv, cmd, buff);;
        }

        return RES_PARERR;
}

配置ffconf.h文件

复制代码
#define FF_USE_MKFS   1
#define FF_CODE_PAGE  936
#define FF_USE_LFN    1
#define FF_VOLUMES    1
#define FF_MIN_SS     512
#define FF_MAX_SS     4096
  1. FF_USE_MKFS: 格式化功能选择,为使用FatFs格式化功能,需要把它设置为1。

  2. FF_CODE_PAGE: 语言功能选择,并要求把相关语言文件添加到工程宏。为支持简体中文文件名需要使用"936"

  3. FF_USE_LFN: 长文件名支持,默认不支持长文件名,这里配置为1,支持长文件名,并指定将文件名存储在BSS段(数据段),也就是将其作为全局变量进行存储;配置为"#define FF_USE_LFN 2"就是将 文件名存储在STACK区(栈区);配置为"#define FF_USE_LFN 3"就是将文件名存储在HEAP(堆区)。一般配置为配置为"#define FF_USE_LFN 1"。如果存储在栈空间,防止某处操作不当而溢出。

  4. FF_VOLUMES: 指定物理设备数量,这里设置为1,SD卡设备

  5. FF_MIN_SS 、FF_MAX_SS: 指定扇区大小的最小值和最大值。SD卡扇区大小一般都为512字节,W25Q64芯片扇区大小一般设置为4096字节,所以需要把_MAX_SS改为4096。

测试代码

变量定义

复制代码
FATFS fs;
FATFS *pfs;
FIL fp;
FRESULT fres;
DWORD fre_clust;
uint32_t totalSpace, freeSpace;

初始化部分

复制代码
        FRESULT ret = f_mount(&fs, "0:", 0x01);
        log_d("f_mount result: %02X\r\n", ret);
        if(ret != FR_OK)
        {
                log_d("f_mount failed\r\n");
                Error_Handler();
        }

        /* Check freeSpace space */
        if(f_getfree("", &fre_clust, &pfs) != FR_OK)
        {
                log_d("f_getfree failed\r\n");
                Error_Handler();
        }

        totalSpace = (uint32_t)((pfs->n_fatent - 2) * pfs->csize * 0.5);
        freeSpace = (uint32_t)(fre_clust * pfs->csize * 0.5);
        log_d("total:%dKB, free:%dKB\r\n", totalSpace, freeSpace);

        /* free space is less than 1kb */
        if(freeSpace < 1)
        {
                log_d("freeSpace not enough\r\n");
                Error_Handler();
        }

        /* Open file to write */
        log_d("f_open first.txt\r\n");
        if(f_open(&fp, "first.txt", FA_OPEN_ALWAYS | FA_READ | FA_WRITE) != FR_OK)
        {
                log_d("f_open failed\r\n");
                Error_Handler();
        }

        /* Writing text */
        f_puts("STM32 SD Card I/O Example via SPI\n", &fp);
        f_puts("Black Sheep Wall!!!", &fp);

        /* Close file */
        log_d("f_close first.txt\r\n");
        if(f_close(&fp) != FR_OK)
        {
                log_d("f_close failed\r\n");
                Error_Handler();
        }

        /* Open file to read */
        log_d("f_open first.txt\r\n");
        if(f_open(&fp, "first.txt", FA_READ) != FR_OK)
        {
                log_d("f_open failed\r\n");
                Error_Handler();
        }

        log_d("f_gets first.txt\r\n");
        while(f_gets(buffer, sizeof(buffer), &fp))
        {
                /* SWV output */
                log_d("%s", buffer);
                fflush(stdout);
        }
        log_d("\r\ndone\r\n");

        /* Close file */
        log_d("f_close first.txt\r\n");
        if(f_close(&fp) != FR_OK)
        {
                log_d("f_close failed\r\n");
                Error_Handler();
        }

        /* Unmount SDCARD */
        log_d("f_mount unmount");
        if(f_mount(NULL, "0:", 1) != FR_OK) 
        {
                log_d("f_mount failed (unmount)\r\n");
                Error_Handler();
        }

运行效果

相关推荐
十月的皮皮9 小时前
stm20260720-从新手 C 到量产 STM32 工程:程序设计推导指南
c语言·开发语言·stm32·stm32cubemx·hal库
开发笔记-阿牛9 小时前
解析一款有意思的产品||CK6159A语音芯片设计的儿童专注力训练机-舒尔特玩具
stm32·单片机·嵌入式硬件·音频
搞全栈小苏11 小时前
SIMetrix_simplis8.4安装教程——附安装包
stm32·单片机·嵌入式硬件·电力电子
qq_5739678212 小时前
STM32控制器
stm32·单片机·嵌入式硬件
某林21213 小时前
履带小车底盘stm32F103RCT6开发
人工智能·stm32·单片机·嵌入式硬件·架构·人机交互·ros2
做萤石二次开发的哈哈15 小时前
萤石 ERTC Windows SDK 包含哪些类型定义?
stm32·单片机·嵌入式硬件
亿道电子Emdoor15 小时前
【Aitium】PCB导出DXF文件出现eDuplicateRecordName报错
stm32·单片机·嵌入式硬件·altium
巴巴媛6661 天前
STM32学习笔记【38.DHT11实验】
笔记·stm32·学习
深圳市泰凌微电子1 天前
HK航顺 HK32F407RGT7替STM32F405RGT6 微控制器32位MCU
stm32·单片机·嵌入式硬件
小心亦新1 天前
STM32学习16--定时器输出比较2直流电机
stm32·嵌入式硬件·学习