SD card init failed

mattia424
Posts: 13
Joined: Sun Jan 07, 2024 11:56 pm

SD card init failed

Postby mattia424 » Thu Jan 25, 2024 11:58 pm

Hello, everyone,
I'm fairly new to ESP-IDF and I'm trying to use an SD via SPI but every time it returns

Code: Select all

 E (641) vfs_fat_sdmmc: sdmmc_card_init failed (0x109).
This is the code I use:

Code: Select all

#define SD_CLK_PIN          GPIO_NUM_5
#define SD_MISO_PIN         GPIO_NUM_6
#define SD_MOSI_PIN         GPIO_NUM_7
#define SD_CS_PIN           GPIO_NUM_8

ESP_LOGI(__FUNCTION__, "Initializing SD card");

    // Configura i pin SPI per la comunicazione con la SD
    spi_bus_config_t buscfg = {
        .mosi_io_num = SD_MOSI_PIN,
        .miso_io_num = SD_MISO_PIN,
        .sclk_io_num = SD_CLK_PIN,
        .quadwp_io_num = -1,
        .quadhd_io_num = -1,
        .max_transfer_sz = 4000,
    };

    // Inizializza il bus SPI
    ESP_ERROR_CHECK(spi_bus_initialize(SPI2_HOST, &buscfg, SPI_DMA_CH_AUTO));

    spi_device_interface_config_t devcfg = {
        .mode = 0,                         // Modalità SPI
        .clock_speed_hz = SDMMC_FREQ_DEFAULT, // Velocità di clock SPI
        .spics_io_num = SD_CS_PIN,         // Pin del chip select
        .queue_size = 7,                   // Lunghezza della coda delle transazioni SPI
    };

    spi_device_handle_t spi;
    ESP_ERROR_CHECK(spi_bus_add_device(SPI2_HOST, &devcfg, &spi)); 

    sdspi_dev_handle_t sd_handle;
    sdspi_device_config_t dev_config = SDSPI_DEVICE_CONFIG_DEFAULT();
    dev_config.host_id   = SPI2_HOST;
    dev_config.gpio_cs   = SD_CS_PIN;

    ESP_ERROR_CHECK(sdspi_host_init_device(&dev_config, &sd_handle));

    sdmmc_host_t sd_host = SDSPI_HOST_DEFAULT();
    sd_host.slot = SPI2_HOST;
    sd_host.max_freq_khz = SDMMC_FREQ_DEFAULT;

    sdmmc_card_t *card;

    esp_vfs_fat_sdmmc_mount_config_t mount_config = {
        .format_if_mount_failed = false,
        .max_files = 5,
        .allocation_unit_size = 16 * 1024
    };

    ESP_ERROR_CHECK(esp_vfs_fat_sdspi_mount("/", &sd_host, &dev_config, &mount_config, &card));
    
 
I am sure the hardware works and the pins are right because if I use the arduino-esp32 framework it works.
Thanks to anyone who can help me out!

MicroController
Posts: 1736
Joined: Mon Oct 17, 2022 7:38 pm
Location: Europe, Germany

Re: SD card init failed

Postby MicroController » Fri Jan 26, 2024 1:36 pm

See https://github.com/espressif/esp-idf/bl ... main.c#L67

Don't spi_bus_add_device/sdspi_host_init_device yourself when using esp_vfs_fat_sdspi_mount.

mattia424
Posts: 13
Joined: Sun Jan 07, 2024 11:56 pm

Re: SD card init failed

Postby mattia424 » Fri Jan 26, 2024 2:21 pm

I tried removing spi_bus_add_device but I still get the same error.
I tried loading the example but even with that I still get the same error.
I have tried lowering the frequency to 4000kHz as I have read in other posts but nothing.

On lowering the frequency I did several tests and noticed that:
- Arduino-espidf starts with a frequency of 400kHz and then does the data transfer in 4000kHz
- ESPIDF I can only see that it starts with a frequency of 400kHz and then I can't detect anything else because there is no transfer and consequently any frequency value has no impact.

Below you can see the physical behaviour
Attachments
espidf_total.png
espidf_total.png (134.41 KiB) Viewed 3850 times
Arduino.png
Arduino.png (72.36 KiB) Viewed 3850 times

