fatfs移植和使用(在W25Q16上建立文件系统)

准备再单片机CH579上移植FATFS1.3方便数据管理,下面简单介绍一下移植注意事项和误区。

需要准备的材料有:

(1)FATFS文件系统源码FATFS1.3(点此下载最新FATFS源码)。

(2)单片机平台一个(CH579)。

(3)SPI_FLASH芯片一个(如:W25Q16)。

FATFS是一个通用的嵌入式文件系统,对不同的平台支持很好,大到硬盘、U盘、存储卡,小到spi_flash芯片甚至单片机内部FLASH都可以使用FATFS。今天我们就在一个2M大小的SPI_FLASH( W25Q16)上建立一个文件系统,主控制器是CH579单片机。在做文件系统移植前,你需要把操作SPI_FLASH的驱动调通,能读写SPI_FLASH就可以了。

第一步、 解压缩新下载的FATFS源码,看看里面都是些什么文件。如下图所示,红色框是移植FATFS所必须的文件,蓝色框内的文件是可选的移植文件。

diskio.c个diskio.h是和存储器读写控制相关的驱动接口,比如SPI_FLASH的读写函数接口,都要映射到这里面。必须的文件 

ff.h和ff.h是FATFS的核心文件,必须的文件

ffconf.h是FATFS的配置文件,用来裁剪FATFS,必须的文件

integer.h是FATFS所用到的数据类型定义,用以兼容不同字长CPU,必须的文件

ffsystem.c是一些关于在带操作系统平台中,使用的示例,可选文件

ffunicode.c是万国码编码文件,文件里主要是大数组定义,假如你需要让文件名支持中文就需要这个文件,这个文件会使代码空间急剧变大,可选文件

第二步、 本次FATFS移植未使用操作系统,文件系统支持中文路径和名称,所以需要ff.c、ff.h、ffconf.h、diskio.c、diskio.h、ffunicode.c和integer.h这六个文件添加到工程中即可。如下图:

fatfs移植和使用(在W25Q16上建立文件系统)_第1张图片

 

第三步 修改ffconf.h文件,来裁剪我们的FATFS,通过宏开关来去掉不用的功能,来精简文件系统。想知道每个宏的功能?(点击这里)

需要注意的是:由于我们此次移植支持了中文路径和名称,所以这个要设置这个宏    #define FF_CODE_PAGE936 /*936代表 简体中文*/

特别注意:下图的修改,FF_MAX_SS的值必须和FLASH的块的值一直,我在这里走了歪路,搞了半天,它默认的是512,网上其它文档没有提示这里的修改。

fatfs移植和使用(在W25Q16上建立文件系统)_第2张图片

第四步 修改diskio.c 来映射我们的存储器读写控制接口,如下:

/*-----------------------------------------------------------------------*/
/* Low level disk I/O module skeleton for FatFs     (C)ChaN, 2016        */
/*-----------------------------------------------------------------------*/
/* 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 "SPIFlash.H"

/* Definitions of physical drive number for each drive */
#define SPI_FLASH        0    /* Example: Map Ramdisk to physical drive 0 */
 
/*-----------------------------------------------------------------------*/
/* Get Drive Status                                                      */
/*-----------------------------------------------------------------------*/
 
DSTATUS disk_status (
    BYTE pdrv        /* Physical drive nmuber to identify the drive */
)
{

    if(pdrv == SPI_FLASH) 
    {
        PRINT("!!!disk_status OK\r\n");
        return RES_OK; //Ö±½Ó·µ»ØOK¼´¿É
    }
    else
    {
    PRINT("!!!disk_status ERR\r\n");

        return RES_PARERR;
    }
}
 
 
 
/*-----------------------------------------------------------------------*/
/* Inidialize a Drive                                                    */
/*-----------------------------------------------------------------------*/
 
DSTATUS disk_initialize (
    BYTE pdrv                /* Physical drive nmuber to identify the drive */
)
{
    if(pdrv == SPI_FLASH) 
    {
        SPIFlash_Init();//³õʼ»¯spi flash
        PRINT("!!!disk_initialize OK\r\n");
        return RES_OK;
    }
    else
    {
        PRINT("!!!disk_initialize ERR\r\n");

        return RES_PARERR;
    }
}
 
 
 
