diff --git a/components/esp_driver_spi/src/gpspi/spi_common.c b/components/esp_driver_spi/src/gpspi/spi_common.c index 7d5b139a0c..3e2ba4895c 100644 --- a/components/esp_driver_spi/src/gpspi/spi_common.c +++ b/components/esp_driver_spi/src/gpspi/spi_common.c @@ -243,12 +243,13 @@ static esp_err_t alloc_dma_chan(spi_host_device_t host_id, spi_dma_chan_t dma_ch gdma_connect(dma_ctx->rx_dma_chan, GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_SPI, 3)); } #endif - gdma_transfer_ability_t ability = { - .psram_trans_align = 0, // fall back to use the same size of the psram data cache line size - .sram_trans_align = 4, + // TODO: add support to allow SPI transfer PSRAM buffer + gdma_transfer_config_t trans_cfg = { + .max_data_burst_size = 16, + .access_ext_mem = false, }; - ESP_RETURN_ON_ERROR(gdma_set_transfer_ability(dma_ctx->tx_dma_chan, &ability), SPI_TAG, "set gdma tx transfer ability failed"); - ESP_RETURN_ON_ERROR(gdma_set_transfer_ability(dma_ctx->rx_dma_chan, &ability), SPI_TAG, "set gdma rx transfer ability failed"); + ESP_RETURN_ON_ERROR(gdma_config_transfer(dma_ctx->tx_dma_chan, &trans_cfg), SPI_TAG, "config gdma tx transfer failed"); + ESP_RETURN_ON_ERROR(gdma_config_transfer(dma_ctx->rx_dma_chan, &trans_cfg), SPI_TAG, "config gdma rx transfer failed"); } return ret; } diff --git a/components/esp_hw_support/CMakeLists.txt b/components/esp_hw_support/CMakeLists.txt index db2c68dadd..e1b8875dc5 100644 --- a/components/esp_hw_support/CMakeLists.txt +++ b/components/esp_hw_support/CMakeLists.txt @@ -68,13 +68,16 @@ if(NOT BOOTLOADER_BUILD) endif() if(CONFIG_SOC_GDMA_SUPPORTED) - list(APPEND srcs "dma/gdma.c") + list(APPEND srcs "dma/gdma.c" "deprecated/gdma_legacy.c") if(CONFIG_SOC_GDMA_SUPPORT_SLEEP_RETENTION) list(APPEND srcs "dma/gdma_sleep_retention.c") endif() if(CONFIG_SOC_GDMA_SUPPORT_ETM) list(APPEND srcs "dma/gdma_etm.c") endif() + if(CONFIG_SOC_GDMA_SUPPORT_CRC) + list(APPEND srcs "dma/gdma_crc.c") + endif() endif() if(CONFIG_SOC_GP_LDO_SUPPORTED) diff --git a/components/esp_hw_support/deprecated/gdma_legacy.c b/components/esp_hw_support/deprecated/gdma_legacy.c new file mode 100644 index 0000000000..f25dd2c8ab --- /dev/null +++ b/components/esp_hw_support/deprecated/gdma_legacy.c @@ -0,0 +1,62 @@ +/* + * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include "sdkconfig.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "esp_log.h" +#include "esp_check.h" +#include "../dma/gdma_priv.h" +#include "hal/cache_hal.h" +#include "hal/cache_ll.h" + +static const char *TAG = "gdma"; + +esp_err_t gdma_set_transfer_ability(gdma_channel_handle_t dma_chan, const gdma_transfer_ability_t *ability) +{ + ESP_RETURN_ON_FALSE(dma_chan && ability, ESP_ERR_INVALID_ARG, TAG, "invalid argument"); + gdma_pair_t *pair = dma_chan->pair; + gdma_group_t *group = pair->group; + gdma_hal_context_t *hal = &group->hal; + + size_t int_mem_alignment = ability->sram_trans_align; + size_t ext_mem_alignment = ability->psram_trans_align; + // alignment should be 2^n + ESP_RETURN_ON_FALSE((int_mem_alignment & (int_mem_alignment - 1)) == 0, ESP_ERR_INVALID_ARG, + TAG, "invalid sram alignment: %zu", int_mem_alignment); + + uint32_t ext_mem_cache_line_size = cache_hal_get_cache_line_size(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_DATA); + if (ext_mem_alignment == 0) { + // fall back to use the same size of the psram data cache line size + ext_mem_alignment = ext_mem_cache_line_size; + } + if ((ext_mem_cache_line_size > 0) && (ext_mem_alignment > ext_mem_cache_line_size)) { + ESP_RETURN_ON_FALSE(((ext_mem_alignment % ext_mem_cache_line_size) == 0), ESP_ERR_INVALID_ARG, + TAG, "ext_mem_alignment(%d) should be multiple of the ext_mem_cache_line_size(%"PRIu32")", + ext_mem_alignment, ext_mem_cache_line_size); + } + + // if the DMA can't access the PSRAM, this HAL function is no-op + gdma_hal_set_burst_size(hal, pair->pair_id, dma_chan->direction, ext_mem_alignment); + + // TX channel can always enable burst mode, no matter data alignment + bool en_burst = true; + if (dma_chan->direction == GDMA_CHANNEL_DIRECTION_RX) { + // RX channel burst mode depends on specific data alignment + en_burst = int_mem_alignment >= 4; + } + gdma_hal_enable_burst(hal, pair->pair_id, dma_chan->direction, en_burst, en_burst); + + dma_chan->int_mem_alignment = int_mem_alignment; + dma_chan->ext_mem_alignment = ext_mem_alignment; + ESP_LOGD(TAG, "%s channel (%d,%d), (%u:%u) bytes aligned, burst %s", dma_chan->direction == GDMA_CHANNEL_DIRECTION_TX ? "tx" : "rx", + group->group_id, pair->pair_id, int_mem_alignment, ext_mem_alignment, en_burst ? "enabled" : "disabled"); + + return ESP_OK; +} diff --git a/components/esp_hw_support/dma/async_memcpy_cp_dma.c b/components/esp_hw_support/dma/async_memcpy_cp_dma.c index 975bb92c36..e86bf10a18 100644 --- a/components/esp_hw_support/dma/async_memcpy_cp_dma.c +++ b/components/esp_hw_support/dma/async_memcpy_cp_dma.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -48,7 +48,6 @@ typedef struct async_memcpy_transaction_t { /// @note - Number of transaction objects are determined by the backlog parameter typedef struct { async_memcpy_context_t parent; // Parent IO interface - size_t sram_trans_align; // DMA transfer alignment (both in size and address) for SRAM memory size_t max_single_dma_buffer; // max DMA buffer size by a single descriptor cp_dma_hal_context_t hal; // CPDMA hal intr_handle_t intr; // CPDMA interrupt handle @@ -90,7 +89,7 @@ esp_err_t esp_async_memcpy_install_cpdma(const async_memcpy_config_t *config, as uint32_t trans_queue_len = config->backlog ? config->backlog : DEFAULT_TRANSACTION_QUEUE_LENGTH; // allocate memory for transaction pool, aligned to 4 because the trans->eof_node requires that alignment mcp_dma->transaction_pool = heap_caps_aligned_calloc(4, trans_queue_len, sizeof(async_memcpy_transaction_t), - MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT | MALLOC_CAP_DMA); + MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT | MALLOC_CAP_DMA); ESP_GOTO_ON_FALSE(mcp_dma->transaction_pool, ESP_ERR_NO_MEM, err, TAG, "no mem for transaction pool"); // Init hal context @@ -111,8 +110,7 @@ esp_err_t esp_async_memcpy_install_cpdma(const async_memcpy_config_t *config, as // initialize other members portMUX_INITIALIZE(&mcp_dma->spin_lock); atomic_init(&mcp_dma->fsm, MCP_FSM_IDLE); - mcp_dma->sram_trans_align = config->sram_trans_align; - size_t trans_align = config->sram_trans_align; + size_t trans_align = config->dma_burst_size; mcp_dma->max_single_dma_buffer = trans_align ? ALIGN_DOWN(DMA_DESCRIPTOR_BUFFER_MAX_SIZE, trans_align) : DMA_DESCRIPTOR_BUFFER_MAX_SIZE; mcp_dma->parent.del = mcp_cpdma_del; mcp_dma->parent.memcpy = mcp_cpdma_memcpy; @@ -240,12 +238,6 @@ static esp_err_t mcp_cpdma_memcpy(async_memcpy_context_t *ctx, void *dst, void * esp_err_t ret = ESP_OK; async_memcpy_cpdma_context_t *mcp_dma = __containerof(ctx, async_memcpy_cpdma_context_t, parent); ESP_RETURN_ON_FALSE(esp_ptr_internal(src) && esp_ptr_internal(dst), ESP_ERR_INVALID_ARG, TAG, "CP_DMA can only access SRAM"); - // alignment check - if (mcp_dma->sram_trans_align) { - ESP_RETURN_ON_FALSE((((intptr_t)dst & (mcp_dma->sram_trans_align - 1)) == 0), ESP_ERR_INVALID_ARG, TAG, "buffer address not aligned: %p -> %p", src, dst); - ESP_RETURN_ON_FALSE(((n & (mcp_dma->sram_trans_align - 1)) == 0), ESP_ERR_INVALID_ARG, TAG, - "copy size should align to %d bytes", mcp_dma->sram_trans_align); - } async_memcpy_transaction_t *trans = NULL; // pick one transaction node from idle queue trans = try_pop_trans_from_idle_queue(mcp_dma); @@ -257,12 +249,12 @@ static esp_err_t mcp_cpdma_memcpy(async_memcpy_context_t *ctx, void *dst, void * uint32_t num_desc_per_path = (n + max_single_dma_buffer - 1) / max_single_dma_buffer; // allocate DMA descriptors, descriptors need a strict alignment trans->tx_desc_link = heap_caps_aligned_calloc(4, num_desc_per_path, sizeof(dma_descriptor_align4_t), - MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT | MALLOC_CAP_DMA); + MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT | MALLOC_CAP_DMA); ESP_GOTO_ON_FALSE(trans->tx_desc_link, ESP_ERR_NO_MEM, err, TAG, "no mem for DMA descriptors"); // don't have to allocate the EOF descriptor, we will use trans->eof_node as the RX EOF descriptor if (num_desc_per_path > 1) { trans->rx_desc_link = heap_caps_aligned_calloc(4, num_desc_per_path - 1, sizeof(dma_descriptor_align4_t), - MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT | MALLOC_CAP_DMA); + MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT | MALLOC_CAP_DMA); ESP_GOTO_ON_FALSE(trans->rx_desc_link, ESP_ERR_NO_MEM, err, TAG, "no mem for DMA descriptors"); } else { // small copy buffer, use the trans->eof_node is sufficient diff --git a/components/esp_hw_support/dma/async_memcpy_gdma.c b/components/esp_hw_support/dma/async_memcpy_gdma.c index 8b8fa19930..7282f946fa 100644 --- a/components/esp_hw_support/dma/async_memcpy_gdma.c +++ b/components/esp_hw_support/dma/async_memcpy_gdma.c @@ -69,8 +69,10 @@ typedef struct async_memcpy_transaction_t { typedef struct { async_memcpy_context_t parent; // Parent IO interface size_t descriptor_align; // DMA descriptor alignment - size_t sram_trans_align; // DMA buffer alignment (both in size and address) for SRAM memory - size_t psram_trans_align; // DMA buffer alignment (both in size and address) for PSRAM memory + size_t rx_int_mem_alignment; // DMA buffer alignment (both in size and address) for internal RX memory + size_t rx_ext_mem_alignment; // DMA buffer alignment (both in size and address) for external RX memory + size_t tx_int_mem_alignment; // DMA buffer alignment (both in size and address) for internal TX memory + size_t tx_ext_mem_alignment; // DMA buffer alignment (both in size and address) for external TX memory size_t max_single_dma_buffer; // max DMA buffer size by a single descriptor int gdma_bus_id; // GDMA bus id (AHB, AXI, etc.) gdma_channel_handle_t tx_channel; // GDMA TX channel handle @@ -146,12 +148,12 @@ static esp_err_t esp_async_memcpy_install_gdma_template(const async_memcpy_confi ESP_GOTO_ON_ERROR(gdma_connect(mcp_gdma->rx_channel, m2m_trigger), err, TAG, "GDMA rx connect failed"); ESP_GOTO_ON_ERROR(gdma_connect(mcp_gdma->tx_channel, m2m_trigger), err, TAG, "GDMA tx connect failed"); - gdma_transfer_ability_t transfer_ability = { - .sram_trans_align = config->sram_trans_align, - .psram_trans_align = config->psram_trans_align, + gdma_transfer_config_t transfer_cfg = { + .max_data_burst_size = config->dma_burst_size ? config->dma_burst_size : 16, + .access_ext_mem = true, // allow to do memory copy from/to external memory }; - ESP_GOTO_ON_ERROR(gdma_set_transfer_ability(mcp_gdma->tx_channel, &transfer_ability), err, TAG, "set tx trans ability failed"); - ESP_GOTO_ON_ERROR(gdma_set_transfer_ability(mcp_gdma->rx_channel, &transfer_ability), err, TAG, "set rx trans ability failed"); + ESP_GOTO_ON_ERROR(gdma_config_transfer(mcp_gdma->tx_channel, &transfer_cfg), err, TAG, "config transfer for tx channel failed"); + ESP_GOTO_ON_ERROR(gdma_config_transfer(mcp_gdma->rx_channel, &transfer_cfg), err, TAG, "config transfer for rx channel failed"); // register rx eof callback gdma_rx_event_callbacks_t cbs = { @@ -172,15 +174,13 @@ static esp_err_t esp_async_memcpy_install_gdma_template(const async_memcpy_confi atomic_init(&mcp_gdma->fsm, MCP_FSM_IDLE); mcp_gdma->gdma_bus_id = gdma_bus_id; - uint32_t psram_cache_line_size = cache_hal_get_cache_line_size(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_DATA); - uint32_t sram_cache_line_size = cache_hal_get_cache_line_size(CACHE_LL_LEVEL_INT_MEM, CACHE_TYPE_DATA); - // if the psram_trans_align is configured to zero, we should fall back to use the data cache line size - size_t psram_trans_align = MAX(psram_cache_line_size, config->psram_trans_align); - size_t sram_trans_align = MAX(sram_cache_line_size, config->sram_trans_align); - size_t trans_align = MAX(sram_trans_align, psram_trans_align); - mcp_gdma->max_single_dma_buffer = ALIGN_DOWN(DMA_DESCRIPTOR_BUFFER_MAX_SIZE, trans_align); - mcp_gdma->psram_trans_align = psram_trans_align; - mcp_gdma->sram_trans_align = sram_trans_align; + // get the buffer alignment required by the GDMA channel + gdma_get_alignment_constraints(mcp_gdma->rx_channel, &mcp_gdma->rx_int_mem_alignment, &mcp_gdma->rx_ext_mem_alignment); + gdma_get_alignment_constraints(mcp_gdma->tx_channel, &mcp_gdma->tx_int_mem_alignment, &mcp_gdma->tx_ext_mem_alignment); + + size_t buf_align = MAX(MAX(mcp_gdma->rx_int_mem_alignment, mcp_gdma->rx_ext_mem_alignment), + MAX(mcp_gdma->tx_int_mem_alignment, mcp_gdma->tx_ext_mem_alignment)); + mcp_gdma->max_single_dma_buffer = ALIGN_DOWN(DMA_DESCRIPTOR_BUFFER_MAX_SIZE, buf_align); mcp_gdma->parent.del = mcp_gdma_del; mcp_gdma->parent.memcpy = mcp_gdma_memcpy; #if SOC_GDMA_SUPPORT_ETM @@ -335,29 +335,21 @@ static async_memcpy_transaction_t *try_pop_trans_from_idle_queue(async_memcpy_gd static bool check_buffer_alignment(async_memcpy_gdma_context_t *mcp_gdma, void *src, void *dst, size_t n) { bool valid = true; - uint32_t psram_align_mask = 0; - uint32_t sram_align_mask = 0; - if (mcp_gdma->psram_trans_align) { - psram_align_mask = mcp_gdma->psram_trans_align - 1; - } - if (mcp_gdma->sram_trans_align) { - sram_align_mask = mcp_gdma->sram_trans_align - 1; - } if (esp_ptr_external_ram(dst)) { - valid = valid && (((uint32_t)dst & psram_align_mask) == 0); - valid = valid && ((n & psram_align_mask) == 0); + valid = valid && (((uint32_t)dst & (mcp_gdma->rx_ext_mem_alignment - 1)) == 0); + valid = valid && ((n & (mcp_gdma->rx_ext_mem_alignment - 1)) == 0); } else { - valid = valid && (((uint32_t)dst & sram_align_mask) == 0); - valid = valid && ((n & sram_align_mask) == 0); + valid = valid && (((uint32_t)dst & (mcp_gdma->rx_int_mem_alignment - 1)) == 0); + valid = valid && ((n & (mcp_gdma->rx_int_mem_alignment - 1)) == 0); } if (esp_ptr_external_ram(src)) { - valid = valid && (((uint32_t)src & psram_align_mask) == 0); - valid = valid && ((n & psram_align_mask) == 0); + valid = valid && (((uint32_t)src & (mcp_gdma->tx_ext_mem_alignment - 1)) == 0); + valid = valid && ((n & (mcp_gdma->tx_ext_mem_alignment - 1)) == 0); } else { - valid = valid && (((uint32_t)src & sram_align_mask) == 0); - valid = valid && ((n & sram_align_mask) == 0); + valid = valid && (((uint32_t)src & (mcp_gdma->tx_int_mem_alignment - 1)) == 0); + valid = valid && ((n & (mcp_gdma->tx_int_mem_alignment - 1)) == 0); } return valid; diff --git a/components/esp_hw_support/dma/gdma.c b/components/esp_hw_support/dma/gdma.c index c283a30bd0..d78c5cbf1b 100644 --- a/components/esp_hw_support/dma/gdma.c +++ b/components/esp_hw_support/dma/gdma.c @@ -29,6 +29,7 @@ #include #include #include +#include #include "sdkconfig.h" #if CONFIG_GDMA_ENABLE_DEBUG_LOG // The local log level must be defined before including esp_log.h @@ -42,10 +43,9 @@ #include "esp_log.h" #include "esp_check.h" #include "esp_memory_utils.h" +#include "esp_flash_encrypt.h" #include "esp_private/periph_ctrl.h" #include "gdma_priv.h" -#include "hal/cache_hal.h" -#include "hal/cache_ll.h" #if CONFIG_PM_ENABLE && SOC_PM_SUPPORT_TOP_PD #include "esp_private/gdma_sleep_retention.h" @@ -354,46 +354,68 @@ esp_err_t gdma_get_free_m2m_trig_id_mask(gdma_channel_handle_t dma_chan, uint32_ return ESP_OK; } -esp_err_t gdma_set_transfer_ability(gdma_channel_handle_t dma_chan, const gdma_transfer_ability_t *ability) +esp_err_t gdma_config_transfer(gdma_channel_handle_t dma_chan, const gdma_transfer_config_t *config) { - ESP_RETURN_ON_FALSE(dma_chan && ability, ESP_ERR_INVALID_ARG, TAG, "invalid argument"); + ESP_RETURN_ON_FALSE(dma_chan && config, ESP_ERR_INVALID_ARG, TAG, "invalid argument"); + uint32_t max_data_burst_size = config->max_data_burst_size; + if (max_data_burst_size) { + // burst size must be power of 2 + ESP_RETURN_ON_FALSE((max_data_burst_size & (max_data_burst_size - 1)) == 0, ESP_ERR_INVALID_ARG, + TAG, "invalid max_data_burst_size: %"PRIu32, max_data_burst_size); + } gdma_pair_t *pair = dma_chan->pair; gdma_group_t *group = pair->group; gdma_hal_context_t *hal = &group->hal; + size_t int_mem_alignment = 1; + size_t ext_mem_alignment = 1; - size_t sram_alignment = ability->sram_trans_align; - size_t psram_alignment = ability->psram_trans_align; - // alignment should be 2^n - ESP_RETURN_ON_FALSE((sram_alignment & (sram_alignment - 1)) == 0, ESP_ERR_INVALID_ARG, - TAG, "invalid sram alignment: %zu", sram_alignment); - - uint32_t ext_mem_cache_line_size = cache_hal_get_cache_line_size(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_DATA); - if (psram_alignment == 0) { - // fall back to use the same size of the psram data cache line size - psram_alignment = ext_mem_cache_line_size; - } - if (psram_alignment > ext_mem_cache_line_size) { - ESP_RETURN_ON_FALSE(((psram_alignment % ext_mem_cache_line_size) == 0), ESP_ERR_INVALID_ARG, - TAG, "psram_alignment(%d) should be multiple of the ext_mem_cache_line_size(%"PRIu32")", - psram_alignment, ext_mem_cache_line_size); + // always enable descriptor burst as the descriptor is always word aligned and is in the internal SRAM + bool en_desc_burst = true; + bool en_data_burst = max_data_burst_size > 0; + gdma_hal_enable_burst(hal, pair->pair_id, dma_chan->direction, en_data_burst, en_desc_burst); + if (en_data_burst) { + gdma_hal_set_burst_size(hal, pair->pair_id, dma_chan->direction, max_data_burst_size); } - // if the DMA can't access the PSRAM, this HAL function is no-op - gdma_hal_set_ext_mem_align(hal, pair->pair_id, dma_chan->direction, psram_alignment); - - // TX channel can always enable burst mode, no matter data alignment - bool en_burst = true; - if (dma_chan->direction == GDMA_CHANNEL_DIRECTION_RX) { - // RX channel burst mode depends on specific data alignment - en_burst = sram_alignment >= 4; +#if GDMA_LL_AHB_RX_BURST_NEEDS_ALIGNMENT + if (en_data_burst && dma_chan->direction == GDMA_CHANNEL_DIRECTION_RX) { + int_mem_alignment = MAX(int_mem_alignment, 4); + ext_mem_alignment = MAX(ext_mem_alignment, max_data_burst_size); } - gdma_hal_enable_burst(hal, pair->pair_id, dma_chan->direction, en_burst, en_burst); +#endif - dma_chan->sram_alignment = sram_alignment; - dma_chan->psram_alignment = psram_alignment; - ESP_LOGD(TAG, "%s channel (%d,%d), (%u:%u) bytes aligned, burst %s", dma_chan->direction == GDMA_CHANNEL_DIRECTION_TX ? "tx" : "rx", - group->group_id, pair->pair_id, sram_alignment, psram_alignment, en_burst ? "enabled" : "disabled"); + // if MSPI encryption is enabled, and DMA wants to read/write external memory + if (esp_flash_encryption_enabled()) { + gdma_hal_enable_access_encrypt_mem(hal, pair->pair_id, dma_chan->direction, config->access_ext_mem); + // when DMA access the encrypted memory, extra alignment is needed, for both internal and external memory + if (config->access_ext_mem) { + ext_mem_alignment = MAX(ext_mem_alignment, GDMA_ACCESS_ENCRYPTION_MEM_ALIGNMENT); + int_mem_alignment = MAX(int_mem_alignment, GDMA_ACCESS_ENCRYPTION_MEM_ALIGNMENT); + } + } else { + gdma_hal_enable_access_encrypt_mem(hal, pair->pair_id, dma_chan->direction, false); + } + // if the channel is not allowed to access external memory, set a super big (meaningless) alignment value + // so when the upper layer checks the alignment with an external buffer, the check should fail + if (!config->access_ext_mem) { + ext_mem_alignment = BIT(31); + } + + dma_chan->int_mem_alignment = int_mem_alignment; + dma_chan->ext_mem_alignment = ext_mem_alignment; + return ESP_OK; +} + +esp_err_t gdma_get_alignment_constraints(gdma_channel_handle_t dma_chan, size_t *int_mem_alignment, size_t *ext_mem_alignment) +{ + ESP_RETURN_ON_FALSE(dma_chan, ESP_ERR_INVALID_ARG, TAG, "invalid argument"); + if (int_mem_alignment) { + *int_mem_alignment = dma_chan->int_mem_alignment; + } + if (ext_mem_alignment) { + *ext_mem_alignment = dma_chan->ext_mem_alignment; + } return ESP_OK; } @@ -421,57 +443,6 @@ esp_err_t gdma_set_priority(gdma_channel_handle_t dma_chan, uint32_t priority) return ESP_OK; } -#if SOC_GDMA_SUPPORT_CRC -esp_err_t gdma_config_crc_calculator(gdma_channel_handle_t dma_chan, const gdma_crc_calculator_config_t *config) -{ - ESP_RETURN_ON_FALSE(dma_chan && config, ESP_ERR_INVALID_ARG, TAG, "invalid argument"); - gdma_pair_t *pair = dma_chan->pair; - gdma_group_t *group = pair->group; - gdma_hal_context_t *hal = &group->hal; - switch (group->bus_id) { -#if SOC_AHB_GDMA_SUPPORTED - case SOC_GDMA_BUS_AHB: - ESP_RETURN_ON_FALSE(config->crc_bit_width <= GDMA_LL_AHB_MAX_CRC_BIT_WIDTH, ESP_ERR_INVALID_ARG, TAG, "invalid crc bit width"); - break; -#endif // SOC_AHB_GDMA_SUPPORTED -#if SOC_AXI_GDMA_SUPPORTED - case SOC_GDMA_BUS_AXI: - ESP_RETURN_ON_FALSE(config->crc_bit_width <= GDMA_LL_AXI_MAX_CRC_BIT_WIDTH, ESP_ERR_INVALID_ARG, TAG, "invalid crc bit width"); - break; -#endif // SOC_AXI_GDMA_SUPPORTED - default: - ESP_LOGE(TAG, "invalid bus id: %d", group->bus_id); - return ESP_ERR_INVALID_ARG; - } - - // clear the previous CRC result - gdma_hal_clear_crc(hal, pair->pair_id, dma_chan->direction); - - // set polynomial and initial value - gdma_hal_crc_config_t hal_config = { - .crc_bit_width = config->crc_bit_width, - .poly_hex = config->poly_hex, - .init_value = config->init_value, - .reverse_data_mask = config->reverse_data_mask, - }; - gdma_hal_set_crc_poly(hal, pair->pair_id, dma_chan->direction, &hal_config); - - return ESP_OK; -} - -esp_err_t gdma_crc_get_result(gdma_channel_handle_t dma_chan, uint32_t *result) -{ - ESP_RETURN_ON_FALSE(dma_chan && result, ESP_ERR_INVALID_ARG, TAG, "invalid argument"); - gdma_pair_t *pair = dma_chan->pair; - gdma_group_t *group = pair->group; - gdma_hal_context_t *hal = &group->hal; - - *result = gdma_hal_get_crc_result(hal, pair->pair_id, dma_chan->direction); - - return ESP_OK; -} -#endif // SOC_GDMA_SUPPORT_CRC - esp_err_t gdma_register_tx_event_callbacks(gdma_channel_handle_t dma_chan, gdma_tx_event_callbacks_t *cbs, void *user_data) { ESP_RETURN_ON_FALSE(dma_chan && cbs && dma_chan->direction == GDMA_CHANNEL_DIRECTION_TX, ESP_ERR_INVALID_ARG, TAG, "invalid argument"); diff --git a/components/esp_hw_support/dma/gdma_crc.c b/components/esp_hw_support/dma/gdma_crc.c new file mode 100644 index 0000000000..da7425d39d --- /dev/null +++ b/components/esp_hw_support/dma/gdma_crc.c @@ -0,0 +1,74 @@ +/* + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include "sdkconfig.h" +#if CONFIG_GDMA_ENABLE_DEBUG_LOG +// The local log level must be defined before including esp_log.h +// Set the maximum log level for this source file +#define LOG_LOCAL_LEVEL ESP_LOG_DEBUG +#endif +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "soc/soc_caps.h" +#include "soc/periph_defs.h" +#include "esp_log.h" +#include "esp_check.h" +#include "gdma_priv.h" + +static const char *TAG = "gdma"; + +esp_err_t gdma_config_crc_calculator(gdma_channel_handle_t dma_chan, const gdma_crc_calculator_config_t *config) +{ + ESP_RETURN_ON_FALSE(dma_chan && config, ESP_ERR_INVALID_ARG, TAG, "invalid argument"); + gdma_pair_t *pair = dma_chan->pair; + gdma_group_t *group = pair->group; + gdma_hal_context_t *hal = &group->hal; + switch (group->bus_id) { +#if SOC_AHB_GDMA_SUPPORTED + case SOC_GDMA_BUS_AHB: + ESP_RETURN_ON_FALSE(config->crc_bit_width <= GDMA_LL_AHB_MAX_CRC_BIT_WIDTH, ESP_ERR_INVALID_ARG, TAG, "invalid crc bit width"); + break; +#endif // SOC_AHB_GDMA_SUPPORTED +#if SOC_AXI_GDMA_SUPPORTED + case SOC_GDMA_BUS_AXI: + ESP_RETURN_ON_FALSE(config->crc_bit_width <= GDMA_LL_AXI_MAX_CRC_BIT_WIDTH, ESP_ERR_INVALID_ARG, TAG, "invalid crc bit width"); + break; +#endif // SOC_AXI_GDMA_SUPPORTED + default: + ESP_LOGE(TAG, "invalid bus id: %d", group->bus_id); + return ESP_ERR_INVALID_ARG; + } + + // clear the previous CRC result + gdma_hal_clear_crc(hal, pair->pair_id, dma_chan->direction); + + // set polynomial and initial value + gdma_hal_crc_config_t hal_config = { + .crc_bit_width = config->crc_bit_width, + .poly_hex = config->poly_hex, + .init_value = config->init_value, + .reverse_data_mask = config->reverse_data_mask, + }; + gdma_hal_set_crc_poly(hal, pair->pair_id, dma_chan->direction, &hal_config); + + return ESP_OK; +} + +esp_err_t gdma_crc_get_result(gdma_channel_handle_t dma_chan, uint32_t *result) +{ + ESP_RETURN_ON_FALSE(dma_chan && result, ESP_ERR_INVALID_ARG, TAG, "invalid argument"); + gdma_pair_t *pair = dma_chan->pair; + gdma_group_t *group = pair->group; + gdma_hal_context_t *hal = &group->hal; + + *result = gdma_hal_get_crc_result(hal, pair->pair_id, dma_chan->direction); + + return ESP_OK; +} diff --git a/components/esp_hw_support/dma/gdma_priv.h b/components/esp_hw_support/dma/gdma_priv.h index 202f3ec949..600397be02 100644 --- a/components/esp_hw_support/dma/gdma_priv.h +++ b/components/esp_hw_support/dma/gdma_priv.h @@ -32,6 +32,8 @@ #define GDMA_INTR_ALLOC_FLAGS ESP_INTR_FLAG_INTRDISABLED #endif +#define GDMA_ACCESS_ENCRYPTION_MEM_ALIGNMENT 16 /*!< The alignment of the memory and size when DMA accesses the encryption memory */ + #ifdef __cplusplus extern "C" { #endif @@ -67,8 +69,8 @@ struct gdma_channel_t { portMUX_TYPE spinlock; // channel level spinlock gdma_channel_direction_t direction; // channel direction int periph_id; // Peripheral instance ID, indicates which peripheral is connected to this GDMA channel - size_t sram_alignment; // alignment for memory in SRAM - size_t psram_alignment; // alignment for memory in PSRAM + size_t int_mem_alignment; // alignment for memory in internal memory + size_t ext_mem_alignment; // alignment for memory in external memory esp_err_t (*del)(gdma_channel_t *channel); // channel deletion function, it's polymorphic, see `gdma_del_tx_channel` or `gdma_del_rx_channel` struct { uint32_t start_stop_by_etm: 1; // whether the channel is started/stopped by ETM diff --git a/components/esp_hw_support/dma/include/esp_private/gdma.h b/components/esp_hw_support/dma/include/esp_private/gdma.h index 2d61d531be..cd58cd285b 100644 --- a/components/esp_hw_support/dma/include/esp_private/gdma.h +++ b/components/esp_hw_support/dma/include/esp_private/gdma.h @@ -4,9 +4,6 @@ * SPDX-License-Identifier: Apache-2.0 */ -// DO NOT USE THESE APIS IN ANY APPLICATIONS -// GDMA driver is not public for end users, but for ESP-IDF developers. - #pragma once #include @@ -37,19 +34,6 @@ typedef struct { } flags; } gdma_channel_alloc_config_t; -/** - * @brief GDMA transfer ability - * - * @note The alignment set in this structure is **not** a guarantee that gdma driver will take care of the nonalignment cases. - * Actually the GDMA driver has no knowledge about the DMA buffer (address and size) used by upper layer. - * So it's the responsibility of the **upper layer** to take care of the buffer address and size. - * - */ -typedef struct { - size_t sram_trans_align; /*!< DMA transfer alignment for memory in SRAM, in bytes. The driver enables/disables burst mode based on this value. 0 means no alignment is required */ - size_t psram_trans_align; /*!< DMA transfer alignment for memory in PSRAM, in bytes. The driver sets proper burst block size based on the alignment value. 0 means no alignment is required */ -} gdma_transfer_ability_t; - /** * @brief Type of GDMA event data */ @@ -199,16 +183,48 @@ esp_err_t gdma_connect(gdma_channel_handle_t dma_chan, gdma_trigger_t trig_perip esp_err_t gdma_disconnect(gdma_channel_handle_t dma_chan); /** - * @brief Set DMA channel transfer ability + * @brief Channel transfer configurations + */ +typedef struct { + uint32_t max_data_burst_size; /*!< Set the max burst size when DMA read/write the data buffer. + Set to 0 means to disable the data burst. + Other value must be power of 2, e.g., 4/8/16/32/64 */ + bool access_ext_mem; /*!< Set this if the DMA transfer will access external memory */ +} gdma_transfer_config_t; + +/** + * @brief Configure transfer parameters for a DMA channel + * + * @note It's highly recommended to enable the burst mode and set proper burst size for the DMA channel, + * which can improve the performance in accessing external memory by a lot. + * + * @param[in] chan DMA channel handle, allocated by `gdma_new_channel` + * @param[in] config Transfer configurations + * @return + * - ESP_OK: Configure DMA transfer parameters successfully + * - ESP_ERR_INVALID_ARG: Configure DMA transfer parameters failed because of invalid argument + * - ESP_FAIL: Configure DMA transfer parameters failed because of other error + */ +esp_err_t gdma_config_transfer(gdma_channel_handle_t dma_chan, const gdma_transfer_config_t *config); + +/** + * @brief Get the alignment constraints for internal and external memory + * + * @note You should call this function after `gdma_config_transfer`, the later one can + * adjust the alignment constraints based on various conditions, e.g. burst size, memory encryption, etc. + * @note You can use returned alignment value to validate if a DMA buffer provided by the upper layer meets the constraints. + * @note The returned alignment doesn't take the cache line size into account, if you want to do aligned memory allocation, + * you should align the buffer size to the cache line size by yourself if the DMA buffer is behind a cache. * * @param[in] dma_chan GDMA channel handle, allocated by `gdma_new_channel` - * @param[in] ability Transfer ability, e.g. alignment + * @param[out] int_mem_alignment Internal memory alignment + * @param[out] ext_mem_alignment External memory alignment * @return - * - ESP_OK: Set DMA channel transfer ability successfully - * - ESP_ERR_INVALID_ARG: Set DMA channel transfer ability failed because of invalid argument - * - ESP_FAIL: Set DMA channel transfer ability failed because of other error + * - ESP_OK: Get alignment constraints successfully + * - ESP_ERR_INVALID_ARG: Get alignment constraints failed because of invalid argument + * - ESP_FAIL: Get alignment constraints failed because of other error */ -esp_err_t gdma_set_transfer_ability(gdma_channel_handle_t dma_chan, const gdma_transfer_ability_t *ability); +esp_err_t gdma_get_alignment_constraints(gdma_channel_handle_t dma_chan, size_t *int_mem_alignment, size_t *ext_mem_alignment); /** * @brief Apply channel strategy for GDMA channel @@ -457,6 +473,36 @@ esp_err_t gdma_config_crc_calculator(gdma_channel_handle_t dma_chan, const gdma_ esp_err_t gdma_crc_get_result(gdma_channel_handle_t dma_chan, uint32_t *result); #endif // SOC_GDMA_SUPPORT_CRC +/**************************************************************************************** + * Deprecated APIs + ****************************************************************************************/ + +/** + * @brief GDMA transfer ability + * + * @note The alignment set in this structure is **not** a guarantee that gdma driver will take care of the nonalignment cases. + * Actually the GDMA driver has no knowledge about the DMA buffer (address and size) used by upper layer. + * So it's the responsibility of the **upper layer** to take care of the buffer address and size. + * + */ +typedef struct { + size_t sram_trans_align; /*!< DMA transfer alignment for memory in SRAM, in bytes. The driver enables/disables burst mode based on this value. 0 means no alignment is required */ + size_t psram_trans_align; /*!< DMA transfer alignment for memory in PSRAM, in bytes. The driver sets proper burst block size based on the alignment value. 0 means no alignment is required */ +} gdma_transfer_ability_t; + +/** + * @brief Set DMA channel transfer ability + * + * @param[in] dma_chan GDMA channel handle, allocated by `gdma_new_channel` + * @param[in] ability Transfer ability, e.g. alignment + * @return + * - ESP_OK: Set DMA channel transfer ability successfully + * - ESP_ERR_INVALID_ARG: Set DMA channel transfer ability failed because of invalid argument + * - ESP_FAIL: Set DMA channel transfer ability failed because of other error + */ +esp_err_t gdma_set_transfer_ability(gdma_channel_handle_t dma_chan, const gdma_transfer_ability_t *ability) +__attribute__((deprecated("please use gdma_config_transfer instead"))); + #ifdef __cplusplus } #endif diff --git a/components/esp_hw_support/include/esp_async_memcpy.h b/components/esp_hw_support/include/esp_async_memcpy.h index 033bb9ed91..1b91b84093 100644 --- a/components/esp_hw_support/include/esp_async_memcpy.h +++ b/components/esp_hw_support/include/esp_async_memcpy.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -51,8 +51,11 @@ typedef bool (*async_memcpy_isr_cb_t)(async_memcpy_handle_t mcp_hdl, async_memcp */ typedef struct { uint32_t backlog; /*!< Maximum number of transactions that can be prepared in the background */ - size_t sram_trans_align; /*!< DMA transfer alignment (both in size and address) for SRAM memory */ - size_t psram_trans_align; /*!< DMA transfer alignment (both in size and address) for PSRAM memory */ + size_t sram_trans_align __attribute__((deprecated)); /*!< DMA transfer alignment (both in size and address) for SRAM memory */ + union { + size_t psram_trans_align; /*!< DMA transfer alignment (both in size and address) for PSRAM memory */ + size_t dma_burst_size; /*!< DMA transfer burst size, in bytes */ + }; uint32_t flags; /*!< Extra flags to control async memcpy feature */ } async_memcpy_config_t; @@ -62,8 +65,7 @@ typedef struct { #define ASYNC_MEMCPY_DEFAULT_CONFIG() \ { \ .backlog = 8, \ - .sram_trans_align = 0, \ - .psram_trans_align = 0, \ + .dma_burst_size = 16, \ .flags = 0, \ } diff --git a/components/esp_hw_support/test_apps/dma/main/test_async_memcpy.c b/components/esp_hw_support/test_apps/dma/main/test_async_memcpy.c index 81939889d0..79423a3205 100644 --- a/components/esp_hw_support/test_apps/dma/main/test_async_memcpy.c +++ b/components/esp_hw_support/test_apps/dma/main/test_async_memcpy.c @@ -302,8 +302,7 @@ static void memcpy_performance_test(uint32_t buffer_size) async_memcpy_config_t config = ASYNC_MEMCPY_DEFAULT_CONFIG(); config.backlog = (buffer_size / DMA_DESCRIPTOR_BUFFER_MAX_SIZE + 1) * TEST_ASYNC_MEMCPY_BENCH_COUNTS; - config.sram_trans_align = 4; // at least 4 bytes aligned for SRAM transfer - config.psram_trans_align = 64; // at least 64 bytes aligned for PSRAM transfer + config.dma_burst_size = 64; // set a big burst size for performance async_memcpy_handle_t driver = NULL; int64_t elapse_us = 0; float throughput = 0.0; @@ -311,7 +310,7 @@ static void memcpy_performance_test(uint32_t buffer_size) // 1. SRAM->SRAM memcpy_testbench_context_t test_context = { - .align = config.psram_trans_align, + .align = config.dma_burst_size, .buffer_size = buffer_size, .src_in_psram = false, .dst_in_psram = false, diff --git a/components/esp_lcd/i80/esp_lcd_panel_io_i80.c b/components/esp_lcd/i80/esp_lcd_panel_io_i80.c index 5f2911e573..cbaea3f63d 100644 --- a/components/esp_lcd/i80/esp_lcd_panel_io_i80.c +++ b/components/esp_lcd/i80/esp_lcd_panel_io_i80.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -27,10 +27,9 @@ #include "soc/soc_caps.h" #include "esp_clk_tree.h" #include "esp_memory_utils.h" +#include "esp_cache.h" #include "hal/dma_types.h" #include "hal/gpio_hal.h" -#include "hal/cache_hal.h" -#include "hal/cache_ll.h" #include "esp_private/gdma.h" #include "driver/gpio.h" #include "esp_private/periph_ctrl.h" @@ -38,7 +37,6 @@ #include "soc/lcd_periph.h" #include "hal/lcd_ll.h" #include "hal/lcd_hal.h" -#include "esp_cache.h" #define ALIGN_UP(size, align) (((size) + (align) - 1) & ~((align) - 1)) #define ALIGN_DOWN(size, align) ((size) & ~((align) - 1)) @@ -52,7 +50,7 @@ typedef struct lcd_i80_trans_descriptor_t lcd_i80_trans_descriptor_t; static esp_err_t panel_io_i80_tx_param(esp_lcd_panel_io_t *io, int lcd_cmd, const void *param, size_t param_size); static esp_err_t panel_io_i80_tx_color(esp_lcd_panel_io_t *io, int lcd_cmd, const void *color, size_t color_size); static esp_err_t panel_io_i80_del(esp_lcd_panel_io_t *io); -static esp_err_t lcd_i80_init_dma_link(esp_lcd_i80_bus_handle_t bus); +static esp_err_t lcd_i80_init_dma_link(esp_lcd_i80_bus_handle_t bus, const esp_lcd_i80_bus_config_t *bus_config); static void lcd_periph_trigger_quick_trans_done_event(esp_lcd_i80_bus_handle_t bus); static esp_err_t lcd_i80_select_periph_clock(esp_lcd_i80_bus_handle_t bus, lcd_clock_source_t clk_src); static esp_err_t lcd_i80_bus_configure_gpio(esp_lcd_i80_bus_handle_t bus, const esp_lcd_i80_bus_config_t *bus_config); @@ -72,8 +70,8 @@ struct esp_lcd_i80_bus_t { uint8_t *format_buffer; // The driver allocates an internal buffer for DMA to do data format transformer size_t resolution_hz; // LCD_CLK resolution, determined by selected clock source gdma_channel_handle_t dma_chan; // DMA channel handle - size_t psram_trans_align; // DMA transfer alignment for data allocated from PSRAM - size_t sram_trans_align; // DMA transfer alignment for data allocated from SRAM + size_t int_mem_align; // Alignment for internal memory + size_t ext_mem_align; // Alignment for external memory lcd_i80_trans_descriptor_t *cur_trans; // Current transaction lcd_panel_io_i80_t *cur_device; // Current working device LIST_HEAD(i80_device_list, lcd_panel_io_i80_t) device_list; // Head of i80 device list @@ -175,10 +173,8 @@ esp_err_t esp_lcd_new_i80_bus(const esp_lcd_i80_bus_config_t *bus_config, esp_lc lcd_ll_enable_interrupt(bus->hal.dev, LCD_LL_EVENT_TRANS_DONE, false); // disable all interrupts lcd_ll_clear_interrupt_status(bus->hal.dev, UINT32_MAX); // clear pending interrupt // install DMA service - bus->psram_trans_align = bus_config->psram_trans_align; - bus->sram_trans_align = bus_config->sram_trans_align; bus->bus_width = bus_config->bus_width; - ret = lcd_i80_init_dma_link(bus); + ret = lcd_i80_init_dma_link(bus, bus_config); ESP_GOTO_ON_ERROR(ret, err, TAG, "install DMA failed"); // disable RGB-LCD mode lcd_ll_enable_rgb_mode(bus->hal.dev, false); @@ -481,6 +477,18 @@ static esp_err_t panel_io_i80_tx_color(esp_lcd_panel_io_t *io, int lcd_cmd, cons esp_lcd_i80_bus_t *bus = i80_device->bus; lcd_i80_trans_descriptor_t *trans_desc = NULL; assert(color_size <= (bus->num_dma_nodes * DMA_DESCRIPTOR_BUFFER_MAX_SIZE) && "color bytes too long, enlarge max_transfer_bytes"); + if (esp_ptr_external_ram(color)) { + // check alignment + ESP_RETURN_ON_FALSE(((uint32_t)color & (bus->ext_mem_align - 1)) == 0, ESP_ERR_INVALID_ARG, TAG, "color address not aligned"); + ESP_RETURN_ON_FALSE((color_size & (bus->ext_mem_align - 1)) == 0, ESP_ERR_INVALID_ARG, TAG, "color size not aligned"); + // flush frame buffer from cache to the physical PSRAM + esp_cache_msync((void *)color, color_size, ESP_CACHE_MSYNC_FLAG_DIR_C2M | ESP_CACHE_MSYNC_FLAG_UNALIGNED); + } else { + // check alignment + ESP_RETURN_ON_FALSE(((uint32_t)color & (bus->int_mem_align - 1)) == 0, ESP_ERR_INVALID_ARG, TAG, "color address not aligned"); + ESP_RETURN_ON_FALSE((color_size & (bus->int_mem_align - 1)) == 0, ESP_ERR_INVALID_ARG, TAG, "color size not aligned"); + } + // in case bus_width=16 and cmd_bits=8, we still need 1 cmd_cycle uint32_t cmd_cycles = i80_device->lcd_cmd_bits / bus->bus_width; if (cmd_cycles * bus->bus_width < i80_device->lcd_cmd_bits) { @@ -503,13 +511,6 @@ static esp_err_t panel_io_i80_tx_color(esp_lcd_panel_io_t *io, int lcd_cmd, cons trans_desc->trans_done_cb = i80_device->on_color_trans_done; trans_desc->user_ctx = i80_device->user_ctx; - if (esp_ptr_external_ram(color)) { - uint32_t dcache_line_size = cache_hal_get_cache_line_size(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_DATA); - // flush frame buffer from cache to the physical PSRAM - // note the esp_cache_msync function will check the alignment of the address and size, make sure they're aligned to current cache line size - esp_cache_msync((void *)ALIGN_DOWN((intptr_t)color, dcache_line_size), ALIGN_UP(color_size, dcache_line_size), 0); - } - // send transaction to trans_queue xQueueSend(i80_device->trans_queue, &trans_desc, portMAX_DELAY); i80_device->num_trans_inflight++; @@ -542,7 +543,7 @@ static esp_err_t lcd_i80_select_periph_clock(esp_lcd_i80_bus_handle_t bus, lcd_c return ESP_OK; } -static esp_err_t lcd_i80_init_dma_link(esp_lcd_i80_bus_handle_t bus) +static esp_err_t lcd_i80_init_dma_link(esp_lcd_i80_bus_handle_t bus, const esp_lcd_i80_bus_config_t *bus_config) { esp_err_t ret = ESP_OK; // chain DMA descriptors @@ -567,12 +568,13 @@ static esp_err_t lcd_i80_init_dma_link(esp_lcd_i80_bus_handle_t bus) .owner_check = true }; gdma_apply_strategy(bus->dma_chan, &strategy_config); - // set DMA transfer ability - gdma_transfer_ability_t ability = { - .psram_trans_align = bus->psram_trans_align, - .sram_trans_align = bus->sram_trans_align, + // config DMA transfer parameters + gdma_transfer_config_t trans_cfg = { + .max_data_burst_size = bus_config->dma_burst_size ? bus_config->dma_burst_size : 16, // Enable DMA burst transfer for better performance + .access_ext_mem = true, // the LCD can carry pixel buffer from the external memory }; - gdma_set_transfer_ability(bus->dma_chan, &ability); + ESP_GOTO_ON_ERROR(gdma_config_transfer(bus->dma_chan, &trans_cfg), err, TAG, "config DMA transfer failed"); + gdma_get_alignment_constraints(bus->dma_chan, &bus->int_mem_align, &bus->ext_mem_align); return ESP_OK; err: if (bus->dma_chan) { diff --git a/components/esp_lcd/include/esp_lcd_panel_io.h b/components/esp_lcd/include/esp_lcd_panel_io.h index ffae62e680..03f0248a89 100644 --- a/components/esp_lcd/include/esp_lcd_panel_io.h +++ b/components/esp_lcd/include/esp_lcd_panel_io.h @@ -238,8 +238,11 @@ typedef struct { int data_gpio_nums[ESP_LCD_I80_BUS_WIDTH_MAX]; /*!< GPIOs used for data lines */ size_t bus_width; /*!< Number of data lines, 8 or 16 */ size_t max_transfer_bytes; /*!< Maximum transfer size, this determines the length of internal DMA link */ - size_t psram_trans_align; /*!< DMA transfer alignment for data allocated from PSRAM */ - size_t sram_trans_align; /*!< DMA transfer alignment for data allocated from SRAM */ + union { + size_t psram_trans_align; /*!< DMA transfer alignment for data allocated from PSRAM */ + size_t dma_burst_size; /*!< DMA burst size, in bytes */ + }; + size_t sram_trans_align __attribute__((deprecated)); /*!< DMA transfer alignment for data allocated from SRAM */ } esp_lcd_i80_bus_config_t; /** diff --git a/components/esp_lcd/rgb/esp_lcd_panel_rgb.c b/components/esp_lcd/rgb/esp_lcd_panel_rgb.c index 03161e1a96..a12f244229 100644 --- a/components/esp_lcd/rgb/esp_lcd_panel_rgb.c +++ b/components/esp_lcd/rgb/esp_lcd_panel_rgb.c @@ -39,7 +39,8 @@ #include "soc/lcd_periph.h" #include "hal/lcd_hal.h" #include "hal/lcd_ll.h" -#include "hal/gdma_ll.h" +#include "hal/cache_hal.h" +#include "hal/cache_ll.h" #include "rom/cache.h" #include "esp_cache.h" @@ -77,7 +78,8 @@ static esp_err_t rgb_panel_swap_xy(esp_lcd_panel_t *panel, bool swap_axes); static esp_err_t rgb_panel_set_gap(esp_lcd_panel_t *panel, int x_gap, int y_gap); static esp_err_t rgb_panel_disp_on_off(esp_lcd_panel_t *panel, bool off); static esp_err_t lcd_rgb_panel_select_clock_src(esp_rgb_panel_t *panel, lcd_clock_source_t clk_src); -static esp_err_t lcd_rgb_panel_create_trans_link(esp_rgb_panel_t *panel); +static esp_err_t lcd_rgb_create_dma_channel(esp_rgb_panel_t *panel); +static void lcd_rgb_panel_init_trans_link(esp_rgb_panel_t *panel); static esp_err_t lcd_rgb_panel_configure_gpio(esp_rgb_panel_t *panel, const esp_lcd_rgb_panel_config_t *panel_config); static void lcd_rgb_panel_start_transmission(esp_rgb_panel_t *rgb_panel); static void lcd_default_isr_handler(void *args); @@ -90,8 +92,7 @@ struct esp_rgb_panel_t { size_t fb_bits_per_pixel; // Frame buffer color depth, in bpp size_t num_fbs; // Number of frame buffers size_t output_bits_per_pixel; // Color depth seen from the output data line. Default to fb_bits_per_pixel, but can be changed by YUV-RGB conversion - size_t sram_trans_align; // Alignment for framebuffer that allocated in SRAM - size_t psram_trans_align; // Alignment for framebuffer that allocated in PSRAM + size_t dma_burst_size; // DMA transfer burst size int disp_gpio_num; // Display control GPIO, which is used to perform action like "disp_off" intr_handle_t intr; // LCD peripheral interrupt handle esp_pm_lock_handle_t pm_lock; // Power management lock @@ -134,10 +135,20 @@ struct esp_rgb_panel_t { static esp_err_t lcd_rgb_panel_alloc_frame_buffers(const esp_lcd_rgb_panel_config_t *rgb_panel_config, esp_rgb_panel_t *rgb_panel) { bool fb_in_psram = false; - size_t psram_trans_align = rgb_panel_config->psram_trans_align ? rgb_panel_config->psram_trans_align : 64; - size_t sram_trans_align = rgb_panel_config->sram_trans_align ? rgb_panel_config->sram_trans_align : 4; - rgb_panel->psram_trans_align = psram_trans_align; - rgb_panel->sram_trans_align = sram_trans_align; + size_t ext_mem_align = 0; + size_t int_mem_align = 0; + gdma_get_alignment_constraints(rgb_panel->dma_chan, &int_mem_align, &ext_mem_align); + + // also take the cache line size into account when allocating the frame buffer + uint32_t ext_mem_cache_line_size = cache_hal_get_cache_line_size(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_DATA); + uint32_t int_mem_cache_line_size = cache_hal_get_cache_line_size(CACHE_LL_LEVEL_INT_MEM, CACHE_TYPE_DATA); + // The buffer must be aligned to the cache line size + if (ext_mem_cache_line_size) { + ext_mem_align = MAX(ext_mem_align, ext_mem_cache_line_size); + } + if (int_mem_cache_line_size) { + int_mem_align = MAX(int_mem_align, int_mem_cache_line_size); + } // alloc frame buffer if (rgb_panel->num_fbs > 0) { @@ -152,13 +163,13 @@ static esp_err_t lcd_rgb_panel_alloc_frame_buffers(const esp_lcd_rgb_panel_confi for (int i = 0; i < rgb_panel->num_fbs; i++) { if (fb_in_psram) { // the low level malloc function will help check the validation of alignment - rgb_panel->fbs[i] = heap_caps_aligned_calloc(psram_trans_align, 1, rgb_panel->fb_size, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); + rgb_panel->fbs[i] = heap_caps_aligned_calloc(ext_mem_align, 1, rgb_panel->fb_size, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); ESP_RETURN_ON_FALSE(rgb_panel->fbs[i], ESP_ERR_NO_MEM, TAG, "no mem for frame buffer"); // calloc not only allocates but also zero's the buffer. We have to make sure this is // properly committed to the PSRAM, otherwise all sorts of visual corruption will happen. ESP_RETURN_ON_ERROR(esp_cache_msync(rgb_panel->fbs[i], rgb_panel->fb_size, ESP_CACHE_MSYNC_FLAG_DIR_C2M), TAG, "cache write back failed"); } else { - rgb_panel->fbs[i] = heap_caps_aligned_calloc(sram_trans_align, 1, rgb_panel->fb_size, MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA); + rgb_panel->fbs[i] = heap_caps_aligned_calloc(int_mem_align, 1, rgb_panel->fb_size, MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA); ESP_RETURN_ON_FALSE(rgb_panel->fbs[i], ESP_ERR_NO_MEM, TAG, "no mem for frame buffer"); } } @@ -168,7 +179,7 @@ static esp_err_t lcd_rgb_panel_alloc_frame_buffers(const esp_lcd_rgb_panel_confi if (rgb_panel->bb_size) { for (int i = 0; i < RGB_LCD_PANEL_BOUNCE_BUF_NUM; i++) { // bounce buffer must come from SRAM - rgb_panel->bounce_buffer[i] = heap_caps_aligned_calloc(sram_trans_align, 1, rgb_panel->bb_size, MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA); + rgb_panel->bounce_buffer[i] = heap_caps_aligned_calloc(int_mem_align, 1, rgb_panel->bb_size, MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA); ESP_RETURN_ON_FALSE(rgb_panel->bounce_buffer[i], ESP_ERR_NO_MEM, TAG, "no mem for bounce buffer"); } } @@ -302,9 +313,6 @@ esp_err_t esp_lcd_new_rgb_panel(const esp_lcd_rgb_panel_config_t *rgb_panel_conf } } - // allocate frame buffers + bounce buffers - ESP_GOTO_ON_ERROR(lcd_rgb_panel_alloc_frame_buffers(rgb_panel_config, rgb_panel), err, TAG, "alloc frame buffers failed"); - // initialize HAL layer, so we can call LL APIs later lcd_hal_init(&rgb_panel->hal, panel_id); // enable clock @@ -334,8 +342,13 @@ esp_err_t esp_lcd_new_rgb_panel(const esp_lcd_rgb_panel_config_t *rgb_panel_conf // install DMA service rgb_panel->flags.stream_mode = !rgb_panel_config->flags.refresh_on_demand; rgb_panel->fb_bits_per_pixel = fb_bits_per_pixel; - ret = lcd_rgb_panel_create_trans_link(rgb_panel); - ESP_GOTO_ON_ERROR(ret, err, TAG, "install DMA failed"); + rgb_panel->dma_burst_size = rgb_panel_config->dma_burst_size ? rgb_panel_config->dma_burst_size : 64; + ESP_GOTO_ON_ERROR(lcd_rgb_create_dma_channel(rgb_panel), err, TAG, "install DMA failed"); + // allocate frame buffers + bounce buffers + ESP_GOTO_ON_ERROR(lcd_rgb_panel_alloc_frame_buffers(rgb_panel_config, rgb_panel), err, TAG, "alloc frame buffers failed"); + // initialize DMA descriptor link + lcd_rgb_panel_init_trans_link(rgb_panel); + // configure GPIO ret = lcd_rgb_panel_configure_gpio(rgb_panel, rgb_panel_config); ESP_GOTO_ON_ERROR(ret, err, TAG, "configure GPIO failed"); @@ -959,11 +972,42 @@ static IRAM_ATTR bool lcd_rgb_panel_eof_handler(gdma_channel_handle_t dma_chan, return lcd_rgb_panel_fill_bounce_buffer(panel, panel->bounce_buffer[bb]); } +static esp_err_t lcd_rgb_create_dma_channel(esp_rgb_panel_t *panel) +{ + // alloc DMA channel and connect to LCD peripheral + gdma_channel_alloc_config_t dma_chan_config = { + .direction = GDMA_CHANNEL_DIRECTION_TX, + }; +#if SOC_GDMA_TRIG_PERIPH_LCD0_BUS == SOC_GDMA_BUS_AHB + ESP_RETURN_ON_ERROR(gdma_new_ahb_channel(&dma_chan_config, &panel->dma_chan), TAG, "alloc DMA channel failed"); +#elif SOC_GDMA_TRIG_PERIPH_LCD0_BUS == SOC_GDMA_BUS_AXI + ESP_RETURN_ON_ERROR(gdma_new_axi_channel(&dma_chan_config, &panel->dma_chan), TAG, "alloc DMA channel failed"); +#endif + gdma_connect(panel->dma_chan, GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_LCD, 0)); + + // configure DMA transfer parameters + gdma_transfer_config_t trans_cfg = { + .max_data_burst_size = panel->dma_burst_size, + .access_ext_mem = true, // frame buffer was allocated from external memory + }; + ESP_RETURN_ON_ERROR(gdma_config_transfer(panel->dma_chan, &trans_cfg), TAG, "config DMA transfer failed"); + + // we need to refill the bounce buffer in the DMA EOF interrupt, so only register the callback for bounce buffer mode + if (panel->bb_size) { + gdma_tx_event_callbacks_t cbs = { + .on_trans_eof = lcd_rgb_panel_eof_handler, + }; + gdma_register_tx_event_callbacks(panel->dma_chan, &cbs, panel); + } + + return ESP_OK; +} + // If we restart GDMA, many pixels already have been transferred to the LCD peripheral. // Looks like that has 16 pixels of FIFO plus one holding register. #define LCD_FIFO_PRESERVE_SIZE_PX (LCD_LL_FIFO_DEPTH + 1) -static esp_err_t lcd_rgb_panel_create_trans_link(esp_rgb_panel_t *panel) +static void lcd_rgb_panel_init_trans_link(esp_rgb_panel_t *panel) { for (int i = 0; i < RGB_LCD_PANEL_DMA_LINKS_REPLICA; i++) { panel->dma_links[i] = &panel->dma_nodes[panel->num_dma_nodes * i]; @@ -1007,32 +1051,6 @@ static esp_err_t lcd_rgb_panel_create_trans_link(esp_rgb_panel_t *panel) panel->dma_restart_node.buffer = &p[restart_skip_bytes]; panel->dma_restart_node.dw0.length -= restart_skip_bytes; panel->dma_restart_node.dw0.size -= restart_skip_bytes; - - // alloc DMA channel and connect to LCD peripheral - gdma_channel_alloc_config_t dma_chan_config = { - .direction = GDMA_CHANNEL_DIRECTION_TX, - }; -#if SOC_GDMA_TRIG_PERIPH_LCD0_BUS == SOC_GDMA_BUS_AHB - ESP_RETURN_ON_ERROR(gdma_new_ahb_channel(&dma_chan_config, &panel->dma_chan), TAG, "alloc DMA channel failed"); -#elif SOC_GDMA_TRIG_PERIPH_LCD0_BUS == SOC_GDMA_BUS_AXI - ESP_RETURN_ON_ERROR(gdma_new_axi_channel(&dma_chan_config, &panel->dma_chan), TAG, "alloc DMA channel failed"); -#endif - gdma_connect(panel->dma_chan, GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_LCD, 0)); - gdma_transfer_ability_t ability = { - .psram_trans_align = panel->psram_trans_align, - .sram_trans_align = panel->sram_trans_align, - }; - gdma_set_transfer_ability(panel->dma_chan, &ability); - - // we need to refill the bounce buffer in the DMA EOF interrupt, so only register the callback for bounce buffer mode - if (panel->bb_size) { - gdma_tx_event_callbacks_t cbs = { - .on_trans_eof = lcd_rgb_panel_eof_handler, - }; - gdma_register_tx_event_callbacks(panel->dma_chan, &cbs, panel); - } - - return ESP_OK; } // reset the GDMA channel every VBlank to stop permanent desyncs from happening. diff --git a/components/esp_lcd/rgb/include/esp_lcd_panel_rgb.h b/components/esp_lcd/rgb/include/esp_lcd_panel_rgb.h index 7cd4c690b7..2e9e5a95a6 100644 --- a/components/esp_lcd/rgb/include/esp_lcd_panel_rgb.h +++ b/components/esp_lcd/rgb/include/esp_lcd_panel_rgb.h @@ -132,8 +132,11 @@ typedef struct { size_t num_fbs; /*!< Number of screen-sized frame buffers that allocated by the driver. By default (set to either 0 or 1) only one frame buffer will be used. Maximum number of buffers are 3 */ size_t bounce_buffer_size_px; /*!< If it's non-zero, the driver allocates two DRAM bounce buffers for DMA use. DMA fetching from DRAM bounce buffer is much faster than PSRAM frame buffer. */ - size_t sram_trans_align; /*!< Alignment of buffers (frame buffer or bounce buffer) that allocated in SRAM */ - size_t psram_trans_align; /*!< Alignment of buffers (frame buffer) that allocated in PSRAM */ + size_t sram_trans_align __attribute__((deprecated)); /*!< Alignment of buffers (frame buffer or bounce buffer) that allocated in SRAM */ + union { + size_t psram_trans_align; /*!< Alignment of buffers (frame buffer) that allocated in PSRAM */ + size_t dma_burst_size; /*!< DMA burst size, in bytes */ + }; int hsync_gpio_num; /*!< GPIO used for HSYNC signal */ int vsync_gpio_num; /*!< GPIO used for VSYNC signal */ int de_gpio_num; /*!< GPIO used for DE signal, set to -1 if it's not used */ diff --git a/components/esp_lcd/test_apps/rgb_lcd/main/test_rgb_panel.c b/components/esp_lcd/test_apps/rgb_lcd/main/test_rgb_panel.c index 4e1eb3edd3..8c39c32121 100644 --- a/components/esp_lcd/test_apps/rgb_lcd/main/test_rgb_panel.c +++ b/components/esp_lcd/test_apps/rgb_lcd/main/test_rgb_panel.c @@ -31,7 +31,7 @@ static esp_lcd_panel_handle_t test_rgb_panel_initialization(size_t data_width, s esp_lcd_panel_handle_t panel_handle = NULL; esp_lcd_rgb_panel_config_t panel_config = { .data_width = data_width, - .psram_trans_align = 64, + .dma_burst_size = 64, .bounce_buffer_size_px = bb_pixels, .bits_per_pixel = bpp, .clk_src = LCD_CLK_SRC_DEFAULT, diff --git a/components/esp_lcd/test_apps/rgb_lcd/main/test_yuv_rgb_conv.c b/components/esp_lcd/test_apps/rgb_lcd/main/test_yuv_rgb_conv.c index 4bcf65dbdc..73ab6dede7 100644 --- a/components/esp_lcd/test_apps/rgb_lcd/main/test_yuv_rgb_conv.c +++ b/components/esp_lcd/test_apps/rgb_lcd/main/test_yuv_rgb_conv.c @@ -27,7 +27,7 @@ TEST_CASE("lcd_rgb_panel_yuv422_conversion", "[lcd]") esp_lcd_panel_handle_t panel_handle = NULL; esp_lcd_rgb_panel_config_t panel_config = { .data_width = 16, - .psram_trans_align = 64, + .dma_burst_size = 64, .bits_per_pixel = 16, // YUV422: 16bits per pixel .clk_src = LCD_CLK_SRC_DEFAULT, .disp_gpio_num = TEST_LCD_DISP_EN_GPIO, diff --git a/components/hal/esp32c2/include/hal/gdma_ll.h b/components/hal/esp32c2/include/hal/gdma_ll.h index 6bf41c6a50..37d7179c68 100644 --- a/components/hal/esp32c2/include/hal/gdma_ll.h +++ b/components/hal/esp32c2/include/hal/gdma_ll.h @@ -48,6 +48,7 @@ extern "C" { #define GDMA_LL_AHB_TX_RX_SHARE_INTERRUPT 1 // TX and RX channel in the same pair will share the same interrupt source number #define GDMA_LL_AHB_DESC_ALIGNMENT 4 +#define GDMA_LL_AHB_RX_BURST_NEEDS_ALIGNMENT 1 ///////////////////////////////////// Common ///////////////////////////////////////// diff --git a/components/hal/esp32c3/include/hal/gdma_ll.h b/components/hal/esp32c3/include/hal/gdma_ll.h index a6cb889b7d..e11d1fbc49 100644 --- a/components/hal/esp32c3/include/hal/gdma_ll.h +++ b/components/hal/esp32c3/include/hal/gdma_ll.h @@ -48,6 +48,7 @@ extern "C" { #define GDMA_LL_AHB_TX_RX_SHARE_INTERRUPT 1 // TX and RX channel in the same pair will share the same interrupt source number #define GDMA_LL_AHB_DESC_ALIGNMENT 4 +#define GDMA_LL_AHB_RX_BURST_NEEDS_ALIGNMENT 1 ///////////////////////////////////// Common ///////////////////////////////////////// diff --git a/components/hal/esp32c6/include/hal/gdma_ll.h b/components/hal/esp32c6/include/hal/gdma_ll.h index 78dd95c5c3..2a168bb692 100644 --- a/components/hal/esp32c6/include/hal/gdma_ll.h +++ b/components/hal/esp32c6/include/hal/gdma_ll.h @@ -51,6 +51,7 @@ extern "C" { #define GDMA_LL_AHB_PAIRS_PER_GROUP 3 // Number of GDMA pairs in each AHB group #define GDMA_LL_AHB_DESC_ALIGNMENT 4 +#define GDMA_LL_AHB_RX_BURST_NEEDS_ALIGNMENT 1 #define GDMA_LL_TX_ETM_EVENT_TABLE(group, chan, event) \ (uint32_t[1][3][GDMA_ETM_EVENT_MAX]){{{ \ diff --git a/components/hal/esp32h2/include/hal/gdma_ll.h b/components/hal/esp32h2/include/hal/gdma_ll.h index 78dd95c5c3..2a168bb692 100644 --- a/components/hal/esp32h2/include/hal/gdma_ll.h +++ b/components/hal/esp32h2/include/hal/gdma_ll.h @@ -51,6 +51,7 @@ extern "C" { #define GDMA_LL_AHB_PAIRS_PER_GROUP 3 // Number of GDMA pairs in each AHB group #define GDMA_LL_AHB_DESC_ALIGNMENT 4 +#define GDMA_LL_AHB_RX_BURST_NEEDS_ALIGNMENT 1 #define GDMA_LL_TX_ETM_EVENT_TABLE(group, chan, event) \ (uint32_t[1][3][GDMA_ETM_EVENT_MAX]){{{ \ diff --git a/components/hal/esp32p4/include/hal/axi_dma_ll.h b/components/hal/esp32p4/include/hal/axi_dma_ll.h index ddc1f5c3fb..923dcc66ac 100644 --- a/components/hal/esp32p4/include/hal/axi_dma_ll.h +++ b/components/hal/esp32p4/include/hal/axi_dma_ll.h @@ -125,7 +125,7 @@ static inline void axi_dma_ll_rx_enable_owner_check(axi_dma_dev_t *dev, uint32_t } /** - * @brief Enable DMA RX channel burst reading data, disabled by default + * @brief Enable DMA RX channel burst reading data, always enabled */ static inline void axi_dma_ll_rx_enable_data_burst(axi_dma_dev_t *dev, uint32_t channel, bool enable) { @@ -139,6 +139,16 @@ static inline void axi_dma_ll_rx_enable_descriptor_burst(axi_dma_dev_t *dev, uin dev->in[channel].conf.in_conf0.indscr_burst_en_chn = enable; } +/** + * @brief Set the RX channel burst size + */ +static inline void axi_dma_ll_rx_set_burst_size(axi_dma_dev_t *dev, uint32_t channel, uint32_t sz) +{ + HAL_ASSERT(sz >= 8 && sz <= 128); + int ctz = __builtin_ctz(sz); + dev->in[channel].conf.in_conf0.in_burst_size_sel_chn = ctz - 3; +} + /** * @brief Reset DMA RX channel FSM and FIFO pointer */ @@ -274,11 +284,11 @@ static inline void axi_dma_ll_rx_enable_etm_task(axi_dma_dev_t *dev, uint32_t ch } /** - * @brief Whether to enable the mean access ecc or aes domain + * @brief Whether to enable access to ecc or aes memory */ static inline void axi_dma_ll_rx_enable_ext_mem_ecc_aes_access(axi_dma_dev_t *dev, uint32_t channel, bool enable) { - dev->in[channel].conf.in_conf0.in_ecc_aec_en_chn = enable; + dev->in[channel].conf.in_conf0.in_ecc_aes_en_chn = enable; } ///////////////////////////////////// TX ///////////////////////////////////////// @@ -333,7 +343,7 @@ static inline void axi_dma_ll_tx_enable_owner_check(axi_dma_dev_t *dev, uint32_t } /** - * @brief Enable DMA TX channel burst sending data, disabled by default + * @brief Enable DMA TX channel burst sending data, always enabled */ static inline void axi_dma_ll_tx_enable_data_burst(axi_dma_dev_t *dev, uint32_t channel, bool enable) { @@ -347,6 +357,16 @@ static inline void axi_dma_ll_tx_enable_descriptor_burst(axi_dma_dev_t *dev, uin dev->out[channel].conf.out_conf0.outdscr_burst_en_chn = enable; } +/** + * @brief Set the TX channel burst size + */ +static inline void axi_dma_ll_tx_set_burst_size(axi_dma_dev_t *dev, uint32_t channel, uint32_t sz) +{ + HAL_ASSERT(sz >= 8 && sz <= 128); + int ctz = __builtin_ctz(sz); + dev->out[channel].conf.out_conf0.out_burst_size_sel_chn = ctz - 3; +} + /** * @brief Set TX channel EOF mode */ @@ -480,11 +500,11 @@ static inline void axi_dma_ll_tx_enable_etm_task(axi_dma_dev_t *dev, uint32_t ch } /** - * @brief Whether to enable the mean access ecc or aes domain + * @brief Whether to enable access to ecc or aes memory */ static inline void axi_dma_ll_tx_enable_ext_mem_ecc_aes_access(axi_dma_dev_t *dev, uint32_t channel, bool enable) { - dev->out[channel].conf.out_conf0.out_ecc_aec_en_chn = enable; + dev->out[channel].conf.out_conf0.out_ecc_aes_en_chn = enable; } ///////////////////////////////////// CRC-TX ///////////////////////////////////////// diff --git a/components/hal/esp32s3/include/hal/gdma_ll.h b/components/hal/esp32s3/include/hal/gdma_ll.h index 951145e85f..33c5c934eb 100644 --- a/components/hal/esp32s3/include/hal/gdma_ll.h +++ b/components/hal/esp32s3/include/hal/gdma_ll.h @@ -62,6 +62,9 @@ extern "C" { #define GDMA_LL_AHB_DESC_ALIGNMENT 4 +#define GDMA_LL_AHB_BURST_SIZE_ADJUSTABLE 1 // AHB GDMA supports adjustable burst size +#define GDMA_LL_AHB_RX_BURST_NEEDS_ALIGNMENT 1 + ///////////////////////////////////// Common ///////////////////////////////////////// /** @@ -177,20 +180,20 @@ static inline void gdma_ll_rx_reset_channel(gdma_dev_t *dev, uint32_t channel) } /** - * @brief Set DMA RX channel memory block size based on the alignment requirement - * @param align Supported value: 16/32/64 + * @brief Set DMA RX channel memory block size based on the burst requirement + * @param burst_sz Supported value: 16/32/64 */ -static inline void gdma_ll_rx_set_ext_mem_block_size(gdma_dev_t *dev, uint32_t channel, uint8_t align) +static inline void gdma_ll_rx_set_burst_size(gdma_dev_t *dev, uint32_t channel, uint32_t burst_sz) { uint32_t block_size = 0; - switch (align) { - case 64: // 64 Bytes alignment + switch (burst_sz) { + case 64: block_size = GDMA_LL_EXT_MEM_BK_SIZE_64B; break; - case 32: // 32 Bytes alignment + case 32: block_size = GDMA_LL_EXT_MEM_BK_SIZE_32B; break; - case 16: // 16 Bytes alignment + case 16: block_size = GDMA_LL_EXT_MEM_BK_SIZE_16B; break; default: @@ -461,20 +464,20 @@ static inline void gdma_ll_tx_reset_channel(gdma_dev_t *dev, uint32_t channel) } /** - * @brief Set DMA TX channel memory block size based on the alignment requirement - * @param align Supported value: 16/32/64 + * @brief Set DMA TX channel memory block size based on the burst requirement + * @param burst_sz Supported value: 16/32/64 */ -static inline void gdma_ll_tx_set_ext_mem_block_size(gdma_dev_t *dev, uint32_t channel, uint8_t align) +static inline void gdma_ll_tx_set_burst_size(gdma_dev_t *dev, uint32_t channel, uint32_t burst_sz) { uint32_t block_size = 0; - switch (align) { - case 64: // 64 Bytes alignment + switch (burst_sz) { + case 64: block_size = GDMA_LL_EXT_MEM_BK_SIZE_64B; break; - case 32: // 32 Bytes alignment + case 32: block_size = GDMA_LL_EXT_MEM_BK_SIZE_32B; break; - case 16: // 16 Bytes alignment + case 16: block_size = GDMA_LL_EXT_MEM_BK_SIZE_16B; break; default: diff --git a/components/hal/gdma_hal_ahb_v1.c b/components/hal/gdma_hal_ahb_v1.c index 6964b98790..08130d25ce 100644 --- a/components/hal/gdma_hal_ahb_v1.c +++ b/components/hal/gdma_hal_ahb_v1.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -91,16 +91,16 @@ void gdma_ahb_hal_enable_burst(gdma_hal_context_t *hal, int chan_id, gdma_channe } } -#if SOC_AHB_GDMA_SUPPORT_PSRAM -void gdma_ahb_hal_set_ext_mem_align(gdma_hal_context_t *hal, int chan_id, gdma_channel_direction_t dir, uint8_t align) +#if GDMA_LL_AHB_BURST_SIZE_ADJUSTABLE +void gdma_ahb_hal_set_burst_size(gdma_hal_context_t *hal, int chan_id, gdma_channel_direction_t dir, uint32_t burst_sz) { if (dir == GDMA_CHANNEL_DIRECTION_RX) { - gdma_ll_rx_set_ext_mem_block_size(hal->dev, chan_id, align); + gdma_ll_rx_set_burst_size(hal->dev, chan_id, burst_sz); } else { - gdma_ll_tx_set_ext_mem_block_size(hal->dev, chan_id, align); + gdma_ll_tx_set_burst_size(hal->dev, chan_id, burst_sz); } } -#endif +#endif // GDMA_LL_AHB_BURST_SIZE_ADJUSTABLE void gdma_ahb_hal_set_strategy(gdma_hal_context_t *hal, int chan_id, gdma_channel_direction_t dir, bool en_owner_check, bool en_desc_write_back) { @@ -193,8 +193,8 @@ void gdma_ahb_hal_init(gdma_hal_context_t *hal, const gdma_hal_config_t *config) #if SOC_GDMA_SUPPORT_ETM hal->enable_etm_task = gdma_ahb_hal_enable_etm_task; #endif -#if SOC_AHB_GDMA_SUPPORT_PSRAM - hal->set_ext_mem_align = gdma_ahb_hal_set_ext_mem_align; -#endif // SOC_AHB_GDMA_SUPPORT_PSRAM +#if GDMA_LL_AHB_BURST_SIZE_ADJUSTABLE + hal->set_burst_size = gdma_ahb_hal_set_burst_size; +#endif // GDMA_LL_AHB_BURST_SIZE_ADJUSTABLE hal->priv_data = &gdma_ahb_hal_priv_data; } diff --git a/components/hal/gdma_hal_ahb_v2.c b/components/hal/gdma_hal_ahb_v2.c index 71385465fe..b24b39b9d5 100644 --- a/components/hal/gdma_hal_ahb_v2.c +++ b/components/hal/gdma_hal_ahb_v2.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -102,6 +102,17 @@ void gdma_ahb_hal_set_strategy(gdma_hal_context_t *hal, int chan_id, gdma_channe } } +#if GDMA_LL_AHB_BURST_SIZE_ADJUSTABLE +void gdma_ahb_hal_set_burst_size(gdma_hal_context_t *hal, int chan_id, gdma_channel_direction_t dir, uint32_t burst_sz) +{ + if (dir == GDMA_CHANNEL_DIRECTION_RX) { + ahb_dma_ll_rx_set_burst_size(hal->ahb_dma_dev, chan_id, burst_sz); + } else { + ahb_dma_ll_tx_set_burst_size(hal->ahb_dma_dev, chan_id, burst_sz); + } +} +#endif // GDMA_LL_AHB_BURST_SIZE_ADJUSTABLE + void gdma_ahb_hal_enable_intr(gdma_hal_context_t *hal, int chan_id, gdma_channel_direction_t dir, uint32_t intr_event_mask, bool en_or_dis) { if (dir == GDMA_CHANNEL_DIRECTION_RX) { @@ -244,5 +255,8 @@ void gdma_ahb_hal_init(gdma_hal_context_t *hal, const gdma_hal_config_t *config) #if SOC_GDMA_SUPPORT_ETM hal->enable_etm_task = gdma_ahb_hal_enable_etm_task; #endif // SOC_GDMA_SUPPORT_ETM +#if GDMA_LL_AHB_BURST_SIZE_ADJUSTABLE + hal->set_burst_size = gdma_ahb_hal_set_burst_size; +#endif // GDMA_LL_AHB_BURST_SIZE_ADJUSTABLE ahb_dma_ll_set_default_memory_range(hal->ahb_dma_dev); } diff --git a/components/hal/gdma_hal_axi.c b/components/hal/gdma_hal_axi.c index da31498cad..9596808900 100644 --- a/components/hal/gdma_hal_axi.c +++ b/components/hal/gdma_hal_axi.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -102,6 +102,15 @@ void gdma_axi_hal_set_strategy(gdma_hal_context_t *hal, int chan_id, gdma_channe } } +void gdma_axi_hal_set_burst_size(gdma_hal_context_t *hal, int chan_id, gdma_channel_direction_t dir, uint32_t burst_sz) +{ + if (dir == GDMA_CHANNEL_DIRECTION_RX) { + axi_dma_ll_rx_set_burst_size(hal->axi_dma_dev, chan_id, burst_sz); + } else { + axi_dma_ll_tx_set_burst_size(hal->axi_dma_dev, chan_id, burst_sz); + } +} + void gdma_axi_hal_enable_intr(gdma_hal_context_t *hal, int chan_id, gdma_channel_direction_t dir, uint32_t intr_event_mask, bool en_or_dis) { if (dir == GDMA_CHANNEL_DIRECTION_RX) { @@ -151,6 +160,15 @@ uint32_t gdma_axi_hal_get_eof_desc_addr(gdma_hal_context_t *hal, int chan_id, gd } } +void gdma_axi_hal_enable_access_encrypt_mem(gdma_hal_context_t *hal, int chan_id, gdma_channel_direction_t dir, bool en_or_dis) +{ + if (dir == GDMA_CHANNEL_DIRECTION_RX) { + axi_dma_ll_rx_enable_ext_mem_ecc_aes_access(hal->axi_dma_dev, chan_id, en_or_dis); + } else { + axi_dma_ll_tx_enable_ext_mem_ecc_aes_access(hal->axi_dma_dev, chan_id, en_or_dis); + } +} + #if SOC_GDMA_SUPPORT_CRC void gdma_axi_hal_clear_crc(gdma_hal_context_t *hal, int chan_id, gdma_channel_direction_t dir) { @@ -236,6 +254,8 @@ void gdma_axi_hal_init(gdma_hal_context_t *hal, const gdma_hal_config_t *config) hal->read_intr_status = gdma_axi_hal_read_intr_status; hal->get_intr_status_reg = gdma_axi_hal_get_intr_status_reg; hal->get_eof_desc_addr = gdma_axi_hal_get_eof_desc_addr; + hal->set_burst_size = gdma_axi_hal_set_burst_size; + hal->enable_access_encrypt_mem = gdma_axi_hal_enable_access_encrypt_mem; #if SOC_GDMA_SUPPORT_CRC hal->clear_crc = gdma_axi_hal_clear_crc; hal->set_crc_poly = gdma_axi_hal_set_crc_poly; diff --git a/components/hal/gdma_hal_top.c b/components/hal/gdma_hal_top.c index e3c882b2a2..eb0c8fb0dc 100644 --- a/components/hal/gdma_hal_top.c +++ b/components/hal/gdma_hal_top.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -53,10 +53,10 @@ void gdma_hal_enable_burst(gdma_hal_context_t *hal, int chan_id, gdma_channel_di hal->enable_burst(hal, chan_id, dir, en_data_burst, en_desc_burst); } -void gdma_hal_set_ext_mem_align(gdma_hal_context_t *hal, int chan_id, gdma_channel_direction_t dir, uint8_t align) +void gdma_hal_set_burst_size(gdma_hal_context_t *hal, int chan_id, gdma_channel_direction_t dir, uint32_t burst_sz) { - if (hal->set_ext_mem_align) { - hal->set_ext_mem_align(hal, chan_id, dir, align); + if (hal->set_burst_size) { + hal->set_burst_size(hal, chan_id, dir, burst_sz); } } @@ -90,6 +90,13 @@ uint32_t gdma_hal_get_eof_desc_addr(gdma_hal_context_t *hal, int chan_id, gdma_c return hal->get_eof_desc_addr(hal, chan_id, dir, is_success); } +void gdma_hal_enable_access_encrypt_mem(gdma_hal_context_t *hal, int chan_id, gdma_channel_direction_t dir, bool en_or_dis) +{ + if (hal->enable_access_encrypt_mem) { + hal->enable_access_encrypt_mem(hal, chan_id, dir, en_or_dis); + } +} + #if SOC_GDMA_SUPPORT_CRC void gdma_hal_clear_crc(gdma_hal_context_t *hal, int chan_id, gdma_channel_direction_t dir) { diff --git a/components/hal/include/hal/gdma_hal.h b/components/hal/include/hal/gdma_hal.h index 1eca5ebf3c..228d9af83e 100644 --- a/components/hal/include/hal/gdma_hal.h +++ b/components/hal/include/hal/gdma_hal.h @@ -80,13 +80,14 @@ struct gdma_hal_context_t { void (*connect_peri)(gdma_hal_context_t *hal, int chan_id, gdma_channel_direction_t dir, gdma_trigger_peripheral_t periph, int periph_sub_id); /// Connect the channel to a peripheral void (*disconnect_peri)(gdma_hal_context_t *hal, int chan_id, gdma_channel_direction_t dir); /// Disconnect the channel from a peripheral void (*enable_burst)(gdma_hal_context_t *hal, int chan_id, gdma_channel_direction_t dir, bool en_data_burst, bool en_desc_burst); /// Enable burst mode - void (*set_ext_mem_align)(gdma_hal_context_t *hal, int chan_id, gdma_channel_direction_t dir, uint8_t align); /// Set the alignment of the external memory void (*set_strategy)(gdma_hal_context_t *hal, int chan_id, gdma_channel_direction_t dir, bool en_owner_check, bool en_desc_write_back); /// Set some misc strategy of the channel behaviour + void (*set_burst_size)(gdma_hal_context_t *hal, int chan_id, gdma_channel_direction_t dir, uint32_t burst_sz); /// Set burst transfer size uint32_t (*get_intr_status_reg)(gdma_hal_context_t *hal, int chan_id, gdma_channel_direction_t dir); // Get the interrupt status register address void (*enable_intr)(gdma_hal_context_t *hal, int chan_id, gdma_channel_direction_t dir, uint32_t intr_event_mask, bool en_or_dis); /// Enable the channel interrupt void (*clear_intr)(gdma_hal_context_t *hal, int chan_id, gdma_channel_direction_t dir, uint32_t intr_event_mask); /// Clear the channel interrupt uint32_t (*read_intr_status)(gdma_hal_context_t *hal, int chan_id, gdma_channel_direction_t dir, bool raw); /// Read the channel interrupt status uint32_t (*get_eof_desc_addr)(gdma_hal_context_t *hal, int chan_id, gdma_channel_direction_t dir, bool is_success); /// Get the address of the descriptor with success/error EOF flag set + void (*enable_access_encrypt_mem)(gdma_hal_context_t *hal, int chan_id, gdma_channel_direction_t dir, bool en_or_dis); /// Enable the access to the encrypted memory #if SOC_GDMA_SUPPORT_CRC void (*clear_crc)(gdma_hal_context_t *hal, int chan_id, gdma_channel_direction_t dir); /// Clear the CRC interim results void (*set_crc_poly)(gdma_hal_context_t *hal, int chan_id, gdma_channel_direction_t dir, const gdma_hal_crc_config_t *config); /// Set the CRC polynomial @@ -115,7 +116,7 @@ void gdma_hal_disconnect_peri(gdma_hal_context_t *hal, int chan_id, gdma_channel void gdma_hal_enable_burst(gdma_hal_context_t *hal, int chan_id, gdma_channel_direction_t dir, bool en_data_burst, bool en_desc_burst); -void gdma_hal_set_ext_mem_align(gdma_hal_context_t *hal, int chan_id, gdma_channel_direction_t dir, uint8_t align); +void gdma_hal_set_burst_size(gdma_hal_context_t *hal, int chan_id, gdma_channel_direction_t dir, uint32_t burst_sz); void gdma_hal_set_strategy(gdma_hal_context_t *hal, int chan_id, gdma_channel_direction_t dir, bool en_owner_check, bool en_desc_write_back); @@ -129,6 +130,8 @@ uint32_t gdma_hal_read_intr_status(gdma_hal_context_t *hal, int chan_id, gdma_ch uint32_t gdma_hal_get_eof_desc_addr(gdma_hal_context_t *hal, int chan_id, gdma_channel_direction_t dir, bool is_success); +void gdma_hal_enable_access_encrypt_mem(gdma_hal_context_t *hal, int chan_id, gdma_channel_direction_t dir, bool en_or_dis); + #if SOC_GDMA_SUPPORT_CRC void gdma_hal_build_parallel_crc_matrix(int crc_width, uint32_t crc_poly_hex, int data_width, uint32_t *lfsr_transform_matrix, uint32_t *data_transform_matrix); diff --git a/components/hal/include/hal/gdma_hal_ahb.h b/components/hal/include/hal/gdma_hal_ahb.h index e2de69b9e9..03782e251e 100644 --- a/components/hal/include/hal/gdma_hal_ahb.h +++ b/components/hal/include/hal/gdma_hal_ahb.h @@ -28,7 +28,7 @@ void gdma_ahb_hal_disconnect_peri(gdma_hal_context_t *hal, int chan_id, gdma_cha void gdma_ahb_hal_enable_burst(gdma_hal_context_t *hal, int chan_id, gdma_channel_direction_t dir, bool en_data_burst, bool en_desc_burst); -void gdma_ahb_hal_set_ext_mem_align(gdma_hal_context_t *hal, int chan_id, gdma_channel_direction_t dir, uint8_t align); +void gdma_ahb_hal_set_burst_size(gdma_hal_context_t *hal, int chan_id, gdma_channel_direction_t dir, uint32_t burst_sz); void gdma_ahb_hal_set_strategy(gdma_hal_context_t *hal, int chan_id, gdma_channel_direction_t dir, bool en_owner_check, bool en_desc_write_back); diff --git a/components/hal/include/hal/gdma_hal_axi.h b/components/hal/include/hal/gdma_hal_axi.h index e9cb68b708..c9f5a8f318 100644 --- a/components/hal/include/hal/gdma_hal_axi.h +++ b/components/hal/include/hal/gdma_hal_axi.h @@ -28,6 +28,8 @@ void gdma_axi_hal_disconnect_peri(gdma_hal_context_t *hal, int chan_id, gdma_cha void gdma_axi_hal_enable_burst(gdma_hal_context_t *hal, int chan_id, gdma_channel_direction_t dir, bool en_data_burst, bool en_desc_burst); +void gdma_axi_hal_set_burst_size(gdma_hal_context_t *hal, int chan_id, gdma_channel_direction_t dir, uint32_t burst_sz); + void gdma_axi_hal_set_ext_mem_align(gdma_hal_context_t *hal, int chan_id, gdma_channel_direction_t dir, uint8_t align); void gdma_axi_hal_set_strategy(gdma_hal_context_t *hal, int chan_id, gdma_channel_direction_t dir, bool en_owner_check, bool en_desc_write_back); diff --git a/components/mbedtls/port/crypto_shared_gdma/esp_crypto_shared_gdma.c b/components/mbedtls/port/crypto_shared_gdma/esp_crypto_shared_gdma.c index 9f202249e9..e906b9ac6f 100644 --- a/components/mbedtls/port/crypto_shared_gdma/esp_crypto_shared_gdma.c +++ b/components/mbedtls/port/crypto_shared_gdma/esp_crypto_shared_gdma.c @@ -73,12 +73,6 @@ static esp_err_t crypto_shared_gdma_init(void) .direction = GDMA_CHANNEL_DIRECTION_RX, }; - gdma_transfer_ability_t transfer_ability = { - .sram_trans_align = 1, - .psram_trans_align = 16, - }; - - ret = crypto_shared_gdma_new_channel(&channel_config_tx, &tx_channel); if (ret != ESP_OK) { goto err; @@ -90,9 +84,13 @@ static esp_err_t crypto_shared_gdma_init(void) goto err; } - - gdma_set_transfer_ability(tx_channel, &transfer_ability); - gdma_set_transfer_ability(rx_channel, &transfer_ability); + gdma_transfer_config_t transfer_cfg = { + .max_data_burst_size = 16, + .access_ext_mem = true, // crypto peripheral may want to access PSRAM + }; + gdma_config_transfer(tx_channel, &transfer_cfg); + transfer_cfg.max_data_burst_size = 0; + gdma_config_transfer(rx_channel, &transfer_cfg); gdma_connect(rx_channel, GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_AES, 0)); gdma_connect(tx_channel, GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_AES, 0)); @@ -223,7 +221,7 @@ bool esp_crypto_shared_gdma_done(void) { int rx_ch_id = 0; gdma_get_channel_id(rx_channel, &rx_ch_id); - while(1) { + while (1) { if ((axi_dma_ll_rx_get_interrupt_status(&AXI_DMA, rx_ch_id, true) & 1)) { break; } diff --git a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in index 6f6566e6c4..1219cd9e87 100644 --- a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in @@ -471,7 +471,7 @@ config SOC_DS_KEY_CHECK_MAX_WAIT_US int default 1100 -config SOC_DMA_CAN_ACCESS_MSPI_MEM +config SOC_DMA_CAN_ACCESS_FLASH bool default y diff --git a/components/soc/esp32p4/include/soc/axi_dma_struct.h b/components/soc/esp32p4/include/soc/axi_dma_struct.h index dcd83b04c8..61b3de7fc8 100644 --- a/components/soc/esp32p4/include/soc/axi_dma_struct.h +++ b/components/soc/esp32p4/include/soc/axi_dma_struct.h @@ -1,5 +1,5 @@ /** - * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -273,10 +273,10 @@ typedef union { * 1:mean disable cmd of this ch0 */ uint32_t in_cmd_disable_chn: 1; - /** in_ecc_aec_en_chn : R/W; bitpos: [8]; default: 0; + /** in_ecc_aes_en_chn : R/W; bitpos: [8]; default: 0; * 1: mean access ecc or aes domain,0: mean not */ - uint32_t in_ecc_aec_en_chn: 1; + uint32_t in_ecc_aes_en_chn: 1; /** indscr_burst_en_chn : R/W; bitpos: [9]; default: 0; * Set this bit to 1 to enable INCR burst transfer for Rx channel 0 reading link * descriptor when accessing internal SRAM. @@ -567,7 +567,7 @@ typedef union { */ uint32_t rx_ch_arb_weigh_chn: 4; /** rx_arb_weigh_opt_dir_chn : R/W; bitpos: [8]; default: 0; - * 0: mean not optimazation weight function ,1: mean optimazation + * 0: mean not optimization weight function ,1: mean optimization */ uint32_t rx_arb_weigh_opt_dir_chn: 1; uint32_t reserved_9: 23; @@ -952,10 +952,10 @@ typedef union { * 1:mean disable cmd of this chn */ uint32_t out_cmd_disable_chn: 1; - /** out_ecc_aec_en_chn : R/W; bitpos: [9]; default: 0; + /** out_ecc_aes_en_chn : R/W; bitpos: [9]; default: 0; * 1: mean access ecc or aes domain,0: mean not */ - uint32_t out_ecc_aec_en_chn: 1; + uint32_t out_ecc_aes_en_chn: 1; /** outdscr_burst_en_chn : R/W; bitpos: [10]; default: 0; * Set this bit to 1 to enable INCR burst transfer for Tx channel0 reading link * descriptor when accessing internal SRAM. @@ -1238,7 +1238,7 @@ typedef union { */ uint32_t tx_ch_arb_weigh_chn: 4; /** tx_arb_weigh_opt_dir_chn : R/W; bitpos: [8]; default: 0; - * 0: mean not optimazation weight function ,1: mean optimazation + * 0: mean not optimization weight function ,1: mean optimization */ uint32_t tx_arb_weigh_opt_dir_chn: 1; uint32_t reserved_9: 23; @@ -1374,106 +1374,6 @@ typedef union { uint32_t val; } axi_dma_tx_crc_data_en_addr_chn_reg_t; -/** Type of out_conf0_ch1 register - * Configure 0 register of Tx channel1 - */ -typedef union { - struct { - /** out_rst_ch1 : R/W; bitpos: [0]; default: 0; - * This bit is used to reset AXI_DMA channel1 Tx FSM and Tx FIFO pointer. - */ - uint32_t out_rst_ch1: 1; - /** out_loop_test_ch1 : R/W; bitpos: [1]; default: 0; - * reserved - */ - uint32_t out_loop_test_ch1: 1; - /** out_auto_wrback_ch1 : R/W; bitpos: [2]; default: 0; - * Set this bit to enable automatic outlink-writeback when all the data in tx buffer - * has been transmitted. - */ - uint32_t out_auto_wrback_ch1: 1; - /** out_eof_mode_ch1 : R/W; bitpos: [3]; default: 1; - * EOF flag generation mode when transmitting data. 1: EOF flag for Tx channel1 is - * generated when data need to transmit has been popped from FIFO in AXI_DMA - */ - uint32_t out_eof_mode_ch1: 1; - /** out_etm_en_ch1 : R/W; bitpos: [4]; default: 0; - * Set this bit to 1 to enable etm control mode, dma Tx channel1 is triggered by etm - * task. - */ - uint32_t out_etm_en_ch1: 1; - /** out_burst_size_sel_ch1 : R/W; bitpos: [7:5]; default: 0; - * 3'b000-3'b100:burst length 8byte~128byte - */ - uint32_t out_burst_size_sel_ch1: 3; - /** out_cmd_disable_ch1 : R/W; bitpos: [8]; default: 0; - * 1:mean disable cmd of this ch1 - */ - uint32_t out_cmd_disable_ch1: 1; - /** out_ecc_aec_en_ch1 : R/W; bitpos: [9]; default: 0; - * 1: mean access ecc or aes domain,0: mean not - */ - uint32_t out_ecc_aec_en_ch1: 1; - /** outdscr_burst_en_ch1 : R/W; bitpos: [10]; default: 0; - * Set this bit to 1 to enable INCR burst transfer for Tx channel1 reading link - * descriptor when accessing internal SRAM. - */ - uint32_t outdscr_burst_en_ch1: 1; - uint32_t reserved_11: 21; - }; - uint32_t val; -} axi_dma_out_conf0_ch1_reg_t; - -/** Type of out_conf0_ch2 register - * Configure 0 register of Tx channel2 - */ -typedef union { - struct { - /** out_rst_ch2 : R/W; bitpos: [0]; default: 0; - * This bit is used to reset AXI_DMA channel2 Tx FSM and Tx FIFO pointer. - */ - uint32_t out_rst_ch2: 1; - /** out_loop_test_ch2 : R/W; bitpos: [1]; default: 0; - * reserved - */ - uint32_t out_loop_test_ch2: 1; - /** out_auto_wrback_ch2 : R/W; bitpos: [2]; default: 0; - * Set this bit to enable automatic outlink-writeback when all the data in tx buffer - * has been transmitted. - */ - uint32_t out_auto_wrback_ch2: 1; - /** out_eof_mode_ch2 : R/W; bitpos: [3]; default: 1; - * EOF flag generation mode when transmitting data. 1: EOF flag for Tx channel2 is - * generated when data need to transmit has been popped from FIFO in AXI_DMA - */ - uint32_t out_eof_mode_ch2: 1; - /** out_etm_en_ch2 : R/W; bitpos: [4]; default: 0; - * Set this bit to 1 to enable etm control mode, dma Tx channel2 is triggered by etm - * task. - */ - uint32_t out_etm_en_ch2: 1; - /** out_burst_size_sel_ch2 : R/W; bitpos: [7:5]; default: 0; - * 3'b000-3'b100:burst length 8byte~128byte - */ - uint32_t out_burst_size_sel_ch2: 3; - /** out_cmd_disable_ch2 : R/W; bitpos: [8]; default: 0; - * 1:mean disable cmd of this ch2 - */ - uint32_t out_cmd_disable_ch2: 1; - /** out_ecc_aec_en_ch2 : R/W; bitpos: [9]; default: 0; - * 1: mean access ecc or aes domain,0: mean not - */ - uint32_t out_ecc_aec_en_ch2: 1; - /** outdscr_burst_en_ch2 : R/W; bitpos: [10]; default: 0; - * Set this bit to 1 to enable INCR burst transfer for Tx channel2 reading link - * descriptor when accessing internal SRAM. - */ - uint32_t outdscr_burst_en_ch2: 1; - uint32_t reserved_11: 21; - }; - uint32_t val; -} axi_dma_out_conf0_ch2_reg_t; - /** Group: Configuration Registers */ /** Type of arb_timeout register * This retister is used to config arbiter time slice @@ -1705,12 +1605,12 @@ typedef union { /** Group: Status Registers */ /** Type of wresp_cnt register - * AXI wr responce cnt register. + * AXI wr response cnt register. */ typedef union { struct { /** wresp_cnt : RO; bitpos: [3:0]; default: 0; - * axi wr responce cnt reg. + * axi wr response cnt reg. */ uint32_t wresp_cnt: 4; uint32_t reserved_4: 28; @@ -1719,12 +1619,12 @@ typedef union { } axi_dma_wresp_cnt_reg_t; /** Type of rresp_cnt register - * AXI wr responce cnt register. + * AXI wr response cnt register. */ typedef union { struct { /** rresp_cnt : RO; bitpos: [3:0]; default: 0; - * axi rd responce cnt reg. + * axi rd response cnt reg. */ uint32_t rresp_cnt: 4; uint32_t reserved_4: 28; diff --git a/components/soc/esp32p4/include/soc/soc_caps.h b/components/soc/esp32p4/include/soc/soc_caps.h index d2a55eea8b..0cfd662b8e 100644 --- a/components/soc/esp32p4/include/soc/soc_caps.h +++ b/components/soc/esp32p4/include/soc/soc_caps.h @@ -188,7 +188,7 @@ #define SOC_DS_KEY_CHECK_MAX_WAIT_US (1100) /*-------------------------- DMA Common CAPS ----------------------------------------*/ -#define SOC_DMA_CAN_ACCESS_MSPI_MEM 1 /*!< DMA can access MSPI memory (e.g. Flash, PSRAM) */ +#define SOC_DMA_CAN_ACCESS_FLASH 1 /*!< DMA can access Flash memory */ /*-------------------------- GDMA CAPS -------------------------------------*/ #define SOC_AHB_GDMA_VERSION 2 diff --git a/components/wpa_supplicant/test_apps/main/test_crypto.c b/components/wpa_supplicant/test_apps/main/test_crypto.c index 42fefce803..23f14b8da5 100644 --- a/components/wpa_supplicant/test_apps/main/test_crypto.c +++ b/components/wpa_supplicant/test_apps/main/test_crypto.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -37,7 +37,6 @@ TEST_CASE("Test crypto lib bignum apis", "[wpa_crypto]") bn = crypto_bignum_init_set(buf, 32); TEST_ASSERT_NOT_NULL(bn); - TEST_ASSERT(crypto_bignum_to_bin(bn, buf2, 32, 0) == 32); TEST_ASSERT(!memcmp(buf, buf2, 32)); @@ -245,7 +244,6 @@ TEST_CASE("Test crypto lib bignum apis", "[wpa_crypto]") uint8_t buf1[32], buf2[32]; crypto_bignum *bn1, *bn2; - buf1[0] = 0xf; buf2[0] = 0x11; @@ -277,7 +275,6 @@ TEST_CASE("Test crypto lib bignum apis", "[wpa_crypto]") } } - /* * Conversion macros for embedded constants: * build lists of mbedtls_mpi_uint's from lists of unsigned char's grouped by 8, 4 or 2 @@ -322,30 +319,29 @@ TEST_CASE("Test crypto lib bignum apis", "[wpa_crypto]") * (assumes len is an exact multiple of sizeof mbedtls_mpi_uint) * Allocate a new memory as well so that it can be freed. */ -static inline void ecp_mpi_load( mbedtls_mpi *X, const mbedtls_mpi_uint *p, size_t len ) +static inline void ecp_mpi_load(mbedtls_mpi *X, const mbedtls_mpi_uint *p, size_t len) { X->MBEDTLS_PRIVATE(s) = 1; - X->MBEDTLS_PRIVATE(n) = len / sizeof( mbedtls_mpi_uint ); + X->MBEDTLS_PRIVATE(n) = len / sizeof(mbedtls_mpi_uint); X->MBEDTLS_PRIVATE(p) = os_zalloc(len); memcpy(X->MBEDTLS_PRIVATE(p), (void *)p, len); } - TEST_CASE("Test crypto lib ECC apis", "[wpa_crypto]") { - set_leak_threshold(600); + set_leak_threshold(620); static const mbedtls_mpi_uint secp256r1_gx[] = { - BYTES_TO_T_UINT_8( 0x96, 0xC2, 0x98, 0xD8, 0x45, 0x39, 0xA1, 0xF4 ), - BYTES_TO_T_UINT_8( 0xA0, 0x33, 0xEB, 0x2D, 0x81, 0x7D, 0x03, 0x77 ), - BYTES_TO_T_UINT_8( 0xF2, 0x40, 0xA4, 0x63, 0xE5, 0xE6, 0xBC, 0xF8 ), - BYTES_TO_T_UINT_8( 0x47, 0x42, 0x2C, 0xE1, 0xF2, 0xD1, 0x17, 0x6B ), + BYTES_TO_T_UINT_8(0x96, 0xC2, 0x98, 0xD8, 0x45, 0x39, 0xA1, 0xF4), + BYTES_TO_T_UINT_8(0xA0, 0x33, 0xEB, 0x2D, 0x81, 0x7D, 0x03, 0x77), + BYTES_TO_T_UINT_8(0xF2, 0x40, 0xA4, 0x63, 0xE5, 0xE6, 0xBC, 0xF8), + BYTES_TO_T_UINT_8(0x47, 0x42, 0x2C, 0xE1, 0xF2, 0xD1, 0x17, 0x6B), }; static const mbedtls_mpi_uint secp256r1_gy[] = { - BYTES_TO_T_UINT_8( 0xF5, 0x51, 0xBF, 0x37, 0x68, 0x40, 0xB6, 0xCB ), - BYTES_TO_T_UINT_8( 0xCE, 0x5E, 0x31, 0x6B, 0x57, 0x33, 0xCE, 0x2B ), - BYTES_TO_T_UINT_8( 0x16, 0x9E, 0x0F, 0x7C, 0x4A, 0xEB, 0xE7, 0x8E ), - BYTES_TO_T_UINT_8( 0x9B, 0x7F, 0x1A, 0xFE, 0xE2, 0x42, 0xE3, 0x4F ), + BYTES_TO_T_UINT_8(0xF5, 0x51, 0xBF, 0x37, 0x68, 0x40, 0xB6, 0xCB), + BYTES_TO_T_UINT_8(0xCE, 0x5E, 0x31, 0x6B, 0x57, 0x33, 0xCE, 0x2B), + BYTES_TO_T_UINT_8(0x16, 0x9E, 0x0F, 0x7C, 0x4A, 0xEB, 0xE7, 0x8E), + BYTES_TO_T_UINT_8(0x9B, 0x7F, 0x1A, 0xFE, 0xE2, 0x42, 0xE3, 0x4F), }; { @@ -393,8 +389,8 @@ TEST_CASE("Test crypto lib ECC apis", "[wpa_crypto]") TEST_ASSERT_NOT_NULL(q); TEST_ASSERT_NOT_NULL(r); - mbedtls_mpi_init( &num ); - mbedtls_mpi_lset( &num, 3 ); + mbedtls_mpi_init(&num); + mbedtls_mpi_lset(&num, 3); ecp_mpi_load(& ((mbedtls_ecp_point *)p)->MBEDTLS_PRIVATE(X), secp256r1_gx, sizeof(secp256r1_gx)); ecp_mpi_load(& ((mbedtls_ecp_point *)p)->MBEDTLS_PRIVATE(Y), secp256r1_gy, sizeof(secp256r1_gy)); @@ -408,7 +404,7 @@ TEST_CASE("Test crypto lib ECC apis", "[wpa_crypto]") TEST_ASSERT(crypto_ec_point_cmp(e, q, r) == 0); - mbedtls_mpi_free( &num ); + mbedtls_mpi_free(&num); crypto_ec_point_deinit(p, 1); crypto_ec_point_deinit(q, 1); crypto_ec_point_deinit(r, 1); @@ -432,8 +428,8 @@ TEST_CASE("Test crypto lib ECC apis", "[wpa_crypto]") TEST_ASSERT_NOT_NULL(q); TEST_ASSERT_NOT_NULL(r); - mbedtls_mpi_init( &num ); - mbedtls_mpi_lset( &num, 100 ); + mbedtls_mpi_init(&num); + mbedtls_mpi_lset(&num, 100); ecp_mpi_load(& ((mbedtls_ecp_point *)p)->MBEDTLS_PRIVATE(X), secp256r1_gx, sizeof(secp256r1_gx)); ecp_mpi_load(& ((mbedtls_ecp_point *)p)->MBEDTLS_PRIVATE(Y), secp256r1_gy, sizeof(secp256r1_gy)); @@ -448,7 +444,7 @@ TEST_CASE("Test crypto lib ECC apis", "[wpa_crypto]") TEST_ASSERT(crypto_ec_point_is_at_infinity(e, r)); - mbedtls_mpi_free( &num ); + mbedtls_mpi_free(&num); crypto_ec_point_deinit(p, 1); crypto_ec_point_deinit(q, 1); crypto_ec_point_deinit(r, 1); @@ -468,8 +464,8 @@ TEST_CASE("Test crypto lib ECC apis", "[wpa_crypto]") TEST_ASSERT_NOT_NULL(p); TEST_ASSERT_NOT_NULL(q); - mbedtls_mpi_init( &num ); - mbedtls_mpi_lset( &num, 50 ); + mbedtls_mpi_init(&num); + mbedtls_mpi_lset(&num, 50); ecp_mpi_load(& ((mbedtls_ecp_point *)p)->MBEDTLS_PRIVATE(X), secp256r1_gx, sizeof(secp256r1_gx)); ecp_mpi_load(& ((mbedtls_ecp_point *)p)->MBEDTLS_PRIVATE(Y), secp256r1_gy, sizeof(secp256r1_gy)); @@ -483,8 +479,7 @@ TEST_CASE("Test crypto lib ECC apis", "[wpa_crypto]") TEST_ASSERT(crypto_ec_point_mul(e, p, (crypto_bignum *) &num, q) == 0); TEST_ASSERT(crypto_ec_point_is_on_curve(e, q)); - - mbedtls_mpi_free( &num ); + mbedtls_mpi_free(&num); crypto_ec_point_deinit(p, 1); crypto_ec_point_deinit(q, 1); crypto_ec_deinit(e); @@ -506,8 +501,8 @@ TEST_CASE("Test crypto lib ECC apis", "[wpa_crypto]") TEST_ASSERT_NOT_NULL(q); TEST_ASSERT_NOT_NULL(r); - mbedtls_mpi_init( &num ); - mbedtls_mpi_lset( &num, 50 ); + mbedtls_mpi_init(&num); + mbedtls_mpi_lset(&num, 50); ecp_mpi_load(& ((mbedtls_ecp_point *)p)->MBEDTLS_PRIVATE(X), secp256r1_gx, sizeof(secp256r1_gx)); ecp_mpi_load(& ((mbedtls_ecp_point *)p)->MBEDTLS_PRIVATE(Y), secp256r1_gy, sizeof(secp256r1_gy)); @@ -532,7 +527,7 @@ TEST_CASE("Test crypto lib ECC apis", "[wpa_crypto]") TEST_ASSERT(crypto_ec_point_add(e, q, r, r) == 0); TEST_ASSERT(crypto_ec_point_is_at_infinity(e, r)); - mbedtls_mpi_free( &num ); + mbedtls_mpi_free(&num); crypto_ec_point_deinit(p, 1); crypto_ec_point_deinit(q, 1); crypto_ec_point_deinit(r, 1); diff --git a/docs/en/api-reference/peripherals/lcd/i80_lcd.rst b/docs/en/api-reference/peripherals/lcd/i80_lcd.rst index 69df232a93..95fd79c993 100644 --- a/docs/en/api-reference/peripherals/lcd/i80_lcd.rst +++ b/docs/en/api-reference/peripherals/lcd/i80_lcd.rst @@ -29,8 +29,7 @@ I80 Interfaced LCD }, .bus_width = 8, .max_transfer_bytes = EXAMPLE_LCD_H_RES * 100 * sizeof(uint16_t), // transfer 100 lines of pixels (assume pixel is RGB565) at most in one transaction - .psram_trans_align = EXAMPLE_PSRAM_DATA_ALIGNMENT, - .sram_trans_align = 4, + .dma_burst_size = EXAMPLE_DMA_BURST_SIZE, }; ESP_ERROR_CHECK(esp_lcd_new_i80_bus(&bus_config, &i80_bus)); diff --git a/docs/en/api-reference/peripherals/lcd/rgb_lcd.rst b/docs/en/api-reference/peripherals/lcd/rgb_lcd.rst index 882dfb7406..1ecb0a0646 100644 --- a/docs/en/api-reference/peripherals/lcd/rgb_lcd.rst +++ b/docs/en/api-reference/peripherals/lcd/rgb_lcd.rst @@ -7,7 +7,7 @@ RGB LCD panel is allocated in one step: :cpp:func:`esp_lcd_new_rgb_panel`, with - :cpp:member:`esp_lcd_rgb_panel_config_t::data_width` set number of data lines used by the RGB interface. Currently, the supported value can be 8 or 16. - :cpp:member:`esp_lcd_rgb_panel_config_t::bits_per_pixel` set the number of bits per pixel. This is different from :cpp:member:`esp_lcd_rgb_panel_config_t::data_width`. By default, if you set this field to 0, the driver will automatically adjust the bpp to the :cpp:member:`esp_lcd_rgb_panel_config_t::data_width`. But in some cases, these two value must be different. For example, a Serial RGB interface LCD only needs ``8`` data lines, but the color width can reach to ``RGB888``, i.e., the :cpp:member:`esp_lcd_rgb_panel_config_t::bits_per_pixel` should be set to ``24``. - :cpp:member:`esp_lcd_rgb_panel_config_t::hsync_gpio_num`, :cpp:member:`esp_lcd_rgb_panel_config_t::vsync_gpio_num`, :cpp:member:`esp_lcd_rgb_panel_config_t::de_gpio_num`, :cpp:member:`esp_lcd_rgb_panel_config_t::pclk_gpio_num`, :cpp:member:`esp_lcd_rgb_panel_config_t::disp_gpio_num` and :cpp:member:`esp_lcd_rgb_panel_config_t::data_gpio_nums` are the GPIO pins used by the RGB LCD controller. If some of them are not used, please set it to `-1`. - - :cpp:member:`esp_lcd_rgb_panel_config_t::sram_trans_align` and :cpp:member:`esp_lcd_rgb_panel_config_t::psram_trans_align` set the alignment of the allocated frame buffer. Internally, the DMA transfer ability will adjust against these alignment values. A higher alignment value can lead to a bigger DMA burst size. Please note, the alignment value must be a power of 2. + - :cpp:member:`esp_lcd_rgb_panel_config_t::dma_burst_size` set the DMA transfer burst size, the value must be a power of 2. - :cpp:member:`esp_lcd_rgb_panel_config_t::bounce_buffer_size_px` set the size of bounce buffer. This is only necessary for a so-called "bounce buffer" mode. Please refer to :ref:`bounce_buffer_with_single_psram_frame_buffer` for more information. - :cpp:member:`esp_lcd_rgb_panel_config_t::timings` sets the LCD panel specific timing parameters. All required parameters are listed in the :cpp:type:`esp_lcd_rgb_timing_t`, including the LCD resolution and blanking porches. Please fill them according to the datasheet of your LCD. - :cpp:member:`esp_lcd_rgb_panel_config_t::fb_in_psram` sets whether to allocate the frame buffer from PSRAM or not. Please refer to :ref:`single_frame_buffer_in_psram` for more information. diff --git a/docs/en/api-reference/peripherals/spi_flash/spi_flash_concurrency.rst b/docs/en/api-reference/peripherals/spi_flash/spi_flash_concurrency.rst index b20dc9bb82..e8181236c6 100644 --- a/docs/en/api-reference/peripherals/spi_flash/spi_flash_concurrency.rst +++ b/docs/en/api-reference/peripherals/spi_flash/spi_flash_concurrency.rst @@ -77,12 +77,12 @@ Non-IRAM-Safe Interrupt Handlers If the ``ESP_INTR_FLAG_IRAM`` flag is not set when registering, the interrupt handler will not get executed when the caches are disabled. Once the caches are restored, the non-IRAM-safe interrupts will be re-enabled. After this moment, the interrupt handler will run normally again. This means that as long as caches are disabled, users will not see the corresponding hardware event happening. -.. only:: SOC_DMA_CAN_ACCESS_MSPI_MEM +.. only:: SOC_DMA_CAN_ACCESS_FLASH When DMA Read Data from Flash ----------------------------- - When DMA is reading data from Flash, erase/write operations from SPI1 take higher priority in hardware, resulting in unpredictable data read by DMA. It is recommended to stop DMA access to Flash before erasing or writing to it. If DMA cannot be stopped (for example, the LCD needs to continuously refresh image data stored in Flash), it is advisable to copy such data to PSRAM or internal SRAM. + When DMA is reading data from Flash, erase/write operations from SPI1 take higher priority in hardware, resulting in unpredictable data read by DMA if auto-suspend is not enabled. It is recommended to stop DMA access to Flash before erasing or writing to it. If DMA cannot be stopped (for example, the LCD needs to continuously refresh image data stored in Flash), it is advisable to copy such data to PSRAM or internal SRAM. .. only:: SOC_SPI_MEM_SUPPORT_AUTO_SUSPEND diff --git a/docs/en/api-reference/system/async_memcpy.rst b/docs/en/api-reference/system/async_memcpy.rst index d2ff7f2030..000e86d4a2 100644 --- a/docs/en/api-reference/system/async_memcpy.rst +++ b/docs/en/api-reference/system/async_memcpy.rst @@ -36,8 +36,7 @@ There are several ways to install the async memcpy driver, depending on the unde Driver configuration is described in :cpp:type:`async_memcpy_config_t`: * :cpp:member:`backlog`: This is used to configure the maximum number of memory copy transactions that can be queued up before the first one is completed. If this field is set to zero, then the default value 4 will be applied. -* :cpp:member:`sram_trans_align`: Declare SRAM alignment for both data address and copy size, set to zero if the data has no restriction in alignment. If set to a quadruple value (i.e., 4X), the driver will enable the burst mode internally, which is helpful for some performance related application. -* :cpp:member:`psram_trans_align`: Declare PSRAM alignment for both data address and copy size. User has to give it a valid value (only 16, 32, 64 are supported) if the destination of memcpy is located in PSRAM. The default alignment (i.e., 16) will be applied if it is set to zero. Internally, the driver configures the size of block used by DMA to access PSRAM, according to the alignment. +* :cpp:member:`dma_burst_size`: Set the burst size in a DMA burst transfer. * :cpp:member:`flags`: This is used to enable some special driver features. .. code-block:: c diff --git a/docs/zh_CN/api-reference/peripherals/spi_flash/spi_flash_concurrency.rst b/docs/zh_CN/api-reference/peripherals/spi_flash/spi_flash_concurrency.rst index 7e45a61373..75662fa991 100644 --- a/docs/zh_CN/api-reference/peripherals/spi_flash/spi_flash_concurrency.rst +++ b/docs/zh_CN/api-reference/peripherals/spi_flash/spi_flash_concurrency.rst @@ -77,12 +77,12 @@ IRAM 安全中断处理程序 如果在注册时没有设置 ``ESP_INTR_FLAG_IRAM`` 标志,当禁用 cache 时,将不会执行中断处理程序。一旦 cache 恢复,非 IRAM 安全的中断将重新启用,中断处理程序随即再次正常运行。这意味着,只要禁用了 cache,就不会发生相应的硬件事件。 -.. only:: SOC_DMA_CAN_ACCESS_MSPI_MEM +.. only:: SOC_DMA_CAN_ACCESS_FLASH 当 DMA 也可以访问 Flash 中的数据时 ---------------------------------- - 当 DMA 正在从 Flash 中读取数据时,来自 SPI1 的擦/写操作优先级会更高,导致 DMA 读到错误的数据。建议在擦写 Flash 之前先停止 DMA 对 Flash 的访问。如果 DMA 不可以停止,比如 LCD 需要持续刷新保存在 Flash 中的图像数据,建议将此类数据拷贝到 PSRAM 或者内部的 SRAM 中。 + 当 DMA 正在从 Flash 中读取数据时,来自 SPI1 的擦/写操作优先级会更高,如果 Flash 的 auto-suspend 功能没有开启,将会导致 DMA 读到错误的数据。建议在擦写 Flash 之前先停止 DMA 对 Flash 的访问。如果 DMA 不可以停止,比如 LCD 需要持续刷新保存在 Flash 中的图像数据,建议将此类数据拷贝到 PSRAM 或者内部的 SRAM 中。 .. only:: SOC_SPI_MEM_SUPPORT_AUTO_SUSPEND diff --git a/docs/zh_CN/api-reference/system/async_memcpy.rst b/docs/zh_CN/api-reference/system/async_memcpy.rst index fdd40d6bef..af3d772b85 100644 --- a/docs/zh_CN/api-reference/system/async_memcpy.rst +++ b/docs/zh_CN/api-reference/system/async_memcpy.rst @@ -36,8 +36,7 @@ DMA 允许多个内存复制请求在首个请求完成之前排队,即允许 在 :cpp:type:`async_memcpy_config_t` 中设置驱动配置: * :cpp:member:`backlog`:此项用于配置首个请求完成前可以排队的最大内存复制事务数量。如果将此字段设置为零,会应用默认值 4。 -* :cpp:member:`sram_trans_align`:声明 SRAM 中数据地址和复制大小的对齐方式,如果数据没有对齐限制,则设置为零。如果设置为四的倍数值(即 4X),驱动程序将内部启用突发模式,这有利于某些和性能相关的应用程序。 -* :cpp:member:`psram_trans_align`:声明 PSRAM 中数据地址和复制大小的对齐方式。如果 memcpy 的目标地址位于 PSRAM 中,用户必须给出一个有效值(只支持 16、32、64)。如果设置为零,会默认采用 16 位对齐。在内部,驱动程序会根据对齐方式来配置 DMA 访问 PSRAM 时所用的块大小。 +* :cpp:member:`dma_burst_size`:设置单次 DMA 传输中突发数据量的大小。 * :cpp:member:`flags`:此项可以启用一些特殊的驱动功能。 .. code-block:: c diff --git a/examples/peripherals/lcd/i80_controller/main/i80_controller_example_main.c b/examples/peripherals/lcd/i80_controller/main/i80_controller_example_main.c index 86e8ce2b41..146c28ea7f 100644 --- a/examples/peripherals/lcd/i80_controller/main/i80_controller_example_main.c +++ b/examples/peripherals/lcd/i80_controller/main/i80_controller_example_main.c @@ -93,8 +93,7 @@ static const char *TAG = "example"; #define EXAMPLE_LVGL_TASK_STACK_SIZE (4 * 1024) #define EXAMPLE_LVGL_TASK_PRIORITY 2 -// Supported alignment: 16, 32, 64. A higher alignment can enables higher burst transfer size, thus a higher i80 bus throughput. -#define EXAMPLE_PSRAM_DATA_ALIGNMENT 64 +#define EXAMPLE_DMA_BURST_SIZE 64 // 16, 32, 64. Higher burst size can improve the performance when the DMA buffer comes from PSRAM static SemaphoreHandle_t lvgl_mux = NULL; @@ -248,8 +247,7 @@ void example_init_i80_bus(esp_lcd_panel_io_handle_t *io_handle, void *user_ctx) }, .bus_width = CONFIG_EXAMPLE_LCD_I80_BUS_WIDTH, .max_transfer_bytes = EXAMPLE_LCD_H_RES * 100 * sizeof(uint16_t), - .psram_trans_align = EXAMPLE_PSRAM_DATA_ALIGNMENT, - .sram_trans_align = 4, + .dma_burst_size = EXAMPLE_DMA_BURST_SIZE, }; ESP_ERROR_CHECK(esp_lcd_new_i80_bus(&bus_config, &i80_bus)); diff --git a/examples/peripherals/lcd/rgb_panel/main/rgb_lcd_example_main.c b/examples/peripherals/lcd/rgb_panel/main/rgb_lcd_example_main.c index 8c8599a3d3..f388294a41 100644 --- a/examples/peripherals/lcd/rgb_panel/main/rgb_lcd_example_main.c +++ b/examples/peripherals/lcd/rgb_panel/main/rgb_lcd_example_main.c @@ -166,7 +166,7 @@ void app_main(void) esp_lcd_panel_handle_t panel_handle = NULL; esp_lcd_rgb_panel_config_t panel_config = { .data_width = 16, // RGB565 in parallel mode, thus 16bit in width - .psram_trans_align = 64, + .dma_burst_size = 64, .num_fbs = EXAMPLE_LCD_NUM_FB, #if CONFIG_EXAMPLE_USE_BOUNCE_BUFFER .bounce_buffer_size_px = 10 * EXAMPLE_LCD_H_RES,