FatFs移植

文章目录

      • FatFs源码
      • 目录结构
      • 以flash为例
      • 使用例子

FatFs源码

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

目录结构

FatFs移植_第1张图片

只需要下面6个文件即可,介绍如下
diskio.c/h:存储介质操作文件,说移植也就是porting这个文件
ff.c/h:FatFs源码,不用动
ffconfig.h:FatFs配置文件,可以根据需求进行裁剪
integer.h:基本数据类型接口文件

以flash为例

修改diskio.c
下面以在flash上支持FatFs为例,主要是编写diskio.cdiskio.c有如下几个函数,最后一个是获得文件时间戳,也可以不用移植
FatFs移植_第2张图片
下面这个例子还预留了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库文件系统操作类似

你可能感兴趣的:(文件系统)