SPI Connection to SD Card Fails to Recognize Chinese Directories
Port, board and/or hardware
esp32
MicroPython version
When using SPI to connect an SD card in a MicroPython environment, directories with Chinese characters in their names are not recognized correctly. This results in errors or the directories being displayed as garbled text.
Reproduction
1.Connect an SD card to a MicroPython device using SPI.
2.list a directory on the SD card with a name containing Chinese characters.
3.list the Chinese directory contents using os.listdir().
Expected behaviour
The directory with Chinese characters should be listed correctly without errors.
Observed behaviour
The directory name appears as garbled text, and accessing it may result in errors.
Additional Information
No, I've provided everything above.
Code of Conduct
Yes, I agree
esp32/sdcard: Unable to use SD card on some ESP32-P4 boards.
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_5power 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:~
- ~Make
DEFAULT_SLOT=0on the ESP32-P4.~ - ~Make the default
slotconfigurable inmpconfigboard.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