一、把FatFs源码拷贝到工程目录,此此移植文件系统是基于之前SPI_FLASH的工程下进行。
源码地址:Petit FAT File System Module。
二、在keil打开工程文件,将源码添加到工程中。
三、添加FatFs源码的头文件。
四、尝试构建程序,解决错误。
主要错误为函数未定义却使用了。可以进行删除,或者实现即可。
五、实现FatFs底层驱动的接口。
a.disk_status 获取设备状态的接口。示例代码如下:
DSTATUS disk_status (
BYTE pdrv /* Physical drive nmuber to identify the drive */
)
{
DSTATUS stat=STA_NOINIT;
switch (pdrv) {
case DEV_FLASH :
{
if(SPI_FLASH_ReadID()==sFLASH_ID)
stat&=~STA_NOINIT;
else
stat=STA_NOINIT;
}
return stat;
}
return STA_NOINIT;
}
b.disk_initialize 初始化设备的接口。示例代码如下:
DSTATUS disk_initialize (
BYTE pdrv /* Physical drive nmuber to identify the drive */
)
{
DSTATUS stat=STA_NOINIT;
switch (pdrv) {
case DEV_FLASH :
{
SPI_FLASH_Init();
if(SPI_FLASH_ReadID()==sFLASH_ID)
stat&=~STA_NOINIT;
else
stat=STA_NOINIT;
}
return stat;
}
return STA_NOINIT;
}
c.disk_read 读。示例代码如下:
DRESULT disk_read (
BYTE pdrv, /* Physical drive nmuber to identify the drive */
BYTE *buff, /* Data buffer to store read data */
LBA_t sector, /* Start sector in LBA */
UINT count /* Number of sectors to read */
)
{
DRESULT res;
switch (pdrv) {
case DEV_FLASH :
{
SPI_FLASH_BufferRead(buff, sector*4096, count*4096);
res=RES_OK;
}
return res;
}
return RES_PARERR;
}
d.disk_write 写。示例代码如下:
DRESULT disk_write (
BYTE pdrv, /* Physical drive nmuber to identify the drive */
const BYTE *buff, /* Data to be written */
LBA_t sector, /* Start sector in LBA */
UINT count /* Number of sectors to write */
)
{
DRESULT res;
switch (pdrv) {
case DEV_FLASH :
{
SPI_FLASH_SectorErase(sector*4096);
SPI_FLASH_BufferWrite((BYTE *)buff, sector*4096, count*4096);
res=RES_OK;
}
return res;
}
return RES_PARERR;
}
e.disk_ioctl 设备属性接口。示例代码如下:
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_FLASH :
{
switch (cmd) {
/* 扇区数量:2048*4096/1024/1024=8(MB) */
case GET_SECTOR_COUNT:
*(DWORD * )buff = 2048;
break;
/* 扇区大小 */
case GET_SECTOR_SIZE :
*(WORD * )buff = 4096;
break;
/* 同时擦除扇区个数 */
case GET_BLOCK_SIZE :
*(DWORD * )buff = 1;
break;
}
res=RES_OK;
}
return res;
}
return RES_PARERR;
}
f.DWORD get_fattime 获取时间。示例代码如下:
DWORD get_fattime (void)
{
return ((2021-1980)<<(25)|(1)<<(21)|(1)<<(16)|(1)<<(11)|(1)<<(5)|(2)<<(0));
}
六、修改ffconf.h,配置文件系统的具体功能。
a.FF_USE_MKFS 1 使用格式化的功能
b.FF_CODE_PAGE 936 修改编码页以支持中文文件名
c.FF_USE_LFN 0 支持长文件名
d.FF_MAX_SS 4096 修改支持最大的设备扇区大小,与flash设备对应。
七、尝试使用文件系统来测试是否移植成功。
常规使用流程
a.挂在文件系统到一个设备。使用函数:f_mount()
b.打开文件。使用函数:f_open()
c.数据的读取与写入
d.关闭文件。使用函数:f_close()
注意:测试过程可使用返回值判断是否移植成功。在挂载设备时,存在错误FR_NO_FILESYSTEM(13),可采用函数f_mkfs进行解决,该函数用于格式化文件系统。相关代码如下:
printf("\r\nFatFs测试实验\r\n");
res=f_mount(&flash_fs, "", 1);
if(res==FR_OK)
{
printf("\r\n文件系统挂载成功!\r\n");
}
else
{
printf("\r\nf_mount错误代码:%d\r\n",res);
if(res == FR_NO_FILESYSTEM)
{
res=f_mkfs("", 0, work, sizeof work);
if(res==FR_OK)
{
printf("\r\n文件系统格式化成功!\r\n");
}
else
{
printf("\r\nf_mkfs错误代码:%d\r\n",res);
}
}
}
//打开文件,写入数据,关闭文件
res = f_open(&flash_fil, "hello.txt", FA_OPEN_ALWAYS|FA_WRITE|FA_READ);
if(res==FR_OK)
{
printf("\r\nf_open测试成功!\r\n");
}
else
{
printf("\r\nf_open错误代码:%d\r\n",res);
}
//
printf("\r\n正在写入:%s\r\n",Tx_Buffer);
res=f_write(&flash_fil, Tx_Buffer,BufferSize,&Num_Of_Written);
if(res==FR_OK)
{
printf("\r\nf_write测试成功!\r\n");
}
else
{
printf("\r\nf_write错误代码:%d\r\n",res);
}
//
f_close(&flash_fil);
//打开文件,读取数据,关闭文件
res = f_open(&flash_fil, "hello.txt", FA_OPEN_ALWAYS|FA_WRITE|FA_READ);
if(res==FR_OK)
{
printf("\r\nf_open测试成功!\r\n");
}
else
{
printf("\r\nf_open错误代码:%d\r\n",res);
}
//
res=f_read(&flash_fil, Rx_Buffer, BufferSize, &Num_Of_Read);
printf("\r\n读取完成:%s\r\n",Rx_Buffer);
if(res==FR_OK)
{
printf("\r\nf_read测试成功!\r\n");
}
else
{
printf("\r\nf_read错误代码:%d\r\n",res);
}
//
f_close(&flash_fil);
结果展示: