FATFS挂载多个存储设备(1):底层设备驱动函数编写

前言

FATFS文件系统支持挂载多个存储设备,下面以挂载TF卡和Flash来说明FATFS挂载多个存储设备的方法。

1.底层设备驱动函数编写

(1)为存储设备定义编号

和PC上使用C开头表示盘符不同,FATFS使用数字表示存储设备,因此我们需要为物理设备定义编号。这里将TF卡定义为0,Flash定义为1:

#define TF         0     // TF卡
#define EX_FLASH   1     // 外部SPI Flash

(2)设备状态获取函数修改

这里主要根据存储设备编号不同返回存储设备是否存在的状态信息:

DSTATUS disk_status (
	BYTE pdrv		/* Physical drive nmuber to identify the drive */
)
{
  DSTATUS stat;
  switch (pdrv)
  {
    case TF:
      stat = disk.drv[pdrv]->disk_status(disk.lun[pdrv]);
      break;
    case EX_FLASH:
      // 读取Flash设备ID是否正确
      if (SPI_FLASH_ReadID() == sFLASH_ID)
      {
        stat = ERR_OK;
      }
      else
      {
        stat = STA_NOINIT;
      }
      break;
      default:
        stat = STA_NOINIT;
        break;
  }
  return stat;
}

(3)设备初始化

这里主要根据存储设备编号不同对存储设备进行初始化操作:

DSTATUS disk_initialize (
	BYTE pdrv				/* Physical drive nmuber to identify the drive */
)
{
  DSTATUS stat = RES_OK;
  switch (pdrv)
  {
    case TF:
      if(disk.is_initialized[pdrv] == 0)
      { 
        disk.is_initialized[pdrv] = 1;
        stat = disk.drv[pdrv]->disk_initialize(disk.lun[pdrv]);
      }
      break;
    case EX_FLASH:
      // 初始化flash
      SPI_FLASH_Init();
      Delay_ms(10);
      // 唤醒flash
      SPI_Flash_WAKEUP();
      stat = disk_status(EX_FLASH);
      break;
    default:
      stat = STA_NOINIT;
      break;
  }
  return stat;
}

(4)扇区读取

这里主要根据存储设备编号不同对存储设备的扇区进行读取操作:

DRESULT disk_read (
	BYTE pdrv,		/* Physical drive nmuber to identify the drive */
	BYTE *buff,		/* Data buffer to store read data */
	DWORD sector,	        /* Sector address in LBA */
	UINT count		/* Number of sectors to read */
)
{
  DRESULT res;
  switch (pdrv)
  {
    case TF:
      res = disk.drv[pdrv]->disk_read(disk.lun[pdrv], buff, sector, count);
      break;
    case EX_FLASH:
      SPI_FLASH_BufferRead(buff, sector * 4096, count * 4096);
      res = RES_OK;
      break;
    default:
      res = RES_ERROR;
      break;
  }
  
  return res;
}

(5)扇区写入

这里主要根据存储设备编号不同对存储设备的扇区进行写入操作:

DRESULT disk_write (
	BYTE pdrv,		/* Physical drive nmuber to identify the drive */
	const BYTE *buff,	/* Data to be written */
	DWORD sector,		/* Sector address in LBA */
	UINT count        	/* Number of sectors to write */
)
{
  DRESULT res;
  switch (pdrv)
  {
    case TF:
      res = disk.drv[pdrv]->disk_write(disk.lun[pdrv], buff, sector, count);
      break;
    case EX_FLASH:
      SPI_FLASH_SectorErase(sector * 4096);
      SPI_FLASH_BufferWrite((u8 *)buff, sector * 4096, count * 4096);
      res = RES_OK;
      break;
    default:
      res = RES_ERROR;
      break;
  }
  
  return res;
}

(6)I/O控制操作

这里主要根据存储设备编号不同,返回文件系统请求的存储设备信息:扇区数量、扇区大小等。

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 TF:
      res = disk.drv[pdrv]->disk_ioctl(disk.lun[pdrv], cmd, buff);
      break;
    case EX_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;
      }
      res = RES_OK;
      break;
    default:
      res = RES_ERROR;
      break;
  }
  return res;
}

(7)时间戳获取

这里我们提前开启了rtc功能,直接返回rtc寄存器数据即可:

__weak DWORD get_fattime (void)
{
  RTC_DateTypeDef date;
  RTC_TimeTypeDef time;
  RTC_TimeAndDate_Get(&date, &time);
  return	  ((DWORD)(date.Year + 2000 - 1980) << 25) //  1980 至今是多少年,范围是(0..127)
      | ((DWORD)date.Month << 21) // 月份,范围为 (1..12)
      | ((DWORD)date.Date << 16) // 日期,范围为 (1..31)
      | ((DWORD)time.Hours << 11) // 时,范围为 (0..23)
      | ((DWORD)time.Minutes << 5) // 分,范围为 (0..59)
      | ((DWORD)time.Seconds / 2 >> 1); // / 2,范围为 (0..29)
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

时光飞逝的日子

感谢您的支持,让我们一起进步!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值