From d15a897d134d26b4fc68e4fd71871f2a51e0489d 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 --- components/esp_driver_jpeg/jpeg_decode.c | 6 +- components/esp_driver_jpeg/jpeg_encode.c | 6 +- .../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 | 55 ++++++++- 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 | 53 ++++++--- .../esp_driver_ppa/test_apps/pytest_ppa.py | 15 ++- .../test_apps/sdkconfig.ci.flash_enc | 9 ++ components/esp_hw_support/dma/dma2d.c | 26 ++++- components/esp_hw_support/dma/gdma.c | 2 +- .../dma/include/esp_private/dma2d.h | 3 +- .../test_apps/.build-test-rules.yml | 1 + .../test_apps/dma/main/test_gdma.c | 2 +- .../test_apps/dma/main/test_gdma_crc.c | 4 +- .../test_apps/dma/pytest_dma.py | 8 +- .../test_apps/dma/sdkconfig.ci.flash_enc | 9 ++ .../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_lcd/src/esp_async_fbcpy.c | 3 + components/esp_mm/heap_align_hw.c | 2 +- components/hal/esp32c5/include/hal/gdma_ll.h | 1 - components/hal/esp32c61/include/hal/gdma_ll.h | 1 - components/hal/esp32h21/include/hal/gdma_ll.h | 1 - components/hal/esp32h4/include/hal/gdma_ll.h | 1 - components/hal/esp32p4/include/hal/dma2d_ll.h | 26 ++--- components/hal/esp32p4/include/hal/gdma_ll.h | 1 - components/hal/esp32s3/include/hal/gdma_ll.h | 1 - components/hal/include/hal/dma2d_types.h | 16 +-- components/hal/include/hal/ppa_types.h | 11 +- .../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 | 2 + .../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 | 4 + components/soc/esp32s3/include/soc/soc_caps.h | 2 + .../api-reference/peripherals/lcd/dsi_lcd.rst | 4 + docs/en/api-reference/peripherals/ppa.rst | 23 ++++ .../api-reference/peripherals/lcd/dsi_lcd.rst | 4 + docs/zh_CN/api-reference/peripherals/ppa.rst | 23 ++++ 65 files changed, 479 insertions(+), 135 deletions(-) create mode 100644 components/esp_driver_ppa/test_apps/sdkconfig.ci.flash_enc create mode 100644 components/esp_hw_support/test_apps/dma/sdkconfig.ci.flash_enc create mode 100644 components/esp_hw_support/test_apps/dma2d/sdkconfig.ci.flash_enc diff --git a/components/esp_driver_jpeg/jpeg_decode.c b/components/esp_driver_jpeg/jpeg_decode.c index 8c6e0b0f114..adda2c084cf 100644 --- a/components/esp_driver_jpeg/jpeg_decode.c +++ b/components/esp_driver_jpeg/jpeg_decode.c @@ -498,13 +498,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 f94662ac730..3de95cb16a3 100644 --- a/components/esp_driver_jpeg/jpeg_encode.c +++ b/components/esp_driver_jpeg/jpeg_encode.c @@ -430,13 +430,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/include/driver/ppa.h b/components/esp_driver_ppa/include/driver/ppa.h index 5a3917d88d0..a2433e1c629 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` */ + uint32_t cm; /*!< Color ID */ }; 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` */ + uint32_t cm; /*!< Color ID */ }; 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 e5cdb5ceb28..6b09aace200 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 */ @@ -118,6 +118,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, @@ -187,9 +188,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 @@ -236,6 +234,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); } @@ -268,6 +273,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; color_space_pixel_format_t in_bg_pixel_format = { .color_type_id = config->in_bg.blend_cm, }; diff --git a/components/esp_driver_ppa/src/ppa_core.c b/components/esp_driver_ppa/src/ppa_core.c index a7b371478e9..162835c343e 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 "hal/efuse_hal.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 (efuse_hal_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, @@ -525,3 +534,47 @@ 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 (efuse_hal_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; + uint32_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; + color_space_pixel_format_t pixel_format = { + .color_type_id = color_mode, + }; + uint32_t pixel_depth_bytes = color_hal_pixel_format_get_bit_depth(pixel_format) / 8; // bytes + + 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 6b923e24bf8..fa9e12d1b9f 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 */ @@ -62,6 +62,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, @@ -93,9 +94,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 @@ -117,10 +115,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 e1810be07a5..0d2d068bd1d 100644 --- a/components/esp_driver_ppa/src/ppa_priv.h +++ b/components/esp_driver_ppa/src/ppa_priv.h @@ -225,6 +225,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 c35a736bf32..489d5bbe0c1 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 */ @@ -93,6 +93,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, @@ -191,9 +192,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"); @@ -228,18 +226,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); } @@ -258,6 +266,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; color_space_pixel_format_t in_pixel_format = { .color_type_id = config->in.srm_cm, }; @@ -282,10 +291,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 8684e6ee154..3aefee6b499 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 "hal/efuse_hal.h" #define ALIGN_UP(num, align) (((num) + ((align) - 1)) & ~((align) - 1)) @@ -83,7 +84,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 (!efuse_hal_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)); @@ -166,6 +169,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 (efuse_hal_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; @@ -284,7 +292,7 @@ TEST_CASE("ppa_srm_basic_data_correctness_check", "[PPA]") }; const uint32_t buf_len = w * h * color_hal_pixel_format_get_bit_depth(buf_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] = { @@ -593,6 +601,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 (efuse_hal_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 @@ -690,6 +703,11 @@ 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; + size_t in_buf_alignment = 4; // no special alignment requirement for input buffers + if (efuse_hal_flash_encryption_enabled()) { + in_buf_alignment = SOC_MEMSPI_ENCRYPTION_ALIGNMENT; + } + color_space_pixel_format_t in_bg_pixel_format = { .color_type_id = in_bg_cm, }; @@ -700,8 +718,8 @@ TEST_CASE("ppa_blend_performance", "[PPA]") .color_type_id = out_cm, }; - uint32_t in_bg_buf_size = w * h * color_hal_pixel_format_get_bit_depth(in_bg_pixel_format) / 8; - uint32_t in_fg_buf_size = w * h * color_hal_pixel_format_get_bit_depth(in_fg_pixel_format) / 8; + uint32_t in_bg_buf_size = ALIGN_UP(w * h * color_hal_pixel_format_get_bit_depth(in_bg_pixel_format) / 8, in_buf_alignment); + uint32_t in_fg_buf_size = ALIGN_UP(w * h * color_hal_pixel_format_get_bit_depth(in_fg_pixel_format) / 8, in_buf_alignment); uint32_t out_buf_size = ALIGN_UP(w * h * color_hal_pixel_format_get_bit_depth(out_pixel_format) / 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); @@ -767,10 +785,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 (!efuse_hal_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)); @@ -829,10 +849,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 (!efuse_hal_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)); @@ -841,6 +863,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 (efuse_hal_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 ed182199270..c699ab0f43b 100644 --- a/components/esp_driver_ppa/test_apps/pytest_ppa.py +++ b/components/esp_driver_ppa/test_apps/pytest_ppa.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut @@ -17,3 +17,16 @@ from pytest_embedded_idf.utils import soc_filtered_targets @idf_parametrize('target', soc_filtered_targets('SOC_PPA_SUPPORTED == 1'), indirect=['target']) def test_ppa(dut: Dut) -> None: dut.run_all_single_board_cases() + + +@pytest.mark.flash_encryption +@pytest.mark.parametrize( + 'config', + [ + 'flash_enc', + ], + indirect=True, +) +@idf_parametrize('target', soc_filtered_targets('SOC_PPA_SUPPORTED == 1'), indirect=['target']) +def test_ppa_flash_encryption(dut: Dut) -> None: + dut.run_all_single_board_cases() diff --git a/components/esp_driver_ppa/test_apps/sdkconfig.ci.flash_enc b/components/esp_driver_ppa/test_apps/sdkconfig.ci.flash_enc new file mode 100644 index 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_hw_support/dma/dma2d.c b/components/esp_hw_support/dma/dma2d.c index b240a941ac2..17543574920 100644 --- a/components/esp_hw_support/dma/dma2d.c +++ b/components/esp_hw_support/dma/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 */ @@ -24,6 +24,7 @@ #include "soc/dma2d_channel.h" #include "soc/dma2d_periph.h" #include "esp_bit_defs.h" +#include "hal/efuse_hal.h" /** * The 2D-DMA driver is designed with a pool & client model + queue design pattern. @@ -583,7 +584,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) { @@ -607,7 +608,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) { @@ -712,6 +713,8 @@ esp_err_t dma2d_set_desc_addr(dma2d_channel_handle_t dma2d_chan, intptr_t desc_b ESP_GOTO_ON_FALSE_ISR(dma2d_chan && desc_base_addr, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument"); // 2D-DMA descriptor addr needs 8-byte alignment and not in SPM (addr not in SPM is IDF restriction) ESP_GOTO_ON_FALSE_ISR((desc_base_addr & 0x7) == 0 && !esp_ptr_in_spm((void *)desc_base_addr), ESP_ERR_INVALID_ARG, err, TAG, "invalid argument"); + // When flash encryption is enabled, the descriptor must be in internal RAM because descriptor size is not 16-byte aligned, which breaks flash encryption alignment restriction + ESP_GOTO_ON_FALSE_ISR(!efuse_hal_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; @@ -827,19 +830,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 (efuse_hal_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_hw_support/dma/gdma.c b/components/esp_hw_support/dma/gdma.c index e61a222df0e..fbda00f2de4 100644 --- a/components/esp_hw_support/dma/gdma.c +++ b/components/esp_hw_support/dma/gdma.c @@ -388,7 +388,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 (efuse_hal_flash_encryption_enabled() && config->access_ext_mem) { - uint32_t enc_mem_alignment = GDMA_LL_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_hw_support/dma/include/esp_private/dma2d.h b/components/esp_hw_support/dma/include/esp_private/dma2d.h index 10c964d2109..6629d85945d 100644 --- a/components/esp_hw_support/dma/include/esp_private/dma2d.h +++ b/components/esp_hw_support/dma/include/esp_private/dma2d.h @@ -229,7 +229,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_hw_support/test_apps/.build-test-rules.yml b/components/esp_hw_support/test_apps/.build-test-rules.yml index 384c11b35bd..1046d30d89b 100644 --- a/components/esp_hw_support/test_apps/.build-test-rules.yml +++ b/components/esp_hw_support/test_apps/.build-test-rules.yml @@ -5,6 +5,7 @@ components/esp_hw_support/test_apps/dma: - if: IDF_TARGET in ["esp32"] temporary: false reason: No general DMA controller on ESP32 + - if: CONFIG_NAME == "flash_enc" and SOC_FLASH_ENC_SUPPORTED != 1 depends_filepatterns: - components/esp_hw_support/dma/**/* diff --git a/components/esp_hw_support/test_apps/dma/main/test_gdma.c b/components/esp_hw_support/test_apps/dma/main/test_gdma.c index d9e0bc5065d..68e8d0a76bb 100644 --- a/components/esp_hw_support/test_apps/dma/main/test_gdma.c +++ b/components/esp_hw_support/test_apps/dma/main/test_gdma.c @@ -272,7 +272,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_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_hw_support/test_apps/dma/main/test_gdma_crc.c b/components/esp_hw_support/test_apps/dma/main/test_gdma_crc.c index b54d81a20db..eaf2b278536 100644 --- a/components/esp_hw_support/test_apps/dma/main/test_gdma_crc.c +++ b/components/esp_hw_support/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_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_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_hw_support/test_apps/dma/pytest_dma.py b/components/esp_hw_support/test_apps/dma/pytest_dma.py index d9b663c51c3..40f8b86c972 100644 --- a/components/esp_hw_support/test_apps/dma/pytest_dma.py +++ b/components/esp_hw_support/test_apps/dma/pytest_dma.py @@ -39,12 +39,12 @@ def test_dma_psram(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) @@ -52,10 +52,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_hw_support/test_apps/dma/sdkconfig.ci.flash_enc b/components/esp_hw_support/test_apps/dma/sdkconfig.ci.flash_enc new file mode 100644 index 00000000000..5be9651c381 --- /dev/null +++ b/components/esp_hw_support/test_apps/dma/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_hw_support/test_apps/dma2d/main/CMakeLists.txt b/components/esp_hw_support/test_apps/dma2d/main/CMakeLists.txt index 1edd6de51cc..a15f4606b29 100644 --- a/components/esp_hw_support/test_apps/dma2d/main/CMakeLists.txt +++ b/components/esp_hw_support/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 + PRIV_REQUIRES unity esp_mm esp_psram WHOLE_ARCHIVE) diff --git a/components/esp_hw_support/test_apps/dma2d/main/test_dma2d.c b/components/esp_hw_support/test_apps/dma2d/main/test_dma2d.c index 931688448e1..ed1a9380e7d 100644 --- a/components/esp_hw_support/test_apps/dma2d/main/test_dma2d.c +++ b/components/esp_hw_support/test_apps/dma2d/main/test_dma2d.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023-2024 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 "hal/efuse_hal.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 (efuse_hal_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 (efuse_hal_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, }; @@ -326,8 +342,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 (efuse_hal_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++) { @@ -345,7 +366,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, }; @@ -465,8 +487,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 (efuse_hal_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++) { @@ -484,7 +511,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, }; @@ -571,20 +599,33 @@ 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 color_space_pixel_format_t pixel_format = { .color_space = COLOR_SPACE_RGB, .pixel_format = COLOR_PIXEL_RGB565, }; - 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 (efuse_hal_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++) { @@ -594,15 +635,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, }; @@ -610,8 +654,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; @@ -622,8 +666,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, @@ -661,12 +705,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_hw_support/test_apps/dma2d/pytest_dma2d.py b/components/esp_hw_support/test_apps/dma2d/pytest_dma2d.py index 3a55fff306b..61ff068677a 100644 --- a/components/esp_hw_support/test_apps/dma2d/pytest_dma2d.py +++ b/components/esp_hw_support/test_apps/dma2d/pytest_dma2d.py @@ -17,3 +17,17 @@ from pytest_embedded_idf.utils import idf_parametrize @pytest.mark.temp_skip_ci(targets=['esp32p4'], reason='p4 rev3 migration # TODO: IDF-14471') 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', ['esp32p4'], indirect=['target']) +@pytest.mark.temp_skip_ci(targets=['esp32p4'], reason='p4 rev3 migration # TODO: IDF-14471') +def test_dma2d_flash_encryption(dut: Dut) -> None: + dut.run_all_single_board_cases() diff --git a/components/esp_hw_support/test_apps/dma2d/sdkconfig.ci.flash_enc b/components/esp_hw_support/test_apps/dma2d/sdkconfig.ci.flash_enc new file mode 100644 index 00000000000..5be9651c381 --- /dev/null +++ b/components/esp_hw_support/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_lcd/src/esp_async_fbcpy.c b/components/esp_lcd/src/esp_async_fbcpy.c index b206303ba15..4b3243c31a8 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_mm/heap_align_hw.c b/components/esp_mm/heap_align_hw.c index 344b27b882c..eea20c7fa61 100644 --- a/components/esp_mm/heap_align_hw.c +++ b/components/esp_mm/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_GDMA_SUPPORTED && (SOC_PSRAM_DMA_CAPABLE || SOC_DMA_CAN_ACCESS_FLASH) if ((caps & MALLOC_CAP_DMA) && efuse_hal_flash_encryption_enabled()) { - alignment = (alignment > GDMA_LL_ACCESS_ENCRYPTION_MEM_ALIGNMENT) ? alignment : GDMA_LL_ACCESS_ENCRYPTION_MEM_ALIGNMENT; + alignment = (alignment > SOC_MEMSPI_ENCRYPTION_ALIGNMENT) ? alignment : SOC_MEMSPI_ENCRYPTION_ALIGNMENT; } #endif diff --git a/components/hal/esp32c5/include/hal/gdma_ll.h b/components/hal/esp32c5/include/hal/gdma_ll.h index 8176ed1c408..f4a17e88f47 100644 --- a/components/hal/esp32c5/include/hal/gdma_ll.h +++ b/components/hal/esp32c5/include/hal/gdma_ll.h @@ -9,7 +9,6 @@ #include "hal/ahb_dma_ll.h" #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/hal/esp32c61/include/hal/gdma_ll.h b/components/hal/esp32c61/include/hal/gdma_ll.h index 8176ed1c408..f4a17e88f47 100644 --- a/components/hal/esp32c61/include/hal/gdma_ll.h +++ b/components/hal/esp32c61/include/hal/gdma_ll.h @@ -9,7 +9,6 @@ #include "hal/ahb_dma_ll.h" #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/hal/esp32h21/include/hal/gdma_ll.h b/components/hal/esp32h21/include/hal/gdma_ll.h index 3e56d0d6211..4d0f42c6133 100644 --- a/components/hal/esp32h21/include/hal/gdma_ll.h +++ b/components/hal/esp32h21/include/hal/gdma_ll.h @@ -49,7 +49,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/hal/esp32h4/include/hal/gdma_ll.h b/components/hal/esp32h4/include/hal/gdma_ll.h index 83db6730c6b..0e04e3b4951 100644 --- a/components/hal/esp32h4/include/hal/gdma_ll.h +++ b/components/hal/esp32h4/include/hal/gdma_ll.h @@ -9,7 +9,6 @@ #include "hal/ahb_dma_ll.h" #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/hal/esp32p4/include/hal/dma2d_ll.h b/components/hal/esp32p4/include/hal/dma2d_ll.h index 8c0fab88846..7f5e9b501d9 100644 --- a/components/hal/esp32p4/include/hal/dma2d_ll.h +++ b/components/hal/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 */ @@ -232,23 +232,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: @@ -748,23 +748,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/hal/esp32p4/include/hal/gdma_ll.h b/components/hal/esp32p4/include/hal/gdma_ll.h index f987c565037..6316a33f945 100644 --- a/components/hal/esp32p4/include/hal/gdma_ll.h +++ b/components/hal/esp32p4/include/hal/gdma_ll.h @@ -49,7 +49,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/hal/esp32s3/include/hal/gdma_ll.h b/components/hal/esp32s3/include/hal/gdma_ll.h index 8cfba49a123..58cc22253cd 100644 --- a/components/hal/esp32s3/include/hal/gdma_ll.h +++ b/components/hal/esp32s3/include/hal/gdma_ll.h @@ -65,7 +65,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/hal/include/hal/dma2d_types.h b/components/hal/include/hal/dma2d_types.h index 3e9142f2e2e..3cf61343ace 100644 --- a/components/hal/include/hal/dma2d_types.h +++ b/components/hal/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/hal/include/hal/ppa_types.h b/components/hal/include/hal/ppa_types.h index 0120556ce3f..a6b902bb198 100644 --- a/components/hal/include/hal/ppa_types.h +++ b/components/hal/include/hal/ppa_types.h @@ -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/soc/esp32/include/soc/Kconfig.soc_caps.in b/components/soc/esp32/include/soc/Kconfig.soc_caps.in index cbc5d52fb3e..ccdcb54481f 100644 --- a/components/soc/esp32/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32/include/soc/Kconfig.soc_caps.in @@ -783,6 +783,10 @@ config SOC_SPI_MEM_SUPPORT_CONFIG_GPIO_BY_EFUSE bool default y +config SOC_MEMSPI_ENCRYPTION_ALIGNMENT + int + default 16 + config SOC_SHA_SUPPORT_PARALLEL_ENG bool default y diff --git a/components/soc/esp32/include/soc/soc_caps.h b/components/soc/esp32/include/soc/soc_caps.h index 039303747f1..4ba76fcf45c 100644 --- a/components/soc/esp32/include/soc/soc_caps.h +++ b/components/soc/esp32/include/soc/soc_caps.h @@ -366,6 +366,8 @@ /*-------------------------- SPI MEM CAPS ---------------------------------------*/ #define SOC_SPI_MEM_SUPPORT_CONFIG_GPIO_BY_EFUSE (1) +#define SOC_MEMSPI_ENCRYPTION_ALIGNMENT 16 /*!< 16-byte alignment restriction to mem addr and size if encryption is enabled */ + /*--------------------------- SHA CAPS ---------------------------------------*/ /* ESP32 style SHA engine, where multiple states can be stored in parallel */ #define SOC_SHA_SUPPORT_PARALLEL_ENG (1) diff --git a/components/soc/esp32c2/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c2/include/soc/Kconfig.soc_caps.in index 96d7a98f0d6..f2595cf38b6 100644 --- a/components/soc/esp32c2/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c2/include/soc/Kconfig.soc_caps.in @@ -563,6 +563,10 @@ config SOC_SPI_MEM_SUPPORT_WRAP bool default y +config SOC_MEMSPI_ENCRYPTION_ALIGNMENT + int + default 16 + config SOC_SYSTIMER_COUNTER_NUM int default 2 diff --git a/components/soc/esp32c2/include/soc/soc_caps.h b/components/soc/esp32c2/include/soc/soc_caps.h index 3976848ae2d..5c8725452d6 100644 --- a/components/soc/esp32c2/include/soc/soc_caps.h +++ b/components/soc/esp32c2/include/soc/soc_caps.h @@ -257,6 +257,8 @@ #define SOC_SPI_MEM_SUPPORT_CHECK_SUS (1) #define SOC_SPI_MEM_SUPPORT_WRAP (1) +#define SOC_MEMSPI_ENCRYPTION_ALIGNMENT 16 /*!< 16-byte alignment restriction to mem addr and size if encryption is enabled */ + /*-------------------------- SYSTIMER CAPS ----------------------------------*/ #define SOC_SYSTIMER_COUNTER_NUM 2 // Number of counter units #define SOC_SYSTIMER_ALARM_NUM 3 // Number of alarm units diff --git a/components/soc/esp32c3/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c3/include/soc/Kconfig.soc_caps.in index 11e0e7014d8..a799a3abf5f 100644 --- a/components/soc/esp32c3/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c3/include/soc/Kconfig.soc_caps.in @@ -823,6 +823,10 @@ config SOC_SPI_MEM_SUPPORT_WRAP bool default y +config SOC_MEMSPI_ENCRYPTION_ALIGNMENT + int + default 16 + config SOC_SYSTIMER_COUNTER_NUM int default 2 diff --git a/components/soc/esp32c3/include/soc/soc_caps.h b/components/soc/esp32c3/include/soc/soc_caps.h index 57860acd94e..fe62122b993 100644 --- a/components/soc/esp32c3/include/soc/soc_caps.h +++ b/components/soc/esp32c3/include/soc/soc_caps.h @@ -352,6 +352,8 @@ #define SOC_SPI_MEM_SUPPORT_CONFIG_GPIO_BY_EFUSE (1) #define SOC_SPI_MEM_SUPPORT_WRAP (1) +#define SOC_MEMSPI_ENCRYPTION_ALIGNMENT 16 /*!< 16-byte alignment restriction to mem addr and size if encryption is enabled */ + /*-------------------------- SYSTIMER CAPS ----------------------------------*/ #define SOC_SYSTIMER_COUNTER_NUM 2 // Number of counter units #define SOC_SYSTIMER_ALARM_NUM 3 // Number of alarm units diff --git a/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in index 4b4c555eb0f..e1952182eb6 100644 --- a/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in @@ -1271,6 +1271,10 @@ config SOC_MEMSPI_TIMING_TUNING_BY_MSPI_DELAY bool default y +config SOC_MEMSPI_ENCRYPTION_ALIGNMENT + int + default 16 + config SOC_SYSTIMER_COUNTER_NUM int default 2 diff --git a/components/soc/esp32c5/include/soc/soc_caps.h b/components/soc/esp32c5/include/soc/soc_caps.h index b3413628831..0a7d89cbf55 100644 --- a/components/soc/esp32c5/include/soc/soc_caps.h +++ b/components/soc/esp32c5/include/soc/soc_caps.h @@ -488,6 +488,8 @@ #define SOC_SPI_MEM_FLASH_SUPPORT_HPM (1) /*!< Support High Performance Mode */ #define SOC_MEMSPI_TIMING_TUNING_BY_MSPI_DELAY (1) +#define SOC_MEMSPI_ENCRYPTION_ALIGNMENT 16 /*!< 16-byte alignment restriction to mem addr and size if encryption is enabled */ + /*-------------------------- SYSTIMER CAPS ----------------------------------*/ // TODO: [ESP32C5] IDF-8707 #define SOC_SYSTIMER_COUNTER_NUM 2 // Number of counter units diff --git a/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in index eb1461e69a3..35308e114ec 100644 --- a/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in @@ -1111,6 +1111,10 @@ config SOC_SPI_MEM_SUPPORT_WRAP bool default y +config SOC_MEMSPI_ENCRYPTION_ALIGNMENT + int + default 16 + config SOC_SYSTIMER_COUNTER_NUM int default 2 diff --git a/components/soc/esp32c6/include/soc/soc_caps.h b/components/soc/esp32c6/include/soc/soc_caps.h index 562493afe1b..aa754c6376b 100644 --- a/components/soc/esp32c6/include/soc/soc_caps.h +++ b/components/soc/esp32c6/include/soc/soc_caps.h @@ -435,6 +435,8 @@ #define SOC_SPI_MEM_SUPPORT_CHECK_SUS (1) #define SOC_SPI_MEM_SUPPORT_WRAP (1) +#define SOC_MEMSPI_ENCRYPTION_ALIGNMENT 16 /*!< 16-byte alignment restriction to mem addr and size if encryption is enabled */ + /*-------------------------- SYSTIMER CAPS ----------------------------------*/ #define SOC_SYSTIMER_COUNTER_NUM 2 // Number of counter units #define SOC_SYSTIMER_ALARM_NUM 3 // Number of alarm units diff --git a/components/soc/esp32c61/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c61/include/soc/Kconfig.soc_caps.in index 7a994fa5c7d..8f6038f8697 100644 --- a/components/soc/esp32c61/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c61/include/soc/Kconfig.soc_caps.in @@ -875,6 +875,10 @@ config SOC_MEMSPI_TIMING_TUNING_BY_MSPI_DELAY bool default y +config SOC_MEMSPI_ENCRYPTION_ALIGNMENT + int + default 16 + config SOC_SYSTIMER_COUNTER_NUM int default 2 diff --git a/components/soc/esp32c61/include/soc/soc_caps.h b/components/soc/esp32c61/include/soc/soc_caps.h index 0cebae47e22..9ed84a42d69 100644 --- a/components/soc/esp32c61/include/soc/soc_caps.h +++ b/components/soc/esp32c61/include/soc/soc_caps.h @@ -353,6 +353,8 @@ #define SOC_SPI_MEM_FLASH_SUPPORT_HPM (1) /*!< Support High Performance Mode */ #define SOC_MEMSPI_TIMING_TUNING_BY_MSPI_DELAY (1) +#define SOC_MEMSPI_ENCRYPTION_ALIGNMENT 16 /*!< 16-byte alignment restriction to mem addr and size if encryption is enabled */ + /*-------------------------- SYSTIMER CAPS ----------------------------------*/ #define SOC_SYSTIMER_COUNTER_NUM 2 // Number of counter units #define SOC_SYSTIMER_ALARM_NUM 3 // Number of alarm units diff --git a/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in b/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in index 1025f6570c0..8838a1a5627 100644 --- a/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in @@ -1123,6 +1123,10 @@ config SOC_SPI_MEM_SUPPORT_WRAP bool default y +config SOC_MEMSPI_ENCRYPTION_ALIGNMENT + int + default 16 + config SOC_SYSTIMER_COUNTER_NUM int default 2 diff --git a/components/soc/esp32h2/include/soc/soc_caps.h b/components/soc/esp32h2/include/soc/soc_caps.h index 733e3b37049..88a7e9a92ee 100644 --- a/components/soc/esp32h2/include/soc/soc_caps.h +++ b/components/soc/esp32h2/include/soc/soc_caps.h @@ -452,6 +452,8 @@ #define SOC_SPI_MEM_SUPPORT_CHECK_SUS (1) #define SOC_SPI_MEM_SUPPORT_WRAP (1) +#define SOC_MEMSPI_ENCRYPTION_ALIGNMENT 16 /*!< 16-byte alignment restriction to mem addr and size if encryption is enabled */ + /*-------------------------- SYSTIMER CAPS ----------------------------------*/ #define SOC_SYSTIMER_COUNTER_NUM 2 // Number of counter units #define SOC_SYSTIMER_ALARM_NUM 3 // Number of alarm units diff --git a/components/soc/esp32h21/include/soc/Kconfig.soc_caps.in b/components/soc/esp32h21/include/soc/Kconfig.soc_caps.in index 04c204ae7fb..8887b0d1f59 100644 --- a/components/soc/esp32h21/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32h21/include/soc/Kconfig.soc_caps.in @@ -579,6 +579,10 @@ config SOC_MEMSPI_SRC_FREQ_16M_SUPPORTED bool default y +config SOC_MEMSPI_ENCRYPTION_ALIGNMENT + int + default 16 + config SOC_SYSTIMER_COUNTER_NUM int default 2 diff --git a/components/soc/esp32h21/include/soc/soc_caps.h b/components/soc/esp32h21/include/soc/soc_caps.h index d630b35ea12..ec43995222b 100644 --- a/components/soc/esp32h21/include/soc/soc_caps.h +++ b/components/soc/esp32h21/include/soc/soc_caps.h @@ -420,6 +420,8 @@ #define SOC_MEMSPI_SRC_FREQ_32M_SUPPORTED 1 #define SOC_MEMSPI_SRC_FREQ_16M_SUPPORTED 1 +#define SOC_MEMSPI_ENCRYPTION_ALIGNMENT 16 /*!< 16-byte alignment restriction to mem addr and size if encryption is enabled */ + /*-------------------------- SYSTIMER CAPS ----------------------------------*/ #define SOC_SYSTIMER_COUNTER_NUM 2 // Number of counter units #define SOC_SYSTIMER_ALARM_NUM 3 // Number of alarm units diff --git a/components/soc/esp32h4/include/soc/Kconfig.soc_caps.in b/components/soc/esp32h4/include/soc/Kconfig.soc_caps.in index 5155d3e4ea8..65f56d2b858 100644 --- a/components/soc/esp32h4/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32h4/include/soc/Kconfig.soc_caps.in @@ -283,6 +283,10 @@ config SOC_MEMSPI_SRC_FREQ_16M_SUPPORTED bool default y +config SOC_MEMSPI_ENCRYPTION_ALIGNMENT + int + default 16 + config SOC_SYSTIMER_COUNTER_NUM int default 2 diff --git a/components/soc/esp32h4/include/soc/soc_caps.h b/components/soc/esp32h4/include/soc/soc_caps.h index 7539f159ecc..89c15fb6be7 100644 --- a/components/soc/esp32h4/include/soc/soc_caps.h +++ b/components/soc/esp32h4/include/soc/soc_caps.h @@ -420,6 +420,8 @@ #define SOC_MEMSPI_SRC_FREQ_32M_SUPPORTED 1 #define SOC_MEMSPI_SRC_FREQ_16M_SUPPORTED 1 +#define SOC_MEMSPI_ENCRYPTION_ALIGNMENT 16 /*!< 16-byte alignment restriction to mem addr and size if encryption is enabled */ + /*-------------------------- SYSTIMER CAPS ----------------------------------*/ #define SOC_SYSTIMER_COUNTER_NUM 2 // Number of counter units #define SOC_SYSTIMER_ALARM_NUM 3 // Number of alarm units diff --git a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in index 2ea33193b69..23287ee0711 100644 --- a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in @@ -1711,6 +1711,10 @@ config SOC_MEMSPI_FLASH_PSRAM_INDEPENDENT bool default y +config SOC_MEMSPI_ENCRYPTION_ALIGNMENT + int + default 16 + config SOC_SYSTIMER_COUNTER_NUM int default 2 diff --git a/components/soc/esp32p4/include/soc/soc_caps.h b/components/soc/esp32p4/include/soc/soc_caps.h index a9c86ddb954..3a455bda3ee 100644 --- a/components/soc/esp32p4/include/soc/soc_caps.h +++ b/components/soc/esp32p4/include/soc/soc_caps.h @@ -627,6 +627,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 ----------------------------------*/ #define SOC_SYSTIMER_COUNTER_NUM 2 // Number of counter units #define SOC_SYSTIMER_ALARM_NUM 3 // Number of alarm units diff --git a/components/soc/esp32p4/register/hw_ver1/soc/dma2d_struct.h b/components/soc/esp32p4/register/hw_ver1/soc/dma2d_struct.h index a63f6d64ff4..a9392e08dd5 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 7105d670bcf..2164353cce2 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 cddc3dfc13f..23e05ac2ada 100644 --- a/components/soc/esp32s2/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32s2/include/soc/Kconfig.soc_caps.in @@ -759,6 +759,10 @@ config SOC_MEMSPI_IS_INDEPENDENT bool default y +config SOC_MEMSPI_ENCRYPTION_ALIGNMENT + int + default 16 + config SOC_SYSTIMER_COUNTER_NUM int default 1 diff --git a/components/soc/esp32s2/include/soc/soc_caps.h b/components/soc/esp32s2/include/soc/soc_caps.h index 282f49bce69..fb79ae4d913 100644 --- a/components/soc/esp32s2/include/soc/soc_caps.h +++ b/components/soc/esp32s2/include/soc/soc_caps.h @@ -325,6 +325,8 @@ #define SOC_MEMSPI_IS_INDEPENDENT 1 +#define SOC_MEMSPI_ENCRYPTION_ALIGNMENT 16 /*!< 16-byte alignment restriction to mem addr and size if encryption is enabled */ + /*-------------------------- SYSTIMER CAPS ----------------------------------*/ #define SOC_SYSTIMER_COUNTER_NUM (1U) // Number of counter units #define SOC_SYSTIMER_ALARM_NUM 3 // Number of alarm units diff --git a/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in b/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in index 5fba20ba130..27a5f07ba63 100644 --- a/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in @@ -1435,6 +1435,10 @@ config SOC_SPI_MEM_FLASH_SUPPORT_HPM bool default y +config SOC_MEMSPI_ENCRYPTION_ALIGNMENT + int + default 16 + config SOC_COEX_HW_PTI bool default y diff --git a/components/soc/esp32s3/include/soc/soc_caps.h b/components/soc/esp32s3/include/soc/soc_caps.h index e5ce39f10a2..450f7a83f90 100644 --- a/components/soc/esp32s3/include/soc/soc_caps.h +++ b/components/soc/esp32s3/include/soc/soc_caps.h @@ -559,6 +559,8 @@ #define SOC_SPI_MEM_FLASH_SUPPORT_HPM (1) /*!< Support High Performance Mode */ +#define SOC_MEMSPI_ENCRYPTION_ALIGNMENT 16 /*!< 16-byte alignment restriction to mem addr and size if encryption is enabled */ + /*-------------------------- COEXISTENCE HARDWARE PTI CAPS -------------------------------*/ #define SOC_COEX_HW_PTI (1) diff --git a/docs/en/api-reference/peripherals/lcd/dsi_lcd.rst b/docs/en/api-reference/peripherals/lcd/dsi_lcd.rst index b1a47b66402..07b553f4e9b 100644 --- a/docs/en/api-reference/peripherals/lcd/dsi_lcd.rst +++ b/docs/en/api-reference/peripherals/lcd/dsi_lcd.rst @@ -63,6 +63,10 @@ MIPI DSI Interfaced LCD - :cpp:member:`esp_lcd_dpi_panel_config_t::video_timing` sets the LCD panel specific timing parameters. All required parameters are listed in the :cpp:type:`esp_lcd_video_timing_t`, including the LCD resolution and blanking porches. Please fill them according to the datasheet of your LCD. - :cpp:member:`esp_lcd_dpi_panel_config_t::extra_dpi_panel_flags::use_dma2d` sets whether to use the 2D DMA peripheral to copy the user data to the frame buffer, asynchronously. + .. note:: + + 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. + .. code-block:: c esp_lcd_panel_handle_t mipi_dpi_panel = NULL; 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 63118e9ae42..5f6b4c96239 100644 --- a/docs/zh_CN/api-reference/peripherals/lcd/dsi_lcd.rst +++ b/docs/zh_CN/api-reference/peripherals/lcd/dsi_lcd.rst @@ -63,6 +63,10 @@ MIPI DSI 接口的 LCD - :cpp:member:`esp_lcd_dpi_panel_config_t::video_timing` 设置 LCD 面板的特定时序参数。包括 LCD 分辨率和消隐间隔在内的必要参数列表见 :cpp:type:`esp_lcd_video_timing_t`,请依据 LCD 技术规格书填写参数。 - :cpp:member:`esp_lcd_dpi_panel_config_t::extra_dpi_panel_flags::use_dma2d` 设置是否用 2D DMA 将用户数据异步复制到帧 buffer 中。 + .. note:: + + 由于硬件限制,如果启用了外部存储加密,则 DMA2D 只能访问地址和长度都对齐到 {IDF_TARGET_SOC_MEMSPI_ENCRYPTION_ALIGNMENT} 字节的地址空间。你需要确保你的绘制 buffer 的地址和长度都对齐到 {IDF_TARGET_SOC_MEMSPI_ENCRYPTION_ALIGNMENT} 字节。 :example:`peripherals/lcd/mipi_dsi` 演示了如何使用 LVGL 控制重新绘制区域来确保对齐。 + .. code-block:: c esp_lcd_panel_handle_t mipi_dpi_panel = NULL; 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: 线程安全