目 的: 移直FAT文件系统
本 文:编写底层接口函数 及FAT测试代码
移植版本:R0.09
参 考:FatFs使用说明—基于SmartARMCortexM3-1700.pdf
编 者:张永辉 2013年1月16日
//****************************************************************************************
1 新建win控制台工程,使用空项目,工程取名fat009。
2 下载官网 R0.09源码。
3 将源码src的所有内容复制到工程下,新建文件夹FAT中
4 添加如下代码到工程,即如下结构:
bsp\
bspeeprom.h *(windows模拟储存器1--EEPROM)
bspeeprom.c *
FAT\
ffconf.h *FatFs 模块配置文件
ff.h FatFs 和应用模块公用的包含文件
ff.c FatFs 模块
diskio.h FatFs and disk I/O 模块公用的包含文件
diskio.c *
integer.h *数据类型定义
option\ 可选的外部功能
main\
main.c *
5 修改integer.h,定义数据类型
6 修改配置文件ffconf.h
7 编写diskio.c函数
//****************************************************************************************
需要的文件:
main.c
bspeeprom.h (见windows模拟储存器1--EEPROM)
bspeeprom.c (见windows模拟储存器1--EEPROM)
ffconf.h
integer.h
diskio.c
/*****************************************************************************************
文 件:main.c
/****************************************************************************************/
#include "ff.h"
#include "integer.h"
#include "bspeeprom.h"
/*****************************************************************************************
函数功能:写文件
入口参数:fileName:要写入的文件名或要创建的文件名
buffer: 要写入的数据存放数据
出口参数:0:成功 1:失败
/****************************************************************************************/
FRESULT FileWrite(const TCHAR *fileName,const uint8 *buffer)
{
FATFS fs; //文件系统
FIL file; //文件
UINT bw; //数据字节数
f_mount(0, &fs); //挂载文件系统
//给文件中写入数据,如果没有该文件,创建一个名为*fileName的文件,并写入数据
if(f_open(&file, fileName, FA_CREATE_ALWAYS|FA_WRITE))
{
return FR_NO_FILE;
}else
{
do
{
if(f_write(&file, buffer, 512, &bw))
{
return FR_NO_FILE;
}
} while (bw < 512); //判断是否读完(bw = 512,表示写入完成)
f_close(&file); //关闭文件,必须和f_open函数成对出现
}
f_mount(0, 0); //卸载文件系统
return FR_OK;
}
/*****************************************************************************************
函数功能:读文件
入口参数:fileName:要读取的文件名
buf: 要读取的数据存放数组
出口参数:0:成功 1:失败
*****************************************************************************************/
FRESULT FileRead(const TCHAR *fileName, uint8 *buf)
{
FATFS fs; //建立一个文件系统
FIL file; //暂存文件
UINT br; //字节计数器
FRESULT res; //存储函数执行结果
f_mount(0,&fs); //加载文件系统
res = f_open(&file, fileName, FA_OPEN_EXISTING|FA_READ); // 打开文件
if(res != FR_OK) //如果没有正确打开文件
{
return res; //返回错误报告
}else //如果打开了文件
{
do
{ // 读取文件内容,每次512个字节
f_read(&file, buf, 512, &br);
}while(br); //br = 0 表示读完了数据
}
f_close(&file); //关闭文件,必须和f_open函数成对出现
f_mount(0,0); //卸载文件系统
return FR_OK;
}
//****************************************************************************************
int main(void)
{
char *a = "abcdefghijklmnopqrstuvxyz";
char b[200];
FATFS fs; //文件系统
//为了格式化系统。格式化一次后就不需要再次格式化了
f_mount(0,&fs);
f_mkfs (0,0,0);
f_mount(0,0);
FileWrite("0:123.txt",a);
FileRead("0:123.txt",b);
}
/*****************************************************************************************
fat文件系统配置函数
文 件:ffconf.h
FatFs - FAT file system module configuration file R0.09 (C)ChaN, 2011
*****************************************************************************************/
#ifndef _FFCONF
//****************************************************************************************
#define _FFCONF 6502 //Revision ID
// Functions and Buffer Configurations
#define _FS_TINY 0 //==0:Normal 或==1:Tiny
//Tiny模式占用内存更小,每个文件占512字节。
//定义为1时,不能使用如下函数
//f_write, f_sync, f_unlink, f_mkdir, f_chmod, f_rename,f_truncate and useless f_getfree
#define _FS_READONLY 0 //0:Read/Write or 1:Read only
#define _FS_MINIMIZE 0 //0 to 3
// The _FS_MINIMIZE option defines minimization level to remove some functions.
// 0: Full function.
// 1: f_stat, f_getfree, f_unlink, f_mkdir, f_chmod, f_truncate and f_rename
// are removed.
// 2: f_opendir and f_readdir are removed in addition to 1.
// 3: f_lseek is removed in addition to 2.
//使能字符串功能
#define _USE_STRFUNC 0 //0:Disable or 1-2:Enable
#define _USE_MKFS 1 //0:Disable or 1:Enable
// To enable f_mkfs function, set _USE_MKFS to 1 and set _FS_READONLY to 0
#define _USE_FORWARD 0 //0:Disable or 1:Enable
// To enable f_forward function, set _USE_FORWARD to 1 and set _FS_TINY to 1.
#define _USE_FASTSEEK 0 //0:Disable or 1:Enable
// To enable fast seek feature, set _USE_FASTSEEK to 1.
//使用语言 简体中文 代码会增加160K左右
#define _CODE_PAGE 1
// Incorrect setting of the code page can cause a file open failure.
// 936 - Simplified Chinese GBK (DBCS, OEM, Windows)
// 950 - Traditional Chinese Big5 (DBCS, OEM, Windows)
// 1 - ASCII only (Valid for non LFN cfg.)
#define _USE_LFN 0 //==0\1\2\3
#define _MAX_LFN 64 //Maximum LFN length to handle (12 to 255)
// The _USE_LFN option switches the LFN support.
// 0: Disable LFN feature. _MAX_LFN and _LFN_UNICODE have no effect.
// 1: Enable LFN with static working buffer on the BSS. Always NOT reentrant.
// 2: Enable LFN with dynamic working buffer on the STACK. 栈为工作区
// 3: Enable LFN with dynamic working buffer on the HEAP.
#define _LFN_UNICODE 0 //0:ANSI/OEM or 1:Unicode
#define _FS_RPATH 0 //0 to 2
//****************************************************************************************
// Physical Drive Configurations
#define _VOLUMES 1 //支持的逻辑卷数目 最大10个
#define _MAX_SS 512 //定义扇区大小,支持512, 1024, 2048 或 4096
//定义是否支持重入,使用 uCOS-II 时需要定义
#define _MULTI_PARTITION 0 //0:Single partition, 1/2:Enable multiple partition
//==0 each volume is bound to the same physical drive number and it can mount only first primaly partition.
//==1 When it is set to 1, each volume is tied to the partitions listed in VolToPart[]
#define _USE_ERASE 0 //0:Disable or 1:Enable
// To enable sector erase feature, set _USE_ERASE to 1. CTRL_ERASE_SECTOR command
// should be added to the disk_ioctl functio.
//****************************************************************************************
// System Configurations
#define _WORD_ACCESS 0 //0 or 1
#define _FS_REENTRANT 0 //0:Disable or 1:Enable
#define _FS_TIMEOUT 1000 //定义超时周期,使用uCOS-II时需要定义
//定义 sync object.的类型,使用 uCOS-II 时需要定义
#define _SYNC_t HANDLE //O/S dependent type of sync object. e.g. HANDLE, OS_EVENT*, ID and etc..
#define _FS_SHARE 0 //0:Disable or >=1:Enable
// To enable file shareing feature, set _FS_SHARE to 1 or greater. The value
// defines how many files can be opened simultaneously.
//****************************************************************************************
#endif
/*****************************************************************************************
数据类型定义
文 件:integer.h
以下定义为在嵌入式平台而修改
*****************************************************************************************/
#ifndef _INTEGER
#define _INTEGER
//必须16位或更大
typedef int INT;
typedef unsigned int UINT;
//必须8位
typedef char CHAR;
typedef unsigned char UCHAR;
typedef unsigned char BYTE;
//必须16位
typedef short SHORT;
typedef unsigned short USHORT;
typedef unsigned short WORD;
typedef unsigned short WCHAR;
//必须32位
typedef int LONG;
typedef unsigned int ULONG;
typedef unsigned int DWORD;
//其他地方需要的定义
typedef unsigned char INT8U;
typedef unsigned char uint8;
//****************************************************************************************
#endif
/*****************************************************************************************
文 件:diskio.h
*****************************************************************************************/
#include "ffconf.h"
#include "integer.h"
#include "diskio.h"
#include "bspeeprom.h"
DSTATUS Drv0Stat = STA_NOINIT; //磁盘状态
/*****************************************************************************************
功能: 函数初始化一个逻辑驱 动器为 读/ 写做 准备
入参:Drive指定要初始化的逻辑驱动器号,即盘符,应当取值 0~9
出参:函数返回一个磁盘状态作为结果
注意:应用程序不应调用此函数。如果需要重新初始化文件系统,可使用 f_mount 函数
*/
DSTATUS disk_initialize(BYTE Drive)
{
Drv0Stat |= STA_NOINIT;
switch (Drive)
{
//仅使用了盘符0 模拟EE
case 0 :
BspEePromInit(); //此函数,不能每次都清除EE的内容,否则会报文件系统不存在(经验)
Drv0Stat = 0; //成功
return Drv0Stat;
default:
return STA_NOINIT; //失败
}
return STA_NOINIT;
}
/*****************************************************************************************
功能:返回当前磁盘驱动器的状态
入参:Drive:指定要确认的逻辑驱动器号,即盘符,应当取值 0~9
出参:(磁盘状态返回下列标志的组合 FatFs只使用STA_NOINIT和STA_PROTECTED)
STA_NOINIT: 表明磁盘驱动未初始化,可能的 原因如下:
置位:系统复位,磁盘被移除和磁盘初始化函数失败;
清零:磁盘初始化函数成功
STA_NODISK: 表明驱动器中没有设备。
STA_PROTECTED: 表明设备被写保护。
*/
DSTATUS disk_status(BYTE Drive)
{
switch (Drive)
{
case 0 :
return Drv0Stat;
default:
return STA_NODISK; //失败
}
return STA_NOINIT;
}
/*****************************************************************************************
功能:从磁盘驱动器上读取扇区
入参: Drive: 指定逻辑驱动器号,即盘符,应当取值 0~9
Buffer: 指向存储读取数据字节数组的指针
SectorNumber: 指定起始扇区的逻辑块(LBA)上的地址
SectorCount: 指定要读取的扇区数,取值 1~128
出参: RES_OK(0): 函数成功
RES_ERROR: 读操作期间产生了任何错误且不能恢复它
RES_PARERR: 非法参数
RES_NOTRDY: 磁盘驱动器没有初始化
*/
DRESULT disk_read(BYTE Drive, BYTE* Buffer, DWORD SectorNumber, BYTE SectorCount)
{
INT8U ucRet;
if (Drv0Stat & STA_NOINIT)
{
return RES_NOTRDY;
} else if (!SectorCount)
{
return RES_PARERR;
}
switch(Drive)
{
case 0 :
ucRet = BspEePromSectorReads(Buffer,SectorNumber,SectorCount);
if (ucRet != 0x00)
{
return RES_ERROR;
} else
{
return RES_OK;
}
default:
return RES_PARERR;
}
return RES_PARERR;
}
/*****************************************************************************************
功能:向磁盘写入一个或多个扇区
入参:
Drive: 指定逻辑驱动器号,即盘符,应当取值 0~9
Buffer: 指向要写入字节数组的指针,
SectorNumber: 指定起始扇区的逻辑块(LBA)上的地址
SectorNumber: 指定要写入的扇区数,取值 1~128
出参:
RES_OK(0): 函数成功
RES_ERROR: 读操作期间产生了任何错误且不能恢复它
RES_WRPRT: 媒体被写保护
RES_PARERR: 非法参数
RES_NOTRDY: 磁盘驱动器没有初始化
注: FatFs 指定的内存地址并不总是字对齐的,如果硬件不支持不对齐的数据传输,函数里需要进行处理
*/
#if _READONLY == 0
DRESULT disk_write(BYTE Drive, const BYTE* Buffer, DWORD SectorNumber, BYTE SectorCount)
{
INT8U ucRet;
if (Drv0Stat & STA_NOINIT)
{
return RES_NOTRDY;
} else if (!SectorCount)
{
return RES_PARERR;
}
switch (Drive)
{
case 0 :
ucRet = BspEePromSectorWrites((BYTE*)Buffer,SectorNumber,SectorCount);
if (ucRet != 0x00)
{
return RES_ERROR;
}else
{
return RES_OK;
}
}
return RES_PARERR;
}
#endif
/*****************************************************************************************
功能:控制设备指定特性和除了读/写外的杂项功能
入参:
Drive: 指定逻辑驱动器号,即盘符,应当取值 0~9
Command: 指定命令代码
CTRL_SYNC: 确保磁盘驱动器已经完成了写处理,有一个写回缓存,立即刷新原扇区,只读配置下不适用此命令
GET_SECTOR_SIZE: 返回磁盘的扇区大小,只用于 f_mkfs()
GET_SECTOR_COUNT: 返回可利用的扇区数, _MAX_SS >= 1024 时可用
GET_BLOCK_SIZE: 获取擦除块大小,只用于 f_mkfs()
CTRL_ERASE_SECTOR: 强制擦除一块的扇区,_USE_ERASE >0 时可用
Buffer: 指向参数缓冲区的指针,取决于命令代码,不使用时,指定一个 NULL 指针
出参:
RES_OK(0): 函数成功
RES_ERROR: 读操作期间产生了任何错误且不能恢复它
RES_PARERR:非法参数
RES_NOTRDY:磁盘驱动器没有初始化
*/
DRESULT disk_ioctl(BYTE Drive, BYTE Command, void* Buffer)
{
if (Drv0Stat & STA_NOINIT)
{
return RES_NOTRDY;
}
switch (Drive)
{
case 0:
break;
default:
return RES_PARERR;
}
switch (Command)
{
case CTRL_SYNC:
return RES_OK;
case GET_SECTOR_SIZE: //扇区大小
*(DWORD*)Buffer = BspEePromSectorSizeGet();
return RES_OK;
case GET_SECTOR_COUNT: //扇区数
*(DWORD*)Buffer = BspEePromSectorConutGet();
return RES_OK;
case GET_BLOCK_SIZE: //块大小 要大于128
*(DWORD*)Buffer = BspEePromPageSizeGet();
return RES_OK;
case CTRL_ERASE_SECTOR: //扇区擦除
return RES_OK;
default:
return RES_PARERR;
}
return RES_PARERR;
}
/*****************************************************************************************
功能:函数必须返回一个合法的时间即使系统不支持实时时钟,
注 :如果返回 0,文件没有一个合法的时间,只读配置下无需此函数。
*/
DWORD get_fattime(void)
{
return ((2010UL-1980) << 25) /* Year = 2010 */
| (11UL << 21) /* Month = 11 */
| (2UL << 16) /* Day = 2 */
| (15U << 11) /* Hour = 15 */
| (0U << 5) /* Min = 0 */
| (0U >> 1) /* Sec = 0 */
;
}