diff --git a/components/esp_driver_dma/src/gdma.c b/components/esp_driver_dma/src/gdma.c index 58ff052844..488c38bf88 100644 --- a/components/esp_driver_dma/src/gdma.c +++ b/components/esp_driver_dma/src/gdma.c @@ -28,7 +28,6 @@ #include "gdma_priv.h" #include "esp_memory_utils.h" -#include "esp_flash_encrypt.h" #define GDMA_INVALID_PERIPH_TRIG (0x3F) #define SEARCH_REQUEST_RX_CHANNEL (1 << 0) @@ -435,12 +434,21 @@ esp_err_t gdma_config_transfer(gdma_channel_handle_t dma_chan, const gdma_transf #endif // if MSPI encryption is enabled, and DMA wants to read/write external memory - if (esp_flash_encryption_enabled()) { + if (efuse_hal_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 external memory +#if SOC_PSRAM_DMA_CAPABLE || SOC_DMA_CAN_ACCESS_FLASH + uint32_t enc_mem_alignment = GDMA_LL_GET(ACCESS_ENCRYPTION_MEM_ALIGNMENT); + // when DMA access the encrypted external memory, extra alignment is needed for external memory if (config->access_ext_mem) { - ext_mem_alignment = MAX(ext_mem_alignment, GDMA_ACCESS_ENCRYPTION_MEM_ALIGNMENT); + ext_mem_alignment = MAX(ext_mem_alignment, enc_mem_alignment); } +#if SOC_HAS(AXI_GDMA) + if (group->bus_id == SOC_GDMA_BUS_AXI) { + // once AXI-GDMA enables access to encrypted memory, internal memory also needs to align + int_mem_alignment = MAX(int_mem_alignment, enc_mem_alignment); + } +#endif // SOC_HAS(AXI_GDMA) +#endif // SOC_PSRAM_DMA_CAPABLE } else { gdma_hal_enable_access_encrypt_mem(hal, pair->pair_id, dma_chan->direction, false); } diff --git a/components/esp_driver_dma/src/gdma_link.c b/components/esp_driver_dma/src/gdma_link.c index af699f83e7..107c430d32 100644 --- a/components/esp_driver_dma/src/gdma_link.c +++ b/components/esp_driver_dma/src/gdma_link.c @@ -16,6 +16,7 @@ #include "esp_heap_caps.h" #include "esp_private/gdma_link.h" #include "hal/cache_hal.h" +#include "hal/efuse_hal.h" #include "hal/cache_ll.h" #include "esp_cache.h" @@ -79,9 +80,16 @@ esp_err_t gdma_new_link_list(const gdma_link_list_config_t *config, gdma_link_li // guard against overflow when calculating total bytes for descriptors ESP_GOTO_ON_FALSE(num_items <= SIZE_MAX / item_size, ESP_ERR_INVALID_SIZE, err, TAG, "list too big"); + bool items_in_ext_mem = config->flags.items_in_ext_mem; uint32_t list_items_mem_caps = MALLOC_CAP_8BIT | MALLOC_CAP_DMA; - if (config->flags.items_in_ext_mem) { - list_items_mem_caps |= MALLOC_CAP_SPIRAM; + if (items_in_ext_mem) { + if (efuse_hal_flash_encryption_enabled()) { + items_in_ext_mem = false; + list_items_mem_caps |= MALLOC_CAP_INTERNAL; + ESP_LOGW(TAG, "DMA linked list items cannot be placed in PSRAM when external memory encryption is enabled, using internal memory instead"); + } else { + list_items_mem_caps |= MALLOC_CAP_SPIRAM; + } } else { list_items_mem_caps |= MALLOC_CAP_INTERNAL; } @@ -90,7 +98,7 @@ esp_err_t gdma_new_link_list(const gdma_link_list_config_t *config, gdma_link_li // do memory sync if the list items are in the cache uint32_t data_cache_line_size = 0; - if (config->flags.items_in_ext_mem) { + if (items_in_ext_mem) { data_cache_line_size = cache_hal_get_cache_line_size(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_DATA); } else { data_cache_line_size = cache_hal_get_cache_line_size(CACHE_LL_LEVEL_INT_MEM, CACHE_TYPE_DATA); @@ -178,6 +186,10 @@ esp_err_t gdma_link_mount_buffers(gdma_link_list_handle_t list, int start_item_i size_t max_buffer_mount_length = ALIGN_DOWN(GDMA_MAX_BUFFER_SIZE_PER_LINK_ITEM, buffer_alignment); if (!config->flags.bypass_buffer_align_check) { ESP_RETURN_ON_FALSE_ISR(((uintptr_t)buf & (buffer_alignment - 1)) == 0, ESP_ERR_INVALID_ARG, TAG, "buf misalign idx=%"PRIu32" align=%"PRIu32, bi, buffer_alignment); + if (efuse_hal_flash_encryption_enabled()) { + // buffer size must be aligned to the encryption alignment which should be provided by the upper buffer_alignment + ESP_RETURN_ON_FALSE_ISR((len & (buffer_alignment - 1)) == 0, ESP_ERR_INVALID_ARG, TAG, "buf len misalign idx=%"PRIu32" len=%"PRIu32" align=%"PRIu32"", bi, len, buffer_alignment); + } } size_t num_items_need = (len + max_buffer_mount_length - 1) / max_buffer_mount_length; ESP_RETURN_ON_FALSE_ISR(num_items_need <= remaining, ESP_ERR_INVALID_ARG, TAG, diff --git a/components/esp_driver_dma/src/gdma_priv.h b/components/esp_driver_dma/src/gdma_priv.h index ecaf09a178..fcc8b677f8 100644 --- a/components/esp_driver_dma/src/gdma_priv.h +++ b/components/esp_driver_dma/src/gdma_priv.h @@ -30,6 +30,7 @@ #include "hal/gdma_hal_ahb.h" #include "hal/gdma_hal_axi.h" #include "hal/gdma_periph.h" +#include "hal/efuse_hal.h" #include "soc/periph_defs.h" #include "esp_private/gdma.h" #include "esp_private/periph_ctrl.h" @@ -42,8 +43,6 @@ #define GDMA_MEM_ALLOC_CAPS MALLOC_CAP_DEFAULT #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 diff --git a/components/esp_driver_dma/test_apps/dma/main/test_async_memcpy.c b/components/esp_driver_dma/test_apps/dma/main/test_async_memcpy.c index 2e4e5f570c..720cac7fd5 100644 --- a/components/esp_driver_dma/test_apps/dma/main/test_async_memcpy.c +++ b/components/esp_driver_dma/test_apps/dma/main/test_async_memcpy.c @@ -16,6 +16,8 @@ #include "freertos/semphr.h" #include "ccomp_timer.h" #include "esp_async_memcpy.h" +#include "hal/efuse_hal.h" + #if SOC_GDMA_SUPPORTED #include "hal/gdma_ll.h" #endif @@ -152,17 +154,19 @@ static bool test_async_memcpy_cb_v1(async_memcpy_handle_t mcp_hdl, async_memcpy_ static void test_memory_copy_blocking(async_memcpy_handle_t driver) { SemaphoreHandle_t sem = xSemaphoreCreateBinary(); - const uint32_t test_buffer_size[] = {256, 512, 1024, 2048, 4096, 5012}; + const uint32_t test_buffer_size[] = {256, 512, 1024, 2048, 4096, 5008}; memcpy_testbench_context_t test_context = { - .align = 4, + .align = 16, }; for (int i = 0; i < sizeof(test_buffer_size) / sizeof(test_buffer_size[0]); i++) { // Test different align edge for (int off = 0; off < 4; off++) { test_context.buffer_size = test_buffer_size[i]; test_context.seed = i; - test_context.src_offset = off; - test_context.dst_offset = off; + if (!efuse_hal_flash_encryption_enabled()) { + test_context.src_offset = off; + test_context.dst_offset = off; + } async_memcpy_setup_testbench(&test_context); TEST_ESP_OK(esp_async_memcpy(driver, test_context.to_addr, test_context.from_addr, test_context.copy_size, test_async_memcpy_cb_v1, sem)); @@ -239,6 +243,10 @@ TEST_CASE("memory copy with dest address unaligned", "[async mcp]") }; [[maybe_unused]] async_memcpy_handle_t driver = NULL; + if (efuse_hal_flash_encryption_enabled()) { + TEST_PASS_MESSAGE("Flash encryption is enabled, skip this test"); + } + #if SOC_CP_DMA_SUPPORTED printf("Testing memcpy by CP DMA\r\n"); TEST_ESP_OK(esp_async_memcpy_install_cpdma(&driver_config, &driver)); @@ -459,7 +467,7 @@ TEST_CASE("GDMA M2M Weighted Arbitration Test SRAM->SRAM", "[GDMA][M2M][async mc { async_memcpy_config_t driver_config = { .backlog = TEST_ASYNC_MEMCPY_BENCH_COUNTS, - .dma_burst_size = 64, + .dma_burst_size = 32, }; async_memcpy_handle_t driver[2] = {NULL}; diff --git a/components/esp_driver_dma/test_apps/dma/main/test_dw_gdma.c b/components/esp_driver_dma/test_apps/dma/main/test_dw_gdma.c index 45eeb11c32..37999612cb 100644 --- a/components/esp_driver_dma/test_apps/dma/main/test_dw_gdma.c +++ b/components/esp_driver_dma/test_apps/dma/main/test_dw_gdma.c @@ -11,6 +11,7 @@ #include "unity.h" #include "esp_private/dw_gdma.h" #include "hal/dw_gdma_ll.h" +#include "hal/efuse_hal.h" #include "esp_cache.h" #include "esp_private/esp_cache_private.h" @@ -540,6 +541,9 @@ TEST_CASE("DW_GDMA M2M Test: memory set with fixed address", "[DW_GDMA]") size_t int_mem_alignment = 0; TEST_ESP_OK(esp_cache_get_alignment(MALLOC_CAP_SPIRAM, &ext_mem_alignment)); TEST_ESP_OK(esp_cache_get_alignment(0, &int_mem_alignment)); + if (efuse_hal_flash_encryption_enabled()) { + TEST_PASS_MESSAGE("Flash encryption is enabled, skip this test"); + } uint8_t *src_buf = heap_caps_aligned_calloc(ext_mem_alignment, 1, 256, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); uint8_t *dst_buf = heap_caps_aligned_calloc(int_mem_alignment, 1, 256, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); TEST_ASSERT_NOT_NULL(src_buf); diff --git a/components/esp_driver_dma/test_apps/dma/main/test_gdma.c b/components/esp_driver_dma/test_apps/dma/main/test_gdma.c index 28f94a6342..0e6b367f1e 100644 --- a/components/esp_driver_dma/test_apps/dma/main/test_gdma.c +++ b/components/esp_driver_dma/test_apps/dma/main/test_gdma.c @@ -20,6 +20,7 @@ #include "hal/gdma_ll.h" #include "hal/cache_ll.h" #include "hal/cache_hal.h" +#include "hal/efuse_hal.h" #include "esp_cache.h" #include "esp_memory_utils.h" #include "gdma_test_utils.h" @@ -149,7 +150,8 @@ TEST_CASE("GDMA channel allocation", "[GDMA]") } static void test_gdma_config_link_list(gdma_channel_handle_t tx_chan, gdma_channel_handle_t rx_chan, - gdma_link_list_handle_t *tx_link_list, gdma_link_list_handle_t *rx_link_list, bool dma_link_in_ext_mem) + gdma_link_list_handle_t *tx_link_list, gdma_link_list_handle_t *rx_link_list, + size_t burst_size, bool dma_link_in_ext_mem) { gdma_strategy_config_t strategy = { @@ -159,6 +161,15 @@ static void test_gdma_config_link_list(gdma_channel_handle_t tx_chan, gdma_chann TEST_ESP_OK(gdma_apply_strategy(tx_chan, &strategy)); TEST_ESP_OK(gdma_apply_strategy(rx_chan, &strategy)); + gdma_transfer_config_t transfer_cfg = { + .max_data_burst_size = burst_size, +#if SOC_DMA_CAN_ACCESS_FLASH + .access_ext_mem = true, +#endif + }; + TEST_ESP_OK(gdma_config_transfer(tx_chan, &transfer_cfg)); + TEST_ESP_OK(gdma_config_transfer(rx_chan, &transfer_cfg)); + gdma_trigger_t m2m_trigger = GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_M2M, 0); // get a free DMA trigger ID for memory copy uint32_t free_m2m_id_mask = 0; @@ -207,16 +218,24 @@ static void test_gdma_m2m_transaction(gdma_channel_handle_t tx_chan, gdma_channe TEST_ASSERT_NOT_NULL(done_sem); TEST_ESP_OK(gdma_register_rx_event_callbacks(rx_chan, &rx_cbs, done_sem)); + if (efuse_hal_flash_encryption_enabled()) { + dma_link_in_ext_mem = false; + } + gdma_link_list_handle_t tx_link_list = NULL; gdma_link_list_handle_t rx_link_list = NULL; - test_gdma_config_link_list(tx_chan, rx_chan, &tx_link_list, &rx_link_list, dma_link_in_ext_mem); + test_gdma_config_link_list(tx_chan, rx_chan, &tx_link_list, &rx_link_list, 16, dma_link_in_ext_mem); + + size_t int_mem_alignment = 0; + size_t ext_mem_alignment = 0; + TEST_ESP_OK(gdma_get_alignment_constraints(tx_chan, &int_mem_alignment, &ext_mem_alignment)); // allocate the source buffer from SRAM - uint8_t *src_data = heap_caps_calloc(1, 128, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); + uint8_t *src_data = heap_caps_aligned_calloc(int_mem_alignment, 1, 128, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); TEST_ASSERT_NOT_NULL(src_data); // allocate the destination buffer from SRAM - uint8_t *dst_data = heap_caps_calloc(1, 256, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); + uint8_t *dst_data = heap_caps_aligned_calloc(int_mem_alignment, 1, 256, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); TEST_ASSERT_NOT_NULL(dst_data); // prepare the source data @@ -229,7 +248,7 @@ static void test_gdma_m2m_transaction(gdma_channel_handle_t tx_chan, gdma_channe } // test DMA can read data from main flash #if SOC_DMA_CAN_ACCESS_FLASH - const char *src_string = "GDMA can read data from MSPI Flash"; + static const char src_string[] __attribute__((aligned(GDMA_LL_GET(ACCESS_ENCRYPTION_MEM_ALIGNMENT)))) = "GDMA can read MSPI Flash data!!!"; size_t src_string_len = strlen(src_string); TEST_ASSERT_TRUE(esp_ptr_in_drom(src_string)); @@ -244,12 +263,12 @@ static void test_gdma_m2m_transaction(gdma_channel_handle_t tx_chan, gdma_channe gdma_buffer_mount_config_t tx_buf_mount_config[] = { [0] = { .buffer = src_data, - .buffer_alignment = 1, + .buffer_alignment = int_mem_alignment, .length = 64, }, [1] = { .buffer = src_data + 64, - .buffer_alignment = 1, + .buffer_alignment = int_mem_alignment, .length = 64, #if !SOC_DMA_CAN_ACCESS_FLASH .flags = { @@ -261,7 +280,7 @@ static void test_gdma_m2m_transaction(gdma_channel_handle_t tx_chan, gdma_channe #if SOC_DMA_CAN_ACCESS_FLASH [2] = { .buffer = (void *)src_string, - .buffer_alignment = 1, + .buffer_alignment = ext_mem_alignment, .length = src_string_len, .flags = { .mark_eof = true, @@ -369,6 +388,8 @@ static void test_gdma_m2m_unaligned_buffer_test(uint8_t *dst_data, uint8_t *src_ { TEST_ASSERT_NOT_NULL(src_data); TEST_ASSERT_NOT_NULL(dst_data); + memset(src_data, 0, data_length + offset_len); + memset(dst_data, 0, data_length + offset_len); gdma_channel_handle_t tx_chan = NULL; gdma_channel_handle_t rx_chan = NULL; gdma_channel_alloc_config_t chan_alloc_config = {}; @@ -377,7 +398,10 @@ static void test_gdma_m2m_unaligned_buffer_test(uint8_t *dst_data, uint8_t *src_ gdma_link_list_handle_t tx_link_list = NULL; gdma_link_list_handle_t rx_link_list = NULL; - test_gdma_config_link_list(tx_chan, rx_chan, &tx_link_list, &rx_link_list, false); + test_gdma_config_link_list(tx_chan, rx_chan, &tx_link_list, &rx_link_list, 0, false); + + size_t rx_mem_alignment = 0; + TEST_ESP_OK(gdma_get_alignment_constraints(rx_chan, &rx_mem_alignment, NULL)); // prepare the source data for (int i = 0; i < data_length; i++) { @@ -407,7 +431,7 @@ static void test_gdma_m2m_unaligned_buffer_test(uint8_t *dst_data, uint8_t *src_ TEST_ESP_OK(esp_dma_split_rx_buffer_to_cache_aligned(dst_data + offset_len, data_length, &align_array, &stash_buffer)); for (int i = 0; i < 3; i++) { rx_aligned_buf_mount_config[i].buffer = align_array.aligned_buffer[i].aligned_buffer; - rx_aligned_buf_mount_config[i].buffer_alignment = sram_alignment; + rx_aligned_buf_mount_config[i].buffer_alignment = MAX(sram_alignment, rx_mem_alignment); rx_aligned_buf_mount_config[i].length = align_array.aligned_buffer[i].length; } TEST_ESP_OK(gdma_link_mount_buffers(rx_link_list, 0, rx_aligned_buf_mount_config, 3, NULL)); @@ -443,6 +467,10 @@ static void test_gdma_m2m_unaligned_buffer_test(uint8_t *dst_data, uint8_t *src_ TEST_CASE("GDMA M2M Unaligned RX Buffer Test", "[GDMA][M2M]") { + if (efuse_hal_flash_encryption_enabled()) { + TEST_PASS_MESSAGE("Flash encryption is enabled, skip this test"); + } + uint8_t *sbuf = heap_caps_aligned_calloc(64, 1, 10240, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); uint8_t *dbuf = heap_caps_aligned_calloc(64, 1, 10240, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); diff --git a/components/esp_driver_dma/test_apps/dma/main/test_gdma_crc.c b/components/esp_driver_dma/test_apps/dma/main/test_gdma_crc.c index ce56c4e725..9ab75ac552 100644 --- a/components/esp_driver_dma/test_apps/dma/main/test_gdma_crc.c +++ b/components/esp_driver_dma/test_apps/dma/main/test_gdma_crc.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -17,6 +17,7 @@ #include "soc/soc_caps.h" #include "hal/cache_hal.h" #include "hal/cache_ll.h" +#include "hal/gdma_ll.h" #include "esp_cache.h" typedef struct { @@ -32,37 +33,47 @@ static test_crc_case_t crc_test_cases[] = { .crc_bit_width = 8, .init_value = 0x00, .poly_hex = 0x07, - .expected_result = 0xC6, + .expected_result = 0xB8, }, [1] = { .crc_bit_width = 8, .init_value = 0x00, .poly_hex = 0x07, .reverse_data_mask = true, // refin = true - .expected_result = 0xDE, + .expected_result = 0xF0, }, // CRC16, x^16+x^12+x^5+1 [2] = { .crc_bit_width = 16, .init_value = 0xFFFF, .poly_hex = 0x1021, - .expected_result = 0x5289, + .expected_result = 0xA9B2, }, // CRC32, x32+x26+x23+x22+x16+x12+x11+x10+x8+x7+x5+x4+x2+x+1 [3] = { .crc_bit_width = 32, .init_value = 0xFFFFFFFF, .poly_hex = 0x04C11DB7, - .expected_result = 0x63B3E283, + .expected_result = 0x692F6C7E, } }; // CRC online: https://www.lddgo.net/en/encrypt/crc static void test_gdma_crc_calculation(gdma_channel_handle_t tx_chan, int test_num_crc_algorithm) { + // Note, burst size should be at least 16 when accessing encrypted external memory + gdma_transfer_config_t transfer_cfg = { + .max_data_burst_size = 16, + .access_ext_mem = true, + }; + TEST_ESP_OK(gdma_config_transfer(tx_chan, &transfer_cfg)); + uint32_t crc_result = 0; - const char *test_input_string = "Share::Connect::Innovate"; + + static const char test_input_string[] __attribute__((aligned(GDMA_LL_GET(ACCESS_ENCRYPTION_MEM_ALIGNMENT)))) = "GDMACRC Share::Connect::Innovate"; size_t input_data_size = strlen(test_input_string); + + TEST_ASSERT_EQUAL((uintptr_t)test_input_string % GDMA_LL_GET(ACCESS_ENCRYPTION_MEM_ALIGNMENT), 0); // this test case also test the GDMA can fetch data from MSPI Flash TEST_ASSERT_TRUE(esp_ptr_in_drom(test_input_string)); printf("Calculate CRC value for string: \"%s\"\r\n", test_input_string); diff --git a/components/esp_driver_dma/test_apps/dma/pytest_dma.py b/components/esp_driver_dma/test_apps/dma/pytest_dma.py index a009ce6d50..a684d7fdc5 100644 --- a/components/esp_driver_dma/test_apps/dma/pytest_dma.py +++ b/components/esp_driver_dma/test_apps/dma/pytest_dma.py @@ -47,3 +47,29 @@ def test_dma_psram(dut: Dut) -> None: @idf_parametrize('target', soc_filtered_targets('SOC_GDMA_SUPPORT_WEIGHTED_ARBITRATION == 1'), indirect=['target']) def test_dma_weighted_arbitration(dut: Dut) -> None: dut.run_all_single_board_cases(reset=True) + + +@pytest.mark.flash_encryption +@pytest.mark.parametrize( + 'config', + [ + 'ext_mem_encryption', + ], + indirect=True, +) +@idf_parametrize('target', ['esp32p4', 'esp32c5'], indirect=['target']) +def test_dma_ext_mem_encryption(dut: Dut) -> None: + dut.run_all_single_board_cases(reset=True) + + +@pytest.mark.flash_encryption_f4r8 +@pytest.mark.parametrize( + 'config', + [ + 'ext_mem_encryption', + ], + indirect=True, +) +@idf_parametrize('target', ['esp32s3'], indirect=['target']) +def test_dma_ext_mem_encryption_s3_f4r8(dut: Dut) -> None: + dut.run_all_single_board_cases(reset=True) diff --git a/components/esp_driver_dma/test_apps/dma/sdkconfig.ci.ext_mem_encryption b/components/esp_driver_dma/test_apps/dma/sdkconfig.ci.ext_mem_encryption new file mode 100644 index 0000000000..5be9651c38 --- /dev/null +++ b/components/esp_driver_dma/test_apps/dma/sdkconfig.ci.ext_mem_encryption @@ -0,0 +1,9 @@ +CONFIG_PARTITION_TABLE_OFFSET=0x9000 +CONFIG_SECURE_FLASH_ENC_ENABLED=y +CONFIG_SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT=y +CONFIG_SECURE_BOOT_ALLOW_ROM_BASIC=y +CONFIG_SECURE_BOOT_ALLOW_JTAG=y +CONFIG_SECURE_FLASH_UART_BOOTLOADER_ALLOW_ENC=y +CONFIG_SECURE_FLASH_UART_BOOTLOADER_ALLOW_DEC=y +CONFIG_SECURE_FLASH_UART_BOOTLOADER_ALLOW_CACHE=y +CONFIG_SECURE_FLASH_REQUIRE_ALREADY_ENABLED=y diff --git a/components/esp_driver_dma/test_apps/dma/sdkconfig.ci.weighted_arbitration b/components/esp_driver_dma/test_apps/dma/sdkconfig.ci.weighted_arbitration new file mode 100644 index 0000000000..2bf15839c9 --- /dev/null +++ b/components/esp_driver_dma/test_apps/dma/sdkconfig.ci.weighted_arbitration @@ -0,0 +1,2 @@ +CONFIG_GDMA_ENABLE_WEIGHTED_ARBITRATION=y +CONFIG_IDF_EXPERIMENTAL_FEATURES=y diff --git a/components/esp_hal_dma/esp32c5/include/hal/gdma_ll.h b/components/esp_hal_dma/esp32c5/include/hal/gdma_ll.h index 9a759a5d57..5b098afb30 100644 --- a/components/esp_hal_dma/esp32c5/include/hal/gdma_ll.h +++ b/components/esp_hal_dma/esp32c5/include/hal/gdma_ll.h @@ -17,6 +17,7 @@ #define GDMA_LL_AHB_BURST_SIZE_ADJUSTABLE 1 // AHB GDMA supports adjustable burst size #define GDMA_LL_MAX_BURST_SIZE_PSRAM 32 // PSRAM controller doesn't support burst access with size > 32 bytes +#define GDMA_LL_ACCESS_ENCRYPTION_MEM_ALIGNMENT 16 // The alignment of the memory and size when DMA accesses encrypted memory #ifdef __cplusplus extern "C" { diff --git a/components/esp_hal_dma/esp32c61/include/hal/gdma_ll.h b/components/esp_hal_dma/esp32c61/include/hal/gdma_ll.h index 9a759a5d57..5b098afb30 100644 --- a/components/esp_hal_dma/esp32c61/include/hal/gdma_ll.h +++ b/components/esp_hal_dma/esp32c61/include/hal/gdma_ll.h @@ -17,6 +17,7 @@ #define GDMA_LL_AHB_BURST_SIZE_ADJUSTABLE 1 // AHB GDMA supports adjustable burst size #define GDMA_LL_MAX_BURST_SIZE_PSRAM 32 // PSRAM controller doesn't support burst access with size > 32 bytes +#define GDMA_LL_ACCESS_ENCRYPTION_MEM_ALIGNMENT 16 // The alignment of the memory and size when DMA accesses encrypted memory #ifdef __cplusplus extern "C" { diff --git a/components/esp_hal_dma/esp32h21/include/hal/gdma_ll.h b/components/esp_hal_dma/esp32h21/include/hal/gdma_ll.h index 23fdc99fb8..e8a391d29b 100644 --- a/components/esp_hal_dma/esp32h21/include/hal/gdma_ll.h +++ b/components/esp_hal_dma/esp32h21/include/hal/gdma_ll.h @@ -53,6 +53,7 @@ extern "C" { #define GDMA_LL_AHB_DESC_ALIGNMENT 4 #define GDMA_LL_AHB_RX_BURST_NEEDS_ALIGNMENT 1 +#define GDMA_LL_ACCESS_ENCRYPTION_MEM_ALIGNMENT 16 // The alignment of the memory and size when DMA accesses encrypted memory #define GDMA_LL_AHB_M2M_CAPABLE_PAIR_MASK 0x07 // pair 0,1,2 are M2M capable diff --git a/components/esp_hal_dma/esp32h4/include/hal/gdma_ll.h b/components/esp_hal_dma/esp32h4/include/hal/gdma_ll.h index f9c7127989..38e434b991 100644 --- a/components/esp_hal_dma/esp32h4/include/hal/gdma_ll.h +++ b/components/esp_hal_dma/esp32h4/include/hal/gdma_ll.h @@ -17,6 +17,7 @@ #define GDMA_LL_AHB_BURST_SIZE_ADJUSTABLE 1 // AHB GDMA supports adjustable burst size #define GDMA_LL_MAX_BURST_SIZE_PSRAM 64 // PSRAM support INCR16 +#define GDMA_LL_ACCESS_ENCRYPTION_MEM_ALIGNMENT 16 // The alignment of the memory and size when DMA accesses encrypted memory #ifdef __cplusplus extern "C" { diff --git a/components/esp_hal_dma/esp32p4/include/hal/gdma_ll.h b/components/esp_hal_dma/esp32p4/include/hal/gdma_ll.h index db94709822..a2feabafee 100644 --- a/components/esp_hal_dma/esp32p4/include/hal/gdma_ll.h +++ b/components/esp_hal_dma/esp32p4/include/hal/gdma_ll.h @@ -58,6 +58,7 @@ #define GDMA_LL_AHB_DESC_ALIGNMENT 4 #define GDMA_LL_AXI_DESC_ALIGNMENT 8 #define GDMA_LL_MAX_BURST_SIZE_PSRAM 128 // PSRAM controller doesn't support burst access with size > 128 bytes +#define GDMA_LL_ACCESS_ENCRYPTION_MEM_ALIGNMENT 16 // The alignment of the memory and size when DMA accesses encrypted memory #if HAL_CONFIG(CHIP_SUPPORT_MIN_REV) >= 300 #define GDMA_LL_AHB_BURST_SIZE_ADJUSTABLE 1 // AHB GDMA supports adjustable burst size diff --git a/components/esp_hal_dma/esp32s3/include/hal/gdma_ll.h b/components/esp_hal_dma/esp32s3/include/hal/gdma_ll.h index b3680dda2f..1c4936e273 100644 --- a/components/esp_hal_dma/esp32s3/include/hal/gdma_ll.h +++ b/components/esp_hal_dma/esp32s3/include/hal/gdma_ll.h @@ -71,6 +71,7 @@ extern "C" { #define GDMA_LL_AHB_BURST_SIZE_ADJUSTABLE 1 // AHB GDMA supports adjustable burst size #define GDMA_LL_AHB_RX_BURST_NEEDS_ALIGNMENT 1 #define GDMA_LL_MAX_BURST_SIZE_PSRAM 64 // PSRAM controller doesn't support burst access with size > 64 bytes +#define GDMA_LL_ACCESS_ENCRYPTION_MEM_ALIGNMENT 16 // The alignment of the memory and size when DMA accesses encrypted memory #define GDMA_LL_AHB_M2M_CAPABLE_PAIR_MASK 0x1F // pair 0,1,2,3,4 are M2M capable diff --git a/components/esp_mm/heap_align_hw.c b/components/esp_mm/heap_align_hw.c index 74afffbee9..294fb5a2d7 100644 --- a/components/esp_mm/heap_align_hw.c +++ b/components/esp_mm/heap_align_hw.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2019-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2019-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -9,9 +9,11 @@ #include "sdkconfig.h" #include "esp_heap_caps.h" #include "esp_private/esp_cache_private.h" +#include "esp_private/gdma.h" #include "soc/soc_caps.h" -#if SOC_GDMA_SUPPORTED +#if SOC_HAS(GDMA) #include "hal/gdma_ll.h" +#include "hal/efuse_hal.h" #endif #if CONFIG_HEAP_PLACE_FUNCTION_INTO_FLASH @@ -80,6 +82,12 @@ HEAP_IRAM_ATTR void esp_heap_adjust_alignment_to_hw(size_t *p_alignment, size_t } #endif +#if SOC_HAS(GDMA) && (SOC_PSRAM_DMA_CAPABLE || SOC_DMA_CAN_ACCESS_FLASH) + if ((caps & MALLOC_CAP_DMA) && efuse_hal_flash_encryption_enabled()) { + alignment = (alignment > GDMA_LL_GET(ACCESS_ENCRYPTION_MEM_ALIGNMENT)) ? alignment : GDMA_LL_GET(ACCESS_ENCRYPTION_MEM_ALIGNMENT); + } +#endif + // Align up `size` to resulting alignment as well. size = (size + alignment - 1) & (~(alignment - 1)); diff --git a/docs/en/api-reference/peripherals/lcd/dsi_lcd.rst b/docs/en/api-reference/peripherals/lcd/dsi_lcd.rst index a92defdecc..93a7a513c3 100644 --- a/docs/en/api-reference/peripherals/lcd/dsi_lcd.rst +++ b/docs/en/api-reference/peripherals/lcd/dsi_lcd.rst @@ -92,6 +92,10 @@ MIPI DSI Interfaced LCD ESP_ERROR_CHECK(esp_lcd_dpi_panel_enable_dma2d(mipi_dpi_panel)); + .. note:: + + Due to hardware limitation, if external memory encryption is enabled, DMA2D can only access address and length that are aligned to 16 bytes. Unless you can ensure that your draw buffer's address and length are aligned to 16 bytes, it is not recommended to use DMA2D to draw bitmap. + If you need more advanced applications, you can add a custom hook for draw bitmap, such as using PPA to implement rotation, scaling, etc. .. code-block:: c diff --git a/docs/zh_CN/api-reference/peripherals/lcd/dsi_lcd.rst b/docs/zh_CN/api-reference/peripherals/lcd/dsi_lcd.rst index 41964aaf5f..32694f3bb7 100644 --- a/docs/zh_CN/api-reference/peripherals/lcd/dsi_lcd.rst +++ b/docs/zh_CN/api-reference/peripherals/lcd/dsi_lcd.rst @@ -92,6 +92,10 @@ MIPI DSI 接口的 LCD ESP_ERROR_CHECK(esp_lcd_dpi_panel_enable_dma2d(mipi_dpi_panel)); + .. note:: + + 由于硬件限制,如果启用了外部存储加密,则 DMA2D 只能访问地址和长度都对齐到 16 字节的地址空间。除非你能确保你的绘制 buffer 的地址和长度都对齐到 16 字节, 否则不建议使用 DMA2D 来绘制位图。 + 若需更高级的应用,用户可为绘制位图添加自定义钩子,例如通过 PPA 实现旋转、缩放等操作。 .. code-block:: c