cancel
Showing results for 
Search instead for 
Did you mean: 

STM32H750 SDMMC & IDMA issue

Robertson.Jamie
Associate II

I have code running on an STM32H750 which uses the HAL drivers to stream audio from a microSD (SDMMC + IDMA) to a DAC (SAI + DMA). I’m doing mostly mostly 16-sector reads, at a rate of about 300 reads per second (28 16-sector reads every 93 ms). The card handles this easily with a 50MHz bus speed. I’m using sine-wave audio data and monitoring the output with a spectrum analyzer so that any issues show up easily.

All reads are using AXI memory, and I have an MPU region enabled properly for this memory and am doing cache management, as I have done successfully with other STM32 processors. Everything works great with one exception.

My issue is that about once every hour or two (or more), the HAL_SD_ReadBlocks_DMA() function times out. By “times out�?, I mean that the read multi-block command is sent and a correct response is received, but the subsequent interrupt never occurs, and the code waiting for the read completion (by checking a flag cleared in the SD interrupt), times out.

The HAL function calls SDMMC_CmdReadMultiBlock() which in turn calls SDMMC_SendCommand() followed by SDMMC_GetCmdResp1(); I’ve instrumented the code to preserve the value of the SDMMC Status register on the occasions when the command times out, and there’s nothing unusual to be seen.

Most interesting, I’ve discovered if I insert even a small delay between the SDMMC_SendCommand() and the SDMMC_GetCmdResp1() functions, I can get the command to time out in exactly the same manner almost immediately. The call to SDMMC_GetCmdResp1() normally immediately follows the call to SDMMC_SendCommand(), so if a delay between them causes this condition, then I would imagine that if another interrupt were to happen right at this point, this could be an issue. I tried disabling the SAI DMA interrupts around these calls, but it didn’t seem to help.

I’ve read through the errata, and don’t see anything that applies here. It seems odd that a small delay between sending a command and checking the response would cause a problem.

Wondering if anyone here has insights.

1 ACCEPTED SOLUTION

Accepted Solutions
Robertson.Jamie
Associate II

I found the problem, and would like to pass along what appears to be a bug in the CubeMX-generated file, "sd_diskio.c". The issue is in the SD_Read() function:

/**
  * @brief  Reads Sector(s)
  * @param  lun : not used
  * @param  *buff: Data buffer to store read data
  * @param  sector: Sector address (LBA)
  * @param  count: Number of sectors to read (1..128)
  * @retval DRESULT: Operation result
  */
              
