cancel
Showing results for 
Search instead for 
Did you mean: 

Solution to fix STM32F4xxx STMCubeMX Firmware V1.18 SDIO FATFS DMA not working issue

Bardeen Lai
Associate III
Posted on January 02, 2018 at 12:18

Hi all,

Recently I use STM32CubeMX Ver 4.0 (STMCube V1.0), firmware V1.18 to generate codes for STM32F407 by using SDIO 4-bit bus to access SD card via DMA or standard IO. The generated codes could not function probably.

In order to make it work, you have to modify three files generated by STM32CubeMX:

1. bsp_driver_sd.c

2. sd_diskio.c

3. fatfs.c

Here are the procedures:

1.

bsp_driver_sd.c

Modify the

BSP_SD_WriteBlocks() and

BSP_SD_ReadBlocks_DMA() to support DMA or standard I/O:

// A flag indicating if to use DMA for read/write
uint8_t BSP_SD_Ext_UseDMA = 1;
/*==========================================================================
 Description
 DMA or polling mode of Reads block(s) from a specified address in an SD card
* @param pData: Pointer to the buffer that will contain the data to transmit
 * @param ReadAddr: Address from where data is to be read 
 * @param NumOfBlocks: Number of SD blocks to read 
 * @param Timeout: Timeout for read operation
 * @retval SD status
---------------------------------------------------------------------------*/
uint8_t BSP_SD_ReadBlocks(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks, uint32_t Timeout)
{
 HAL_SD_StateTypeDef state_return;
 uint32_t timeout = 0;
 if (BSP_SD_Ext_UseDMA == 0) {
 if (HAL_SD_ReadBlocks(&hsd, (uint8_t *)pData, ReadAddr, NumOfBlocks, Timeout) != HAL_OK)
 return MSD_ERROR;
 } else {
// Read block(s) in DMA transfer mode
 if (HAL_SD_ReadBlocks_DMA(&hsd, (uint8_t*) pData, ReadAddr, NumOfBlocks) != HAL_OK)
 return MSD_ERROR;
 // Wait until the SDIO/SDMMC and DMA finish the read/write
 timeout = 0;
 do {
 state_return = HAL_SD_GetState(&hsd);
 timeout++;
 } while((state_return == HAL_SD_STATE_BUSY) && (timeout < SD_DATATIMEOUT));
 if (HAL_SD_STATE_READY != state_return)
 return MSD_ERROR;
 }
 return MSD_OK;
}
/*==========================================================================
 Description
 DMA or polling mode of Write block(s) to a specified address in an SD card
* @param pData: Pointer to the buffer that will contain the data to transmit
 * @param WriteAddr: Address from where data is to be written
 * @param NumOfBlocks: Number of SD blocks to write
 * @param Timeout: Timeout for write operation
 * @retval SD status
---------------------------------------------------------------------------*/
uint8_t BSP_SD_WriteBlocks(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks, uint32_t Timeout)
{
 HAL_SD_StateTypeDef state_return;
 uint32_t timeout = 0;
 if(BSP_SD_Ext_UseDMA == 0) {
 if (HAL_SD_WriteBlocks(&hsd, (uint8_t *)pData, WriteAddr, NumOfBlocks, Timeout) != HAL_OK)
 return MSD_ERROR;
 } else {
// Read block(s) in DMA transfer mode
 if (HAL_SD_WriteBlocks_DMA(&hsd, (uint8_t*) pData, WriteAddr, NumOfBlocks) != HAL_OK)
 return MSD_ERROR;
 // Wait until the SDIO/SDMMC and DMA finish the read/write
timeout = 0;
 do {
 state_return = HAL_SD_GetState(&hsd);
 timeout++;
 } 
 while((state_return == HAL_SD_STATE_BUSY) && (timeout < SD_DATATIMEOUT));
if (HAL_SD_STATE_READY != state_return)
 return MSD_ERROR;
 }
 return MSD_OK;
}�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?

2. sd_diskio.c

i) fix the missing initialization code for SDIO

Original generated code:

DSTATUS SD_initialize(BYTE lun)
{
 return SD_CheckStatus(lun);
}�?�?�?�?

Shoud be modified (I have no idea

why BSP_SD_Init() was missing!

:(

DSTATUS SD_initialize(BYTE lun)
{
 Stat = STA_NOINIT;
 if (BSP_SD_Init() == MSD_OK)
 Stat = SD_CheckStatus(lun);
 return Stat;
}�?�?�?�?�?�?�?�?�?

Otherwise, it could not initialize the SDIOvia HAL_SD_Init()!

ii) modifySD_read() andSD_write:

DRESULT SD_read(BYTE lun, BYTE *buff, DWORD sector, UINT count)
{
 DRESULT res = RES_ERROR;
 if (BSP_SD_ReadBlocks((uint32_t*)buff,
 (uint32_t) (sector),
 count,
 SDMMC_DATATIMEOUT) == MSD_OK) {
 // wait until the read operation is finished
 while (BSP_SD_GetCardState()!= MSD_OK);
 res = RES_OK;
 }
 return res;
}
DRESULT SD_write(BYTE lun, const BYTE *buff, DWORD sector, UINT count)
{
 DRESULT res = RES_ERROR;
 if (BSP_SD_WriteBlocks((uint32_t*)buff,
 (uint32_t)(sector),
 count,
 SDMMC_DATATIMEOUT) == MSD_OK) {
 // wait until the Write operation is finished
 while (BSP_SD_GetCardState() != MSD_OK);
 res = RES_OK;
 }
 return res;
}
�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?

3.

fatfs.c

Add a mounting procedure to mount thefile system of SD card

Original generated code:

void MX_FATFS_Init(void) 
{
 /*## FatFS: Link the SD driver ###########################*/
 retSD = FATFS_LinkDriver(&SD_Driver, SDPath);
 /* USER CODE BEGIN Init */
 /* additional user code for init */ 
 
 /* USER CODE END Init */
}�?�?�?�?�?�?�?�?�?�?

Modified code:

void MX_FATFS_Init(void) 
{
 /*## FatFS: Link the SD driver ###########################*/
 retSD = FATFS_LinkDriver(&SD_Driver, SDPath);
 /* USER CODE BEGIN Init */
 /* additional user code for init */ 
 if (retSD != 0)
 Error_Handler();
 if (f_mount(&SDFatFS, (TCHAR const*)SDPath, 0) != FR_OK)
 Error_Handler();
 /* USER CODE END Init */
}�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?

Finally, we could write codes to test the FATFS :

void SDFileTest(void)
{
 FIL MyFile;
 FRESULT res; /* FatFs function common result code */
 uint32_t byteswritten, bytesread; /* File write/read counts */
 uint8_t wtext[] = 'Hello, STM32F4 FatFs!'; /* File write buffer */
 uint8_t rtext[100]; /* File read buffer */
 printf('SD File create\n');
 // Create file test
 if (f_open(&MyFile, 'STMTXT', FA_CREATE_ALWAYS | FA_WRITE) != FR_OK)
 Error_Handler();
 res = f_write(&MyFile, wtext, sizeof(wtext), (void *)&byteswritten);
 if ((byteswritten == 0) || (res != FR_OK))
 Error_Handler();
 f_close(&MyFile);
 printf('done!\n');
 printf('SD File open\n');
 // Read file test
 if (f_open(&MyFile, 'STMTXT', FA_READ) != FR_OK)
 Error_Handler();
 res = f_read(&MyFile, rtext, sizeof(rtext), (UINT*)&bytesread);
 
 if ((bytesread == 0) || (res != FR_OK))
 Error_Handler();
 f_close(&MyFile);
 
 if ((bytesread != byteswritten))
 Error_Handler();
 printf('done!\n');
}
int main(void)
{
.
.
 MX_DMA_Init();
 .
 .
 MX_SDIO_SD_Init();
 .
 .
 MX_FATFS_Init();
 .
 .
 SDFileTest();
 while (1);
}
�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?

It works and note that I have reported this kind of issue to ST on-line support team.

Best regards

31 REPLIES 31
Posted on February 28, 2018 at 14:29

Actually everything is working well except unmounting SD card using f_mount. The idea is to unmount a disc once the power is down and mount it again if the power is restored. So, I tried various combinations of disk unmounting and none of them works:

 - f_mount(NULL, (TCHAR const*)SDPath, 0);

 - f_mount((void *)0, (TCHAR const*)SDPath, 0);

 - f_mount(NULL, (TCHAR const*)SDPath, 1);

 - f_mount((void *)0, (TCHAR const*)SDPath, 1);

Maybe there is some other way to unmount a disk?
Posted on March 01, 2018 at 05:25

Hi Evgenily,

You could try the following steps to solve your problem.

Open the freertos.c file and

1. Modify the SDFileTest() to accept string parameter

/* USER CODE BEGIN FunctionPrototypes */
void SDFileTest(char *msg)
{
 FIL MyFile;
 FRESULT res; /* FatFs function common result code */
 uint32_t byteswritten, bytesread; /* File write/read counts */
 char rtext[256]; /* File read buffer */
// printf(''SD File create
'');
 // Create file test
 if (f_open(&MyFile, ''STMTXT'', FA_CREATE_ALWAYS | FA_WRITE) != FR_OK)
 Error_Handler();
 res = f_write(&MyFile, msg, strlen(msg), (void *)&byteswritten);
 if ((byteswritten == 0) || (res != FR_OK))
 Error_Handler();
 f_close(&MyFile);
// printf(''done!
'');
// printf(''SD File open
'');
 // Read file test
 if (f_open(&MyFile, ''STMTXT'', FA_READ) != FR_OK)
 Error_Handler();
 res = f_read(&MyFile, rtext, sizeof(rtext), (UINT*)&bytesread);
 
 if ((bytesread == 0) || (res != FR_OK))
 Error_Handler();
 f_close(&MyFile);
 
 if ((bytesread != byteswritten))
 Error_Handler();
