fatfs移植细节。

发布时间 2023-08-30 11:20:29作者: 一只小云安

  有一次移植fatfs忘了很多东西,进行一次详细的记录。(主要是对本人自己记不清的地方查漏补缺,因此此贴不能当作教程使用。)

  fatfs的下载链接 https://github.com/abbrev/fatfs 。将source内的文件都放入工程。

  文件加入之后就是适配了,fatfs的适配主要工作是:ffconf.h的宏定义,disk.c的接口函数实现。

  一:

    配置ffconf.h内的宏定义,引用一个链接来描述(网上有很多就不再赘述)。

    主要就是是否支持中文,块的字节数,长文件名,时间戳。

  二:

     disk.c的适配主要是五个函数的填充。

  DSTATUS disk_initialize (BYTE pdrv )  /* Physical drive nmuber to identify the drive  初始化函数,一般放入储存设备初始化函数,放在其他地方的话直接返回0就可以了*/
 
  DSTATUS disk_status (BYTE pdrv )        /* Physical drive nmuber to identify the drive 获取磁盘状态,一般读取ID检测是否与磁盘通信成功,可以直接返回0*/
 
  DRESULT disk_read (
  BYTE pdrv,      /* Physical drive nmuber to identify the drive */
  BYTE *buff,     /* Data buffer to store read data */
     LBA_t sector,   /* Start sector in LBA */
   UINT count      /* Number of sectors to read */
  )
  DRESULT disk_write (
     BYTE pdrv,          /* Physical drive nmuber to identify the drive */
     const BYTE *buff,   /* Data to be written */
  LBA_t sector,       /* Start sector in LBA */
     UINT count          /* Number of sectors to write */
  )
  读写函数都是相似的,主要解释一下参数的意思。drv是盘符,*buff是数据流地址,sector是起始地址(以扇区为单位)。count是数据流长度(以扇区为单位)。
  
  DRESULT disk_ioctl (
     BYTE pdrv,      /* Physical drive nmuber (0..) */
     BYTE cmd,       /* Control code */
     void *buff      /* Buffer to send/receive control data */
  )
  解释参数:drv为盘符,cmd为命令,*buff为返回值。
  这个上个例程就一目了然了
        switch(cmd)
        {
            case CTRL_SYNC:
                res = RES_OK;
                break;  
            case GET_SECTOR_SIZE:    //得到flash硬件 一个扇区的大小。单位为字节
                *(WORD*)buff = 256;
                res = RES_OK;
                break;  
            case GET_BLOCK_SIZE:  //得到flash硬件擦除的最小单元,单位为硬件扇区
                *(WORD*)buff = 512;
                res = RES_OK;
                break;  
            case GET_SECTOR_COUNT:    //得到flash有多少个扇区(ps:那么磁盘大小就可以算出来为SIZE*COUNT)
                *(DWORD*)buff = 65536;
                res = RES_OK;
                break;
            default:
                res = RES_PARERR;
                break;
        }
  以上就是移植的忽略点(记不详细)。然后再补充一点块设备的常识。
  在操作系统里一般通的名词是:SECTOR(扇区),BLOCK(块)。具体解释如下:
    block:操作系统里可操作的最小单元,一般为4096,2048,1024*32等等,block的目的是为了包含不同规格的存储器。(举个栗子,文件系统把256,512等等扇区大小的存储器封装成统一块大小的磁盘,操作系统就不需要关注那些硬件细节了。)
  在文件系统里通用的名词
    sector:硬件里可写入的最小单元,有256,512(Byte)类型
    block: 由于有些硬件写入和擦除的最小单元不一致,所以把sector当作最小写入单元,block当做最小擦除单元。(往往最小擦除单元大于最小写入单元且是整数倍关系,所以block就是最小可读写单元,符合操作系统上block的定义)
  在flash硬件层面,就比较复杂,有PAGE(页),SECTOR(扇区),BLOCK(块),关系为,一个储存器由x个块组成,一个块由y个扇区组成,一个扇区由z个页组成,一页由m个字节组成。 
 
    PAGE(页):
    SECTOR(扇区):
    BLOCK(块):
  NOR FLASH
    可以随机读取写入,但是写入前需要先检查是否需要擦除。
    擦除最小单元可能是sector或者page(取决于硬件组成)。
  NAND FLASH
    块Block,是Nand Flash的擦除操作的基本/最小单位
    只支持按page读取写入,写入需要先按Block擦除,再按照page写入。