http://elm-chan.org/fsw/ff/00index_e.html
只需要下面6个文件即可,介绍如下
diskio.c/h
:存储介质操作文件,说移植也就是porting这个文件
ff.c/h
:FatFs源码,不用动
ffconfig.h
:FatFs配置文件,可以根据需求进行裁剪
integer.h
:基本数据类型接口文件
修改diskio.c
下面以在flash上支持FatFs为例,主要是编写diskio.c
,diskio.c
有如下几个函数,最后一个是获得文件时间戳,也可以不用移植
下面这个例子还预留了SD卡,FatFs支持多个存储介质,如下FLASH在1号介质,SD卡在0号介质
#include "diskio.h" /* FatFs lower layer API */
#include "ff.h"
#include "./flash/bsp_spi_flash.h"
/* 为每个设备定义一个物理编号 */
#define ATA 0 // 预留SD卡使用
#define SPI_FLASH 1 // 外部SPI Flash
/*-----------------------------------------------------------------------*/
/* 获取设备状态 */
/*-----------------------------------------------------------------------*/
DSTATUS disk_status (
BYTE pdrv /* 物理编号 */
)
{
DSTATUS status = STA_NOINIT;
switch (pdrv) {
case ATA: /* SD CARD */
break;
case SPI_FLASH:
/* SPI Flash状态检测:读取SPI Flash 设备ID */
if(sFLASH_ID == SPI_FLASH_ReadID())
{
/* 设备ID读取结果正确 */
status &= ~STA_NOINIT;
}
else
{
/* 设备ID读取结果错误 */
status = STA_NOINIT;;
}
break;
default:
status = STA_NOINIT;
}
return status;
}
/*-----------------------------------------------------------------------*/
/* 设备初始化 */
/*-----------------------------------------------------------------------*/
DSTATUS disk_initialize (
BYTE pdrv /* 物理编号 */
)
{
uint16_t i;
DSTATUS status = STA_NOINIT;
switch (pdrv) {
case ATA: /* SD CARD */
break;
case SPI_FLASH: /* SPI Flash */
/* 初始化SPI Flash */
SPI_FLASH_Init();
/* 延时一小段时间 */
i=500;
while(--i);
/* 唤醒SPI Flash */
SPI_Flash_WAKEUP();
/* 获取SPI Flash芯片状态 */
status=disk_status(SPI_FLASH);
break;
default:
status = STA_NOINIT;
}
return status;
}
/*-----------------------------------------------------------------------*/
/* 读扇区:读取扇区内容到指定存储区 */
/*-----------------------------------------------------------------------*/
DRESULT disk_read (
BYTE pdrv, /* 设备物理编号(0..) */
BYTE *buff, /* 数据缓存区 */
DWORD sector, /* 扇区首地址 */
UINT count /* 扇区个数(1..128) */
)
{
DRESULT status = RES_PARERR;
switch (pdrv) {
case ATA: /* SD CARD */
break;
case SPI_FLASH:
/* 扇区偏移2MB,外部Flash文件系统空间放在SPI Flash后面6MB空间 */
sector+=512;
SPI_FLASH_BufferRead(buff, sector <<12, count<<12);
status = RES_OK;
break;
default:
status = RES_PARERR;
}
return status;
}
/*-----------------------------------------------------------------------*/
/* 写扇区:见数据写入指定扇区空间上 */
/*-----------------------------------------------------------------------*/
#if _USE_WRITE
DRESULT disk_write (
BYTE pdrv, /* 设备物理编号(0..) */
const BYTE *buff, /* 欲写入数据的缓存区 */
DWORD sector, /* 扇区首地址 */
UINT count /* 扇区个数(1..128) */
)
{
uint32_t write_addr;
DRESULT status = RES_PARERR;
if (!count) {
return RES_PARERR; /* Check parameter */
}
switch (pdrv) {
case ATA: /* SD CARD */
break;
case SPI_FLASH:
/* 扇区偏移2MB,外部Flash文件系统空间放在SPI Flash后面6MB空间 */
sector+=512;
write_addr = sector<<12;
SPI_FLASH_SectorErase(write_addr);
SPI_FLASH_BufferWrite((u8 *)buff,write_addr,count<<12);
status = RES_OK;
break;
default:
status = RES_PARERR;
}
return status;
}
#endif
/*-----------------------------------------------------------------------*/
/* 其他控制 */
/*-----------------------------------------------------------------------*/
#if _USE_IOCTL
DRESULT disk_ioctl (
BYTE pdrv, /* 物理编号 */
BYTE cmd, /* 控制指令 */
void *buff /* 写入或者读取数据地址指针 */
)
{
DRESULT status = RES_PARERR;
switch (pdrv) {
case ATA: /* SD CARD */
break;
case SPI_FLASH:
switch (cmd) {
/* 扇区数量:1536*4096/1024/1024=6(MB) */
case GET_SECTOR_COUNT:
*(DWORD * )buff = 1536;
break;
/* 扇区大小 */
case GET_SECTOR_SIZE :
*(WORD * )buff = 4096;
break;
/* 同时擦除扇区个数 */
case GET_BLOCK_SIZE :
*(DWORD * )buff = 1;
break;
}
status = RES_OK;
break;
default:
status = RES_PARERR;
}
return status;
}
#endif
__weak DWORD get_fattime(void) {
/* 返回当前时间戳 */
return ((DWORD)(2015 - 1980) << 25) /* Year 2015 */
| ((DWORD)1 << 21) /* Month 1 */
| ((DWORD)1 << 16) /* Mday 1 */
| ((DWORD)0 << 11) /* Hour 0 */
| ((DWORD)0 << 5) /* Min 0 */
| ((DWORD)0 >> 1); /* Sec 0 */
}
修改ffconf.c
1.flash 最小擦写单位是4096字节,所以要改如下宏
#define _MIN_SS 512
#define _MAX_SS 4096
/* These options configure the range of sector size to be supported. (512, 1024,
/ 2048 or 4096) Always set both 512 for most systems, all type of memory cards and
/ harddisk. But a larger value may be required for on-board flash memory and some
/ type of optical media. When _MAX_SS is larger than _MIN_SS, FatFs is configured
/ to variable sector size and GET_SECTOR_SIZE command must be implemented to the
/ disk_ioctl() function. */
2.如果有多个存储介质(比如要支持SD卡和flash),如下宏为介质个数
#define _VOLUMES 2
/* Number of volumes (logical drives) to be used. */
3.为节省函数栈空间,可将下面宏改为1
#define _FS_TINY 1
/* This option switches tiny buffer configuration. (0:Normal or 1:Tiny)
/ At the tiny configuration, size of the file object (FIL) is reduced _MAX_SS
/ bytes. Instead of private sector buffer eliminated from the file object,
/ common sector buffer in the file system object (FATFS) is used for the file
/ data transfer. */
static FATFS sg_fatfs;
void app_fatfs_mount(void)
{
FRESULT res;
FIL fil;
BYTE work[FF_MAX_SS];
res = f_mount(&sg_fatfs, "1:", 1);
if(res == FR_NO_FILESYSTEM)
{
printf("FLASH还没有文件系统,即将进行格式化...\r\n");
/* 格式化 */
res = f_mkfs("1:", 0, work, sizeof(work));
/* 格式化后,先取消挂载 */
f_mount(NULL, "1:", 1);
/* 重新挂载 */
f_mount(&sg_fatfs, "1:", 1);
}
}
FRESULT app_fatfs_file_write(char *path, const uint8_t *data, uint32_t len)
{
FIL fil; /* File object */
FRESULT res; /* API result code */
UINT bw; /* Bytes written */
res = f_open(&fil, path, FA_CREATE_ALWAYS | FA_WRITE);
if(res == FR_OK)
{
res = f_write(&fil, data, len, &bw);
}
f_close(&fil);
return res;
}
FRESULT app_fatfs_file_read(char *path,uint32_t offset, uint8_t *data, uint32_t len)
{
FIL fil; /* File object */
FRESULT res; /* API result code */
UINT br; /* Bytes written */
res = f_open(&fil, path, FA_READ);
if(res == FR_OK)
{
if(offset>0 && offset<f_size(&fil))
{
res = f_lseek(&fil,offset);
if(res == FR_OK)
res = f_read(&fil, data, len, &br);
}
}
f_close(&fil);
return res;
}
FRESULT app_fatfs_file_size(char *path, uint32_t *size)
{
FIL fil; /* File object */
FRESULT res; /* API result code */
res = f_open(&fil, path, FA_READ);
if(res == FR_OK)
{
if(size != NULL)
*size = f_size(&fil);
}
f_close(&fil);
return res;
}
FRESULT app_fatfs_file_rm(char *path)
{
return f_unlink(path);
}
和C库文件系统操作类似