FileX SD card insertion/removal handling
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2024-04-09 1:53 PM
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);
}
}
- Labels:
-
AzureRTOS
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2024-04-15 7:28 AM
hi @Pajaka
Not clear on which STM32 you are working but below application code that support uSD hot plug.
regards
Haithem.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2024-04-15 11:24 PM
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2024-04-15 11:53 PM
>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 :
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.)
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2024-04-16 2:42 AM
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2024-04-16 2:57 AM
Ok, so ... did you try :
fresult = HAL_SD_DeInit(&hsd1); //error...MX_FATFS_Init
...
//with new inserted card ->
fresult = HAL_SD_InitCard(&hsd1); // insert -> then new init
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2024-04-16 3:01 AM
I haven't tried this yet. I will test it in a few hours and come back. I tried the following in a similar fashion
fx_stm32_sd_deinit(0);
with no luck.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2024-04-17 11:28 AM
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2024-04-18 1:11 AM
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2024-04-18 1:49 AM
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.
