Zephyr SD Card Remount Issue: fs_unmount vs. Disk Deinitialization Leading to EIO or Blocked Workqueue

Zephyr RTOS SD Card Hot-Plug Re-Mount Issue

I'm implementing SD card hot-plug functionality in a Zephyr RTOS application. My workflow for managing the SD card involves the following Zephyr APIs:

Initialization/Insertion:

  • disk_access_ioctl(DISK_DRIVE_NAME, DISK_IOCTL_CTRL_INIT, NULL)
  • fs_mount(&mp)

Removal:

  • fs_unmount(&mp)

Problem Description:

When an SD card is inserted for the first time or on power-up, the sequence of disk_access_ioctl(DISK_IOCTL_CTRL_INIT) followed by fs_mount() works perfectly.

However, if I remove the SD card (triggering fs_unmount()) and then re-insert it, the re-initialization (disk_access_ioctl(DISK_IOCTL_CTRL_INIT)) succeeds, but the subsequent fs_mount() call fails consistently with an EIO (-5) error. The relevant log output is:

<err> sd: Failed to read from SDMMC -5
<err> sd: Card read failed
<err> fs: fs mount error (-5)

My understanding, based on the Zephyr documentation (e.g., the general usage of fs_unmount and the disk_access API), is that fs_unmount() should sufficiently deinitialize or prepare the disk for a future re-mount. It says I should have to explicitly use DISK_IOCTL_CTRL_DEINIT after fs_unmount.

Additional Observation (if I were to hypothetically force deinitialization):

If I manually deinit using disk_access_ioctl, within a k_work item scheduled on the system workqueue, it causes that k_work item to become permanently blocked or never complete its execution after the first removal. I also tried passing a pointer to a bool set as true as the buf arg but that also causes more errors.

My questions are:

  1. What is the correct Zephyr API sequence or state management required to reliably remount an SD card after it has been fs_unmount'ed and then re-inserted?
  2. Why would disk_access_ioctl(DISK_IOCTL_CTRL_INIT) succeed on re-insertion, but fs_mount() subsequently fail with EIO? What internal states or resources might be improperly released or re-initialized?
  3. Am I using disk_access_ioctlcommandsincorrectly?

Any insights into successfully managing SD card hot-plugging in Zephyr, specifically regarding reliable re-mounting after unmounting, would be greatly appreciated.

Parents Reply
  • Hi,

    There doesn't appear to be a DISK_IOCTL_CTRL_DEINIT explicitly documented or commonly used that would be called after fs_unmount.

    Documentation specifies that de-initializing the disk should be left to filesystem implementations. User application should not need to manually de-initialize the disk. Calling fs_unmount() should be sufficient. However, for hot-pluggable devices, DISK_IOCTL_CTRL_DEINIT might be needed for disk de-initialization. In this case, initialization and de-initialization must be balanced. You can get more information in initializing disks. Information about DISK_IOCTL_CTRL_DEINIT is shown in the disk driver interface API

    Best regards,
    Dejan



Children
  • Sorry my bad. I had tried DISK_IOCTL_CTRL_DEINIT but it causes the system to hang. I have tried it with both passing NULL as buf arg and also pointer to boolean true. In both cases the system workqueue hangs and does not release

  • So this is how my insertion and removal code was implemented. Everything is done in a workqueue.

    On Insert:

    disk_access_ioctl("SD", DISK_IOCTL_CTRL_INIT, NULL);
    fs_mount(&sd_mount);

    On Removal - Issues Encountered:

    Approach 1: Only unmount

    fs_unmount(&sd_mount);

    Result: Error on re-insert:

    <err> sd: Failed to read from SDMMC -5
    <err> sd: Card read failed
    <err> fs: fs mount error (-5)

    Approach 2: Unmount + deinit

    fs_unmount(&sd_mount);
    disk_access_ioctl("SD", DISK_IOCTL_CTRL_DEINIT, NULL);

    Result: System workqueue permanent blockage with logs:

    [00:00:13.367,187] <dbg> sdhc: unmount_filesystem: Starting filesystem unmount
    [00:00:13.367,248] <dbg> sdhc: unmount_filesystem: Disk unmounted from /SD:
    [00:00:27.875,366] <wrn> sd: Card busy when powering off
    [00:00:27.875,396] <dbg> sdhc: unmount_filesystem: Disk deinitialized successfully
    [00:00:27.875,396] <inf> sdhc: SD card removal cleanup completed
    [00:00:27.875,427] <dbg> sdhc: sdhc_work_handler: SDHC work handler completed

    Note: Long delay between unmount and deinit completion

    Approach 3: Force deinit

    bool force = true;
    res = disk_access_ioctl("SD", DISK_IOCTL_CTRL_DEINIT, &force);

    Result: Same permanent workqueue blockage as Approach 2

  • Hi,

    If you unmount and deinit, that is correct but you may have to wait. If this blocks for some reason, then there might be a  problem with either VFS (10% chance) or Disk Access (90%).
    You must provide a user triggered mode where mount points are unmounted and disk is deinitialized, for a card to be removed.

    Best regards,
    Dejan

  • Hi thanks for the reply.

    It is blocking and does not release.

    The proposed user-triggered mode is not possible in a lot of systems, including mine. I expect the user to remove the card and insert it as they please, without unmounting first or deinitializing. This is very common in consumer and embedded devices where users aren’t expected to perform manual unmount procedures - for example, in handheld data loggers or cameras.

    Would you or anyone happen to know how to solve this?

    Thank you! 

    Aanas

Related