uC_Jon
Posts: 18
Joined: Fri Jan 05, 2024 7:03 pm

Re: SD card init failed

Postby uC_Jon » Sat Jan 27, 2024 10:56 am

When I used the example for the sdcard on an esp32-c6 I had to add a delay between the spi_bus_initalize and the sdspi_mount of a few ms to get the sdcard to consistently work at every single boot otherwise it would fail more often than not. I should note that it also failed after a warm reboot (reset) caused by the monitor. I also added pullup resistors as the sdcard breakout board didn't have them (but I can't recall if that made any difference) and the spi was connected to both the sdcard and one of those cheap spi lcd/touch devices.

I made quite a few mods to the code (I'm unit testing multiple different things on different dev-kit's) including adding the LCD SPI device (just spi_bus_add_device) and the touch device (also just an add to the spi bus). Just adding those two devices was enough of a delay to allow the sdcard to init and work without problems close to 100% of the time (I say close, but after multiple boots from cold and warm, from monitoring, there was not a single failed to init error).

My guess is that it takes a non-zero amount of time for the voltage to stabilize, either on the device (devkit) as a whole or at the sdcard breakout board (which are connected on a breadboard with circa 70mm long jumper wires and then 30mm to the lcd/touch), enough to allow the sdcard to work. As I don't have a scope I am going entirely on gut feeling, but as the delay resolves the issue it seems like a good candidate.

Edited to add the area of code that allows it to work. As I say, this code was originally the example code that has been modified so it should be fairly easy to see where it fits.

Code: Select all

    spi_bus_config_t bus_cfg = {
        .mosi_io_num = PIN_NUM_MOSI,
        .miso_io_num = PIN_NUM_MISO,
        .sclk_io_num = PIN_NUM_CLK,
        .quadwp_io_num = -1,
        .quadhd_io_num = -1,
        .max_transfer_sz = 4000,
    };
    ret = spi_bus_initialize(host.slot, &bus_cfg, SDSPI_DEFAULT_DMA);
    if (ret != ESP_OK) {
        ESP_LOGE(TAG, "Failed to initialize bus.");
        return;
    }

    #define EXAMPLE_LCD_PIXEL_CLOCK_HZ     (20 * 1000 * 1000)
    spi_device_interface_config_t dev_cfg = {
        .flags = SPI_DEVICE_HALFDUPLEX | SPI_DEVICE_TXBIT_LSBFIRST | SPI_DEVICE_3WIRE,
        .clock_speed_hz = EXAMPLE_LCD_PIXEL_CLOCK_HZ,
        .mode = 0,
        .queue_size = 10,
    };


    /*
     * Adding "fake" devices here to the SPI bus means that there no longer needs
     * to be a delay before adding the SD card to the SPI bus to allow the devices
     * to reach a consistent "we're not listening" state and/or incorrect levels
     * on the pins. Even when no other devices were attached it was sometimes touch
     * and go whether the SD card would work or fail after a reboot/cold start.
     *
     * It should be noted that the physical SPI devices are attached and the cs pin
     * numbers used in the dummy device adds are real connections. It is just that
     * the devices are not being handled in this testing/experimental code.
     *
     * It should also be noted that until the SD card is registered and mounted that
     * no transactions should happen on any other SPI device because the SD card
     * may decide not to go into SPI mode and then may randomly respond to any
     * transactions because it will be in SD mode and so will ignore CS polling.
     *
     */
    ESP_LOGI(TAG, "Adding fake LCD SPI device");
    dev_cfg.spics_io_num = PIN_NUM_LCD_CS;
    spi_device_handle_t lcd_handle;
    lcd_handle = (spi_device_handle_t)malloc(sizeof(lcd_handle));
    ESP_ERROR_CHECK(spi_bus_add_device(host.slot, &dev_cfg, &lcd_handle));

    ESP_LOGI(TAG, "Adding fake LCD TOUCH device");
    dev_cfg.spics_io_num = PIN_NUM_TOUCH_CS;
    spi_device_handle_t touch_handle;
    touch_handle = (spi_device_handle_t)malloc(sizeof(touch_handle));
    ESP_ERROR_CHECK(spi_bus_add_device(host.slot, &dev_cfg, &touch_handle));

    // This initializes the slot without card detect (CD) and write protect (WP) signals.
    // Modify slot_config.gpio_cd and slot_config.gpio_wp if your board has these signals.
    sdspi_device_config_t slot_config = SDSPI_DEVICE_CONFIG_DEFAULT();
    slot_config.gpio_cs = PIN_NUM_CS;
    slot_config.host_id = host.slot;

    ESP_LOGI(TAG, "Mounting filesystem");
    ESP_ERROR_CHECK(s_sdcard_esp_vfs_fat_sdspi_mount(mount_point, &host, &slot_config, &mount_config, &card));
    //ESP_ERROR_CHECK(esp_vfs_fat_sdspi_mount(mount_point, &host, &slot_config, &mount_config, &card));

    ESP_LOGI(TAG, "Filesystem mounted");

