diff --git a/components/esp_driver_dma/include/esp_private/dma2d.h b/components/esp_driver_dma/include/esp_private/dma2d.h index c508174298..9c488ef7a8 100644 --- a/components/esp_driver_dma/include/esp_private/dma2d.h +++ b/components/esp_driver_dma/include/esp_private/dma2d.h @@ -228,7 +228,8 @@ esp_err_t dma2d_apply_strategy(dma2d_channel_handle_t dma2d_chan, const dma2d_st */ typedef struct { bool desc_burst_en; /*!< If set / clear, DMA channel enables / disables burst reading descriptor link */ - dma2d_data_burst_length_t data_burst_length; /*!< Configure the DMA channel burst reading data length */ + uint32_t data_burst_length; /*!< Configure the DMA channel burst reading data length */ + bool access_ext_mem; /*!< Set this bit if the DMA transfer may access external memory */ dma2d_macro_block_size_t mb_size; /*!< Configure the DMA channel macro block size (only useful in DMA2D_DESCRIPTOR_BLOCK_RW_MODE_MULTIPLE mode) */ } dma2d_transfer_ability_t; diff --git a/components/esp_driver_dma/src/dma2d.c b/components/esp_driver_dma/src/dma2d.c index bcb4d470f6..2020a19ac5 100644 --- a/components/esp_driver_dma/src/dma2d.c +++ b/components/esp_driver_dma/src/dma2d.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -26,6 +26,7 @@ #include "hal/dma2d_periph.h" #include "soc/soc_caps.h" #include "esp_bit_defs.h" +#include "esp_efuse.h" /** * The 2D-DMA driver is designed with a pool & client model + queue design pattern. @@ -584,7 +585,7 @@ esp_err_t dma2d_connect(dma2d_channel_handle_t dma2d_chan, const dma2d_trigger_t dma2d_ll_tx_enable_auto_write_back(group->hal.dev, channel_id, false); dma2d_ll_tx_enable_eof_mode(group->hal.dev, channel_id, true); dma2d_ll_tx_enable_descriptor_burst(group->hal.dev, channel_id, false); - dma2d_ll_tx_set_data_burst_length(group->hal.dev, channel_id, DMA2D_DATA_BURST_LENGTH_128); + dma2d_ll_tx_set_data_burst_length(group->hal.dev, channel_id, 128); dma2d_ll_tx_enable_page_bound_wrap(group->hal.dev, channel_id, true); dma2d_ll_tx_set_macro_block_size(group->hal.dev, channel_id, DMA2D_MACRO_BLOCK_SIZE_NONE); if ((1 << channel_id) & DMA2D_LL_TX_CHANNEL_SUPPORT_CSC_MASK) { @@ -608,7 +609,7 @@ esp_err_t dma2d_connect(dma2d_channel_handle_t dma2d_chan, const dma2d_trigger_t dma2d_ll_rx_enable_owner_check(group->hal.dev, channel_id, false); dma2d_ll_rx_set_auto_return_owner(group->hal.dev, channel_id, DMA2D_DESCRIPTOR_BUFFER_OWNER_CPU); // After auto write back, the owner field will be cleared dma2d_ll_rx_enable_descriptor_burst(group->hal.dev, channel_id, false); - dma2d_ll_rx_set_data_burst_length(group->hal.dev, channel_id, DMA2D_DATA_BURST_LENGTH_128); + dma2d_ll_rx_set_data_burst_length(group->hal.dev, channel_id, 128); dma2d_ll_rx_enable_page_bound_wrap(group->hal.dev, channel_id, true); dma2d_ll_rx_set_macro_block_size(group->hal.dev, channel_id, DMA2D_MACRO_BLOCK_SIZE_NONE); if ((1 << channel_id) & DMA2D_LL_RX_CHANNEL_SUPPORT_CSC_MASK) { @@ -713,6 +714,8 @@ esp_err_t dma2d_set_desc_addr(dma2d_channel_handle_t dma2d_chan, intptr_t desc_b ESP_GOTO_ON_FALSE_ISR(dma2d_chan && desc_base_addr, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument"); // 2D-DMA descriptor addr needs 8-byte alignment and not in SPM (addr not in SPM is IDF restriction) ESP_GOTO_ON_FALSE_ISR((desc_base_addr & 0x7) == 0 && !esp_ptr_in_spm((void *)desc_base_addr), ESP_ERR_INVALID_ARG, err, TAG, "invalid argument"); + // When flash encryption is enabled, the descriptor must be in internal RAM because descriptor size is not 16-byte aligned, which breaks flash encryption alignment restriction + ESP_GOTO_ON_FALSE_ISR(!esp_efuse_is_flash_encryption_enabled() || esp_ptr_internal((void *)desc_base_addr), ESP_ERR_INVALID_ARG, err, TAG, "invalid argument"); dma2d_group_t *group = dma2d_chan->group; int channel_id = dma2d_chan->channel_id; @@ -828,19 +831,30 @@ esp_err_t dma2d_set_transfer_ability(dma2d_channel_handle_t dma2d_chan, const dm { esp_err_t ret = ESP_OK; ESP_GOTO_ON_FALSE_ISR(dma2d_chan && ability, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument"); - ESP_GOTO_ON_FALSE_ISR(ability->data_burst_length < DMA2D_DATA_BURST_LENGTH_INVALID, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument"); + ESP_GOTO_ON_FALSE_ISR(ability->data_burst_length && ((ability->data_burst_length & (ability->data_burst_length - 1)) == 0), ESP_ERR_INVALID_ARG, err, TAG, "invalid argument"); // burst size must be power of 2 ESP_GOTO_ON_FALSE_ISR(ability->mb_size < DMA2D_MACRO_BLOCK_SIZE_INVALID, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument"); dma2d_group_t *group = dma2d_chan->group; int channel_id = dma2d_chan->channel_id; + // When flash encryption is enabled, and the channel is accessing external memory, burst length has to be as least as the encryption alignment restriction size + uint32_t data_burst_length = ability->data_burst_length; +#if SOC_PSRAM_DMA_CAPABLE || SOC_DMA_CAN_ACCESS_FLASH + if (esp_efuse_is_flash_encryption_enabled() && ability->access_ext_mem) { + if (data_burst_length < SOC_MEMSPI_ENCRYPTION_ALIGNMENT) { + data_burst_length = SOC_MEMSPI_ENCRYPTION_ALIGNMENT; + ESP_LOGW(TAG, "channel access encrypted external memory, adjust burst size to %d", SOC_MEMSPI_ENCRYPTION_ALIGNMENT); + } + } +#endif + if (dma2d_chan->direction == DMA2D_CHANNEL_DIRECTION_TX) { dma2d_ll_tx_enable_descriptor_burst(group->hal.dev, channel_id, ability->desc_burst_en); - dma2d_ll_tx_set_data_burst_length(group->hal.dev, channel_id, ability->data_burst_length); + dma2d_ll_tx_set_data_burst_length(group->hal.dev, channel_id, data_burst_length); dma2d_ll_tx_set_macro_block_size(group->hal.dev, channel_id, ability->mb_size); } else { dma2d_ll_rx_enable_descriptor_burst(group->hal.dev, channel_id, ability->desc_burst_en); - dma2d_ll_rx_set_data_burst_length(group->hal.dev, channel_id, ability->data_burst_length); + dma2d_ll_rx_set_data_burst_length(group->hal.dev, channel_id, data_burst_length); dma2d_ll_rx_set_macro_block_size(group->hal.dev, channel_id, ability->mb_size); } diff --git a/components/esp_driver_dma/src/gdma.c b/components/esp_driver_dma/src/gdma.c index e95b192706..485f200edc 100644 --- a/components/esp_driver_dma/src/gdma.c +++ b/components/esp_driver_dma/src/gdma.c @@ -422,7 +422,7 @@ esp_err_t gdma_config_transfer(gdma_channel_handle_t dma_chan, const gdma_transf #if (SOC_PSRAM_DMA_CAPABLE || SOC_DMA_CAN_ACCESS_FLASH) && SOC_AHB_GDMA_VERSION != 1 // if MSPI encryption is enabled, and DMA wants to read/write external memory if (esp_efuse_is_flash_encryption_enabled() && config->access_ext_mem) { - uint32_t enc_mem_alignment = GDMA_LL_GET(ACCESS_ENCRYPTION_MEM_ALIGNMENT); + uint32_t enc_mem_alignment = SOC_MEMSPI_ENCRYPTION_ALIGNMENT; // when DMA access the encrypted external memory, extra alignment is needed for external memory ext_mem_alignment = MAX(ext_mem_alignment, enc_mem_alignment); if (max_data_burst_size < enc_mem_alignment) { diff --git a/components/esp_driver_dma/test_apps/.build-test-rules.yml b/components/esp_driver_dma/test_apps/.build-test-rules.yml index 5087696a4c..0a29c61e0e 100644 --- a/components/esp_driver_dma/test_apps/.build-test-rules.yml +++ b/components/esp_driver_dma/test_apps/.build-test-rules.yml @@ -3,6 +3,7 @@ components/esp_driver_dma/test_apps/dma: disable: - if: SOC_GDMA_SUPPORTED != 1 and SOC_CP_DMA_SUPPORTED != 1 + - if: CONFIG_NAME == "flash_enc" and SOC_FLASH_ENC_SUPPORTED != 1 depends_components: - esp_driver_dma - esp_hal_dma 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 7e7d474f9d..b14e4ace09 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 @@ -249,7 +249,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 - static const char src_string[] __attribute__((aligned(GDMA_LL_GET(ACCESS_ENCRYPTION_MEM_ALIGNMENT)))) = "GDMA can read MSPI Flash data!!!"; + static const char src_string[] __attribute__((aligned(SOC_MEMSPI_ENCRYPTION_ALIGNMENT))) = "GDMA can read MSPI Flash data!!!"; size_t src_string_len = strlen(src_string); TEST_ASSERT_TRUE(esp_ptr_in_drom(src_string)); 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 9ab75ac552..2a8233f690 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 @@ -70,10 +70,10 @@ static void test_gdma_crc_calculation(gdma_channel_handle_t tx_chan, int test_nu uint32_t crc_result = 0; - static const char test_input_string[] __attribute__((aligned(GDMA_LL_GET(ACCESS_ENCRYPTION_MEM_ALIGNMENT)))) = "GDMACRC Share::Connect::Innovate"; + static const char test_input_string[] __attribute__((aligned(SOC_MEMSPI_ENCRYPTION_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); + TEST_ASSERT_EQUAL((uintptr_t)test_input_string % SOC_MEMSPI_ENCRYPTION_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 a684d7fdc5..6c73c61215 100644 --- a/components/esp_driver_dma/test_apps/dma/pytest_dma.py +++ b/components/esp_driver_dma/test_apps/dma/pytest_dma.py @@ -53,12 +53,12 @@ def test_dma_weighted_arbitration(dut: Dut) -> None: @pytest.mark.parametrize( 'config', [ - 'ext_mem_encryption', + 'flash_enc', ], indirect=True, ) @idf_parametrize('target', ['esp32p4', 'esp32c5'], indirect=['target']) -def test_dma_ext_mem_encryption(dut: Dut) -> None: +def test_dma_flash_encryption(dut: Dut) -> None: dut.run_all_single_board_cases(reset=True) @@ -66,10 +66,10 @@ def test_dma_ext_mem_encryption(dut: Dut) -> None: @pytest.mark.parametrize( 'config', [ - 'ext_mem_encryption', + 'flash_enc', ], indirect=True, ) @idf_parametrize('target', ['esp32s3'], indirect=['target']) -def test_dma_ext_mem_encryption_s3_f4r8(dut: Dut) -> None: +def test_dma_flash_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.flash_enc similarity index 100% rename from components/esp_driver_dma/test_apps/dma/sdkconfig.ci.ext_mem_encryption rename to components/esp_driver_dma/test_apps/dma/sdkconfig.ci.flash_enc diff --git a/components/esp_driver_dma/test_apps/dma2d/main/CMakeLists.txt b/components/esp_driver_dma/test_apps/dma2d/main/CMakeLists.txt index 02fd540ce6..bd6d24b9d8 100644 --- a/components/esp_driver_dma/test_apps/dma2d/main/CMakeLists.txt +++ b/components/esp_driver_dma/test_apps/dma2d/main/CMakeLists.txt @@ -6,5 +6,5 @@ set(srcs "test_app_main.c" # the component can be registered as WHOLE_ARCHIVE idf_component_register(SRCS ${srcs} INCLUDE_DIRS "." - PRIV_REQUIRES unity esp_mm esp_psram esp_driver_dma + PRIV_REQUIRES unity esp_mm esp_psram esp_driver_dma efuse WHOLE_ARCHIVE) diff --git a/components/esp_driver_dma/test_apps/dma2d/main/test_dma2d.c b/components/esp_driver_dma/test_apps/dma2d/main/test_dma2d.c index 580f485c90..27b1ef060b 100644 --- a/components/esp_driver_dma/test_apps/dma2d/main/test_dma2d.c +++ b/components/esp_driver_dma/test_apps/dma2d/main/test_dma2d.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -17,6 +17,9 @@ #include "hal/color_types.h" #include "esp_heap_caps.h" #include "esp_cache.h" +#include "esp_efuse.h" + +#define ALIGN_UP(num, align) (((num) + ((align) - 1)) & ~((align) - 1)) // All test will perform `M2M_TRANS_TIMES` times memcpy transactions, utilizing all available 2D-DMA channels. // This tests the hardware capability of multiple 2D-DMA transactions running together, and the driver capbility of @@ -25,6 +28,7 @@ #define M2M_TRANS_TIMES (12) // Descriptor and buffer address and size should aligned to 64 bytes (the cacheline size alignment restriction) to be used by CPU +// Additionally, if flash encryption is enabled, no matter descriptor or buffer, if in internal RAM, the address should be 16-byte aligned; if in external RAM, the address and size both should be 16-byte aligned. static dma2d_descriptor_t *tx_dsc[M2M_TRANS_TIMES]; static dma2d_descriptor_t *rx_dsc[M2M_TRANS_TIMES]; @@ -71,8 +75,13 @@ TEST_CASE("DMA2D_M2M_1D_basic", "[DMA2D]") memset(m2m_trans_config, 0, M2M_TRANS_TIMES * sizeof(dma2d_m2m_trans_config_t)); TEST_ESP_OK(dma2d_m2m_init()); - dma2d_descriptor_t *tx_link_buffer = (dma2d_descriptor_t *)heap_caps_aligned_calloc(64, M2M_TRANS_TIMES, 64, MALLOC_CAP_DEFAULT); - dma2d_descriptor_t *rx_link_buffer = (dma2d_descriptor_t *)heap_caps_aligned_calloc(64, M2M_TRANS_TIMES, 64, MALLOC_CAP_DEFAULT); + uint32_t desc_malloc_cap = MALLOC_CAP_DEFAULT; // can be in internal RAM or external RAM + if (esp_efuse_is_flash_encryption_enabled()) { + // descriptor size is not 16-byte aligned, so can not be in external RAM + desc_malloc_cap = MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT; + } + dma2d_descriptor_t *tx_link_buffer = (dma2d_descriptor_t *)heap_caps_aligned_calloc(64, M2M_TRANS_TIMES, 64, desc_malloc_cap); + dma2d_descriptor_t *rx_link_buffer = (dma2d_descriptor_t *)heap_caps_aligned_calloc(64, M2M_TRANS_TIMES, 64, desc_malloc_cap); TEST_ASSERT_NOT_NULL(tx_link_buffer); TEST_ASSERT_NOT_NULL(rx_link_buffer); for (int i = 0; i < M2M_TRANS_TIMES; i++) { @@ -88,7 +97,8 @@ TEST_CASE("DMA2D_M2M_1D_basic", "[DMA2D]") TEST_ASSERT_NOT_NULL(rx_buf); dma2d_transfer_ability_t transfer_ability_config = { - .data_burst_length = DMA2D_DATA_BURST_LENGTH_64, + .access_ext_mem = true, + .data_burst_length = 64, .desc_burst_en = true, .mb_size = DMA2D_MACRO_BLOCK_SIZE_NONE, }; @@ -210,8 +220,13 @@ TEST_CASE("DMA2D_M2M_1D_RGB565_to_RGB888", "[DMA2D]") memset(m2m_trans_config, 0, M2M_TRANS_TIMES * sizeof(dma2d_m2m_trans_config_t)); TEST_ESP_OK(dma2d_m2m_init()); - dma2d_descriptor_t *tx_link_buffer = (dma2d_descriptor_t *)heap_caps_aligned_calloc(64, M2M_TRANS_TIMES, 64, MALLOC_CAP_DEFAULT); - dma2d_descriptor_t *rx_link_buffer = (dma2d_descriptor_t *)heap_caps_aligned_calloc(64, M2M_TRANS_TIMES, 64, MALLOC_CAP_DEFAULT); + uint32_t desc_malloc_cap = MALLOC_CAP_DEFAULT; // can be in internal RAM or external RAM + if (esp_efuse_is_flash_encryption_enabled()) { + // descriptor size is not 16-byte aligned, so can not be in external RAM + desc_malloc_cap = MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT; + } + dma2d_descriptor_t *tx_link_buffer = (dma2d_descriptor_t *)heap_caps_aligned_calloc(64, M2M_TRANS_TIMES, 64, desc_malloc_cap); + dma2d_descriptor_t *rx_link_buffer = (dma2d_descriptor_t *)heap_caps_aligned_calloc(64, M2M_TRANS_TIMES, 64, desc_malloc_cap); TEST_ASSERT_NOT_NULL(tx_link_buffer); TEST_ASSERT_NOT_NULL(rx_link_buffer); for (int i = 0; i < M2M_TRANS_TIMES; i++) { @@ -229,7 +244,8 @@ TEST_CASE("DMA2D_M2M_1D_RGB565_to_RGB888", "[DMA2D]") SemaphoreHandle_t counting_sem = xSemaphoreCreateCounting(M2M_TRANS_TIMES, 0); dma2d_transfer_ability_t transfer_ability_config = { - .data_burst_length = DMA2D_DATA_BURST_LENGTH_128, + .access_ext_mem = true, + .data_burst_length = 128, .desc_burst_en = true, .mb_size = DMA2D_MACRO_BLOCK_SIZE_NONE, }; @@ -323,8 +339,13 @@ TEST_CASE("DMA2D_M2M_2D_basic", "[DMA2D]") memset(m2m_trans_config, 0, M2M_TRANS_TIMES * sizeof(dma2d_m2m_trans_config_t)); TEST_ESP_OK(dma2d_m2m_init()); - dma2d_descriptor_t *tx_link_buffer = (dma2d_descriptor_t *)heap_caps_aligned_calloc(64, M2M_TRANS_TIMES, 64, MALLOC_CAP_DEFAULT); - dma2d_descriptor_t *rx_link_buffer = (dma2d_descriptor_t *)heap_caps_aligned_calloc(64, M2M_TRANS_TIMES, 64, MALLOC_CAP_DEFAULT); + uint32_t desc_malloc_cap = MALLOC_CAP_DEFAULT; // can be in internal RAM or external RAM + if (esp_efuse_is_flash_encryption_enabled()) { + // descriptor size is not 16-byte aligned, so can not be in external RAM + desc_malloc_cap = MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT; + } + dma2d_descriptor_t *tx_link_buffer = (dma2d_descriptor_t *)heap_caps_aligned_calloc(64, M2M_TRANS_TIMES, 64, desc_malloc_cap); + dma2d_descriptor_t *rx_link_buffer = (dma2d_descriptor_t *)heap_caps_aligned_calloc(64, M2M_TRANS_TIMES, 64, desc_malloc_cap); TEST_ASSERT_NOT_NULL(tx_link_buffer); TEST_ASSERT_NOT_NULL(rx_link_buffer); for (int i = 0; i < M2M_TRANS_TIMES; i++) { @@ -342,7 +363,8 @@ TEST_CASE("DMA2D_M2M_2D_basic", "[DMA2D]") SemaphoreHandle_t counting_sem = xSemaphoreCreateCounting(M2M_TRANS_TIMES, 0); dma2d_transfer_ability_t transfer_ability_config = { - .data_burst_length = DMA2D_DATA_BURST_LENGTH_128, + .access_ext_mem = true, + .data_burst_length = 128, .desc_burst_en = true, .mb_size = DMA2D_MACRO_BLOCK_SIZE_NONE, }; @@ -456,8 +478,13 @@ TEST_CASE("DMA2D_M2M_2D_RGB888_to_RGB565", "[DMA2D]") memset(m2m_trans_config, 0, M2M_TRANS_TIMES * sizeof(dma2d_m2m_trans_config_t)); TEST_ESP_OK(dma2d_m2m_init()); - dma2d_descriptor_t *tx_link_buffer = (dma2d_descriptor_t *)heap_caps_aligned_calloc(64, M2M_TRANS_TIMES, 64, MALLOC_CAP_DEFAULT); - dma2d_descriptor_t *rx_link_buffer = (dma2d_descriptor_t *)heap_caps_aligned_calloc(64, M2M_TRANS_TIMES, 64, MALLOC_CAP_DEFAULT); + uint32_t desc_malloc_cap = MALLOC_CAP_DEFAULT; // can be in internal RAM or external RAM + if (esp_efuse_is_flash_encryption_enabled()) { + // descriptor size is not 16-byte aligned, so can not be in external RAM + desc_malloc_cap = MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT; + } + dma2d_descriptor_t *tx_link_buffer = (dma2d_descriptor_t *)heap_caps_aligned_calloc(64, M2M_TRANS_TIMES, 64, desc_malloc_cap); + dma2d_descriptor_t *rx_link_buffer = (dma2d_descriptor_t *)heap_caps_aligned_calloc(64, M2M_TRANS_TIMES, 64, desc_malloc_cap); TEST_ASSERT_NOT_NULL(tx_link_buffer); TEST_ASSERT_NOT_NULL(rx_link_buffer); for (int i = 0; i < M2M_TRANS_TIMES; i++) { @@ -475,7 +502,8 @@ TEST_CASE("DMA2D_M2M_2D_RGB888_to_RGB565", "[DMA2D]") SemaphoreHandle_t counting_sem = xSemaphoreCreateCounting(M2M_TRANS_TIMES, 0); dma2d_transfer_ability_t transfer_ability_config = { - .data_burst_length = DMA2D_DATA_BURST_LENGTH_16, + .access_ext_mem = true, + .data_burst_length = 16, .desc_burst_en = true, .mb_size = DMA2D_MACRO_BLOCK_SIZE_NONE, }; @@ -562,17 +590,30 @@ TEST_CASE("DMA2D_M2M_2D_RGB888_to_RGB565", "[DMA2D]") TEST_CASE("DMA2D_M2M_2D_window", "[DMA2D]") { - // Test 2D memcpy to a 2 x 2 block at (2, 4) in a 8 x 8 picture (pixel in RGB565 format) + // Test 2D memcpy to a 8 x 2 block at (8,0) in a 24 x 8 picture (pixel in RGB565 format) + + // When flash encryption is enabled, and tx/rx buffer are in PSRAM (if located in internal RAM, there is no alignment restriction due to encryption): + // - The address and size of the tx/rx buffer should be 16-byte aligned + // - The width of the window multiply byte number of one pixel should be 16-byte aligned + // - The address of every row of the window should be 16-byte aligned + const esp_color_fourcc_t pixel_format = ESP_COLOR_FOURCC_RGB16; - const uint32_t va = 8, ha = 8; // Define picture height and width (unit: pixel) - const uint32_t vb = 2, hb = 2; // Define block height and width (unit: pixel) - const uint32_t x_offset = 2, y_offset = 4; // Define block location in the picture (unit: pixel) + const uint32_t va = 8, ha = 24; // Define picture height and width (unit: pixel) + const uint32_t vb = 2, hb = 8; // Define block height and width (unit: pixel) + const uint32_t x_offset = 8, y_offset = 0; // Define block location in the picture (unit: pixel) memset(m2m_trans_config, 0, M2M_TRANS_TIMES * sizeof(dma2d_m2m_trans_config_t)); TEST_ESP_OK(dma2d_m2m_init()); - dma2d_descriptor_t *tx_link_buffer = (dma2d_descriptor_t *)heap_caps_aligned_calloc(64, M2M_TRANS_TIMES, 64, MALLOC_CAP_DEFAULT); - dma2d_descriptor_t *rx_link_buffer = (dma2d_descriptor_t *)heap_caps_aligned_calloc(64, M2M_TRANS_TIMES, 64, MALLOC_CAP_DEFAULT); + uint32_t desc_malloc_cap = MALLOC_CAP_DEFAULT; // can be in internal RAM or external RAM + uint32_t buf_malloc_cap = MALLOC_CAP_INTERNAL; + if (esp_efuse_is_flash_encryption_enabled()) { + // descriptor size is not 16-byte aligned, so can not be in external RAM + desc_malloc_cap = MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT; + buf_malloc_cap = MALLOC_CAP_SPIRAM; // to test its strict alignment requirement + } + dma2d_descriptor_t *tx_link_buffer = (dma2d_descriptor_t *)heap_caps_aligned_calloc(64, M2M_TRANS_TIMES, 64, desc_malloc_cap); + dma2d_descriptor_t *rx_link_buffer = (dma2d_descriptor_t *)heap_caps_aligned_calloc(64, M2M_TRANS_TIMES, 64, desc_malloc_cap); TEST_ASSERT_NOT_NULL(tx_link_buffer); TEST_ASSERT_NOT_NULL(rx_link_buffer); for (int i = 0; i < M2M_TRANS_TIMES; i++) { @@ -582,15 +623,18 @@ TEST_CASE("DMA2D_M2M_2D_window", "[DMA2D]") uint8_t *prtx; uint8_t *prrx; - uint8_t *tx_buf = heap_caps_aligned_calloc(64, 64 * M2M_TRANS_TIMES, sizeof(uint8_t), MALLOC_CAP_INTERNAL); - uint8_t *rx_buf = heap_caps_aligned_calloc(64, va * ha * 2 * M2M_TRANS_TIMES, sizeof(uint8_t), MALLOC_CAP_INTERNAL); + size_t tx_buf_size = ALIGN_UP(vb * hb * 2, 64); // buffer msync alignment restriction + uint8_t *tx_buf = heap_caps_aligned_calloc(64, tx_buf_size * M2M_TRANS_TIMES, sizeof(uint8_t), buf_malloc_cap); + size_t rx_buf_size = ALIGN_UP(va * ha * 2, 64); // buffer msync alignment restriction + uint8_t *rx_buf = heap_caps_aligned_calloc(64, rx_buf_size * M2M_TRANS_TIMES, sizeof(uint8_t), buf_malloc_cap); TEST_ASSERT_NOT_NULL(tx_buf); TEST_ASSERT_NOT_NULL(rx_buf); SemaphoreHandle_t counting_sem = xSemaphoreCreateCounting(M2M_TRANS_TIMES, 0); dma2d_transfer_ability_t transfer_ability_config = { - .data_burst_length = DMA2D_DATA_BURST_LENGTH_128, + .access_ext_mem = (buf_malloc_cap & MALLOC_CAP_SPIRAM) ? true : false, + .data_burst_length = 128, .desc_burst_en = true, .mb_size = DMA2D_MACRO_BLOCK_SIZE_NONE, }; @@ -598,8 +642,8 @@ TEST_CASE("DMA2D_M2M_2D_window", "[DMA2D]") // Preparation for (int i = 0; i < M2M_TRANS_TIMES; i++) { // Buffer data preparation - prtx = tx_buf + i * 64; - prrx = rx_buf + i * va * ha * 2; + prtx = tx_buf + i * tx_buf_size; + prrx = rx_buf + i * rx_buf_size; for (int idx = 0; idx < vb * hb; idx++) { prtx[idx * 2] = 0x55 + idx + i; prtx[idx * 2 + 1] = 0xAA + idx + i; @@ -610,8 +654,8 @@ TEST_CASE("DMA2D_M2M_2D_window", "[DMA2D]") } // Writeback TX and RX buffers - esp_cache_msync((void *)prtx, 64, ESP_CACHE_MSYNC_FLAG_DIR_C2M); - esp_cache_msync((void *)prrx, va * ha * 2, ESP_CACHE_MSYNC_FLAG_DIR_C2M); + esp_cache_msync((void *)prtx, tx_buf_size, ESP_CACHE_MSYNC_FLAG_DIR_C2M); + esp_cache_msync((void *)prrx, rx_buf_size, ESP_CACHE_MSYNC_FLAG_DIR_C2M); // DMA description preparation dma2d_link_dscr_init((uint32_t *)tx_dsc[i], NULL, (void *)prtx, @@ -649,12 +693,12 @@ TEST_CASE("DMA2D_M2M_2D_window", "[DMA2D]") // Print the picture and check result for (int i = 0; i < M2M_TRANS_TIMES; i++) { - prtx = tx_buf + i * 64; - prrx = rx_buf + i * va * ha * 2; + prtx = tx_buf + i * tx_buf_size; + prrx = rx_buf + i * rx_buf_size; // Invalidate TX and RX buffers - esp_cache_msync((void *)prtx, 64, ESP_CACHE_MSYNC_FLAG_DIR_M2C); - esp_cache_msync((void *)prrx, va * ha * 2, ESP_CACHE_MSYNC_FLAG_DIR_M2C); + esp_cache_msync((void *)prtx, tx_buf_size, ESP_CACHE_MSYNC_FLAG_DIR_M2C); + esp_cache_msync((void *)prrx, rx_buf_size, ESP_CACHE_MSYNC_FLAG_DIR_M2C); printf("pic:\n"); for (int idx = 0; idx < va * ha; idx++) { diff --git a/components/esp_driver_dma/test_apps/dma2d/pytest_dma2d.py b/components/esp_driver_dma/test_apps/dma2d/pytest_dma2d.py index 8f02215a63..ee1cb98f3c 100644 --- a/components/esp_driver_dma/test_apps/dma2d/pytest_dma2d.py +++ b/components/esp_driver_dma/test_apps/dma2d/pytest_dma2d.py @@ -17,3 +17,16 @@ from pytest_embedded_idf.utils import soc_filtered_targets @idf_parametrize('target', soc_filtered_targets('SOC_DMA2D_SUPPORTED == 1'), indirect=['target']) def test_dma2d(dut: Dut) -> None: dut.run_all_single_board_cases() + + +@pytest.mark.flash_encryption +@pytest.mark.parametrize( + 'config', + [ + 'flash_enc', + ], + indirect=True, +) +@idf_parametrize('target', soc_filtered_targets('SOC_DMA2D_SUPPORTED == 1'), indirect=['target']) +def test_dma2d_flash_encryption(dut: Dut) -> None: + dut.run_all_single_board_cases() diff --git a/components/esp_driver_dma/test_apps/dma2d/sdkconfig.ci.flash_enc b/components/esp_driver_dma/test_apps/dma2d/sdkconfig.ci.flash_enc new file mode 100644 index 0000000000..5be9651c38 --- /dev/null +++ b/components/esp_driver_dma/test_apps/dma2d/sdkconfig.ci.flash_enc @@ -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_jpeg/jpeg_decode.c b/components/esp_driver_jpeg/jpeg_decode.c index d9cb7f87f4..f4b29ffca3 100644 --- a/components/esp_driver_jpeg/jpeg_decode.c +++ b/components/esp_driver_jpeg/jpeg_decode.c @@ -521,13 +521,15 @@ static void jpeg_dec_config_dma_trans_ability(jpeg_decoder_handle_t decoder_engi { // set transfer ability dma2d_transfer_ability_t transfer_ability_config_tx = { - .data_burst_length = DMA2D_DATA_BURST_LENGTH_128, + .access_ext_mem = true, // in most cases + .data_burst_length = 128, .desc_burst_en = true, .mb_size = DMA2D_MACRO_BLOCK_SIZE_NONE, }; dma2d_transfer_ability_t transfer_ability_config_rx = { - .data_burst_length = DMA2D_DATA_BURST_LENGTH_128, + .access_ext_mem = true, // in most cases + .data_burst_length = 128, .desc_burst_en = true, .mb_size = DMA2D_MACRO_BLOCK_SIZE_NONE, }; diff --git a/components/esp_driver_jpeg/jpeg_encode.c b/components/esp_driver_jpeg/jpeg_encode.c index ce564a8330..84d778e6af 100644 --- a/components/esp_driver_jpeg/jpeg_encode.c +++ b/components/esp_driver_jpeg/jpeg_encode.c @@ -434,13 +434,15 @@ static void jpeg_enc_config_dma_trans_ability(jpeg_encoder_handle_t encoder_engi { // set transfer ability dma2d_transfer_ability_t transfer_ability_config_tx = { - .data_burst_length = DMA2D_DATA_BURST_LENGTH_128, + .access_ext_mem = true, // in most cases + .data_burst_length = 128, .desc_burst_en = true, .mb_size = DMA2D_MACRO_BLOCK_SIZE_NONE, }; dma2d_transfer_ability_t transfer_ability_config_rx = { - .data_burst_length = DMA2D_DATA_BURST_LENGTH_128, + .access_ext_mem = true, // in most cases + .data_burst_length = 128, .desc_burst_en = true, .mb_size = DMA2D_MACRO_BLOCK_SIZE_NONE, }; diff --git a/components/esp_driver_ppa/CMakeLists.txt b/components/esp_driver_ppa/CMakeLists.txt index 4e98be6b02..5933dc0479 100644 --- a/components/esp_driver_ppa/CMakeLists.txt +++ b/components/esp_driver_ppa/CMakeLists.txt @@ -12,7 +12,7 @@ endif() if(${target} STREQUAL "linux") set(priv_requires "") else() - set(priv_requires esp_mm esp_pm esp_driver_dma) + set(priv_requires esp_mm esp_pm esp_driver_dma efuse) endif() diff --git a/components/esp_driver_ppa/include/driver/ppa.h b/components/esp_driver_ppa/include/driver/ppa.h index 5a3917d88d..9eacd523ba 100644 --- a/components/esp_driver_ppa/include/driver/ppa.h +++ b/components/esp_driver_ppa/include/driver/ppa.h @@ -124,6 +124,7 @@ typedef struct { ppa_srm_color_mode_t srm_cm; /*!< Color mode of the picture in a PPA SRM operation. Supported color mode in `ppa_srm_color_mode_t` */ ppa_blend_color_mode_t blend_cm; /*!< Color mode of the picture in a PPA blend operation. Supported color mode in `ppa_blend_color_mode_t` */ ppa_fill_color_mode_t fill_cm; /*!< Color mode of the picture in a PPA fill operation. Supported color mode in `ppa_fill_color_mode_t` */ + esp_color_fourcc_t cm; /*!< Four Character Code of the color mode */ }; ppa_color_range_t yuv_range; /*!< When the color mode is any YUV color space, this field is to describe its color range */ ppa_color_conv_std_rgb_yuv_t yuv_std; /*!< When the color mode is any YUV color space, this field is to describe its YUV<->RGB conversion standard */ @@ -143,6 +144,7 @@ typedef struct { ppa_srm_color_mode_t srm_cm; /*!< Color mode of the picture in a PPA SRM operation. Supported color mode in `ppa_srm_color_mode_t` */ ppa_blend_color_mode_t blend_cm; /*!< Color mode of the picture in a PPA blend operation. Supported color mode in `ppa_blend_color_mode_t` */ ppa_fill_color_mode_t fill_cm; /*!< Color mode of the picture in a PPA fill operation. Supported color mode in `ppa_fill_color_mode_t` */ + esp_color_fourcc_t cm; /*!< Four Character Code of the color mode */ }; ppa_color_range_t yuv_range; /*!< When the color mode is any YUV color space, this field is to describe its color range */ ppa_color_conv_std_rgb_yuv_t yuv_std; /*!< When the color mode is any YUV color space, this field is to describe its YUV<->RGB conversion standard */ diff --git a/components/esp_driver_ppa/src/ppa_blend.c b/components/esp_driver_ppa/src/ppa_blend.c index 9606bdebdd..e3cd6816c0 100644 --- a/components/esp_driver_ppa/src/ppa_blend.c +++ b/components/esp_driver_ppa/src/ppa_blend.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -108,6 +108,7 @@ bool ppa_blend_transaction_on_picked(uint32_t num_chans, const dma2d_trans_chann dma2d_connect(dma2d_rx_chan, &trig_periph); dma2d_transfer_ability_t dma_transfer_ability = { + .access_ext_mem = true, // in most cases the buffers are located in external memory, will not bother checking the memory region of the buffers .data_burst_length = blend_trans_desc->data_burst_length, .desc_burst_en = true, .mb_size = DMA2D_MACRO_BLOCK_SIZE_NONE, @@ -177,9 +178,6 @@ esp_err_t ppa_do_blend(ppa_client_handle_t ppa_client, const ppa_blend_oper_conf ESP_RETURN_ON_FALSE(config->mode <= PPA_TRANS_MODE_NON_BLOCKING, ESP_ERR_INVALID_ARG, TAG, "invalid mode"); // in_buffer could be anywhere (ram, flash, psram), out_buffer ptr cannot in flash region ESP_RETURN_ON_FALSE(esp_ptr_internal(config->out.buffer) || esp_ptr_external_ram(config->out.buffer), ESP_ERR_INVALID_ARG, TAG, "invalid out.buffer addr"); - uint32_t buf_alignment_size = (uint32_t)ppa_client->engine->platform->buf_alignment_size; - ESP_RETURN_ON_FALSE(((uint32_t)config->out.buffer & (buf_alignment_size - 1)) == 0 && (config->out.buffer_size & (buf_alignment_size - 1)) == 0, - ESP_ERR_INVALID_ARG, TAG, "out.buffer addr or out.buffer_size not aligned to cache line size"); ESP_RETURN_ON_FALSE(ppa_ll_blend_is_color_mode_supported(config->in_bg.blend_cm) && ppa_ll_blend_is_color_mode_supported(config->in_fg.blend_cm) && ppa_ll_blend_is_color_mode_supported(config->out.blend_cm), ESP_ERR_INVALID_ARG, TAG, "unsupported color mode"); // For YUV420 input/output: in desc, ha/hb/va/vb/x/y must be even number // For YUV422 input/output: in desc, ha/hb/x must be even number @@ -223,6 +221,13 @@ esp_err_t ppa_do_blend(ppa_client_handle_t ppa_client, const ppa_blend_oper_conf ESP_RETURN_ON_FALSE(config->in_fg.block_w <= (config->out.pic_w - config->out.block_offset_x) && config->in_fg.block_h <= (config->out.pic_h - config->out.block_offset_y), ESP_ERR_INVALID_ARG, TAG, "block does not fit in the out pic"); + + if (!ppa_check_buffer_alignment(ppa_client, &config->in_bg, true, config->in_bg.block_w) || + !ppa_check_buffer_alignment(ppa_client, &config->in_fg, true, config->in_fg.block_w) || + !ppa_check_buffer_alignment(ppa_client, &config->out, false, config->in_fg.block_w)) { + return ESP_ERR_INVALID_ARG; + } + if (config->bg_byte_swap) { PPA_CHECK_CM_SUPPORT_BYTE_SWAP("in_bg.blend", (uint32_t)config->in_bg.blend_cm); } @@ -255,6 +260,7 @@ esp_err_t ppa_do_blend(ppa_client_handle_t ppa_client, const ppa_blend_oper_conf // Write back and invalidate necessary data (note that the window content is not continuous in the buffer) // Write back in_bg_buffer, in_fg_buffer extended windows (alignment not necessary on C2M direction) + uint32_t buf_alignment_size = (uint32_t)ppa_client->engine->platform->buf_alignment_size; uint32_t in_bg_pixel_depth = color_hal_pixel_format_fourcc_get_bit_depth((esp_color_fourcc_t)config->in_bg.blend_cm); // bits // Usually C2M can let the msync do alignment internally, however, it only do L1-cacheline-size alignment for L1->L2, and then L2-cacheline-size alignment for L2->mem // While M2C direction manual alignment is L2-cacheline-size alignment for mem->L2->L1 diff --git a/components/esp_driver_ppa/src/ppa_core.c b/components/esp_driver_ppa/src/ppa_core.c index 4b1ba3c706..d0047524b0 100644 --- a/components/esp_driver_ppa/src/ppa_core.c +++ b/components/esp_driver_ppa/src/ppa_core.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -20,6 +20,7 @@ #include "freertos/queue.h" #include "esp_heap_caps.h" #include "esp_cache.h" +#include "esp_memory_utils.h" #include "esp_private/esp_cache_private.h" #include "hal/cache_hal.h" #include "hal/cache_ll.h" @@ -30,7 +31,11 @@ #include "hal/ppa_hal.h" #include "hal/ppa_ll.h" #include "hal/ppa_types.h" +#include "hal/color_hal.h" +#include "hal/color_types.h" #include "esp_private/periph_ctrl.h" +#include "esp_efuse.h" +#include "soc/soc_caps.h" static const char *TAG = "ppa_core"; @@ -276,6 +281,10 @@ esp_err_t ppa_register_client(const ppa_client_config_t *config, ppa_client_hand client->oper_type = config->oper_type; client->spinlock = (portMUX_TYPE)portMUX_INITIALIZER_UNLOCKED; client->data_burst_length = config->data_burst_length ? config->data_burst_length : PPA_DATA_BURST_LENGTH_128; + if (esp_efuse_is_flash_encryption_enabled() && (client->data_burst_length < SOC_MEMSPI_ENCRYPTION_ALIGNMENT)) { + ESP_LOGW(TAG, "flash encryption is enabled, but selected data burst length does not meet encryption alignment restriction if accessing external memory, will be automatically adjusted later on"); + } + if (config->oper_type == PPA_OPERATION_SRM) { ppa_engine_config_t engine_config = { .engine = PPA_ENGINE_TYPE_SRM, @@ -527,3 +536,44 @@ esp_err_t ppa_set_rgb2gray_formula(uint8_t r_weight, uint8_t g_weight, uint8_t b _lock_release(&s_platform.mutex); return ESP_OK; } + +bool ppa_check_buffer_alignment(ppa_client_handle_t ppa_client, const void *pic_blk_config, bool is_input, uint32_t block_width) +{ + // 1. check with cache line size alignment (output buffer only) + uint32_t buf_alignment_size = (uint32_t)ppa_client->engine->platform->buf_alignment_size; + if (!is_input) { + ppa_out_pic_blk_config_t *out_pic_blk_config = (ppa_out_pic_blk_config_t *)pic_blk_config; + if (((uint32_t)out_pic_blk_config->buffer & (buf_alignment_size - 1)) != 0 || (out_pic_blk_config->buffer_size & (buf_alignment_size - 1)) != 0) { + ESP_LOGE(TAG, "out.buffer addr or out.buffer_size not aligned to cache line size"); + return false; + } + } + + // 2. check with mspi encryption alignment + // When flash encryption is enabled, and in/out buffer are in PSRAM (if located in internal RAM, there is no alignment restriction due to encryption): + // - The width of the window multiply byte number of one pixel should align to SOC_MEMSPI_ENCRYPTION_ALIGNMENT + // - The starting address of every row of the window should align to SOC_MEMSPI_ENCRYPTION_ALIGNMENT + // (which also implies the address and size of the in/out buffer will align to SOC_MEMSPI_ENCRYPTION_ALIGNMENT) + + // check pic_width, block_width, block_head + const void *buffer = (is_input) ? ((ppa_in_pic_blk_config_t *)pic_blk_config)->buffer : ((ppa_out_pic_blk_config_t *)pic_blk_config)->buffer; + if (esp_efuse_is_flash_encryption_enabled() && !esp_ptr_internal(buffer)) { + if (ppa_client->engine->type == PPA_ENGINE_TYPE_SRM) { + ESP_LOGE(TAG, "SRM processes by macro blocks, where alignment is uncontrollable, makes it unable to work with flash encrypted if buffer is in external memory"); + return false; + } + uint32_t pic_width = (is_input) ? ((ppa_in_pic_blk_config_t *)pic_blk_config)->pic_w : ((ppa_out_pic_blk_config_t *)pic_blk_config)->pic_w; + uint32_t block_offset_x = (is_input) ? ((ppa_in_pic_blk_config_t *)pic_blk_config)->block_offset_x : ((ppa_out_pic_blk_config_t *)pic_blk_config)->block_offset_x; + esp_color_fourcc_t color_mode = (is_input) ? ((ppa_in_pic_blk_config_t *)pic_blk_config)->cm : ((ppa_out_pic_blk_config_t *)pic_blk_config)->cm; + uint32_t pixel_depth_bytes = color_hal_pixel_format_fourcc_get_bit_depth(color_mode) / 8; + + if (((pic_width * pixel_depth_bytes) & (SOC_MEMSPI_ENCRYPTION_ALIGNMENT - 1)) != 0 || + ((block_width * pixel_depth_bytes) & (SOC_MEMSPI_ENCRYPTION_ALIGNMENT - 1)) != 0 || + ((block_offset_x * pixel_depth_bytes) & (SOC_MEMSPI_ENCRYPTION_ALIGNMENT - 1)) != 0) { + ESP_LOGE(TAG, "(pic_width/block_width/block_offset_x * pixel_depth_bytes) not aligned to SOC_MEMSPI_ENCRYPTION_ALIGNMENT"); + return false; + } + } + + return true; +} diff --git a/components/esp_driver_ppa/src/ppa_fill.c b/components/esp_driver_ppa/src/ppa_fill.c index 30a7d79f27..70fe4278d9 100644 --- a/components/esp_driver_ppa/src/ppa_fill.c +++ b/components/esp_driver_ppa/src/ppa_fill.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -58,6 +58,7 @@ bool ppa_fill_transaction_on_picked(uint32_t num_chans, const dma2d_trans_channe dma2d_connect(dma2d_rx_chan, &trig_periph); dma2d_transfer_ability_t dma_transfer_ability = { + .access_ext_mem = true, // in most cases the buffer is located in external memory, will not bother checking the memory region of the buffer .data_burst_length = fill_trans_desc->data_burst_length, .desc_burst_en = true, .mb_size = DMA2D_MACRO_BLOCK_SIZE_NONE, @@ -89,9 +90,6 @@ esp_err_t ppa_do_fill(ppa_client_handle_t ppa_client, const ppa_fill_oper_config ESP_RETURN_ON_FALSE(config->mode <= PPA_TRANS_MODE_NON_BLOCKING, ESP_ERR_INVALID_ARG, TAG, "invalid mode"); // out_buffer ptr cannot in flash region ESP_RETURN_ON_FALSE(esp_ptr_internal(config->out.buffer) || esp_ptr_external_ram(config->out.buffer), ESP_ERR_INVALID_ARG, TAG, "invalid out.buffer addr"); - uint32_t buf_alignment_size = (uint32_t)ppa_client->engine->platform->buf_alignment_size; - ESP_RETURN_ON_FALSE(((uint32_t)config->out.buffer & (buf_alignment_size - 1)) == 0 && (config->out.buffer_size & (buf_alignment_size - 1)) == 0, - ESP_ERR_INVALID_ARG, TAG, "out.buffer addr or out.buffer_size not aligned to cache line size"); ESP_RETURN_ON_FALSE(ppa_ll_blend_is_color_mode_supported((ppa_blend_color_mode_t)config->out.fill_cm), ESP_ERR_INVALID_ARG, TAG, "unsupported color mode"); // For YUV420 output: in desc, ha/hb/va/vb/x/y must be even number // For YUV422 output: in desc, ha/hb/x must be even number @@ -110,10 +108,15 @@ esp_err_t ppa_do_fill(ppa_client_handle_t ppa_client, const ppa_fill_oper_config ESP_RETURN_ON_FALSE(config->fill_block_w <= (config->out.pic_w - config->out.block_offset_x) && config->fill_block_h <= (config->out.pic_h - config->out.block_offset_y), ESP_ERR_INVALID_ARG, TAG, "block does not fit in the out pic"); + + if (!ppa_check_buffer_alignment(ppa_client, &config->out, false, config->fill_block_w)) { + return ESP_ERR_INVALID_ARG; + } // To reduce complexity, specific color_mode, fill_block_w/h correctness are checked in their corresponding LL functions // Write back and invalidate necessary data (note that the window content is not continuous in the buffer) // Write back and invalidate buffer extended window (alignment not necessary on C2M direction, but alignment strict on M2C direction) + uint32_t buf_alignment_size = (uint32_t)ppa_client->engine->platform->buf_alignment_size; uint32_t out_ext_window = (uint32_t)config->out.buffer + config->out.block_offset_y * config->out.pic_w * out_pixel_depth / 8; uint32_t out_ext_window_aligned = PPA_ALIGN_DOWN(out_ext_window, buf_alignment_size); uint32_t out_ext_window_len = config->out.pic_w * config->fill_block_h * out_pixel_depth / 8; diff --git a/components/esp_driver_ppa/src/ppa_priv.h b/components/esp_driver_ppa/src/ppa_priv.h index 4dc7cc1ece..4f629f4bb8 100644 --- a/components/esp_driver_ppa/src/ppa_priv.h +++ b/components/esp_driver_ppa/src/ppa_priv.h @@ -231,6 +231,8 @@ bool ppa_transaction_done_cb(dma2d_channel_handle_t dma2d_chan, dma2d_event_data bool ppa_recycle_transaction(ppa_client_handle_t ppa_client, ppa_trans_t *trans_elm); +bool ppa_check_buffer_alignment(ppa_client_handle_t ppa_client, const void *pic_blk_config, bool is_input, uint32_t block_width); + /****************************** PPA DRIVER ***********************************/ struct ppa_platform_t { diff --git a/components/esp_driver_ppa/src/ppa_srm.c b/components/esp_driver_ppa/src/ppa_srm.c index 03fdc93342..88b7d6cfee 100644 --- a/components/esp_driver_ppa/src/ppa_srm.c +++ b/components/esp_driver_ppa/src/ppa_srm.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -89,6 +89,7 @@ bool ppa_srm_transaction_on_picked(uint32_t num_chans, const dma2d_trans_channel dma2d_connect(dma2d_rx_chan, &trig_periph); dma2d_transfer_ability_t dma_transfer_ability = { + .access_ext_mem = true, // in most cases the buffers are located in external memory, will not bother checking the memory region of the buffers .data_burst_length = srm_trans_desc->data_burst_length, .desc_burst_en = true, .mb_size = DMA2D_MACRO_BLOCK_SIZE_NONE, @@ -184,9 +185,6 @@ esp_err_t ppa_do_scale_rotate_mirror(ppa_client_handle_t ppa_client, const ppa_s ESP_RETURN_ON_FALSE(config->mode <= PPA_TRANS_MODE_NON_BLOCKING, ESP_ERR_INVALID_ARG, TAG, "invalid mode"); // in_buffer could be anywhere (ram, flash, psram), out_buffer ptr cannot in flash region ESP_RETURN_ON_FALSE(esp_ptr_internal(config->out.buffer) || esp_ptr_external_ram(config->out.buffer), ESP_ERR_INVALID_ARG, TAG, "invalid out.buffer addr"); - uint32_t buf_alignment_size = (uint32_t)ppa_client->engine->platform->buf_alignment_size; - ESP_RETURN_ON_FALSE(((uint32_t)config->out.buffer & (buf_alignment_size - 1)) == 0 && (config->out.buffer_size & (buf_alignment_size - 1)) == 0, - ESP_ERR_INVALID_ARG, TAG, "out.buffer addr or out.buffer_size not aligned to cache line size"); ESP_RETURN_ON_FALSE(ppa_ll_srm_is_color_mode_supported(config->in.srm_cm) && (ppa_ll_srm_is_color_mode_supported(config->out.srm_cm) && config->out.srm_cm != PPA_SRM_COLOR_MODE_YUV444), ESP_ERR_INVALID_ARG, TAG, "unsupported color mode"); @@ -218,18 +216,28 @@ esp_err_t ppa_do_scale_rotate_mirror(ppa_client_handle_t ppa_client, const ppa_s ESP_RETURN_ON_FALSE(config->scale_x < PPA_LL_SRM_SCALING_INT_MAX && config->scale_x >= (1.0 / PPA_LL_SRM_SCALING_FRAG_MAX) && config->scale_y < PPA_LL_SRM_SCALING_INT_MAX && config->scale_y >= (1.0 / PPA_LL_SRM_SCALING_FRAG_MAX), ESP_ERR_INVALID_ARG, TAG, "invalid scale"); + uint32_t scale_x_int = (uint32_t)config->scale_x; + uint32_t scale_x_frag = (uint32_t)(config->scale_x * PPA_LL_SRM_SCALING_FRAG_MAX) & (PPA_LL_SRM_SCALING_FRAG_MAX - 1); + uint32_t scale_y_int = (uint32_t)config->scale_y; + uint32_t scale_y_frag = (uint32_t)(config->scale_y * PPA_LL_SRM_SCALING_FRAG_MAX) & (PPA_LL_SRM_SCALING_FRAG_MAX - 1); uint32_t new_block_w = 0; uint32_t new_block_h = 0; if (config->rotation_angle == PPA_SRM_ROTATION_ANGLE_0 || config->rotation_angle == PPA_SRM_ROTATION_ANGLE_180) { - new_block_w = (uint32_t)(config->scale_x * config->in.block_w); - new_block_h = (uint32_t)(config->scale_y * config->in.block_h); + new_block_w = (uint32_t)(scale_x_int * config->in.block_w + scale_x_frag * config->in.block_w / PPA_LL_SRM_SCALING_FRAG_MAX); + new_block_h = (uint32_t)(scale_y_int * config->in.block_h + scale_y_frag * config->in.block_h / PPA_LL_SRM_SCALING_FRAG_MAX); } else { - new_block_w = (uint32_t)(config->scale_y * config->in.block_h); - new_block_h = (uint32_t)(config->scale_x * config->in.block_w); + new_block_w = (uint32_t)(scale_y_int * config->in.block_h + scale_y_frag * config->in.block_h / PPA_LL_SRM_SCALING_FRAG_MAX); + new_block_h = (uint32_t)(scale_x_int * config->in.block_w + scale_x_frag * config->in.block_w / PPA_LL_SRM_SCALING_FRAG_MAX); } ESP_RETURN_ON_FALSE(new_block_w <= (config->out.pic_w - config->out.block_offset_x) && new_block_h <= (config->out.pic_h - config->out.block_offset_y), ESP_ERR_INVALID_ARG, TAG, "scale does not fit in the out pic"); + + if (!ppa_check_buffer_alignment(ppa_client, &config->in, true, config->in.block_w) || + !ppa_check_buffer_alignment(ppa_client, &config->out, false, new_block_w)) { + return ESP_ERR_INVALID_ARG; + } + if (config->byte_swap) { PPA_CHECK_CM_SUPPORT_BYTE_SWAP("in.srm", (uint32_t)config->in.srm_cm); } @@ -248,6 +256,7 @@ esp_err_t ppa_do_scale_rotate_mirror(ppa_client_handle_t ppa_client, const ppa_s // Write back and invalidate necessary data (note that the window content is not continuous in the buffer) // Write back in_buffer extended window (alignment not necessary on C2M direction) + uint32_t buf_alignment_size = (uint32_t)ppa_client->engine->platform->buf_alignment_size; uint32_t in_pixel_depth = color_hal_pixel_format_fourcc_get_bit_depth((esp_color_fourcc_t)config->in.srm_cm); // bits uint32_t in_ext_window = (uint32_t)config->in.buffer + config->in.block_offset_y * config->in.pic_w * in_pixel_depth / 8; uint32_t in_ext_window_len = config->in.pic_w * config->in.block_h * in_pixel_depth / 8; @@ -269,10 +278,10 @@ esp_err_t ppa_do_scale_rotate_mirror(ppa_client_handle_t ppa_client, const ppa_s ppa_srm_oper_t *srm_trans_desc = (ppa_srm_oper_t *)trans_on_picked_desc->srm_desc; memcpy(srm_trans_desc, config, sizeof(ppa_srm_oper_config_t)); - srm_trans_desc->scale_x_int = (uint32_t)srm_trans_desc->scale_x; - srm_trans_desc->scale_x_frag = (uint32_t)(srm_trans_desc->scale_x * PPA_LL_SRM_SCALING_FRAG_MAX) & (PPA_LL_SRM_SCALING_FRAG_MAX - 1); - srm_trans_desc->scale_y_int = (uint32_t)srm_trans_desc->scale_y; - srm_trans_desc->scale_y_frag = (uint32_t)(srm_trans_desc->scale_y * PPA_LL_SRM_SCALING_FRAG_MAX) & (PPA_LL_SRM_SCALING_FRAG_MAX - 1); + srm_trans_desc->scale_x_int = scale_x_int; + srm_trans_desc->scale_x_frag = scale_x_frag; + srm_trans_desc->scale_y_int = scale_y_int; + srm_trans_desc->scale_y_frag = scale_y_frag; // SRM processes in blocks. Block x/(y) cannot be scaled to odd number when YUV422/YUV420 is the output color mode // When block size is 16x16, odd number is possible, so needs to make them even // When block size is 32x32, calculated frag values are always even diff --git a/components/esp_driver_ppa/test_apps/main/CMakeLists.txt b/components/esp_driver_ppa/test_apps/main/CMakeLists.txt index 5988460a63..eea601d8b1 100644 --- a/components/esp_driver_ppa/test_apps/main/CMakeLists.txt +++ b/components/esp_driver_ppa/test_apps/main/CMakeLists.txt @@ -5,5 +5,5 @@ set(srcs "test_app_main.c" # the component can be registered as WHOLE_ARCHIVE idf_component_register(SRCS ${srcs} INCLUDE_DIRS "." - PRIV_REQUIRES esp_driver_ppa esp_psram unity esp_mm + PRIV_REQUIRES esp_driver_ppa esp_psram unity esp_mm efuse WHOLE_ARCHIVE) diff --git a/components/esp_driver_ppa/test_apps/main/test_ppa.c b/components/esp_driver_ppa/test_apps/main/test_ppa.c index 8ee2923b54..b9093157b0 100644 --- a/components/esp_driver_ppa/test_apps/main/test_ppa.c +++ b/components/esp_driver_ppa/test_apps/main/test_ppa.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -19,6 +19,7 @@ #include "esp_cache.h" #include "ppa_performance.h" #include "esp_random.h" +#include "esp_efuse.h" #define ALIGN_UP(num, align) (((num) + ((align) - 1)) & ~((align) - 1)) @@ -76,7 +77,9 @@ TEST_CASE("ppa_client_do_ppa_operation", "[PPA]") .mode = PPA_TRANS_MODE_BLOCKING, }; // A SRM client can request to do a SRM operation - TEST_ESP_OK(ppa_do_scale_rotate_mirror(ppa_client_srm_handle, &srm_oper_config)); + if (!esp_efuse_is_flash_encryption_enabled()) { + TEST_ESP_OK(ppa_do_scale_rotate_mirror(ppa_client_srm_handle, &srm_oper_config)); + } // A non-SRM client can not request to do a SRM operation TEST_ESP_ERR(ESP_ERR_INVALID_ARG, ppa_do_scale_rotate_mirror(ppa_client_blend_handle, &srm_oper_config)); @@ -159,6 +162,11 @@ static bool ppa_trans_done_cb(ppa_client_handle_t ppa_client, ppa_event_data_t * TEST_CASE("ppa_pending_transactions_in_queue", "[PPA]") { + // this test tests software correctness, and SRM does not work with flash encrypted if buffer is in external memory, so skip + if (esp_efuse_is_flash_encryption_enabled()) { + TEST_PASS_MESSAGE("Flash encryption is enabled, skip this test"); + } + // A big picture block takes longer time to process, desired for this test case const uint32_t w = 1920; const uint32_t h = 1080; @@ -267,7 +275,7 @@ TEST_CASE("ppa_srm_basic_data_correctness_check", "[PPA]") const uint32_t buf_len = w * h * color_hal_pixel_format_fourcc_get_bit_depth((esp_color_fourcc_t)cm) / 8; // 32 uint32_t out_buf_size = ALIGN_UP(buf_len, 64); - uint8_t *out_buf = heap_caps_aligned_calloc(4, out_buf_size, sizeof(uint8_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT | MALLOC_CAP_DMA); + uint8_t *out_buf = heap_caps_aligned_calloc(4, out_buf_size, sizeof(uint8_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT | MALLOC_CAP_DMA); // located in internal RAM so even w/ flash encrypted, it won't be affected TEST_ASSERT_NOT_NULL(out_buf); esp_cache_msync((void *)out_buf, out_buf_size, ESP_CACHE_MSYNC_FLAG_DIR_C2M); const uint16_t in_buf[16] = { @@ -565,6 +573,11 @@ TEST_CASE("ppa_fill_basic_data_correctness_check", "[PPA]") TEST_CASE("ppa_srm_performance", "[PPA]") { + // SRM does not work with flash encrypted if buffer is in external memory, so skip + if (esp_efuse_is_flash_encryption_enabled()) { + TEST_PASS_MESSAGE("Flash encryption is enabled, skip this test"); + } + // Configurable parameters const uint32_t w = 1920; // 1920 / 1280 / 800 / 640 const uint32_t h = 1080; // 1080 / 720 / 480 @@ -655,8 +668,12 @@ TEST_CASE("ppa_blend_performance", "[PPA]") const ppa_blend_color_mode_t in_fg_cm = PPA_BLEND_COLOR_MODE_ARGB8888; const ppa_blend_color_mode_t out_cm = PPA_BLEND_COLOR_MODE_ARGB8888; - uint32_t in_bg_buf_size = w * h * color_hal_pixel_format_fourcc_get_bit_depth((esp_color_fourcc_t)in_bg_cm) / 8; - uint32_t in_fg_buf_size = w * h * color_hal_pixel_format_fourcc_get_bit_depth((esp_color_fourcc_t)in_fg_cm) / 8; + size_t in_buf_alignment = 4; // no special alignment requirement for input buffers + if (esp_efuse_is_flash_encryption_enabled()) { + in_buf_alignment = SOC_MEMSPI_ENCRYPTION_ALIGNMENT; + } + uint32_t in_bg_buf_size = ALIGN_UP(w * h * color_hal_pixel_format_fourcc_get_bit_depth((esp_color_fourcc_t)in_bg_cm) / 8, in_buf_alignment); + uint32_t in_fg_buf_size = ALIGN_UP(w * h * color_hal_pixel_format_fourcc_get_bit_depth((esp_color_fourcc_t)in_fg_cm) / 8, in_buf_alignment); uint32_t out_buf_size = ALIGN_UP(w * h * color_hal_pixel_format_fourcc_get_bit_depth((esp_color_fourcc_t)out_cm) / 8, 64); uint8_t *out_buf = heap_caps_aligned_calloc(4, out_buf_size, sizeof(uint8_t), MALLOC_CAP_SPIRAM | MALLOC_CAP_DMA); TEST_ASSERT_NOT_NULL(out_buf); @@ -722,10 +739,12 @@ TEST_CASE("ppa_blend_performance", "[PPA]") printf("PPA Blend - Process Time: %lld us\n", oper_time); // Check performance - uint64_t num_pixels_processed = block_w * block_h; - uint64_t px_per_second = (num_pixels_processed - PPA_BLEND_TIME_OFFSET) * 1000 * 1000 / oper_time; - printf("PPA Blend performance = %lld pixels/sec\n", px_per_second); - TEST_ASSERT_GREATER_THAN(PPA_BLEND_MIN_PERFORMANCE_PX_PER_SEC, px_per_second); + if (!esp_efuse_is_flash_encryption_enabled()) { // flash encryption slows down the performance, so skip the check + uint64_t num_pixels_processed = block_w * block_h; + uint64_t px_per_second = (num_pixels_processed - PPA_BLEND_TIME_OFFSET) * 1000 * 1000 / oper_time; + printf("PPA Blend performance = %lld pixels/sec\n", px_per_second); + TEST_ASSERT_GREATER_THAN(PPA_BLEND_MIN_PERFORMANCE_PX_PER_SEC, px_per_second); + } TEST_ESP_OK(ppa_unregister_client(ppa_client_handle)); @@ -780,10 +799,12 @@ TEST_CASE("ppa_fill_performance", "[PPA]") printf("PPA Fill - Process Time: %lld us\n", oper_time); // Check performance - uint64_t num_pixels_processed = block_w * block_h; - uint64_t px_per_second = (num_pixels_processed - PPA_FILL_TIME_OFFSET) * 1000 * 1000 / oper_time; - printf("PPA Blend performance = %lld pixels/sec\n", px_per_second); - TEST_ASSERT_GREATER_THAN(PPA_FILL_MIN_PERFORMANCE_PX_PER_SEC, px_per_second); + if (!esp_efuse_is_flash_encryption_enabled()) { // flash encryption slows down the performance, so skip the check + uint64_t num_pixels_processed = block_w * block_h; + uint64_t px_per_second = (num_pixels_processed - PPA_FILL_TIME_OFFSET) * 1000 * 1000 / oper_time; + printf("PPA Blend performance = %lld pixels/sec\n", px_per_second); + TEST_ASSERT_GREATER_THAN(PPA_FILL_MIN_PERFORMANCE_PX_PER_SEC, px_per_second); + } TEST_ESP_OK(ppa_unregister_client(ppa_client_handle)); @@ -792,6 +813,11 @@ TEST_CASE("ppa_fill_performance", "[PPA]") TEST_CASE("ppa_srm_stress_test", "[PPA]") { + // SRM does not work with flash encrypted if buffer is in external memory, so skip + if (esp_efuse_is_flash_encryption_enabled()) { + TEST_PASS_MESSAGE("Flash encryption is enabled, skip this test"); + } + // Configurable parameters const uint32_t w = 200; const uint32_t h = 200; diff --git a/components/esp_driver_ppa/test_apps/pytest_ppa.py b/components/esp_driver_ppa/test_apps/pytest_ppa.py index ed18219927..c699ab0f43 100644 --- a/components/esp_driver_ppa/test_apps/pytest_ppa.py +++ b/components/esp_driver_ppa/test_apps/pytest_ppa.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut @@ -17,3 +17,16 @@ from pytest_embedded_idf.utils import soc_filtered_targets @idf_parametrize('target', soc_filtered_targets('SOC_PPA_SUPPORTED == 1'), indirect=['target']) def test_ppa(dut: Dut) -> None: dut.run_all_single_board_cases() + + +@pytest.mark.flash_encryption +@pytest.mark.parametrize( + 'config', + [ + 'flash_enc', + ], + indirect=True, +) +@idf_parametrize('target', soc_filtered_targets('SOC_PPA_SUPPORTED == 1'), indirect=['target']) +def test_ppa_flash_encryption(dut: Dut) -> None: + dut.run_all_single_board_cases() diff --git a/components/esp_driver_ppa/test_apps/sdkconfig.ci.flash_enc b/components/esp_driver_ppa/test_apps/sdkconfig.ci.flash_enc new file mode 100644 index 0000000000..5be9651c38 --- /dev/null +++ b/components/esp_driver_ppa/test_apps/sdkconfig.ci.flash_enc @@ -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_hal_dma/esp32c5/include/hal/gdma_ll.h b/components/esp_hal_dma/esp32c5/include/hal/gdma_ll.h index 5b098afb30..9a759a5d57 100644 --- a/components/esp_hal_dma/esp32c5/include/hal/gdma_ll.h +++ b/components/esp_hal_dma/esp32c5/include/hal/gdma_ll.h @@ -17,7 +17,6 @@ #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 5b098afb30..9a759a5d57 100644 --- a/components/esp_hal_dma/esp32c61/include/hal/gdma_ll.h +++ b/components/esp_hal_dma/esp32c61/include/hal/gdma_ll.h @@ -17,7 +17,6 @@ #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 e8a391d29b..23fdc99fb8 100644 --- a/components/esp_hal_dma/esp32h21/include/hal/gdma_ll.h +++ b/components/esp_hal_dma/esp32h21/include/hal/gdma_ll.h @@ -53,7 +53,6 @@ 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 38e434b991..f9c7127989 100644 --- a/components/esp_hal_dma/esp32h4/include/hal/gdma_ll.h +++ b/components/esp_hal_dma/esp32h4/include/hal/gdma_ll.h @@ -17,7 +17,6 @@ #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/dma2d_ll.h b/components/esp_hal_dma/esp32p4/include/hal/dma2d_ll.h index c3f70dbccf..7bc5d94d6b 100644 --- a/components/esp_hal_dma/esp32p4/include/hal/dma2d_ll.h +++ b/components/esp_hal_dma/esp32p4/include/hal/dma2d_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -245,23 +245,23 @@ static inline void dma2d_ll_rx_enable_page_bound_wrap(dma2d_dev_t *dev, uint32_t * @brief Set 2D-DMA RX channel maximum burst reading data length in bytes */ __attribute__((always_inline)) -static inline void dma2d_ll_rx_set_data_burst_length(dma2d_dev_t *dev, uint32_t channel, dma2d_data_burst_length_t length) +static inline void dma2d_ll_rx_set_data_burst_length(dma2d_dev_t *dev, uint32_t channel, uint32_t length) { uint32_t sel; switch (length) { - case DMA2D_DATA_BURST_LENGTH_8: + case 8: sel = 0; break; - case DMA2D_DATA_BURST_LENGTH_16: + case 16: sel = 1; break; - case DMA2D_DATA_BURST_LENGTH_32: + case 32: sel = 2; break; - case DMA2D_DATA_BURST_LENGTH_64: + case 64: sel = 3; break; - case DMA2D_DATA_BURST_LENGTH_128: + case 128: sel = 4; break; default: @@ -761,23 +761,23 @@ static inline void dma2d_ll_tx_enable_page_bound_wrap(dma2d_dev_t *dev, uint32_t * @brief Set 2D-DMA TX channel maximum burst reading data length in bytes */ __attribute__((always_inline)) -static inline void dma2d_ll_tx_set_data_burst_length(dma2d_dev_t *dev, uint32_t channel, dma2d_data_burst_length_t length) +static inline void dma2d_ll_tx_set_data_burst_length(dma2d_dev_t *dev, uint32_t channel, uint32_t length) { uint32_t sel; switch (length) { - case DMA2D_DATA_BURST_LENGTH_8: + case 8: sel = 0; break; - case DMA2D_DATA_BURST_LENGTH_16: + case 16: sel = 1; break; - case DMA2D_DATA_BURST_LENGTH_32: + case 32: sel = 2; break; - case DMA2D_DATA_BURST_LENGTH_64: + case 64: sel = 3; break; - case DMA2D_DATA_BURST_LENGTH_128: + case 128: sel = 4; break; default: 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 a2feabafee..db94709822 100644 --- a/components/esp_hal_dma/esp32p4/include/hal/gdma_ll.h +++ b/components/esp_hal_dma/esp32p4/include/hal/gdma_ll.h @@ -58,7 +58,6 @@ #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 1c4936e273..b3680dda2f 100644 --- a/components/esp_hal_dma/esp32s3/include/hal/gdma_ll.h +++ b/components/esp_hal_dma/esp32s3/include/hal/gdma_ll.h @@ -71,7 +71,6 @@ 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_hal_dma/include/hal/dma2d_types.h b/components/esp_hal_dma/include/hal/dma2d_types.h index 8081c0ff3d..28c1d6fa6a 100644 --- a/components/esp_hal_dma/include/hal/dma2d_types.h +++ b/components/esp_hal_dma/include/hal/dma2d_types.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -116,20 +116,6 @@ typedef enum { DMA2D_CHANNEL_DIRECTION_RX, /*!< 2D-DMA channel direction: RX */ } dma2d_channel_direction_t; -/** - * @brief Enumeration of 2D-DMA data burst length options - * - * Starting from 1, saving 0 for special purpose (upper layer could use 0 to be a default burst length) - */ -typedef enum { - DMA2D_DATA_BURST_LENGTH_8 = 1, /*!< 2D-DMA block size: 8 bytes */ - DMA2D_DATA_BURST_LENGTH_16, /*!< 2D-DMA block size: 16 bytes */ - DMA2D_DATA_BURST_LENGTH_32, /*!< 2D-DMA block size: 32 bytes */ - DMA2D_DATA_BURST_LENGTH_64, /*!< 2D-DMA block size: 64 bytes */ - DMA2D_DATA_BURST_LENGTH_128, /*!< 2D-DMA block size: 128 bytes */ - DMA2D_DATA_BURST_LENGTH_INVALID, /*!< Invalid 2D-DMA block size */ -} dma2d_data_burst_length_t; - /** * @brief Enumeration of 2D-DMA macro block size options * Only useful in DMA2D_DESCRIPTOR_BLOCK_RW_MODE_MULTIPLE mode (dma2d_en = 1, mode = 1) diff --git a/components/esp_hal_ppa/include/hal/ppa_types.h b/components/esp_hal_ppa/include/hal/ppa_types.h index 0bae34032c..9ceb33f413 100644 --- a/components/esp_hal_ppa/include/hal/ppa_types.h +++ b/components/esp_hal_ppa/include/hal/ppa_types.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -8,7 +8,6 @@ #include #include "hal/color_types.h" -#include "hal/dma2d_types.h" #ifdef __cplusplus extern "C" { @@ -115,11 +114,11 @@ typedef enum { * @brief Enumeration of PPA supported data burst length */ typedef enum { - PPA_DATA_BURST_LENGTH_8 = DMA2D_DATA_BURST_LENGTH_8, /*!< Data burst length: 8 bytes */ - PPA_DATA_BURST_LENGTH_16 = DMA2D_DATA_BURST_LENGTH_16, /*!< Data burst length: 16 bytes */ - PPA_DATA_BURST_LENGTH_32 = DMA2D_DATA_BURST_LENGTH_32, /*!< Data burst length: 32 bytes */ - PPA_DATA_BURST_LENGTH_64 = DMA2D_DATA_BURST_LENGTH_64, /*!< Data burst length: 64 bytes */ - PPA_DATA_BURST_LENGTH_128 = DMA2D_DATA_BURST_LENGTH_128, /*!< Data burst length: 128 bytes */ + PPA_DATA_BURST_LENGTH_8 = 8, /*!< Data burst length: 8 bytes */ + PPA_DATA_BURST_LENGTH_16 = 16, /*!< Data burst length: 16 bytes */ + PPA_DATA_BURST_LENGTH_32 = 32, /*!< Data burst length: 32 bytes */ + PPA_DATA_BURST_LENGTH_64 = 64, /*!< Data burst length: 64 bytes */ + PPA_DATA_BURST_LENGTH_128 = 128, /*!< Data burst length: 128 bytes */ } ppa_data_burst_length_t; #ifdef __cplusplus diff --git a/components/esp_hw_support/heap_align_hw.c b/components/esp_hw_support/heap_align_hw.c index d786b3705b..4b97c7e2cf 100644 --- a/components/esp_hw_support/heap_align_hw.c +++ b/components/esp_hw_support/heap_align_hw.c @@ -84,7 +84,7 @@ HEAP_IRAM_ATTR void esp_heap_adjust_alignment_to_hw(size_t *p_alignment, size_t #if SOC_HAS(GDMA) && (SOC_PSRAM_DMA_CAPABLE || SOC_DMA_CAN_ACCESS_FLASH) if ((caps & MALLOC_CAP_DMA) && esp_efuse_is_flash_encryption_enabled()) { - alignment = (alignment > GDMA_LL_GET(ACCESS_ENCRYPTION_MEM_ALIGNMENT)) ? alignment : GDMA_LL_GET(ACCESS_ENCRYPTION_MEM_ALIGNMENT); + alignment = (alignment > SOC_MEMSPI_ENCRYPTION_ALIGNMENT) ? alignment : SOC_MEMSPI_ENCRYPTION_ALIGNMENT; } #endif diff --git a/components/esp_lcd/src/esp_async_fbcpy.c b/components/esp_lcd/src/esp_async_fbcpy.c index 6407cb2899..ae8e95ad21 100644 --- a/components/esp_lcd/src/esp_async_fbcpy.c +++ b/components/esp_lcd/src/esp_async_fbcpy.c @@ -173,6 +173,9 @@ static bool dma2d_job_picked_cb(uint32_t num_chans, const dma2d_trans_channel_in }; dma2d_register_rx_event_callbacks(rx_chan, &dma_cbs, mcp); + // 2D-DMA channel data burst length is set to the maximum burst length by default, which meets the encryption alignment restriction + // so even if flash encryption is enabled, it can work properly + dma2d_set_desc_addr(tx_chan, (intptr_t)(mcp->tx_desc)); dma2d_set_desc_addr(rx_chan, (intptr_t)(mcp->rx_desc)); diff --git a/components/esp_lcd/test_apps/mipi_dsi_lcd/main/test_mipi_dsi_panel.c b/components/esp_lcd/test_apps/mipi_dsi_lcd/main/test_mipi_dsi_panel.c index 8b5488b299..1c642b9ded 100644 --- a/components/esp_lcd/test_apps/mipi_dsi_lcd/main/test_mipi_dsi_panel.c +++ b/components/esp_lcd/test_apps/mipi_dsi_lcd/main/test_mipi_dsi_panel.c @@ -178,9 +178,9 @@ TEST_CASE("MIPI DSI use DMA2D (EK79007)", "[mipi_dsi]") uint8_t *img = NULL; size_t buffer_alignment = 1; - // If flash encryption is enabled, the buffer address and size must be aligned to SOC_GDMA_EXT_MEM_ENC_ALIGNMENT. + // If flash encryption is enabled, the buffer address and size must be aligned to SOC_MEMSPI_ENCRYPTION_ALIGNMENT. if (esp_efuse_is_flash_encryption_enabled()) { - buffer_alignment = SOC_GDMA_EXT_MEM_ENC_ALIGNMENT; + buffer_alignment = SOC_MEMSPI_ENCRYPTION_ALIGNMENT; } img = heap_caps_aligned_calloc(buffer_alignment, 1, TEST_IMG_SIZE, MALLOC_CAP_DMA | MALLOC_CAP_SPIRAM); @@ -249,12 +249,12 @@ TEST_CASE("MIPI DSI use DMA2D (EK79007)", "[mipi_dsi]") size_t start_alignment = 1; size_t src_x_start = 50; size_t src_y_start = 50; - // If flash encryption is enabled, the buffer address and size must be aligned to SOC_GDMA_EXT_MEM_ENC_ALIGNMENT. + // If flash encryption is enabled, the buffer address and size must be aligned to SOC_MEMSPI_ENCRYPTION_ALIGNMENT. if (esp_efuse_is_flash_encryption_enabled()) { - test_block_size = ALIGN_DOWN(test_block_size, SOC_GDMA_EXT_MEM_ENC_ALIGNMENT); - start_alignment = SOC_GDMA_EXT_MEM_ENC_ALIGNMENT; - src_x_start = ALIGN_DOWN(src_x_start, SOC_GDMA_EXT_MEM_ENC_ALIGNMENT); - src_y_start = ALIGN_DOWN(src_y_start, SOC_GDMA_EXT_MEM_ENC_ALIGNMENT); + test_block_size = ALIGN_DOWN(test_block_size, SOC_MEMSPI_ENCRYPTION_ALIGNMENT); + start_alignment = SOC_MEMSPI_ENCRYPTION_ALIGNMENT; + src_x_start = ALIGN_DOWN(src_x_start, SOC_MEMSPI_ENCRYPTION_ALIGNMENT); + src_y_start = ALIGN_DOWN(src_y_start, SOC_MEMSPI_ENCRYPTION_ALIGNMENT); } printf("Add Built-in DMA2D draw bitmap hook\r\n"); diff --git a/components/soc/esp32/include/soc/Kconfig.soc_caps.in b/components/soc/esp32/include/soc/Kconfig.soc_caps.in index 5f0f9b72dd..1af27c97fa 100644 --- a/components/soc/esp32/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32/include/soc/Kconfig.soc_caps.in @@ -531,6 +531,10 @@ config SOC_SPI_MAX_PRE_DIVIDER int default 8192 +config SOC_MEMSPI_ENCRYPTION_ALIGNMENT + int + default 16 + config SOC_LP_TIMER_BIT_WIDTH_LO int default 32 diff --git a/components/soc/esp32/include/soc/soc_caps.h b/components/soc/esp32/include/soc/soc_caps.h index db4801f800..058b3415ec 100644 --- a/components/soc/esp32/include/soc/soc_caps.h +++ b/components/soc/esp32/include/soc/soc_caps.h @@ -271,6 +271,8 @@ // Peripheral supports DIO, DOUT, QIO, or QOUT #define SOC_SPI_PERIPH_SUPPORT_MULTILINE_MODE(spi_host) ({(void)spi_host; 1;}) +#define SOC_MEMSPI_ENCRYPTION_ALIGNMENT 16 /*!< 16-byte alignment restriction to mem addr and size if encryption is enabled */ + /*-------------------------- LP_TIMER CAPS ----------------------------------*/ #define SOC_LP_TIMER_BIT_WIDTH_LO 32 // Bit width of lp_timer low part #define SOC_LP_TIMER_BIT_WIDTH_HI 16 // Bit width of lp_timer high part diff --git a/components/soc/esp32c2/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c2/include/soc/Kconfig.soc_caps.in index 73cd5c76e5..9e9309cd00 100644 --- a/components/soc/esp32c2/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c2/include/soc/Kconfig.soc_caps.in @@ -555,6 +555,10 @@ config SOC_SYSTIMER_ALARM_MISS_COMPENSATE bool default y +config SOC_MEMSPI_ENCRYPTION_ALIGNMENT + int + default 16 + config SOC_LP_TIMER_BIT_WIDTH_LO int default 32 diff --git a/components/soc/esp32c2/include/soc/soc_caps.h b/components/soc/esp32c2/include/soc/soc_caps.h index 15d1db1561..6821a36026 100644 --- a/components/soc/esp32c2/include/soc/soc_caps.h +++ b/components/soc/esp32c2/include/soc/soc_caps.h @@ -256,6 +256,8 @@ #define SOC_SYSTIMER_INT_LEVEL 1 // Systimer peripheral uses level interrupt #define SOC_SYSTIMER_ALARM_MISS_COMPENSATE 1 // Systimer peripheral can generate interrupt immediately if t(target) > t(current) +#define SOC_MEMSPI_ENCRYPTION_ALIGNMENT 16 /*!< 16-byte alignment restriction to mem addr and size if encryption is enabled */ + /*-------------------------- LP_TIMER CAPS ----------------------------------*/ #define SOC_LP_TIMER_BIT_WIDTH_LO 32 // Bit width of lp_timer low part #define SOC_LP_TIMER_BIT_WIDTH_HI 16 // Bit width of lp_timer high part diff --git a/components/soc/esp32c3/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c3/include/soc/Kconfig.soc_caps.in index 438a488b93..1f7763cc4a 100644 --- a/components/soc/esp32c3/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c3/include/soc/Kconfig.soc_caps.in @@ -743,6 +743,10 @@ config SOC_SYSTIMER_ALARM_MISS_COMPENSATE bool default y +config SOC_MEMSPI_ENCRYPTION_ALIGNMENT + int + default 16 + config SOC_LP_TIMER_BIT_WIDTH_LO int default 32 diff --git a/components/soc/esp32c3/include/soc/soc_caps.h b/components/soc/esp32c3/include/soc/soc_caps.h index 699b939334..8eb3101f3a 100644 --- a/components/soc/esp32c3/include/soc/soc_caps.h +++ b/components/soc/esp32c3/include/soc/soc_caps.h @@ -333,6 +333,8 @@ #define SOC_SYSTIMER_INT_LEVEL 1 // Systimer peripheral uses level interrupt #define SOC_SYSTIMER_ALARM_MISS_COMPENSATE 1 // Systimer peripheral can generate interrupt immediately if t(target) > t(current) +#define SOC_MEMSPI_ENCRYPTION_ALIGNMENT 16 /*!< 16-byte alignment restriction to mem addr and size if encryption is enabled */ + /*-------------------------- LP_TIMER CAPS ----------------------------------*/ #define SOC_LP_TIMER_BIT_WIDTH_LO 32 // Bit width of lp_timer low part #define SOC_LP_TIMER_BIT_WIDTH_HI 16 // Bit width of lp_timer high part diff --git a/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in index a0ec2814e5..aa351cdea6 100644 --- a/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in @@ -1067,6 +1067,10 @@ config SOC_MEMSPI_TIMING_TUNING_BY_MSPI_DELAY bool default y +config SOC_MEMSPI_ENCRYPTION_ALIGNMENT + int + default 16 + config SOC_SYSTIMER_COUNTER_NUM int default 2 diff --git a/components/soc/esp32c5/include/soc/soc_caps.h b/components/soc/esp32c5/include/soc/soc_caps.h index 56be78bedb..2fe9aa5cb4 100644 --- a/components/soc/esp32c5/include/soc/soc_caps.h +++ b/components/soc/esp32c5/include/soc/soc_caps.h @@ -437,6 +437,8 @@ #define SOC_SPI_MEM_FLASH_SUPPORT_HPM (1) /*!< Support High Performance Mode */ #define SOC_MEMSPI_TIMING_TUNING_BY_MSPI_DELAY (1) +#define SOC_MEMSPI_ENCRYPTION_ALIGNMENT 16 /*!< 16-byte alignment restriction to mem addr and size if encryption is enabled */ + /*-------------------------- SYSTIMER CAPS ----------------------------------*/ // TODO: [ESP32C5] IDF-8707 #define SOC_SYSTIMER_COUNTER_NUM 2 // Number of counter units diff --git a/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in index 5967b81444..3f39b1c186 100644 --- a/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in @@ -911,6 +911,10 @@ config SOC_SPI_MEM_SUPPORT_WRAP bool default y +config SOC_MEMSPI_ENCRYPTION_ALIGNMENT + int + default 16 + config SOC_SYSTIMER_COUNTER_NUM int default 2 diff --git a/components/soc/esp32c6/include/soc/soc_caps.h b/components/soc/esp32c6/include/soc/soc_caps.h index 72801cddd5..07a5fc7940 100644 --- a/components/soc/esp32c6/include/soc/soc_caps.h +++ b/components/soc/esp32c6/include/soc/soc_caps.h @@ -385,6 +385,8 @@ #define SOC_SPI_MEM_SUPPORT_CHECK_SUS (1) #define SOC_SPI_MEM_SUPPORT_WRAP (1) +#define SOC_MEMSPI_ENCRYPTION_ALIGNMENT 16 /*!< 16-byte alignment restriction to mem addr and size if encryption is enabled */ + /*-------------------------- SYSTIMER CAPS ----------------------------------*/ #define SOC_SYSTIMER_COUNTER_NUM 2 // Number of counter units #define SOC_SYSTIMER_ALARM_NUM 3 // Number of alarm units diff --git a/components/soc/esp32c61/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c61/include/soc/Kconfig.soc_caps.in index e829ab603d..eb680ac703 100644 --- a/components/soc/esp32c61/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c61/include/soc/Kconfig.soc_caps.in @@ -807,6 +807,10 @@ config SOC_MEMSPI_TIMING_TUNING_BY_MSPI_DELAY bool default y +config SOC_MEMSPI_ENCRYPTION_ALIGNMENT + int + default 16 + config SOC_SYSTIMER_COUNTER_NUM int default 2 diff --git a/components/soc/esp32c61/include/soc/soc_caps.h b/components/soc/esp32c61/include/soc/soc_caps.h index 2273aa18ff..e873863c64 100644 --- a/components/soc/esp32c61/include/soc/soc_caps.h +++ b/components/soc/esp32c61/include/soc/soc_caps.h @@ -341,6 +341,8 @@ #define SOC_SPI_MEM_FLASH_SUPPORT_HPM (1) /*!< Support High Performance Mode */ #define SOC_MEMSPI_TIMING_TUNING_BY_MSPI_DELAY (1) +#define SOC_MEMSPI_ENCRYPTION_ALIGNMENT 16 /*!< 16-byte alignment restriction to mem addr and size if encryption is enabled */ + /*-------------------------- SYSTIMER CAPS ----------------------------------*/ #define SOC_SYSTIMER_COUNTER_NUM 2 // Number of counter units #define SOC_SYSTIMER_ALARM_NUM 3 // Number of alarm units diff --git a/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in b/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in index c8d33b40a7..4861594770 100644 --- a/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in @@ -915,6 +915,10 @@ config SOC_SPI_MEM_SUPPORT_WRAP bool default y +config SOC_MEMSPI_ENCRYPTION_ALIGNMENT + int + default 16 + config SOC_SYSTIMER_COUNTER_NUM int default 2 diff --git a/components/soc/esp32h2/include/soc/soc_caps.h b/components/soc/esp32h2/include/soc/soc_caps.h index add8a54d3f..6b826a201f 100644 --- a/components/soc/esp32h2/include/soc/soc_caps.h +++ b/components/soc/esp32h2/include/soc/soc_caps.h @@ -401,6 +401,8 @@ #define SOC_SPI_MEM_SUPPORT_CHECK_SUS (1) #define SOC_SPI_MEM_SUPPORT_WRAP (1) +#define SOC_MEMSPI_ENCRYPTION_ALIGNMENT 16 /*!< 16-byte alignment restriction to mem addr and size if encryption is enabled */ + /*-------------------------- SYSTIMER CAPS ----------------------------------*/ #define SOC_SYSTIMER_COUNTER_NUM 2 // Number of counter units #define SOC_SYSTIMER_ALARM_NUM 3 // Number of alarm units diff --git a/components/soc/esp32h21/include/soc/Kconfig.soc_caps.in b/components/soc/esp32h21/include/soc/Kconfig.soc_caps.in index c6eb179d90..692dbefe85 100644 --- a/components/soc/esp32h21/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32h21/include/soc/Kconfig.soc_caps.in @@ -651,6 +651,10 @@ config SOC_SPI_MEM_SUPPORT_WRAP bool default y +config SOC_MEMSPI_ENCRYPTION_ALIGNMENT + int + default 16 + config SOC_SYSTIMER_COUNTER_NUM int default 2 diff --git a/components/soc/esp32h21/include/soc/soc_caps.h b/components/soc/esp32h21/include/soc/soc_caps.h index c74717ef9e..d10d57a7ac 100644 --- a/components/soc/esp32h21/include/soc/soc_caps.h +++ b/components/soc/esp32h21/include/soc/soc_caps.h @@ -387,6 +387,8 @@ #define SOC_SPI_MEM_SUPPORT_CHECK_SUS (1) #define SOC_SPI_MEM_SUPPORT_WRAP (1) +#define SOC_MEMSPI_ENCRYPTION_ALIGNMENT 16 /*!< 16-byte alignment restriction to mem addr and size if encryption is enabled */ + /*-------------------------- SYSTIMER CAPS ----------------------------------*/ #define SOC_SYSTIMER_COUNTER_NUM 2 // Number of counter units #define SOC_SYSTIMER_ALARM_NUM 3 // Number of alarm units diff --git a/components/soc/esp32h4/include/soc/Kconfig.soc_caps.in b/components/soc/esp32h4/include/soc/Kconfig.soc_caps.in index c3187f8925..e40710931f 100644 --- a/components/soc/esp32h4/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32h4/include/soc/Kconfig.soc_caps.in @@ -687,6 +687,10 @@ config SOC_SPI_MEM_SUPPORT_WRAP bool default y +config SOC_MEMSPI_ENCRYPTION_ALIGNMENT + int + default 16 + config SOC_SYSTIMER_COUNTER_NUM int default 2 diff --git a/components/soc/esp32h4/include/soc/soc_caps.h b/components/soc/esp32h4/include/soc/soc_caps.h index 767f3a0e99..8f3c45d255 100644 --- a/components/soc/esp32h4/include/soc/soc_caps.h +++ b/components/soc/esp32h4/include/soc/soc_caps.h @@ -385,6 +385,8 @@ #define SOC_SPI_MEM_SUPPORT_CHECK_SUS (1) #define SOC_SPI_MEM_SUPPORT_WRAP (1) +#define SOC_MEMSPI_ENCRYPTION_ALIGNMENT 16 /*!< 16-byte alignment restriction to mem addr and size if encryption is enabled */ + /*-------------------------- SYSTIMER CAPS ----------------------------------*/ #define SOC_SYSTIMER_COUNTER_NUM 2 // Number of counter units #define SOC_SYSTIMER_ALARM_NUM 3 // Number of alarm units diff --git a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in index 5e8afc3089..c760f1a1ef 100644 --- a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in @@ -1439,6 +1439,10 @@ config SOC_SPI_MEM_FLASH_SUPPORT_HPM bool default y +config SOC_MEMSPI_ENCRYPTION_ALIGNMENT + int + default 16 + config SOC_SYSTIMER_COUNTER_NUM int default 2 diff --git a/components/soc/esp32p4/include/soc/soc_caps.h b/components/soc/esp32p4/include/soc/soc_caps.h index 8e4e2f8dcc..7a14166360 100644 --- a/components/soc/esp32p4/include/soc/soc_caps.h +++ b/components/soc/esp32p4/include/soc/soc_caps.h @@ -553,6 +553,8 @@ #define SOC_SPI_MEM_FLASH_SUPPORT_HPM (1) /*!< Support High Performance Mode */ +#define SOC_MEMSPI_ENCRYPTION_ALIGNMENT 16 /*!< 16-byte alignment restriction to mem addr and size if encryption is enabled */ + /*-------------------------- SYSTIMER CAPS ----------------------------------*/ #define SOC_SYSTIMER_COUNTER_NUM 2 // Number of counter units #define SOC_SYSTIMER_ALARM_NUM 3 // Number of alarm units @@ -632,6 +634,7 @@ #define SOC_FLASH_ENCRYPTION_XTS_AES_128 1 /* SOC_EFUSE_XTS_AES_KEY_128 (1) || SOC_KEY_MANAGER_FE_KEY_DEPLOY_XTS_AES_128 (1) */ #define SOC_FLASH_ENCRYPTION_XTS_AES_256 1 /* SOC_EFUSE_XTS_AES_KEY_256 (1) || SOC_KEY_MANAGER_FE_KEY_DEPLOY_XTS_AES_256 (1) */ #define SOC_FLASH_ENCRYPTION_XTS_AES_SUPPORT_PSEUDO_ROUND 1 /*!< Only available in chip version above 3.0 */ + /*-------------------------- MEMPROT CAPS ------------------------------------*/ /*-------------------------- UART CAPS ---------------------------------------*/ diff --git a/components/soc/esp32p4/register/hw_ver1/soc/dma2d_struct.h b/components/soc/esp32p4/register/hw_ver1/soc/dma2d_struct.h index a63f6d64ff..a9392e08dd 100644 --- a/components/soc/esp32p4/register/hw_ver1/soc/dma2d_struct.h +++ b/components/soc/esp32p4/register/hw_ver1/soc/dma2d_struct.h @@ -33,8 +33,12 @@ typedef union { uint32_t outdscr_burst_en_chn:1; /** out_ecc_aes_en_chn : R/W; bitpos: [3]; default: 0; * When access address space is ecc/aes area, this bit should be set to 1. In this - * case, the start address of square should be 16-bit aligned. The width of square - * multiply byte number of one pixel should be 16-bit aligned. + * case, the start address of square should be 16-byte aligned. The width of square + * multiply byte number of one pixel should be 16-byte aligned. + * + * 2D-DMA w/ flash encryption enabled can still work properly even if this bit is not set to 1 + * Meanwhile, enabling this bit will restrict addr and size in internal RAM also has to be 16-byte aligned + * Therefore, this bit is not used. */ uint32_t out_ecc_aes_en_chn:1; /** out_check_owner_chn : R/W; bitpos: [4]; default: 0; @@ -749,8 +753,12 @@ typedef union { uint32_t indscr_burst_en_chn:1; /** in_ecc_aes_en_chn : R/W; bitpos: [3]; default: 0; * When access address space is ecc/aes area, this bit should be set to 1. In this - * case, the start address of square should be 16-bit aligned. The width of square - * multiply byte number of one pixel should be 16-bit aligned. + * case, the start address of square should be 16-byte aligned. The width of square + * multiply byte number of one pixel should be 16-byte aligned. + * + * 2D-DMA w/ flash encryption enabled can still work properly even if this bit is not set to 1 + * Meanwhile, enabling this bit will restrict addr and size in internal RAM also has to be 16-byte aligned + * Therefore, this bit is not used. */ uint32_t in_ecc_aes_en_chn:1; /** in_check_owner_chn : R/W; bitpos: [4]; default: 0; diff --git a/components/soc/esp32p4/register/hw_ver3/soc/dma2d_struct.h b/components/soc/esp32p4/register/hw_ver3/soc/dma2d_struct.h index 7105d670bc..2164353cce 100644 --- a/components/soc/esp32p4/register/hw_ver3/soc/dma2d_struct.h +++ b/components/soc/esp32p4/register/hw_ver3/soc/dma2d_struct.h @@ -32,8 +32,12 @@ typedef union { uint32_t outdscr_burst_en_chn:1; /** out_ecc_aes_en_chn : R/W; bitpos: [3]; default: 0; * When access address space is ecc/aes area, this bit should be set to 1. In this - * case, the start address of square should be 16-bit aligned. The width of square - * multiply byte number of one pixel should be 16-bit aligned. + * case, the start address of square should be 16-byte aligned. The width of square + * multiply byte number of one pixel should be 16-byte aligned. + * + * 2D-DMA w/ flash encryption enabled can still work properly even if this bit is not set to 1 + * Meanwhile, enabling this bit will restrict addr and size in internal RAM also has to be 16-byte aligned + * Therefore, this bit is not used. */ uint32_t out_ecc_aes_en_chn:1; /** out_check_owner_chn : R/W; bitpos: [4]; default: 0; @@ -746,8 +750,12 @@ typedef union { uint32_t indscr_burst_en_chn:1; /** in_ecc_aes_en_chn : R/W; bitpos: [3]; default: 0; * When access address space is ecc/aes area, this bit should be set to 1. In this - * case, the start address of square should be 16-bit aligned. The width of square - * multiply byte number of one pixel should be 16-bit aligned. + * case, the start address of square should be 16-byte aligned. The width of square + * multiply byte number of one pixel should be 16-byte aligned. + * + * 2D-DMA w/ flash encryption enabled can still work properly even if this bit is not set to 1 + * Meanwhile, enabling this bit will restrict addr and size in internal RAM also has to be 16-byte aligned + * Therefore, this bit is not used. */ uint32_t in_ecc_aes_en_chn:1; /** in_check_owner_chn : R/W; bitpos: [4]; default: 0; diff --git a/components/soc/esp32s2/include/soc/Kconfig.soc_caps.in b/components/soc/esp32s2/include/soc/Kconfig.soc_caps.in index 90b63cfc99..14049a85c8 100644 --- a/components/soc/esp32s2/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32s2/include/soc/Kconfig.soc_caps.in @@ -627,6 +627,10 @@ config SOC_MEMSPI_IS_INDEPENDENT bool default y +config SOC_MEMSPI_ENCRYPTION_ALIGNMENT + int + default 16 + config SOC_SYSTIMER_COUNTER_NUM int default 1 diff --git a/components/soc/esp32s2/include/soc/soc_caps.h b/components/soc/esp32s2/include/soc/soc_caps.h index 7b6dc0cc66..e454af050f 100644 --- a/components/soc/esp32s2/include/soc/soc_caps.h +++ b/components/soc/esp32s2/include/soc/soc_caps.h @@ -293,6 +293,8 @@ #define SOC_MEMSPI_IS_INDEPENDENT 1 +#define SOC_MEMSPI_ENCRYPTION_ALIGNMENT 16 /*!< 16-byte alignment restriction to mem addr and size if encryption is enabled */ + /*-------------------------- SYSTIMER CAPS ----------------------------------*/ #define SOC_SYSTIMER_COUNTER_NUM (1U) // Number of counter units #define SOC_SYSTIMER_ALARM_NUM 3 // Number of alarm units diff --git a/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in b/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in index cefb6a2521..7b500cf80e 100644 --- a/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in @@ -1179,6 +1179,10 @@ config SOC_SPI_MEM_FLASH_SUPPORT_HPM bool default y +config SOC_MEMSPI_ENCRYPTION_ALIGNMENT + int + default 16 + config SOC_COEX_HW_PTI bool default y diff --git a/components/soc/esp32s3/include/soc/soc_caps.h b/components/soc/esp32s3/include/soc/soc_caps.h index ef117e6673..261987e68f 100644 --- a/components/soc/esp32s3/include/soc/soc_caps.h +++ b/components/soc/esp32s3/include/soc/soc_caps.h @@ -484,6 +484,8 @@ #define SOC_SPI_MEM_FLASH_SUPPORT_HPM (1) /*!< Support High Performance Mode */ +#define SOC_MEMSPI_ENCRYPTION_ALIGNMENT 16 /*!< 16-byte alignment restriction to mem addr and size if encryption is enabled */ + /*-------------------------- COEXISTENCE HARDWARE PTI CAPS -------------------------------*/ #define SOC_COEX_HW_PTI (1) diff --git a/docs/en/api-reference/peripherals/lcd/dsi_lcd.rst b/docs/en/api-reference/peripherals/lcd/dsi_lcd.rst index 4afa6032c3..5d15966550 100644 --- a/docs/en/api-reference/peripherals/lcd/dsi_lcd.rst +++ b/docs/en/api-reference/peripherals/lcd/dsi_lcd.rst @@ -94,7 +94,7 @@ MIPI DSI Interfaced LCD .. note:: - Due to hardware limitation, if external memory encryption is enabled, DMA2D can only access address and length that are aligned to 16 bytes. You need to ensure that your draw buffer's address and length are aligned to 16 bytes. :example:`peripherals/lcd/mipi_dsi` shows how to use LVGL to constrain the redrawn area to ensure alignment. + Due to hardware limitation, if external memory encryption is enabled, DMA2D can only access address and length that are aligned to {IDF_TARGET_SOC_MEMSPI_ENCRYPTION_ALIGNMENT} bytes. You need to ensure that your draw buffer's address and length are aligned to {IDF_TARGET_SOC_MEMSPI_ENCRYPTION_ALIGNMENT} bytes. :example:`peripherals/lcd/mipi_dsi` shows how to use LVGL to constrain the redrawn area to ensure alignment. If you need more advanced applications, you can add a custom hook for draw bitmap, such as using PPA to implement rotation, scaling, etc. diff --git a/docs/en/api-reference/peripherals/ppa.rst b/docs/en/api-reference/peripherals/ppa.rst index 3a6f64fe55..9ae45f3a9e 100644 --- a/docs/en/api-reference/peripherals/ppa.rst +++ b/docs/en/api-reference/peripherals/ppa.rst @@ -44,6 +44,7 @@ The following sections detail the design of the PPA driver: - :ref:`ppa-client-registration` - Covers how to register a PPA client to perform any PPA operations. - :ref:`ppa-register-callback` - Covers how to hook user specific code to PPA driver event callback function. - :ref:`ppa-perform-operation` - Covers how to perform a PPA operation. +- :ref:`ppa-buffer-alignment` - Covers the buffer alignment requirements for PPA input and output buffers. - :ref:`ppa-thread-safety` - Covers the usage of the PPA operation APIs in thread safety aspect. - :ref:`ppa-performance-overview` - Covers the performance of PPA operations. @@ -129,6 +130,28 @@ Call :cpp:func:`ppa_do_fill` to fill a target block inside a picture. :cpp:type:`ppa_trans_mode_t` is a field configurable to all the PPA operation APIs. It decides whether you want the call to the PPA operation API to block until the transaction finishes or to return immediately after the transaction is pushed to the internal queue. +.. _ppa-buffer-alignment: + +Buffer Alignment +^^^^^^^^^^^^^^^^ + +The PPA requires certain buffer alignment rules to ensure memory access correctness: + +- Cache line alignment (output buffer only): + + - The ``out.buffer`` address and ``out.buffer_size`` must be aligned to the cache line size (see Kconfig option :ref:`CONFIG_CACHE_L2_CACHE_LINE_SIZE`). + +- Flash encryption alignment (when flash encryption is enabled and the buffers are located in external memory): + + - The byte width of the block must be aligned to {IDF_TARGET_SOC_MEMSPI_ENCRYPTION_ALIGNMENT} bytes. + - The starting address of each row of the block must be aligned to {IDF_TARGET_SOC_MEMSPI_ENCRYPTION_ALIGNMENT} bytes. + + Additionally, when accessing encrypted external memory, the PPA's DMA data burst length must be greater than or equal to {IDF_TARGET_SOC_MEMSPI_ENCRYPTION_ALIGNMENT} bytes. If a smaller burst length is configured, the driver will automatically increase it to meet this requirement. + + .. warning:: + + SRM engine processes the picture by macro blocks, where the alignment of the macro blocks is uncontrollable, thus if the buffer is in external memory, SRM operation is unable to work with flash encrypted. + .. _ppa-thread-safety: Thread Safety 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 082052d249..71a7733c4c 100644 --- a/docs/zh_CN/api-reference/peripherals/lcd/dsi_lcd.rst +++ b/docs/zh_CN/api-reference/peripherals/lcd/dsi_lcd.rst @@ -94,7 +94,7 @@ MIPI DSI 接口的 LCD .. note:: - 由于硬件限制,如果启用了外部存储加密,则 DMA2D 只能访问地址和长度都对齐到 16 字节的地址空间。你需要确保你的绘制 buffer 的地址和长度都对齐到 16 字节。 :example:`peripherals/lcd/mipi_dsi` 演示了如何使用 LVGL 控制重新绘制区域来确保对齐。 + 由于硬件限制,如果启用了外部存储加密,则 DMA2D 只能访问地址和长度都对齐到 {IDF_TARGET_SOC_MEMSPI_ENCRYPTION_ALIGNMENT} 字节的地址空间。你需要确保你的绘制 buffer 的地址和长度都对齐到 {IDF_TARGET_SOC_MEMSPI_ENCRYPTION_ALIGNMENT} 字节。 :example:`peripherals/lcd/mipi_dsi` 演示了如何使用 LVGL 控制重新绘制区域来确保对齐。 若需更高级的应用,用户可为绘制位图添加自定义钩子,例如通过 PPA 实现旋转、缩放等操作。 diff --git a/docs/zh_CN/api-reference/peripherals/ppa.rst b/docs/zh_CN/api-reference/peripherals/ppa.rst index c9b4841413..f1e2e37003 100644 --- a/docs/zh_CN/api-reference/peripherals/ppa.rst +++ b/docs/zh_CN/api-reference/peripherals/ppa.rst @@ -44,6 +44,7 @@ - :ref:`ppa-client-registration` - 涵盖如何注册 PPA 客户端来执行一切 PPA 操作。 - :ref:`ppa-register-callback` - 涵盖如何将用户特定代码挂接到 PPA 驱动程序事件回调函数。 - :ref:`ppa-perform-operation` - 涵盖如何执行 PPA 操作。 +- :ref:`ppa-buffer-alignment` - 涵盖 PPA 输入和输出缓冲区的内存对齐要求。 - :ref:`ppa-thread-safety`- 涵盖在线程安全方面使用 PPA 操作 API 的情况。 - :ref:`ppa-performance-overview` - 涵盖 PPA 操作的性能。 @@ -129,6 +130,28 @@ PPA 操作包括: :cpp:type:`ppa_trans_mode_t` 为可配置字段,适用于所有 PPA 操作 API。可以配置该字段,在调用 PPA 操作 API 时等待操作完成后再返回,或者在事务推送到内部队列后立即返回。 +.. _ppa-buffer-alignment: + +缓存区对齐要求 +^^^^^^^^^^^^^^ + +PPA 缓存区需要满足以下对齐要求,以确保存储器访问的正确性: + +- 缓冲行对齐(仅针对输出缓存区): + + - ``out.buffer`` 地址和 ``out.buffer_size`` 大小必须与缓冲行大小对齐(请参阅 Kconfig 选项 :ref:`CONFIG_CACHE_L2_CACHE_LINE_SIZE`)。 + +- 存储加密对齐(当存储加密启用且缓冲区位于外部存储空间时): + + - 块的字节宽度必须与 {IDF_TARGET_SOC_MEMSPI_ENCRYPTION_ALIGNMENT} 字节对齐。 + - 块每行的起始地址必须与 {IDF_TARGET_SOC_MEMSPI_ENCRYPTION_ALIGNMENT} 字节对齐。 + + 此外,当访问加密外部存储空间时,PPA 的 DMA 数据突发长度必须大于或等于 {IDF_TARGET_SOC_MEMSPI_ENCRYPTION_ALIGNMENT} 字节。如果配置的突发长度小于该值,驱动程序将自动增加到满足该要求。 + + .. warning:: + + SRM 引擎以宏块为单位处理图片,而宏块的对齐无法受到控制,因此如果缓冲区位于外部存储空间,则 SRM 操作在存储加密的情况下无法正常工作。 + .. _ppa-thread-safety: 线程安全