cancel
Showing results for 
Search instead for 
Did you mean: 

SDMMC with Internal (I)DMA + FATFS with DMA Template - not working! [STM32H7]

Mohammed Eshaq
Associate III

Hi, everyone!

I have a custom board with an STM32H7. I configured SDMMC2 correctly on it.

0693W00000AP0rtQAD.png 

As you can see there is no options for configuring DMA since it has an Internal (I)DMA.

I have also added FATFS, as follows.

0693W00000AP0s3QAD.png 

I managed to write/ready successfully to SD CARD mounted via FATFS. My problem arises when I enable the ‘Use DMA Template’. It is a must in order to later add FreeRTOS to the project.

After hours of debugging I realized that:

  • f_write() calls disk_write(), which calls sd_write(), which calls BSP_SD_WriteBlocks_DMA(), which calls HAL_SD_WriteBlocks_DMA(), and does not return any errors.
  • In sd_write(), WriteStatus desn’t get set to 1 [in sd_diskio.c] and times out.
  • HAL_SD_IRQHandler() gets called but it subsequently never calls HAL_SD_TxCpltCallBack() (which should eventually via many wrappers set WriteStatus to 1), and completely skips it.
  • I get HAL_SD_ERROR_TX_UNDERRUN.

Any help is highly appreciate it 🙏 .

4 REPLIES 4
Amel NASRI
ST Employee

Hi @Mohammed Eshaq​ ,

Please make sure that you are not hitting one of the conditions that makes "DMA is not working on STM32H7 devices".

You can also refer to following example available under STM32CubeH7 package (path: Projects\STM32H743I-EVAL\Applications\FatFs\FatFs_uSD_DMA_RTOS).

-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.

Hi @Mohammed Eshaq​ ,

Were you able to solve the issue you described here? If yes it will be helpful for us and other Community members to know what was the solution?

-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.

Hi @Amel NASRI​ ,

I appreciate your follow-up. But, no, the solution provided did not solve my problem. I have tried the following.

  • I have completely disabled the Data and Instruction Cache completely.
  • Changed the Linker Description File so that .data .bss, and user heap points to RAM_D1 (also tried D2 since SDMMC is located on D2).
  • Changed the starting address in the Linker Description File for RAM.

I noticed that SDMMC2_IRQHandler() does get called but exits without calling BSP_SD_WriteCpltCallBack(). I get HAL_SD_ERROR_TX_UNDERRUN. I spent days debugging this and trying different configurations but with no luck!

Hi Sirlsaac,

I also have this problem. I solved it by:

  • Replacing DTCMRAM with RAM_D1 (as DMA of SDMMC1 only works on RAM D1) in file STM32H743XIHx_FLASH.ld. Correct code for file STM32H743XIHx_FLASH.ld (I replaced at lines 27, 44, 55:(
/* Specify the memory areas */
MEMORY
{
DTCMRAM (xrw)      : ORIGIN = 0x20000000, LENGTH = 128K
RAM_D1 (xrw)      : ORIGIN = 0x24000000, LENGTH = 512K
RAM_D2 (xrw)      : ORIGIN = 0x30000000, LENGTH = 288K
RAM_D3 (xrw)      : ORIGIN = 0x38000000, LENGTH = 64K
ITCMRAM (xrw)      : ORIGIN = 0x00000000, LENGTH = 64K
FLASH (rx)      : ORIGIN = 0x8000000, LENGTH = 2048K
}
 
/* Define output sections */
SECTIONS
{
  /* Stuff unchanged (FLASH initialization) here ... */
 
  /* Initialized data sections goes into RAM, load LMA copy after code */
  .data : 
  {
    . = ALIGN(4);
    _sdata = .;        /* create a global symbol at data start */
    *(.data)           /* .data sections */
    *(.data*)          /* .data* sections */
 
    . = ALIGN(4);
    _edata = .;        /* define a global symbol at data end */
  } >RAM_D1 AT> FLASH /************ Replace here please ***********/
 
  
  /* Uninitialized data section */
  . = ALIGN(4);
  .bss :
  {
    /* This is used by the startup in order to initialize the .bss secion */
    _sbss = .;         /* define a global symbol at bss start */
    __bss_start__ = _sbss;
    *(.bss)
    *(.bss*)
    *(COMMON)
 
    . = ALIGN(4);
    _ebss = .;         /* define a global symbol at bss end */
    __bss_end__ = _ebss;
  } >RAM_D1 /************ Replace here please ***********/
 
  /* User_heap_stack section, used to check that there is enough RAM left */
  ._user_heap_stack :
  {
    . = ALIGN(8);
    PROVIDE ( end = . );
    PROVIDE ( _end = . );
    . = . + _Min_Heap_Size;
    . = . + _Min_Stack_Size;
    . = ALIGN(8);
  } >RAM_D1 /************ Replace here please ***********/
 
  
 
  /* Remove information from the standard libraries */
  /DISCARD/ :
  {
    libc.a ( * )
    libm.a ( * )
    libgcc.a ( * )
  }
 
  .ARM.attributes 0 : { *(.ARM.attributes) }
}
  • Replacing HAL_SD_IRQHandler with BSP_SD_IRQHandler in SDMMC1_IRQHandler file stm32h7xx_it.c (I replaced at line 7).
void SDMMC1_IRQHandler(void)
{
  /* USER CODE BEGIN SDMMC1_IRQn 0 */
 
  /* USER CODE END SDMMC1_IRQn 0 */
  //HAL_SD_IRQHandler(&hsd1);
  BSP_SD_IRQHandler(0); /*************** Replace here ****************/
  /* USER CODE BEGIN SDMMC1_IRQn 1 */
 
  /* USER CODE END SDMMC1_IRQn 1 */
}
  • That change is because I found hsd1 is incorrect (Instance->STA = 938160664 // SDMMC_FLAG_RXOVERR), while hsd_sdmmc[0] indicates the correct one (Instance->STA = 256 // SDMMC_FLAG_DATAEND).

0693W00000BcZCqQAN.jpg0693W00000BcZD0QAN.jpgHope it helpfull!

-Hai-