Skip to main content
Visitor II
May 19, 2025
Solved

H7 USB_OTG_HS Mass Storage with SD card — issues at higher SD clock frequency

  • May 19, 2025
  • 2 replies
  • 751 views

Hello,

I’m working on a custom board based on the STM32H753IITx and I'm trying to access a microSD card via USB_OTG_HS using the USB Mass Storage Class (MSC). I've read this post, which is close to my use case, but unfortunately, I haven’t been able to solve my issue.

Here is a summary of my configuration in STM32CubeMX:

SDMMC1 (SD card interface):

  • Mode: SD 4-bit wide bus
  • Clock transition: Rising edge
  • Clock output when idle: Enabled (Power save disabled)
  • Hardware flow control: Disabled
  • Clock divide factor: 1 (which results in 200 MHz / (2 × 1) = 100 MHz SDMMC_CK)
  • External transceiver: Not present
  • All GPIOs maximum output speed to Very High
  • All GPIOs except SDMMC1_CK have pull-up

USB_OTG_HS (Mass Storage Device):

  • PHY: External PHY (ULPI), Device_Only
  • Speed: High Speed (480 Mbit/s)
  • IP DMA: Disabled
  • Power management features: All disabled
  • VBUS sensing: Disabled
  • USB Class: Mass Storage Class
  • MSC_MEDIA_PACKET size: 512 bytes
  • USBD_SELF_POWERED: Enabled
  • LPM (Link Power Management): Enabled
  • All GPIOs maximum output speed to Very High

 

Here’s what I’m observing:

  • When the SDMMC1 clock is set to 100 MHz, my PC detects the USB device, but fails to read from the SD card.
  • When I reduce the clock to 25 MHz, the PC detects the card and I can read/write successfully.
  • On the MCU side, FatFS works fine at both 25 MHz and 100 MHz for standalone read/write.
  • When I try to initialize the SD card (via BSP_SD_Init) in the USB cable detection interrupt, the CPU freezes, SysTick stops, and the system gets stuck in an infinite timeout loop using HAL_GetTick().
  • Even at low clock speeds, SD DMA read/write doesn't work when triggered from the USB MSC.

I'm using:

STM32CubeFW_H7 v1.12.1

STM32 USB Device Library v1.17.0

I've created a minimal standalone project reproducing the issue — it’s available here: https://github.com/Brandon-Altaneos/STM32H7_SD_USB_StandAlone/tree/master/SD_USB_Stand_Alone .

Any guidance or suggestions would be greatly appreciated.

Thanks in advance,
Brandon

    This topic has been closed for replies.
    Best answer by Brandon-Altaneos

    Hello,

    I wanted to share the solution I found in case it helps others.

    After trying various things — including checking for cache coherency using SCB_CleanDCache_by_Addr() and SCB_InvalidateDCache_by_Addr() — I identified the issue was related to the location of the bot_data buffer used by the USB MSC layer.

    Since this buffer is accessed during USB interrupt context and the SD card driver uses DMA, I moved the bot_data buffer to a non-cacheable memory region (in my case, external RAM configured as non-cacheable via MPU settings).

    in usbd_conf.c:

    #ifdef USBD_malloc
    #undef USBD_malloc
    #define USBD_malloc USBD_static_malloc_sdram
    #endif
    
    SDRAM_BUFFER uint32_t USBD_pStaticMem[(sizeof(USBD_MSC_BOT_HandleTypeDef)/4)+1];

    ...

    void *USBD_static_malloc_sdram(uint32_t size);
    
    void *USBD_static_malloc_sdram(uint32_t size)
    {
     UNUSED(size);
     return USBD_pStaticMem;
    }

     

    with :

    #define SDRAM_BUFFER __attribute__((section(".sdram_buffer"), aligned(32)))

     

    Once that was done, I was able to:

    • Use my SD card driver in the USB context without system freezes,
    • Enable SDMMC at 50 MHz (instead of limiting to 25 MHz),
    • And perform read/write sdcard over USB MSC reliably.

    Brandon

    2 replies

    Super User
    May 19, 2025

    Hi,

    Clock divide factor: 1 (which results in 200 MHz / (2 × 1) = 100 MHz SDMMC_CK

    - is too much ! sd-card max is 50MHz , set div to 2 (or3) , to have max. 50 M .

     

    +

    Try first without DMA ;

    if working,  then try with DMA : disable D-cache (to check, if its a problem with cache manage.)

    Visitor II
    May 21, 2025

    Hi,

    Thanks for the suggestion.

     

    Clock divide factor: 1 (which results in 200 MHz / (2 × 1) = 100 MHz SDMMC_CK

    - is too much ! sd-card max is 50MHz , set div to 2 (or3) , to have max. 50 M .



    My SD card actually supports a clock frequency up to 104 MHz, as it complies with the SDHC UHS-I SDR104 standard. when I perform SD read/write operations via the MCU using FatFs, either in blocking mode or with DMA, it works flawlessly even at 100 MHz.

    However, the issue appears in the context of USB MSC, i have to reduce the SDMCC clock ot 25 MHz to perform SD read/write operations in blocking mode. otherwise, the system hangs.

     

    Try first without DMA ;

    if working,  then try with DMA : disable D-cache (to check, if its a problem with cache manage.)


    D-Cache is not enabled in the current configuration (standalone project) so cache maintenance isn't an issue here.

    Let me know if you have any insight on using DMA safely in the USB context.

    Best regards,
    Brandon

    Super User
    May 21, 2025

    Hi,

    >My SD card actually supports a clock frequency up to 104 MHz

    fine, but my H7 needs 1.8V transceiver for this - you have this ?

    at 3v3 : 50M max ...

    AScha3_0-1747839292154.png

     

    Brandon-AltaneosAuthorAnswer
    Visitor II
    June 13, 2025

    Hello,

    I wanted to share the solution I found in case it helps others.

    After trying various things — including checking for cache coherency using SCB_CleanDCache_by_Addr() and SCB_InvalidateDCache_by_Addr() — I identified the issue was related to the location of the bot_data buffer used by the USB MSC layer.

    Since this buffer is accessed during USB interrupt context and the SD card driver uses DMA, I moved the bot_data buffer to a non-cacheable memory region (in my case, external RAM configured as non-cacheable via MPU settings).

    in usbd_conf.c:

    #ifdef USBD_malloc
    #undef USBD_malloc
    #define USBD_malloc USBD_static_malloc_sdram
    #endif
    
    SDRAM_BUFFER uint32_t USBD_pStaticMem[(sizeof(USBD_MSC_BOT_HandleTypeDef)/4)+1];

    ...

    void *USBD_static_malloc_sdram(uint32_t size);
    
    void *USBD_static_malloc_sdram(uint32_t size)
    {
     UNUSED(size);
     return USBD_pStaticMem;
    }

     

    with :

    #define SDRAM_BUFFER __attribute__((section(".sdram_buffer"), aligned(32)))

     

    Once that was done, I was able to:

    • Use my SD card driver in the USB context without system freezes,
    • Enable SDMMC at 50 MHz (instead of limiting to 25 MHz),
    • And perform read/write sdcard over USB MSC reliably.

    Brandon