FATs文件系统笔记
1.f_mkfs函数创建文件系统之前,需要先调用f_mount函数挂载文件系统。因为f_mkfs需要知道创建文件系统的磁盘驱动号,而挂载文件系统后才能获得该信息。
2.FatF 需要每个逻辑驱动器(FAT 卷)的工作区(文件系统对象)。在执行任何文件/目录操作之前,需要向逻辑驱动器的f_mount函数注册文件系统对象。文件/目录 API 函数在此过程后即可开始工作。某些卷管理功能(f_mkfs、f_fdisk和f_setcp)不需要文件系统对象。
3.文件系统的最小操作单位是512byte。
//
//
/***********************************************************************************************************/
f_open的打开模式:
FA_READ(0x01):指定文件以只读方式打开。可以从文件中读取数据,但不能写入或修改文件。
FA_WRITE(0x02):指定文件以可写方式打开。可以向文件写入数据,但不能读取文件。
FA_OPEN_EXISTING(0x00):指定打开现有文件。如果文件不存在,则打开操作将失败。
FA_CREATE_NEW(0x04):指定创建一个新文件。如果文件已经存在,则创建操作将失败。
FA_CREATE_ALWAYS(0x08):指定创建一个新文件。如果文件已经存在,则会将其截断为空文件。
FA_OPEN_ALWAYS(0x10):指定打开文件,如果文件不存在,则创建一个新文件。
FA_OPEN_APPEND(0x30):与FA_OPEN_ALWAYS相同,只是读/写指针设置在文件末尾。
1.设备状态获取
点击查看代码
DSTATUS disk_status (
BYTE pdrv /* 物理编号 */
)
{
DSTATUS status = STA_NOINIT;
switch (pdrv) {
case ATA: /* SD CARD */
break;
case SPI_FLASH:
/* SPI Flash状态检测:读取SPI Flash 设备ID */
if (sFLASH_ID == SPI_FLASH_ReadID()) {
/* 设备ID读取结果正确 */
status &= ~STA_NOINIT;
} else {
/* 设备ID读取结果错误 */
status = STA_NOINIT;;
}
break;
default:
status = STA_NOINIT;
}
return status;
}
2.设备初始化:
参数pdrv,用来指定设备物理编号。对于SPI Flash芯片我们调用SPI_FLASH_Init()函数实现对SPI Flash芯片引脚GPIO初始化配置以及SPI通信参数配置。 SPI_Flash_WAKEUP()函数唤醒SPI Flash芯片,当SPIFlash芯片处于睡眠模式时需要唤醒芯片才可以进行读写操作。
点击查看代码
DSTATUS disk_initialize (
BYTE pdrv /* 物理编号 */
)
{
uint16_t i;
DSTATUS status = STA_NOINIT;
switch (pdrv) {
case ATA: /* SD CARD */
break;
case SPI_FLASH: /* SPI Flash */
/* 初始化SPI Flash */
SPI_FLASH_Init();
/* 延时一小段时间 */
i=500;
while (--i);
/* 唤醒SPI Flash */
SPI_Flash_WAKEUP();
/* 获取SPI Flash芯片状态 */
status=disk_status(SPI_FLASH);
break;
default:
status = STA_NOINIT;
}
return status;
}
3.读取扇区:
野火开发板使用的SPI Flash芯片型号为W25Q256FV,每个扇区大小为4096个字节(4KB),总共有32M字节空间, 为兼容后面实验程序,我们只将后部分16MB空间分配给FatFs使用,前部分16MB空间用于其他实验需要, 即FatFs是从16MB空间开始,为实现这个效果需要将所有的读写地址都偏移4096个扇区空间。
点击查看代码
DRESULT disk_write (
BYTE pdrv, /* 设备物理编号(0..) */
const BYTE *buff, /* 欲写入数据的缓存区 */
DWORD sector, /* 扇区首地址 */
UINT count /* 扇区个数(1..128) */
)
{
uint32_t write_addr;
DRESULT status = RES_PARERR;
if (!count) {
return RES_PARERR; /* Check parameter */
}
switch (pdrv) {
case ATA: /* SD CARD */
break;
case SPI_FLASH:
/* 扇区偏移16MB,外部Flash文件系统空间放在SPI Flash后面16MB空间 */
sector+=4096;
write_addr = sector<<12;
SPI_FLASH_SectorErase(write_addr);
SPI_FLASH_BufferWrite((u8 *)buff,write_addr,count<<12);
status = RES_OK;
break;
default:
status = RES_PARERR;
}
return status;
}
4.扇区写入
disk_write函数有四个形参,pdrv为设备物理编号。buff指向待写入扇区数据的首地址。sector,指定要读取数据的扇区首地址。 count指定扇区数量。对于SPI Flash芯片,在写入数据之前需要先擦除,所以用到扇区擦除函数(SPI_FLASH_SectorErase)。 然后就是在调用数据写入函数(SPI_FLASH_BufferWrite)把数据写入到指定位置内。
点击查看代码
DRESULT disk_write (
BYTE pdrv, /* 设备物理编号(0..) */
const BYTE *buff, /* 欲写入数据的缓存区 */
DWORD sector, /* 扇区首地址 */
UINT count /* 扇区个数(1..128) */
)
{
uint32_t write_addr;
DRESULT status = RES_PARERR;
if (!count) {
return RES_PARERR; /* Check parameter */
}
switch (pdrv) {
case ATA: /* SD CARD */
break;
case SPI_FLASH:
/* 扇区偏移16MB,外部Flash文件系统空间放在SPI Flash后面16MB空间 */
sector+=4096;
write_addr = sector<<12;
SPI_FLASH_SectorErase(write_addr);
SPI_FLASH_BufferWrite((u8 *)buff,write_addr,count<<12); //左移12位实际是乘以4096
status = RES_OK;
break;
default:
status = RES_PARERR;
}
return status;
}
5.其他控制
点击查看代码
DRESULT disk_ioctl (
BYTE pdrv, /* 物理编号 */
BYTE cmd, /* 控制指令 */
void *buff /* 写入或者读取数据地址指针 */
)
{
DRESULT status = RES_PARERR;
switch (pdrv) {
case ATA: /* SD CARD */
break;
case SPI_FLASH:
switch (cmd) {
/* 扇区数量:4096*4096/1024/1024=16(MB) */
case GET_SECTOR_COUNT:
*(DWORD * )buff = 4096;
break;
/* 扇区大小 */
case GET_SECTOR_SIZE :
*(WORD * )buff = 4096;
break;
/* 同时擦除扇区个数 */
case GET_BLOCK_SIZE :
*(DWORD * )buff = 1;
break;
}
status = RES_OK;
break;
default:
status = RES_PARERR;
}
return status;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了