Merge branch 'feat/tusb_msc_example_sdmmc_esp32s31_backport_v6.1' into 'release/v6.1'

feat(usb_device): Add SDMMC support for MSC USB Device example for esp32s31 target v6.1 backport

See merge request espressif/esp-idf!50827
This commit is contained in:
Jiang Jiang Jian
2026-07-17 10:53:58 +08:00
8 changed files with 100 additions and 35 deletions

View File

@@ -827,6 +827,21 @@ examples/peripherals/usb/device/tusb_cdc_acm_wakeup:
disable:
- if: SOC_USB_OTG_SUPPORTED != 1 or SOC_PM_SUPPORT_USB_WAKEUP != 1
examples/peripherals/usb/device/tusb_msc:
disable:
- if: SOC_USB_OTG_SUPPORTED != 1
- if: CONFIG_NAME == "sdmmc" and SOC_SDMMC_HOST_SUPPORTED != 1
reason: Only USB-OTG supported targets with SDMMC support
disable_test:
- if: IDF_TARGET not in ["esp32s2", "esp32p4"]
temporary: true
reason: lack of runners with usb_device tag
depends_components:
- fatfs
- soc
depends_filepatterns:
- examples/peripherals/usb/device/tusb_msc/**/*
examples/peripherals/usb/device/tusb_ncm:
disable:
- if: SOC_USB_OTG_SUPPORTED != 1 or SOC_WIFI_SUPPORTED != 1

View File

