fix(sdmmc): Allow disabling SDIO specific steps in sdmmc card init

This commit is contained in:
sonika.rathi
2025-07-21 11:47:59 +02:00
committed by BOT
parent 863d682614
commit 4d91eac13f
14 changed files with 160 additions and 6 deletions

View File

@@ -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"

View File

@@ -0,0 +1,47 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdio.h>
#include <string.h>
#include <sys/unistd.h>
#include <sys/stat.h>
#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

View File

@@ -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,

View File

@@ -0,0 +1,2 @@
# SDMMC Configuration
CONFIG_SD_ENABLE_SDIO_SUPPORT=n

View File

@@ -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"

View File

@@ -0,0 +1,44 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdio.h>
#include <string.h>
#include <sys/unistd.h>
#include <sys/stat.h>
#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

View File

@@ -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)

View File

@@ -0,0 +1,2 @@
# SDMMC Configuration
CONFIG_SD_ENABLE_SDIO_SUPPORT=n

View File

@@ -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()

8
components/sdmmc/Kconfig Normal file
View File

@@ -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

View File

@@ -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.

View File

@@ -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);

View File

@@ -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);
}

View File

@@ -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;
}