2024-05-16 03:34 PM
Hello,
I am using the SDMMC1 interface with DMA and FATFS and write data to an SD card. When starting my application with inserted SD card, everything works as expected (reliably and fast). I use FreeRTOS.
When ejecting the SD card during runtime, and re-inserting it, writing succeeds for 2-6 times, but stops working eventually, even after multiple re-initialisations and wait times. The only thing which works is to reset the whole MCU.
Here is what I do:
Before writing, I check the status of the SD card with HAL_SD_GetCardState():
/*
* Purpose:
* Waiting for the SD card to process requests
*/
fenrirStatus_t SD1_WaitForSDInterface(){
// Check current SD card state
HAL_SD_CardStateTypeDef sdState = HAL_SD_GetCardState(&hsd1);
if(sdState == HAL_SD_CARD_PROGRAMMING) {
// If state is currently in programming, wait for max 1 second
uint16_t startWait = osKernelGetTickCount();
while((osKernelGetTickCount() - startWait) < 1000 && sdState == HAL_SD_CARD_PROGRAMMING){
osDelay(75);
sdState = HAL_SD_GetCardState(&hsd1);
}
}
// when state is now in state ready to receive, return okay
switch(sdState){
case HAL_SD_CARD_TRANSFER:
case HAL_SD_CARD_STANDBY:
case HAL_SD_CARD_READY:
SD1_Interfae_Error_Counter = 0;
return fenrirOk;
case 0: // card was most likely disconnected
SD1_Status = SD_NotFound;
break;
default:
break;
};
return fenrirError;
}
In case of ejected SD card, sdState will be 0 indicating no result. Next, I deinitialize the SD interface:
HAL_SD_Abort(&hsd1);
HAL_SD_DeInit(&hsd1);
HAL_SD_MspDeInit(&hsd1);
Now I periodically check for the SD detect signal. As soon as it signals a present SD card, I call the same init functions as before:
HAL_SD_MspInit(&hsd1);
hsd1.ErrorCode = HAL_SD_ERROR_NONE;
hsd1.State = HAL_SD_STATE_RESET;
MX_SDMMC1_SD_Init();
This also succeeds. After that, I mount my filesystem and my write attempts succeed for 2-6 times (usually 4).
But eventually, when checking for the SD card state with the following function calls, I am "stuck" in a timeout loop and do not get a response from the SD card.
HAL_SD_GetCardState -> SD_SendStatus -> SDMMC_CmdSendStatus -> SDMMC_GetCmdResp1
The loop:
do
{
if (count-- == 0U)
{
return SDMMC_ERROR_TIMEOUT;
}
sta_reg = SDMMCx->STA;
} while (((sta_reg & (SDMMC_FLAG_CCRCFAIL | SDMMC_FLAG_CMDREND | SDMMC_FLAG_CTIMEOUT |
SDMMC_FLAG_BUSYD0END)) == 0U) || ((sta_reg & SDMMC_FLAG_CMDACT) != 0U));
Maybe not relevant but here you can see that data is written after reinsertion.
I already tried a lot and I have no idea how to continue debugging this further. Any help is appreciated!
Solved! Go to Solution.
2024-09-11 03:42 AM
I think I figured something out, but it is unrelated to the HAL Driver.
When launching my application (from reset) I create a new file. To speed up memory allocation on the SD card during the logging, I expand the file by a fixed size. When the SD card is removed, and reinserted, the application takes the previous created file and continues writing to the same file.
I can observe the following Behaviour:
1. When the application writes less data to the file then initially allocated, then removed and reinserted results in failed logging
2. When the application writes more data to the file then initially allocated, then removed and reinserted does not result in logging failure
As I am not experienced with FATFS this might be expected since I might miss a operation I need to do or something. Maybe someone else knows?
A strange behaviour I have with the default "HAL_SD_Init" is that there seems to be a timing issue. I need to insert a delay before the "HAL_SD_ConfigWideBusOperation".
if(HAL_SD_GetCardStatus(hsd, &CardStatus) != HAL_OK)
{
return HAL_ERROR;
}
/* Get Initial Card Speed from Card Status*/
speedgrade = CardStatus.UhsSpeedGrade;
unitsize = CardStatus.UhsAllocationUnitSize;
if((hsd->SdCard.CardType == CARD_SDHC_SDXC) && ((speedgrade != 0U) || (unitsize != 0U)))
{
hsd->SdCard.CardSpeed = CARD_ULTRA_HIGH_SPEED;
}
else
{
if(hsd->SdCard.CardType == CARD_SDHC_SDXC)
{
hsd->SdCard.CardSpeed = CARD_HIGH_SPEED;
}
else
{
hsd->SdCard.CardSpeed = CARD_NORMAL_SPEED;
}
}
// HAL_SD_ConfigWideBusOperation fails without delay
osDelay(100);
/* Configure the bus wide */
if(HAL_SD_ConfigWideBusOperation(hsd, hsd->Init.BusWide) != HAL_OK)
{
return HAL_ERROR;
}
I hope this helps someone, and somebody has some insights on the FATFS thingy.
2024-05-16 06:50 PM
I'm not totally sure but try adding MX_FATFS_Init() at the initialization when re-insert SD card.
MX_SDMMC1_SD_Init();
MX_FATFS_Init();
2024-05-17 01:13 AM
I was not able to generate the FATFS integration with CubeMx.
It also seems that
MX_FATFS_Init
only calls the link driver function:
uint8_t FATFS_LinkDriverEx(const Diskio_drvTypeDef *drv, char *path, uint8_t lun)
{
uint8_t ret = 1;
uint8_t DiskNum = 0;
if(disk.nbr < _VOLUMES)
{
disk.is_initialized[disk.nbr] = 0;
disk.drv[disk.nbr] = drv;
disk.lun[disk.nbr] = lun;
DiskNum = disk.nbr++;
path[0] = DiskNum + '0';
path[1] = ':';
path[2] = '/';
path[3] = 0;
ret = 0;
}
return ret;
}
which is only setting variables like path and disk number. No actual file system function calls.
But I also tried to unmount the filesystem with:
f_mount(NULL, "", 1)
No success, unfortunately.
2024-05-17 03:04 AM
Did you try like this?
if(sdcard_insert == true) {
// SD CARD Inserted
f_mount(&FatFs, SDPath, 0); // Mount
} else {
// SD CARD Removed
f_mount(NULL, "", 0); // Unmount
}
or, did you unmount whenever you write file?
1. Mount
2. File Write
3. Unmount
2024-05-17 04:17 AM
Yeah, something similar like you proposed.
But instead of 0 as opt byte I set it to 1 to immediately mount the file system.
I only unmount when I notice that the SD card is removed.
2024-05-24 10:15 AM
Hello @strg-v ,
I have replicated the issue on the STM32F446E-EVAL board and can confirm it's a recognized concern. For certain microSD cards, replacing them while the application is running can lead to application failure. The recommended practice is to reset the board using the "Reset button" after swapping out the uSD card to ensure proper operation.
For the U5 series, developing your application using ThreadX RTOS instead and enabling FileX should resolve this issue, it is possible to unplug/plug or replace the SD card without any need to reset the STM32U575I-EV. That is why MX_SDMMC1_SD_Init() should be public to initialize the newly plugged SD card.
Should there be any new concerns, please do not hesitate to update me.
2024-07-03 06:57 AM
Hi @strg-v ,
Is there any news regarding this issue?
2024-09-11 03:42 AM
I think I figured something out, but it is unrelated to the HAL Driver.
When launching my application (from reset) I create a new file. To speed up memory allocation on the SD card during the logging, I expand the file by a fixed size. When the SD card is removed, and reinserted, the application takes the previous created file and continues writing to the same file.
I can observe the following Behaviour:
1. When the application writes less data to the file then initially allocated, then removed and reinserted results in failed logging
2. When the application writes more data to the file then initially allocated, then removed and reinserted does not result in logging failure
As I am not experienced with FATFS this might be expected since I might miss a operation I need to do or something. Maybe someone else knows?
A strange behaviour I have with the default "HAL_SD_Init" is that there seems to be a timing issue. I need to insert a delay before the "HAL_SD_ConfigWideBusOperation".
if(HAL_SD_GetCardStatus(hsd, &CardStatus) != HAL_OK)
{
return HAL_ERROR;
}
/* Get Initial Card Speed from Card Status*/
speedgrade = CardStatus.UhsSpeedGrade;
unitsize = CardStatus.UhsAllocationUnitSize;
if((hsd->SdCard.CardType == CARD_SDHC_SDXC) && ((speedgrade != 0U) || (unitsize != 0U)))
{
hsd->SdCard.CardSpeed = CARD_ULTRA_HIGH_SPEED;
}
else
{
if(hsd->SdCard.CardType == CARD_SDHC_SDXC)
{
hsd->SdCard.CardSpeed = CARD_HIGH_SPEED;
}
else
{
hsd->SdCard.CardSpeed = CARD_NORMAL_SPEED;
}
}
// HAL_SD_ConfigWideBusOperation fails without delay
osDelay(100);
/* Configure the bus wide */
if(HAL_SD_ConfigWideBusOperation(hsd, hsd->Init.BusWide) != HAL_OK)
{
return HAL_ERROR;
}
I hope this helps someone, and somebody has some insights on the FATFS thingy.