Skip to main content
oleksandr.karbivsky
Senior II
September 10, 2018
Question

STM32H743-EVAL SDMMC CMD12 no response from SD card

  • September 10, 2018
  • 2 replies
  • 1243 views

Hi. I have created app with SDMMC+FreeRTOS+FatFS for STM32H743 Eval board using CubeMX 4.26.1 and STM32CubeH7 Firmware Package V1.3.0 . And found some weird thing: every time when f_write function called also called funcction HAL_SD_ErrorCallback with error code SDMMC_ERROR_CMD_RSP_TIMEOUT.

This happened when HAL SD driver send STOP TRANSMISSION command after WRITE SINGLE BLOCK complete. In code this is line 1460 in stm32h7xx_hal_sd.c file:

/* Stop Transfer for Write Single/Multi blocks or Read Multi blocks */
 if((context & SD_CONTEXT_READ_SINGLE_BLOCK) == 0U)
 {
 errorstate = SDMMC_CmdStopTransfer(hsd->Instance);
 if(errorstate != HAL_SD_ERROR_NONE)
 {
 hsd->ErrorCode |= errorstate;
 HAL_SD_ErrorCallback(hsd);
 }
 }

SD card continue work fine, but spend time for handling this command.

Maybe don't need send STOP TRANSMISSION command (CMD12) after WRITE SINGLE BLOCK command (CMD24)?

This topic has been closed for replies.

2 replies

Tesla DeLorean
Guru
September 10, 2018

Correct, shouldn't need a stop for single block transfers.

Tips, Buy me a coffee, or three.. PayPal VenmoUp vote any posts that you find helpful, it shows what's working..
Andrew1
Associate II
October 23, 2018

Hello!

I have same problem.

Can you share correct code for HAL_SD_IRQHandler() here ?

oleksandr.karbivsky
Senior II
October 29, 2018

Hi. This is my handler for SDMMC1. I use only DMA transfer.

void SDMMC1_Handler(void)
{
 SD_HandleTypeDef* hsd = &hsd1;
 
 uint32_t errorstate;
 uint32_t context = hsd->Context;
 
 /* Check for SDMMC interrupt flags */
 if(__HAL_SD_GET_FLAG(hsd, SDMMC_IT_DATAEND) != RESET) // End data transfer
 {
 __HAL_SD_CLEAR_FLAG(hsd, SDMMC_FLAG_DATAEND);
 
 __HAL_SD_DISABLE_IT(hsd, SDMMC_IT_DATAEND | SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT |\
 SDMMC_IT_TXUNDERR | SDMMC_IT_RXOVERR | SDMMC_IT_TXFIFOHE |\
 SDMMC_IT_RXFIFOHF);
 
 __HAL_SD_DISABLE_IT(hsd, SDMMC_IT_IDMABTC);
 __SDMMC_CMDTRANS_DISABLE( hsd->Instance);
 
 if((context & SD_CONTEXT_DMA) != 0U)
 {
 hsd->Instance->DLEN = 0;
 hsd->Instance->DCTRL = 0;
 hsd->Instance->IDMACTRL = SDMMC_DISABLE_IDMA;
 
 /* Stop Transfer for Write Single/Multi blocks or Read Multi blocks */
 if((context & (SD_CONTEXT_WRITE_MULTIPLE_BLOCK|SD_CONTEXT_READ_MULTIPLE_BLOCK)) != 0U)
 {
 errorstate = SDMMC_CmdStopTransfer(hsd->Instance);
 if(errorstate != HAL_SD_ERROR_NONE)
 {
 hsd->ErrorCode |= errorstate;
 HAL_SD_ErrorCallback(hsd);
 }
 }
 
 hsd->State = HAL_SD_STATE_READY;
 if(((context & SD_CONTEXT_WRITE_SINGLE_BLOCK) != 0U) || ((context & SD_CONTEXT_WRITE_MULTIPLE_BLOCK) != 0U))
 {
 HAL_SD_TxCpltCallback(hsd);
 }
 if(((context & SD_CONTEXT_READ_SINGLE_BLOCK) != 0U) || ((context & SD_CONTEXT_READ_MULTIPLE_BLOCK) != 0U))
 {
 HAL_SD_RxCpltCallback(hsd);
 }
 }
 else
 {
 /* Nothing to do */
 }
 }
 else if(__HAL_SD_GET_FLAG(hsd, SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT | SDMMC_IT_RXOVERR | SDMMC_IT_TXUNDERR) != RESET) 
 {
 /* Set Error code */
 if(__HAL_SD_GET_FLAG(hsd, SDMMC_IT_DCRCFAIL) != RESET)
 {
 hsd->ErrorCode |= HAL_SD_ERROR_DATA_CRC_FAIL;
 }
 if(__HAL_SD_GET_FLAG(hsd, SDMMC_IT_DTIMEOUT) != RESET)
 {
 hsd->ErrorCode |= HAL_SD_ERROR_DATA_TIMEOUT;
 }
 if(__HAL_SD_GET_FLAG(hsd, SDMMC_IT_RXOVERR) != RESET)
 {
 hsd->ErrorCode |= HAL_SD_ERROR_RX_OVERRUN;
 }
 if(__HAL_SD_GET_FLAG(hsd, SDMMC_IT_TXUNDERR) != RESET)
 {
 hsd->ErrorCode |= HAL_SD_ERROR_TX_UNDERRUN;
 }
 
 /* Clear All flags */
 __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_DATA_FLAGS);
 
 /* Disable all interrupts */
 __HAL_SD_DISABLE_IT(hsd, SDMMC_IT_DATAEND | SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT|\
 SDMMC_IT_TXUNDERR| SDMMC_IT_RXOVERR);
 
 __SDMMC_CMDTRANS_DISABLE( hsd->Instance);
 hsd->Instance->DCTRL |= SDMMC_DCTRL_FIFORST;
 hsd->Instance->CMD |= SDMMC_CMD_CMDSTOP;
 hsd->ErrorCode |= SDMMC_CmdStopTransfer(hsd->Instance);
 hsd->Instance->CMD &= ~(SDMMC_CMD_CMDSTOP);
 __HAL_SD_CLEAR_FLAG(hsd, SDMMC_FLAG_DABORT);
 
 if((context & SD_CONTEXT_DMA) != 0U)
 {
 if(hsd->ErrorCode != HAL_SD_ERROR_NONE)
 {
 /* Disable Internal DMA */
 __HAL_SD_DISABLE_IT(hsd, SDMMC_IT_IDMABTC);
 hsd->Instance->IDMACTRL = SDMMC_DISABLE_IDMA;
 
 /* Set the SD state to ready to be able to start again the process */
 hsd->State = HAL_SD_STATE_READY;
 HAL_SD_ErrorCallback(hsd);
 }
 }
 else
 {
 /* Nothing to do */
 }
 }
 else
 {
 /* Nothing to do */
 }
}