STM32 Hal库SDIO在FATFS使用下的函数调用关系
本文并不将FATFS的相关接口操作,而是将HAL在使用FATFS通过SDIO外设管理SD卡时,内部函数的调用逻辑,有助于当我们使用CUBEMX生成FATFS读取SD卡的代码时无法运行时Debug。本文也会说明一些可能出现的bug用于参考。
主要对象和变量的说明
接口文件 sd_diskio.c
- 文件
sd_diskio.c
是CUBEMX自动生成的FATFS操作SD卡的接口函数文件,如果没有CubeMX生成的话,一般这个文件是需要我们自己写的。 - 这个文件中有一个全局变量
SD_driver
这个全局变量是底层操作接口的函数集合,Diskio_drvTypeDef
类型。包含的操作函数接口有SD_initialize
、SD_states
、SD_reead
、SD_write
、SD_read
、SD_ioctl
。 - 上面提到的接口函数都调用了
BSP_
开头的函数,这是CubeMX生成的底层直接操作SDIO的函数。
驱动器数组
-
驱动器类型是
Disk_drvTypeDef
在ff_gen_drv.c
文件中有这个类的一个全局变量disk
。 -
typedef struct { uint8_t is_initialized[_VOLUMES]; Diskio_drvTypeDef *drv[_VOLUMES]; uint8_t lun[_VOLUMES]; __IO uint8_t nbr; }Disk_drvTypeDef;
-
这个驱动集合中用多个数组来存放各个驱动器操作函数接口集合
drv
和对应的卷号lun
。而在CubeMX中生成的MX_FATFS_Init
中就将SD_Driver
这个SD卡的接口函数集合变量和卷号0绑定在一起。
函数调用关系图
上面的关系图很清楚的说明各个函数间的调用关系。有些需要注意的地方在下面说明:
-
MX_SDIO_SD_Init
只是对hsd
这个结构体的部分成员作初始化,真正初始化SDIO的动作不在这儿。- 而且这里赋值的
hsd.Init.BusWide
只是中间阶段测试读取一个块大小时参数,并不是最终的参数。所以,这里,这个参数一定要求是SDIO_BUS_WIDE_1B
。 - 如果我们硬件最终设计的是1B/4B/8B的卡的话,直接在CubeMX设置就可以,它会在
BSP_SD_init
最后使用HAL_SD_ConfigWideBusOperation
设置对应运行的SDIO的数据位宽。 - 这里赋值的
hsd.Init.ClockDiv
是 最终运行时SDIO的运行速率。
- 而且这里赋值的
-
真正对SDIO进行初始化的地方是
f_mount
函数调用时,通过数组索引到SD卡驱动接口函数集合SD_Driver
再调用其中的SD_initialize
实现SDIO底层硬件的初始化。所以需要注意,如果我们有任何对SD卡直接的操作,需要放在
f_mount
之后,因为在f_mount
之前,SDIO外设根本还没有开始初始化。 -
由于SD卡在初始化的时候一开始需要以1B位宽低速进行读取和设置,所以
BSP_SD_Init
中使用了三次SDIO外设的初始化SDIO_Init
,具体看上面的关系图即可。