FAT文件系统之----在VS上的移植

目    的: 移直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          */
            ;
}

你可能感兴趣的:(存储器及文件管理)