diff --git a/components/esp_driver_sdmmc/src/sdmmc_transaction.c b/components/esp_driver_sdmmc/src/sdmmc_transaction.c index ca471ec384..c6a360b8d1 100644 --- a/components/esp_driver_sdmmc/src/sdmmc_transaction.c +++ b/components/esp_driver_sdmmc/src/sdmmc_transaction.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -14,7 +14,6 @@ #include "freertos/semphr.h" #include "freertos/task.h" #include "soc/sdmmc_periph.h" -#include "soc/soc_memory_layout.h" #include "driver/sdmmc_types.h" #include "driver/sdmmc_defs.h" #include "driver/sdmmc_host.h" @@ -130,14 +129,18 @@ esp_err_t sdmmc_host_do_transaction(int slot, sdmmc_command_t* cmdinfo) if (cmdinfo->data) { // Length should be either <4 or >=4 and =0 (mod 4). if (cmdinfo->datalen >= 4 && cmdinfo->datalen % 4 != 0) { - ESP_LOGD(TAG, "%s: invalid size: total=%d", + ESP_LOGE(TAG, "%s: invalid size: total=%d", __func__, cmdinfo->datalen); ret = ESP_ERR_INVALID_SIZE; goto out; } - if ((intptr_t) cmdinfo->data % 4 != 0 || - !esp_ptr_dma_capable(cmdinfo->data)) { - ESP_LOGD(TAG, "%s: buffer %p can not be used for DMA", __func__, cmdinfo->data); + esp_dma_mem_info_t dma_mem_info; + sdmmc_host_get_dma_info(slot, &dma_mem_info); +#ifdef SOC_SDMMC_PSRAM_DMA_CAPABLE + dma_mem_info.extra_heap_caps |= MALLOC_CAP_SPIRAM; +#endif + if (!esp_dma_is_buffer_alignment_satisfied(cmdinfo->data, cmdinfo->buflen, dma_mem_info)) { + ESP_LOGE(TAG, "%s: buffer %p can not be used for DMA", __func__, cmdinfo->data); ret = ESP_ERR_INVALID_ARG; goto out; } 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 625f9d0786..360928efd8 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 @@ -1,13 +1,16 @@ /* - * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ +#include #include #include #include #include #include +#include "esp_dma_utils.h" +#include "esp_heap_caps.h" #include "test_utils.h" #include "sdkconfig.h" #include "soc/soc_caps.h" @@ -17,7 +20,8 @@ #include "sdmmc_test_rw_common.h" static void do_single_rw_perf_test(sdmmc_card_t* card, size_t start_block, - size_t block_count, size_t alignment, FILE* performance_log); + size_t block_count, size_t alignment, FILE* performance_log, + uint32_t extra_alloc_caps); static void fill_buffer(uint32_t seed, uint8_t* dst, size_t count) { @@ -41,13 +45,22 @@ static void check_buffer(uint32_t seed, const uint8_t* src, size_t count) } static void do_single_rw_perf_test(sdmmc_card_t* card, size_t start_block, - size_t block_count, size_t alignment, FILE* performance_log) + size_t block_count, size_t alignment, FILE* performance_log, + uint32_t extra_alloc_caps) { size_t block_size = card->csd.sector_size; size_t total_size = block_size * block_count; - printf(" %8d | %3d | %d | %4.1f ", start_block, block_count, alignment, total_size / 1024.0f); + const char* alloc_str = (extra_alloc_caps & MALLOC_CAP_SPIRAM) ? "spiram" : " sram "; + printf(" %8d | %3d | %d | %s | %4.1f ", start_block, block_count, alignment, alloc_str, total_size / 1024.0f); + + size_t actual_size = 0; + uint32_t *buffer = NULL; + esp_dma_mem_info_t dma_mem_info = { + .extra_heap_caps = extra_alloc_caps, + .dma_alignment_bytes = 64, + }; + TEST_ESP_OK(esp_dma_capable_malloc(total_size + 4, &dma_mem_info, (void**) &buffer, &actual_size)); - uint32_t* buffer = heap_caps_malloc(total_size + 4, MALLOC_CAP_DMA); size_t offset = alignment % 4; uint8_t* c_buffer = (uint8_t*) buffer + offset; fill_buffer(start_block, c_buffer, total_size / sizeof(buffer[0])); @@ -80,10 +93,10 @@ static void do_single_rw_perf_test(sdmmc_card_t* card, size_t start_block, static const char wr_speed_str[] = "SDMMC_WR_SPEED"; static const char rd_speed_str[] = "SDMMC_RD_SPEED"; int aligned = ((alignment % 4) == 0) ? 1 : 0; - IDF_LOG_PERFORMANCE(wr_speed_str, "%d, blk_n: %d, aligned: %d", - (int)(total_size * 1000 / time_wr), block_count, aligned); - IDF_LOG_PERFORMANCE(rd_speed_str, "%d, blk_n: %d, aligned: %d", - (int)(total_size * 1000 / time_rd), block_count, aligned); + IDF_LOG_PERFORMANCE(wr_speed_str, "%d, blk_n: %d, aligned: %d, alloc: %s", + (int)(total_size * 1000 / time_wr), block_count, aligned, alloc_str); + IDF_LOG_PERFORMANCE(rd_speed_str, "%d, blk_n: %d, aligned: %d, alloc: %s", + (int)(total_size * 1000 / time_rd), block_count, aligned, alloc_str); stdout = old_stdout; } } @@ -93,7 +106,13 @@ void sdmmc_test_rw_unaligned_buffer(sdmmc_card_t* card) const size_t buffer_size = 4096; const size_t block_count = buffer_size / 512; const size_t extra = 4; - uint8_t* buffer = heap_caps_malloc(buffer_size + extra, MALLOC_CAP_DMA); + const size_t total_size = buffer_size + extra; + size_t actual_size = 0; + uint8_t *buffer = NULL; + esp_dma_mem_info_t dma_mem_info = { + .dma_alignment_bytes = 64, + }; + TEST_ESP_OK(esp_dma_capable_malloc(total_size + 4, &dma_mem_info, (void**) &buffer, &actual_size)); // Check read behavior: do aligned write, then unaligned read const uint32_t seed = 0x89abcdef; @@ -116,20 +135,30 @@ void sdmmc_test_rw_unaligned_buffer(sdmmc_card_t* card) void sdmmc_test_rw_performance(sdmmc_card_t *card, FILE *perf_log) { sdmmc_card_print_info(stdout, card); - printf(" sector | count | align | size(kB) | wr_time(ms) | wr_speed(MB/s) | rd_time(ms) | rd_speed(MB/s)\n"); + printf(" sector | count | align | alloc | size(kB) | wr_time(ms) | wr_speed(MB/s) | rd_time(ms) | rd_speed(MB/s)\n"); const int offset = 0; /* aligned */ - do_single_rw_perf_test(card, offset, 1, 4, perf_log); - do_single_rw_perf_test(card, offset, 4, 4, perf_log); - do_single_rw_perf_test(card, offset, 8, 4, perf_log); - do_single_rw_perf_test(card, offset, 16, 4, perf_log); - do_single_rw_perf_test(card, offset, 32, 4, perf_log); - do_single_rw_perf_test(card, offset, 64, 4, perf_log); - do_single_rw_perf_test(card, offset, 128, 4, perf_log); + do_single_rw_perf_test(card, offset, 1, 4, perf_log, 0); + do_single_rw_perf_test(card, offset, 4, 4, perf_log, 0); + do_single_rw_perf_test(card, offset, 8, 4, perf_log, 0); + do_single_rw_perf_test(card, offset, 16, 4, perf_log, 0); + do_single_rw_perf_test(card, offset, 32, 4, perf_log, 0); + do_single_rw_perf_test(card, offset, 64, 4, perf_log, 0); + do_single_rw_perf_test(card, offset, 128, 4, perf_log, 0); /* unaligned */ - do_single_rw_perf_test(card, offset, 1, 1, perf_log); - do_single_rw_perf_test(card, offset, 8, 1, perf_log); - do_single_rw_perf_test(card, offset, 128, 1, perf_log); + do_single_rw_perf_test(card, offset, 1, 1, perf_log, 0); + do_single_rw_perf_test(card, offset, 8, 1, perf_log, 0); + do_single_rw_perf_test(card, offset, 128, 1, perf_log, 0); +#if CONFIG_SPIRAM && SOC_SDMMC_PSRAM_DMA_CAPABLE + /* spiram */ + do_single_rw_perf_test(card, offset, 1, 4, perf_log, MALLOC_CAP_SPIRAM); + do_single_rw_perf_test(card, offset, 4, 4, perf_log, MALLOC_CAP_SPIRAM); + do_single_rw_perf_test(card, offset, 8, 4, perf_log, MALLOC_CAP_SPIRAM); + do_single_rw_perf_test(card, offset, 16, 4, perf_log, MALLOC_CAP_SPIRAM); + do_single_rw_perf_test(card, offset, 32, 4, perf_log, MALLOC_CAP_SPIRAM); + do_single_rw_perf_test(card, offset, 64, 4, perf_log, MALLOC_CAP_SPIRAM); + do_single_rw_perf_test(card, offset, 128, 4, perf_log, MALLOC_CAP_SPIRAM); +#endif } void sdmmc_test_rw_with_offset(sdmmc_card_t* card) @@ -137,22 +166,22 @@ void sdmmc_test_rw_with_offset(sdmmc_card_t* card) sdmmc_card_print_info(stdout, card); printf(" sector | count | align | size(kB) | wr_time(ms) | wr_speed(MB/s) | rd_time(ms) | rd_speed(MB/s)\n"); /* aligned */ - do_single_rw_perf_test(card, 1, 16, 4, NULL); - do_single_rw_perf_test(card, 16, 32, 4, NULL); - do_single_rw_perf_test(card, 48, 64, 4, NULL); - do_single_rw_perf_test(card, 128, 128, 4, NULL); - do_single_rw_perf_test(card, card->csd.capacity - 64, 32, 4, NULL); - do_single_rw_perf_test(card, card->csd.capacity - 64, 64, 4, NULL); - do_single_rw_perf_test(card, card->csd.capacity - 8, 1, 4, NULL); - do_single_rw_perf_test(card, card->csd.capacity / 2, 1, 4, NULL); - do_single_rw_perf_test(card, card->csd.capacity / 2, 4, 4, NULL); - do_single_rw_perf_test(card, card->csd.capacity / 2, 8, 4, NULL); - do_single_rw_perf_test(card, card->csd.capacity / 2, 16, 4, NULL); - do_single_rw_perf_test(card, card->csd.capacity / 2, 32, 4, NULL); - do_single_rw_perf_test(card, card->csd.capacity / 2, 64, 4, NULL); - do_single_rw_perf_test(card, card->csd.capacity / 2, 128, 4, NULL); + do_single_rw_perf_test(card, 1, 16, 4, NULL, 0); + do_single_rw_perf_test(card, 16, 32, 4, NULL, 0); + do_single_rw_perf_test(card, 48, 64, 4, NULL, 0); + do_single_rw_perf_test(card, 128, 128, 4, NULL, 0); + do_single_rw_perf_test(card, card->csd.capacity - 64, 32, 4, NULL, 0); + do_single_rw_perf_test(card, card->csd.capacity - 64, 64, 4, NULL, 0); + do_single_rw_perf_test(card, card->csd.capacity - 8, 1, 4, NULL, 0); + do_single_rw_perf_test(card, card->csd.capacity / 2, 1, 4, NULL, 0); + do_single_rw_perf_test(card, card->csd.capacity / 2, 4, 4, NULL, 0); + do_single_rw_perf_test(card, card->csd.capacity / 2, 8, 4, NULL, 0); + do_single_rw_perf_test(card, card->csd.capacity / 2, 16, 4, NULL, 0); + do_single_rw_perf_test(card, card->csd.capacity / 2, 32, 4, NULL, 0); + do_single_rw_perf_test(card, card->csd.capacity / 2, 64, 4, NULL, 0); + do_single_rw_perf_test(card, card->csd.capacity / 2, 128, 4, NULL, 0); /* unaligned */ - do_single_rw_perf_test(card, card->csd.capacity / 2, 1, 1, NULL); - do_single_rw_perf_test(card, card->csd.capacity / 2, 8, 1, NULL); - do_single_rw_perf_test(card, card->csd.capacity / 2, 128, 1, NULL); + do_single_rw_perf_test(card, card->csd.capacity / 2, 1, 1, NULL, 0); + do_single_rw_perf_test(card, card->csd.capacity / 2, 8, 1, NULL, 0); + do_single_rw_perf_test(card, card->csd.capacity / 2, 128, 1, NULL, 0); } diff --git a/components/esp_driver_sdmmc/test_apps/sdmmc/main/CMakeLists.txt b/components/esp_driver_sdmmc/test_apps/sdmmc/main/CMakeLists.txt index 03cd59aaed..e253a3431b 100644 --- a/components/esp_driver_sdmmc/test_apps/sdmmc/main/CMakeLists.txt +++ b/components/esp_driver_sdmmc/test_apps/sdmmc/main/CMakeLists.txt @@ -5,6 +5,8 @@ set(priv_requires sdmmc_tests # general unity + # for PSRAM tests + esp_psram ) idf_component_register(SRCS ${srcs} diff --git a/components/esp_driver_sdmmc/test_apps/sdmmc/sdkconfig.defaults.esp32p4 b/components/esp_driver_sdmmc/test_apps/sdmmc/sdkconfig.defaults.esp32p4 new file mode 100644 index 0000000000..7b8ca4566c --- /dev/null +++ b/components/esp_driver_sdmmc/test_apps/sdmmc/sdkconfig.defaults.esp32p4 @@ -0,0 +1,5 @@ +CONFIG_SDMMC_BOARD_ESP32P4_EV_BOARD=y + +CONFIG_SPIRAM=y +CONFIG_IDF_EXPERIMENTAL_FEATURES=y +CONFIG_SPIRAM_SPEED_200M=y diff --git a/components/sdmmc/sdmmc_cmd.c b/components/sdmmc/sdmmc_cmd.c index 6f2c6e8e57..08e5cf3d1c 100644 --- a/components/sdmmc/sdmmc_cmd.c +++ b/components/sdmmc/sdmmc_cmd.c @@ -405,6 +405,9 @@ esp_err_t sdmmc_write_sectors(sdmmc_card_t* card, const void* src, size_t block_size = card->csd.sector_size; esp_dma_mem_info_t dma_mem_info; card->host.get_dma_info(card->host.slot, &dma_mem_info); +#ifdef SOC_SDMMC_PSRAM_DMA_CAPABLE + dma_mem_info.extra_heap_caps |= MALLOC_CAP_SPIRAM; +#endif if (esp_dma_is_buffer_alignment_satisfied(src, block_size * block_count, dma_mem_info)) { err = sdmmc_write_sectors_dma(card, src, start_block, block_count, block_size * block_count); } else { @@ -413,6 +416,9 @@ esp_err_t sdmmc_write_sectors(sdmmc_card_t* card, const void* src, // DMA-capable buffer. void *tmp_buf = NULL; size_t actual_size = 0; + // Clear the SPIRAM flag. We don't want to force the allocation into SPIRAM, the allocator + // will decide based on the buffer size and memory availability. + dma_mem_info.extra_heap_caps &= ~MALLOC_CAP_SPIRAM; err = esp_dma_capable_malloc(block_size, &dma_mem_info, &tmp_buf, &actual_size); if (err != ESP_OK) { return err; diff --git a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in index 3d5d61b8aa..d9371a5b47 100644 --- a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in @@ -1011,6 +1011,10 @@ config SOC_SDMMC_IO_POWER_EXTERNAL bool default y +config SOC_SDMMC_PSRAM_DMA_CAPABLE + bool + default y + config SOC_SHA_DMA_MAX_BUFFER_SIZE int default 3968 diff --git a/components/soc/esp32p4/include/soc/soc_caps.h b/components/soc/esp32p4/include/soc/soc_caps.h index 81371dbc3c..164a275a81 100644 --- a/components/soc/esp32p4/include/soc/soc_caps.h +++ b/components/soc/esp32p4/include/soc/soc_caps.h @@ -407,6 +407,7 @@ /* Supported host clock delay phase number */ #define SOC_SDMMC_DELAY_PHASE_NUM 4 #define SOC_SDMMC_IO_POWER_EXTERNAL 1 ///< SDMMC IO power controlled by external power supply +#define SOC_SDMMC_PSRAM_DMA_CAPABLE 1 ///< SDMMC peripheral can do DMA transfer to/from PSRAM // TODO: IDF-5353 (Copy from esp32c3, need check) /*--------------------------- SHA CAPS ---------------------------------------*/ diff --git a/tools/test_apps/storage/sdmmc_console/main/CMakeLists.txt b/tools/test_apps/storage/sdmmc_console/main/CMakeLists.txt index af1ef8ab2c..ccd58e98c8 100644 --- a/tools/test_apps/storage/sdmmc_console/main/CMakeLists.txt +++ b/tools/test_apps/storage/sdmmc_console/main/CMakeLists.txt @@ -7,6 +7,8 @@ set(requires sdmmc_test_boards sdmmc_tests sdspi_tests # various console commands cmd_unity cmd_system cmd_sdmmc + # for PSRAM-related tests + esp_psram ) idf_component_register(SRCS sdmmc_console_main.c diff --git a/tools/test_apps/storage/sdmmc_console/sdkconfig.defaults.esp32p4 b/tools/test_apps/storage/sdmmc_console/sdkconfig.defaults.esp32p4 new file mode 100644 index 0000000000..7b8ca4566c --- /dev/null +++ b/tools/test_apps/storage/sdmmc_console/sdkconfig.defaults.esp32p4 @@ -0,0 +1,5 @@ +CONFIG_SDMMC_BOARD_ESP32P4_EV_BOARD=y + +CONFIG_SPIRAM=y +CONFIG_IDF_EXPERIMENTAL_FEATURES=y +CONFIG_SPIRAM_SPEED_200M=y