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

This discussion is locked. Please start a new topic to ask your question.
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 */
  }
}