mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
Merge branch 'feature/sdmmc_p4_psram' into 'master'
feat(sdmmc): add support for PSRAM DMA Closes IDF-9662 See merge request espressif/esp-idf!30044
This commit is contained in:
commit
8a66e059e9
@ -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;
|
||||
}
|
||||
|
@ -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 <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/time.h>
|
||||
#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);
|
||||
}
|
||||
|
@ -5,6 +5,8 @@ set(priv_requires
|
||||
sdmmc_tests
|
||||
# general
|
||||
unity
|
||||
# for PSRAM tests
|
||||
esp_psram
|
||||
)
|
||||
|
||||
idf_component_register(SRCS ${srcs}
|
||||
|
@ -0,0 +1,5 @@
|
||||
CONFIG_SDMMC_BOARD_ESP32P4_EV_BOARD=y
|
||||
|
||||
CONFIG_SPIRAM=y
|
||||
CONFIG_IDF_EXPERIMENTAL_FEATURES=y
|
||||
CONFIG_SPIRAM_SPEED_200M=y
|
@ -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;
|
||||
|
@ -1027,6 +1027,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
|
||||
|
@ -415,6 +415,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 ---------------------------------------*/
|
||||
|
@ -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
|
||||
|
@ -0,0 +1,5 @@
|
||||
CONFIG_SDMMC_BOARD_ESP32P4_EV_BOARD=y
|
||||
|
||||
CONFIG_SPIRAM=y
|
||||
CONFIG_IDF_EXPERIMENTAL_FEATURES=y
|
||||
CONFIG_SPIRAM_SPEED_200M=y
|
Loading…
Reference in New Issue
Block a user