2018-09-10 6:13 AM
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)?
2018-09-10 7:32 AM
Correct, shouldn't need a stop for single block transfers.
2018-10-22 10:51 PM
Hello!
I have same problem.
Can you share correct code for HAL_SD_IRQHandler() here ?
2018-10-29 12:29 AM
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 */
  }
}