diff --git a/components/esp_driver_sdmmc/test_apps/sdmmc/components/sdmmc_tests/CMakeLists.txt b/components/esp_driver_sdmmc/test_apps/sdmmc/components/sdmmc_tests/CMakeLists.txt index 96fe18ea96..97bfc4d35c 100644 --- a/components/esp_driver_sdmmc/test_apps/sdmmc/components/sdmmc_tests/CMakeLists.txt +++ b/components/esp_driver_sdmmc/test_apps/sdmmc/components/sdmmc_tests/CMakeLists.txt @@ -10,7 +10,8 @@ if(CONFIG_SOC_SDMMC_HOST_SUPPORTED) "sdmmc_test_trim_sd.c" "sdmmc_test_discard_sd.c" "sdmmc_test_sanitize_sd.c" - "sdmmc_test_various_cmds.c") + "sdmmc_test_various_cmds.c" + "sdmmc_test_card_init.c") endif() set(priv_requires "sdmmc" diff --git a/components/esp_driver_sdmmc/test_apps/sdmmc/components/sdmmc_tests/sdmmc_test_card_init.c b/components/esp_driver_sdmmc/test_apps/sdmmc/components/sdmmc_tests/sdmmc_test_card_init.c new file mode 100644 index 0000000000..dfa2446caf --- /dev/null +++ b/components/esp_driver_sdmmc/test_apps/sdmmc/components/sdmmc_tests/sdmmc_test_card_init.c @@ -0,0 +1,47 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include "sdmmc_cmd.h" +#include "driver/sdmmc_host.h" +#include "unity.h" +#include "sdmmc_test_begin_end_sd.h" +#if SOC_SDMMC_IO_POWER_EXTERNAL +#include "sd_pwr_ctrl_by_on_chip_ldo.h" +#endif + +#if SOC_SDMMC_HOST_SUPPORTED +TEST_CASE("sdmmc_card_init with SDIO configuration test", "[sdmmc]") +{ + sdmmc_card_t card; + + // Test with slot 1, 1-bit width, default frequency + sdmmc_test_sd_skip_if_board_incompatible(SLOT_1, 1, SDMMC_FREQ_DEFAULT, NO_DDR, NO_EMMC); + + // Print current SDIO configuration for verification +#ifdef CONFIG_SD_ENABLE_SDIO_SUPPORT + printf("\n[CONFIG] SDIO support is ENABLED\n"); +#else + printf("\n[CONFIG] SDIO support is DISABLED\n"); +#endif + + // Initialize using the test framework + sdmmc_test_sd_begin(SLOT_1, 1, SDMMC_FREQ_DEFAULT, NO_DDR, &card); + + // Print card information to verify card was initialized correctly + sdmmc_card_print_info(stdout, &card); + + // Verify basic card properties are initialized + TEST_ASSERT_NOT_EQUAL(0, card.csd.capacity); + TEST_ASSERT_NOT_EQUAL(0, card.csd.sector_size); + + // Clean up + sdmmc_test_sd_end(&card); +} +#endif diff --git a/components/esp_driver_sdmmc/test_apps/sdmmc/pytest_sdmmc.py b/components/esp_driver_sdmmc/test_apps/sdmmc/pytest_sdmmc.py index dfc410e7b2..5adf56eb8c 100644 --- a/components/esp_driver_sdmmc/test_apps/sdmmc/pytest_sdmmc.py +++ b/components/esp_driver_sdmmc/test_apps/sdmmc/pytest_sdmmc.py @@ -6,6 +6,14 @@ from pytest_embedded_idf.utils import idf_parametrize @pytest.mark.sdcard +@pytest.mark.parametrize( + 'config', + [ + 'default', + 'nosdio', + ], + indirect=True, +) @idf_parametrize('target', ['esp32', 'esp32s3', 'esp32p4'], indirect=['target']) def test_sdmmc(dut: IdfDut) -> None: # SDMMC driver can't be reinitialized if the test fails, diff --git a/components/esp_driver_sdmmc/test_apps/sdmmc/sdkconfig.ci.nosdio b/components/esp_driver_sdmmc/test_apps/sdmmc/sdkconfig.ci.nosdio new file mode 100644 index 0000000000..165270af77 --- /dev/null +++ b/components/esp_driver_sdmmc/test_apps/sdmmc/sdkconfig.ci.nosdio @@ -0,0 +1,2 @@ +# SDMMC Configuration +CONFIG_SD_ENABLE_SDIO_SUPPORT=n diff --git a/components/esp_driver_sdspi/test_apps/sdspi/components/sdspi_tests/CMakeLists.txt b/components/esp_driver_sdspi/test_apps/sdspi/components/sdspi_tests/CMakeLists.txt index b4e403e407..4c3657836d 100644 --- a/components/esp_driver_sdspi/test_apps/sdspi/components/sdspi_tests/CMakeLists.txt +++ b/components/esp_driver_sdspi/test_apps/sdspi/components/sdspi_tests/CMakeLists.txt @@ -6,7 +6,8 @@ if(CONFIG_SOC_GPSPI_SUPPORTED) "sdmmc_test_probe_spi.c" "sdmmc_test_rw_spi.c" "sdmmc_test_erase_spi.c" - "sdmmc_test_erase_common_spi.c") + "sdmmc_test_erase_common_spi.c" + "sdmmc_test_card_init_spi.c") endif() set(priv_requires "sdmmc" diff --git a/components/esp_driver_sdspi/test_apps/sdspi/components/sdspi_tests/sdmmc_test_card_init_spi.c b/components/esp_driver_sdspi/test_apps/sdspi/components/sdspi_tests/sdmmc_test_card_init_spi.c new file mode 100644 index 0000000000..2653b01bc5 --- /dev/null +++ b/components/esp_driver_sdspi/test_apps/sdspi/components/sdspi_tests/sdmmc_test_card_init_spi.c @@ -0,0 +1,44 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include "sdmmc_cmd.h" +#include "driver/sdspi_host.h" +#include "unity.h" +#include "sdmmc_test_begin_end_spi.h" + +#if CONFIG_SOC_GPSPI_SUPPORTED +TEST_CASE("sdspi_card_init with SDIO configuration test", "[sdspi]") +{ + sdmmc_card_t card; + + // Test with slot 1, default frequency for SPI mode + sdmmc_test_spi_skip_if_board_incompatible(SLOT_1, SDMMC_FREQ_DEFAULT); + + // Print current SDIO configuration for verification +#ifdef CONFIG_SD_ENABLE_SDIO_SUPPORT + printf("\n[CONFIG] SDIO support is ENABLED\n"); +#else + printf("\n[CONFIG] SDIO support is DISABLED\n"); +#endif + + // Initialize using the SPI test framework + sdmmc_test_spi_begin(SLOT_1, SDMMC_FREQ_DEFAULT, &card, NULL, NULL, NULL); + + // Print card information to verify card was initialized correctly + sdmmc_card_print_info(stdout, &card); + + // Verify basic card properties are initialized + TEST_ASSERT_NOT_EQUAL(0, card.csd.capacity); + TEST_ASSERT_NOT_EQUAL(0, card.csd.sector_size); + + // Clean up + sdmmc_test_spi_end(SLOT_1, &card); +} +#endif diff --git a/components/esp_driver_sdspi/test_apps/sdspi/pytest_sdspi.py b/components/esp_driver_sdspi/test_apps/sdspi/pytest_sdspi.py index 4c187b2d12..ef98c8aaa1 100644 --- a/components/esp_driver_sdspi/test_apps/sdspi/pytest_sdspi.py +++ b/components/esp_driver_sdspi/test_apps/sdspi/pytest_sdspi.py @@ -7,6 +7,14 @@ from pytest_embedded_idf.utils import idf_parametrize @pytest.mark.temp_skip_ci(targets=['esp32c61'], reason='C5 C61 GPSPI same, so testing on C5 is enough') @pytest.mark.sdcard_spimode +@pytest.mark.parametrize( + 'config', + [ + 'default', + 'nosdio', + ], + indirect=True, +) @idf_parametrize('target', ['esp32', 'esp32s3', 'esp32c3', 'esp32p4', 'esp32c5'], indirect=['target']) def test_sdspi(dut: IdfDut) -> None: dut.run_all_single_board_cases(reset=True) diff --git a/components/esp_driver_sdspi/test_apps/sdspi/sdkconfig.ci.nosdio b/components/esp_driver_sdspi/test_apps/sdspi/sdkconfig.ci.nosdio new file mode 100644 index 0000000000..165270af77 --- /dev/null +++ b/components/esp_driver_sdspi/test_apps/sdspi/sdkconfig.ci.nosdio @@ -0,0 +1,2 @@ +# SDMMC Configuration +CONFIG_SD_ENABLE_SDIO_SUPPORT=n diff --git a/components/sdmmc/CMakeLists.txt b/components/sdmmc/CMakeLists.txt index df25a79ecc..38b46c827e 100644 --- a/components/sdmmc/CMakeLists.txt +++ b/components/sdmmc/CMakeLists.txt @@ -7,11 +7,14 @@ endif() set(srcs "sdmmc_cmd.c" "sdmmc_common.c" "sdmmc_init.c" - "sdmmc_io.c" "sdmmc_mmc.c" "sdmmc_sd.c" "sd_pwr_ctrl/sd_pwr_ctrl.c") +if(CONFIG_SD_ENABLE_SDIO_SUPPORT) + list(APPEND srcs "sdmmc_io.c") +endif() + if(CONFIG_SOC_GP_LDO_SUPPORTED) list(APPEND srcs "sd_pwr_ctrl/sd_pwr_ctrl_by_on_chip_ldo.c") endif() diff --git a/components/sdmmc/Kconfig b/components/sdmmc/Kconfig new file mode 100644 index 0000000000..0d2ed43fee --- /dev/null +++ b/components/sdmmc/Kconfig @@ -0,0 +1,8 @@ +menu "SD Protocol Layer Configuration" + config SD_ENABLE_SDIO_SUPPORT + bool "Enable SDIO support" + default y + help + Enable SDIO support. + Disabling this will skip SDIO-specific initialization steps +endmenu diff --git a/components/sdmmc/README.md b/components/sdmmc/README.md index 7e18e31dd0..d61aa8e824 100644 --- a/components/sdmmc/README.md +++ b/components/sdmmc/README.md @@ -1,3 +1,6 @@ +| Supported Targets | ESP32 | ESP32-P4 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | + # SDMMC Protocol Layer Driver ## SD Host Side Related Component Architecture @@ -33,3 +36,10 @@ - `esp_driver_sdmmc` is in driver layer (G2), it relies on `sdmmc` - `esp_driver_sdspi` is in driver layer (G2), it relies on `sdmmc` - `sdmmc` does not and should not rely on `esp_driver_sdmmc` or `esp_driver_sdspi`. Though `sdmmc` is independent, it still stays in G2. + +## Configuration Options + +### CONFIG_SD_ENABLE_SDIO_SUPPORT + +This configuration option allows you to enable/disable SDIO support. By default this option is enabled. +Consider disabling SDIO support (`CONFIG_SD_ENABLE_SDIO_SUPPORT=n`) when card is **Memory-only card** and not when **Combo cards** which provide both I/O functionality and memory storage. diff --git a/components/sdmmc/include/esp_private/sdmmc_common.h b/components/sdmmc/include/esp_private/sdmmc_common.h index 9172c0318a..d1ea4d7abd 100644 --- a/components/sdmmc/include/esp_private/sdmmc_common.h +++ b/components/sdmmc/include/esp_private/sdmmc_common.h @@ -113,6 +113,7 @@ esp_err_t sdmmc_decode_scr(uint32_t *raw_scr, sdmmc_scr_t* out_scr); esp_err_t sdmmc_decode_ssr(uint32_t *raw_ssr, sdmmc_ssr_t* out_ssr); uint32_t sdmmc_sd_get_erase_timeout_ms(const sdmmc_card_t* card, int arg, size_t erase_size_kb); +#if CONFIG_SD_ENABLE_SDIO_SUPPORT /* SDIO specific */ esp_err_t sdmmc_io_reset(sdmmc_card_t* card); esp_err_t sdmmc_io_enable_hs_mode(sdmmc_card_t* card); @@ -123,6 +124,7 @@ esp_err_t sdmmc_io_rw_direct(sdmmc_card_t* card, int function, uint32_t reg, uin // cache, unless `SDMMC_HOST_FLAG_ALLOC_ALIGNED_BUF` flag is set when calling `sdmmc_card_init`. This flag is mandory // when the buffer is behind the cache in byte mode. esp_err_t sdmmc_io_rw_extended(sdmmc_card_t* card, int function, uint32_t reg, int arg, void *data, size_t size); +#endif /* MMC specific */ esp_err_t sdmmc_mmc_send_ext_csd_data(sdmmc_card_t* card, void *out_data, size_t datalen, size_t buffer_len); @@ -141,9 +143,6 @@ esp_err_t sdmmc_init_rca(sdmmc_card_t* card); esp_err_t sdmmc_init_mmc_decode_cid(sdmmc_card_t* card); esp_err_t sdmmc_init_ocr(sdmmc_card_t* card); esp_err_t sdmmc_init_spi_crc(sdmmc_card_t* card); -esp_err_t sdmmc_init_io(sdmmc_card_t* card); -esp_err_t sdmmc_io_init_read_card_cap(sdmmc_card_t* card, uint8_t* card_cap); -esp_err_t sdmmc_io_init_check_card_cap(sdmmc_card_t* card, uint8_t* card_cap); esp_err_t sdmmc_init_sd_blocklen(sdmmc_card_t* card); esp_err_t sdmmc_init_sd_scr(sdmmc_card_t* card); esp_err_t sdmmc_init_sd_ssr(sdmmc_card_t* card); @@ -152,7 +151,12 @@ esp_err_t sdmmc_init_mmc_read_ext_csd(sdmmc_card_t* card); esp_err_t sdmmc_init_mmc_read_cid(sdmmc_card_t* card); esp_err_t sdmmc_init_host_bus_width(sdmmc_card_t* card); esp_err_t sdmmc_init_sd_bus_width(sdmmc_card_t* card); +#if CONFIG_SD_ENABLE_SDIO_SUPPORT +esp_err_t sdmmc_init_io(sdmmc_card_t* card); esp_err_t sdmmc_init_io_bus_width(sdmmc_card_t* card); +esp_err_t sdmmc_io_init_read_card_cap(sdmmc_card_t* card, uint8_t* card_cap); +esp_err_t sdmmc_io_init_check_card_cap(sdmmc_card_t* card, uint8_t* card_cap); +#endif esp_err_t sdmmc_init_mmc_bus_width(sdmmc_card_t* card); esp_err_t sdmmc_init_card_hs_mode(sdmmc_card_t* card); esp_err_t sdmmc_init_host_frequency(sdmmc_card_t* card); diff --git a/components/sdmmc/sdmmc_common.c b/components/sdmmc/sdmmc_common.c index e4611ff7a4..63c6d2f4ed 100644 --- a/components/sdmmc/sdmmc_common.c +++ b/components/sdmmc/sdmmc_common.c @@ -180,8 +180,10 @@ esp_err_t sdmmc_init_card_hs_mode(sdmmc_card_t* card) esp_err_t err = ESP_ERR_NOT_SUPPORTED; if (card->is_mem && !card->is_mmc) { err = sdmmc_enable_hs_mode_and_check(card); +#if CONFIG_SD_ENABLE_SDIO_SUPPORT } else if (card->is_sdio) { err = sdmmc_io_enable_hs_mode(card); +#endif } else if (card->is_mmc){ err = sdmmc_mmc_enable_hs_mode(card); } diff --git a/components/sdmmc/sdmmc_init.c b/components/sdmmc/sdmmc_init.c index 6e7bf863f8..290971fd94 100644 --- a/components/sdmmc/sdmmc_init.c +++ b/components/sdmmc/sdmmc_init.c @@ -51,7 +51,11 @@ esp_err_t sdmmc_card_init(const sdmmc_host_t* config, sdmmc_card_t* card) const bool is_spi = host_is_spi(card); const bool always = true; +#if !CONFIG_SD_ENABLE_SDIO_SUPPORT + card->is_mem = 1; +#else const bool io_supported = true; +#endif if (config->pwr_ctrl_handle) { int voltage_mv = config->io_voltage * 1000; @@ -71,8 +75,10 @@ esp_err_t sdmmc_card_init(const sdmmc_host_t* config, sdmmc_card_t* card) /* Check if host function pointers are correctly initialised */ SDMMC_INIT_STEP(always, sdmmc_check_host_function_ptr_integrity); +#if CONFIG_SD_ENABLE_SDIO_SUPPORT /* Reset SDIO (CMD52, RES) before re-initializing IO (CMD5). */ SDMMC_INIT_STEP(io_supported, sdmmc_io_reset); +#endif /* GO_IDLE_STATE (CMD0) command resets the card */ SDMMC_INIT_STEP(always, sdmmc_send_cmd_go_idle_state); @@ -80,8 +86,10 @@ esp_err_t sdmmc_card_init(const sdmmc_host_t* config, sdmmc_card_t* card) /* SEND_IF_COND (CMD8) command is used to identify SDHC/SDXC cards. */ SDMMC_INIT_STEP(always, sdmmc_init_sd_if_cond); +#if CONFIG_SD_ENABLE_SDIO_SUPPORT /* IO_SEND_OP_COND(CMD5), Determine if the card is an IO card. */ SDMMC_INIT_STEP(io_supported, sdmmc_init_io); +#endif const bool is_mem = card->is_mem; const bool is_sdio = !is_mem; @@ -133,9 +141,11 @@ esp_err_t sdmmc_card_init(const sdmmc_host_t* config, sdmmc_card_t* card) /* MMC cards: read CXD */ SDMMC_INIT_STEP(is_mmc, sdmmc_init_mmc_read_ext_csd); +#if CONFIG_SD_ENABLE_SDIO_SUPPORT /* SDIO cards: read CCCR card capabilities */ uint8_t card_cap = 0; SDMMC_INIT_STEP_PARAM(is_sdio, sdmmc_io_init_read_card_cap, &card_cap); +#endif /* Try to switch card to HS mode if the card supports it. * Set card->max_freq_khz value accordingly. @@ -145,7 +155,9 @@ esp_err_t sdmmc_card_init(const sdmmc_host_t* config, sdmmc_card_t* card) /* Set bus width. One call for every kind of card, then one for the host */ if (!is_spi) { SDMMC_INIT_STEP(is_sdmem, sdmmc_init_sd_bus_width); +#if CONFIG_SD_ENABLE_SDIO_SUPPORT SDMMC_INIT_STEP(is_sdio, sdmmc_init_io_bus_width); +#endif SDMMC_INIT_STEP(is_mmc, sdmmc_init_mmc_bus_width); SDMMC_INIT_STEP(always, sdmmc_init_host_bus_width); } @@ -169,8 +181,10 @@ esp_err_t sdmmc_card_init(const sdmmc_host_t* config, sdmmc_card_t* card) SDMMC_INIT_STEP(is_sdmem, sdmmc_check_scr); /* Sanity check after eMMC switch to HS mode */ SDMMC_INIT_STEP(is_mmc, sdmmc_init_mmc_check_ext_csd); +#if CONFIG_SD_ENABLE_SDIO_SUPPORT /* Sanity check for SDIO after switching the frequency */ SDMMC_INIT_STEP_PARAM(is_sdio, sdmmc_io_init_check_card_cap, &card_cap); +#endif return ESP_OK; }