2017-07-05 01:53 AM
While using SDMMC with FatFS to interface with SDCards occasionally I get Command Timeout when issuing:
SDMMC_CmdReadSingleBlock
This is when using new 1.7.0 drivers. Did anyone experience similar issue?
2017-07-05 08:47 AM
Hi
Hockuba.Krzyszto.002
,I recommend you to use the latest STM32CubeL4 v1.8.1 and have a look into
FatFs_uSD
example for your board, this will help you to develop your application:STM32Cube_FW_L4_V1.8.1\Projects\STM32L496G-Discovery\Applications\FatFs\FatFs_uSD
With Regards
Imen
2017-07-05 01:05 PM
Hi
I'm indeed using latest 1.8.1 and had a look at examples. This doesn't really help and microcontroller still ends up occasionallyin Command Timeout. Only using taskENTER_CRITICAL(); as well as taskEXIT_CRITICAL(); 'solves' the problem the Read Single Block command becomes:uint32_t SDMMC_CmdReadSingleBlock(SDMMC_TypeDef *SDMMCx, uint32_t ReadAdd){ SDMMC_CmdInitTypeDef sdmmc_cmdinit; uint32_t errorstate = SDMMC_ERROR_NONE; /* Set Block Size for Card */ sdmmc_cmdinit.Argument = (uint32_t)ReadAdd; sdmmc_cmdinit.CmdIndex = SDMMC_CMD_READ_SINGLE_BLOCK; sdmmc_cmdinit.Response = SDMMC_RESPONSE_SHORT; sdmmc_cmdinit.WaitForInterrupt = SDMMC_WAIT_NO; sdmmc_cmdinit.CPSM = SDMMC_CPSM_ENABLE; taskENTER_CRITICAL(); SDMMC_SendCommand(SDMMCx, &sdmmc_cmdinit); /* Check for error conditions */ errorstate = SDMMC_GetCmdResp1(SDMMCx, SDMMC_CMD_READ_SINGLE_BLOCK, SDMMC_CMDTIMEOUT); taskEXIT_CRITICAL(); return errorstate;}�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?
This bug can be reproduced by placing interrupt at command which is on line 13 above on unmodified code and going step by step into next function. SDMMC_GetCmdResp1 will timeout every time in my case, when in runtime application timeouts only occasionally,I can't really say when exactly and what is happening in between. But clearly looks like peripheral is missing the response from SD Card.
2017-07-05 05:05 PM
Ok after some time I found a bug. I'm running FreeRTOS with a couple of tasks so overall we have a pretty complex system. Becuase DMA transfer is very quick and happens independently to the system, DMA interrupt can occur before the command can read a response.
SD_DMAReceiveCplt callback clears out all static flags which result in CMDREND flag being cleared before SDMMC_GetCmdResp1 can read it. Not sure how ST sees it but in my humble opinion this is a bug. This doesn't concern DMA Write because the command is issued before the transfer starts. This bug was actually introduced after SD drivers rewrite.
2017-07-12 09:01 AM
DAHMEN.IMEN
I would like for someone from ST to comment on my observations as It seems that read operation while using DMA is non-atomic and can run into timeout while in fact, it was successful.2017-07-26 05:13 AM
Hi Imen,
I have reproduced the same issue.
SDMMC_CmdReadSingleBlock() and SDMMC_CmdSendStatus() functions often end with timeout on our complex system with FreeRTOS, multiple interrupts and DMA channels used.
It did not happen in previous versions of HAL library. I have tested it on the same hardware, so no hardware issue here.I request, that ST investigates this issue.
Regards,
Tomasz2017-08-13 03:20 PM
I am using HAL library (no FreeRTOS or any other OS). Following code stuck in
SDMMC_GetCmdResp1 function if HAL_Delay(1) is commented. Although I am not sure about that. But when i disabled SDIO global interrupt, then problem did not occured.It seems that HAL_SD_IRQHandler somehow interacts with DMA operation. I do not use any interrupts/callbacks for SDIO.
With
SDIO global interrupt disabled i have an another problem, now for write operation: after calling HAL_SD_WriteBlocks_DMA function HAL_SD_GetCardState never returns HAL_SD_CARD_TRANSFER value and stuck with endlessly returningHAL_SD_CARD_RECEIVING.
Any Ideas?
ch=HAL_SD_ReadBlocks_DMA(&hsd, (uint8_t*)&tmpBuffer, sdaddr, 32);
comSend((uint8_t *)&ch,1);
while (1)
{
ch=HAL_SD_GetCardState(&hsd);
if (ch==HAL_SD_CARD_TRANSFER) break;
// HAL_Delay(1);
}�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?
2017-08-14 09:46 AM
This is irrelevant to the topi but I will answer it, obviously when using DMA use interrupts with SDIO interrupt having higher priority than DMA interrupt for SDIO peripheral. Before each transfer you need to configure DMA accordingly (transfer direction - memory to periph or periph to men). Lastly don’t use pooling to check if transfer finished use callbacks and then execute function getcardstate. Read manual for SDIO you will understand why you need to do all above.
2017-08-29 05:41 AM
I've seen the exact same issue. It seems ST needs to fix this in STM32CubeMX. RIght now I've commented out the following line in SD_DMAReceiveCplt():
__HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
I'm sure this is not the perfect solution, but it works for now
2017-08-29 08:11 AM
I'm happy you are optimistic but it has been almost 2 months now and still, no one replied fromST Engineers to comment on this issue. I modified ReciveCplt in this way so it leaves flags that CMD Resp checks and clears rest of them.
/**
* @brief DMA SD receive process complete callback
* @param hdma: DMA handle
* @retval None
*/
static void SD_DMAReceiveCplt(DMA_HandleTypeDef *hdma)
{
SD_HandleTypeDef* hsd = (SD_HandleTypeDef* )(hdma->Parent);
uint32_t errorstate = HAL_SD_ERROR_NONE;
/* Send stop command in multiblock write */
if(hsd->Context == (SD_CONTEXT_READ_MULTIPLE_BLOCK | SD_CONTEXT_DMA))
{
errorstate = SDMMC_CmdStopTransfer(hsd->Instance);
if(errorstate != HAL_SD_ERROR_NONE)
{
hsd->ErrorCode |= errorstate;
HAL_SD_ErrorCallback(hsd);
}
}
/* Disable the DMA transfer for transmit request by setting the DMAEN bit
in the SD DCTRL register */
hsd->Instance->DCTRL &= (uint32_t)~((uint32_t)SDMMC_DCTRL_DMAEN);
/* Check current state of Command Register and don't clear those flags */
if (hsd->Context == (SD_CONTEXT_READ_SINGLE_BLOCK | SD_CONTEXT_DMA))
{
if (__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_CMDREND)) {
/* Clear only selected flags */
__HAL_SD_CLEAR_FLAG(hsd, ((uint32_t)(SDMMC_FLAG_DCRCFAIL | SDMMC_FLAG_DTIMEOUT |
SDMMC_FLAG_TXUNDERR | SDMMC_FLAG_RXOVERR |
SDMMC_FLAG_CMDSENT | SDMMC_FLAG_DATAEND | SDMMC_FLAG_DBCKEND)));
} else {
/* Clear all the static flags */
__HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
}
}
else
{
/* Clear all the static flags */
__HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
}
hsd->State = HAL_SD_STATE_READY;
HAL_SD_RxCpltCallback(hsd);
}�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?