mattia424
Posts: 13
Joined: Sun Jan 07, 2024 11:56 pm

Re: SD card init failed

Postby mattia424 » Sat Jan 27, 2024 12:19 pm

I tried adding the fake TOUCH LCD and the SPI LCD, I also tried with a delay before calling sdspi_mout but nothing to do, always error 109
I also tried:
- Change with 4 different SD cards
- Try with another ESP32-S3
- Completely change the pins
- Change from SPI2_HOST to SPI3_HOST

But I noticed that you use "s_sdcard_esp_vfs_fat_sdspi_mount()", this function is not recognized for me, which library is it included in?

mattia424
Posts: 13
Joined: Sun Jan 07, 2024 11:56 pm

Re: SD card init failed

Postby mattia424 » Sat Jan 27, 2024 1:13 pm

Analysing the error output, I see the following lines:

I (337) main_task: Calling app_main()
I (337) example: Initializing SD card
I (347) example: Adding fake LCD SPI device
I (347) example: Adding fake LCD TOUCH device
I (357) example: Mounting filesystem
I (357) gpio: GPIO[38]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0
E (387) vfs_fat_sdmmc: sdmmc_card_init failed (0x109).
I (387) gpio: GPIO[38]| InputEn: 1| OutputEn: 0| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0
ESP_ERROR_CHECK failed: esp_err_t 0x109 (ESP_ERR_INVALID_CRC) at 0x42001b2b

is it normal that pin 38 (CS) is put first as output and then as input?

finally from the graphs above you can see that the MISO wire with Arduino is normally HIGHT while with espidf it is normally LOW and yet the 10k pullup resistor is present.

uC_Jon
Posts: 18
Joined: Fri Jan 05, 2024 7:03 pm

Re: SD card init failed

Postby uC_Jon » Sat Jan 27, 2024 5:02 pm

mattia424 wrote:
Sat Jan 27, 2024 12:19 pm
But I noticed that you use "s_sdcard_esp_vfs_fat_sdspi_mount()", this function is not recognized for me, which library is it included in?
To help myself understand what the helper function in the example, esp_vfs_fat_sdspi_mount (commented out), was doing I copied the whole function in to my main program code and renamed it so I could also modify it and see what various changes to the code would do. I was trying to figure out having the "wear levelling" code that runs on the flash work on the sdcard but I eventually worked out (gave up!) that they were not interoperable and I was working from a wrong assumption.


Looking at your log, it seems to be missing "Using SPI peripheral" which I can see is just after the "Initializing SD card" in the example code and before ret = spi_bus_initialize(host.slot, &bus_cfg, SDSPI_DEFAULT_DMA);

Did that get missed out during the modifications?

It might be worth starting from a clean version of the examples/storage/sd_card/sdspi/ directory. My esp idf was cloned from the latest "master" version (at the time, its was a couple of months back now). And the delay was put after the spi_bus_initialize and before the esp_vfs_fat_sdspi_mount.

As to the GPIO level (in your follow up post), I think its just the GPIO being torn down after the error is raised.

Its also worth double checking pullups as the code specifically has error message ESP_LOGE(TAG, "Failed to initialize the card (%s). "
"Make sure SD card lines have pull-up resistors in place.", esp_err_to_name(ret));

