From 20313f82e6d6b3f55dc151a7d28d419c4754769c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adam=20M=C3=BAdry?= Date: Thu, 12 Jun 2025 17:44:17 +0200 Subject: [PATCH] feat(storage): Update emmc and perf_benchmark example to work with ESP32-P4 --- examples/storage/.build-test-rules.yml | 8 +++- examples/storage/emmc/README.md | 36 ++++++++--------- examples/storage/emmc/main/Kconfig.projbuild | 14 +++++++ examples/storage/emmc/sdkconfig.defaults | 1 + .../perf_benchmark/main/Kconfig.projbuild | 32 ++++++++++++++- .../perf_benchmark/main/idf_component.yml | 2 +- .../main/perf_benchmark_example_main.c | 15 ++++++- .../main/perf_benchmark_example_sd_utils.c | 39 +++++++++---------- 8 files changed, 103 insertions(+), 44 deletions(-) diff --git a/examples/storage/.build-test-rules.yml b/examples/storage/.build-test-rules.yml index a7b9542dfc..ae865e6177 100644 --- a/examples/storage/.build-test-rules.yml +++ b/examples/storage/.build-test-rules.yml @@ -13,8 +13,12 @@ examples/storage/emmc: - esp_driver_sdmmc - esp_driver_sdspi enable: - - if: IDF_TARGET == "esp32s3" - reason: only support on esp32s3 + - if: IDF_TARGET in ["esp32s3", "esp32p4"] + reason: only support on esp32s3 and esp32p4 + disable_test: + - if: IDF_TARGET == "esp32p4" + temporary: true + reason: lack of runners examples/storage/partition_api/partition_find: depends_components: diff --git a/examples/storage/emmc/README.md b/examples/storage/emmc/README.md index 00ecc6b331..64d85be82f 100644 --- a/examples/storage/emmc/README.md +++ b/examples/storage/emmc/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32-S3 | -| ----------------- | -------- | +| Supported Targets | ESP32-P4 | ESP32-S3 | +| ----------------- | -------- | -------- | # eMMC chip example (with SDMMC Host) @@ -22,34 +22,34 @@ This example supports eMMC chips. ## Hardware -This example requires an ESP32-S3 development board and an eMMC chip. Default connections can be found in next chapter. The standard ESP32S3 devkits do not have an eMMC integrated. Considering the signal integrity issues, we suggesting you make your custom PCB board with ESP32-S3 module and an eMMC chip. The signal integrity issues will be more important, when the bus is working under higher speeds. This includes but not limited to increasing the frequency, switching to DDR mode. We will talk a bit more about signal integrity issues in a following chapter. +This example requires an ESP32-S3 or ESP32-P4 development board and an eMMC chip. Default connections can be found in next chapter. Standard devkits do not have an eMMC integrated. Considering the signal integrity issues, we suggesting you make your custom PCB board with an ESP module and an eMMC chip. The signal integrity issues will be more important, when the bus is working under higher speeds. This includes but not limited to increasing the frequency, switching to DDR mode. We will talk a bit more about signal integrity issues in a following chapter. It is possible to connect an eMMC breakout adapter, but note that cable connections will decrease the signal integrity, leading communication timing violations. When in this condition, you may need to use a lower clock frequency, or switch to SDR mode. -Pull-up resistors is needed. As the SD specification and the eMMC datasheet clarify, minimum 10k pull-up resistors are required for the bus IOs to protect the IOs against bus floating issue. Note these pull-up resistors are needed, even if the pin is not used (For example, you use 1-line-mode, the pull-up resistor is still required for the D1 pin). +Pull-up resistors are needed. As specified in the SD specification and the eMMC datasheet, a minimum of 10k pull-up resistors are required on the bus I/Os to protect against bus floating issues. Note that these pull-up resistors are necessary even if a pin is not used. For example, if you are using 1-line mode, a pull-up resistor is still required on the D1 pin. -### Pin assignments for ESP32-S3 +### 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: +On ESP32-S3 and ESP32-P4, 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: 1. Using menuconfig: Run `idf.py menuconfig` in the project directory and open "eMMC Example Configuration" menu. 2. In the source code: See the initialization of ``sdmmc_slot_config_t slot_config`` structure in the example code. The table below lists the default pin assignments. -ESP32-S3 pin | eMMC pin | Notes ---------------|-------------|------------ -GPIO34 | CLK | 10k pullup -GPIO33 | CMD | 10k pullup -GPIO37 | D0 | 10k pullup -GPIO38 | D1 | not used in 1-line mode; but card's D1 pin must have a 10k pullup -GPIO39 | D2 | not used in 1-line mode; but card's D2 pin must have a 10k pullup -GPIO36 | D3 | not used in 1-line mode, but card's D3 pin must have a 10k pullup -GPIO35 | D4 | not used in 1/4-line mode, but card's D4 pin must have a 10k pullup -GPIO40 | D5 | not used in 1/4-line mode, but card's D5 pin must have a 10k pullup -GPIO42 | D6 | not used in 1/4-line mode, but card's D6 pin must have a 10k pullup -GPIO41 | D7 | not used in 1/4-line mode, but card's D7 pin must have a 10k pullup +ESP32-S3 pin | ESP32-P4 pin | eMMC pin | Notes +--------------|----------------|-------------|------- +GPIO34 | GPIO43 | CLK | 10k pullup +GPIO33 | GPIO44 | CMD | 10k pullup +GPIO37 | GPIO39 | D0 | 10k pullup +GPIO38 | GPIO40 | D1 | not used in 1-line mode; but card's D1 pin must have a 10k pullup +GPIO39 | GPIO41 | D2 | not used in 1-line mode; but card's D2 pin must have a 10k pullup +GPIO36 | GPIO42 | D3 | not used in 1-line mode, but card's D3 pin must have a 10k pullup +GPIO35 | GPIO45 | D4 | not used in 1/4-line mode, but card's D4 pin must have a 10k pullup +GPIO40 | GPIO46 | D5 | not used in 1/4-line mode, but card's D5 pin must have a 10k pullup +GPIO42 | GPIO47 | D6 | not used in 1/4-line mode, but card's D6 pin must have a 10k pullup +GPIO41 | GPIO48 | D7 | not used in 1/4-line mode, but card's D7 pin must have a 10k pullup ### Line modes diff --git a/examples/storage/emmc/main/Kconfig.projbuild b/examples/storage/emmc/main/Kconfig.projbuild index 1eee307b30..c500bc40a1 100644 --- a/examples/storage/emmc/main/Kconfig.projbuild +++ b/examples/storage/emmc/main/Kconfig.projbuild @@ -28,28 +28,34 @@ menu "eMMC Example Configuration" config EXAMPLE_PIN_CMD int "CMD GPIO number" default 33 if IDF_TARGET_ESP32S3 + default 44 if IDF_TARGET_ESP32P4 config EXAMPLE_PIN_CLK int "CLK GPIO number" default 34 if IDF_TARGET_ESP32S3 + default 43 if IDF_TARGET_ESP32P4 config EXAMPLE_PIN_D0 int "D0 GPIO number" default 37 if IDF_TARGET_ESP32S3 + default 39 if IDF_TARGET_ESP32P4 if EXAMPLE_EMMC_BUS_WIDTH_4 || EXAMPLE_EMMC_BUS_WIDTH_8 config EXAMPLE_PIN_D1 int "D1 GPIO number" default 38 if IDF_TARGET_ESP32S3 + default 40 if IDF_TARGET_ESP32P4 config EXAMPLE_PIN_D2 int "D2 GPIO number" default 39 if IDF_TARGET_ESP32S3 + default 41 if IDF_TARGET_ESP32P4 config EXAMPLE_PIN_D3 int "D3 GPIO number" default 36 if IDF_TARGET_ESP32S3 + default 42 if IDF_TARGET_ESP32P4 endif # EXAMPLE_EMMC_BUS_WIDTH_4 || EXAMPLE_EMMC_BUS_WIDTH_8 @@ -58,18 +64,26 @@ menu "eMMC Example Configuration" config EXAMPLE_PIN_D4 int "D4 GPIO number" default 35 if IDF_TARGET_ESP32S3 + default 45 if IDF_TARGET_ESP32P4 + default -1 config EXAMPLE_PIN_D5 int "D5 GPIO number" default 40 if IDF_TARGET_ESP32S3 + default 46 if IDF_TARGET_ESP32P4 + default -1 config EXAMPLE_PIN_D6 int "D6 GPIO number" default 42 if IDF_TARGET_ESP32S3 + default 47 if IDF_TARGET_ESP32P4 + default -1 config EXAMPLE_PIN_D7 int "D7 GPIO number" default 41 if IDF_TARGET_ESP32S3 + default 48 if IDF_TARGET_ESP32P4 + default -1 endif # EXAMPLE_EMMC_BUS_WIDTH_8 diff --git a/examples/storage/emmc/sdkconfig.defaults b/examples/storage/emmc/sdkconfig.defaults index 7847e636ee..f554aae677 100644 --- a/examples/storage/emmc/sdkconfig.defaults +++ b/examples/storage/emmc/sdkconfig.defaults @@ -1 +1,2 @@ CONFIG_EXAMPLE_FORMAT_IF_MOUNT_FAILED=y +CONFIG_ESP_TASK_WDT_INIT=n diff --git a/examples/storage/perf_benchmark/main/Kconfig.projbuild b/examples/storage/perf_benchmark/main/Kconfig.projbuild index 82debaba8f..44f154602c 100644 --- a/examples/storage/perf_benchmark/main/Kconfig.projbuild +++ b/examples/storage/perf_benchmark/main/Kconfig.projbuild @@ -167,6 +167,10 @@ menu "Performance Benchmark Example Configuration" Otherwise the card may enter SPI mode, the only way to recover from which is to cycle power to the card. + config EXAMPLE_SDMMC_BUS_WIDTH_8 + bool "8 lines (D0 - D7)" + depends on IDF_TARGET_ESP32S3 || IDF_TARGET_ESP32P4 + config EXAMPLE_SDMMC_BUS_WIDTH_4 bool "4 lines (D0 - D3)" @@ -191,7 +195,7 @@ menu "Performance Benchmark Example Configuration" default 37 if IDF_TARGET_ESP32S3 default 39 if IDF_TARGET_ESP32P4 - if EXAMPLE_SDMMC_BUS_WIDTH_4 + if EXAMPLE_SDMMC_BUS_WIDTH_4 || EXAMPLE_SDMMC_BUS_WIDTH_8 config EXAMPLE_PIN_D1 int "D1 GPIO number" @@ -208,7 +212,31 @@ menu "Performance Benchmark Example Configuration" default 34 if IDF_TARGET_ESP32S3 default 42 if IDF_TARGET_ESP32P4 - endif # EXAMPLE_SDMMC_BUS_WIDTH_4 + endif # EXAMPLE_SDMMC_BUS_WIDTH_4 || EXAMPLE_SDMMC_BUS_WIDTH_8 + + if EXAMPLE_SDMMC_BUS_WIDTH_8 + + config EXAMPLE_PIN_D4 + int "D4 GPIO number" + default 35 if IDF_TARGET_ESP32S3 + default 45 if IDF_TARGET_ESP32P4 + + config EXAMPLE_PIN_D5 + int "D5 GPIO number" + default 40 if IDF_TARGET_ESP32S3 + default 46 if IDF_TARGET_ESP32P4 + + config EXAMPLE_PIN_D6 + int "D6 GPIO number" + default 42 if IDF_TARGET_ESP32S3 + default 47 if IDF_TARGET_ESP32P4 + + config EXAMPLE_PIN_D7 + int "D7 GPIO number" + default 41 if IDF_TARGET_ESP32S3 + default 48 if IDF_TARGET_ESP32P4 + + endif # EXAMPLE_SDMMC_BUS_WIDTH_8 endif # SOC_SDMMC_USE_GPIO_MATRIX diff --git a/examples/storage/perf_benchmark/main/idf_component.yml b/examples/storage/perf_benchmark/main/idf_component.yml index 6ebb3cc920..ba55485722 100644 --- a/examples/storage/perf_benchmark/main/idf_component.yml +++ b/examples/storage/perf_benchmark/main/idf_component.yml @@ -1,3 +1,3 @@ ## IDF Component Manager Manifest File dependencies: - joltwallet/littlefs: "~=1.16.0" + joltwallet/littlefs: "~=1.20.0" diff --git a/examples/storage/perf_benchmark/main/perf_benchmark_example_main.c b/examples/storage/perf_benchmark/main/perf_benchmark_example_main.c index 880fb53de0..db8c0dd69e 100644 --- a/examples/storage/perf_benchmark/main/perf_benchmark_example_main.c +++ b/examples/storage/perf_benchmark/main/perf_benchmark_example_main.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ @@ -22,6 +22,9 @@ #include "esp_vfs_fat.h" #include "esp_spiffs.h" #include "wear_levelling.h" +#if SOC_SDMMC_IO_POWER_EXTERNAL +#include "sd_pwr_ctrl_by_on_chip_ldo.h" +#endif #include "esp_littlefs.h" @@ -91,6 +94,16 @@ void app_main(void) test_sd_littlefs(); #endif // CONFIG_EXAMPLE_TEST_SD_CARD_LITTLEFS + // Deinitialize the power control driver if it was used +#if CONFIG_EXAMPLE_SD_PWR_CTRL_LDO_INTERNAL_IO + esp_err_t ret = sd_pwr_ctrl_del_on_chip_ldo(host_g.pwr_ctrl_handle); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "Failed to delete the on-chip LDO power control driver"); + ESP_ERROR_CHECK(ret); + } + host_g.pwr_ctrl_handle = NULL; +#endif + #endif // CONFIG_EXAMPLE_TEST_SD_CARD } diff --git a/examples/storage/perf_benchmark/main/perf_benchmark_example_sd_utils.c b/examples/storage/perf_benchmark/main/perf_benchmark_example_sd_utils.c index 9979d6d821..68d86c3742 100644 --- a/examples/storage/perf_benchmark/main/perf_benchmark_example_sd_utils.c +++ b/examples/storage/perf_benchmark/main/perf_benchmark_example_sd_utils.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ @@ -31,11 +31,11 @@ sdspi_device_config_t slot_config_g; #endif // CONFIG_EXAMPLE_USE_SDSPI #ifdef CONFIG_EXAMPLE_USE_SDMMC -void init_sd_config(sdmmc_host_t *out_host, sdmmc_slot_config_t *out_slot_config, int freq_khz) { +void init_sd_config(sdmmc_host_t *out_host, sdmmc_slot_config_t *out_slot_config, int freq_khz) #else // CONFIG_EXAMPLE_USE_SDMMC -void init_sd_config(sdmmc_host_t *out_host, sdspi_device_config_t *out_slot_config, int freq_khz) { +void init_sd_config(sdmmc_host_t *out_host, sdspi_device_config_t *out_slot_config, int freq_khz) #endif // CONFIG_EXAMPLE_USE_SDSPI - +{ // For SoCs where the SD power can be supplied both via an internal or external (e.g. on-board LDO) power supply. // When using specific IO pins (which can be used for ultra high-speed SDMMC) to connect to the SD card // and the internal LDO power supply, we need to initialize the power supply first. @@ -66,7 +66,9 @@ void init_sd_config(sdmmc_host_t *out_host, sdspi_device_config_t *out_slot_conf sdmmc_slot_config_t slot_config = SDMMC_SLOT_CONFIG_DEFAULT(); // Set bus width to use: - #ifdef CONFIG_EXAMPLE_SDMMC_BUS_WIDTH_4 + #ifdef CONFIG_EXAMPLE_SDMMC_BUS_WIDTH_8 + slot_config.width = 8; + #elif CONFIG_EXAMPLE_SDMMC_BUS_WIDTH_4 slot_config.width = 4; #else slot_config.width = 1; @@ -78,11 +80,17 @@ void init_sd_config(sdmmc_host_t *out_host, sdspi_device_config_t *out_slot_conf slot_config.clk = CONFIG_EXAMPLE_PIN_CLK; slot_config.cmd = CONFIG_EXAMPLE_PIN_CMD; slot_config.d0 = CONFIG_EXAMPLE_PIN_D0; - #ifdef CONFIG_EXAMPLE_SDMMC_BUS_WIDTH_4 + #if CONFIG_EXAMPLE_SDMMC_BUS_WIDTH_4 || CONFIG_EXAMPLE_SDMMC_BUS_WIDTH_8 slot_config.d1 = CONFIG_EXAMPLE_PIN_D1; slot_config.d2 = CONFIG_EXAMPLE_PIN_D2; slot_config.d3 = CONFIG_EXAMPLE_PIN_D3; - #endif // CONFIG_EXAMPLE_SDMMC_BUS_WIDTH_4 + #endif // CONFIG_EXAMPLE_SDMMC_BUS_WIDTH_4 || CONFIG_EXAMPLE_SDMMC_BUS_WIDTH_8 + #ifdef CONFIG_EXAMPLE_SDMMC_BUS_WIDTH_8 + slot_config.d4 = CONFIG_EXAMPLE_PIN_D4; + slot_config.d5 = CONFIG_EXAMPLE_PIN_D5; + slot_config.d6 = CONFIG_EXAMPLE_PIN_D6; + slot_config.d7 = CONFIG_EXAMPLE_PIN_D7; + #endif // CONFIG_EXAMPLE_SDMMC_BUS_WIDTH_8 #endif // CONFIG_SOC_SDMMC_USE_GPIO_MATRIX // Enable internal pullups on enabled pins. The internal pullups @@ -120,7 +128,8 @@ void init_sd_config(sdmmc_host_t *out_host, sdspi_device_config_t *out_slot_conf *out_slot_config = slot_config; } -esp_err_t init_sd_card(sdmmc_card_t **out_card) { +esp_err_t init_sd_card(sdmmc_card_t **out_card) +{ esp_err_t ret = ESP_OK; sdmmc_card_t* card = (sdmmc_card_t *)malloc(sizeof(sdmmc_card_t)); if (card == NULL) { @@ -155,7 +164,8 @@ esp_err_t init_sd_card(sdmmc_card_t **out_card) { return ret; } -void deinit_sd_card(sdmmc_card_t **card) { +void deinit_sd_card(sdmmc_card_t **card) +{ // Unmount SD card #ifdef CONFIG_EXAMPLE_USE_SDMMC sdmmc_host_deinit(); @@ -163,17 +173,6 @@ void deinit_sd_card(sdmmc_card_t **card) { sdspi_host_deinit(); #endif // CONFIG_EXAMPLE_USE_SDSPI - // Deinitialize the power control driver if it was used -#if CONFIG_EXAMPLE_SD_PWR_CTRL_LDO_INTERNAL_IO - sd_pwr_ctrl_handle_t pwr_ctrl_handle = (*card)->host.pwr_ctrl_handle; - esp_err_t ret = sd_pwr_ctrl_del_on_chip_ldo(pwr_ctrl_handle); - if (ret != ESP_OK) { - ESP_LOGE(TAG, "Failed to delete the on-chip LDO power control driver"); - ESP_ERROR_CHECK(ret); - } - pwr_ctrl_handle = NULL; -#endif - free(*card); *card = NULL; }