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 Children
  • 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



  • 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

Related