fatfs_diskio关键代码

发布时间:2024年01月23日

fatfs文件关键代码

宏定义

#define ATA 0// 预留 SD 卡使用
#define SPI_FLASH 1// 外部 SPI Flash

设备状态获取

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;
}

这是一个用于获取磁盘状态的函数,具体分析如下:

  1. 函数声明:

    DSTATUS disk_status(BYTE pdrv);
    

    该函数返回一个 DSTATUS 类型的状态,接受一个 BYTE 类型的参数 pdrv

  2. 局部变量初始化:

    DSTATUS status = STA_NOINIT;
    

    在函数一开始,status 被初始化为 STA_NOINIT,这是磁盘状态的初始值。

  3. Switch 语句:

    • 如果 pdrv 等于 ATA,则执行一个空操作(break),表示SD卡。
    • 如果 pdrv 等于 SPI_FLASH,则进行SPI Flash状态检测。
      • 如果SPI Flash的设备ID等于通过 SPI_FLASH_ReadID() 读取的值,那么将 statusSTA_NOINIT 标志位清零。
      • 如果设备ID读取结果不正确,将 status 设置为 STA_NOINIT
    • 如果 pdrv 不是上述两者之一,将 status 设置为 STA_NOINIT
  4. 返回状态:

    return status;
    

    返回最终的磁盘状态。

设备初始化

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;
}

这是一个用于初始化磁盘的函数,具体分析如下:

  1. 函数声明:

    DSTATUS disk_initialize(BYTE pdrv);
    

    该函数返回一个 DSTATUS 类型的状态,接受一个 BYTE 类型的参数 pdrv

  2. 局部变量初始化:

    uint16_t i;
    DSTATUS status = STA_NOINIT;
    

    在函数一开始,定义了一个 uint16_t 类型的变量 i 用于延时,同时将 status 初始化为 STA_NOINIT,即磁盘状态的初始值。

  3. Switch 语句:

    • 如果 pdrv 等于 ATA,则执行一个空操作(break),表示SD卡。
    • 如果 pdrv 等于 SPI_FLASH,则进行SPI Flash的初始化过程。
      • 初始化 SPI Flash。
      • 执行一个简单的延时操作。
      • 唤醒 SPI Flash。
      • 获取 SPI Flash 的芯片状态,调用了之前提到的 disk_status 函数。
  4. 返回状态:

    return status;
    

    返回最终的磁盘初始化状态。

总体来说,该函数用于根据输入的磁盘编号 pdrv 进行初始化操作,主要处理了SD卡和SPI Flash的情况,包括SPI Flash的初始化、唤醒以及获取芯片状态。最终返回磁盘的初始化状态。

扇区读取

DRESULT disk_read(BYTE pdrv, BYTE *buff, DWORD sector, UINT count)
{
    DRESULT status = RES_PARERR;

    switch (pdrv) {
        case ATA: /* SD CARD */
            break;

        case SPI_FLASH:
            /* 扇区偏移 2MB,外部 Flash 文件系统空间放在 SPI Flash 后面 6MB 空间 */
            sector += 512;
            SPI_FLASH_BufferRead(buff, sector << 12, count << 12);
            status = RES_OK;
            break;

        default:
            status = RES_PARERR;
    }

    return status;
}

变量类型定义

typedef unsigned char	BYTE;

/* These types MUST be 16-bit */
typedef short			SHORT;
typedef unsigned short	WORD;
typedef unsigned short	WCHAR;

/* These types MUST be 16-bit or 32-bit */
typedef int				INT;
typedef unsigned int	UINT;

/* These types MUST be 32-bit */
typedef long			LONG;
typedef unsigned long	DWORD;

偏移原因

在这里插入图片描述

外部flash读写起始地址为512*4096 也就是2*1024*1024 为2MB

/* 扇区偏移 2MB,外部 Flash 文件系统空间放在 SPI Flash 后面 6MB 空间 */
        sector += 512;
        SPI_FLASH_BufferRead(buff, sector << 12, count << 12);
		/*
		左移 12 位实际是乘以 4096
		SPI_FLASH_BufferRead(buff,sector*4096,count*4096);
		*/
        status = RES_OK;
        break;

开发板使用的 SPI Flash 芯片型号为 W25Q64FV,每个扇区大小为 4096 个字节 (4KB),总共有 8M字节空间,为兼容后面实验程序,我们只将后部分 6MB 空间分配给 FatFs 使用,前部分 2MB 空间用于其他实验需要,即 FatFs 是从 2MB 空间开始,为实现这个效果需要将所有的读写地址都偏移 512 个扇区空间。

扇区写入

DRESULT disk_write(BYTE pdrv, const BYTE *buff, DWORD sector, UINT count) {
    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:
            /* 扇区偏移 2MB,外部 Flash 文件系统空间放在 SPI Flash 后面 6MB 空间 */
            sector += 512;
            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;
}

同的读取扇区同理,不过一定要记得写入前要擦除

其他控制

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 SD_CARD :

		// Process of the command for the ATA drive

		return res;

	case SPI_FLASH :
		
		switch(cmd)
		{
			//返回扇区个数
			case GET_SECTOR_COUNT:
				/* 扇区数量:1536*4096/1024/1024=6(MB) */
				*(DWORD*)buff = 1536;
				
			break;
			//返回每个扇区大小
			case GET_SECTOR_SIZE:
				*(WORD*)buff = 4096;

			break;
			//返回擦除扇区的最小个数(单位为扇区)
			case GET_BLOCK_SIZE:
			 *(WORD*)buff = 1;
			
			break;
			
		}		
			

		// Process of the command for the MMC/SD card
		res = RES_OK;
		return res;

	}

获取时间

__weak DWORD get_fattime(void)
{
 /* 返回当前时间戳 */
 return ((DWORD)(2015 - 1980) << 25) /* Year 2015 */
 | ((DWORD)1 << 21) /* Month 1 */
 | ((DWORD)1 << 16) /* Mday 1 */
 | ((DWORD)0 << 11) /* Hour 0 */
 | ((DWORD)0 << 5) /* Min 0 */
 | ((DWORD)0 >> 1); /* Sec 0 */
 }
文章来源:https://blog.csdn.net/elderingezez/article/details/135765923
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。