Skip to content

Commit

Permalink
fix(storage): Fix SD card examples for SoCs with SOC_SDMMC_IO_POWER_E…
Browse files Browse the repository at this point in the history
…XTERNAL 1
  • Loading branch information
adokitkat committed May 22, 2024
1 parent 0de1efc commit 8485fa9
Show file tree
Hide file tree
Showing 11 changed files with 185 additions and 41 deletions.
31 changes: 23 additions & 8 deletions examples/storage/perf_benchmark/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,14 +54,14 @@ This example doesn't utilize card detect (CD) and write protect (WP) signals fro

The table below shows the default pin assignments.

SD card pin | SPI pin | ESP32 pin | ESP32-S2 | ESP32-S3 | ESP32-H2 | ESP32-C3 and other chips | Notes
------------|---------|---------------|----------|----------|----------|--------------------------|-------------
D0 | MISO | GPIO2 | GPIO37 | GPIO37 | GPIO0 | GPIO6 | 10k pullup
D1 | - | GPIO4 | - | GPIO38 | - | - | not used in 1-line SD mode; 10k pullup in 4-line mode
D2 | - | GPIO12 (MTDI) | - | GPIO33 | - | - | not used in 1-line SD mode; 10k pullup in 4-line mode
D3 | CS | GPIO13 (MTCK) | GPIO34 | GPIO34 | GPIO1 | GPIO1 | not used in 1-line SD mode, but card's D3 pin must have a 10k pullup
CLK | SCK | GPIO14 (MTMS) | GPIO36 | GPIO36 | GPIO4 | GPIO5 | 10k pullup
CMD | MOSI | GPIO15 (MTDO) | GPIO35 | GPIO35 | GPIO5 | GPIO4 | 10k pullup
SD card pin | SPI pin | ESP32 pin | ESP32-S2 | ESP32-S3 | ESP32-P4 SDMMC | ESP32-P4 SDSPI | ESP32-H2 | ESP32-C3 and other chips | Notes
------------|---------|---------------|----------|----------|----------------|----------------|----------|--------------------------|-------------
D0 | MISO | GPIO2 | GPIO37 | GPIO37 | GPIO43 | GPIO13 | GPIO0 | GPIO6 | 10k pullup
D1 | - | GPIO4 | - | GPIO38 | GPIO44 | - | - | - | not used in 1-line SD mode; 10k pullup in 4-line mode
D2 | - | GPIO12 (MTDI) | - | GPIO33 | GPIO39 | - | - | - | not used in 1-line SD mode; 10k pullup in 4-line mode
D3 | CS | GPIO13 (MTCK) | GPIO34 | GPIO34 | GPIO40 | GPIO10 | GPIO1 | GPIO1 | not used in 1-line SD mode, but card's D3 pin must have a 10k pullup
CLK | SCK | GPIO14 (MTMS) | GPIO36 | GPIO36 | GPIO41 | GPIO12 | GPIO4 | GPIO5 | 10k pullup
CMD | MOSI | GPIO15 (MTDO) | GPIO35 | GPIO35 | GPIO42 | GPIO11 | GPIO5 | GPIO4 | 10k pullup

### 4-line and 1-line SD modes

Expand Down Expand Up @@ -97,6 +97,21 @@ This command will burn the `XPD_SDIO_TIEH`, `XPD_SDIO_FORCE`, and `XPD_SDIO_REG`

