diff --git a/components/esp_driver_sdmmc/src/sd_host_sdmmc.c b/components/esp_driver_sdmmc/src/sd_host_sdmmc.c index 4b6002df833..cdd5e686e80 100644 --- a/components/esp_driver_sdmmc/src/sd_host_sdmmc.c +++ b/components/esp_driver_sdmmc/src/sd_host_sdmmc.c @@ -460,6 +460,16 @@ bool sd_host_check_buffer_alignment(sd_host_sdmmc_slot_t *slot, const void *buf, return false; } +#if !SOC_SDMMC_PSRAM_DMA_CAPABLE + // The SDMMC peripheral's DMA cannot reach PSRAM on this target, so a PSRAM + // buffer can never be used directly regardless of its alignment. Reporting + // it as not directly usable makes the protocol layer fall back to an + // internal DMA-capable buffer. + if (esp_ptr_external_ram(buf)) { + return false; + } +#endif + esp_err_t ret = ESP_FAIL; int cache_flags = 0; size_t cache_alignment_bytes = 0; diff --git a/components/esp_driver_sdmmc/test_apps/sd_test_utils/components/common_test_flows/include/sdmmc_test_rw_common.h b/components/esp_driver_sdmmc/test_apps/sd_test_utils/components/common_test_flows/include/sdmmc_test_rw_common.h index d31c917b2e2..6061b821ea3 100644 --- a/components/esp_driver_sdmmc/test_apps/sd_test_utils/components/common_test_flows/include/sdmmc_test_rw_common.h +++ b/components/esp_driver_sdmmc/test_apps/sd_test_utils/components/common_test_flows/include/sdmmc_test_rw_common.h @@ -73,6 +73,31 @@ void sdmmc_test_rw_highprio_task(sdmmc_card_t* card); */ void sdmmc_test_rw_unaligned_buffer_multiblock(sdmmc_card_t* card, size_t chunk_size); +/** + * @brief Test read/write with PSRAM-allocated buffers + * + * This function verifies that the driver correctly handles buffers allocated in PSRAM. + * When the host reports the PSRAM buffer as directly usable (via check_buffer_alignment), + * data is transferred directly without intermediate copying. Otherwise, the driver uses + * double-buffering through internal RAM. + * + * The test covers: + * - Writing from PSRAM, reading to internal RAM + * - Writing from internal RAM, reading to PSRAM + * - Both writing and reading from PSRAM + * + * If PSRAM is not enabled (CONFIG_SPIRAM), this function is a no-op. Callers + * must skip the test (TEST_IGNORE) BEFORE initializing the slot/controller, so + * that this function is not relied upon to abort the test. Doing the skip here + * would longjmp out of the test before the caller's cleanup runs and leak the + * SD slot. + * + * This test function works both with SDMMC and SDSPI hosts. + * + * @param card Pointer to the card object, must be initialized before calling this function. + */ +void sdmmc_test_rw_psram_buffer(sdmmc_card_t *card); + #ifdef __cplusplus }; #endif diff --git a/components/esp_driver_sdmmc/test_apps/sd_test_utils/components/common_test_flows/sdmmc_test_rw_common.c b/components/esp_driver_sdmmc/test_apps/sd_test_utils/components/common_test_flows/sdmmc_test_rw_common.c index ee28ce83e47..32ffd704725 100644 --- a/components/esp_driver_sdmmc/test_apps/sd_test_utils/components/common_test_flows/sdmmc_test_rw_common.c +++ b/components/esp_driver_sdmmc/test_apps/sd_test_utils/components/common_test_flows/sdmmc_test_rw_common.c @@ -14,6 +14,7 @@ #include "test_utils.h" #include "sdkconfig.h" #include "soc/soc_caps.h" +#include "esp_memory_utils.h" #include "unity.h" #include "sd_protocol_defs.h" #include "sdmmc_cmd.h" @@ -295,3 +296,64 @@ void sdmmc_test_rw_unaligned_buffer_multiblock(sdmmc_card_t* card, size_t chunk_ free(buffer); } + +void sdmmc_test_rw_psram_buffer(sdmmc_card_t *card) +{ +#if !CONFIG_SPIRAM + /* The PSRAM-disabled skip is intentionally NOT done here via TEST_IGNORE. + * This function runs after the slot/controller has been initialized, and + * TEST_IGNORE would longjmp out before the caller's *_end() cleanup runs, + * leaking the slot. Callers must skip before initializing the hardware. + */ + (void)card; +#else + const size_t block_size = card->csd.sector_size; + const size_t block_count = 8; + const size_t buffer_size = block_size * block_count; + + /* Allocate buffer in PSRAM */ + uint8_t *psram_buf = heap_caps_malloc(buffer_size, MALLOC_CAP_SPIRAM | MALLOC_CAP_DMA | MALLOC_CAP_CACHE_ALIGNED); + TEST_ASSERT_NOT_NULL_MESSAGE(psram_buf, "Failed to allocate PSRAM buffer; is PSRAM enabled?"); + TEST_ASSERT_MESSAGE(esp_ptr_external_ram(psram_buf), "Buffer not in PSRAM"); + + /* Also allocate a reference buffer in internal RAM for comparison */ + uint8_t *internal_buf = heap_caps_malloc(buffer_size, MALLOC_CAP_DMA | MALLOC_CAP_CACHE_ALIGNED); + TEST_ASSERT_NOT_NULL(internal_buf); + + /* A PSRAM buffer can be transferred directly only if the host reports it as + * usable; otherwise the protocol layer transparently bounce-buffers it. This + * test verifies correctness for both cases. */ + bool host_can_use_psram_directly = + card->host.check_buffer_alignment(card->host.slot, psram_buf, buffer_size); + printf("Testing PSRAM buffer R/W: %d blocks, host can use PSRAM directly=%s\n", + (int)block_count, host_can_use_psram_directly ? "true" : "false"); + + /* Test A: Write from PSRAM buffer, read back to internal buffer, verify */ + const uint32_t seed_a = 0xABCD1234; + fill_buffer(seed_a, psram_buf, buffer_size / sizeof(uint32_t)); + TEST_ESP_OK(sdmmc_write_sectors(card, psram_buf, 0, block_count)); + memset(internal_buf, 0xcc, buffer_size); + TEST_ESP_OK(sdmmc_read_sectors(card, internal_buf, 0, block_count)); + check_buffer(seed_a, internal_buf, buffer_size / sizeof(uint32_t)); + + /* Test B: Write from internal buffer, read back to PSRAM buffer, verify */ + const uint32_t seed_b = 0x5678EFAB; + fill_buffer(seed_b, internal_buf, buffer_size / sizeof(uint32_t)); + TEST_ESP_OK(sdmmc_write_sectors(card, internal_buf, 0, block_count)); + memset(psram_buf, 0xcc, buffer_size); + TEST_ESP_OK(sdmmc_read_sectors(card, psram_buf, 0, block_count)); + check_buffer(seed_b, psram_buf, buffer_size / sizeof(uint32_t)); + + /* Test C: Both write and read from PSRAM buffer */ + const uint32_t seed_c = 0xDEAD9876; + fill_buffer(seed_c, psram_buf, buffer_size / sizeof(uint32_t)); + TEST_ESP_OK(sdmmc_write_sectors(card, psram_buf, 0, block_count)); + memset(psram_buf, 0xcc, buffer_size); + TEST_ESP_OK(sdmmc_read_sectors(card, psram_buf, 0, block_count)); + check_buffer(seed_c, psram_buf, buffer_size / sizeof(uint32_t)); + + free(psram_buf); + free(internal_buf); + printf("PSRAM buffer R/W test passed\n"); +#endif // CONFIG_SPIRAM +} diff --git a/components/esp_driver_sdmmc/test_apps/sdmmc/components/sdmmc_tests/sdmmc_test_rw_sd.c b/components/esp_driver_sdmmc/test_apps/sdmmc/components/sdmmc_tests/sdmmc_test_rw_sd.c index 8c1a5c36a76..51cc9999f7f 100644 --- a/components/esp_driver_sdmmc/test_apps/sdmmc/components/sdmmc_tests/sdmmc_test_rw_sd.c +++ b/components/esp_driver_sdmmc/test_apps/sdmmc/components/sdmmc_tests/sdmmc_test_rw_sd.c @@ -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: Apache-2.0 */ @@ -128,3 +128,26 @@ TEST_CASE("sdmmc read/write with concurrent high-prio task, slot 1, 4-bit", "[sd { do_one_sdmmc_rw_test_highprio_task(1, 4); } + +static void do_one_sdmmc_rw_test_psram_dma_buffer(int slot, int width) +{ + sdmmc_card_t card; + int freq_khz = SDMMC_FREQ_HIGHSPEED; +#if !CONFIG_SPIRAM + TEST_IGNORE_MESSAGE("PSRAM is not enabled"); +#endif + sdmmc_test_sd_skip_if_board_incompatible(slot, width, freq_khz, NO_DDR, NO_EMMC); + sdmmc_test_sd_begin(slot, width, freq_khz, 0, &card); + sdmmc_test_rw_psram_buffer(&card); + sdmmc_test_sd_end(&card); +} + +TEST_CASE("sdmmc read/write using PSRAM DMA accessible buffer, slot 0, 4-bit", "[sdmmc]") +{ + do_one_sdmmc_rw_test_psram_dma_buffer(0, 4); +} + +TEST_CASE("sdmmc read/write using PSRAM DMA accessible buffer, slot 1, 4-bit", "[sdmmc]") +{ + do_one_sdmmc_rw_test_psram_dma_buffer(1, 4); +} diff --git a/components/esp_driver_sdspi/test_apps/sdspi/components/sdspi_tests/sdmmc_test_rw_spi.c b/components/esp_driver_sdspi/test_apps/sdspi/components/sdspi_tests/sdmmc_test_rw_spi.c index 986ff591ad1..954f34bc245 100644 --- a/components/esp_driver_sdspi/test_apps/sdspi/components/sdspi_tests/sdmmc_test_rw_spi.c +++ b/components/esp_driver_sdspi/test_apps/sdspi/components/sdspi_tests/sdmmc_test_rw_spi.c @@ -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: Apache-2.0 */ @@ -107,3 +107,30 @@ TEST_CASE("sdspi read/write performance - wait_for_miso == -1, slot 1", "[sdspi] //here freq should be changed to SDMMC_FREQ_HIGHSPEED after fixing IDF-8749 do_one_sdspi_perf_test_dont_wait_for_miso(SLOT_1, SDMMC_FREQ_DEFAULT); } + +/* ========== Read/write PSRAM DMA test, SPI ========== */ + +static void do_one_sdspi_psram_dma_test(int slot, int freq_khz) +{ + sdmmc_card_t card; +#if !CONFIG_SPIRAM + TEST_IGNORE_MESSAGE("PSRAM is not enabled"); +#endif + sdmmc_test_spi_skip_if_board_incompatible(slot, freq_khz); + sdmmc_test_spi_begin(slot, freq_khz, &card, NULL, NULL, NULL); + sdmmc_card_print_info(stdout, &card); + sdmmc_test_rw_psram_buffer(&card); + sdmmc_test_spi_end(slot, &card); +} + +TEST_CASE("sdspi read/write psram dma, slot 0", "[sdspi]") +{ + do_one_sdspi_psram_dma_test(SLOT_0, SDMMC_FREQ_HIGHSPEED); +} + +TEST_CASE("sdspi read/write psram dma, slot 1", "[sdspi]") +{ + //TODO: IDF-8749 + //here freq should be changed to SDMMC_FREQ_HIGHSPEED after fixing IDF-8749 + do_one_sdspi_psram_dma_test(SLOT_1, SDMMC_FREQ_DEFAULT); +} diff --git a/components/sdmmc/include/esp_private/sdmmc_blockdev.h b/components/sdmmc/include/esp_private/sdmmc_blockdev.h new file mode 100644 index 00000000000..37930d544ca --- /dev/null +++ b/components/sdmmc/include/esp_private/sdmmc_blockdev.h @@ -0,0 +1,22 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include +#include "esp_err.h" + +#ifdef __cplusplus +extern "C" { +#endif + +esp_err_t sdmmc_blockdev_calculate_sectors(size_t sector_size, uint64_t addr, size_t data_len, + size_t *out_start_sector_num, size_t *out_num_of_sectors); + +#ifdef __cplusplus +} +#endif diff --git a/components/sdmmc/include/sd_protocol_types.h b/components/sdmmc/include/sd_protocol_types.h index 9e2a0a24c69..75d4e96a4cb 100644 --- a/components/sdmmc/include/sd_protocol_types.h +++ b/components/sdmmc/include/sd_protocol_types.h @@ -247,7 +247,7 @@ typedef struct { */ void* dma_aligned_buffer; sd_pwr_ctrl_handle_t pwr_ctrl_handle; /*!< Power control handle */ - bool (*check_buffer_alignment)(int slot, const void *buf, size_t size); /*!< Check if buffer meets alignment requirements */ + bool (*check_buffer_alignment)(int slot, const void *buf, size_t size); /*!< Check if the host can use the buffer directly for a transfer (accounts for alignment and any hardware-specific DMA reachability constraints) */ esp_err_t (*is_slot_set_to_uhs1)(int slot, bool *is_uhs1); /*!< host slot is set to uhs1 or not*/ } sdmmc_host_t; diff --git a/components/sdmmc/sdmmc_blockdev.c b/components/sdmmc/sdmmc_blockdev.c index d951dd6a75e..3fbf43c1b3b 100644 --- a/components/sdmmc/sdmmc_blockdev.c +++ b/components/sdmmc/sdmmc_blockdev.c @@ -1,34 +1,37 @@ /* - * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ #include #include "esp_private/sdmmc_common.h" +#include "esp_private/sdmmc_blockdev.h" #include "esp_blockdev.h" #include "sdmmc_cmd.h" -static esp_err_t calculate_start_sector_num_and_sector_count(size_t sector_size, uint64_t addr, size_t data_len, size_t* out_start_sector_num, size_t* out_num_of_sectors) +esp_err_t sdmmc_blockdev_calculate_sectors(size_t sector_size, uint64_t addr, size_t data_len, + size_t *out_start_sector_num, size_t *out_num_of_sectors) { - size_t offset_in_start_sector = (size_t) addr % sector_size; - size_t offset_in_end_sector = (size_t) data_len % sector_size; - - // Has to be aligned to sector boundaries - if (offset_in_start_sector != 0 || offset_in_end_sector != 0) { + if (sector_size == 0 || addr % sector_size != 0 || data_len % sector_size != 0) { return ESP_ERR_INVALID_ARG; } + if (data_len > UINT64_MAX - addr) { + return ESP_ERR_INVALID_SIZE; + } - size_t start_sector_num = (size_t) addr / sector_size; - size_t last_byte_addr = (size_t) (addr + data_len - 1); // Address of the last accessed byte - size_t end_sector_num = last_byte_addr / sector_size; + uint64_t start_sector_num = addr / sector_size; + size_t num_of_sectors = data_len / sector_size; + if (start_sector_num > SIZE_MAX || num_of_sectors > SIZE_MAX - start_sector_num) { + return ESP_ERR_INVALID_SIZE; + } if (out_start_sector_num) { - *out_start_sector_num = start_sector_num; + *out_start_sector_num = (size_t) start_sector_num; } if (out_num_of_sectors) { - *out_num_of_sectors = end_sector_num - start_sector_num + 1; + *out_num_of_sectors = num_of_sectors; } return ESP_OK; @@ -41,7 +44,7 @@ static esp_err_t sdmmc_blockdev_read(esp_blockdev_handle_t handle, uint8_t* dst_ } sdmmc_card_t* card = (sdmmc_card_t*) handle->ctx; size_t start_sector_num, num_of_sectors; - esp_err_t err = calculate_start_sector_num_and_sector_count((size_t) card->csd.sector_size, src_addr, data_read_len, &start_sector_num, &num_of_sectors); + esp_err_t err = sdmmc_blockdev_calculate_sectors((size_t) card->csd.sector_size, src_addr, data_read_len, &start_sector_num, &num_of_sectors); if (err != ESP_OK) { return err; } @@ -56,7 +59,7 @@ static esp_err_t sdmmc_blockdev_write(esp_blockdev_handle_t handle, const uint8_ } sdmmc_card_t* card = (sdmmc_card_t*) handle->ctx; size_t start_sector_num, num_of_sectors; - esp_err_t err = calculate_start_sector_num_and_sector_count((size_t) card->csd.sector_size, dst_addr, data_write_len, &start_sector_num, &num_of_sectors); + esp_err_t err = sdmmc_blockdev_calculate_sectors((size_t) card->csd.sector_size, dst_addr, data_write_len, &start_sector_num, &num_of_sectors); if (err != ESP_OK) { return err; } @@ -71,7 +74,7 @@ static esp_err_t sdmmc_blockdev_erase(esp_blockdev_handle_t handle, uint64_t sta } sdmmc_card_t* card = (sdmmc_card_t*) handle->ctx; size_t start_sector_num, num_of_sectors; - esp_err_t err = calculate_start_sector_num_and_sector_count((size_t) card->csd.sector_size, start_addr, erase_len, &start_sector_num, &num_of_sectors); + esp_err_t err = sdmmc_blockdev_calculate_sectors((size_t) card->csd.sector_size, start_addr, erase_len, &start_sector_num, &num_of_sectors); if (err != ESP_OK) { return err; } diff --git a/components/sdmmc/sdmmc_cmd.c b/components/sdmmc/sdmmc_cmd.c index eb9622521df..881d515902a 100644 --- a/components/sdmmc/sdmmc_cmd.c +++ b/components/sdmmc/sdmmc_cmd.c @@ -23,6 +23,20 @@ static inline size_t get_chunk_size(const sdmmc_card_t *card) return (chunk_size != 0) ? chunk_size : 1; } +/** + * @brief Whether the host can transfer the user buffer directly, without an + * intermediate DMA-capable buffer. + * + * The protocol layer does not need to reason about DMA or PSRAM: it simply asks + * the host driver whether the buffer is usable as-is. The driver accounts for + * alignment and any hardware-specific reachability constraints (e.g. whether the + * peripheral's DMA can reach PSRAM). + */ +static inline bool sdmmc_buffer_directly_usable(const sdmmc_card_t *card, const void *buf, size_t size) +{ + return card->host.check_buffer_alignment(card->host.slot, buf, size); +} + static esp_err_t allocate_dma_buf(size_t* actual_size, size_t block_size, void **buf) { if (actual_size == NULL || buf == NULL) { @@ -486,16 +500,10 @@ esp_err_t sdmmc_write_sectors(sdmmc_card_t* card, const void* src, esp_err_t err = ESP_OK; size_t block_size = card->csd.sector_size; - bool is_aligned = card->host.check_buffer_alignment(card->host.slot, src, block_size * block_count); - - if (is_aligned - #if !SOC_SDMMC_PSRAM_DMA_CAPABLE - && !esp_ptr_external_ram(src) - #endif - ) { + if (sdmmc_buffer_directly_usable(card, src, block_size * block_count)) { err = sdmmc_write_sectors_dma(card, src, start_block, block_count, block_size * block_count); } else { - // SDMMC peripheral needs DMA-capable buffers. Split the write into + // The host cannot transfer this buffer directly. Split the write into // separate (multi) block writes, if needed, and allocate a temporary // DMA-capable buffer. size_t chunk_size = get_chunk_size(card); @@ -649,16 +657,10 @@ esp_err_t sdmmc_read_sectors(sdmmc_card_t* card, void* dst, esp_err_t err = ESP_OK; size_t block_size = card->csd.sector_size; - bool is_aligned = card->host.check_buffer_alignment(card->host.slot, dst, block_size * block_count); - - if (is_aligned - #if !SOC_SDMMC_PSRAM_DMA_CAPABLE - && !esp_ptr_external_ram(dst) - #endif - ) { + if (sdmmc_buffer_directly_usable(card, dst, block_size * block_count)) { err = sdmmc_read_sectors_dma(card, dst, start_block, block_count, block_size * block_count); } else { - // SDMMC peripheral needs DMA-capable buffers. Split the read into + // The host cannot transfer this buffer directly. Split the read into // separate (multi) block reads, if needed, and allocate a temporary // DMA-capable buffer. size_t chunk_size = get_chunk_size(card); diff --git a/components/sdmmc/test_apps/main/test_sdmmc_app.c b/components/sdmmc/test_apps/main/test_sdmmc_app.c index 1fe319e4e7a..3dee78e0621 100644 --- a/components/sdmmc/test_apps/main/test_sdmmc_app.c +++ b/components/sdmmc/test_apps/main/test_sdmmc_app.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -9,23 +9,42 @@ #include #include "unity.h" #include "unity_fixture.h" +#include "unity_test_utils.h" #include "sd_protocol_defs.h" #include "sdmmc_cmd.h" #include "sdmmc_test_begin_end_sd.h" #include "sdmmc_test_rw_common.h" #include "esp_blockdev.h" +#include "esp_private/sdmmc_blockdev.h" -TEST_GROUP(sdmmc); +#define TEST_MEMORY_LEAK_THRESHOLD (200) -TEST_SETUP(sdmmc) +TEST_CASE("sdmmc blockdev converts byte ranges to sectors", "[sdmmc]") { + size_t start_sector; + size_t sector_count; + + TEST_ESP_OK(sdmmc_blockdev_calculate_sectors(512, UINT64_C(0x100000000), 1024, + &start_sector, §or_count)); + TEST_ASSERT_EQUAL_UINT32(8388608, start_sector); + TEST_ASSERT_EQUAL_UINT32(2, sector_count); + + TEST_ESP_OK(sdmmc_blockdev_calculate_sectors(512, UINT64_C(0x100000000), 0, + &start_sector, §or_count)); + TEST_ASSERT_EQUAL_UINT32(8388608, start_sector); + TEST_ASSERT_EQUAL_UINT32(0, sector_count); + + TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, + sdmmc_blockdev_calculate_sectors(512, 1, 512, NULL, NULL)); + TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, + sdmmc_blockdev_calculate_sectors(512, 0, 1, NULL, NULL)); + TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, + sdmmc_blockdev_calculate_sectors(0, 0, 512, NULL, NULL)); + TEST_ASSERT_EQUAL(ESP_ERR_INVALID_SIZE, + sdmmc_blockdev_calculate_sectors(512, UINT64_MAX - 511, 512, NULL, NULL)); } -TEST_TEAR_DOWN(sdmmc) -{ -} - -TEST(sdmmc, test_bdl_interface) +TEST_CASE("sdmmc extra, bdl interface test", "[sdcard]") { sdmmc_card_t card; int slot = 1; @@ -70,7 +89,7 @@ TEST(sdmmc, test_bdl_interface) sdmmc_test_sd_end(&card); } -TEST(sdmmc, test_multiblock_unaligned_rw) +TEST_CASE("sdmmc extra, multiblock unaligned rw test", "[sdcard]") { sdmmc_card_t card; int slot = 1; @@ -82,13 +101,17 @@ TEST(sdmmc, test_multiblock_unaligned_rw) sdmmc_test_sd_end(&card); } -TEST_GROUP_RUNNER(sdmmc) +void setUp(void) { - RUN_TEST_CASE(sdmmc, test_bdl_interface) - RUN_TEST_CASE(sdmmc, test_multiblock_unaligned_rw) + unity_utils_record_free_mem(); +} + +void tearDown(void) +{ + unity_utils_evaluate_leaks_direct(TEST_MEMORY_LEAK_THRESHOLD); } void app_main(void) { - UNITY_MAIN(sdmmc); + unity_run_menu(); } diff --git a/components/sdmmc/test_apps/pytest_sdmmc_extra.py b/components/sdmmc/test_apps/pytest_sdmmc_extra.py index 51c186ee2dc..a067d5bf7bc 100644 --- a/components/sdmmc/test_apps/pytest_sdmmc_extra.py +++ b/components/sdmmc/test_apps/pytest_sdmmc_extra.py @@ -10,4 +10,4 @@ from pytest_embedded_idf.utils import idf_parametrize @idf_parametrize('config', ['default'], indirect=['config']) @idf_parametrize('target', ['esp32'], indirect=['target']) def test_sdmmc_extra(dut: Dut) -> None: - dut.expect_unity_test_output() + dut.run_all_single_board_cases()