2026-05-07 7:25 AM - last edited on 2026-05-07 7:30 AM by Andrew Neil
Hello,
I’m working on an STM32H757 (Cortex-M7 core, dual-core system) using SDMMC1 + FATFS (CubeMX-generated stack) and I consistently hit a blocking issue:
f_mount() always returns:
FR_NOT_READY
or the execution breaks inside Error_Handler() depending on build/debug timing.
Hardware / system context
MCU: STM32H757 (Cortex-M7, DCache enabled)
SD interface: SDMMC1, 4-bit mode
DMA: enabled (CubeMX SDMMC DMA configuration)
External subsystem: Riverdi TFT display 12.1 inches (LTDC active)
FATFS: CubeMX middleware (generic SD diskio template)
No RTOS
STM32CubeIDE latest
HAL SDMMC driver (CubeMX generated)
FATFS with sd_diskio.c DMA template
BSP layer present (mixed HAL/BSP abstraction)
Cache enabled (I/D Cache ON, MPU default CubeMX config)
During initialization:
BSP_SD_Init() returns OK
SD card is physically detected
HAL_SD_GetCardState() does NOT consistently reach SD_TRANSFER_OK
SD_CheckStatusWithTimeout() frequently times out
FATFS layer reports:
FR_NOT_READY
Mount never succeeds.
SDMMC peripheral initializes without error
DMA transfer callbacks are triggered inconsistently
No explicit DCache maintenance is performed in user code
MPU remains CubeMX default (no SD/DMA region tuning)
sd_diskio.c is the CubeMX DMA template version (unaltered logic)
At this point I strongly suspect one (or more) of the following:
No explicit:
SCB_CleanDCache_by_Addr
SCB_InvalidateDCache_by_Addr
around SDMMC DMA buffers.
Given Cortex-M7 behavior, this alone can fully explain:
stuck SD state machine
invalid transfer completion flags
FATFS seeing STA_NOINIT → FR_NOT_READY
Default CubeMX MPU configuration appears unchanged.
Risk:
SDMMC DMA buffer located in cacheable region
or MPU attributes conflicting with DMA access
CubeMX-generated stack mixes:
HAL_SD
BSP_SD_*
FatFS diskio DMA template
The abstraction layering is inconsistent and may be causing:
incorrect card state polling
race conditions in BSP_SD_GetCardState()
Even though init returns OK, the card never reliably reaches transfer state under FATFS load.
Is there a known stable reference configuration for STM32H757 SDMMC + FATFS + DMA that actually works under Cortex-M7 cache enabled system?
Specifically:
Is DCache maintenance mandatory in sd_diskio.c for H7 family even with BSP DMA template?
Should MPU explicitly mark SD DMA buffers as non-cacheable?
Is the CubeMX SDMMC DMA template actually valid for H757 or known broken in real-world use cases?
Any recommended HAL/BSP layering for stable FATFS on H7?
At this point the behavior looks less like an application bug and more like a system-level coherency issue in the generated stack.
Any concrete working reference or confirmed fix would be appreciated.
Thanks.
2026-05-08 6:36 AM
Hello @Sasa1234
@Sasa1234 wrote:Is there a known stable reference configuration for STM32H757 SDMMC + FATFS + DMA that actually works under Cortex-M7 cache enabled system?
Please refer to the example FatFs_Shared_Device in STM32CubeH7.
2026-05-21 1:51 AM
Hello everyone,
I've been working for a couple of days on a project using a Riverdi 12-inch display based on an STM32 MCU (STM32H7 series, to be precise). I modified a single line of code inside fatfs_platform.c (Re: Riverdi 12.1" + TouchGFX 4.25 + FATFS not work... - STMicroelectronics Community) – the low‑level FatFs driver provided by STM32CubeMX – to better adapt it to my SDMMC/SDIO peripheral.when I run this main code
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file fatfs.c
* @brief Code for fatfs applications
******************************************************************************
* @attention
*
* Copyright (c) 2024 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
#include "fatfs.h"
uint8_t retSD; /* Return value for SD */
char SDPath[4]; /* SD logical drive path */
FATFS SDFatFS; /* File system object for SD logical drive */
FIL SDFile; /* File object for SD */
/* USER CODE BEGIN Variables */
#define LED_OK LED1
#define LED_ERROR LED2
#define APP_OK 0
#define APP_ERROR -1
#define APP_SD_UNPLUGGED -2
#define APP_INIT 1
#define FATFS_MKFS_ALLOWED 1
typedef enum {
APPLICATION_IDLE = 0,
APPLICATION_INIT,
APPLICATION_RUNNING,
APPLICATION_SD_UNPLUGGED,
}FS_FileOperationsTypeDef;
FS_FileOperationsTypeDef Appli_state_uSD = APPLICATION_IDLE;
uint32_t is_initialized = 0;
int32_t ProcessStatus = 0;
static int32_t FS_FileOperations(void);
static void SD_Init(void);
static uint8_t workBuffer[_MAX_SS]; /* a work buffer for the f_mkfs() */
volatile int32_t process_res = APP_OK;
static int32_t FS_FileOperations(void)
{
FRESULT res; /* FatFs function common result code */
uint32_t byteswritten, bytesread; /* File write/read counts */
uint8_t wtext[] = "This is STM32 working with FatFs and uSD diskio driver"; /* File write buffer */
uint8_t rtext[100]; /* File read buffer */
/* Register the file system object to the FatFs module */
if(f_mount(&SDFatFS, (TCHAR const*)SDPath, 0) == FR_OK)
{
res = f_open(&SDFile, "gennarino.TXT", FA_CREATE_ALWAYS | FA_WRITE);
/* Create and Open a new text file object with write access */
if(res == FR_OK)
{
/* Write data to the text file */
res = f_write(&SDFile, wtext, sizeof(wtext), (void *)&byteswritten);
if((byteswritten > 0) && (res == FR_OK))
{
/* Close the open text file */
f_close(&SDFile);
/* Open the text file object with read access */
if(f_open(&SDFile, "M.TXT", FA_READ) == FR_OK)
{
/* Read data from the text file */
res = f_read(&SDFile, rtext, sizeof(rtext), (void *)&bytesread);
if((bytesread > 0) && (res == FR_OK))
{
/* Close the open text file */
f_close(&SDFile);
/* Compare read data with the expected data */
if((bytesread == byteswritten))
{
// if(Buffercmp((uint32_t *)rtext, (uint32_t *)wtext, sizeof(rtext)))
{ /* Success of the demo: no error occurrence */
return 0;
}
}
}
}
}
}
}
/* Error */
return -1;
}
/* USER CODE END Variables */
void MX_FATFS_Init(void)
{
/*## FatFS: Link the SD driver ###########################*/
retSD = FATFS_LinkDriver(&SD_Driver, SDPath);
/* USER CODE BEGIN Init */
Appli_state_uSD = APPLICATION_INIT;
/* additional user code for init */
/* USER CODE END Init */
}
/**
* @brief Gets Time from RTC
* @PAram None
* @retval Time in DWORD
*/
DWORD get_fattime(void)
{
/* USER CODE BEGIN get_fattime */
return 0;
/* USER CODE END get_fattime */
}
/* USER CODE BEGIN Application */
void MX_FATFS_Process(void *argument)
{
/* USER CODE BEGIN MX_FATFS_Process */
Start_uSD_Test = 1;
/* Mass Storage Application State Machine */
while(1)
{
if(Start_uSD_Test)
{
switch(Appli_state_uSD)
{
case APPLICATION_INIT:
if(BSP_SD_IsDetected() == SD_PRESENT)
{
// SD_Init();
#if FATFS_MKFS_ALLOWED
FRESULT res;
res = f_mkfs(SDPath, FM_ANY, 0, workBuffer, sizeof(workBuffer));
if (res != FR_OK)
{
process_res = APP_ERROR;
}
else
{
process_res = APP_INIT;
Appli_state_uSD = APPLICATION_RUNNING;
}
#else
process_res = APP_INIT;
Appli_state_uSD = APPLICATION_RUNNING;
#endif
}
else
{
Appli_state_uSD = APPLICATION_SD_UNPLUGGED;
}
break;
case APPLICATION_RUNNING:
// SD_Init();
process_res = FS_FileOperations();
Appli_state_uSD = APPLICATION_IDLE;
Start_uSD_Test = process_res;
break;
case APPLICATION_SD_UNPLUGGED:
process_res = APP_SD_UNPLUGGED;
break;
case APPLICATION_IDLE:
default:
break;
}
ProcessStatus = process_res;
}
osDelay(1000);
}
/* USER CODE END MX_FATFS_Process */
}
/**
* @brief BSP SD Initialization
* @PAram None
* @retval None.
*/
static void SD_Init()
{
if (!is_initialized)
{
BSP_SD_Init();
is_initialized = 1;
}
}
/* USER CODE END Application */during debugging the variable res becomes FR_DISK_ERR (generic physical drive error). I cannot figure out why.
Attached is my .ioc configuration file
Has anyone experienced a similar issue when modifying low‑level FatFs drivers on a Riverdi display?
Could this be related to timing, stack/heap size, DMA configuration, or an incorrect implementation of disk_read() / disk_write()?
Any suggestion or shared experience would be greatly appreciated.
Thank you all in advance!