RX overrun error when reading blocks from uSD card using HAL driver.
I am using a custom board which includes a uSD that is interfaced to a STM32F765 through the SDMMC1 pins. The clock rate is set to 48 MHz. I am using the stm32f7xx_hal_sd driver to read and write to an uSD card.
I initialize the driver with a call to the HAL_SD_Init routine. I am able to read the card information from the uSD card using the HAL_SD_GetCardInfo routine. It returns the information shown in the attached screen shot.
When I attempt to read a single block from sector #0 of the uSD card with a call to the HAL_SD_ReadBlocks routine, the read operation terminates with a SDMMC_FLAG_RXOVERR (RX FIFO overrun error) after it reads 64 bytes from the FIFO (which I guess is the size of the FIFO). The suspect portion of the driver code is shown below:
/* Poll on SDMMC flags */
while(!__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_RXOVERR | SDMMC_FLAG_DCRCFAIL | SDMMC_FLAG_DTIMEOUT | SDMMC_FLAG_DATAEND))
{
if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_RXFIFOHF))
{
/* Read data from SDMMC Rx FIFO */
for(count = 0U; count < 8U; count++)
{
*(tempbuff + count) = SDMMC_ReadFIFO(hsd->Instance);
}
tempbuff += 8U;
}
if((Timeout == 0U)||((HAL_GetTick()-tickstart) >= Timeout))
{
/* Clear all the static flags */
__HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
hsd->ErrorCode |= HAL_SD_ERROR_TIMEOUT;
hsd->State= HAL_SD_STATE_READY;
return HAL_TIMEOUT;
}
}
/* Send stop transmission command in case of multiblock read */
if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_DATAEND) && (NumberOfBlocks > 1U))
{
if(hsd->SdCard.CardType != CARD_SECURED)
{
/* Send stop transmission command */
errorstate = SDMMC_CmdStopTransfer(hsd->Instance);
if(errorstate != HAL_SD_ERROR_NONE)
{
/* Clear all the static flags */
__HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
hsd->ErrorCode |= errorstate;
hsd->State = HAL_SD_STATE_READY;
return HAL_ERROR;
}
}
}
/* Get error state */
if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_DTIMEOUT))
{
/* Clear all the static flags */
__HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
hsd->ErrorCode |= HAL_SD_ERROR_DATA_TIMEOUT;
hsd->State = HAL_SD_STATE_READY;
return HAL_ERROR;
}
else if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_DCRCFAIL))
{
/* Clear all the static flags */
__HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
hsd->ErrorCode |= HAL_SD_ERROR_DATA_CRC_FAIL;
hsd->State = HAL_SD_STATE_READY;
return HAL_ERROR;
}
else if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_RXOVERR))
{
/* Clear all the static flags */
__HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
hsd->ErrorCode |= HAL_SD_ERROR_RX_OVERRUN;
hsd->State = HAL_SD_STATE_READY;
return HAL_ERROR;
}
I have examined the read buffer pointer (tempbuff) and it is advanced by 64 bytes so the code in the driver that reads from the FIFO is being executed which would suggest that the FIFO is being emptied.
The only thing that I can think of is that the receive FIFO is not being emptied as quickly as it is being filled and so it is overrun.
I have not yet tried reducing the SDMMC clock frequency to slow the transfer down.
I am running the code in debug mode.
Any ideas would be helpful.
