首先配置USB为Mass Storage Class,配置SDIO为 SD 4 bits wide bus。
这里我使用了FreeRTOS和FATFS,用不用和本例无关。有一个坑,就是SDIO的配置界面,MX软件建议不设分频,但这里需要慎重,SDIOCLK的分频要按照自己硬件板子的情况设置,我用的某型号开发板,如果用最高频率,会出现TF卡读写不稳定,设置一下分频才好。
设置完毕,生成代码和工程。打开工程,在usbd_storage_if.c文件里配置TF卡(SD卡)的基本IO操作。
在文件开头加入
#define BLOCK_SIZE 512
extern SD_HandleTypeDef hsd;
extern HAL_SD_CardInfoTypedef SDCardInfo;
注意!上面这三行就算写到USER CODE BEGIN... 和USER CODE END...的保护区里MX重新生成貌似也会被自动抹掉。
填充如下函数
int8_t STORAGE_GetCapacity_FS (uint8_t lun, uint32_t *block_num, uint16_t *block_size)
{
/* USER CODE BEGIN 3 */
HAL_SD_Get_CardInfo(&hsd, &SDCardInfo);
*block_num = SDCardInfo.CardCapacity / BLOCK_SIZE;
*block_size = BLOCK_SIZE;
return (USBD_OK);
/* USER CODE END 3 */
}
int8_t STORAGE_Read_FS (uint8_t lun,
uint8_t *buf,
uint32_t blk_addr,
uint16_t blk_len)
{
/* USER CODE BEGIN 6 */
HAL_SD_ReadBlocks(&hsd, (uint32_t*)buf, (uint64_t)(blk_addr * BLOCK_SIZE), BLOCK_SIZE, blk_len);
return (USBD_OK);
/* USER CODE END 6 */
}
int8_t STORAGE_Write_FS (uint8_t lun,
uint8_t *buf,
uint32_t blk_addr,
uint16_t blk_len)
{
/* USER CODE BEGIN 7 */
HAL_SD_WriteBlocks(&hsd, (uint32_t*)buf, (uint64_t)(blk_addr * BLOCK_SIZE), BLOCK_SIZE, blk_len);
return (USBD_OK);
/* USER CODE END 7 */
}
还有一个需要注意的,就是生成的代码中sdio.c文件里有个问题需要手工改
void MX_SDIO_SD_Init(void)
{
hsd.Instance = SDIO;
hsd.Init.ClockEdge = SDIO_CLOCK_EDGE_RISING;
hsd.Init.ClockBypass = SDIO_CLOCK_BYPASS_DISABLE;
hsd.Init.ClockPowerSave = SDIO_CLOCK_POWER_SAVE_DISABLE;
hsd.Init.BusWide = SDIO_BUS_WIDE_1B;
hsd.Init.HardwareFlowControl = SDIO_HARDWARE_FLOW_CONTROL_ENABLE;
hsd.Init.ClockDiv = 2;
}
这里的
hsd.Init.HardwareFlowControl = SDIO_HARDWARE_FLOW_CONTROL_ENABLE;
这句话生成出来的时候是disable的(然而在MX的图形界面中并没有发现怎么配置这段话),要人工改成enable,否则读写会不稳定。另,每一次MX重新生成,这里的enable又会被自动的改回去,老坑爹了。
到此,所有配置完成。
最后说下MX的另一个bug,就是使用FreeRTOS的时候HAL_Delay函数无法使用,最后发现原因是 stm32f1xx_it.c 文件中的SysTick_Handler
只加入了osSystickHandler()没加入HAL_IncTick(),把后者加入就好了。
MX的bug比教程还多。。。ST的攻城狮们可长点心吧。。。