From 9362907287564917b7fe7e9d8b82b8cdd4b02473 Mon Sep 17 00:00:00 2001 From: Song Ruo Jing Date: Wed, 14 Jan 2026 17:31:52 +0800 Subject: [PATCH] feat(dma2d,ppa): Support flash encryption for DMA2D and PPA --- .../include/esp_private/dma2d.h | 3 +- components/esp_driver_dma/src/dma2d.c | 26 ++++- components/esp_driver_dma/src/gdma.c | 2 +- .../test_apps/.build-test-rules.yml | 2 +- .../test_apps/dma/main/test_gdma.c | 2 +- .../test_apps/dma/main/test_gdma_crc.c | 4 +- .../test_apps/dma/pytest_dma.py | 8 +- ..._mem_encryption => sdkconfig.ci.flash_enc} | 0 .../test_apps/dma2d/main/CMakeLists.txt | 2 +- .../test_apps/dma2d/main/test_dma2d.c | 104 +++++++++++++----- .../test_apps/dma2d/pytest_dma2d.py | 14 ++- .../test_apps/dma2d/sdkconfig.ci.flash_enc | 9 ++ components/esp_driver_jpeg/jpeg_decode.c | 6 +- components/esp_driver_jpeg/jpeg_encode.c | 6 +- components/esp_driver_ppa/CMakeLists.txt | 2 +- .../esp_driver_ppa/include/driver/ppa.h | 2 + components/esp_driver_ppa/src/ppa_blend.c | 14 ++- components/esp_driver_ppa/src/ppa_core.c | 52 ++++++++- components/esp_driver_ppa/src/ppa_fill.c | 11 +- components/esp_driver_ppa/src/ppa_priv.h | 2 + components/esp_driver_ppa/src/ppa_srm.c | 33 ++++-- .../test_apps/main/CMakeLists.txt | 2 +- .../esp_driver_ppa/test_apps/main/test_ppa.c | 52 ++++++--- .../esp_driver_ppa/test_apps/pytest_ppa.py | 15 ++- .../test_apps/sdkconfig.ci.flash_enc | 9 ++ .../esp_hal_dma/esp32c5/include/hal/gdma_ll.h | 1 - .../esp32c61/include/hal/gdma_ll.h | 1 - .../esp32h21/include/hal/gdma_ll.h | 1 - .../esp_hal_dma/esp32h4/include/hal/gdma_ll.h | 1 - .../esp32p4/include/hal/dma2d_ll.h | 26 ++--- .../esp_hal_dma/esp32p4/include/hal/gdma_ll.h | 1 - .../esp_hal_dma/esp32s3/include/hal/gdma_ll.h | 1 - .../esp32s31/include/hal/gdma_ll.h | 1 - .../esp_hal_dma/include/hal/dma2d_types.h | 16 +-- .../esp_hal_ppa/include/hal/ppa_types.h | 13 +-- components/esp_hw_support/heap_align_hw.c | 2 +- components/esp_lcd/src/esp_async_fbcpy.c | 3 + .../mipi_dsi_lcd/main/test_mipi_dsi_panel.c | 14 +-- .../soc/esp32/include/soc/Kconfig.soc_caps.in | 4 + components/soc/esp32/include/soc/soc_caps.h | 2 + .../esp32c2/include/soc/Kconfig.soc_caps.in | 4 + components/soc/esp32c2/include/soc/soc_caps.h | 2 + .../esp32c3/include/soc/Kconfig.soc_caps.in | 4 + components/soc/esp32c3/include/soc/soc_caps.h | 2 + .../esp32c5/include/soc/Kconfig.soc_caps.in | 4 + components/soc/esp32c5/include/soc/soc_caps.h | 2 + .../esp32c6/include/soc/Kconfig.soc_caps.in | 4 + components/soc/esp32c6/include/soc/soc_caps.h | 2 + .../esp32c61/include/soc/Kconfig.soc_caps.in | 4 + .../soc/esp32c61/include/soc/soc_caps.h | 2 + .../esp32h2/include/soc/Kconfig.soc_caps.in | 4 + components/soc/esp32h2/include/soc/soc_caps.h | 2 + .../esp32h21/include/soc/Kconfig.soc_caps.in | 4 + .../soc/esp32h21/include/soc/soc_caps.h | 2 + .../esp32h4/include/soc/Kconfig.soc_caps.in | 4 + components/soc/esp32h4/include/soc/soc_caps.h | 2 + .../esp32p4/include/soc/Kconfig.soc_caps.in | 4 + components/soc/esp32p4/include/soc/soc_caps.h | 3 + .../register/hw_ver1/soc/dma2d_struct.h | 16 ++- .../register/hw_ver3/soc/dma2d_struct.h | 16 ++- .../esp32s2/include/soc/Kconfig.soc_caps.in | 4 + components/soc/esp32s2/include/soc/soc_caps.h | 2 + .../esp32s3/include/soc/Kconfig.soc_caps.in | 20 ++-- components/soc/esp32s3/include/soc/soc_caps.h | 10 +- .../esp32s31/include/soc/Kconfig.soc_caps.in | 4 + .../soc/esp32s31/include/soc/soc_caps.h | 2 + .../soc/esp32s31/register/soc/dma2d_struct.h | 16 ++- .../api-reference/peripherals/lcd/dsi_lcd.rst | 2 +- docs/en/api-reference/peripherals/ppa.rst | 23 ++++ .../api-reference/peripherals/lcd/dsi_lcd.rst | 2 +- docs/zh_CN/api-reference/peripherals/ppa.rst | 23 ++++ 71 files changed, 499 insertions(+), 165 deletions(-) rename components/esp_driver_dma/test_apps/dma/{sdkconfig.ci.ext_mem_encryption => sdkconfig.ci.flash_enc} (100%) create mode 100644 components/esp_driver_dma/test_apps/dma2d/sdkconfig.ci.flash_enc create mode 100644 components/esp_driver_ppa/test_apps/sdkconfig.ci.flash_enc diff --git a/components/esp_driver_dma/include/esp_private/dma2d.h b/components/esp_driver_dma/include/esp_private/dma2d.h index c5081742987..9c488ef7a84 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 748dc00ca0b..a215ec5f1a2 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 TCM (addr not in TCM is IDF restriction) ESP_GOTO_ON_FALSE_ISR((desc_base_addr & 0x7) == 0 && !esp_ptr_in_tcm((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 98c24bccd92..4c54195d89a 100644 --- a/components/esp_driver_dma/src/gdma.c +++ b/components/esp_driver_dma/src/gdma.c @@ -437,7 +437,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 0c09e5ca3fa..fb45cdd41f6 100644 --- a/components/esp_driver_dma/test_apps/.build-test-rules.yml +++ b/components/esp_driver_dma/test_apps/.build-test-rules.yml @@ -3,7 +3,7 @@ components/esp_driver_dma/test_apps/dma: disable: - if: SOC_GDMA_SUPPORTED != 1 and SOC_CP_DMA_SUPPORTED != 1 - - if: CONFIG_NAME == "ext_mem_encryption" and SOC_FLASH_ENC_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 953120f6b71..cdefe582a07 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 @@ -307,7 +307,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 9ab75ac5521..2a8233f6906 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 a684d7fdc58..6c73c61215e 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 02fd540ce6d..bd6d24b9d8f 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 580f485c900..27b1ef060b3 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 f7f936fc3c8..ee1cb98f3c1 100644 --- a/components/esp_driver_dma/test_apps/dma2d/pytest_dma2d.py +++ b/components/esp_driver_dma/test_apps/dma2d/pytest_dma2d.py @@ -15,6 +15,18 @@ from pytest_embedded_idf.utils import soc_filtered_targets indirect=True, ) @idf_parametrize('target', soc_filtered_targets('SOC_DMA2D_SUPPORTED == 1'), indirect=['target']) -@pytest.mark.temp_skip_ci(targets=['esp32p4'], reason='p4 rev3 migration') 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 00000000000..5be9651c381 --- /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 5c7931d3a27..22032941b0b 100644 --- a/components/esp_driver_jpeg/jpeg_decode.c +++ b/components/esp_driver_jpeg/jpeg_decode.c @@ -526,13 +526,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 363bb37a2a9..e4aa4ba5853 100644 --- a/components/esp_driver_jpeg/jpeg_encode.c +++ b/components/esp_driver_jpeg/jpeg_encode.c @@ -410,13 +410,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 4e98be6b021..5933dc04792 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 5a3917d88d0..9eacd523bae 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 9606bdebdd1..e3cd6816c04 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 4b1ba3c7063..d0047524b04 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 30a7d79f27a..70fe4278d91 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 4dc7cc1ece4..4f629f4bb85 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 03fdc93342f..88b7d6cfeed 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 5988460a63c..eea601d8b18 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 8ee2923b546..b9093157b02 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 78d7bff0da5..b0b63f90006 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 @@ -31,3 +31,16 @@ def test_ppa(dut: Dut) -> None: @idf_parametrize('target', ['esp32p4'], indirect=['target']) def test_ppa_esp32p4_eco4(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 00000000000..5be9651c381 --- /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 5b098afb30d..9a759a5d575 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 5b098afb30d..9a759a5d575 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 e8a391d29b6..23fdc99fb82 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 38e434b9910..f9c71279891 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 c3f70dbccfa..7bc5d94d6b7 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 5b21def6ae2..4d7d80f7ba0 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 1c4936e273c..b3680dda2fc 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/esp32s31/include/hal/gdma_ll.h b/components/esp_hal_dma/esp32s31/include/hal/gdma_ll.h index b445d9b505e..089a74167e0 100644 --- a/components/esp_hal_dma/esp32s31/include/hal/gdma_ll.h +++ b/components/esp_hal_dma/esp32s31/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 #define GDMA_LL_AHB_M2M_CAPABLE_PAIR_MASK 0x1F // pair 0,1,2,3,4 are M2M capable #define GDMA_LL_AXI_M2M_CAPABLE_PAIR_MASK 0x07 // pair 0,1,2 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 8081c0ff3d9..28c1d6fa6a3 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 0bae34032c0..9ceb33f4132 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 d786b3705bd..4b97c7e2cfe 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 6407cb28992..ae8e95ad217 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 8b5488b299b..1c642b9ded6 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 575d14a1207..6c0133869d6 100644 --- a/components/soc/esp32/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32/include/soc/Kconfig.soc_caps.in @@ -511,6 +511,10 @@ config SOC_SPI_MAXIMUM_BUFFER_SIZE int default 64 +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 b67ba9a2aca..5c724911a53 100644 --- a/components/soc/esp32/include/soc/soc_caps.h +++ b/components/soc/esp32/include/soc/soc_caps.h @@ -259,6 +259,8 @@ #define SOC_SPI_MAXIMUM_BUFFER_SIZE 64 #define SOC_SPI_MAX_BITWIDTH(host_id) (4) // Supported line mode: DIO, DOUT, QIO, or QOUT +#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 a463ec3c839..1aac2ccc79e 100644 --- a/components/soc/esp32c2/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c2/include/soc/Kconfig.soc_caps.in @@ -479,6 +479,10 @@ config SOC_MEMSPI_IS_INDEPENDENT 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 f2897e098db..ccc5ff193a9 100644 --- a/components/soc/esp32c2/include/soc/soc_caps.h +++ b/components/soc/esp32c2/include/soc/soc_caps.h @@ -226,6 +226,8 @@ #define SOC_MEMSPI_SUPPORT_CONTROL_DUMMY_OUT 1 #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 */ + /*-------------------------- 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 e6d50a5ff71..4046dd3e225 100644 --- a/components/soc/esp32c3/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c3/include/soc/Kconfig.soc_caps.in @@ -667,6 +667,10 @@ config SOC_MEMSPI_IS_INDEPENDENT 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 6222fc40c29..2fbe7f0590c 100644 --- a/components/soc/esp32c3/include/soc/soc_caps.h +++ b/components/soc/esp32c3/include/soc/soc_caps.h @@ -302,6 +302,8 @@ #define SOC_MEMSPI_SUPPORT_CONTROL_DUMMY_OUT 1 #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 */ + /*-------------------------- 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 92c120e371b..37a9b5ccc5a 100644 --- a/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in @@ -1035,6 +1035,10 @@ config SOC_SPI_MEM_FLASH_SUPPORT_HPM bool default y +config SOC_MEMSPI_ENCRYPTION_ALIGNMENT + int + default 16 + config SOC_SYSTIMER_SUPPORT_ETM bool default y diff --git a/components/soc/esp32c5/include/soc/soc_caps.h b/components/soc/esp32c5/include/soc/soc_caps.h index 949938b247c..0526111b16f 100644 --- a/components/soc/esp32c5/include/soc/soc_caps.h +++ b/components/soc/esp32c5/include/soc/soc_caps.h @@ -426,6 +426,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_SUPPORT_ETM 1 // Systimer comparator can generate ETM event diff --git a/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in index fa0bf967c78..02d7dc35569 100644 --- a/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in @@ -863,6 +863,10 @@ config SOC_MEMSPI_IS_INDEPENDENT bool default y +config SOC_MEMSPI_ENCRYPTION_ALIGNMENT + int + default 16 + config SOC_SYSTIMER_SUPPORT_ETM bool default y diff --git a/components/soc/esp32c6/include/soc/soc_caps.h b/components/soc/esp32c6/include/soc/soc_caps.h index fb70d4ddde8..2c504e3bbcc 100644 --- a/components/soc/esp32c6/include/soc/soc_caps.h +++ b/components/soc/esp32c6/include/soc/soc_caps.h @@ -365,6 +365,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_SUPPORT_ETM 1 // Systimer comparator can generate ETM event diff --git a/components/soc/esp32c61/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c61/include/soc/Kconfig.soc_caps.in index 1b0a98b95cd..5ea7e7afafc 100644 --- a/components/soc/esp32c61/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c61/include/soc/Kconfig.soc_caps.in @@ -795,6 +795,10 @@ config SOC_SPI_MEM_FLASH_SUPPORT_HPM bool default y +config SOC_MEMSPI_ENCRYPTION_ALIGNMENT + int + default 16 + config SOC_SYSTIMER_SUPPORT_ETM bool default y diff --git a/components/soc/esp32c61/include/soc/soc_caps.h b/components/soc/esp32c61/include/soc/soc_caps.h index e4edb7d5263..43202cb7f13 100644 --- a/components/soc/esp32c61/include/soc/soc_caps.h +++ b/components/soc/esp32c61/include/soc/soc_caps.h @@ -333,6 +333,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_SUPPORT_ETM 1 // Systimer comparator can generate ETM event diff --git a/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in b/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in index dba597853c2..c6d37d74197 100644 --- a/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in @@ -867,6 +867,10 @@ config SOC_MEMSPI_IS_INDEPENDENT bool default y +config SOC_MEMSPI_ENCRYPTION_ALIGNMENT + int + default 16 + config SOC_SYSTIMER_SUPPORT_ETM bool default y diff --git a/components/soc/esp32h2/include/soc/soc_caps.h b/components/soc/esp32h2/include/soc/soc_caps.h index e9481352499..14d1f6d99d9 100644 --- a/components/soc/esp32h2/include/soc/soc_caps.h +++ b/components/soc/esp32h2/include/soc/soc_caps.h @@ -383,6 +383,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_SUPPORT_ETM 1 // Systimer comparator can generate ETM event diff --git a/components/soc/esp32h21/include/soc/Kconfig.soc_caps.in b/components/soc/esp32h21/include/soc/Kconfig.soc_caps.in index fe98bcc952d..24f52c1caba 100644 --- a/components/soc/esp32h21/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32h21/include/soc/Kconfig.soc_caps.in @@ -691,6 +691,10 @@ config SOC_MEMSPI_IS_INDEPENDENT bool default y +config SOC_MEMSPI_ENCRYPTION_ALIGNMENT + int + default 16 + config SOC_SYSTIMER_SUPPORT_ETM bool default y diff --git a/components/soc/esp32h21/include/soc/soc_caps.h b/components/soc/esp32h21/include/soc/soc_caps.h index 341d601b674..8d94bd9bb49 100644 --- a/components/soc/esp32h21/include/soc/soc_caps.h +++ b/components/soc/esp32h21/include/soc/soc_caps.h @@ -360,6 +360,8 @@ #define SOC_SPI_MEM_SUPPORT_WRAP (1) #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_SUPPORT_ETM 1 // Systimer comparator can generate ETM event diff --git a/components/soc/esp32h4/include/soc/Kconfig.soc_caps.in b/components/soc/esp32h4/include/soc/Kconfig.soc_caps.in index 42d14197aaa..40aecbed5d4 100644 --- a/components/soc/esp32h4/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32h4/include/soc/Kconfig.soc_caps.in @@ -767,6 +767,10 @@ config SOC_MEMSPI_IS_INDEPENDENT bool default y +config SOC_MEMSPI_ENCRYPTION_ALIGNMENT + int + default 16 + config SOC_SYSTIMER_SUPPORT_ETM bool default y diff --git a/components/soc/esp32h4/include/soc/soc_caps.h b/components/soc/esp32h4/include/soc/soc_caps.h index 22a9adfccf9..12a34f67bde 100644 --- a/components/soc/esp32h4/include/soc/soc_caps.h +++ b/components/soc/esp32h4/include/soc/soc_caps.h @@ -382,6 +382,8 @@ #define SOC_SPI_MEM_SUPPORT_WRAP (1) #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_SUPPORT_ETM 1 // Systimer comparator can generate ETM event diff --git a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in index 0ec3fb00acb..904aa83f3fd 100644 --- a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in @@ -1415,6 +1415,10 @@ config SOC_SPI_MEM_FLASH_SUPPORT_HPM bool default y +config SOC_MEMSPI_ENCRYPTION_ALIGNMENT + int + default 16 + config SOC_SYSTIMER_SUPPORT_ETM bool default y diff --git a/components/soc/esp32p4/include/soc/soc_caps.h b/components/soc/esp32p4/include/soc/soc_caps.h index f4b7b38f60b..2f042e45156 100644 --- a/components/soc/esp32p4/include/soc/soc_caps.h +++ b/components/soc/esp32p4/include/soc/soc_caps.h @@ -541,6 +541,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_SUPPORT_ETM 1 // Systimer comparator can generate ETM event @@ -612,6 +614,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 3d64b2ab4da..c3ba40200cd 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 384ebcdc6a9..1ee8fb58f98 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 9e866e58afc..80e5cde5e2f 100644 --- a/components/soc/esp32s2/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32s2/include/soc/Kconfig.soc_caps.in @@ -579,6 +579,10 @@ config SOC_MEMSPI_IS_INDEPENDENT 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/esp32s2/include/soc/soc_caps.h b/components/soc/esp32s2/include/soc/soc_caps.h index 32e8bda8aec..99069244bd0 100644 --- a/components/soc/esp32s2/include/soc/soc_caps.h +++ b/components/soc/esp32s2/include/soc/soc_caps.h @@ -270,6 +270,8 @@ #define SOC_MEMSPI_SUPPORT_CONTROL_DUMMY_OUT 1 #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 ----------------------------------*/ /*-------------------------- LP_TIMER CAPS ----------------------------------*/ diff --git a/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in b/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in index d75a8f339a8..7d6b8b2b87a 100644 --- a/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in @@ -675,14 +675,6 @@ config SOC_SPI_SUPPORT_OCT bool default y -config SOC_MEMSPI_SUPPORT_CONTROL_DUMMY_OUT - bool - default y - -config SOC_MEMSPI_IS_INDEPENDENT - bool - default y - config SOC_SPIRAM_SUPPORTED bool default y @@ -1107,6 +1099,18 @@ config SOC_SPI_MEM_FLASH_SUPPORT_HPM bool default y +config SOC_MEMSPI_SUPPORT_CONTROL_DUMMY_OUT + bool + default y + +config SOC_MEMSPI_IS_INDEPENDENT + 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 8a8cc46e8e7..add5e3cef9d 100644 --- a/components/soc/esp32s3/include/soc/soc_caps.h +++ b/components/soc/esp32s3/include/soc/soc_caps.h @@ -285,10 +285,6 @@ #define SOC_SPI_MAX_BITWIDTH(host_id) ((host_id == 2) ? 4 : 8) // Supported line mode: SPI3: 1, 2, 4, SPI1/2: 1, 2, 4, 8 #define SOC_SPI_SCT_SUPPORTED(host_id) ((host_id) == 1) -// Peripheral supports output given level during its "dummy phase" -#define SOC_MEMSPI_SUPPORT_CONTROL_DUMMY_OUT 1 -#define SOC_MEMSPI_IS_INDEPENDENT 1 - /*-------------------------- SPIRAM CAPS ----------------------------------------*/ #define SOC_SPIRAM_SUPPORTED 1 #define SOC_SPIRAM_XIP_SUPPORTED 1 @@ -457,6 +453,12 @@ #define SOC_SPI_MEM_FLASH_SUPPORT_HPM (1) /*!< Support High Performance Mode */ +// Peripheral supports output given level during its "dummy phase" +#define SOC_MEMSPI_SUPPORT_CONTROL_DUMMY_OUT 1 +#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 */ + /*-------------------------- COEXISTENCE HARDWARE PTI CAPS -------------------------------*/ #define SOC_COEX_HW_PTI (1) diff --git a/components/soc/esp32s31/include/soc/Kconfig.soc_caps.in b/components/soc/esp32s31/include/soc/Kconfig.soc_caps.in index 49ec1417c06..8260b2e75d4 100644 --- a/components/soc/esp32s31/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32s31/include/soc/Kconfig.soc_caps.in @@ -295,6 +295,10 @@ config SOC_MEMSPI_FLASH_PSRAM_INDEPENDENT bool default y +config SOC_MEMSPI_ENCRYPTION_ALIGNMENT + int + default 16 + config SOC_TIMER_SUPPORT_ETM bool default y diff --git a/components/soc/esp32s31/include/soc/soc_caps.h b/components/soc/esp32s31/include/soc/soc_caps.h index 5a6a202ff0f..1a34401f4e6 100644 --- a/components/soc/esp32s31/include/soc/soc_caps.h +++ b/components/soc/esp32s31/include/soc/soc_caps.h @@ -221,6 +221,8 @@ #define SOC_MEMSPI_FLASH_PSRAM_INDEPENDENT 1 +#define SOC_MEMSPI_ENCRYPTION_ALIGNMENT 16 /*!< 16-byte alignment restriction to mem addr and size if encryption is enabled */ + /*-------------------------- SYSTIMER CAPS ----------------------------------*/ // TODO: [ESP32S31] IDF-14693 diff --git a/components/soc/esp32s31/register/soc/dma2d_struct.h b/components/soc/esp32s31/register/soc/dma2d_struct.h index f2bb456c56d..422aedf420c 100644 --- a/components/soc/esp32s31/register/soc/dma2d_struct.h +++ b/components/soc/esp32s31/register/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; @@ -372,8 +376,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/docs/en/api-reference/peripherals/lcd/dsi_lcd.rst b/docs/en/api-reference/peripherals/lcd/dsi_lcd.rst index 4afa6032c34..5d15966550e 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 3a6f64fe55e..9ae45f3a9e2 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 082052d2492..71a7733c4c2 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 c9b4841413b..f1e2e37003e 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: 线程安全