← index #18984PR #18576
Related · high · value 1.646
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/machine_sdcard: Fix SDMMC slot assignment for non-default slots

mergedby jetpaxopened 2025-12-16updated 2025-12-18
port-esp32

Summary

Fixes SDMMC slot assignment bug where slot parameter was not being applied to the host configuration, causing initialization failures on ESP32-P4 when using slot 0.

Problem

The SDMMC_HOST_DEFAULT() macro in ESP-IDF hardcodes .slot = SDMMC_HOST_SLOT_1, but MicroPython's machine.SDCard constructor was not overriding this when the user specified a different slot number (e.g., slot=0).

This resulted in the SDMMC peripheral being initialized for the wrong physical slot, causing communication failures and timeouts when attempting to access SD cards on non-default slots.

Solution

Added _temp_host.slot = slot_num; to ensure the user-specified slot number is properly assigned to the sdmmc_host_t structure.

Testing

  • Tested on ESP32-P4 (dual SDMMC host controller) with SD card connected to slot 0
  • Verified SD card initialization, mounting, read/write operations work correctly
  • Matches the pattern already used in the SPI mode path (line 303)

Technical Details

ESP32-P4 has two SDMMC host controllers (slot 0 and slot 1), and the default ESP-IDF configuration assumes slot 1. This fix ensures MicroPython respects the user's slot selection, particularly important for boards that wire SD cards to slot 0.

Closes: N/A (new bug discovered during ESP32-P4 testing)

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