一、使用STM32CUBEMX配置FreeRTOS+SDIO4bit+FATFS注意事项:
以STM32F429为例:
1、SDIO配置
配置为4bit模式,此配置不是最终配置,后面会在代码进行修改。
2、Fatfs配置
Set Defines 选项中的配置可以默认,最重要注意Advanced Setting 选择中的配置,如下
该界面配置默认Use dma template是默认使能的 ,并且不可以选择,只能选择使能,所以需要使能 SDIO中断和SDIO DMA(注意:如果不使能可能会出现问题),如下图所示:
在使能中断之后,注意 SDIO global 中断要小于或者等于SDIO DMA的中断,否则会出现问题
3、FreeRTOS配置
FreeRTOS配置默认即可
配置完成记得把启动文件的堆栈改大一点,如下:
生成代码即可
二、生成代码修改:
找到sdio.c文件中的void MX_SDIO_SD_Init(void)函数,修改如下:
void MX_SDIO_SD_Init(void)
{
/* USER CODE BEGIN SDIO_Init 0 */
/* USER CODE END SDIO_Init 0 */
/* USER CODE BEGIN SDIO_Init 1 */
/* USER CODE END SDIO_Init 1 */
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_4B;
hsd.Init.HardwareFlowControl = SDIO_HARDWARE_FLOW_CONTROL_DISABLE;
hsd.Init.ClockDiv = 4;
/* USER CODE BEGIN SDIO_Init 2 */
//初始化时使用1bit + SDIO_INIT_CLK_DIV初始化时钟频率
hsd.Init.BusWide = SDIO_BUS_WIDE_1B;
hsd.Init.ClockDiv = SDIO_INIT_CLK_DIV;//SDIO_TRANSFER_CLK_DIV;
/* USER CODE END SDIO_Init 2 */
}
经过实际测试,使用最大频率也是可以的,但是初始化时使用1bit+SDIO_INIT_CLK_DIV 初始化时钟频率,防止不必要的错误
在生成的bsp_driver_sd.c文件中找到__weak uint8_t BSP_SD_Init(void)函数,该函数是一个弱函数,可在其他文件复写,如下:
uint8_t BSP_SD_Init(void)
{
uint8_t sd_state = MSD_OK;
/* Check if the SD card is plugged in the slot */
if (BSP_SD_IsDetected() != SD_PRESENT)
{
return MSD_ERROR;
}
/* HAL SD initialization */
sd_state = HAL_SD_Init(&hsd);
/* Configure SD Bus width (4 bits mode selected) */
if (sd_state == MSD_OK)
{
hsd.Init.ClockDiv = SDIO_TRANSFER_CLK_DIV;//改为最大传输频率
/* Enable wide operation */
if (HAL_SD_ConfigWideBusOperation(&hsd, SDIO_BUS_WIDE_4B) != HAL_OK)
{
sd_state = MSD_ERROR;
}
}
return sd_state;
}
由于使用的SD卡支持改频率,所以我采用SDIO_TRANSFER_CLK_DIV最大频率,这里分频根据不同的SD卡可做调整。
我这里是在main.c复写的,到这一步可能会出现HAL_SD_ConfigWideBusOperation(&hsd, SDIO_BUS_WIDE_4B)函数卡死的问题,如果遇到该问题此时我们需要重写几个函数如下:
static uint32_t My_SD_FindSCR(SD_HandleTypeDef *hsd, uint32_t *pSCR)
{
SDIO_DataInitTypeDef config;
uint32_t errorstate;
uint32_t tickstart = HAL_GetTick();
uint32_t index = 0U;
uint32_t tempscr[2U] = {0U, 0U};
uint32_t *scr = pSCR;
uint16_t delay_time;
/* Set Block Size To 8 Bytes */
errorstate = SDMMC_CmdBlockLength(hsd->Instance, 8U);
if(errorstate != HAL_SD_ERROR_NONE)
{
return errorstate;
}
/* Send CMD55 APP_CMD with argument as card's RCA */
errorstate = SDMMC_CmdAppCommand(hsd->Instance, (uint32_t)((hsd->SdCard.RelCardAdd) << 16U));
if(errorstate != HAL_SD_ERROR_NONE)
{
return errorstate;
}
config.DataTimeOut = SDMMC_DATATIMEOUT;
config.DataLength = 8U;
config.DataBlockSize = SDIO_DATABLOCK_SIZE_8B;
config.TransferDir = SDIO_TRANSFER_DIR_TO_SDIO;
config.TransferMode = SDIO_TRANSFER_MODE_BLOCK;
config.DPSM = SDIO_DPSM_ENABLE;
(void)SDIO_ConfigData(hsd->Instance, &config);
//添加延时,等待处琿
for(delay_time = 0; delay_time < 20; delay_time++)
{
__nop();
}
/* Send ACMD51 SD_APP_SEND_SCR with argument as 0 */
errorstate = SDMMC_CmdSendSCR(hsd->Instance);
if(errorstate != HAL_SD_ERROR_NONE)
{
return errorstate;
}
while(!__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_RXOVERR | SDIO_FLAG_DCRCFAIL | SDIO_FLAG_DTIMEOUT))
{
if(__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_RXDAVL))
{
*(tempscr + index) = SDIO_ReadFIFO(hsd->Instance);
index++;
if (index == 2)
break;//因为定义index的时候初始忼是0,但是你们自己追踪下,事实上发鿁这条命令只会返回两个数据, 我的返回的是两个0.而返回两个数据后基本总线就没反映了,成了死循玿
}
else if(!__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_RXACT))
{
break;
}
if((HAL_GetTick() - tickstart) >= SDMMC_DATATIMEOUT)
{
return HAL_SD_ERROR_TIMEOUT;
}
}
if(__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_DTIMEOUT))
{
__HAL_SD_CLEAR_FLAG(hsd, SDIO_FLAG_DTIMEOUT);
return HAL_SD_ERROR_DATA_TIMEOUT;
}
else if(__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_DCRCFAIL))
{
__HAL_SD_CLEAR_FLAG(hsd, SDIO_FLAG_DCRCFAIL);
return HAL_SD_ERROR_DATA_CRC_FAIL;
}
else if(__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_RXOVERR))
{
__HAL_SD_CLEAR_FLAG(hsd, SDIO_FLAG_RXOVERR);
return HAL_SD_ERROR_RX_OVERRUN;
}
else
{
/* No error flag set */
/* Clear all the static flags */
__HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_DATA_FLAGS);
*scr = (((tempscr[1] & SDMMC_0TO7BITS) << 24) | ((tempscr[1] & SDMMC_8TO15BITS) << 8) |\
((tempscr[1] & SDMMC_16TO23BITS) >> 8) | ((tempscr[1] & SDMMC_24TO31BITS) >> 24));
scr++;
*scr = (((tempscr[0] & SDMMC_0TO7BITS) << 24) | ((tempscr[0] & SDMMC_8TO15BITS) << 8) |\
((tempscr[0] & SDMMC_16TO23BITS) >> 8) | ((tempscr[0] & SDMMC_24TO31BITS) >> 24));
}
return HAL_SD_ERROR_NONE;
}
static uint32_t My_SD_WideBus_Enable(SD_HandleTypeDef *hsd)
{
uint32_t scr[2U] = {0U, 0U};
uint32_t errorstate;
if((SDIO_GetResponse(hsd->Instance, SDIO_RESP1) & SDMMC_CARD_LOCKED) == SDMMC_CARD_LOCKED)
{
return HAL_SD_ERROR_LOCK_UNLOCK_FAILED;
}
/* Get SCR Register */
errorstate = My_SD_FindSCR(hsd, scr);
if(errorstate != HAL_SD_ERROR_NONE)
{
return errorstate;
}
/* If requested card supports wide bus operation */
if((scr[1U] & SDMMC_WIDE_BUS_SUPPORT) != SDMMC_ALLZERO)
{
/* Send CMD55 APP_CMD with argument as card's RCA.*/
errorstate = SDMMC_CmdAppCommand(hsd->Instance, (uint32_t)(hsd->SdCard.RelCardAdd << 16U));
if(errorstate != HAL_SD_ERROR_NONE)
{
return errorstate;
}
/* Send ACMD6 APP_CMD with argument as 2 for wide bus mode */
errorstate = SDMMC_CmdBusWidth(hsd->Instance, 2U);
if(errorstate != HAL_SD_ERROR_NONE)
{
return errorstate;
}
return HAL_SD_ERROR_NONE;
}
else
{
return HAL_SD_ERROR_REQUEST_NOT_APPLICABLE;
}
}
static uint32_t My_SD_WideBus_Disable(SD_HandleTypeDef *hsd)
{
uint32_t scr[2U] = {0U, 0U};
uint32_t errorstate;
if((SDIO_GetResponse(hsd->Instance, SDIO_RESP1) & SDMMC_CARD_LOCKED) == SDMMC_CARD_LOCKED)
{
return HAL_SD_ERROR_LOCK_UNLOCK_FAILED;
}
/* Get SCR Register */
errorstate = My_SD_FindSCR(hsd, scr);
if(errorstate != HAL_SD_ERROR_NONE)
{
return errorstate;
}
/* If requested card supports 1 bit mode operation */
if((scr[1U] & SDMMC_SINGLE_BUS_SUPPORT) != SDMMC_ALLZERO)
{
/* Send CMD55 APP_CMD with argument as card's RCA */
errorstate = SDMMC_CmdAppCommand(hsd->Instance, (uint32_t)(hsd->SdCard.RelCardAdd << 16U));
if(errorstate != HAL_SD_ERROR_NONE)
{
return errorstate;
}
/* Send ACMD6 APP_CMD with argument as 0 for single bus mode */
errorstate = SDMMC_CmdBusWidth(hsd->Instance, 0U);
if(errorstate != HAL_SD_ERROR_NONE)
{
return errorstate;
}
return HAL_SD_ERROR_NONE;
}
else
{
return HAL_SD_ERROR_REQUEST_NOT_APPLICABLE;
}
}
HAL_StatusTypeDef My_HAL_SD_ConfigWideBusOperation(SD_HandleTypeDef *hsd, uint32_t WideMode)
{
SDIO_InitTypeDef Init;
uint32_t errorstate;
HAL_StatusTypeDef status = HAL_OK;
/* Check the parameters */
assert_param(IS_SDIO_BUS_WIDE(WideMode));
/* Change State */
hsd->State = HAL_SD_STATE_BUSY;
if(hsd->SdCard.CardType != CARD_SECURED)
{
if(WideMode == SDIO_BUS_WIDE_8B)
{
hsd->ErrorCode |= HAL_SD_ERROR_UNSUPPORTED_FEATURE;
}
else if(WideMode == SDIO_BUS_WIDE_4B)
{
errorstate = My_SD_WideBus_Enable(hsd);
hsd->ErrorCode |= errorstate;
}
else if(WideMode == SDIO_BUS_WIDE_1B)
{
errorstate = My_SD_WideBus_Disable(hsd);
hsd->ErrorCode |= errorstate;
}
else
{
/* WideMode is not a valid argument*/
hsd->ErrorCode |= HAL_SD_ERROR_PARAM;
}
}
else
{
/* MMC Card does not support this feature */
hsd->ErrorCode |= HAL_SD_ERROR_UNSUPPORTED_FEATURE;
}
if(hsd->ErrorCode != HAL_SD_ERROR_NONE)
{
/* Clear all the static flags */
__HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS);
hsd->State = HAL_SD_STATE_READY;
status = HAL_ERROR;
}
else
{
/* Configure the SDIO peripheral */
Init.ClockEdge = hsd->Init.ClockEdge;
Init.ClockBypass = hsd->Init.ClockBypass;
Init.ClockPowerSave = hsd->Init.ClockPowerSave;
Init.BusWide = WideMode;
Init.HardwareFlowControl = hsd->Init.HardwareFlowControl;
Init.ClockDiv = hsd->Init.ClockDiv;
(void)SDIO_Init(hsd->Instance, Init);
}
/* Set Block Size for Card */
errorstate = SDMMC_CmdBlockLength(hsd->Instance, BLOCKSIZE);
if(errorstate != HAL_SD_ERROR_NONE)
{
/* Clear all the static flags */
__HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS);
hsd->ErrorCode |= errorstate;
status = HAL_ERROR;
}
/* Change State */
hsd->State = HAL_SD_STATE_READY;
return status;
}
uint8_t BSP_SD_Init(void)
{
uint8_t sd_state = MSD_OK;
/* Check if the SD card is plugged in the slot */
if (BSP_SD_IsDetected() != SD_PRESENT)
{
return MSD_ERROR;
}
/* HAL SD initialization */
sd_state = HAL_SD_Init(&hsd);
/* Configure SD Bus width (4 bits mode selected) */
if (sd_state == MSD_OK)
{
hsd.Init.ClockDiv = SDIO_TRANSFER_CLK_DIV;//
/* Enable wide operation */
if (My_HAL_SD_ConfigWideBusOperation(&hsd, SDIO_BUS_WIDE_4B) != HAL_OK)
{
sd_state = MSD_ERROR;
}
}
return sd_state;
}
此时,卡死问题就会解决。文章来源:https://www.toymoban.com/news/detail-676261.html
进行实际读写测试:
调试发现能够正常读写,本次分享到此结束。文章来源地址https://www.toymoban.com/news/detail-676261.html
到了这里,关于STM32使用STM32CUBEMX配置FreeRTOS+SDIO4bit+FATFS注意事项的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!