1. 修改diskio.c
/*-----------------------------------------------------------------------*/ /* Low level disk I/O module SKELETON for FatFs (C)ChaN, 2019 */ /*-----------------------------------------------------------------------*/ /* If a working storage control module is available, it should be */ /* attached to the FatFs via a glue function rather than modifying it. */ /* This is an example of glue functions to attach various exsisting */ /* storage control modules to the FatFs module with a defined API. */ /*-----------------------------------------------------------------------*/ #include "ff.h" /* Obtains integer types */ #include "diskio.h" /* Declarations of disk functions */ #include "sdmmc.h" /* Definitions of physical drive number for each drive */ #define DEV_RAM 0 /* Example: Map Ramdisk to physical drive 0 */ #define DEV_MMC 1 /* Example: Map MMC/SD card to physical drive 1 */ #define DEV_USB 2 /* Example: Map USB MSD to physical drive 2 */ /*-----------------------------------------------------------------------*/ /* Get current time */ /*-----------------------------------------------------------------------*/ DWORD get_fattime(void) { return 0; } /*-----------------------------------------------------------------------*/ /* Get Drive Status */ /*-----------------------------------------------------------------------*/ static DSTATUS MMC_disk_status() { DSTATUS stat = STA_NOINIT; char result = GetStatus(); stat = result; return stat; } DSTATUS disk_status ( BYTE pdrv /* Physical drive nmuber to identify the drive */ ) { DSTATUS stat = STA_NOINIT; switch (pdrv) { case DEV_RAM : // stat = RAM_disk_status(); // translate the reslut code here return stat; case DEV_MMC : stat = MMC_disk_status(); // translate the reslut code here return stat; case DEV_USB : // stat = USB_disk_status(); // translate the reslut code here return stat; } return stat; } /*-----------------------------------------------------------------------*/ /* Inidialize a Drive */ /*-----------------------------------------------------------------------*/ static char MMC_disk_initialize() { DSTATUS stat = STA_NOINIT; char result = GetInfo(); stat = result; return stat; } DSTATUS disk_initialize ( BYTE pdrv /* Physical drive nmuber to identify the drive */ ) { DSTATUS stat; int result; switch (pdrv) { case DEV_RAM : // result = RAM_disk_initialize(); // translate the reslut code here return stat; case DEV_MMC : stat = MMC_disk_initialize(); // translate the reslut code here return stat; case DEV_USB : // result = USB_disk_initialize(); // translate the reslut code here return stat; } return STA_NOINIT; } /*-----------------------------------------------------------------------*/ /* Read Sector(s) */ /*-----------------------------------------------------------------------*/ static DRESULT MMC_disk_read( BYTE *buff, /* Data buffer to store read data */ LBA_t sector, /* Start sector in LBA */ UINT count /* Number of sectors to read */ ) { while(HAL_SD_CARD_TRANSFER != HAL_SD_GetCardState(&hsd1)); char result = HAL_SD_ReadBlocks(&hsd1, (uint8_t *)buff, sector, count, 0xffff); return result; } 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 = RES_ERROR; int result; switch (pdrv) { case DEV_RAM : // translate the arguments here // result = RAM_disk_read(buff, sector, count); // translate the reslut code here return res; case DEV_MMC : // translate the arguments here result = MMC_disk_read(buff, sector, count); // translate the reslut code here if(result == 0)res = RES_OK; return res; case DEV_USB : // translate the arguments here // result = USB_disk_read(buff, sector, count); // translate the reslut code here return res; } return RES_PARERR; } /*-----------------------------------------------------------------------*/ /* Write Sector(s) */ /*-----------------------------------------------------------------------*/ #if FF_FS_READONLY == 0 static DRESULT MMC_disk_write( const BYTE *buff, /* Data buffer to store read data */ LBA_t sector, /* Start sector in LBA */ UINT count /* Number of sectors to read */ ) { while(HAL_SD_CARD_TRANSFER != HAL_SD_GetCardState(&hsd1)); char result = HAL_SD_WriteBlocks(&hsd1, (uint8_t *)buff, sector, count, 0xffff); return result; } 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 = RES_ERROR; int result; switch (pdrv) { case DEV_RAM : // translate the arguments here // result = RAM_disk_write(buff, sector, count); // translate the reslut code here return res; case DEV_MMC : // translate the arguments here result = MMC_disk_write(buff, sector, count); // translate the reslut code here if(result == 0)res = RES_OK; return res; case DEV_USB : // translate the arguments here // result = USB_disk_write(buff, sector, count); // translate the reslut code here return res; } return RES_PARERR; } #endif /*-----------------------------------------------------------------------*/ /* 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 = RES_ERROR; int delay = 10240; HAL_SD_CardInfoTypeDef SDCard; switch (pdrv) { case DEV_RAM : // Process of the command for the RAM drive return res; case DEV_MMC : HAL_SD_GetCardInfo(&hsd1,&SDCard); uint64_t CardCap=(uint64_t)(SDCard.LogBlockNbr)*(uint64_t)(SDCard.LogBlockSize); // Process of the command for the MMC/SD card switch ( cmd ) //fatfs ں ʹ cmd { case GET_SECTOR_COUNT: // *(DWORD*)buff = SDCard.BlockNbr; return RES_OK; case GET_SECTOR_SIZE: // С λbytes *(DWORD*)buff = SDCard.BlockSize; return RES_OK; case GET_BLOCK_SIZE: //block size, *(DWORD*)buff = 1; // λΪ sector(FatFs) return RES_OK; case CTRL_SYNC: //ͬ ò FatFs ں ж д Ƿ return RES_OK; } return RES_OK; case DEV_USB : // Process of the command the USB drive return res; } return RES_PARERR; }
2. 实现文件操作
/* * fileapp.c * * Created on: Nov 3, 2023 * Author: luobo */ #include "fileapp.h" volatile BYTE sd_plugin = 0; volatile BYTE sd_inited = 0; volatile FATFS FatFs_user; /* 每个逻辑驱动器的文件系统对象 */ volatile FIL File_user; /* 文件对象 */ FRESULT res_sd_user; /* FatFs_user 函数公共结果代码 */ UINT br, bw; /* 文件写字节计数 */ BYTE FF_Buff[FF_MAX_SS] = "Fatfs file test\r\n"; /* Working buffer */ BYTE FF_Buff2[FF_MAX_SS] = "6666666666666666666666666666666666666666666666666666\r\n"; /************************************************ 函数名称: FF_System_Creates 功能: Fatfs文件系统注册 参数: Drive ---- 盘符 Opt ---- 0:现在不要安装(在第1次访问该卷时安装 1:强制安装该卷以检查它是否可以工作 返回值:无 *************************************************/ void FF_System_Creates( char *pDrive, uint8_t Opt ) { /* 为 ? 辑驱动器工作区注册 */ res_sd_user = f_mount(&FatFs_user, pDrive, Opt); if(1 == Opt) { /* 如果没有文件系统就格式化创建文件系统 */ if(res_sd_user == FR_NO_FILESYSTEM) { NRF_LOG_INFO("SD_formatting...\r\n"); res_sd_user = f_mkfs(pDrive, 0, FF_Buff, sizeof(FF_Buff)); // 格式 ???? if(res_sd_user == FR_OK) { NRF_LOG_INFO("SD formatting successful\r\n"); res_sd_user = f_mount(NULL, pDrive, 1); // 格式化后,先取消挂载 res_sd_user = f_mount(&FatFs_user, pDrive, 1); // 重新挂载 } else { NRF_LOG_INFO("SD formatting file(error code:%d)\r\n",res_sd_user); // while(1); } } else if(res_sd_user != FR_OK) { NRF_LOG_INFO("Failed SD card.(error code:%d)\r\n",res_sd_user); // while(1); } else { NRF_LOG_INFO("SD successful\r\n"); } } else { NRF_LOG_INFO("The file system is mounted successfully, and files can be read and written\r\n"); } } /************************************************ 函数名称: FF_System_Uncreates 功能: Fatfs文件系统 参数: Drive ---- 盘符 Opt ---- 0:现在不要安装(在第1次访问该卷时安装 1:强制安装该卷以检查它是否可以工作 返回值:无 *************************************************/ void FF_System_Uncreates( char *pDrive) { /* 驱动器工作区注销 */ res_sd_user = f_mount(&FatFs_user, pDrive, 0); // 取消挂载 if(res_sd_user == FR_OK) { NRF_LOG_INFO("Unmount a Logical Drive successfully: %s\r\n", pDrive); } } void FF_Mount_System(char *pDrive) { res_sd_user = f_mount(&FatFs_user, pDrive, 1); // 挂载 if(res_sd_user == FR_OK) { NRF_LOG_INFO("Mount a Logical Drive successfully: %s\r\n", pDrive); } } /************************************************ 函数名称: FF_Create 功能: 创建文件 参数: pFile ---- 要创建的文件 返回值: 0 / 1 *************************************************/ uint8_t FF_Create( char *pFile) { uint8_t temp = 0; res_sd_user = f_open(&File_user, pFile, FA_CREATE_ALWAYS); if( res_sd_user == FR_OK ) { NRF_LOG_INFO("create Success: %s\r\n",pFile); f_close(&File_user); // 不再读写,关闭文件 } else { NRF_LOG_INFO("Fail to create the file .\r\n"); } return temp; } /************************************************ 函数名称: FF_Open 功能: 打开文件 参数: pFile ---- 要打开的文件 返回值: 0 / 1 *************************************************/ uint8_t FF_Open( char *pFile) { uint8_t temp = 0; res_sd_user = f_open(&File_user, pFile, FA_CREATE_ALWAYS); if( res_sd_user == FR_OK ) { NRF_LOG_INFO("Open Success: %s\r\n",pFile); } else { NRF_LOG_INFO("create the file .\r\n"); } return temp; } /************************************************ 函数名称: FF_Close 功能: 关闭文件 参数: pFile ---- 要关闭的文件 返回值: 0 / 1 *************************************************/ uint8_t FF_Close( char *pFile) { uint8_t temp = 0; res_sd_user = f_close(&File_user); // 不再读写,关闭文件 if( res_sd_user == FR_OK ) { NRF_LOG_INFO("Close Success: %s\r\n",pFile); f_close(&File_user); // 不再读写,关闭文件 } else { NRF_LOG_INFO("Failed to Close.\r\n"); } return temp; } /************************************************ 函数名称: FF_OpenWrite 功能: 打开文件并写入信息 参数: pFile ---- 要打开的文件 pStr ---- 要写入的信息 Len ---- 长度 返回值: 0 / 1 *************************************************/ uint8_t FF_OpenWrite( char *pFile, void *pStr, uint16_t Len ) { uint8_t temp = 0; static uint32_t count = 0; res_sd_user = f_open(&File_user, pFile, FA_CREATE_ALWAYS | FA_WRITE ); if( res_sd_user == FR_OK ) { //NRF_LOG_INFO("File opened successfully\r\n"); /* 将指定存储区内容写入到文件内 */ res_sd_user = f_write(&File_user, pStr, Len, &bw); if(res_sd_user == FR_OK) { count +=bw; NRF_LOG_INFO("write bytes: %d\r\n", count); //NRF_LOG_INFO("The data written to the file is:\r\n%s\r\n", (char*)pStr); temp = 1; } else { NRF_LOG_INFO("!!File write failure.(error code:%d)\r\n", res_sd_user); } f_close(&File_user); // 不再读写,关闭文件 } else { NRF_LOG_INFO("Failed to open/create the file .\r\n"); } return temp; } /************************************************ 函数名称: FF_OpenWrite 功能: 打开文件并追加写入信息 参数: pFile ---- 要打开的文件 pStr ---- 要写入的信息 Len ---- 长度 返回值: 0 / 1 *************************************************/ uint8_t FF_OpenAppend( char *pFile, void *pStr, uint16_t Len ) { uint8_t temp = 0; uint32_t count = 0; res_sd_user = f_open(&File_user, pFile, FA_OPEN_APPEND | FA_WRITE ); if(res_sd_user != FR_OK) { res_sd_user = f_open(&File_user, pFile, FA_CREATE_NEW | FA_WRITE ); } if( res_sd_user == FR_OK ) { //NRF_LOG_INFO("File opened successfully\r\n"); /* 将指定存储区内容写入到文件内 */ res_sd_user = f_write(&File_user, pStr, Len, &bw); if(res_sd_user == FR_OK) { count = bw; NRF_LOG_INFO("%s write bytes: %d\r\n", pFile, count); //NRF_LOG_INFO("The data written to the file is:\r\n%s\r\n", (char*)pStr); temp = 1; } else { NRF_LOG_INFO("!!File write failure.(error code:%d)\r\n", res_sd_user); } f_close(&File_user); // 不再读写,关闭文件 } else { NRF_LOG_INFO("Failed to open/create the file .\r\n"); } return temp; } /************************************************ 函数名称: FF_OpenRead 功能:打开文件并读取信息 参数: pFile ---- 要打开的文件 pStr ---- 要读取的信息缓存 返回值: 0 / 1 *************************************************/ uint8_t FF_OpenRead( char *pFile, void *pStr, uint16_t Len ) { uint8_t temp = 0; res_sd_user = f_open(&File_user, pFile, FA_OPEN_EXISTING | FA_READ); if(res_sd_user == FR_OK) { NRF_LOG_INFO("File opened successfully\r\n"); /* 将文件内容读取到指定存储区内 */ res_sd_user = f_read(&File_user, pStr, Len, &br); if(res_sd_user == FR_OK) { NRF_LOG_INFO("File read successfully, read bytes: %d\r\n",br); NRF_LOG_INFO("The file data obtained by reading is: %s\r\n", (char*)pStr); temp = 1; } else { NRF_LOG_INFO("!!File write failure.(error code:%d)\r\n", res_sd_user); } } else { NRF_LOG_INFO("!! Failed to open/create the file .\r\n"); } f_close(&File_user); // 不再读写,关闭文 ???? return temp; } /************************************************ 函数名称: FF_ViewRootDir 功能: Fatfs文件扫描显示 参数: Drive ---- 盘符 返回值:无 *************************************************/ void FF_ViewRootDir( char *pDrive ) { /* 本函数使用的 ????部变量占用较多,请修改启动文件,保证堆栈空间够用 */ DIR DirInf; FILINFO FileInf; uint32_t cnt = 0; /* 打开根文件夹 */ res_sd_user = f_opendir(&DirInf, pDrive); if (res_sd_user != FR_OK) { NRF_LOG_INFO("Failed to open the root directory .(error code:%d)\r\n", res_sd_user); return; } /* 读取当前文件夹下的文件和目录 */ NRF_LOG_INFO("\r\n| attribute \t\t| file size \t\t| name\r\n"); for (cnt = 0; ;cnt++) { res_sd_user = f_readdir(&DirInf, &FileInf); /* 读取目录项,索引会自动下 ???? */ if (res_sd_user != FR_OK || FileInf.fname[0] == 0) { break; } if (FileInf.fname[0] == '.') { continue; } /* 判断是文件类型及目录目录 */ switch(FileInf.fattrib) { case AM_DIR: NRF_LOG_INFO("| (0x%02X)subdirectory\t\t", FileInf.fattrib); break; case AM_RDO: NRF_LOG_INFO("| (0x%02X)r\t\t", FileInf.fattrib); break; case AM_HID: NRF_LOG_INFO("| (0x%02X)h\t\t", FileInf.fattrib); break; case AM_SYS: NRF_LOG_INFO("| (0x%02X)sys\t\t", FileInf.fattrib); break; case AM_ARC: NRF_LOG_INFO("| (0x%02X)archived\t\t", FileInf.fattrib); break; default: NRF_LOG_INFO("| (0x%02X)Unknown type\t\t", FileInf.fattrib); break; } /* 打印文件大小, ???? ????4G */ NRF_LOG_INFO("| %1u\t\t", FileInf.fsize); NRF_LOG_INFO("| %s\t\t\r\n", (char *)FileInf.fname); /* 长文件名 */ } NRF_LOG_INFO("\r\n"); res_sd_user = f_closedir(&DirInf); if (res_sd_user != FR_OK) { NRF_LOG_INFO("Failed to close the root directory .(error code:%d)\r\n", res_sd_user); return; } } /************************************************ 函数名称: FF_MKDir 功能: Fatfs文件系统新建文件夹 参数: path ---- 路径 返回值:无 *************************************************/ void FF_MKDir(char *path) { int res_sd_user = f_mkdir(path); switch(res_sd_user) { case FR_OK: { NRF_LOG_INFO("Create successfully Directory the root directory.\r\n"); break; } case FR_EXIST: { NRF_LOG_INFO("Directory exist.\r\n"); break; } default: { NRF_LOG_INFO("Failed to create Directory the root directory .(error code:%d)\r\n", res_sd_user); break; } } } /************************************************ 函数名称: FF_Delete 功能: Fatfs文件系统删除文件夹/文件 参数: path ---- 路径 返回值:无 *************************************************/ void FF_Delete(char *path) { int res_sd_user = f_unlink(path); switch(res_sd_user) { case FR_OK: { NRF_LOG_INFO("Delete successfully %s.\r\n", path); break; } case FR_NO_PATH: { NRF_LOG_INFO("Directory no exist.\r\n"); break; } case FR_NO_FILE: { NRF_LOG_INFO("File no exist.\r\n"); break; } default: { NRF_LOG_INFO("Failed to delete Directory the root directory .(error code:%d)\r\n", res_sd_user); break; } } } /************************************************ 函数名称: FF_Test 功能: Fatfs文件系统测试 参数:无 返回值:无 *************************************************/ void FF_Test(void) { uint32_t num = strlen(FF_Buff2); FF_System_Creates(DRIVER_DISK, 1); FF_OpenWrite("1:temp.txt", FF_Buff2, num); FF_OpenRead("1:temp.txt", &FF_Buff[512], num); FF_OpenWrite("1:temp1.txt", FF_Buff2, num); FF_OpenRead("1:temp1.txt", &FF_Buff[512], num); /* 不再使用文件系统,取消挂载文件系 ???? */ // f_mount(NULL, DRIVER_DISK, 1); } typedef char TCHAR; /************************************************ 函数名称: FF_Dir_Del 功能: 删除Fatfs文件系统指定文件夹下的文件夹及子文件夹/文件 参数:path ---- 路径 返回值:0/1 *************************************************/ FRESULT FF_Dir_Del(TCHAR* path)//递归删除文件夹 { FRESULT res; DIR dir; UINT i; static FILINFO fno; res = f_opendir(&dir, path);//打开此文件夹 if (res == FR_OK){//成功打开文件夹 for (;;){//循环扫描文件夹和文件 res = f_readdir(&dir, &fno);//读取此文件家中的一个子文件 if (res != FR_OK || fno.fname[0] == 0) break;//读取错误或者已经扫描完此文件夹下的所有文件,跳出循环 if (fno.fattrib & AM_DIR) {//子文件为文件夹 i = strlen(path);//统计附文件夹路径长度 sprintf((char*)&path[i], "\\%s", fno.fname);//将子文件夹名加入路径 res = FF_Dir_Del(path);//递归进入子文件夹,扫描文件夹 if (res != FR_OK) break;//操作失败跳出循环 path[i] =0;//文件路径回退 } else {//子文件为 文件类型 i = strlen(path);//统计附文件夹路径长度 sprintf((char*)&path[i], "\\%s", fno.fname);//将子文件名加入路径 res=f_unlink(path);//删除子文件 path[i] =0;//文件路径回退 } } res=f_closedir(&dir);//挂你打开的父文件夹 res=f_unlink(path);//删除已经清空的父文件夹 } return res; }
ffconf.h
/*---------------------------------------------------------------------------/ / Configurations of FatFs Module /---------------------------------------------------------------------------*/ #define FFCONF_DEF 80286 /* Revision ID */ /*---------------------------------------------------------------------------/ / Function Configurations /---------------------------------------------------------------------------*/ #define FF_FS_READONLY 0 /* This option switches read-only configuration. (0:Read/Write or 1:Read-only) / Read-only configuration removes writing API functions, f_write(), f_sync(), / f_unlink(), f_mkdir(), f_chmod(), f_rename(), f_truncate(), f_getfree() / and optional writing functions as well. */ #define FF_FS_MINIMIZE 0 /* This option defines minimization level to remove some basic API functions. / / 0: Basic functions are fully enabled. / 1: f_stat(), f_getfree(), f_unlink(), f_mkdir(), f_truncate() and f_rename() / are removed. / 2: f_opendir(), f_readdir() and f_closedir() are removed in addition to 1. / 3: f_lseek() function is removed in addition to 2. */ #define FF_USE_FIND 0 /* This option switches filtered directory read functions, f_findfirst() and / f_findnext(). (0:Disable, 1:Enable 2:Enable with matching altname[] too) */ #define FF_USE_MKFS 1 /* This option switches f_mkfs() function. (0:Disable or 1:Enable) */ #define FF_USE_FASTSEEK 1 /* This option switches fast seek function. (0:Disable or 1:Enable) */ #define FF_USE_EXPAND 0 /* This option switches f_expand function. (0:Disable or 1:Enable) */ #define FF_USE_CHMOD 0 /* This option switches attribute manipulation functions, f_chmod() and f_utime(). / (0:Disable or 1:Enable) Also FF_FS_READONLY needs to be 0 to enable this option. */ #define FF_USE_LABEL 0 /* This option switches volume label functions, f_getlabel() and f_setlabel(). / (0:Disable or 1:Enable) */ #define FF_USE_FORWARD 0 /* This option switches f_forward() function. (0:Disable or 1:Enable) */ #define FF_USE_STRFUNC 2 #define FF_PRINT_LLI 1 #define FF_PRINT_FLOAT 1 #define FF_STRF_ENCODE 3 /* FF_USE_STRFUNC switches string functions, f_gets(), f_putc(), f_puts() and / f_printf(). / / 0: Disable. FF_PRINT_LLI, FF_PRINT_FLOAT and FF_STRF_ENCODE have no effect. / 1: Enable without LF-CRLF conversion. / 2: Enable with LF-CRLF conversion. / / FF_PRINT_LLI = 1 makes f_printf() support long long argument and FF_PRINT_FLOAT = 1/2 / makes f_printf() support floating point argument. These features want C99 or later. / When FF_LFN_UNICODE >= 1 with LFN enabled, string functions convert the character / encoding in it. FF_STRF_ENCODE selects assumption of character encoding ON THE FILE / to be read/written via those functions. / / 0: ANSI/OEM in current CP / 1: Unicode in UTF-16LE / 2: Unicode in UTF-16BE / 3: Unicode in UTF-8 */ /*---------------------------------------------------------------------------/ / Locale and Namespace Configurations /---------------------------------------------------------------------------*/ #define FF_CODE_PAGE 936 /* This option specifies the OEM code page to be used on the target system. / Incorrect code page setting can cause a file open failure. / / 437 - U.S. / 720 - Arabic / 737 - Greek / 771 - KBL / 775 - Baltic / 850 - Latin 1 / 852 - Latin 2 / 855 - Cyrillic / 857 - Turkish / 860 - Portuguese / 861 - Icelandic / 862 - Hebrew / 863 - Canadian French / 864 - Arabic / 865 - Nordic / 866 - Russian / 869 - Greek 2 / 932 - Japanese (DBCS) / 936 - Simplified Chinese (DBCS) / 949 - Korean (DBCS) / 950 - Traditional Chinese (DBCS) / 0 - Include all code pages above and configured by f_setcp() */ #define FF_USE_LFN 3 #define FF_MAX_LFN 255 /* The FF_USE_LFN switches the support for LFN (long file name). / / 0: Disable LFN. FF_MAX_LFN has no effect. / 1: Enable LFN with static working buffer on the BSS. Always NOT thread-safe. / 2: Enable LFN with dynamic working buffer on the STACK. / 3: Enable LFN with dynamic working buffer on the HEAP. / / To enable the LFN, ffunicode.c needs to be added to the project. The LFN function / requiers certain internal working buffer occupies (FF_MAX_LFN + 1) * 2 bytes and / additional (FF_MAX_LFN + 44) / 15 * 32 bytes when exFAT is enabled. / The FF_MAX_LFN defines size of the working buffer in UTF-16 code unit and it can / be in range of 12 to 255. It is recommended to be set it 255 to fully support LFN / specification. / When use stack for the working buffer, take care on stack overflow. When use heap / memory for the working buffer, memory management functions, ff_memalloc() and / ff_memfree() exemplified in ffsystem.c, need to be added to the project. */ #define FF_LFN_UNICODE 2 /* This option switches the character encoding on the API when LFN is enabled. / / 0: ANSI/OEM in current CP (TCHAR = char) / 1: Unicode in UTF-16 (TCHAR = WCHAR) / 2: Unicode in UTF-8 (TCHAR = char) / 3: Unicode in UTF-32 (TCHAR = DWORD) / / Also behavior of string I/O functions will be affected by this option. / When LFN is not enabled, this option has no effect. */ #define FF_LFN_BUF 255 #define FF_SFN_BUF 12 /* This set of options defines size of file name members in the FILINFO structure / which is used to read out directory items. These values should be suffcient for / the file names to read. The maximum possible length of the read file name depends / on character encoding. When LFN is not enabled, these options have no effect. */ #define FF_FS_RPATH 0 /* This option configures support for relative path. / / 0: Disable relative path and remove related functions. / 1: Enable relative path. f_chdir() and f_chdrive() are available. / 2: f_getcwd() function is available in addition to 1. */ /*---------------------------------------------------------------------------/ / Drive/Volume Configurations /---------------------------------------------------------------------------*/ #define FF_VOLUMES 2 /* Number of volumes (logical drives) to be used. (1-10) */ #define FF_STR_VOLUME_ID 0 #define FF_VOLUME_STRS "RAM","NAND","CF","SD","SD2","USB","USB2","USB3" /* FF_STR_VOLUME_ID switches support for volume ID in arbitrary strings. / When FF_STR_VOLUME_ID is set to 1 or 2, arbitrary strings can be used as drive / number in the path name. FF_VOLUME_STRS defines the volume ID strings for each / logical drives. Number of items must not be less than FF_VOLUMES. Valid / characters for the volume ID strings are A-Z, a-z and 0-9, however, they are / compared in case-insensitive. If FF_STR_VOLUME_ID >= 1 and FF_VOLUME_STRS is / not defined, a user defined volume string table is needed as: / / const char* VolumeStr[FF_VOLUMES] = {"ram","flash","sd","usb",... */ #define FF_MULTI_PARTITION 0 /* This option switches support for multiple volumes on the physical drive. / By default (0), each logical drive number is bound to the same physical drive / number and only an FAT volume found on the physical drive will be mounted. / When this function is enabled (1), each logical drive number can be bound to / arbitrary physical drive and partition listed in the VolToPart[]. Also f_fdisk() / function will be available. */ #define FF_MIN_SS 512 #define FF_MAX_SS 4096 /* This set of options configures the range of sector size to be supported. (512, / 1024, 2048 or 4096) Always set both 512 for most systems, generic memory card and / harddisk, but a larger value may be required for on-board flash memory and some / type of optical media. When FF_MAX_SS is larger than FF_MIN_SS, FatFs is configured / for variable sector size mode and disk_ioctl() function needs to implement / GET_SECTOR_SIZE command. */ #define FF_LBA64 0 /* This option switches support for 64-bit LBA. (0:Disable or 1:Enable) / To enable the 64-bit LBA, also exFAT needs to be enabled. (FF_FS_EXFAT == 1) */ #define FF_MIN_GPT 0x10000000 /* Minimum number of sectors to switch GPT as partitioning format in f_mkfs and / f_fdisk function. 0x100000000 max. This option has no effect when FF_LBA64 == 0. */ #define FF_USE_TRIM 0 /* This option switches support for ATA-TRIM. (0:Disable or 1:Enable) / To enable Trim function, also CTRL_TRIM command should be implemented to the / disk_ioctl() function. */ /*---------------------------------------------------------------------------/ / System Configurations /---------------------------------------------------------------------------*/ #define FF_FS_TINY 0 /* This option switches tiny buffer configuration. (0:Normal or 1:Tiny) / At the tiny configuration, size of file object (FIL) is shrinked FF_MAX_SS bytes. / Instead of private sector buffer eliminated from the file object, common sector / buffer in the filesystem object (FATFS) is used for the file data transfer. */ #define FF_FS_EXFAT 0 /* This option switches support for exFAT filesystem. (0:Disable or 1:Enable) / To enable exFAT, also LFN needs to be enabled. (FF_USE_LFN >= 1) / Note that enabling exFAT discards ANSI C (C89) compatibility. */ #define FF_FS_NORTC 0 #define FF_NORTC_MON 1 #define FF_NORTC_MDAY 1 #define FF_NORTC_YEAR 2022 /* The option FF_FS_NORTC switches timestamp feature. If the system does not have / an RTC or valid timestamp is not needed, set FF_FS_NORTC = 1 to disable the / timestamp feature. Every object modified by FatFs will have a fixed timestamp / defined by FF_NORTC_MON, FF_NORTC_MDAY and FF_NORTC_YEAR in local time. / To enable timestamp function (FF_FS_NORTC = 0), get_fattime() function need to be / added to the project to read current time form real-time clock. FF_NORTC_MON, / FF_NORTC_MDAY and FF_NORTC_YEAR have no effect. / These options have no effect in read-only configuration (FF_FS_READONLY = 1). */ #define FF_FS_NOFSINFO 0 /* If you need to know correct free space on the FAT32 volume, set bit 0 of this / option, and f_getfree() function at the first time after volume mount will force / a full FAT scan. Bit 1 controls the use of last allocated cluster number. / / bit0=0: Use free cluster count in the FSINFO if available. / bit0=1: Do not trust free cluster count in the FSINFO. / bit1=0: Use last allocated cluster number in the FSINFO if available. / bit1=1: Do not trust last allocated cluster number in the FSINFO. */ #define FF_FS_LOCK 0 /* The option FF_FS_LOCK switches file lock function to control duplicated file open / and illegal operation to open objects. This option must be 0 when FF_FS_READONLY / is 1. / / 0: Disable file lock function. To avoid volume corruption, application program / should avoid illegal open, remove and rename to the open objects. / >0: Enable file lock function. The value defines how many files/sub-directories / can be opened simultaneously under file lock control. Note that the file / lock control is independent of re-entrancy. */ #define FF_FS_REENTRANT 0 #define FF_FS_TIMEOUT 1000 /* The option FF_FS_REENTRANT switches the re-entrancy (thread safe) of the FatFs / module itself. Note that regardless of this option, file access to different / volume is always re-entrant and volume control functions, f_mount(), f_mkfs() / and f_fdisk() function, are always not re-entrant. Only file/directory access / to the same volume is under control of this featuer. / / 0: Disable re-entrancy. FF_FS_TIMEOUT have no effect. / 1: Enable re-entrancy. Also user provided synchronization handlers, / ff_mutex_create(), ff_mutex_delete(), ff_mutex_take() and ff_mutex_give() / function, must be added to the project. Samples are available in ffsystem.c. / / The FF_FS_TIMEOUT defines timeout period in unit of O/S time tick. */ /*--- End of configuration options ---*/
4.使用文件系统
void StartDefaultTask(void *argument) { /* USER CODE BEGIN StartDefaultTask */ double time_t = 0; // ϵ TF if(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOD, GPIO_PIN_0)) { printf("SD plug in\r\n"); MX_SDMMC1_SD_Init(); FF_System_Creates(DRIVER_DISK, 1); FF_ViewRootDir(DRIVER_DISK); sd_inited = 1; } /* Infinite loop */ for(;;) { if(1 == sd_plugin) { sd_plugin = 0; osDelay(1000); MX_SDMMC1_SD_Init(); FF_System_Creates(DRIVER_DISK, 1); FF_ViewRootDir(DRIVER_DISK); sd_inited = 1; } else if(2 == sd_plugin) { sd_plugin = 0; FF_System_Uncreates(DRIVER_DISK); HAL_SD_DeInit(&hsd1); sd_inited = 0; } if(sd_inited && !(strncmp((char*)&usart6.rx_buf[0],MENU,strlen(MENU)))) { usart6.rx_rear = 0; memset(usart6.rx_buf,0,BUFF_SIZE); printf("\r\nDrive letter:\t%s\r\n",DRIVER_DISK); FF_ViewRootDir(DRIVER_DISK); printf("CMD List\r\n"); printf("Exit:\t"MENU); printf("Clear File:\t"CLEAR_FILE); printf("Clear Folder:\t"CLEAR_DIR); vTaskSuspend((TaskHandle_t)recTaskHandle); // recTaskHandle while(1) { if(!(strncmp((char*)&usart6.rx_buf[0],MENU,strlen(MENU)))) { usart6.rx_rear = 0; memset(usart6.rx_buf,0,BUFF_SIZE); printf("Exited MENU\r\n"); break; } else if(!(strncmp((char*)&usart6.rx_buf[0],CREATE_FILE,strlen(CREATE_FILE)))) { usart6.rx_rear = 0; memset(usart6.rx_buf,0,BUFF_SIZE); printf("Input Path:\r\n"); while(!usart6.rx_rear); FF_Delete((char*)usart6.rx_buf); FF_ViewRootDir(DRIVER_DISK); usart6.rx_rear = 0; } else if(!(strncmp((char*)&usart6.rx_buf[0],CREATE_DIR,strlen(CREATE_DIR)))) { usart6.rx_rear = 0; memset(usart6.rx_buf,0,BUFF_SIZE); printf("Input Folder Path:\r\n"); while(!usart6.rx_rear); FF_MKDir((char*)usart6.rx_buf); FF_ViewRootDir(DRIVER_DISK); usart6.rx_rear = 0; } else if(!(strncmp((char*)&usart6.rx_buf[0],CLEAR_FILE,strlen(CLEAR_FILE)))) { usart6.rx_rear = 0; memset(usart6.rx_buf,0,BUFF_SIZE); printf("Input Path:\r\n"); while(!usart6.rx_rear); FF_Delete((char*)usart6.rx_buf); FF_ViewRootDir(DRIVER_DISK); usart6.rx_rear = 0; } else if(!(strncmp((char*)&usart6.rx_buf[0],CLEAR_DIR,strlen(CLEAR_DIR)))) { usart6.rx_rear = 0; memset(usart6.rx_buf,0,BUFF_SIZE); printf("Input Folder Path:\r\n"); while(!usart6.rx_rear); FF_Dir_Del((char*)usart6.rx_buf); FF_ViewRootDir(DRIVER_DISK); usart6.rx_rear = 0; } else if(!(strncmp((char*)&usart6.rx_buf[0],AT_CMD,strlen(AT_CMD)))) { if(*(u32*)(usart6.rx_buf)<=0XFF) { while(READ_BIT(UART8->CR1,1U<<7) != 0); // ȴ ͨ 8 UART8->TDR=*(u32*)usart6.rx_buf; } else { UART8SendCmd(usart6.rx_buf, strlen((char*)(usart6.rx_buf))); } usart6.rx_rear = 0; memset(usart6.rx_buf,0,BUFF_SIZE); } } vTaskResume((TaskHandle_t)recTaskHandle); // ָ recTaskHandle } osDelay(1); } /* USER CODE END StartDefaultTask */ }
标签:INFO,res,user,NRF,FatFS,FF,移植,sd From: https://www.cnblogs.com/boring-luobo/p/17935197.html