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;
}
posted @   Charles_hui  阅读(568)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示