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

1 ACCEPTED SOLUTION

Accepted Solutions
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

View solution in original post

31 REPLIES 31
Tobias Wedell
Associate II
Posted on January 04, 2018 at 10:14

Hi,

in my case the auto generatedsource code from CubeMX is working. I have the same version constellation and use a STM32F4

I only have to change two lines in sd_diskio.c. I do the BSP_SD_Init and the f_mount in my user code and not in the drivers itself. Replace the two callbacks for DMA handling in sd_dsikio.clike the comments tells:

void BSP_SD_WriteCpltCallback()
{
 WriteStatus = 1;
}�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?
void BSP_SD_ReadCpltCallback()
{
 ReadStatus = 1;
}�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?

In my case I have replace this with:

void HAL_SD_TxCpltCallback(SD_HandleTypeDef *hsd)
{
 WriteStatus = 1;
}�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?
void HAL_SD_RxCpltCallback(SD_HandleTypeDef *hsd)
{
 ReadStatus = 1;
}
�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?

Best regards�?
Jeon HakJae
Associate
Posted on January 05, 2018 at 01:45

Good !! It work for me !!! Thank you 

Mark Shoe
Senior
Posted on January 13, 2018 at 20:58

Thanks a lot reading a file will work now however SDFileTest will crash in line 19 f_close(&MyFile);

And it was needed to set BSP_SD_Ext_UseDMA = 0;

FATFS R0.12

CubeMX 4.32.0 

STM32F427VIT

1 bit SDIO

Lucky to have a backup of the old project with the FATFS R0.11, your

SDFileTest 

does work!
Posted on January 14, 2018 at 17:02

Humour me and try this when BSP_SD_Ext_UseDMA = 1

...
 if ((BSP_SD_Ext_UseDMA == 0) || (NumOfBlocks == 1)) {
 if (HAL_SD_WriteBlocks(&hsd, (uint8_t *)pData, WriteAddr, NumOfBlocks, Timeout) != HAL_OK)
 return MSD_ERROR;
 } else {...

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Mark Shoe
Senior
Posted on January 27, 2018 at 17:50

There is a new Cube 4.24.0 and new drivers FW_F4 V1.19.0 bus still the fatfs functions are not working. Still crash on f_mount. Also the CAN API's are very much changed so project got lots of errors.Why? this makes the code for can less portable for other series.

abhishek kr
Associate II
Posted on January 30, 2018 at 07:40

Can we have HAL_SDWriteBlocks in DMA modec.

And I am not able to configure the cube generated code for USB-Device FS, With SDIO all in DMA mode along with fatfs

Posted on January 30, 2018 at 14:48

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

Bardeen Lai
Associate III
Posted on February 02, 2018 at 08:58

Hi, the latest CubeMX V4.24 with STM32F4 HAL firmware V1.19 has fixed the above issues. It works fine! I have just finished the Bootloader IAP (In-Application Programming) firmware by use of the latest CubeMX.

The Bootloader IAP utilizes the FATFS to access SD card and upload the binary file to flash address 0x08008000. Here is the portion code of main()

int main(void)
{
 /* USER CODE BEGIN 1 */
 void (*MemJump)(void);
 
 /* USER CODE END 1 */
 /* MCU Configuration----------------------------------------------------------*/
 /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
 HAL_Init();
 /* USER CODE BEGIN Init */
 /* USER CODE END Init */
 /* Configure the system clock */
 SystemClock_Config();
 /* USER CODE BEGIN SysInit */
 MX_GPIO_Init();
 MX_RTC_Init();
 SetLocalTimeZoneHour(8);
 //----------------------------------------------
 // initialize LCM (128x64 dot-matrix LCM, SPI2)
 //----------------------------------------------
 Lcm_Init(26);
 // 012345678901234567890
 printf('Bootloader IAP #V1.0');
 MX_SDIO_SD_Init();
 MX_FATFS_Init();
 app_main(NULL);
 printf('Jump to Application..');
 // must deinitialize before jumpping!
 HAL_DeInit();
 // Initialize user application's Stack Pointer
 // #define APPLICATION_START_ADDR = 0x08008000
 MemJump = (void (*)(void))(*((uint32_t *)(APPLICATION_START_ADDR + 4)));
 __set_MSP(*(__IO uint32_t*)APPLICATION_START_ADDR);
 MemJump();
 /* USER CODE END SysInit */
 /* Initialize all configured peripherals */
// MX_GPIO_Init();
// MX_SDIO_SD_Init();
// MX_SPI2_Init();
// MX_FATFS_Init();
// MX_RTC_Init();
// MX_IWDG_Init();
 /* USER CODE BEGIN 2 */
 /* USER CODE END 2 */
 /* Infinite loop */
 /* USER CODE BEGIN WHILE */
 while (1)
 {
 /* USER CODE END WHILE */
 /* USER CODE BEGIN 3 */
 }
 /* USER CODE END 3 */
}
�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?

Good luck & cheers!