// printf(''done!
'');
}�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?

2. Modify the StartDefaultTask() something like this

/* StartDefaultTask function */
void StartDefaultTask(void const * argument)
{
 /* init code for FATFS */
 MX_FATFS_Init();
 /* USER CODE BEGIN StartDefaultTask */
 if (f_mount(&SDFatFS, (TCHAR const*)SDPath, 1) != FR_OK)
 Error_Handler();
 SDFileTest(''Test pass 1 before unmount
'');
 // unmount FATFS
 if (f_mount(NULL, (TCHAR const*)SDPath, 1) != FR_OK)
 Error_Handler();
 // Unlink the driver
 FATFS_UnLinkDriver(SDPath);
 // **********************************************************
 //
 // Remove the SD Card and examine the file on the PC
 // then insert the SD card again to the STM32F4 SD Card slot
 //
 // **********************************************************

 // Link the Driver
 // NOTE: we are only interested in calling FATFS_LinkDriver(&SD_Driver, SDPath)
 // but there is no header for it :-(
 //
 MX_FATFS_Init();
 // mount FATFS
 if (f_mount(&SDFatFS, (TCHAR const*)SDPath, 1) != FR_OK)
 Error_Handler();
 SDFileTest(''Test pass 2 after remount
'');
 
 /* Infinite loop */
 for(;;)
 {
 osDelay(1);
 }
 /* USER CODE END StartDefaultTask */
}�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?

I have made a quick test with my development board

0690X00000609a3QAA.png

Hope could help you.

Cheers

Posted on March 03, 2018 at 23:28

Thank you again,

bardeenlai

, for your excellent support. The problem at mine was that I set heap_1 for FreeRTOS by mistake in my project. This caused a problem with unmount, which tries to call vPortFree () to free dynamically allocated memory. Once I put heap_4 everything worked without any problem.

Henry Brasil
Associate II
Posted on March 04, 2018 at 11:24

still remains a problem:

- with STM32CUBE 4.24 and STM32F4 

HAL 1.19 if you use FREERTOS with STATIC allocation fmount FAILS with all your fixes