See [the document about pullup requirements](https://docs.espressif.com/projects/esp-idf/en/latest/api-reference/peripherals/sd_pullup_requirements.html) for more details about pullup support and compatibility of modules and development boards.

#### ESP32-P4 related notes

This only applies when `Test SD card` setting in `Performance Benchmark Example Configuration` is enabled.

On ESP32-P4, Slot 1 of the 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 `Performance Benchmark Example Configuration` menu.
2. In the source code: See the initialization of `sdmmc_slot_config_t slot_config` structure in the example code.

If pins selected correspond with default pins used for ESP32-P4 SDMMC (i.e. SD card slot is connected to them), possibly an additional setting up needs to be done.

These pins 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 to enable and configure an internal LDO via `idf.py menuconfig` -> `SD/MMC Example Configuration` -> `SD power supply comes from internal LDO IO`.

When using different GPIO pins this is not required and `SD power supply comes from internal LDO IO` setting can be disabled.

### Note about SPIFFS

The test for SPIFFS is run only once, because SPIFFS has a problem with deleting files.
Expand Down
22 changes: 22 additions & 0 deletions examples/storage/perf_benchmark/main/Kconfig.projbuild
Original file line number Diff line number Diff line change
Expand Up @@ -179,28 +179,34 @@ menu "Performance Benchmark Example Configuration"
config EXAMPLE_PIN_CMD
int "CMD GPIO number"
default 35 if IDF_TARGET_ESP32S3
default 44 if IDF_TARGET_ESP32P4

config EXAMPLE_PIN_CLK
int "CLK GPIO number"
default 36 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_SDMMC_BUS_WIDTH_4

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 33 if IDF_TARGET_ESP32S3
default 41 if IDF_TARGET_ESP32P4

config EXAMPLE_PIN_D3
int "D3 GPIO number"
default 34 if IDF_TARGET_ESP32S3
default 42 if IDF_TARGET_ESP32P4

endif # EXAMPLE_SDMMC_BUS_WIDTH_4

Expand Down Expand Up @@ -243,6 +249,22 @@ menu "Performance Benchmark Example Configuration"

endif # EXAMPLE_USE_SDSPI

config EXAMPLE_SD_PWR_CTRL_LDO_INTERNAL_IO
depends on SOC_SDMMC_IO_POWER_EXTERNAL
bool "SD power supply comes from internal LDO IO (READ HELP!)"
default y
help
Only needed when the SD card is connected to specific IO pins which can be used for high-speed SDMMC.
Please read the schematic first and check if the SD VDD is connected to any internal LDO output.
Unselect this option if the SD card is powered by an external power supply.

config EXAMPLE_SD_PWR_CTRL_LDO_IO_ID
depends on SOC_SDMMC_IO_POWER_EXTERNAL && EXAMPLE_SD_PWR_CTRL_LDO_INTERNAL_IO
int "LDO ID"
default 4 if IDF_TARGET_ESP32P4
help
Please read the schematic first and input your LDO ID.

endmenu # "SD card test config"

endmenu # "Performance Monitor Example Configuration"
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@
#if SOC_SDMMC_HOST_SUPPORTED
#include "driver/sdmmc_host.h"
#endif
#if SOC_SDMMC_IO_POWER_EXTERNAL
#include "sd_pwr_ctrl_by_on_chip_ldo.h"
#endif
#include "esp_err.h"
#include "esp_log.h"

#ifdef CONFIG_EXAMPLE_TEST_SD_CARD
Expand All @@ -32,6 +36,22 @@ void init_sd_config(sdmmc_host_t *out_host, sdmmc_slot_config_t *out_slot_config
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.
#if CONFIG_EXAMPLE_SD_PWR_CTRL_LDO_INTERNAL_IO
sd_pwr_ctrl_ldo_config_t ldo_config = {
.ldo_chan_id = CONFIG_EXAMPLE_SD_PWR_CTRL_LDO_IO_ID,
};
sd_pwr_ctrl_handle_t pwr_ctrl_handle = NULL;

esp_err_t sd_pwr_ctrl_ret = sd_pwr_ctrl_new_on_chip_ldo(&ldo_config, &pwr_ctrl_handle);
if (sd_pwr_ctrl_ret != ESP_OK) {
ESP_LOGE(TAG, "Failed to create a new an on-chip LDO power control driver");
ESP_ERROR_CHECK(sd_pwr_ctrl_ret);
}
#endif // CONFIG_EXAMPLE_SD_PWR_CTRL_LDO_INTERNAL_IO

// By default, SD card frequency is initialized to SDMMC_FREQ_DEFAULT (20MHz)
// For setting a specific frequency, use host.max_freq_khz
// (range 400kHz - 40MHz for SDMMC, 400kHz - 20MHz for SDSPI)
Expand Down Expand Up @@ -91,6 +111,11 @@ void init_sd_config(sdmmc_host_t *out_host, sdspi_device_config_t *out_slot_conf
slot_config.gpio_cs = CONFIG_EXAMPLE_PIN_CS;
slot_config.host_id = host.slot;
#endif // CONFIG_EXAMPLE_USE_SDSPI

#if CONFIG_EXAMPLE_SD_PWR_CTRL_LDO_INTERNAL_IO
host.pwr_ctrl_handle = pwr_ctrl_handle;
#endif // CONFIG_EXAMPLE_SD_PWR_CTRL_LDO_INTERNAL_IO

*out_host = host;
*out_slot_config = slot_config;
}
Expand Down Expand Up @@ -137,6 +162,18 @@ void deinit_sd_card(sdmmc_card_t **card) {
#else // CONFIG_EXAMPLE_USE_SDMMC
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;
}
Expand Down
6 changes: 5 additions & 1 deletion examples/storage/sd_card/sdmmc/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ GPIO34 | D3 | not used in 1-line SD mode, but card's D3 pin must

On ESP32-P4, Slot 1 of the 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 "SD/MMC Example Configuration" menu.
1. Using menuconfig: Run `idf.py menuconfig` in the project directory and open `SD/MMC 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.
Expand All @@ -84,6 +84,10 @@ GPIO40 | D1 | not used in 1-line SD mode; 10k pullup in 4-line m
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 to enable and configure an internal LDO via `idf.py menuconfig` -> `SD/MMC Example Configuration` -> `SD power supply comes from internal LDO IO`.

When using different GPIO pins this is not required and `SD power supply comes from internal LDO IO` setting can be disabled.

### 4-line and 1-line SD modes

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`).
Expand Down
17 changes: 9 additions & 8 deletions examples/storage/sd_card/sdmmc/main/Kconfig.projbuild
Original file line number Diff line number Diff line change
Expand Up @@ -152,18 +152,19 @@ menu "SD/MMC Example Configuration"

endif # EXAMPLE_SDMMC_BUS_WIDTH_4

config EXAMPLE_SDMMC_IO_POWER_INTERNAL_LDO
config EXAMPLE_SD_PWR_CTRL_LDO_INTERNAL_IO
depends on SOC_SDMMC_IO_POWER_EXTERNAL
bool "SDMMC IO power supply comes from internal LDO (READ HELP!)"
bool "SD power supply comes from internal LDO IO (READ HELP!)"
default y
help
Please read the schematic first and check if the SDMMC VDD is connected to any internal LDO output.
If the SDMMC is powered by an external supplier, unselect me
Only needed when the SD card is connected to specific IO pins which can be used for high-speed SDMMC.
Please read the schematic first and check if the SD VDD is connected to any internal LDO output.
Unselect this option if the SD card is powered by an external power supply.

config EXAMPLE_SDMMC_IO_LDO_ID
depends on SOC_SDMMC_IO_POWER_EXTERNAL
config EXAMPLE_SD_PWR_CTRL_LDO_IO_ID
depends on SOC_SDMMC_IO_POWER_EXTERNAL && EXAMPLE_SD_PWR_CTRL_LDO_INTERNAL_IO
int "LDO ID"
default 4
default 4 if IDF_TARGET_ESP32P4
help
Please read the schematic first and input your LDO ID
Please read the schematic first and input your LDO ID.
endmenu
24 changes: 13 additions & 11 deletions examples/storage/sd_card/sdmmc/main/sd_card_example_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@
#include "sdmmc_cmd.h"
#include "driver/sdmmc_host.h"
#include "sd_test_io.h"
#if SOC_SDMMC_IO_POWER_EXTERNAL
#include "sd_pwr_ctrl_by_on_chip_ldo.h"
#endif

#define EXAMPLE_MAX_CHAR_SIZE 64

Expand Down Expand Up @@ -127,18 +129,18 @@ void app_main(void)
// Example: for fixed frequency of 10MHz, use host.max_freq_khz = 10000;
sdmmc_host_t host = SDMMC_HOST_DEFAULT();

/**
* On these chips, the SDMMC IO power is supplied externally
*/
#if CONFIG_EXAMPLE_SDMMC_IO_POWER_INTERNAL_LDO
// 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.
#if CONFIG_EXAMPLE_SD_PWR_CTRL_LDO_INTERNAL_IO
sd_pwr_ctrl_ldo_config_t ldo_config = {
.ldo_chan_id = 4, // `LDO_VO4` is used as the SDMMC IO power
.ldo_chan_id = CONFIG_EXAMPLE_SD_PWR_CTRL_LDO_IO_ID,
};
sd_pwr_ctrl_handle_t pwr_ctrl_handle = NULL;

ret = sd_pwr_ctrl_new_on_chip_ldo(&ldo_config, &pwr_ctrl_handle);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Failed to new an on-chip ldo power control driver");
ESP_LOGE(TAG, "Failed to create a new on-chip LDO power control driver");
return;
}
host.pwr_ctrl_handle = pwr_ctrl_handle;
Expand Down Expand Up @@ -237,7 +239,7 @@ void app_main(void)
ESP_LOGI(TAG, "file still exists");
return;
} else {
ESP_LOGI(TAG, "file doesnt exist, format done");
ESP_LOGI(TAG, "file doesn't exist, formatting done");
}
#endif // CONFIG_EXAMPLE_FORMAT_SD_CARD

