对前面介绍的 STM32H743 移植 FatFs 文件系统,涉及到的底层接口文件 diskio.c 做一下解析。
一、存储设备状态 disk_status
disk_status 用来查询当前存储设备的状态。
DSTATUS disk_status ( BYTE pdrv /* [IN] Physical drive number */ );
Parameter
pdrv:用户定义的物理驱动器号,单驱动器系统中,该参数一直为 0。
Return Values
返回当前设备状态值,具体指在下面描述。FatFs 只使用 STA_NOINIT 和 STA_PROTECT。
STA_NOINIT
说明该设备还未初始化和准备好运行。该标志在系统复位时被设置,当媒体设备被移除或者调用 disk_initialize 函数失败的时候,该标志位被设置。当 disk_initialize 函数被成功调用的时候该标志被清除。当媒体变化或者发生异步访问的时候必须关注该值,或者一些自动挂载方法得不到正确调用的时候也要关注该标志位。如果系统不支持媒介变化检测,应用程序在媒介变化的时候应该明确的再次调用 f_mount 函数来重新挂载。
STA_NODISK
表示当前驱动器号下无设备。该函数在驱动器准备好时被清除。FatFs 不引用该标志。
STA_PROTECT
表明当前设备写保护状态。当设备不包含写保护方法的时候,该标志被清除。当驱动器号下无驱动器的时候,不支持该标志。
二、存储设备初始化 disk_initialize
该函数调用存储设备初始化方法。
DSTATUS disk_initialize ( BYTE pdrv /* [IN] Physical drive number */ );
Parameter
pdrv:用户定义的物理驱动器号,单驱动器系统中,该参数一直为 0。
Return Values
该方法返回初始化设备状态标志,返回值与 disk_status 函数的返回值一致。
Description
该函数初始化存储设备使之可以支持一般的读写方法。当该函数调用成功,STA_NOINIT 标志将会清除。
Remarks:该函数必须在 Fatfs 模块的控制下,应用程序不能调用该函数,当需要重新初始化文件系统的时候,调用 f_mount 即可。
三、存储设备读接口 disk_read
该方法在读写存储设备扇区的时候被调用。
DRESULT disk_read ( BYTE pdrv, /* [IN] Physical drive number */ BYTE* buff, /* [OUT] Pointer to the read data buffer */ DWORD sector, /* [IN] Start sector number */ UINT count /* [IN] Number of sectros to read */ );
Parameters
pdrv:用户定义的物理驱动器号,单驱动器系统中,该参数一直为 0。
buff:指向要存储的读取数据数组的首地址。
sector:读取扇区的起始标号。
count:读取的扇区的数量。
Return Value
RES_OK (0):调用成功。
RES_ERROR:在读取操作执行过程中,发生硬件错误并无法修复。
RES_PARERR:不支持的参数类型。
RES_NOTRDY:设备还未初始化。
Description
数据的读写操作是按照扇区进行的,Fatfs 支持的扇区大小从 512 字节到 4096 字节。当 Fatfs 被配置成指定扇区大小的时候(_MIN_SS == MAX_SS,大多数人的选择配置),读写方法必须和选定的扇区大小配合。单 Fatfs 配置成可变扇区大小的时候(_MIN_SS != MAX_SS),文件系统将会使用 disk_ioctl 方法来获取扇区大小,该函数将会在 disk_initialize 执行完成之后调用。
buff 的内存地址并不都是字对齐的,不对齐的情况发生在使用 Direct Transfer 的时候,当总线架构,尤其是 DMA 控制器不支持不对齐的内存访问的时候,需要在该方法内部解决不对齐的问题,建议的解决方案如下:
- 如果有必要,将地址转换为字对齐的地址。
- 在调用 f_read 的时候,避开一次读取一个扇区的长读取(有一些直接传输无法避开)。
- 当 f_read(fp, data, btw, bw) 被调用的时候,请确保(((UINT)data & 3) == (f_tell(fp) & 3))表达式结果为真,以保证字对齐。
通常不要将多个扇区读请求转换为单个扇区读模式,否则不能得到很好的数据吞吐量。
四、存储设备写接口 disk_write
该函数将会写入一个或者多个扇区数据到设备中。
DRESULT disk_write ( BYTE drv, /* [IN] Physical drive number */ const BYTE* buff, /* [IN] Pointer to the data to be written */ DWORD sector, /* [IN] Sector number to write from */ UINT count /* [IN] Number of sectors to write */ );
Parameters
pdrv:用户定义的物理驱动器号,单驱动器系统中,该参数一直为 0。
buff:指向要写入的读取数据数组的首地址。
sector:写入扇区的起始标号。
count:写入扇区数量。
Return Values
RES_OK (0):调用成功。
RES_ERROR:发生硬件错误且。
RES_WRPRT:设备写保护。
RES_PARERR:不支持的参数。
RES_NOTRDY:设备还未初始化。
Description
写入地址并非一直都是字对齐的,处理方法和 read 一样。
为了好的文件系统吞吐量,多扇区写入不要切换成单扇区写入。
Fatfs 支持硬件层的延迟写入,当写入数据存放在写入缓存中或者写入操作正在执行。写入过程不会立即执行。disk_ioctl CTRL_SYNC 发出时,写入操作完整写入,因此,如果延迟写入被实现,硬盘的写入性能将会被优化。
应用不能直接调用该函数,否则,文件系统会崩溃。
QuickInfo
当 _FS_READONLY == 1 时,该函数不需要实现。
五、存储设备属性接口 disk_ioctl
该函数操作一些特定的设备属性和一些除了读写之外的属性。
DRESULT disk_ioctl ( BYTE pdrv, /* [IN] Drive number */ BYTE cmd, /* [IN] Control command code */ void* buff /* [I/O] Parameter and data buffer */ );
Parameters
pdrv:硬盘驱动号码。
cmd:控制代码。
buff:执行控制代码附带的缓冲区。如果不需要参数,该函数可以忽略。
Return Value
RES_OK (0):成功执行。
RES_ERROR:发生错误。
RES_PARERR:控制代码不被支持。
RES_NOTRDY:设备未初始化。
Description
Fatfs 只支持以下五个独立属性。
Command | Description |
CTRL_SYNC | 保证文件系统已经结束挂起写入处理。如果 IO 模块有写入缓存,此时写入缓存必须立即写入。如果在 disk_write 写入操作中直接写入了,就不需要关注该指令。 |
GET_SECTOR_COUNT | 将指定驱动器号的设备的扇区总数返回,返回缓冲区是 DWORD 类型。该指令只会被 f_mkfs 和 f_fdisk 方法调用,去创建新的分区。前提是 _USE_MKFS == 1 或者 _MULTI_PARTITION == 1 |
GET_SECTOR_SIZE | 返回 word 类型的扇区字节数量。支持的返回值是 512,1024,2048 和 4096。该指令只有在打开了可变扇区配置的时候才会被调用,_MAX_SS > _MIN_SS。如果使用以下配置, _MAX_SS == _MIN_SS,该指令不会被调用且只能在指定的扇区大小下工作。 |
GET_BLOCK_SIZE | 返回 flash 类型的存储器中一个 block 中包含的扇区数量,可选返回值 1 到 32768。当使用 norflash 或者未知 block 大小的时候,返回值为 0,该指令只有在 f_mkfs 被调用,或者系统尝试将数据区和擦除块对其的时候调用,前提是 _USE_MKFS == 1。 |
CTRL_TRIM | 通知设备某个 block 的数据不在需要可以被删除调了。扇区号码存储在 DWORD array {<start sector>, <end sector>} pointed by buff。这是一个 ATA 设备支持的特定指令。如果设备不是 flash 或者不支持该接口,该指令什么也不用做。Fatfa 不会检查该指令的返回值,即使擦除失败。该函数在 f_mkfs 方法中移除文件簇链的时候被调用,调用前提 _USE_TRIM == 1。 |
Fatfs 不再使用其他扩展指令或者其他用户定义指令。以下表格显示了一些非标准用户指令。
Command | Description |
CTRL_FORMAT | Create a physical format on the media. If buff is not null, it is pointer to the call-back function for progress notification. |
CTRL_POWER_IDLE | Put the device idle state. STA_NOINIT in the current status flags may not be set if the device goes active state by generic read/write function. |
CTRL_POWER_OFF | Put the device off state. Shut-down the power to the device and deinitialize the device interface if needed. STA_NOINIT in the current status flags must be set. The device goes active state bydisk_initialize function. |
CTRL_LOCK | Lock media eject mechanism. |
CTRL_UNLOCK | Unlock media eject mechanism. |
CTRL_EJECT | Eject media cartridge. STA_NOINIT and STA_NODISK in status flag are set after the function succeeded. |
MMC_GET_TYPE | Get card type. The type flags, bit0:MMCv3, bit1:SDv1, bit2:SDv2+ and bit3:LBA, is stored to a BYTE variable pointed by buff. (MMC/SDC specific command) |
MMC_GET_CSD | Get CSD register into a 16-byte buffer pointed by buff. (MMC/SDC specific command) |
MMC_GET_CID | Get CID register into a 16-byte buffer pointed by buff. (MMC/SDC specific command) |
MMC_GET_OCR | Get OCR register into a 4-byte buffer pointed by buff. (MMC/SDC specific command) |
MMC_GET_SDSTAT | Get SDSTATUS register into a 64-byte buffer pointed by buff. (SDC specific command) |
ATA_GET_REV | Get the revision string into a 16-byte buffer pointed by buff. (ATA/CFC specific command) |
ATA_GET_MODEL | Get the model string into a 40-byte buffer pointed by buff. (ATA/CFC specific command) |
ATA_GET_SN | Get the serial number string into a 20-byte buffer pointed by buff. (ATA/CFC specific command) |
ISDIO_READ | Read a block of iSDIO registers specified by command structure pointed by buff. (FlashAir specific command) |
ISDIO_WRITE | Write a block of data to iSDIO registers specified by command structure pointed by buff.(FlashAir specific command) |
ISDIO_MRITE | Change bits in an iSDIO register specified by command structure pointed by buff. (FlashAir specific command) |
QuickInfo
当 _FS_READONLY == 1 或者 _MAX_SS == _MIN_SS 的时候,该函数不被调用。
六、存储设备获取当前时间 get_fattime
该函数获取当前时间。
DWORD get_fattime (void);
Return Value
在一个 DWORD 类型中返回当前时间。位区间定义如下:
bit31:25,定义年增量,基础值 1980 (0..127)
bit24:21,月份(1..12)
bit20:16,月日期(1..31)
bit15:11,小时(0..23)
bit10:5,分钟(0..59)
bit4:0,秒的一半/ 2 (0..29)
Description
即使系统没有实时时钟,该函数也应该返回一个固定的时间配置。如果返回零,系统文件将没有时间戳。
QuickInfo
当 _FS_READONLY == 1 或者 _FS_NORTC == 1 的时候,不需要该函数。
扫码关注尚为网微信公众号
原创文章,作者:sunev,如若转载,请注明出处:https://www.sunev.cn/embedded/942.html