-

with

STM32CUBE 4.24

and

STM32F4 

HAL 1.19

if you use

FREERTOS

with

DYNAMIC allocation

fmount WORKS with all your fixes

Posted on March 04, 2018 at 11:31

Dear Bardeen Lai, thanks for your suggestions, anyway(try you too if you want):

- with 

STM32CUBE 4.24

 and 

STM32F4 

HAL 1.19 if you use FREERTOS with STATIC allocation fmount FAILS with all your fixes .  

with

STM32CUBE 4.24

and

STM32F4 

HAL 1.19

if you use

FREERTOS

with

DYNAMIC allocation

fmount WORKS with all your fixes

Bardeen Lai
Associate III
Posted on March 27, 2018 at 06:46

Dear all,

Attached is the test program FATFS+FreeRTOS and functions properly under STM32F407x evaluation board.

Please note that the code is generated by STM32CubeMX V4.

As an embedded software engineer, hope that you can enjoy the beauty of STM32CubeMX!

Good luck and best regards

________________

Attachments :

FreeRTOS_FATFS.ioc.zip : https://st--c.eu10.content.force.com/sfc/dist/version/download/?oid=00Db0000000YtG6&ids=0680X000006Hxql&d=%2Fa%2F0X0000000b1R%2FpmZSKrAZhO3J68VTbYtfpUl5NHKF8kykml5Y79TgptQ&asPdf=false

FreeRTOS_FATFS.rar : https://st--c.eu10.content.force.com/sfc/dist/version/download/?oid=00Db0000000YtG6&ids=0680X000006HxrT&d=%2Fa%2F0X0000000b1S%2FuuQk4g.CNmsuIwp5eTlv9aymBpYXbXZKfccBkXvZ8Lg&asPdf=false
Vagni
Associate II
Posted on May 02, 2018 at 19:29

Dear all,

The issue is still present in the lastSTM32F4 Firmware Package v1.0.

I have my custom board based on STM32F401xx cpu and my old SDIO+DMA+FATFS+FreeRTOS application developed with STM32CubeMX v4.0 and

STM32F4 Firmware Package v1.0 that runs without problems, reading and writing files on a SD card.

Now I have to develope a new application on the same board. I decided to start my new project withSTM32CubeMX v4.0 and

STM32F4 Firmware Package v1.0, the last released versions.

Testing SD card accesses with the new created code always fails in the f_mount() function, because anSD_TIMEOUT event (30 seconds) occurs.

Then I followed the excellent help of

bardeenlai

, I use the same settings in my STM32CubeMX project for SDIO, FATFS and FreeRTOS, but f_mount() always fails for theSD_TIMEOUT event.

The generated code just includes the callback functions at the end of

sd_diskio.c source file, but again there is still somethingwrong/missing in the generated code.

Should I useSTM32F4 Firmware Package v1.0 to solve my SD card issue?

Should I keep usingSTM3

2F4 Firmware Package v1.0, waiting for SDIO+DMA+FATFS+FreeRTOS handling to be fixed?

Posted on May 24, 2018 at 10:57

This fixed it for me!  I just defined the two callbacks in the 'USER CODE BEGIN lastSection' and it works with rebuild of project.  Many thanks!

Bringing up a board can be painful in itself, and a lot more so when you can't trust the vendor provided libraries AT ALL.  The ratio of time wasted for customers vs development time of CubeMX is mind boggling.  Using an SD card is such a common thing, and ST should put a big red 'DOES NOT WORK OUT OF THE BOX'  in cubemx.

aasa
Associate

I'm frustrated to find myself impacted by this same bug, and on top of it the STM forums are broken.

All I see is "The original post was too long to process for migration; we will restore it soon."

It's been like this for over a week now.

@Bardeen Lai​ Is there any chance you can re post your solution? I would be very grateful.

Lionel1
Associate II

Hi

I use CubeMX V5.2.1 and firmware is V1.24.1.

I would like to know if the problems you said are corrected or if I must use your workaround ?

Thanks,

Lionel