Expand All @@ -257,14 +259,14 @@ void app_main(void)

// All done, unmount partition and disable SDMMC peripheral
esp_vfs_fat_sdcard_unmount(mount_point, card);
ESP_LOGI(TAG, "Card unmounted");

#if SOC_SDMMC_IO_POWER_EXTERNAL
// Deinitialize the power control driver if it was used
#if CONFIG_EXAMPLE_SD_PWR_CTRL_LDO_INTERNAL_IO
ret = sd_pwr_ctrl_del_on_chip_ldo(pwr_ctrl_handle);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Failed to delete on-chip ldo power control driver");
ESP_LOGE(TAG, "Failed to delete the on-chip LDO power control driver");
return;
}
#endif

ESP_LOGI(TAG, "Card unmounted");
}
4 changes: 1 addition & 3 deletions examples/storage/sd_card/sdmmc/pytest_sdmmc_card_example.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: Unlicense OR CC0-1.0


import logging
import re

Expand Down Expand Up @@ -32,7 +30,7 @@ def test_examples_sd_card_sdmmc(dut: Dut) -> None:
'Reading file /sdcard/foo.txt',
"Read from file: 'Hello {}!'".format(name))
sd_card_format = re.compile(str.encode('Formatting card, allocation unit size=\\S+'))
message_list2 = ('file doesnt exist, format done',
message_list2 = ("file doesn't exist, formatting done",
'Opening file /sdcard/nihao.txt',
'File written',
'Reading file /sdcard/nihao.txt',
Expand Down
34 changes: 28 additions & 6 deletions examples/storage/sd_card/sdspi/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,12 @@ This example doesn't utilize card detect (CD) and write protect (WP) signals fro

The table below shows the default pin assignments.

SD card pin | SPI pin | ESP32 pin | ESP32-S2, ESP32-S3 | ESP32-H2 | ESP32-C3 and other chips | Notes
------------|---------|---------------|--------------------|----------|---------------------------|-------------
D0 | MISO | GPIO2 | GPIO37 | GPIO0 | GPIO6 |
D3 | CS | GPIO13 (MTCK) | GPIO34 | GPIO1 | GPIO1 |
CLK | SCK | GPIO14 (MTMS) | GPIO36 | GPIO4 | GPIO5 |
CMD | MOSI | GPIO15 (MTDO) | GPIO35 | GPIO5 | GPIO4 | 10k pullup
SD card pin | SPI pin | ESP32 pin | ESP32-S2, ESP32-S3 | ESP32-P4 | ESP32-H2 | ESP32-C3 and other chips | Notes
------------|---------|---------------|--------------------|----------|----------|--------------------------|------------
D0 | MISO | GPIO2 | GPIO37 | GPIO13 | GPIO0 | GPIO6 |
D3 | CS | GPIO13 (MTCK) | GPIO34 | GPIO10 | GPIO1 | GPIO1 |
CLK | SCK | GPIO14 (MTMS) | GPIO36 | GPIO12 | GPIO4 | GPIO5 |
CMD | MOSI | GPIO15 (MTDO) | GPIO35 | GPIO11 | GPIO5 | GPIO4 | 10k pullup


#### ESP32 related notes
Expand All @@ -63,6 +63,28 @@ With the default pin assignments, this example is compatible ESP32-S2-USB-OTG an

For other development boards, adjust the pin assignments as explained above.

#### ESP32-P4 related notes

On ESP32-P4, Slot 1 of the 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 `SD SPI Example Configuration` menu.
2. In the source code: See the initialization of `sdmmc_slot_config_t slot_config` structure in the example code.

Default pins for SDSPI are listed in the table above [Pin assignments](#1-pin-assignments) and using them doesn't require any additional settings.

However on some development boards the SD card slot can be wired to default dedicated pins for SDMMC, which are listed in the table below.

SD card pin | ESP32-P4 pin
------------|--------------
D0 (MISO) | GPIO39
D3 (CS) | GPIO42
CLK (SCK) | GPIO43
CMD (MOSI) | GPIO44

These pins 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 to enable and configure an internal LDO via `idf.py menuconfig` -> `SD/MMC Example Configuration` -> `SD power supply comes from internal LDO IO`.

When using different GPIO pins this is not required and `SD power supply comes from internal LDO IO` setting can be disabled.

#### Notes for ESP32-C3 and other chips

Espressif doesn't offer development boards with an SD card slot for these chips. Please check the pin assignments and adjust them for your board if necessary. The process to change pin assignments is described above.
Expand Down
15 changes: 15 additions & 0 deletions examples/storage/sd_card/sdspi/main/Kconfig.projbuild
Original file line number Diff line number Diff line change
Expand Up @@ -93,4 +93,19 @@ menu "SD SPI Example Configuration"
default 6 if IDF_TARGET_ESP32S3
default 1

config EXAMPLE_SD_PWR_CTRL_LDO_INTERNAL_IO
depends on SOC_SDMMC_IO_POWER_EXTERNAL
bool "SD power supply comes from internal LDO IO (READ HELP!)"
default n
help
Only needed when the SD card is connected to specific IO pins which can be used for high-speed SDMMC.
Please read the schematic first and check if the SD VDD is connected to any internal LDO output.
Unselect this option if the SD card is powered by an external power supply.

config EXAMPLE_SD_PWR_CTRL_LDO_IO_ID
depends on SOC_SDMMC_IO_POWER_EXTERNAL && EXAMPLE_SD_PWR_CTRL_LDO_INTERNAL_IO
int "LDO ID"
default 4 if IDF_TARGET_ESP32P4
help
Please read the schematic first and input your LDO ID.
endmenu
Loading

0 comments on commit 8485fa9

Please sign in to comment.