cancel
Showing results for 
Search instead for 
Did you mean: 

STM32H757 SDMMC + FATFS consistently returns FR_NOT_READY

Sasa1234
Associate III

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:

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


 Software architecture

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


Observed behavior

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.


Key observations (important)

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


 Suspected root causes

At this point I strongly suspect one (or more) of the following:

1. Cache coherency issue (most likely)

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


2. MPU configuration not DMA-safe

Default CubeMX MPU configuration appears unchanged.

Risk:

  • SDMMC DMA buffer located in cacheable region

  • or MPU attributes conflicting with DMA access


3. SDMMC HAL/BSP mismatch

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


4. SDMMC clock / init sequencing sensitivity

Even though init returns OK, the card never reliably reaches transfer state under FATFS load.


 Question to ST / senior devs

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.

2 REPLIES 2
Saket_Om
ST Employee

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.

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

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 

:question_mark: Question

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!