Skip to main content
Explorer
May 16, 2024
Solved

STM32U575 Writing to SD card fails after few times after re-insert

  • May 16, 2024
  • 4 replies
  • 2589 views

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.

strgv_0-1715898438255.png

I already tried a lot and I have no idea how to continue debugging this further. Any help is appreciated!

 

    This topic has been closed for replies.
    Best answer by strg-v

    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.

    4 replies

    Visitor II
    May 17, 2024

    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();

     

    strg-vAuthor
    Explorer
    May 17, 2024

    I was not able to generate the FATFS integration with CubeMx. 

    See: https://community.st.com/t5/stm32-mcus-embedded-software/stm32u5-file-system-with-freertos/td-p/55673

    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.

    Visitor II
    May 17, 2024

    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

     

    strg-vAuthor
    Explorer
    May 17, 2024

    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.

    ST Employee
    May 24, 2024

    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.

    ST Employee
    July 3, 2024

    Hi @strg-v ,

    Is there any news regarding this issue?

    strg-vAuthorAnswer
    Explorer
    September 11, 2024

    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.