/*-----------------------------------------------------------------------*/
/* Read Sector(s)                                                        */
/*-----------------------------------------------------------------------*/
 
DRESULT disk_read (
    BYTE pdrv,        /* Physical drive nmuber to identify the drive */
    BYTE *buff,        /* Data buffer to store read data */
    DWORD sector,    /* Start sector in LBA */
    UINT count        /* Number of sectors to read */
)
{
    DRESULT res;
    PRINT("disk_read---sector:%d,count:%d\r\n",sector,count);
    if(pdrv == SPI_FLASH) 
    {
        for(;count>0;count--)
        {
            
        ReadExternalFlash_SPI_DAN(sector*4096,4096,buff);//spi flashµÄ¶Áº¯Êý£¬×¢Òâ²ÎÊýÀàÐÍÒ»ÖÂ
            sector++;
            buff+=4096;
        }
        
        res = RES_OK; //ĬÈÏдÈëÕý³££¬¿ÉÒÔ¼Ó
    
        return res;
    }
    else
    {
        
        return RES_PARERR;
    }
}
 
 
 
/*-----------------------------------------------------------------------*/
/* Write Sector(s)                                                       */
/*-----------------------------------------------------------------------*/
 
DRESULT disk_write (
    BYTE pdrv,            /* Physical drive nmuber to identify the drive */
    const BYTE *buff,    /* Data to be written */
    DWORD sector,        /* Start sector in LBA */
    UINT count            /* Number of sectors to write */
)
{
    DRESULT res;
 PRINT("disk_write---sector:%d,count:%d\r\n",sector,count);
    if(pdrv == SPI_FLASH) 
    {
            for(;count>0;count--)
        {
            EraseExternal4KFlash_SPI(sector*4096);
         BlukWriteExternalFlash_SPI(sector*4096,4096,(uint8_t *)buff);//spi flashµÄдº¯Êý£¬×¢Òâ²ÎÊýÀàÐÍÒ»ÖÂ
        sector++;
            buff+=4096;
            
        }
         res=RES_OK;
        return res;
    }
    else
    {
    
        PRINT("!!!disk_write ERR\r\n");
        return RES_PARERR;
    }
}
 
 
 
/*-----------------------------------------------------------------------*/
/* Miscellaneous Functions                                               */
/*-----------------------------------------------------------------------*/
 
DRESULT disk_ioctl (
    BYTE pdrv,        /* Physical drive nmuber (0..) */
    BYTE cmd,        /* Control code */
    void *buff        /* Buffer to send/receive control data */
)
{
    if (pdrv == SPI_FLASH)
    {
        switch (cmd) 
        {
         case CTRL_SYNC:
             return RES_OK;
 
         /* ÉÈÇøÊýÁ¿ 1024*1024*1024 =4 (MB) */
 
         case GET_SECTOR_COUNT:
          *(DWORD * )buff = 512;////spi flashµÄ¿é´óСÊÇ4K Bytes
    //         *(DWORD * )buff = 8*1024;//W25Q16 ÓÐ512´óСΪ4k bytesµÄÉÈÇø
             return RES_OK;
 
         /* ÉÈÇø´óС*/
 
         case GET_SECTOR_SIZE :
     *(WORD * )buff = 4096;//spi flashµÄ¿é´óСÊÇ4K Bytes
            // *(WORD * )buff = 512;//spi flashµÄ¿é´óСÊÇ4K Bytes
             return RES_OK;
 
         /*¿é */
 
         case GET_BLOCK_SIZE :
              *(DWORD * )buff =1;
             return RES_OK;
             
         default:
              return RES_PARERR;
         }
    }
    else
    {
        
        PRINT("!!!disk_ioctl ERR\r\n");
        return RES_PARERR;
    }
}
DWORD get_fattime(void) {
//    DWORD time; 
    return 0;
}

 

这里面一定注意,FLASH读写函数驱动的调用。很关键,决定是否能移植成功。

你可能感兴趣的:(fatfs移植和使用(在W25Q16上建立文件系统))