cancel
Showing results for 
Search instead for 
Did you mean: 

STM32H745I-DISCO eMMC how to configure with FATFS?

HTD
Senior III

Yes, I use Cube.

In the documentation I read that eMMC is connected to SDMMC1.

SDMMC1 can be configured either as SD or MMC. I get the SD option in FATFS only when SDMMC1 is configured as SD.

OK, I found the example to use MMC driver, I configured it.

Anyway - it doesn't work. I get SDMMC_ERROR_CMD_RSP_TIMEOUT.

Here's my SDMMC1 initialization:

static void MX_SDMMC1_MMC_Init(void)
{
 
  /* USER CODE BEGIN SDMMC1_Init 0 */
 
  /* USER CODE END SDMMC1_Init 0 */
 
  /* USER CODE BEGIN SDMMC1_Init 1 */
 
  /* USER CODE END SDMMC1_Init 1 */
  hmmc1.Instance = SDMMC1;
  hmmc1.Init.ClockEdge = SDMMC_CLOCK_EDGE_RISING;
  hmmc1.Init.ClockPowerSave = SDMMC_CLOCK_POWER_SAVE_DISABLE;
  hmmc1.Init.BusWide = SDMMC_BUS_WIDE_8B;
  hmmc1.Init.HardwareFlowControl = SDMMC_HARDWARE_FLOW_CONTROL_DISABLE;
  hmmc1.Init.ClockDiv = 2;
  if (HAL_MMC_Init(&hmmc1) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN SDMMC1_Init 2 */
 
  /* USER CODE END SDMMC1_Init 2 */
 
}

 UPDATE:

Now I'm confused. The initialization passes after reset or power cycle. I get the error only directly after flashing the board. Why is that?

1 ACCEPTED SOLUTION

Accepted Solutions
HTD
Senior III

OK, I've solved the case.

Here are steps to make it work:

  1. Configure SDMMC1 to use 8-bit bus, 50MHz clock after division (in my case - 200MHz clock, divider is 2).
  2. Configure FATFS middleware for any device, MMC is not available, USER option can be selected. The key part is to check all the option allowing to use long file names and UTF, optionally exFAT. I just added MMC binding manually, without USER option.
  3. Configure MDMA for SDMMC1 transfers. I just added all available, IDK if it's necessary.
  4. Get the diskio.c template for DMA / RTOS from https://github.com/STMicroelectronics/STM32CubeH7/blob/master/Middlewares/Third_Party/FatFs/src/drivers/sd_diskio_dma_rtos_template_bspv2.c
  5. REPLACE ALL BSP API functions with HAL functions, paying close attention to different return values for BSP and HAL API.
  6. Done. It works.

Of course it's valid only when using RTOS, that is a default option for TouchGFX and that board. The FatFS functions are available when RTOS kernel is running, I mount the eMMC FS in RTOS task. I mounted actually 2 file systems, to access the files I need to provide full path, like "0:/file.dat" or "1:/file.dat", because when I used the file name alone it looked for it on wrong file system (USB disk that was not present at the time).

Parts I missed that costed me over 100 hours of banging my head against the wall:

  1. Check if I use the I/O function on the right handle.
  2. Use only DMA transfers, polling mode fails miserably.
  3. Check what HAL_MMC_GetCardState() function returns.
  4. Check if BSP_MMC_ReadCpltCallback() and BSP_MMC_WriteCpltCallback() functions are called. They should be implemented and awaited after I/O.

When f_mount() or f_mkfs() is called, the first function in the driver that is called is MMC_initialize(). The template has DISABLE_MMC_INIT macro to skip internal initialization. That is crucial when the SDMMC1 is already initialized in main(). This macro MUST be defined. On MMC_initialize() only HAL_MMC_GetCardState() should be called.

View solution in original post

12 REPLIES 12
FBL
ST Employee

Hello @Adam �?yskawa​ ,

I was wondering if the issue persists. If so, here are some suggestions: 

1- Verify set up your pins / AF the right way, or verify the initialization of the SDIO peripheral, 

2- Try this example STM32Cube\Repository\STM32Cube_FW_H7_V1.10.0\Projects\STM32H745I-DISCO\Examples\MMC\MMC_ReadWrite_DMA

to make sure whether the problem persists

Please refer to AN5200 for more details about SDMMC host controller configuration.

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.

HTD
Senior III

Hello. I finally have time to get back to the issue. Yes, the problem still persists.

I wonder how to approach it in my TouchGFX application / STM32CubeIDE. There is a full board configuration I have to work with. It would be the best if I could just follow the CubeMX guide part of AN5200, but it doesn't work at all. When I select SDMMC1 configuration as MMC 8-bit (as it should be and seems best considering the chip used and internal connections) - the SD option is unavailable in FATFS middleware settings. There is no option for MMC, though it can be manually set up in code.

I was able to configure FATFS myself, however, the driver I was able to run seemed not to use DMA at all , that seems to be at least strange. What's more - I honestly don't know how to configure the DMA for the eMMC manually, STM32CubeIDE usually does that perfectly, however - there is no such option here, unless I switch SDMMC1 configuration to work in SD 4bit mode.

So, using SDMMC1 configured as 8-bit MMC doesn't work. BTW, I tried 50MHz and 25MHz clock speeds. The chip initialization passes, it is detected and powered. Then, when the first data transfer occurs I get random buffer underrun errors, that are quite expected since the DMA is not even used.

Now I'm a little lost about what to do next. In order for FATFS work, AFAIK I need provide just a few functions that read and write blocks. I can implement them myself. I wonder why the ones provided by ST (HAL) don't work. I also don't know how can I configure DMA for the eMMC either using CubeIDE or manually.

UPDATE:

I was able to configure MDMA as described in AN5200. Now when I run MX_SDMMC1_MMC_Init() it fails with HAL_MMC_ERROR_RX_OVERRUN error:0693W00000Sw5klQAB.pngWhy is that? The clock that gets into eMMC (MTFC4GACAJCN-1M WT chip) is 25MHz. hmmc1.Init.ClockDiv = 2.

Somewhere else I read it's crucial the clock frequency must be set pretty precisely in order for it to work, however, in MTFC4GACAJCN-1M WT it's stated that the chip accepts up to 50MHz frequency. Why is the ClockDiv? According to the eMMC chip documentation, I should be able to read it up to its top speed, 50MHz, ClockDiv = 0, however - it definitely doesn't work. The first read fails. Using lower speeds makes some read operations succeed, but later on - eventually always a buffer underrun or buffer overrun occurs.

UPDATE:

Now I'm trying to recreate the example:

0693W00000Sw5qZQAR.pngSo, the SDMMC Kernel Clock is 200:

0693W00000Sw5qtQAB.png 

0693W00000Sw5qyQAB.pngThen:

0693W00000Sw5rNQAR.pngSo:

0693W00000Sw5rSQAR.pngStill - the same error, same line.

UPDATE:

I moved MX_SDMMC1_MMC_Init() to main(). What's weird, it completes, however, when I try to format eMMC, I get similar error. This is weird.

So - initialization fails when it's done in RTOS task. When it's done directly from main - it passes. Now - I tried to run f_mkfs() from main, but it immediately triggers HardFault. I have no idea why. When I run f_mkfs() from RTOS task, it starts, then fails on write block function.

HTD
Senior III

OK, I've solved the case.

Here are steps to make it work:

  1. Configure SDMMC1 to use 8-bit bus, 50MHz clock after division (in my case - 200MHz clock, divider is 2).
  2. Configure FATFS middleware for any device, MMC is not available, USER option can be selected. The key part is to check all the option allowing to use long file names and UTF, optionally exFAT. I just added MMC binding manually, without USER option.
  3. Configure MDMA for SDMMC1 transfers. I just added all available, IDK if it's necessary.
  4. Get the diskio.c template for DMA / RTOS from https://github.com/STMicroelectronics/STM32CubeH7/blob/master/Middlewares/Third_Party/FatFs/src/drivers/sd_diskio_dma_rtos_template_bspv2.c
  5. REPLACE ALL BSP API functions with HAL functions, paying close attention to different return values for BSP and HAL API.
  6. Done. It works.

Of course it's valid only when using RTOS, that is a default option for TouchGFX and that board. The FatFS functions are available when RTOS kernel is running, I mount the eMMC FS in RTOS task. I mounted actually 2 file systems, to access the files I need to provide full path, like "0:/file.dat" or "1:/file.dat", because when I used the file name alone it looked for it on wrong file system (USB disk that was not present at the time).

Parts I missed that costed me over 100 hours of banging my head against the wall:

  1. Check if I use the I/O function on the right handle.
  2. Use only DMA transfers, polling mode fails miserably.
  3. Check what HAL_MMC_GetCardState() function returns.
  4. Check if BSP_MMC_ReadCpltCallback() and BSP_MMC_WriteCpltCallback() functions are called. They should be implemented and awaited after I/O.

When f_mount() or f_mkfs() is called, the first function in the driver that is called is MMC_initialize(). The template has DISABLE_MMC_INIT macro to skip internal initialization. That is crucial when the SDMMC1 is already initialized in main(). This macro MUST be defined. On MMC_initialize() only HAL_MMC_GetCardState() should be called.

Hi @HTD ,

I have the same issue when I try to create FATFS on eMMC. Could you give me more information about How you resolve this issue? Or please share your source code, etc. Any suggestions are welcome.

TL;DR: Working example: https://github.com/HTD/STM32H745I-DISCO-Template

If you have STM32H745I-DISCO board, it should work. You can also just look how the eMMC is configured.

 

I'm not sure if I remember it correctly, but it seems like a problem with STM32CubeIDE code generator, that is dependent on IOC file being a template for generating the code for the project. Sometimes, especially with STM32H745, it crashes during the code generation phase and it doesn't apply some necessary changes, like copying / linking files, updating include directories and so on.

Probably exactly this happened when I generated the code for the eMMC/FATFS. I'm not sure if eMMC is even an option to select in Device Configuration Tool.

However, it works as a regular SD/MMC card, so the drivers and project bindings are almost identical.

AFAIR I started with an example, that you can either create in STM32CubeIDE directly as a new project, or just download from STM32H745 GitHub project. The example worked. So I analyzed how the eMMC is accessed in the example using debugger.

I noticed, that the example uses BSP (board support provider) files / drivers. Those files are very similar to the code generated by STM32CubeIDE, with some minor differences. As STM32CubeIDE didn't generate the files for me, I created those files myself from a template that existed in the GitHub project, then I just modified them to work the same as the BSP files.

Generally you have functions and types that start with `HAL_`, and with `BSP_`. They are almost identical. Also the `BSP_` ones generally takes a number called `Instance` as the first parameter, while the ones starting with `HAL_` don't. The number in all examples is zero. Also, they refer to global handles being a part of 1-element array, `HAL_` functions refer to the handles that are usually defined directly in `main` or somewhere else in `Core` directory. Change the references and it will work. It applies not only to eMMC but also to other components.

Thanks for your info.

Look like the FATFS configurator created by CubeIDE is very different. So, I just change the eMMC config to the same template to resolve issue. Then, I can use eMMC like the SDcard to create, write, and read files by FATFS right?

Exactly. But on my STM32H747I-DISCO I have it configured as MMC:

HTD_1-1690184549603.png

Look at the example I uploaded to GitHub, especially here:
https://github.com/HTD/STM32H745I-DISCO-Template/tree/master/CM7/FATFS
and here:
https://github.com/HTD/STM32H745I-DISCO-Template/tree/master/CM7/FATFS/Target

Before first use you should format the memory to FAT32 or ExFAT. In my projects I use mostly ExFAT as it plays better with unexpected resets and shutdowns. Somewhere in my code I try to call `f_mount()` on eMMC, and if it fails with `FR_NO_FILESYSTEM` I call `f_mkfs()`, then `f_mount()` again to test if it worked.

 

It's really a good method. I'm grateful for your taking the time.

Hi @HTD , on my STM32H747I-DISCO board, I see only mode 4 wire. image.pngSo when I configured it as MMC 4-wire, I always take the FR_DISK_ERR error code when call f_write(). Could you give me suggest?