FATFS文件系统移植(FLASH)
一、说明
1、在移植文件系统前需先验证FLASH的全部扇区读写是否没问题,将全部扇区读写一遍。
2、可在FatFs文件系统官网下载文件系统源码:http://elm-chan.org/fsw/ff/00index_e.html.
3、本文章以ff12b版本为例下载源码后需要导入的文件有:
文件 | 说明 |
---|---|
diskio.c | SPI_FLASH的读写函数接口文件(需改动) |
diskio.h | 核心文件(无需改动) |
ff.c | 核心文件(无需改动) |
ff.h | 核心文件(无需改动) |
ffconf.h | 配置文件(需改动) |
integer.h | 数据类型定义文件(无需改动) |
cc936.c | 中文支持文件(需要用到中文目录才用加载进去,不需要则不用) |
二、移植步骤
1、将所需文件导入到工程中,如图
2、diskio.c接口修改
1)添加所需头文件,以及宏定义,将FLASH定义为卷0,如图
2)disk_status函数
DSTATUS disk_status (
BYTE pdrv /* Physical drive nmuber to identify the drive */
)
{
if(pdrv == SPI_FLASH)
{
return RES_OK;
}
else
{
printf("!!!disk_status ERR\r\n");
return RES_PARERR;
}
}
3)disk_initialize 初始化函数
DSTATUS disk_initialize (
BYTE pdrv /* Physical drive nmuber to identify the drive */
)
{
if(pdrv == SPI_FLASH)
{
drv_sflash_init();
return RES_OK;
}
else
{
printf("!!!disk_initialize ERR\r\n");
return RES_PARERR;
}
}
3)disk_read 读取函数接口
buff:读取SPI_FLASH数据,buff是将读取的数据放到buff指针变量中
sector:扇区,一个扇区有4096个字节,比如要读第0扇区,那么读数据的开始地址是:04096如果要读第1扇区,那么读数据的开始地址是:14096
count:有两种方式实现,一是要读取的数据长度,也要乘以4096,表示读的是多少个字节,二是如代码所示。
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 */
)
{
if (!count)return RES_PARERR;//count不能等于0,否则返回参数错误
if(pdrv == SPI_FLASH)
{
for(;count>0;count--)
{
SPI_Flash_Read(buff,sector*SPI_FLASH_SECTOR_SIZE,SPI_FLASH_SECTOR_SIZE);
sector++;
buff+=SPI_FLASH_SECTOR_SIZE;
}
return RES_OK;
}
else
{
printf("!!!disk_read ERR\r\n");
return RES_ERROR;
}
}
4)disk_write 写函数接口
buff:擦写SPI_FLASH数据,buff是将要写入的数据放到buff指针变量中
sector:扇区,一个扇区有4096个字节,比如要写第0扇区,那么读数据的开始地址是:04096如果要写第1扇区,那么读数据的开始地址是:14096
count:有两种方式实现,一是要写入的数据长度乘以4096,表示读的是多少个字节,二是如代码所示。
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 */
)
{
if (!count)return RES_PARERR;//count不能等于0,否则返回参数错误
if(pdrv == SPI_FLASH)
{
for(;count>0;count--)
{
SPI_Flash_Write((u8*)buff,sector*SPI_FLASH_SECTOR_SIZE,SPI_FLASH_SECTOR_SIZE);
sector++;
buff+=SPI_FLASH_SECTOR_SIZE;
}
// SPI_Flash_Write((uint8_t*)buff,sector*4096, count);
return RES_OK;
}
else
{
printf("!!!disk_write ERR\r\n");
return RES_ERROR;
}
}
5)disk_ioctl 函数
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;
case GET_SECTOR_COUNT:
*(DWORD*)buff = SPI_FLASH_SECTOR_NUMBER;//W25Q128 有4096个大小为4k bytes 的扇区
return RES_OK;
case GET_SECTOR_SIZE:
*(WORD*)buff = SPI_FLASH_SECTOR_SIZE;//spi flash的扇区大小是 4K Bytes
return RES_OK;
case GET_BLOCK_SIZE:
*(WORD*)buff = 1;
return RES_OK;;
default:
return RES_PARERR;
}
}
else
{
printf("!!!disk_ioctl ERR\r\n");
return RES_ERROR;
}
}
5)disk_ioctl 获得时间戳函数
不添加会报错,有需要可以参照网上教程填入,默认返回0就好
DWORD get_fattime (void)
{
return 0;
}
2、ffconf.h 配置文件修改
#define _USE_MKFS 1 //支持格式化操作的命令
#define _MIN_SS 512
#define _MAX_SS 4096 //因为Flash每个扇区是4K
3、长文件名与中文支持
在ffconf.h配置,将cc936文件添加进去,支持长文件名和中文的话会占用很大的ROM空间,所以不需要只需将_USE_LFN改为0,去除cc936文件编译即可。
#define _CODE_PAGE 936
#define _USE_LFN 1
#define _MAX_LFN 255
4、测试程序
用于测试文件系统是否移植成功
FATFS fs; /* FatFs文件系统对象 */
FIL fp; /* 文件对象 */
BYTE fatfs_buffer[_MAX_SS]= {0}; /* 读缓冲区 */
UINT bw; /* 文件成功读写数量 */
BYTE write_buf[] = "dffgrgrgrgrgr";/* 写缓冲区*/
BYTE read_buf[sizeof(write_buf)];
UINT br;
char filename[] = "0:test.txt";
void test(void)
{
FRESULT res; /* 文件操作结果 */
res = f_mount(&fs,"0:",1);
if (res == FR_NO_FILESYSTEM)
{
printf("》FLASH还没有文件系统,即将进行格式化...\r\n");
/* 格式化 */
res = f_mkfs("0:",FM_ANY,0,fatfs_buffer,sizeof fatfs_buffer);
if (res == FR_OK)
{
printf("》FLASH已成功格式化文件系统。\r\n");
/* 格式化后,先取消挂载 */
res = f_mount(NULL,"0:",1);
/* 重新挂载 */
res = f_mount(&fs,"0:",1);
if(res == FR_OK)
{
printf("挂载成功 \r\n");
}
}
else
{
printf("《《格式化失败。》》\r\n");
while(1);
}
}
else if(res != FR_OK)
{
printf("!!外部Flash挂载文件系统失败。(%d)\r\n",res);
printf("!!可能原因:SPI Flash初始化不成功。\r\n");
while (1);
}
else
{
printf("》文件系统挂载成功,可以进行读写测试\r\n");
}
res = f_open(&fp, "0:test.txt", FA_READ|FA_WRITE|FA_CREATE_ALWAYS);
printf("\r\n f_open res = %d\r\n", res);
res = f_close(&fp);
printf("\r\n f_close res = %d\r\n", res);
res = f_open(&fp, "0:test.txt", FA_WRITE|FA_OPEN_EXISTING);
printf("\r\n f_open res = %d", res);
res = f_write(&fp, write_buf, sizeof(write_buf), &bw);
printf("\r\n f_write res = %d,bw = %d,sizeof write_buf = %d,", res, br, sizeof(write_buf));
res = f_close(&fp);
// // 读之前需要打开文件:只读权限(文件存在就读取)
res = f_open(&fp, filename, FA_READ|FA_OPEN_EXISTING);
printf("\r\n f_open res = %d", res);
res = f_read(&fp, read_buf, sizeof(write_buf), &br);
printf("\r\n f_read1 res = %d,br = %d,sizeof read_buf = %d,", res, br, sizeof(write_buf));
printf("read_buf = %s\r\n", read_buf);
res = f_close(&fp);
printf("\r\n f_close res = %d\r\n", res);
}
三、文档引用链接
链接: https://www.cnblogs.com/josephcnblog/articles/9261095.html.
对于测试系统操作不了解的,可去看FATFS文件系统常用操作指令的讲解:
链接: https://blog.csdn.net/qq_39772670/article/details/109736363.