FAT文件系统移植-基于STM32F103

一.介绍
FAT文件系统分为三层,如下图所示。

FAT文件系统移植-基于STM32F103_第1张图片
1.底层接口,包括存储媒介读/写接口(disk I/O)和供给文件创建修改时间的实时时钟,需要我们根据平台和存储介质编写移植代码。
2.中间层FATFS模块,实现了FAT 文件读/写协议。FATFS模块提供的是ff.c和ff.h。除非有必要,使用者一般不用修改,使用时将头文件直接包含进去即可。
3.最顶层是应用层,使用者无需理会FATFS的内部结构和复杂的FAT 协议,只需要调用FATFS模块提供给用户的一系列应用接口函数,如f_open,f_read,f_write 和f_close等,就可以像在PC 上读/写文件那样简单。
二、移植
1.从官网下载合适的版本的软件(http://elm-chan.org/fsw/ff/00index_e.html),本次使用FatFs R0.13b
2.把代码合并到工程中,放到一个新建文件夹下。
FAT文件系统移植-基于STM32F103_第2张图片

3.我们需要为diskio. c文件下填充下列六个函数的操作代码
disk_status-获取设备状态
disk_initialize-初始化设备
disk_read-读取数据
disk_write-写入数据
disk_ioctl-控制设备相关的功能
get_fattime-获取当前时间
(1)本次使SPI FLASH 为MX25L6406E,先添加其驱动调用的头文件。
修改以下代码,根据使用Flash数据手册修改

#define DEV_SPIFLASH		0	/* Example: Map SPI Flash to physical drive 0 */

#define FLASH_SECTOR_SIZE 	(4*1024)   //扇区大小
#define FLASH_BLOCK_SIZE	16                //一个块有多少扇区
const unsigned short int FLASH_SECTOR_COUNT = 640; //2.5M,一个使用多少扇区用于FAT文件系统

(2)状态函数

DSTATUS disk_status (
	BYTE pdrv		/* Physical drive nmuber to identify the drive */
)
{
	DSTATUS stat;
	int result;

	switch (pdrv) {
        case DEV_SPIFLASH:return RES_OK;
	}
	return STA_NOINIT;
}

(3)初始化函数

DSTATUS disk_initialize (
	BYTE pdrv				/* Physical drive nmuber to identify the drive */
)
{
	DSTATUS stat;
	int result;

	switch (pdrv) {
	case DEV_SPIFLASH :
     MX25LXXHal_PinInit();//引脚初设化
     MX25LXXHal_SpiInit();//芯片初设化
		return RES_OK;
	}
	return STA_NOINIT;
}

(4)读函数

/*-----------------------------------------------------------------------*/
/* 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;
	int result;
    int i = 0;
    
	switch (pdrv) {
	case DEV_SPIFLASH :
		for(i = 0; i < count;i++)
		{
			MX25L1602_RD(sector*FLASH_SECTOR_SIZE,FLASH_SECTOR_SIZE,buff);
			sector++;
			buff+=FLASH_SECTOR_SIZE;
		}
		return RES_OK;
	}

	return RES_PARERR;
}

(5)写函数

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;
	int result;
    unsigned int s;
	switch (pdrv) {
	case DEV_SPIFLASH :
        for(s = sector;s <= sector+count-1;s++)
		{ 
            MX25L1602_Erase(s, s); // 先檫除扇区,再写入数据
        }
        //MX25L1602_Erase(sector, sector+count-1);
		for(;count>0;count--)
		{            
			MX25L1602_WR(sector*FLASH_SECTOR_SIZE, (u8*)buff,FLASH_SECTOR_SIZE);
			sector++;
			buff+=FLASH_SECTOR_SIZE;
		}
		return RES_OK;
	}

	return RES_PARERR;
}

(6)磁盘控制函数

DRESULT disk_ioctl (
	BYTE pdrv,		/* Physical drive nmuber (0..) */
	BYTE cmd,		/* Control code */
	void *buff		/* Buffer to send/receive control data */
)
{
	DRESULT res;
	int result;

	switch (pdrv) {
	case DEV_SPIFLASH :
	    switch(cmd)
	    {
		    case CTRL_SYNC:
				res = RES_OK; 
		        break;	 
		    case GET_SECTOR_SIZE:
		        *(WORD*)buff = FLASH_SECTOR_SIZE;
		        res = RES_OK;
		        break;	 
		    case GET_BLOCK_SIZE:
		        *(WORD*)buff = FLASH_BLOCK_SIZE;
		        res = RES_OK;
		        break;	 
		    case GET_SECTOR_COUNT:
		        *(DWORD*)buff = FLASH_SECTOR_COUNT;
		        res = RES_OK;
		        break;
		    default:
		        res = RES_PARERR;
		        break;
	    }
    }


	return res;
}

4.应用层的调用
挂载文件系统后即可调用文件操作函数,写函数最好在开辟个缓存,累计到一个扇区大小的数据再存入文件系统,这样可以做好负载均衡,避免flash使用寿命缩短。

/**
 * 文件系统挂载函数
 */
int fatfs_fileSystemReset()
{
    FRESULT res = 0;
    
    res = 1;
    if(res != 0)
    {   printf("mount fail\n");
        res = f_mkfs("0:", FM_FAT, 0, gFsWork, sizeof gFsWork);//在逻辑驱动器上创建FAT卷
        if(res == 0)
        {   printf("mkfs sus\n");
            res = f_mount (&sysFs,"0:",1);//先挂载才能使用
            if(res == 0)
            {   printf("mount susu2\n");
                gFsInited = 1;
                return 0;
            }
            else {
                 printf("mount fail2\n");
                return -1;   }
        }
        else  {   printf("mkfs fail\n");
            return -1;  }
    }
    else
        gFsInited = 1;
    return 0;
}

5.总结
FAT文件比较小巧,适合在相对资源没有那么丰富的芯片上使用,相对于直接对FLASH操作,使用文件系统大大简化编程的难度,操作起来更加方便。

你可能感兴趣的:(STM32)