cancel
Showing results for 
Search instead for 
Did you mean: 

STM32H743-EVAL SDMMC CMD12 no response from SD card

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)?

3 REPLIES 3

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

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

Hello!

I have same problem.

Can you share correct code for HAL_SD_IRQHandler() here ?

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 */
  }
}