使用STM32CUBEMX生成USB Mass Storage程式碼,通過SDIO讀寫TF卡
阿新 • • 發佈:2019-01-12
首先配置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的攻城獅們可長點心吧。。。