feat(dma2d,ppa): Support flash encryption for DMA2D and PPA

This commit is contained in:
Song Ruo Jing
2026-04-13 15:03:37 +08:00
parent 93b9d470db
commit d15a897d13
65 changed files with 479 additions and 135 deletions
+10 -4
View File
@@ -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,
};
+54 -1
View File
@@ -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;
}
+7 -4
View File
@@ -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;
+2
View File
@@ -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 {
+21 -12
View File
@@ -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