@@ -28,9 +28,9 @@ As a USB stack, a TinyUSB component is used.
3. USB which accesses the ESP MSC Partition is plugged-in at boot-up. After boot-up, it is ejected on Host PC manually by user.
- Result: Host PC can't access the partition over USB MSC. Application example can perform operations (read, write) on partition.
4. USB which accesses the ESP MSC Partition is plugged-in at boot-up. It is then unplugged(removed) from Host PC manually by user.
- Result: The behaviour is different for bus-powered devices and self-powered devices
- Result: The behavior is different for bus-powered devices and self-powered devices
- (a) Bus-Powered devices - Both Host PC as well as application example can't access the partition over USB MSC. Here, the device will be Powered-off.
- (b) Self-Powered devices - Here, the device can be powered-on even after unplugging the device from Host PC. These behaviour can be further categorize in two ways:
- (b) Self-Powered devices - Here, the device can be powered-on even after unplugging the device from Host PC. These behavior can be further categorize in two ways:
- (i) Self-Powered Devices without VBUS monitoring - Both Host PC as well as application example can't access the partition over USB MSC.
- (ii) Self-Powered Devices with VBUS monitoring - Host PC can't access the partition over USB MSC. Application example can perform operations (read, write) on partition. Here, in ``tinyusb_config_t`` user must set ``self_powered`` to ``true`` and ``vbus_monitor_io`` to GPIO number (``VBUS_MONITORING_GPIO_NUM``) that will be used for VBUS monitoring.
@@ -47,14 +47,28 @@ See common pin assignments for USB Device examples from [upper level](../../READ
Next, for Self-Powered Devices with VBUS monitoring, user must set ``self_powered`` to ``true`` and ``vbus_monitor_io`` to GPIO number (``VBUS_MONITORING_GPIO_NUM``) that will be used for VBUS monitoring.
### Additional Pin assignments for ESP32-S3 for accessing SD MMC Card
### SD MMC Card Pin Assignments
On ESP32-S3, SDMMC peripheral is connected to GPIO pins using GPIO matrix. This allows arbitrary GPIOs to be used to connect an SD card. In this example, GPIOs can be configured in two ways:
When using SD MMC Card as storage media, additional pins are required beyond the USB pins. SD MMC card support is available on ESP32-S3, ESP32-P4, and ESP32-S31.
1. Using menuconfig: Run `idf.py menuconfig` in the project directory, open "USB DEV MSC Example Configuration" and select "SDMMC CARD" for "Storage Media Used".
2. In the source code: See the initialization of ``sdmmc_slot_config_t slot_config`` structure in the example code.
#### SD MMC Configuration
The table below lists the default pin assignments.
GPIOs and SD bus settings can be configured in two ways:
1. Using menuconfig: Run `idf.py menuconfig` in the project directory, open "TinyUSB MSC Example Configuration", and:
- Select "SDMMC CARD" for "Storage Media Used"
- Select "SD/MMC bus width" — "4 lines (D0 - D3)" or "1 line (D0)" (see `CONFIG_EXAMPLE_SDMMC_BUS_WIDTH_1`)
- On ESP32-S3 and ESP32-P4: set the GPIO numbers for the SD card interface
2. Using target-specific defaults: Pin and LDO defaults for each chip are in ``sdkconfig.defaults.esp32s3``, ``sdkconfig.defaults.esp32p4``, and ``sdkconfig.defaults.esp32s31``. These are applied automatically when you set the target with ``idf.py set-target``.
3. In the source code: See the initialization of ``sdmmc_slot_config_t slot_config`` structure in the example code.
By default, this example uses 4-line SD mode, utilizing 6 pins: CLK, CMD, D0 - D3.
Note that even if card's D3 line is not connected to the ESP chip, it still has to be pulled up, otherwise the card will go into SPI protocol mode.
#### ESP32-S3
On ESP32-S3, the SDMMC peripheral is connected to GPIO pins using the GPIO matrix. This allows arbitrary GPIOs to be used to connect an SD card. The table below lists the default pin assignments.
When using an ESP32-S3-USB-OTG board, this example runs without any extra modifications required. Only an SD card needs to be inserted into the slot.
@@ -67,18 +81,40 @@ GPIO38 | D1 | not used in 1-line SD mode; 10k pullup in 4-line m
GPIO33 | D2 | not used in 1-line SD mode; 10k pullup in 4-line mode
GPIO34 | D3 | not used in 1-line SD mode, but card's D3 pin must have a 10k pullup
By default, this example uses 4 line SD mode, utilizing 6 pins: CLK, CMD, D0 - D3. It is possible to use 1-line mode (CLK, CMD, D0) by changing "SD/MMC bus width" in the example configuration menu (see `CONFIG_EXAMPLE_SDMMC_BUS_WIDTH_1`).
#### ESP32-P4
Note that even if card's D3 line is not connected to the ESP chip, it still has to be pulled up, otherwise the card will go into SPI protocol mode.
On ESP32-P4, Slot 1 of the SDMMC peripheral is connected to GPIO pins using the GPIO matrix. This allows arbitrary GPIOs to be used to connect an SD card. The table below lists the default pin assignments.
ESP32-P4 pin | SD card pin | Notes
--------------|-------------|------------
GPIO43 | CLK | 10k pullup
GPIO44 | CMD | 10k pullup
GPIO39 | D0 | 10k pullup
GPIO40 | D1 | not used in 1-line SD mode; 10k pullup in 4-line mode
GPIO41 | D2 | not used in 1-line SD mode; 10k pullup in 4-line mode
GPIO42 | D3 | not used in 1-line SD mode, but card's D3 pin must have a 10k pullup
Default dedicated pins on ESP32-P4 are able to connect to an ultra high-speed SD card (UHS-I) which requires 1.8V switching (instead of the regular 3.3V). This means the user has to provide an external LDO power supply to use them, or enable and configure the internal LDO via `idf.py menuconfig` -> `TinyUSB MSC Example Configuration` -> `SDMMC powered by internal LDO` and `LDO IO`.
When using different GPIO pins this is not required and the `SDMMC powered by internal LDO` setting can be disabled.
#### ESP32-S31
On ESP32-S31, the SDMMC peripheral is connected to specific GPIO pins using the IO MUX. GPIO pins cannot be customized. The table below lists the pin connections.
ESP32-S31 pin | SD card pin | Notes
--------------|-------------|------------
GPIO24 | CLK | 10k pullup
GPIO25 | CMD | 10k pullup
GPIO20 | D0 | 10k pullup
GPIO21 | D1 | not used in 1-line SD mode; 10k pullup in 4-line mode
GPIO22 | D2 | not used in 1-line SD mode; 10k pullup in 4-line mode
GPIO23 | D3 | not used in 1-line SD mode, but card's D3 pin must have a 10k pullup
### Build and Flash
1. By default, the example will compile to access SPI Flash as storage media. Here, SPI Flash Wear Levelling WL_SECTOR_SIZE is set to 512 and WL_SECTOR_MODE is set to PERF in Menuconfig.
2. In order to access SD MMC card as storage media, configuration has to be changed using `idf.py menuconfig`:
- i. Open "USB Dev MSC Example Configuration" and select "SDMMC CARD" for "Storage Media Used"
- ii. Open "SD/MMC bus width" and select between "4 lines (D0 - D3)" or "1 line (D0)"
- iii. Select the GPIO Pin numbers for SD Card Pin.
- iv. Save the configuration.
2. In order to access SD MMC card as storage media, change the configuration as described in [SD MMC Configuration](#sd-mmc-configuration) above.
Build the project and flash it to the board, then run monitor tool to view serial output:

View File

@@ -13,7 +13,7 @@ menu "TinyUSB MSC Example Configuration"
config EXAMPLE_STORAGE_MEDIA_SDMMC
bool "SDMMC CARD"
depends on IDF_TARGET_ESP32S3 || IDF_TARGET_ESP32P4
depends on SOC_SDMMC_HOST_SUPPORTED
endchoice
if EXAMPLE_STORAGE_MEDIA_SDMMC
@@ -39,59 +39,53 @@ menu "TinyUSB MSC Example Configuration"
config EXAMPLE_PIN_CMD
int "CMD GPIO number"
range ENV_GPIO_RANGE_MIN ENV_GPIO_IN_RANGE_MAX
default 35 if IDF_TARGET_ESP32S3
default 44 if IDF_TARGET_ESP32P4
default 35
config EXAMPLE_PIN_CLK
int "CLK GPIO number"
range ENV_GPIO_RANGE_MIN ENV_GPIO_OUT_RANGE_MAX
default 36 if IDF_TARGET_ESP32S3
default 43 if IDF_TARGET_ESP32P4
default 36
config EXAMPLE_PIN_D0
int "D0 GPIO number"
range ENV_GPIO_RANGE_MIN ENV_GPIO_IN_RANGE_MAX
default 37 if IDF_TARGET_ESP32S3
default 39 if IDF_TARGET_ESP32P4
default 37
if EXAMPLE_SDMMC_BUS_WIDTH_4
config EXAMPLE_PIN_D1
int "D1 GPIO number"
range ENV_GPIO_RANGE_MIN ENV_GPIO_IN_RANGE_MAX
default 38 if IDF_TARGET_ESP32S3
default 40 if IDF_TARGET_ESP32P4
default 38
config EXAMPLE_PIN_D2
int "D2 GPIO number"
range ENV_GPIO_RANGE_MIN ENV_GPIO_IN_RANGE_MAX
default 33 if IDF_TARGET_ESP32S3
default 41 if IDF_TARGET_ESP32P4
default 33
config EXAMPLE_PIN_D3
int "D3 GPIO number"
range ENV_GPIO_RANGE_MIN ENV_GPIO_IN_RANGE_MAX
default 34 if IDF_TARGET_ESP32S3
default 42 if IDF_TARGET_ESP32P4
default 34
endif # EXAMPLE_SDMMC_BUS_WIDTH_4
endif # SOC_SDMMC_USE_GPIO_MATRIX
config EXAMPLE_SD_PWR_CTRL_LDO_INTERNAL_IO
depends on SOC_SDMMC_IO_POWER_EXTERNAL
depends on SOC_SDMMC_IO_POWER_EXTERNAL || SOC_SDMMC_IO_UHS_POWER_EXTERNAL
bool "SDMMC powered by internal LDO"
default y
help
Enable when internal LDO of ESP32-P4 is used as a power supply for SD card. Specify the LDO IO.
Enable when internal LDO of an ESP32 is used as a power supply for SD card. Specify the LDO IO.
Disable when external power supply is used as a power supply for SD card.
config EXAMPLE_SD_PWR_CTRL_LDO_IO_ID
depends on SOC_SDMMC_IO_POWER_EXTERNAL && EXAMPLE_SD_PWR_CTRL_LDO_INTERNAL_IO
depends on SOC_SDMMC_IO_POWER_EXTERNAL || SOC_SDMMC_IO_UHS_POWER_EXTERNAL
depends on EXAMPLE_SD_PWR_CTRL_LDO_INTERNAL_IO
int "LDO IO"
default 4 if IDF_TARGET_ESP32P4
default 1
help
There are several IOs in ESP32-P4 which are in "SD card IO" power domain.
There are several IOs in ESP32 SD card capable targets which are in "SD card IO" power domain.
Power has to be supplied to this power domain externally (from outside the chip) via one of the pins.
Based on the schematic, specify the LDO IO pin.

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
@@ -375,6 +375,11 @@ static esp_err_t storage_init_sdmmc(sdmmc_card_t **card)
host.pwr_ctrl_handle = pwr_ctrl_handle;
#endif
#if SOC_SDMMC_IO_UHS_POWER_EXTERNAL
//for uhs-i power
host.io_voltage = 1.8f;
#endif
// 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.
sdmmc_slot_config_t slot_config = SDMMC_SLOT_CONFIG_DEFAULT();

View File

@@ -1,2 +1 @@
CONFIG_IDF_TARGET="esp32s3"
CONFIG_EXAMPLE_STORAGE_MEDIA_SDMMC=y

View File

@@ -0,0 +1,8 @@
CONFIG_EXAMPLE_PIN_CMD=44
CONFIG_EXAMPLE_PIN_CLK=43
CONFIG_EXAMPLE_PIN_D0=39
CONFIG_EXAMPLE_PIN_D1=40
CONFIG_EXAMPLE_PIN_D2=41
CONFIG_EXAMPLE_PIN_D3=42
CONFIG_EXAMPLE_SD_PWR_CTRL_LDO_INTERNAL_IO=y
CONFIG_EXAMPLE_SD_PWR_CTRL_LDO_IO_ID=4

View File

@@ -0,0 +1,6 @@
CONFIG_EXAMPLE_PIN_CMD=35
CONFIG_EXAMPLE_PIN_CLK=36
CONFIG_EXAMPLE_PIN_D0=37
CONFIG_EXAMPLE_PIN_D1=38
CONFIG_EXAMPLE_PIN_D2=33
CONFIG_EXAMPLE_PIN_D3=34

View File

@@ -0,0 +1,2 @@
CONFIG_EXAMPLE_SD_PWR_CTRL_LDO_INTERNAL_IO=y
CONFIG_EXAMPLE_SD_PWR_CTRL_LDO_IO_ID=1