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 13, 2018 at 21:38

I'm using STM32CubeMx version 4.24.0 with F4 MCU package 1.19.0.  And yes, it fails at f_mount.  Disabled DMA (FATFS Configuration -> IPs Instances -> Use dma template), and now it works.

Bardeen Lai wrote:

Hi Mark,

I have just upgraded to 4.24 and STM32F4 firmware v1.19 today. Yes you’re right it stops at f_mount. Now I’m hunting the root cause. By the way, I’m also using the CAN API in v1.18. I haven’t got time to port to V1.19. According to the release note, ST has changed the HAL of CAN API. Hope I could share with you later on.

cheers

Posted on February 15, 2018 at 07:51

Disable the DMA got me a little further. I can read files. But now when create a file (still your 

SDFileTest) and it fails at SD File create Err 12:

FR_NOT_ENABLED, /* (12) The volume has no work area */

This problem was introduced in December after version 1.16.0 and i do not understand why it is still not repaired by ST???

Posted on February 15, 2018 at 13:49

FR_NOT_ENABLED

suggests the volume needs to be f_mount()ed

Watch how variables/structures are initialized, especially auto/local ones.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on February 18, 2018 at 01:59

Try changing the value at Configuration -> SDIO -> SDIOCLK clock divide factor

Mark Shoe wrote:

FR_NOT_ENABLED, /* (12) The volume has no work area */

This problem was introduced in December after version 1.16.0 and i do not understand why it is still not repaired by ST???

Posted on February 18, 2018 at 18:42

bardeenlai

, did CubeMX V4.24 with STM32F4 HAL firmware V1.19 work well with FATFS R0.12C out of the box at yours? You wrote above that you faced problems with f_mount. How did you solve them? What modifications did you additionally do for it?

I was able to make f_mount work OK by applying suggestions described in this post:

https://community.st.com/0D50X00009XkWyLSAV

, however now creation of a file does not work.

Can you suggest anything?

Bardeen Lai
Associate III
Posted on February 19, 2018 at 05:27

Hi, all

Again, the latest STM32CubeMX V4.24 with STM32F4 HAL firmware V1.19 is great and works well for FATFS R0.12C!

I guess some of you CANNOT mount or open files properly could be one of the following issues:

1. Make sure the project setting of heap and stack sizes are enough, for example

   Heap size: 0x1000

   Stack size: 0x800

0690X00000609gpQAA.png

2. Make sure the number of files opened simultaneously >=2, please change the number if you open or create files more than 2!

0690X00000609bQQAQ.png

3. If you are going to use DMA, then you have to activate the DMA settings at SDIO

0690X00000609jnQAA.png

If you still have problems, please refer to some examples of STM32CubeMX located at ''C:\Users\xxx\STM32Cube\Repository\STM32Cube_FW_F4_V1.19.0\Projects''

Good luck and cheers

Bardeen LAI

Posted on February 21, 2018 at 09:45

bardeenlai

, thank you for your response.

I see that you are not using FreeRTOS in your application. I assume that the problem comes out when FATFS is used together with FreeRTOS enabled (maybe due to FATFS flag 'FATFS Configuration -> IPs Instances -> Use dma template', which you can not disable when using FreeRTOS).

Has anyone successfully launched CubeMX V4.24 with STM32F4 HAL firmware V1.19 with FATFS R0.12C and all of it with FreeRTOS?

Examples provided by CubeMX show application of FATFS without FreeRTOS.

Bardeen Lai
Associate III
Posted on February 22, 2018 at 07:16

Hi,

I have tested FATFS by use of DMA under FreeRTOS, it works!

Here is the screen capture of setting STM32CubeMX V4.24

0690X00000609MwQAI.png

Project Setting:

0690X00000609k3QAA.png

Make sure FATFS configuration ''Use dma template'' enabled:

0690X00000609m8QAA.png

SDIO settings:

Enable NVIC

0690X00000609mDQAQ.png

and DMA settings

0690X00000609mIQAQ.png

Then, tune the FreeRTOS, stack and heap sizes

0690X00000609htQAA.png

After generating codes, you have to modify the following files:

A. sd_diskio.c (as told by

), you have to insert the following code at the end of the file

#endif /* _USE_IOCTL == 1 *//* USER CODE BEGIN afterIoctlSection *//* can be used to modify previous code / undefine following code / add new code *//* USER CODE END afterIoctlSection *//* USER CODE BEGIN callbackSection *//* can be used to modify / following code or add new code */void HAL_SD_TxCpltCallback(SD_HandleTypeDef *hsd){ osMessagePut(SDQueueID, WRITE_CPLT_MSG, osWaitForever);}void HAL_SD_RxCpltCallback(SD_HandleTypeDef *hsd){ osMessagePut(SDQueueID, READ_CPLT_MSG, osWaitForever);}/* USER CODE END callbackSection */�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?

NOTE: HAL_SD_ReadBlocks_DMA and HAL_SD_WriteBlocks_DMA require DMA complete TX/RX interrupt to signal the foreground process whether the DMA TX/RX has been done or not.

B. If you are using MDK-ARM as your IDE, you should eliminate the ''U'', otherwise it would cause compiler error in port.c

Modify the stm32f407xx.h header file to fix error:

#define __NVIC_PRIO_BITS 4 /*!< STM32F4XX uses 4 Bits for the Priority Levels */�?

C. Modify the freertos.c file, insert the FATFS file test procedure:

/* USER CODE BEGIN FunctionPrototypes */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''); // 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!'');// 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!'');}�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?

and insert the following piece of code to

/* 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, 0) != FR_OK) Error_Handler(); SDFileTest(); /* Infinite loop */ for(;;) { osDelay(1); } /* USER CODE END StartDefaultTask */}�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?

I could email you the complete project file if you need.

Good luck and cheers

Bardeen LAI

Posted on February 23, 2018 at 10:56

Thank you,

bardeenlai

, your solution really worked! You are my hero!

Posted on February 25, 2018 at 02:09

I am using CubeMX V4.24 with STM32F4 HAL firmware V1.19 and adding the two callbacks as you showed fixed it for me.

Thank you very much!