2020-02-12 12:33 AM
Hello!
I have a trouble with Timout delay in SDMMC_GetCmdResp1. I invoke HAL_SD_Init from freertos task. Now SD card isn't connected to board. Timout deleay take approximately 30 seconds, but Timout is 5000 ms.
static uint32_t SDMMC_GetCmdResp1(SDMMC_TypeDef *SDMMCx, uint8_t SD_CMD, uint32_t Timeout)
{
uint32_t response_r1;
uint32_t sta_reg;
/* 8 is the number of required instructions cycles for the below loop statement.
The Timeout is expressed in ms */
register uint32_t count = Timeout * (SystemCoreClock / 8U /1000U);
do
{
if (count-- == 0U)
{
return SDMMC_ERROR_TIMEOUT;
}
sta_reg = SDMMCx->STA;
}while(((sta_reg & (SDMMC_FLAG_CCRCFAIL | SDMMC_FLAG_CMDREND | SDMMC_FLAG_CTIMEOUT | SDMMC_FLAG_BUSYD0END)) == 0U) ||
((sta_reg & SDMMC_FLAG_CMDACT) != 0U ));
My guess is this code doesn't work correctly within FreeRTOS task due to interrupts.
To test this theory I've wrapped code in question with __set_PRIMASK and delay was reduced to 15s (code below)
register uint32_t count = Timeout * (SystemCoreClock / 8U /1000U);
__set_PRIMASK(1); // disable interrupts
do
{
if (count-- == 0U)
{
return SDMMC_ERROR_TIMEOUT;
}
sta_reg = SDMMCx->STA;
}while(((sta_reg & (SDMMC_FLAG_CCRCFAIL | SDMMC_FLAG_CMDREND | SDMMC_FLAG_CTIMEOUT | SDMMC_FLAG_BUSYD0END)) == 0U) ||
((sta_reg & SDMMC_FLAG_CMDACT) != 0U ));
__set_PRIMASK(0); // enable interrupts
I decide it using HAL_GetTick().
static uint32_t SDMMC_GetCmdResp1(SDMMC_TypeDef *SDMMCx, uint8_t SD_CMD, uint32_t Timeout)
{
uint32_t response_r1;
uint32_t sta_reg;
uint32_t time;
/* 8 is the number of required instructions cycles for the below loop statement.
The Timeout is expressed in ms */
//register uint32_t count = Timeout * (SystemCoreClock / 10U /1000U);
time = HAL_GetTick() + Timeout;
do
{
if (time < HAL_GetTick())
{
return SDMMC_ERROR_TIMEOUT;
}
sta_reg = SDMMCx->STA;
}while(((sta_reg & (SDMMC_FLAG_CCRCFAIL | SDMMC_FLAG_CMDREND | SDMMC_FLAG_CTIMEOUT | SDMMC_FLAG_BUSYD0END)) == 0U) ||
((sta_reg & SDMMC_FLAG_CMDACT) != 0U ));
Bonus: I have disassembled this code and counted 9 instructions instead of 8 (as written in the comment). below is the image
Disassembler: