Skip to main content
Visitor II
April 9, 2024
Question

FileX SD card insertion/removal handling

  • April 9, 2024
  • 3 replies
  • 2885 views

Hi,

how am I supposed so handle the reinsertion event while using the FileX with an SD card? All the examples I saw assume the SD card cannot be ejected while in use which is obviously unrealistic.

I tried to do it according to the official docs and when the ejection is detected I call the fx_media_abort and fx_stm32_sd_deinit. But during the reinsertion when I call the fx_media_open again I get the FX_IO_ERROR. At this point the driver should be in an uninitialized state and the fx_media_open should call the fx_stm32_sd_init function.

Can anyone relate to this problem? Here is the code example. The FX_STM32_SD_INIT macro is defined.

 

if(card_insertion_flag.Get(0x03, EventGroup::Access::bit_or_clear, TX_WAIT_FOREVER,flag))
{
	if(flag & 0x01)
	{
		//Card inserted
		uint8_t cntr = 0;
		do
		{
			status = fx_media_open(&this->sdio_disk, (char* )"SD card", fx_stm32_sd_driver, 0, (VOID *) media_memory, this->media_memory_size);
			HAL_Delay(50);
		}
		while(cntr++ < 50 && status != FX_SUCCESS);

		if(status != FX_SUCCESS)
		{
			Error_Handler();
		}

		status = fx_file_open(...
	}
	else
	{
		//Here I tried all this and its combinations
		//status = fx_media_abort(&this->sdio_disk);
		//status = fx_media_close(&this->sdio_disk);
		//fx_stm32_sd_deinit(0);
	}
}

 

 

    This topic has been closed for replies.

    3 replies

    ST Employee
    April 15, 2024

    hi @Pajaka 

    Not clear on which STM32 you are working but below application code that support uSD hot plug.

    https://github.com/STMicroelectronics/STM32CubeU5/blob/main/Projects/STM32U575I-EV/Applications/FileX/Fx_uSD_File_Edit/FileX/App/app_filex.c

    regards
    Haithem.

    PajakaAuthor
    Visitor II
    April 16, 2024

    Thanks for your reply, but I cannot see how the code provided handles a hot plug at all. What happens when the SD card is ejected and the code is already beyond the line 232 (app_filex.c) as shown below?

    if (media_status == MEDIA_CLOSED)

     Is it assumed that the code gets executed so fast that you cannot physically manage to insert and eject the card during one execution of the while loop? What if I need to stream a long (mins to 1h) experimental data to a file? Should I mount and unmount the media between each writes as shown in the example? That would create a huge overhead. I could create a large buffer that gets written to the file every X seconds, but then what if the card is ejected before the write operation? I would lose my data.

    The problem is that I cannot unmount the media when streaming the data. When the card is ejected, I call the fx_media_abort and wait for the card insertion. After that when I call the fx_media_open again, I get the FX_IO_ERROR. This is definitely a FW error as it runs correctly again when I restart the MCU. 

    I will try to unmount the media when not used and then get along with the fact that during the experiment I cannot handle the ejection gracefully and simply restart the MCU.

    Super User
    April 16, 2024

    >what if the card is ejected before the write operation? I would lose my data.

    Right - or the card might be damaged, if pulled out, while writing.

    Just try it on your PC: write a big file to the card, pull it out, while writing - then insert it, and see, what the PC telling you about the card now...

    There is no simple solution to the problem...

    but in FileX there is :

    AScha3_0-1713250263072.png

    Maybe this could help - at least, not destroy the whole file system, when power off or pull out at wrong moment.

    Try it and tell ... (I am about to test it next time also.)

    PajakaAuthor
    Visitor II
    April 16, 2024

    This is all known to me, that the filesystem may end up being corrupted, but the problem is when the card is reinserted and I try to mount it - fx_media_open returns IO_ERROR. Corrupted filesystem would result in a different error code.

    When I reset the MCU after the reinsertion, everything works good, so it must be a FW problem. Some initialization code that runs at the startup and is not called during the repeated card insertion.

    I forgot to mention that I use a L562RE MCU and a 4bit SDMMC. Code is written in C++ and everything works as expected except the reinsertion handling.

    PajakaAuthor
    Visitor II
    April 17, 2024

    It was indeed a FW error. I performed a debug session and pin pointed an exact point of failure which turned out to be the cube generated macro

    FX_STM32_SD_PRE_INIT(media_ptr);
    //which expands to this:
    do { \
     if ((tx_semaphore_create(&sd_rx_semaphore, "sd rx transfer semaphore", 0) != TX_SUCCESS) || \
     (tx_semaphore_create(&sd_tx_semaphore, "sd tx transfer semaphore", 0) != TX_SUCCESS)) \
     { \
    	_media_ptr->fx_media_driver_status = FX_IO_ERROR; \
     } \
    } while(0)

    Inside this macro the rx and tx semaphores for the SDMMC are created and the return value is expected to be TX_SUCCESS which is not because the semaphores already exist from the previous initialization. I use the Debug configuration right now so the variables (and structures) get null initialized. That's why it worked when I restarted the MCU during reinsertion.

    So what I did is deleting those semaphores in the uSD ejection handling so that these semaphores can get created during the repeated insertion. My code looks like this now.

    //after includes
    extern TX_SEMAPHORE sd_tx_semaphore;
    extern TX_SEMAPHORE sd_rx_semaphore;
    //actual Task
    while (this->should_run)
    {
    	if (card_insertion_flag.Get(0x03, EventGroup::Access::bit_or_clear, TX_WAIT_FOREVER, flag))
    	{
    		if (flag & 0x01)
    		{
    			//Card inserted
    			memset((void*)&this->sdio_disk,0,sizeof(FX_MEDIA));
    			MX_SDMMC1_SD_Init();
    			status = fx_media_open(&this->sdio_disk, (char* )"SD card", fx_stm32_sd_driver, 0, (VOID *) this->media_memory, this->media_memory_size);
    			if (status != FX_SUCCESS)
    			{
    				Error_Handler();
    			}
    
    			LoadSettings();
    			LoadAccCal();
    			LoadMagCal();
    			msg.event_type = static_cast<uint32_t>(FilesystemEventID::settings_parsed);
    			app.Notify(this, msg);
    		}
    		else
    		{
    			status = fx_media_abort(&this->sdio_disk);
    			HAL_SD_DeInit(&hsd1);
    			tx_semaphore_delete(&sd_rx_semaphore);
    			tx_semaphore_delete(&sd_tx_semaphore);
    		}
    	}
    }

     Please add a function that deletes these semaphores during the SD deinit. Or you can test whether these semaphores were already initialized during the SD init - check the semaphore ID for instance, it gets initialized to a non zero value after creation.

    ST Employee
    April 18, 2024

    HI @Pajaka 

    thanks indeed for the sharing. the issue will be reported and fixed as soon as possible.

    Could you please provide details on which STM32 are you working?

    regards
    Haithem.

    ST Employee
    April 18, 2024

    Hi @Pajaka,

    After checking further, you'll be able to solve your issue. when calling fx_media_abort(), the macro FX_STM32_SD_POST_ABORT(_media_ptr) https://github.com/STMicroelectronics/STM32CubeU5/blob/f0f063146b444e37ef6b1b3d2f219df728a12407/Projects/STM32U575I-EV/Applications/FileX/Fx_uSD_File_Edit/FileX/Target/fx_stm32_sd_driver.h#L107 will be called.

    you can simply define it as done for FX_STM32_SD_POST_DEINIT(_media_ptr)

     

    #define FX_STM32_SD_POST_DEINIT(_media_ptr) do { \
     tx_semaphore_delete(&sd_rx_semaphore); \
     tx_semaphore_delete(&sd_tx_semaphore); \
     } while(0)
    
    /* USER CODE END FX_STM32_SD_POST_DEINIT_TX */
    
    /* Macro called after the abort request */
    /* USER CODE BEGIN FX_STM32_SD_POST_ABORT */
    
    #define FX_STM32_SD_POST_ABORT(_media_ptr) FX_STM32_SD_POST_DEINIT(_media_ptr)

    Could you try and let us know?

     

    regards
    Haithem.