cancel
Showing results for 
Search instead for 
Did you mean: 

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

strg-v
Associate II

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!

 

1 ACCEPTED SOLUTION

Accepted Solutions
strg-v
Associate II

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.

View solution in original post

7 REPLIES 7
hardrock
Associate III

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

 

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.

hardrock
Associate III

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

 

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.

SHs
ST Employee

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.

Please close this topic by clicking on “Accept as solution" button if it fully answered your question.
SHs
ST Employee

Hi @strg-v ,

Is there any news regarding this issue?

Please close this topic by clicking on “Accept as solution" button if it fully answered your question.
strg-v
Associate II

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.