← index #18984PR #16289
Related · high · value 2.613
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: support SD card on ESP32C6

closedby lheckemannopened 2024-11-22updated 2025-03-13
port-esp32

Summary

I wanted to use an SD card with my ESP32C6! This required making SDMMC support optional, since the ESP32C6 only has SPI.

I'm not sure about all of this code, especially the slot defaults and the condition combinations that I've implemented here, feedback is very welcome!

Testing

I've tested initialising an SD card and reading and writing data to and from it directly using readblock and writeblock. This seems to behave correctly, but formatting it using vfs.VfsFat.mkfs fails with EIO (and I don't understand why, as all the calls into machine_sdcard.c that I've traced so far have been successful). Maybe someone else can shed some light on this problem?

Trade-offs and Alternatives

This increases size a bit.
before:

bootloader  @0x000000    18064  (   14704 remaining)
partitions  @0x008000     3072  (    1024 remaining)
application @0x010000  1926480  (  105136 remaining)
total                  1992016

after:

bootloader  @0x000000    18064  (   14704 remaining)
partitions  @0x008000     3072  (    1024 remaining)
application @0x010000  1953376  (   78240 remaining)
total                  2018912

I don't think there are any very relevant alternatives besides not implementing SD support.

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