2018-09-10 06: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 07: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 */
}
}