Skip to main content
Associate
June 9, 2026
Solved

SD Card corruption after f_write with STM32H7 + SDMMC/FATFS + FREERTOS

  • June 9, 2026
  • 1 reply
  • 130 views

I'm seeing a filesystem corruption issue on an STM32H7 when using FatFs with SDMMC DMA.

 

Hardware / Software

  • STM32H7

  • SDMMC1

  • DMA (and MDMA support enabled)

  • FatFs generated by CubeMX

  • D-Cache enabled

  • 8 GB Swissbit industrial SD card

  • Generated sd_diskio.c based on:

    /* Note: code generation based on sd_diskio_dma_rtos_template_bspv1.c v2.1.4 */

Problems

The SD card works normally while mounted:

  • Files can be created

  • Data can be written

  • Data can be read back

  • f_write(), f_sync(), and f_close() all return success

However, after:

  • Removing and reinserting the SD card, or

  • Power cycling the system

the SD card is detected by Windows as:

RAW / Unformatted

and must be reformatted before it can be used again.

Important observation

If I only perform read operations:

Mount card
Read files
Power cycle / reinsert card

the filesystem remains valid. The corruption only occurs after write operations.

Initial investigation

Because the STM32H7 uses D-Cache, I initially suspected cache coherency issues.
I created a dedicated non-cacheable MPU region:

0x24000000 - 0x2401FFFF (128 KB)

and placed my application DMA buffers in that region using:

__attribute__((section(".RAM_D1_NCACHE")))
__attribute__((aligned(32)))

I also verified via the linker map and debugger that the buffers were actually located inside the non-cacheable region.
Despite this, the filesystem corruption remained.

Investigation of sd_diskio.c

The generated driver contains a scratch buffer path used when the user buffer is not suitably aligned.
I noticed the following code:

#if (ENABLE_SD_DMA_CACHE_MAINTENANCE == 1)
SCB_InvalidateDCache_by_Addr((uint32_t*)scratch, BLOCKSIZE);
#endif

for (i = 0; i < count; i++)
{
memcpy((void *)scratch, buff, BLOCKSIZE);
buff += BLOCKSIZE;
ret = BSP_SD_WriteBlocks_DMA((uint32_t*)scratch,
(uint32_t)sector++,
1);
}

The sequence is:

  1. Invalidate cache for scratch buffer

  2. Copy data into scratch buffer using CPU (memcpy)

  3. Start DMA transfer from scratch buffer

  4. No cache clean after the copy

This looked suspicious because the CPU modifies the scratch buffer immediately before the DMA transfer.

Additional test

I moved the scratch buffer from the sd_diskio.c into my non-cacheable MPU region:

__attribute__((section(".RAM_D1_NCACHE")))
__attribute__((aligned(32)))
static uint8_t scratch[BLOCKSIZE];

Result:

Filesystem corruption disappeared.

DMA operation continues to work correctly and the SD card remains valid after reinsertion and power cycling.
Has anyone else observed similar behaviour with the STM32H7 FatFs SD driver, SDMMC DMA, or the generated scratch-buffer path?
If so:

  • What was the root cause?
  • Did you use a similar workaround?
  • Is there a recommended fix that keeps the scratch buffer in normal cacheable RAM?
Best answer by flar

Update / Alternative Fix

I was able to resolve the issue and wanted to share a solution that I consider a bit cleaner than placing the scratch buffer into a dedicated non-cacheable MPU region.

While investigating the DMA write path in the generated sd_diskio.c, I noticed the following code:

#if (ENABLE_SD_DMA_CACHE_MAINTENANCE == 1)
SCB_InvalidateDCache_by_Addr((uint32_t*)scratch, BLOCKSIZE);
#endif

for (i = 0; i < count; i++)
{
memcpy((void *)scratch, buff, BLOCKSIZE);
buff += BLOCKSIZE;

ret = BSP_SD_WriteBlocks_DMA((uint32_t*)scratch,
(uint32_t)sector++,
1);
}

As a first workaround, I moved the scratch buffer into a non-cacheable MPU region, which completely eliminated the filesystem corruption.

However, I then tested keeping the scratch buffer in normal cacheable RAM and instead cleaning the cache after the memcpy() and before starting the DMA transfer:

for (i = 0; i < count; i++)
{
memcpy((void *)scratch, buff, BLOCKSIZE);

#if (ENABLE_SD_DMA_CACHE_MAINTENANCE == 1)
SCB_CleanDCache_by_Addr((uint32_t*)scratch, BLOCKSIZE);
#endif

buff += BLOCKSIZE;

ret = BSP_SD_WriteBlocks_DMA((uint32_t*)scratch,
(uint32_t)sector++,
1);
}

This also resolved the issue completely.

With this change, the scratch buffer no longer needs to be placed in a dedicated non-cacheable MPU region and can remain in normal cacheable RAM.

After applying this modification, the SD card remained valid across multiple write cycles, card reinsertions, and power cycles.

Hopefully this helps anyone encountering similar SDMMC DMA / FatFs issues on STM32H7 devices with D-Cache enabled.

1 reply

flarAuthorBest answer
Associate
June 9, 2026

Update / Alternative Fix

I was able to resolve the issue and wanted to share a solution that I consider a bit cleaner than placing the scratch buffer into a dedicated non-cacheable MPU region.

While investigating the DMA write path in the generated sd_diskio.c, I noticed the following code:

#if (ENABLE_SD_DMA_CACHE_MAINTENANCE == 1)
SCB_InvalidateDCache_by_Addr((uint32_t*)scratch, BLOCKSIZE);
#endif

for (i = 0; i < count; i++)
{
memcpy((void *)scratch, buff, BLOCKSIZE);
buff += BLOCKSIZE;

ret = BSP_SD_WriteBlocks_DMA((uint32_t*)scratch,
(uint32_t)sector++,
1);
}

As a first workaround, I moved the scratch buffer into a non-cacheable MPU region, which completely eliminated the filesystem corruption.

However, I then tested keeping the scratch buffer in normal cacheable RAM and instead cleaning the cache after the memcpy() and before starting the DMA transfer:

for (i = 0; i < count; i++)
{
memcpy((void *)scratch, buff, BLOCKSIZE);

#if (ENABLE_SD_DMA_CACHE_MAINTENANCE == 1)
SCB_CleanDCache_by_Addr((uint32_t*)scratch, BLOCKSIZE);
#endif

buff += BLOCKSIZE;

ret = BSP_SD_WriteBlocks_DMA((uint32_t*)scratch,
(uint32_t)sector++,
1);
}

This also resolved the issue completely.

With this change, the scratch buffer no longer needs to be placed in a dedicated non-cacheable MPU region and can remain in normal cacheable RAM.

After applying this modification, the SD card remained valid across multiple write cycles, card reinsertions, and power cycles.

Hopefully this helps anyone encountering similar SDMMC DMA / FatFs issues on STM32H7 devices with D-Cache enabled.