← index #18984PR #16702
Related · medium · value 6.867
QUERY · ISSUE

esp32/sdcard: Unable to use SD card on some ESP32-P4 boards.

openby sfe-SparkFroopened 2026-03-23updated 2026-03-24
bugport-esp32

Port, board and/or hardware

esp32 port, ESP32-P4-Function-EV-Board (probably other boards with the ESP32-P4 too)

MicroPython version

MicroPython v1.27.0 on 2025-12-09; Generic ESP32P4 module with ESP32P4

Reproduction

Following the docs:

>>> import machine
>>> vfs.mount(machine.SDCard(), "/sd")

Expected behaviour

SD card should mount and be readable/writable.

Observed behaviour

E (11418) sdmmc_common: sdmmc_init_ocr: send_op_cond (1) returned 0x107
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
OSError: 16

SD card does not mount, and is not readable/writable.

Additional Information

I've debugged this, and there are 2 problems.

For context, the ESP32-P4 supports 2 SDMMC slots. Espressif confusingly uses both 1 indexing and 0 indexing in different contexts, so I'll adhere to strict 0 indexing here.

  • Slot 0 supports SDIO 3.0, and is capable of the fast UHS-I mode, but is on fixed GPIO pins (39-48). SDIO 3.0 also requires IO signals to switch between 3.3V and 1.8V, so those GPIO pins are powered by the VDD_IO_5 power pin, which can be powered by one of the internal LDOs on the ESP32-P4.
  • Slot 1 is only SDIO 2.0, but can be routed to any GPIO pin via the GPIO matrix. It always runs at 3.3V.

Again, I'm using the ESP32-P4-Function-EV-Board. Here is the schematic, look at the use of ESP_LDO_VO4 to power VDD_IO_5 the SDIO pull up resistors.

~Problem 1 - Default slot~

~The DEFAULT_SLOT is hard coded to 1 when using SDMMC:~

https://github.com/micropython/micropython/blob/5c00edcee28491b6961a5db6aa0e5aa856664de4/ports/esp32/machine_sdcard.c#L216-L218

~This board uses slot 0. It's likely that other boards will also use slot 0, since it supports SDIO 3.0.
I propose 2 possible solutions:~

  1. ~Make DEFAULT_SLOT=0 on the ESP32-P4.~
  2. ~Make the default slot configurable in mpconfigboard.h. This is probably the better solution.~

~FWIW just setting slot=0 is not enough to get the SD card to work on this board.~

Problem 2 - IO voltage

SDIO 3.0 requires the IO voltage level to change between 3.3V and 1.8V. To achieve this, the board must connect an internal LDO on the ESP32-P4 to the VDD_IO_5 power pin, and the self->host.pwr_ctrl_handle must be configured in machine_sdcard_make_new(). I have a working solution based on the ESP-IDF SDMMC example, with the following changes to machine_sdcard.c:

+#include "sd_pwr_ctrl_by_on_chip_ldo.h"
...
 static mp_obj_t machine_sdcard_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
...
     #if SOC_SDMMC_HOST_SUPPORTED
     else {
         sdmmc_host_t _temp_host = SDMMC_HOST_DEFAULT();
         _temp_host.max_freq_khz = freq / 1000;
         self->host = _temp_host;
     }
     #endif

+    sd_pwr_ctrl_ldo_config_t ldo_config = {
+        .ldo_chan_id = 4,
+    };
+    sd_pwr_ctrl_handle_t pwr_ctrl_handle = NULL;
+
+    int ret = sd_pwr_ctrl_new_on_chip_ldo(&ldo_config, &pwr_ctrl_handle);
+    if (ret != ESP_OK) {
+        DEBUG_printf("  Failed to create a new on-chip LDO power control driver");
+    }
+    self->host.pwr_ctrl_handle = pwr_ctrl_handle;

     DEBUG_printf("  Calling host.init()");

     check_esp_err(self->host.init());
     self->flags |= SDCARD_CARD_FLAGS_HOST_INIT_DONE;
...
 }

This is sufficient for the SD card to work:

>>> import machine, os
>>> vfs.mount(machine.SDCard(slot=0), "/sd")
>>> os.listdir()
['sd', 'boot.py']

I'm currently hard coding ldo_chan_id = 4 since that's what the ESP32-P4-Function-EV-Board uses, but other dev boards may use a different LDO. I think the best solution would be for the default LDO to be defined in mpconfigboard.h.

It's worth noting that a board could power VDD_IO_5 from somewhere other than an internal LDO, in which case this gets more tricky. Espressif's docs say to "implement a custom sd_pwr_ctrl driver"; IMO it's probably not worth the extra effort to support this.

Code of Conduct

Yes, I agree

CANDIDATE · PULL REQUEST

esp32: Improve machine.SDCard support on newer chips

mergedby projectgusopened 2025-02-05updated 2025-03-13
port-esp32

Summary

Updating the esp32 port machine.SDCard support for other chips:

  • Added support for configuring pins in SD/MMC mode on ESP32-S3. Closes #8514. Closes #16526.
  • Added support for SDCard in SPI mode on ESP32-S2, C3 and C6. This is a little restrictive on C3 and C6 as they only have one available SPI bus, so can't use this and machine.SPI together. Have enabled on all boards by default (the code size impact is about 4KB).
  • Explicitly disable slot 0 on original ESP32 (and document this). There are effectively zero ESP32 boards in the world that can use slot 0 for SDMMC.

This work was funded through GitHub sponsors

TODO

  • Final docs pass
  • [ ] ESP32-S3 SDCard object should print the additonal pin config EDIT: Actually SDCard has no print support on esp32, so leaving this off.

Testing

Manual testing with SD card breakout module:

  • ESP32-S3 in SDMMC mode with custom pins.
  • ESP32-S3 in SPI mode on both hosts.
  • ESP32-C3 in SPI mode.
  • ESP32-C6 in SPI mode.
  • ESP32-S2 in SPI mode on both hosts.
  • ESP32 in SDMMC and SPI modes.

Note that testing is easier if cherry-picking #16700 fix into the branch.

Trade-offs and Alternatives

  • Could drop the commit that enables SDCard on SPI-only chips if preferable, and update docs to suit. Although on balance I think it's still potentially useful.

Keyboard

j / / n
next pair
k / / p
previous pair
1 / / h
show query pane
2 / / l
show candidate pane
c
copy suggested comment
r
toggle reasoning
g i
go to index
?
show this help
esc
close overlays

press ? or esc to close

copied