STM32F407-移植FATFS

STM32F407-移植FATFS

上一节操作完flash后,这一节给flash安装文件系统,通过文件系统方式访问flash;
这就需要移植嵌入式领域的文件系统FATFS;
FATFS是开源项目,可在其官网下载源码;
本案例使用的时V0.11

FATFS移植步骤

主要需要修改以下FATFS底层几个驱动接口,让其关联到flash;

1、disk_status()

检查当前设备是否准备就绪;返回值主要为修改此状态,STA_NOINIT;
准备就绪清掉 此状态STA_NOINIT;
没有准备就绪立此状态 STA_NOINIT;
pdrv值传入的设备编号;这里将FLASH定义为1;

#define DEV_SD 0
#define DEV_FLASH 1

DSTATUS disk_status (
	BYTE pdrv		/* Physical drive nmuber to identify the drive */
)
{
	DSTATUS stat = STA_NOINIT;
	
	switch(pdrv)
	{
		case DEV_SD:
		{
			break;
		}
		case DEV_FLASH:
		{
			if(My_Flash_Read_ID() == 0x17)
			{
				stat &= ~STA_NOINIT;
			}
			else
			{
				stat = STA_NOINIT;
			}
			
			break;
		}
		default:
			break;
	}

	return stat;
}

2、disk_initialize()

主要进行底层驱动初始化,本案例为调用 flash初始化

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


	switch(pdrv)
	{
		case DEV_SD:
		{
			break;
		}
		case DEV_FLASH:
		{
			My_Flash_Init();
			stat = disk_status(DEV_FLASH);
			break;
		}
		default:
			break;
	}
	return stat;
}

3、disk_read()

调用 FLASH读函数
这里会引入扇区sector的概念;本案例中将扇区大小配成 FLASH的扇区大小;4096
#define FLASH_SECTOR_SIZE 4096
count指有几个扇区sector

DRESULT disk_read (
	BYTE pdrv,		/* Physical drive nmuber to identify the drive */
	BYTE *buff,		/* Data buffer to store read data */
	DWORD sector,	/* Sector address in LBA */
	UINT count		/* Number of sectors to read */
)
{
	DRESULT res;

	switch(pdrv)
	{
		case DEV_SD:
		{
			break;
		}
		case DEV_FLASH:
		{
			My_FLASH_Read_Buff(sector * FLASH_SECTOR_SIZE,(void *)buff, count * FLASH_SECTOR_SIZE);
			res = RES_OK;
			break;
		}
		default:
			break;
	}

	return res;
}

4、disk_write()

调用FLASH读函数
注意点:
flash写入时需要先擦除;
所以要先调用擦除函数,再写;

DRESULT disk_write (
	BYTE pdrv,			/* Physical drive nmuber to identify the drive */
	const BYTE *buff,	/* Data to be written */
	DWORD sector,		/* Sector address in LBA */
	UINT count			/* Number of sectors to write */
)
{
	DRESULT res;


	switch(pdrv)
	{
		case DEV_SD:
		{
			break;
		}
		case DEV_FLASH:
		{
			while(count--)
			{
				//写入前先擦除
				My_FLASH_Erase_Sector(sector * FLASH_SECTOR_SIZE);
			
				//把要写入的扇区号转换成地址
				My_FLASH_Write_Buff(sector * FLASH_SECTOR_SIZE,(u8*)buff, FLASH_SECTOR_SIZE);
				
				sector++;
				buff += FLASH_SECTOR_SIZE;
			}
			res = RES_OK;
			break;
		}
		default:
			break;
	}

	return res;
}

5、disk_ioctl()