In the readme (the link: https://docs.espressif.com/projects/esp ... ments.html) it makes reference to requiring the lines to be pulled up. I think the sdcard needs to be in a given state before any commands are sent and any state that is not correct can cause the card to enter a different mode. My impression was that in the time it took the esp32 to pull the lines up (I believe they float at power on so might introduce random levels) it might be to late and/or the strength of internal pullups was not enough so I just pulled up all four lines from the power pin to the sdcard breakout (in the breadboard. SD card pins: D0, D3, CLK, CMD) so as soon as there is power they all go high.

I've found the best way to do any work with esp-idf is when starting on something new, clone the very latest "master" version from scratch (I'm only a hobbiest so I don't need the stability of a specific version), install the latest tools, copy the example code directory, and then modify that example to my hearts desires.

mattia424
Posts: 13
Joined: Sun Jan 07, 2024 11:56 pm

Re: SD card init failed

Postby mattia424 » Sun Jan 28, 2024 9:42 pm

Thank you very much for your advice!!!
By now demoralised :? I started from 0 with everything and carefully followed the example and documents from espressif and at the end of it all I discovered that the problem is the SD.....
I think the problem was more than one as changing the SD was one of the first tests I had done and had not led to any results so I decided to keep the SD that I had always used with Arduino-esp32 and had never given any problems.
I still can't explain how it is possible that out of the 5 SDs I tried (from the cheapest and most Chinese to the most powerful and expensive) only one 8 GB original samsung SD doesn't work with ESPIDF... while with Arduino-ESP32 it works...

uC_Jon
Posts: 18
Joined: Fri Jan 05, 2024 7:03 pm

Re: SD card init failed

Postby uC_Jon » Mon Jan 29, 2024 1:32 pm

You're welcome.

I have uploaded my complete code to my github (https://github.com/i400s/tmp-sdcard) which it might be useful to see if your "failed" esp-idf cards that work under Arduino still fail with my code or now work.

I've added some additional comments to the source and an incomplete readme. The code is specific to my requirement but was based on the original example; just expanded to act as a logger. Its entirely self contained and only requires a sd card.

If it runs successfully on your "failed" sd card then it would suggest, if not actually confirm, that the sd card isn't quite stable before the init is called. My code is larger than the example because it contains copies of the helper functions (such as esp_vfs_fat_sdspi_mount) prefixed s_sdcard.

I'm going on fuzzy recollection now, but I am fairly sure that when I was doing lots of googling when my cards (2 of them) were failing to init that one item I saw was related to the Arduino code having a delay in it. I can't remember if the delay was a patch applied to the Arduino code to fix the issue or if it was noted that there was a difference between what the Arduino does and what the esp-idf does.

I also recall that I was getting more frustrated each time it chucked out the failed to init message and so it was a combination of not initing the display & touch screen (which were attached), actually frying one of my cards at some point (I reinserted the breakout board off by one pin after double checking my wiring multiple times) *and* not having some kind of delay that caused the issue for myself. I have noted in the code that removing various combinations causes more or less "failed to init" errors.

Unlike the original code this code is completely hardcoded (there are no menuconfig project options). You just need to change the defines to point to the correct pins.

mattia424
Posts: 13
Joined: Sun Jan 07, 2024 11:56 pm

Re: SD card init failed

Postby mattia424 » Mon Jan 29, 2024 6:55 pm

I have tried the example on your github and am still experiencing the same error for the Samsung microSD that only works with Arduino.

I (322) main_task: Calling app_main()
I (322) sdcard_main: Initialising SPI peripheral
I (332) sdcard_main: Adding fake LCD SPI device
I (332) sdcard_main: Adding fake LCD TOUCH device
I (342) sdcard_main: Mounting filesystem
I (342) gpio: GPIO[15]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0
I (352) sdcard_main: Waiting brief time for card to stabilise after reset
E (1382) sdcard_main: s_sdcard_esp_vfs_fat_sdspi_mount(309): sdmmc_card_init failed
I (1382) gpio: GPIO[15]| InputEn: 1| OutputEn: 0| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0
ESP_ERROR_CHECK failed: esp_err_t 0x107 (ESP_ERR_TIMEOUT) at 0x420021b7
file: "src/main.c" line 492

This is the output with the samsung microsd while all others work correctly and give continuous write output.

Who is online

Users browsing this forum: MicroController and 128 guests