2018-01-02 03:18 AM
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
Solved! Go to Solution.
2018-02-28 06:29 AM
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?2018-02-28 09:25 PM
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
Hope could help you.
Cheers
2018-03-03 03:28 PM
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.2018-03-04 02:24 AM
still remains a problem:
- with STM32CUBE 4.24 and STM32F4HAL 1.19 if you use FREERTOS with STATIC allocation fmount FAILS with all your fixes .
-with
STM32CUBE 4.24andSTM32F4HAL 1.19
if you useFREERTOSwithDYNAMIC allocationfmount WORKS with all your fixes.2018-03-04 03:31 AM
Dear Bardeen Lai, thanks for your suggestions, anyway(try you too if you want):
- with
STM32CUBE 4.24and
STM32F4HAL 1.19 if you use FREERTOS with STATIC allocation fmount FAILS with all your fixes .
-with
STM32CUBE 4.24andSTM32F4HAL 1.19
if you useFREERTOSwithDYNAMIC allocationfmount WORKS with all your fixes.2018-03-26 09:46 PM
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=falseFreeRTOS_FATFS.rar : https://st--c.eu10.content.force.com/sfc/dist/version/download/?oid=00Db0000000YtG6&ids=0680X000006HxrT&d=%2Fa%2F0X0000000b1S%2FuuQk4g.CNmsuIwp5eTlv9aymBpYXbXZKfccBkXvZ8Lg&asPdf=false2018-05-02 10:29 AM
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?
2018-05-24 03:57 AM
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.
2018-09-12 12:46 AM
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.
2019-07-12 06:26 AM
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