cancel
Showing results for 
Search instead for 
Did you mean: 

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

Brandon-Altaneos
Associate II

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

1 ACCEPTED SOLUTION

Accepted Solutions
Brandon-Altaneos
Associate II

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

View solution in original post

5 REPLIES 5
AScha.3
Super User

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

If you feel a post has answered your question, please click "Accept as Solution".

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

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

 

If you feel a post has answered your question, please click "Accept as Solution".

Hi,

You're absolutely right, the SD card may support up to 104 MHz, but without a 1.8V transceiver, we're limited to 50 MHz at 3.3V operation. I’ll stick to 50 MHz to stay within spec.

That said, even with the reduced clock, the DMA transfer from the SD card still doesn’t work when triggered from the USB interrupt context. I'm still investigating this issue, it seems to be unrelated to the clock speed.

Best regards,
Brandon

Brandon-Altaneos
Associate II

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