DRESULT SD_read(BYTE lun, BYTE *buff, DWORD sector, UINT count)
{
  DRESULT res = RES_ERROR;
  uint32_t timeout;
#if defined(ENABLE_SCRATCH_BUFFER)
  uint8_t ret;
#endif
#if (ENABLE_SD_DMA_CACHE_MAINTENANCE == 1)
  uint32_t alignedAddr;
#endif
 
  /*
  * ensure the SDCard is ready for a new operation
  */
 
  if (SD_CheckStatusWithTimeout(SD_TIMEOUT) < 0)
  {
    return res;
  }
 
#if defined(ENABLE_SCRATCH_BUFFER)
  if (!((uint32_t)buff & 0x3))
  {
#endif
    if(BSP_SD_ReadBlocks_DMA((uint32_t*)buff,
                             (uint32_t) (sector),
                             count) == MSD_OK)
    {
      ReadStatus = 0;
      /* Wait that the reading process is completed or a timeout occurs */
      timeout = HAL_GetTick();
      while((ReadStatus == 0) && ((HAL_GetTick() - timeout) < SD_TIMEOUT))
      {
      }
      /* incase of a timeout return error */
      if (ReadStatus == 0)
      {
        res = RES_ERROR;
      }
      else
      {
        ReadStatus = 0;
        timeout = HAL_GetTick();

ReadStatus is set to 0 AFTER the call to BSP_SD_ReadBlocks_DMA(). The action of BSP_SD_ReadBlocks() is to issue the read command and kick off the interrupt when the read is completed, which in turn sets ReadStatus to 1, indicating completion. You can see the problem: Occasionally this all occurs before the following line which sets ReadStatus to 0, hence it never subsequently gets set, since the interrupt has already occurred. The solution is to move this line to the top of the function.

There's a similar potential with the SD_write() function, but the corresponding WriteStatus = 0 is set at the top of that function where it belongs.

Hope this helps others avoid a problem.

View solution in original post

5 REPLIES 5
Robertson.Jamie
Associate II

I found the problem, and would like to pass along what appears to be a bug in the CubeMX-generated file, "sd_diskio.c". The issue is in the SD_Read() function:

/**
  * @brief  Reads Sector(s)
  * @param  lun : not used
  * @param  *buff: Data buffer to store read data
  * @param  sector: Sector address (LBA)
  * @param  count: Number of sectors to read (1..128)
  * @retval DRESULT: Operation result
  */
              
DRESULT SD_read(BYTE lun, BYTE *buff, DWORD sector, UINT count)
{
  DRESULT res = RES_ERROR;
  uint32_t timeout;
#if defined(ENABLE_SCRATCH_BUFFER)
  uint8_t ret;
#endif
#if (ENABLE_SD_DMA_CACHE_MAINTENANCE == 1)
  uint32_t alignedAddr;
#endif
 
  /*
  * ensure the SDCard is ready for a new operation
  */
 
  if (SD_CheckStatusWithTimeout(SD_TIMEOUT) < 0)
  {
    return res;
  }
 
#if defined(ENABLE_SCRATCH_BUFFER)
  if (!((uint32_t)buff & 0x3))
  {
#endif
    if(BSP_SD_ReadBlocks_DMA((uint32_t*)buff,
                             (uint32_t) (sector),
                             count) == MSD_OK)
    {
      ReadStatus = 0;
      /* Wait that the reading process is completed or a timeout occurs */
      timeout = HAL_GetTick();
      while((ReadStatus == 0) && ((HAL_GetTick() - timeout) < SD_TIMEOUT))
      {
      }
      /* incase of a timeout return error */
      if (ReadStatus == 0)
      {
        res = RES_ERROR;
      }
      else
      {
        ReadStatus = 0;
        timeout = HAL_GetTick();

ReadStatus is set to 0 AFTER the call to BSP_SD_ReadBlocks_DMA(). The action of BSP_SD_ReadBlocks() is to issue the read command and kick off the interrupt when the read is completed, which in turn sets ReadStatus to 1, indicating completion. You can see the problem: Occasionally this all occurs before the following line which sets ReadStatus to 0, hence it never subsequently gets set, since the interrupt has already occurred. The solution is to move this line to the top of the function.

There's a similar potential with the SD_write() function, but the corresponding WriteStatus = 0 is set at the top of that function where it belongs.

Hope this helps others avoid a problem.

Hello @Robertson.Jamie​ 

Thanks for the feedback, issue reported to the tool development team that will plan the correction.

Best regards,

Nesrine

Hi,I am desperate to find a solution about the usb_device MSC sd card driver problem.I wonder if it's a bug?

my HAL Driver Version is 1.8.0,cubemx version is 5.6.1. my MCU is stm32h743. I generate a MSC project with cubemx,in usbd_storage_if.c file,there are STORAGE_Read_FS and STORAGE_Write_FS functions,as the picture shows,

The first problem is if I use BSP_SD_WriteBlocks and BSP_SD_ReadBlocks,the project is working while using BSP_SD_WriteBlocks_DMA and BSP_SD_ReadBlocks_DMA fail,I have took aligned and cache in consideration,but it is still not working.Can not enter the SDMMC1_IRQHandler() interrupt.

The second problem is that the project is not working when open Dcache,no matter using BSP_SD_WriteBlocks or BSP_SD_ReadBlocks_DMA.

In sum,it only working when Dcache is closing and DMA is not use.

I hope you might spare your time and help me out,thanks a lot.:rainbow:

0693W000003PJYdQAO.png

0693W000003PJXzQAO.png

0693W000003PJY4QAO.png

0693W000003PJY9QAO.png

0693W000003PJYEQA4.png

Hi @Rdazx.1​ ,

Is this a different problem than what you are reporting in https://community.st.com/s/question/0D53W00000FNYop?

In all cases, it is preferable to keep only one topic per thread.

Coming back to your issue: did you tried to apply the fix suggested by @Robertson.Jamie​  here?

-Amel

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

Thank you for your apply.The MSC sd Driver problem that I encounted might be a little different from @Robertson.Jamie 's problem mentioned above,It just confuse me that why it won't work when I open the Dache and not using IDMA function.I have generate a fatfs sd project,it is working anyway with Dache and IDMA.So I wonder if there is a bug in USB MSC,not sd HAL Driver.Thanks.