Unable to remount SD-Card after physically ejecting without rebooting

Hi there,

I'm using an nRF 52840 with SD-Card connected over SPI. I've attached a runnable project that compiles with NCS V2.1.1. The challenge is as follows.

We need the SD-Card to be shut down. For this, we're using a high-side FET and we're suspending the SPI peripheral through Zephyr's power management API to prevent backfeeding through MOSI/MISO. As the SDHC driver from Zephyr makes the CS-pin logically low (which is high) when the card is unmounted, this results in the SD-card backfeeding through the FET.

We're working around this by manually controlling the CS-pin from the application; set it to an active state (0V as it's active low) on boot and never touch it again. We don't provide the cs-gpios in the devicetree to make sure it isn't overriden by the driver. This all in all is already quite the hassle, but it goes on.

After having manually removed the SD-card and re-insterting it, we're unable to remount the sd-card. Even if we keep the CS-line asserted at all times, and the FET providing power to the sd-card at all times.

So in short; we want to know how we can eject, insert, mount, unmount, eject, insert, mount, etc. without rebooting once.

Kind regards,

Jochem

5428.low_power_sdcard.zip

  • Hi
    I have had similar concerns. The issue is found in sdmmc_subsys.c:40 where the initialization is skipped if card already had status SD_OK.

    That status never changes to anything else it seems after the first card is detected and inited.

    Here is a workaround that works for me. (I had to copy the enums and struct definitions from the sdmmc_subsys.c file.)

    #include <zephyr/sd/sd.h>
    
    extern "C" 
    {
    enum sd_status {
    	SD_UNINIT,
    	SD_ERROR,
    	SD_OK,
    };
    struct sdmmc_data {
    	struct sd_card card;
    	enum sd_status status;
    	char *name;
    };
    }
    
    
    void MountSD() {
        const struct device *dev = mmc_dev;
    	struct sdmmc_data *data = (sdmmc_data*)dev->data;
        data->status = SD_UNINIT; // Set to UNINIT state prior to mounting
        //....
        //Do mounting etc here...
    }

    I have not found a less hacky way yet...

Related