这里主要需要告诉FATFS扇区大小及个数

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


	switch(pdrv)
	{
		case DEV_SD:
		{
			break;
		}
		case DEV_FLASH:
		{
			switch(cmd)
			{
				//存储介质有多少个sector,文件系统通过该值获得存储介质的容量
				case GET_SECTOR_COUNT:
					*(DWORD *)buff = (16*1024*1024/FLASH_SECTOR_SIZE);//4096-1536
					res = RES_OK;
					break;
				
				//每个扇区的个数
				case GET_SECTOR_SIZE:
					*(DWORD  *)buff = FLASH_SECTOR_SIZE;
					res = RES_OK;
					break;

				
				//获取擦除的最小个数, 以sector为单位
				case GET_BLOCK_SIZE:
					*(DWORD  *)buff = 1;
					res = RES_OK;
					break;
				
				//写入同步在disk_write函数已经完成,这里默认返回ok
				case CTRL_SYNC:
					res = RES_OK;
					break;
				
				default:
					res = RES_PARERR;	
					break;			
			}
			
			break;
		}
		default:
			break;
	}

	return res;
}

6、get_fattime()

这个函数需要是FATFS获取文件时间;本例没有实现,直接返回了0;

其他配置

除了上述6个驱动函数需要实现外;以下几个地方也需要注意修改,均在ffconf.h中:

1、虚拟设备个数

本案例中用了两个设备;
0:SD (未实现)
1:FLASH (已实现)
所以这里设备个数配置为2 在这里插入图片描述

2、扇区空间大小

本案例中扇区大小定义为 4096;所以最大上限需要修改:
在这里插入图片描述

3、打开制作文件系统开关

FLASH之前没有被制作为文件系统,所以要首先制作为文件系统;需要打开该开关;否则无法调用相关函数;
在这里插入图片描述

FATFS功能调用

直接上代码

	printf("下边是FATFS实验\n");
   

   ret = f_mount(&fs,"1:",1);    //先挂载
   printf("f_mount is %d\n",ret);
   
   if(ret == FR_NO_FILESYSTEM)   //没有文件系统
   {
   	ret = f_mkfs("1:",0,0 );    //制作文件系统
   	printf("f_mkfs is %d\n",ret);
   	
   	f_mount(0, "1:", 1);
   	
   	ret = f_mount(&fs,"1:",1);
   	printf("f_mount is %d\n",ret);
   }

#if 1
   //写数据
   ret = f_open(&fil, "1:/t", FA_READ|FA_WRITE | FA_CREATE_ALWAYS);
   	
   printf("f_open is %d\n",ret);
   
   ret = f_write(&fil, mystrval, strlen(mystrval) +1, &bw);
   printf("f_write is %d, write number is %d\n",ret,bw);

   f_close(&fil);

   //读数据
   ret = f_open(&fil, "1:/t", FA_READ|FA_WRITE | FA_OPEN_EXISTING);
   printf("f_open is %d\n",ret);
   
   if(ret == 0)
   {
   	ret = f_read(&fil, data, sizeof(data), &bw);
   	printf("f_read is %d, read number is %d,value is %s\n",ret,bw,data);
   }
#endif	
   
   
   f_close(&fil);
   f_mount(0, "1:", 1);

需要注意的函数说明

1、f_mount函数说明

这个函数相当于挂载;将FLASH挂载到程序中;
传入的第一个参数为设备结构体;由于该结构体很大,最好定义为全局变量,防止出现栈溢出;
传入0,或者NULL,表示卸载
第二个参数:为设备号,FLASH设备号为1;另外冒号需要带上;"1:"
第三个参数:1:表示立即挂载;0:稍后挂载

2、f_mkfs函数说明

这个就是制作文件系统的函数;这里需要注意;首先要先挂载;制作完成后,需要卸载再挂载;
如果不挂载就直接调用该函数会报 FR_NOT_ENABLED的错误
参数1:设备号
参数2:文件格式 0:硬盘 1:软盘
参数3:扇区个数;0:FATFS自己计算

3、f_open、f_read 、f_write函数

这几个函数和标准文件操作函数类似,一般没啥问题;这里需要注意两个问题:
1)文件结构体尽量也要定义为全局;可能空间太大导致问题
2)如果f_open返回 FR_NO_FILE报错;在代码都正确的情况下;可能是底层驱动的几个函数,类型转换时出的问题;disk_ioctl、disk_write、disk_read这三个函数中可能存在数据类型转换导致的一些数据问题;

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值