cancel
Showing results for 
Search instead for 
Did you mean: 

RX overrun error when reading blocks from uSD card using HAL driver.

BitBanger46
Associate III

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.

5 REPLIES 5
chaaalyy
Senior II

Two years ago, i also was struggling around with buggy sd card drivers and so on. I took a quick look, how i worked around the problems: Using SDMMC in 1 bit mode, everytime i wanted to read or write something i did it so:

{

   uint32_t prim;

   prim = __get_PRIMASK();

   __disable_irq();   //for Compatibility safe FileRead

// here do your file i/o stuff...

   if (!prim) {

      __enable_irq();   // Re-Enable IRQ´s

   }   

}

Maybe give it a try ...

/Charly

BitBanger46
Associate III

After many hours of research and reviewing community posts, I determined that the problem was related to the speed of the SDMMC clock which was running at 48 MHz. By changing the clock divider (hsd1.Init.ClockDiv) from 0 to 3, the resulting SDMMC clock was slowed to 16 MHz. The slower clock speed allowed the firmware enough time to empty the FIFO before it overran!! I would strongly recommend that the SDMMC be configured with a clock speed of 16 MHz or lower to avoid these kinds of problems!!

Piranha
Chief II

For a high performance transfers DMA should be used.

FGome.1
Associate

Hi I am having the same problem with STM32H7 with a BUS_WIDE=4 + DMA. I have tried to change the clock to different low speeds without success.

I know the problem is the FIFO because I get and overrun error similar to SStar.1. I've checked the set up of the SD card and is correct because I managed to make it work a 1 Bus 150 kHz without DMA.

I also checked data passing throughout the channels and all looks correct. I don't know if you can share with me other tricks that you did see if I am not missing something.

0693W000003PeH9QAK.png 

Regarding the DMA I am using a MDMA for the SDMMC

0693W000003PeHEQA0.png 

I also followed the advice of this link to change the SD_read/write on the sd_diskio to make sure the DMA readblocks is called.

Any help would be great.

Thanks !!

SPoor.1
Associate

Last time I encountered this issue I changed SDMMC clock divide factor from 0 to 3 and it worked for me.