Merge branch 'feature/dma2d_with_flash_encryption_v6.0' into 'release/v6.0'

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

See merge request espressif/esp-idf!46796
This commit is contained in:
morris
2026-03-23 11:07:58 +08:00
67 changed files with 469 additions and 146 deletions
@@ -228,7 +228,8 @@ esp_err_t dma2d_apply_strategy(dma2d_channel_handle_t dma2d_chan, const dma2d_st
*/
typedef struct {
bool desc_burst_en; /*!< If set / clear, DMA channel enables / disables burst reading descriptor link */
dma2d_data_burst_length_t data_burst_length; /*!< Configure the DMA channel burst reading data length */
uint32_t data_burst_length; /*!< Configure the DMA channel burst reading data length */
bool access_ext_mem; /*!< Set this bit if the DMA transfer may access external memory */
dma2d_macro_block_size_t mb_size; /*!< Configure the DMA channel macro block size (only useful in DMA2D_DESCRIPTOR_BLOCK_RW_MODE_MULTIPLE mode) */
} dma2d_transfer_ability_t;
+20 -6
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
*/
@@ -26,6 +26,7 @@
#include "hal/dma2d_periph.h"
#include "soc/soc_caps.h"
#include "esp_bit_defs.h"
#include "esp_efuse.h"
/**
* The 2D-DMA driver is designed with a pool & client model + queue design pattern.
@@ -584,7 +585,7 @@ esp_err_t dma2d_connect(dma2d_channel_handle_t dma2d_chan, const dma2d_trigger_t
dma2d_ll_tx_enable_auto_write_back(group->hal.dev, channel_id, false);
dma2d_ll_tx_enable_eof_mode(group->hal.dev, channel_id, true);
dma2d_ll_tx_enable_descriptor_burst(group->hal.dev, channel_id, false);
dma2d_ll_tx_set_data_burst_length(group->hal.dev, channel_id, DMA2D_DATA_BURST_LENGTH_128);
dma2d_ll_tx_set_data_burst_length(group->hal.dev, channel_id, 128);
dma2d_ll_tx_enable_page_bound_wrap(group->hal.dev, channel_id, true);
dma2d_ll_tx_set_macro_block_size(group->hal.dev, channel_id, DMA2D_MACRO_BLOCK_SIZE_NONE);
if ((1 << channel_id) & DMA2D_LL_TX_CHANNEL_SUPPORT_CSC_MASK) {
@@ -608,7 +609,7 @@ esp_err_t dma2d_connect(dma2d_channel_handle_t dma2d_chan, const dma2d_trigger_t
dma2d_ll_rx_enable_owner_check(group->hal.dev, channel_id, false);
dma2d_ll_rx_set_auto_return_owner(group->hal.dev, channel_id, DMA2D_DESCRIPTOR_BUFFER_OWNER_CPU); // After auto write back, the owner field will be cleared
dma2d_ll_rx_enable_descriptor_burst(group->hal.dev, channel_id, false);
dma2d_ll_rx_set_data_burst_length(group->hal.dev, channel_id, DMA2D_DATA_BURST_LENGTH_128);
dma2d_ll_rx_set_data_burst_length(group->hal.dev, channel_id, 128);
dma2d_ll_rx_enable_page_bound_wrap(group->hal.dev, channel_id, true);
dma2d_ll_rx_set_macro_block_size(group->hal.dev, channel_id, DMA2D_MACRO_BLOCK_SIZE_NONE);
if ((1 << channel_id) & DMA2D_LL_RX_CHANNEL_SUPPORT_CSC_MASK) {
@@ -713,6 +714,8 @@ esp_err_t dma2d_set_desc_addr(dma2d_channel_handle_t dma2d_chan, intptr_t desc_b
ESP_GOTO_ON_FALSE_ISR(dma2d_chan && desc_base_addr, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument");
// 2D-DMA descriptor addr needs 8-byte alignment and not in SPM (addr not in SPM is IDF restriction)
ESP_GOTO_ON_FALSE_ISR((desc_base_addr & 0x7) == 0 && !esp_ptr_in_spm((void *)desc_base_addr), ESP_ERR_INVALID_ARG, err, TAG, "invalid argument");
// When flash encryption is enabled, the descriptor must be in internal RAM because descriptor size is not 16-byte aligned, which breaks flash encryption alignment restriction
ESP_GOTO_ON_FALSE_ISR(!esp_efuse_is_flash_encryption_enabled() || esp_ptr_internal((void *)desc_base_addr), ESP_ERR_INVALID_ARG, err, TAG, "invalid argument");
dma2d_group_t *group = dma2d_chan->group;
int channel_id = dma2d_chan->channel_id;
@@ -828,19 +831,30 @@ esp_err_t dma2d_set_transfer_ability(dma2d_channel_handle_t dma2d_chan, const dm
{
esp_err_t ret = ESP_OK;
ESP_GOTO_ON_FALSE_ISR(dma2d_chan && ability, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument");
ESP_GOTO_ON_FALSE_ISR(ability->data_burst_length < DMA2D_DATA_BURST_LENGTH_INVALID, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument");
ESP_GOTO_ON_FALSE_ISR(ability->data_burst_length && ((ability->data_burst_length & (ability->data_burst_length - 1)) == 0), ESP_ERR_INVALID_ARG, err, TAG, "invalid argument"); // burst size must be power of 2
ESP_GOTO_ON_FALSE_ISR(ability->mb_size < DMA2D_MACRO_BLOCK_SIZE_INVALID, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument");
dma2d_group_t *group = dma2d_chan->group;
int channel_id = dma2d_chan->channel_id;
// When flash encryption is enabled, and the channel is accessing external memory, burst length has to be as least as the encryption alignment restriction size
uint32_t data_burst_length = ability->data_burst_length;
#if SOC_PSRAM_DMA_CAPABLE || SOC_DMA_CAN_ACCESS_FLASH
if (esp_efuse_is_flash_encryption_enabled() && ability->access_ext_mem) {
if (data_burst_length < SOC_MEMSPI_ENCRYPTION_ALIGNMENT) {
data_burst_length = SOC_MEMSPI_ENCRYPTION_ALIGNMENT;
ESP_LOGW(TAG, "channel access encrypted external memory, adjust burst size to %d", SOC_MEMSPI_ENCRYPTION_ALIGNMENT);
}
}
#endif
if (dma2d_chan->direction == DMA2D_CHANNEL_DIRECTION_TX) {
dma2d_ll_tx_enable_descriptor_burst(group->hal.dev, channel_id, ability->desc_burst_en);
dma2d_ll_tx_set_data_burst_length(group->hal.dev, channel_id, ability->data_burst_length);
dma2d_ll_tx_set_data_burst_length(group->hal.dev, channel_id, data_burst_length);
dma2d_ll_tx_set_macro_block_size(group->hal.dev, channel_id, ability->mb_size);
} else {
dma2d_ll_rx_enable_descriptor_burst(group->hal.dev, channel_id, ability->desc_burst_en);
dma2d_ll_rx_set_data_burst_length(group->hal.dev, channel_id, ability->data_burst_length);
dma2d_ll_rx_set_data_burst_length(group->hal.dev, channel_id, data_burst_length);
dma2d_ll_rx_set_macro_block_size(group->hal.dev, channel_id, ability->mb_size);
}
+1 -1
View File
@@ -422,7 +422,7 @@ esp_err_t gdma_config_transfer(gdma_channel_handle_t dma_chan, const gdma_transf
#if (SOC_PSRAM_DMA_CAPABLE || SOC_DMA_CAN_ACCESS_FLASH) && SOC_AHB_GDMA_VERSION != 1
// if MSPI encryption is enabled, and DMA wants to read/write external memory
if (esp_efuse_is_flash_encryption_enabled() && config->access_ext_mem) {
uint32_t enc_mem_alignment = GDMA_LL_GET(ACCESS_ENCRYPTION_MEM_ALIGNMENT);
uint32_t enc_mem_alignment = SOC_MEMSPI_ENCRYPTION_ALIGNMENT;
// when DMA access the encrypted external memory, extra alignment is needed for external memory
ext_mem_alignment = MAX(ext_mem_alignment, enc_mem_alignment);
if (max_data_burst_size < enc_mem_alignment) {
@@ -3,6 +3,7 @@
components/esp_driver_dma/test_apps/dma:
disable:
- if: SOC_GDMA_SUPPORTED != 1 and SOC_CP_DMA_SUPPORTED != 1
- if: CONFIG_NAME == "flash_enc" and SOC_FLASH_ENC_SUPPORTED != 1
depends_components:
- *common_components
- esp_driver_dma
@@ -249,7 +249,7 @@ static void test_gdma_m2m_transaction(gdma_channel_handle_t tx_chan, gdma_channe
}
// test DMA can read data from main flash
#if SOC_DMA_CAN_ACCESS_FLASH
static const char src_string[] __attribute__((aligned(GDMA_LL_GET(ACCESS_ENCRYPTION_MEM_ALIGNMENT)))) = "GDMA can read MSPI Flash data!!!";
static const char src_string[] __attribute__((aligned(SOC_MEMSPI_ENCRYPTION_ALIGNMENT))) = "GDMA can read MSPI Flash data!!!";
size_t src_string_len = strlen(src_string);
TEST_ASSERT_TRUE(esp_ptr_in_drom(src_string));
@@ -70,10 +70,10 @@ static void test_gdma_crc_calculation(gdma_channel_handle_t tx_chan, int test_nu
uint32_t crc_result = 0;
static const char test_input_string[] __attribute__((aligned(GDMA_LL_GET(ACCESS_ENCRYPTION_MEM_ALIGNMENT)))) = "GDMACRC Share::Connect::Innovate";
static const char test_input_string[] __attribute__((aligned(SOC_MEMSPI_ENCRYPTION_ALIGNMENT))) = "GDMACRC Share::Connect::Innovate";
size_t input_data_size = strlen(test_input_string);
TEST_ASSERT_EQUAL((uintptr_t)test_input_string % GDMA_LL_GET(ACCESS_ENCRYPTION_MEM_ALIGNMENT), 0);
TEST_ASSERT_EQUAL((uintptr_t)test_input_string % SOC_MEMSPI_ENCRYPTION_ALIGNMENT, 0);
// this test case also test the GDMA can fetch data from MSPI Flash
TEST_ASSERT_TRUE(esp_ptr_in_drom(test_input_string));
printf("Calculate CRC value for string: \"%s\"\r\n", test_input_string);
@@ -53,12 +53,12 @@ def test_dma_weighted_arbitration(dut: Dut) -> None:
@pytest.mark.parametrize(
'config',
[
'ext_mem_encryption',
'flash_enc',
],
indirect=True,
)
@idf_parametrize('target', ['esp32p4', 'esp32c5'], indirect=['target'])
def test_dma_ext_mem_encryption(dut: Dut) -> None:
def test_dma_flash_encryption(dut: Dut) -> None:
dut.run_all_single_board_cases(reset=True)
@@ -66,10 +66,10 @@ def test_dma_ext_mem_encryption(dut: Dut) -> None:
@pytest.mark.parametrize(
'config',
[
'ext_mem_encryption',
'flash_enc',
],
indirect=True,
)
@idf_parametrize('target', ['esp32s3'], indirect=['target'])
def test_dma_ext_mem_encryption_s3_f4r8(dut: Dut) -> None:
def test_dma_flash_encryption_s3_f4r8(dut: Dut) -> None:
dut.run_all_single_board_cases(reset=True)
@@ -6,5 +6,5 @@ set(srcs "test_app_main.c"
# the component can be registered as WHOLE_ARCHIVE
idf_component_register(SRCS ${srcs}
INCLUDE_DIRS "."
PRIV_REQUIRES unity esp_mm esp_psram esp_driver_dma
PRIV_REQUIRES unity esp_mm esp_psram esp_driver_dma efuse
WHOLE_ARCHIVE)
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -17,6 +17,9 @@
#include "hal/color_types.h"
#include "esp_heap_caps.h"
#include "esp_cache.h"
#include "esp_efuse.h"
#define ALIGN_UP(num, align) (((num) + ((align) - 1)) & ~((align) - 1))
// All test will perform `M2M_TRANS_TIMES` times memcpy transactions, utilizing all available 2D-DMA channels.
// This tests the hardware capability of multiple 2D-DMA transactions running together, and the driver capbility of
@@ -25,6 +28,7 @@
#define M2M_TRANS_TIMES (12)
// Descriptor and buffer address and size should aligned to 64 bytes (the cacheline size alignment restriction) to be used by CPU
// Additionally, if flash encryption is enabled, no matter descriptor or buffer, if in internal RAM, the address should be 16-byte aligned; if in external RAM, the address and size both should be 16-byte aligned.
static dma2d_descriptor_t *tx_dsc[M2M_TRANS_TIMES];
static dma2d_descriptor_t *rx_dsc[M2M_TRANS_TIMES];
@@ -71,8 +75,13 @@ TEST_CASE("DMA2D_M2M_1D_basic", "[DMA2D]")
memset(m2m_trans_config, 0, M2M_TRANS_TIMES * sizeof(dma2d_m2m_trans_config_t));
TEST_ESP_OK(dma2d_m2m_init());
dma2d_descriptor_t *tx_link_buffer = (dma2d_descriptor_t *)heap_caps_aligned_calloc(64, M2M_TRANS_TIMES, 64, MALLOC_CAP_DEFAULT);
dma2d_descriptor_t *rx_link_buffer = (dma2d_descriptor_t *)heap_caps_aligned_calloc(64, M2M_TRANS_TIMES, 64, MALLOC_CAP_DEFAULT);
uint32_t desc_malloc_cap = MALLOC_CAP_DEFAULT; // can be in internal RAM or external RAM
if (esp_efuse_is_flash_encryption_enabled()) {
// descriptor size is not 16-byte aligned, so can not be in external RAM
desc_malloc_cap = MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT;
}
dma2d_descriptor_t *tx_link_buffer = (dma2d_descriptor_t *)heap_caps_aligned_calloc(64, M2M_TRANS_TIMES, 64, desc_malloc_cap);
dma2d_descriptor_t *rx_link_buffer = (dma2d_descriptor_t *)heap_caps_aligned_calloc(64, M2M_TRANS_TIMES, 64, desc_malloc_cap);
TEST_ASSERT_NOT_NULL(tx_link_buffer);
TEST_ASSERT_NOT_NULL(rx_link_buffer);
for (int i = 0; i < M2M_TRANS_TIMES; i++) {
@@ -88,7 +97,8 @@ TEST_CASE("DMA2D_M2M_1D_basic", "[DMA2D]")
TEST_ASSERT_NOT_NULL(rx_buf);
dma2d_transfer_ability_t transfer_ability_config = {
.data_burst_length = DMA2D_DATA_BURST_LENGTH_64,
.access_ext_mem = true,
.data_burst_length = 64,
.desc_burst_en = true,
.mb_size = DMA2D_MACRO_BLOCK_SIZE_NONE,
};
@@ -210,8 +220,13 @@ TEST_CASE("DMA2D_M2M_1D_RGB565_to_RGB888", "[DMA2D]")
memset(m2m_trans_config, 0, M2M_TRANS_TIMES * sizeof(dma2d_m2m_trans_config_t));
TEST_ESP_OK(dma2d_m2m_init());
dma2d_descriptor_t *tx_link_buffer = (dma2d_descriptor_t *)heap_caps_aligned_calloc(64, M2M_TRANS_TIMES, 64, MALLOC_CAP_DEFAULT);
dma2d_descriptor_t *rx_link_buffer = (dma2d_descriptor_t *)heap_caps_aligned_calloc(64, M2M_TRANS_TIMES, 64, MALLOC_CAP_DEFAULT);
uint32_t desc_malloc_cap = MALLOC_CAP_DEFAULT; // can be in internal RAM or external RAM
if (esp_efuse_is_flash_encryption_enabled()) {
// descriptor size is not 16-byte aligned, so can not be in external RAM
desc_malloc_cap = MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT;
}
dma2d_descriptor_t *tx_link_buffer = (dma2d_descriptor_t *)heap_caps_aligned_calloc(64, M2M_TRANS_TIMES, 64, desc_malloc_cap);
dma2d_descriptor_t *rx_link_buffer = (dma2d_descriptor_t *)heap_caps_aligned_calloc(64, M2M_TRANS_TIMES, 64, desc_malloc_cap);
TEST_ASSERT_NOT_NULL(tx_link_buffer);
TEST_ASSERT_NOT_NULL(rx_link_buffer);
for (int i = 0; i < M2M_TRANS_TIMES; i++) {
@@ -229,7 +244,8 @@ TEST_CASE("DMA2D_M2M_1D_RGB565_to_RGB888", "[DMA2D]")
SemaphoreHandle_t counting_sem = xSemaphoreCreateCounting(M2M_TRANS_TIMES, 0);
dma2d_transfer_ability_t transfer_ability_config = {
.data_burst_length = DMA2D_DATA_BURST_LENGTH_128,
.access_ext_mem = true,
.data_burst_length = 128,
.desc_burst_en = true,
.mb_size = DMA2D_MACRO_BLOCK_SIZE_NONE,
};
@@ -323,8 +339,13 @@ TEST_CASE("DMA2D_M2M_2D_basic", "[DMA2D]")
memset(m2m_trans_config, 0, M2M_TRANS_TIMES * sizeof(dma2d_m2m_trans_config_t));
TEST_ESP_OK(dma2d_m2m_init());
dma2d_descriptor_t *tx_link_buffer = (dma2d_descriptor_t *)heap_caps_aligned_calloc(64, M2M_TRANS_TIMES, 64, MALLOC_CAP_DEFAULT);
dma2d_descriptor_t *rx_link_buffer = (dma2d_descriptor_t *)heap_caps_aligned_calloc(64, M2M_TRANS_TIMES, 64, MALLOC_CAP_DEFAULT);
uint32_t desc_malloc_cap = MALLOC_CAP_DEFAULT; // can be in internal RAM or external RAM
if (esp_efuse_is_flash_encryption_enabled()) {
// descriptor size is not 16-byte aligned, so can not be in external RAM
desc_malloc_cap = MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT;
}
dma2d_descriptor_t *tx_link_buffer = (dma2d_descriptor_t *)heap_caps_aligned_calloc(64, M2M_TRANS_TIMES, 64, desc_malloc_cap);
dma2d_descriptor_t *rx_link_buffer = (dma2d_descriptor_t *)heap_caps_aligned_calloc(64, M2M_TRANS_TIMES, 64, desc_malloc_cap);
TEST_ASSERT_NOT_NULL(tx_link_buffer);
TEST_ASSERT_NOT_NULL(rx_link_buffer);
for (int i = 0; i < M2M_TRANS_TIMES; i++) {
@@ -342,7 +363,8 @@ TEST_CASE("DMA2D_M2M_2D_basic", "[DMA2D]")
SemaphoreHandle_t counting_sem = xSemaphoreCreateCounting(M2M_TRANS_TIMES, 0);
dma2d_transfer_ability_t transfer_ability_config = {
.data_burst_length = DMA2D_DATA_BURST_LENGTH_128,
.access_ext_mem = true,
.data_burst_length = 128,
.desc_burst_en = true,
.mb_size = DMA2D_MACRO_BLOCK_SIZE_NONE,
};
@@ -456,8 +478,13 @@ TEST_CASE("DMA2D_M2M_2D_RGB888_to_RGB565", "[DMA2D]")
memset(m2m_trans_config, 0, M2M_TRANS_TIMES * sizeof(dma2d_m2m_trans_config_t));
TEST_ESP_OK(dma2d_m2m_init());
dma2d_descriptor_t *tx_link_buffer = (dma2d_descriptor_t *)heap_caps_aligned_calloc(64, M2M_TRANS_TIMES, 64, MALLOC_CAP_DEFAULT);
dma2d_descriptor_t *rx_link_buffer = (dma2d_descriptor_t *)heap_caps_aligned_calloc(64, M2M_TRANS_TIMES, 64, MALLOC_CAP_DEFAULT);
uint32_t desc_malloc_cap = MALLOC_CAP_DEFAULT; // can be in internal RAM or external RAM
if (esp_efuse_is_flash_encryption_enabled()) {
// descriptor size is not 16-byte aligned, so can not be in external RAM
desc_malloc_cap = MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT;
}
dma2d_descriptor_t *tx_link_buffer = (dma2d_descriptor_t *)heap_caps_aligned_calloc(64, M2M_TRANS_TIMES, 64, desc_malloc_cap);
dma2d_descriptor_t *rx_link_buffer = (dma2d_descriptor_t *)heap_caps_aligned_calloc(64, M2M_TRANS_TIMES, 64, desc_malloc_cap);
TEST_ASSERT_NOT_NULL(tx_link_buffer);
TEST_ASSERT_NOT_NULL(rx_link_buffer);
for (int i = 0; i < M2M_TRANS_TIMES; i++) {
@@ -475,7 +502,8 @@ TEST_CASE("DMA2D_M2M_2D_RGB888_to_RGB565", "[DMA2D]")
SemaphoreHandle_t counting_sem = xSemaphoreCreateCounting(M2M_TRANS_TIMES, 0);
dma2d_transfer_ability_t transfer_ability_config = {
.data_burst_length = DMA2D_DATA_BURST_LENGTH_16,
.access_ext_mem = true,
.data_burst_length = 16,
.desc_burst_en = true,
.mb_size = DMA2D_MACRO_BLOCK_SIZE_NONE,
};
@@ -562,17 +590,30 @@ TEST_CASE("DMA2D_M2M_2D_RGB888_to_RGB565", "[DMA2D]")
TEST_CASE("DMA2D_M2M_2D_window", "[DMA2D]")
{
// Test 2D memcpy to a 2 x 2 block at (2, 4) in a 8 x 8 picture (pixel in RGB565 format)
// Test 2D memcpy to a 8 x 2 block at (8,0) in a 24 x 8 picture (pixel in RGB565 format)
// When flash encryption is enabled, and tx/rx buffer are in PSRAM (if located in internal RAM, there is no alignment restriction due to encryption):
// - The address and size of the tx/rx buffer should be 16-byte aligned
// - The width of the window multiply byte number of one pixel should be 16-byte aligned
// - The address of every row of the window should be 16-byte aligned
const esp_color_fourcc_t pixel_format = ESP_COLOR_FOURCC_RGB16;
const uint32_t va = 8, ha = 8; // Define picture height and width (unit: pixel)
const uint32_t vb = 2, hb = 2; // Define block height and width (unit: pixel)
const uint32_t x_offset = 2, y_offset = 4; // Define block location in the picture (unit: pixel)
const uint32_t va = 8, ha = 24; // Define picture height and width (unit: pixel)
const uint32_t vb = 2, hb = 8; // Define block height and width (unit: pixel)
const uint32_t x_offset = 8, y_offset = 0; // Define block location in the picture (unit: pixel)
memset(m2m_trans_config, 0, M2M_TRANS_TIMES * sizeof(dma2d_m2m_trans_config_t));
TEST_ESP_OK(dma2d_m2m_init());
dma2d_descriptor_t *tx_link_buffer = (dma2d_descriptor_t *)heap_caps_aligned_calloc(64, M2M_TRANS_TIMES, 64, MALLOC_CAP_DEFAULT);
dma2d_descriptor_t *rx_link_buffer = (dma2d_descriptor_t *)heap_caps_aligned_calloc(64, M2M_TRANS_TIMES, 64, MALLOC_CAP_DEFAULT);
uint32_t desc_malloc_cap = MALLOC_CAP_DEFAULT; // can be in internal RAM or external RAM
uint32_t buf_malloc_cap = MALLOC_CAP_INTERNAL;
if (esp_efuse_is_flash_encryption_enabled()) {
// descriptor size is not 16-byte aligned, so can not be in external RAM
desc_malloc_cap = MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT;
buf_malloc_cap = MALLOC_CAP_SPIRAM; // to test its strict alignment requirement
}
dma2d_descriptor_t *tx_link_buffer = (dma2d_descriptor_t *)heap_caps_aligned_calloc(64, M2M_TRANS_TIMES, 64, desc_malloc_cap);
dma2d_descriptor_t *rx_link_buffer = (dma2d_descriptor_t *)heap_caps_aligned_calloc(64, M2M_TRANS_TIMES, 64, desc_malloc_cap);
TEST_ASSERT_NOT_NULL(tx_link_buffer);
TEST_ASSERT_NOT_NULL(rx_link_buffer);
for (int i = 0; i < M2M_TRANS_TIMES; i++) {
@@ -582,15 +623,18 @@ TEST_CASE("DMA2D_M2M_2D_window", "[DMA2D]")
uint8_t *prtx;
uint8_t *prrx;
uint8_t *tx_buf = heap_caps_aligned_calloc(64, 64 * M2M_TRANS_TIMES, sizeof(uint8_t), MALLOC_CAP_INTERNAL);
uint8_t *rx_buf = heap_caps_aligned_calloc(64, va * ha * 2 * M2M_TRANS_TIMES, sizeof(uint8_t), MALLOC_CAP_INTERNAL);
size_t tx_buf_size = ALIGN_UP(vb * hb * 2, 64); // buffer msync alignment restriction
uint8_t *tx_buf = heap_caps_aligned_calloc(64, tx_buf_size * M2M_TRANS_TIMES, sizeof(uint8_t), buf_malloc_cap);
size_t rx_buf_size = ALIGN_UP(va * ha * 2, 64); // buffer msync alignment restriction
uint8_t *rx_buf = heap_caps_aligned_calloc(64, rx_buf_size * M2M_TRANS_TIMES, sizeof(uint8_t), buf_malloc_cap);
TEST_ASSERT_NOT_NULL(tx_buf);
TEST_ASSERT_NOT_NULL(rx_buf);
SemaphoreHandle_t counting_sem = xSemaphoreCreateCounting(M2M_TRANS_TIMES, 0);
dma2d_transfer_ability_t transfer_ability_config = {
.data_burst_length = DMA2D_DATA_BURST_LENGTH_128,
.access_ext_mem = (buf_malloc_cap & MALLOC_CAP_SPIRAM) ? true : false,
.data_burst_length = 128,
.desc_burst_en = true,
.mb_size = DMA2D_MACRO_BLOCK_SIZE_NONE,
};
@@ -598,8 +642,8 @@ TEST_CASE("DMA2D_M2M_2D_window", "[DMA2D]")
// Preparation
for (int i = 0; i < M2M_TRANS_TIMES; i++) {
// Buffer data preparation
prtx = tx_buf + i * 64;
prrx = rx_buf + i * va * ha * 2;
prtx = tx_buf + i * tx_buf_size;
prrx = rx_buf + i * rx_buf_size;
for (int idx = 0; idx < vb * hb; idx++) {
prtx[idx * 2] = 0x55 + idx + i;
prtx[idx * 2 + 1] = 0xAA + idx + i;
@@ -610,8 +654,8 @@ TEST_CASE("DMA2D_M2M_2D_window", "[DMA2D]")
}
// Writeback TX and RX buffers
esp_cache_msync((void *)prtx, 64, ESP_CACHE_MSYNC_FLAG_DIR_C2M);
esp_cache_msync((void *)prrx, va * ha * 2, ESP_CACHE_MSYNC_FLAG_DIR_C2M);
esp_cache_msync((void *)prtx, tx_buf_size, ESP_CACHE_MSYNC_FLAG_DIR_C2M);
esp_cache_msync((void *)prrx, rx_buf_size, ESP_CACHE_MSYNC_FLAG_DIR_C2M);
// DMA description preparation
dma2d_link_dscr_init((uint32_t *)tx_dsc[i], NULL, (void *)prtx,
@@ -649,12 +693,12 @@ TEST_CASE("DMA2D_M2M_2D_window", "[DMA2D]")
// Print the picture and check result
for (int i = 0; i < M2M_TRANS_TIMES; i++) {
prtx = tx_buf + i * 64;
prrx = rx_buf + i * va * ha * 2;
prtx = tx_buf + i * tx_buf_size;
prrx = rx_buf + i * rx_buf_size;
// Invalidate TX and RX buffers
esp_cache_msync((void *)prtx, 64, ESP_CACHE_MSYNC_FLAG_DIR_M2C);
esp_cache_msync((void *)prrx, va * ha * 2, ESP_CACHE_MSYNC_FLAG_DIR_M2C);
esp_cache_msync((void *)prtx, tx_buf_size, ESP_CACHE_MSYNC_FLAG_DIR_M2C);
esp_cache_msync((void *)prrx, rx_buf_size, ESP_CACHE_MSYNC_FLAG_DIR_M2C);
printf("pic:\n");
for (int idx = 0; idx < va * ha; idx++) {
@@ -17,3 +17,16 @@ from pytest_embedded_idf.utils import soc_filtered_targets
@idf_parametrize('target', soc_filtered_targets('SOC_DMA2D_SUPPORTED == 1'), indirect=['target'])
def test_dma2d(dut: Dut) -> None:
dut.run_all_single_board_cases()
@pytest.mark.flash_encryption
@pytest.mark.parametrize(
'config',
[
'flash_enc',
],
indirect=True,
)
@idf_parametrize('target', soc_filtered_targets('SOC_DMA2D_SUPPORTED == 1'), indirect=['target'])
def test_dma2d_flash_encryption(dut: Dut) -> None:
dut.run_all_single_board_cases()
@@ -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
+4 -2
View File
@@ -521,13 +521,15 @@ static void jpeg_dec_config_dma_trans_ability(jpeg_decoder_handle_t decoder_engi
{
// set transfer ability
dma2d_transfer_ability_t transfer_ability_config_tx = {
.data_burst_length = DMA2D_DATA_BURST_LENGTH_128,
.access_ext_mem = true, // in most cases
.data_burst_length = 128,
.desc_burst_en = true,
.mb_size = DMA2D_MACRO_BLOCK_SIZE_NONE,
};
dma2d_transfer_ability_t transfer_ability_config_rx = {
.data_burst_length = DMA2D_DATA_BURST_LENGTH_128,
.access_ext_mem = true, // in most cases
.data_burst_length = 128,
.desc_burst_en = true,
.mb_size = DMA2D_MACRO_BLOCK_SIZE_NONE,
};
+4 -2
View File
@@ -434,13 +434,15 @@ static void jpeg_enc_config_dma_trans_ability(jpeg_encoder_handle_t encoder_engi
{
// set transfer ability
dma2d_transfer_ability_t transfer_ability_config_tx = {
.data_burst_length = DMA2D_DATA_BURST_LENGTH_128,
.access_ext_mem = true, // in most cases
.data_burst_length = 128,
.desc_burst_en = true,
.mb_size = DMA2D_MACRO_BLOCK_SIZE_NONE,
};
dma2d_transfer_ability_t transfer_ability_config_rx = {
.data_burst_length = DMA2D_DATA_BURST_LENGTH_128,
.access_ext_mem = true, // in most cases
.data_burst_length = 128,
.desc_burst_en = true,
.mb_size = DMA2D_MACRO_BLOCK_SIZE_NONE,
};
+1 -1
View File
@@ -12,7 +12,7 @@ endif()
if(${target} STREQUAL "linux")
set(priv_requires "")
else()
set(priv_requires esp_mm esp_pm esp_driver_dma)
set(priv_requires esp_mm esp_pm esp_driver_dma efuse)
endif()
@@ -124,6 +124,7 @@ typedef struct {
ppa_srm_color_mode_t srm_cm; /*!< Color mode of the picture in a PPA SRM operation. Supported color mode in `ppa_srm_color_mode_t` */
ppa_blend_color_mode_t blend_cm; /*!< Color mode of the picture in a PPA blend operation. Supported color mode in `ppa_blend_color_mode_t` */
ppa_fill_color_mode_t fill_cm; /*!< Color mode of the picture in a PPA fill operation. Supported color mode in `ppa_fill_color_mode_t` */
esp_color_fourcc_t cm; /*!< Four Character Code of the color mode */
};
ppa_color_range_t yuv_range; /*!< When the color mode is any YUV color space, this field is to describe its color range */
ppa_color_conv_std_rgb_yuv_t yuv_std; /*!< When the color mode is any YUV color space, this field is to describe its YUV<->RGB conversion standard */
@@ -143,6 +144,7 @@ typedef struct {
ppa_srm_color_mode_t srm_cm; /*!< Color mode of the picture in a PPA SRM operation. Supported color mode in `ppa_srm_color_mode_t` */
ppa_blend_color_mode_t blend_cm; /*!< Color mode of the picture in a PPA blend operation. Supported color mode in `ppa_blend_color_mode_t` */
ppa_fill_color_mode_t fill_cm; /*!< Color mode of the picture in a PPA fill operation. Supported color mode in `ppa_fill_color_mode_t` */
esp_color_fourcc_t cm; /*!< Four Character Code of the color mode */
};
ppa_color_range_t yuv_range; /*!< When the color mode is any YUV color space, this field is to describe its color range */
ppa_color_conv_std_rgb_yuv_t yuv_std; /*!< When the color mode is any YUV color space, this field is to describe its YUV<->RGB conversion standard */
+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
*/
@@ -108,6 +108,7 @@ bool ppa_blend_transaction_on_picked(uint32_t num_chans, const dma2d_trans_chann
dma2d_connect(dma2d_rx_chan, &trig_periph);
dma2d_transfer_ability_t dma_transfer_ability = {
.access_ext_mem = true, // in most cases the buffers are located in external memory, will not bother checking the memory region of the buffers
.data_burst_length = blend_trans_desc->data_burst_length,
.desc_burst_en = true,
.mb_size = DMA2D_MACRO_BLOCK_SIZE_NONE,
@@ -177,9 +178,6 @@ esp_err_t ppa_do_blend(ppa_client_handle_t ppa_client, const ppa_blend_oper_conf
ESP_RETURN_ON_FALSE(config->mode <= PPA_TRANS_MODE_NON_BLOCKING, ESP_ERR_INVALID_ARG, TAG, "invalid mode");
// in_buffer could be anywhere (ram, flash, psram), out_buffer ptr cannot in flash region
ESP_RETURN_ON_FALSE(esp_ptr_internal(config->out.buffer) || esp_ptr_external_ram(config->out.buffer), ESP_ERR_INVALID_ARG, TAG, "invalid out.buffer addr");
uint32_t buf_alignment_size = (uint32_t)ppa_client->engine->platform->buf_alignment_size;
ESP_RETURN_ON_FALSE(((uint32_t)config->out.buffer & (buf_alignment_size - 1)) == 0 && (config->out.buffer_size & (buf_alignment_size - 1)) == 0,
ESP_ERR_INVALID_ARG, TAG, "out.buffer addr or out.buffer_size not aligned to cache line size");
ESP_RETURN_ON_FALSE(ppa_ll_blend_is_color_mode_supported(config->in_bg.blend_cm) && ppa_ll_blend_is_color_mode_supported(config->in_fg.blend_cm) && ppa_ll_blend_is_color_mode_supported(config->out.blend_cm), ESP_ERR_INVALID_ARG, TAG, "unsupported color mode");
// For YUV420 input/output: in desc, ha/hb/va/vb/x/y must be even number
// For YUV422 input/output: in desc, ha/hb/x must be even number
@@ -223,6 +221,13 @@ esp_err_t ppa_do_blend(ppa_client_handle_t ppa_client, const ppa_blend_oper_conf
ESP_RETURN_ON_FALSE(config->in_fg.block_w <= (config->out.pic_w - config->out.block_offset_x) &&
config->in_fg.block_h <= (config->out.pic_h - config->out.block_offset_y),
ESP_ERR_INVALID_ARG, TAG, "block does not fit in the out pic");
if (!ppa_check_buffer_alignment(ppa_client, &config->in_bg, true, config->in_bg.block_w) ||
!ppa_check_buffer_alignment(ppa_client, &config->in_fg, true, config->in_fg.block_w) ||
!ppa_check_buffer_alignment(ppa_client, &config->out, false, config->in_fg.block_w)) {
return ESP_ERR_INVALID_ARG;
}
if (config->bg_byte_swap) {
PPA_CHECK_CM_SUPPORT_BYTE_SWAP("in_bg.blend", (uint32_t)config->in_bg.blend_cm);
}
@@ -255,6 +260,7 @@ esp_err_t ppa_do_blend(ppa_client_handle_t ppa_client, const ppa_blend_oper_conf
// Write back and invalidate necessary data (note that the window content is not continuous in the buffer)
// Write back in_bg_buffer, in_fg_buffer extended windows (alignment not necessary on C2M direction)
uint32_t buf_alignment_size = (uint32_t)ppa_client->engine->platform->buf_alignment_size;
uint32_t in_bg_pixel_depth = color_hal_pixel_format_fourcc_get_bit_depth((esp_color_fourcc_t)config->in_bg.blend_cm); // bits
// Usually C2M can let the msync do alignment internally, however, it only do L1-cacheline-size alignment for L1->L2, and then L2-cacheline-size alignment for L2->mem
// While M2C direction manual alignment is L2-cacheline-size alignment for mem->L2->L1
+51 -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 "esp_efuse.h"
#include "soc/soc_caps.h"
static const char *TAG = "ppa_core";
@@ -276,6 +281,10 @@ esp_err_t ppa_register_client(const ppa_client_config_t *config, ppa_client_hand
client->oper_type = config->oper_type;
client->spinlock = (portMUX_TYPE)portMUX_INITIALIZER_UNLOCKED;
client->data_burst_length = config->data_burst_length ? config->data_burst_length : PPA_DATA_BURST_LENGTH_128;
if (esp_efuse_is_flash_encryption_enabled() && (client->data_burst_length < SOC_MEMSPI_ENCRYPTION_ALIGNMENT)) {
ESP_LOGW(TAG, "flash encryption is enabled, but selected data burst length does not meet encryption alignment restriction if accessing external memory, will be automatically adjusted later on");
}
if (config->oper_type == PPA_OPERATION_SRM) {
ppa_engine_config_t engine_config = {
.engine = PPA_ENGINE_TYPE_SRM,
@@ -527,3 +536,44 @@ esp_err_t ppa_set_rgb2gray_formula(uint8_t r_weight, uint8_t g_weight, uint8_t b
_lock_release(&s_platform.mutex);
return ESP_OK;
}
bool ppa_check_buffer_alignment(ppa_client_handle_t ppa_client, const void *pic_blk_config, bool is_input, uint32_t block_width)
{
// 1. check with cache line size alignment (output buffer only)
uint32_t buf_alignment_size = (uint32_t)ppa_client->engine->platform->buf_alignment_size;
if (!is_input) {
ppa_out_pic_blk_config_t *out_pic_blk_config = (ppa_out_pic_blk_config_t *)pic_blk_config;
if (((uint32_t)out_pic_blk_config->buffer & (buf_alignment_size - 1)) != 0 || (out_pic_blk_config->buffer_size & (buf_alignment_size - 1)) != 0) {
ESP_LOGE(TAG, "out.buffer addr or out.buffer_size not aligned to cache line size");
return false;
}
}
// 2. check with mspi encryption alignment
// When flash encryption is enabled, and in/out buffer are in PSRAM (if located in internal RAM, there is no alignment restriction due to encryption):
// - The width of the window multiply byte number of one pixel should align to SOC_MEMSPI_ENCRYPTION_ALIGNMENT
// - The starting address of every row of the window should align to SOC_MEMSPI_ENCRYPTION_ALIGNMENT
// (which also implies the address and size of the in/out buffer will align to SOC_MEMSPI_ENCRYPTION_ALIGNMENT)
// check pic_width, block_width, block_head
const void *buffer = (is_input) ? ((ppa_in_pic_blk_config_t *)pic_blk_config)->buffer : ((ppa_out_pic_blk_config_t *)pic_blk_config)->buffer;
if (esp_efuse_is_flash_encryption_enabled() && !esp_ptr_internal(buffer)) {
if (ppa_client->engine->type == PPA_ENGINE_TYPE_SRM) {
ESP_LOGE(TAG, "SRM processes by macro blocks, where alignment is uncontrollable, makes it unable to work with flash encrypted if buffer is in external memory");
return false;
}
uint32_t pic_width = (is_input) ? ((ppa_in_pic_blk_config_t *)pic_blk_config)->pic_w : ((ppa_out_pic_blk_config_t *)pic_blk_config)->pic_w;
uint32_t block_offset_x = (is_input) ? ((ppa_in_pic_blk_config_t *)pic_blk_config)->block_offset_x : ((ppa_out_pic_blk_config_t *)pic_blk_config)->block_offset_x;
esp_color_fourcc_t color_mode = (is_input) ? ((ppa_in_pic_blk_config_t *)pic_blk_config)->cm : ((ppa_out_pic_blk_config_t *)pic_blk_config)->cm;
uint32_t pixel_depth_bytes = color_hal_pixel_format_fourcc_get_bit_depth(color_mode) / 8;
if (((pic_width * pixel_depth_bytes) & (SOC_MEMSPI_ENCRYPTION_ALIGNMENT - 1)) != 0 ||
((block_width * pixel_depth_bytes) & (SOC_MEMSPI_ENCRYPTION_ALIGNMENT - 1)) != 0 ||
((block_offset_x * pixel_depth_bytes) & (SOC_MEMSPI_ENCRYPTION_ALIGNMENT - 1)) != 0) {
ESP_LOGE(TAG, "(pic_width/block_width/block_offset_x * pixel_depth_bytes) not aligned to SOC_MEMSPI_ENCRYPTION_ALIGNMENT");
return false;
}
}
return true;
}
+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
*/
@@ -58,6 +58,7 @@ bool ppa_fill_transaction_on_picked(uint32_t num_chans, const dma2d_trans_channe
dma2d_connect(dma2d_rx_chan, &trig_periph);
dma2d_transfer_ability_t dma_transfer_ability = {
.access_ext_mem = true, // in most cases the buffer is located in external memory, will not bother checking the memory region of the buffer
.data_burst_length = fill_trans_desc->data_burst_length,
.desc_burst_en = true,
.mb_size = DMA2D_MACRO_BLOCK_SIZE_NONE,
@@ -89,9 +90,6 @@ esp_err_t ppa_do_fill(ppa_client_handle_t ppa_client, const ppa_fill_oper_config
ESP_RETURN_ON_FALSE(config->mode <= PPA_TRANS_MODE_NON_BLOCKING, ESP_ERR_INVALID_ARG, TAG, "invalid mode");
// out_buffer ptr cannot in flash region
ESP_RETURN_ON_FALSE(esp_ptr_internal(config->out.buffer) || esp_ptr_external_ram(config->out.buffer), ESP_ERR_INVALID_ARG, TAG, "invalid out.buffer addr");
uint32_t buf_alignment_size = (uint32_t)ppa_client->engine->platform->buf_alignment_size;
ESP_RETURN_ON_FALSE(((uint32_t)config->out.buffer & (buf_alignment_size - 1)) == 0 && (config->out.buffer_size & (buf_alignment_size - 1)) == 0,
ESP_ERR_INVALID_ARG, TAG, "out.buffer addr or out.buffer_size not aligned to cache line size");
ESP_RETURN_ON_FALSE(ppa_ll_blend_is_color_mode_supported((ppa_blend_color_mode_t)config->out.fill_cm), ESP_ERR_INVALID_ARG, TAG, "unsupported color mode");
// For YUV420 output: in desc, ha/hb/va/vb/x/y must be even number
// For YUV422 output: in desc, ha/hb/x must be even number
@@ -110,10 +108,15 @@ esp_err_t ppa_do_fill(ppa_client_handle_t ppa_client, const ppa_fill_oper_config
ESP_RETURN_ON_FALSE(config->fill_block_w <= (config->out.pic_w - config->out.block_offset_x) &&
config->fill_block_h <= (config->out.pic_h - config->out.block_offset_y),
ESP_ERR_INVALID_ARG, TAG, "block does not fit in the out pic");
if (!ppa_check_buffer_alignment(ppa_client, &config->out, false, config->fill_block_w)) {
return ESP_ERR_INVALID_ARG;
}
// To reduce complexity, specific color_mode, fill_block_w/h correctness are checked in their corresponding LL functions
// Write back and invalidate necessary data (note that the window content is not continuous in the buffer)
// Write back and invalidate buffer extended window (alignment not necessary on C2M direction, but alignment strict on M2C direction)
uint32_t buf_alignment_size = (uint32_t)ppa_client->engine->platform->buf_alignment_size;
uint32_t out_ext_window = (uint32_t)config->out.buffer + config->out.block_offset_y * config->out.pic_w * out_pixel_depth / 8;
uint32_t out_ext_window_aligned = PPA_ALIGN_DOWN(out_ext_window, buf_alignment_size);
uint32_t out_ext_window_len = config->out.pic_w * config->fill_block_h * out_pixel_depth / 8;
+2
View File
@@ -231,6 +231,8 @@ bool ppa_transaction_done_cb(dma2d_channel_handle_t dma2d_chan, dma2d_event_data
bool ppa_recycle_transaction(ppa_client_handle_t ppa_client, ppa_trans_t *trans_elm);
bool ppa_check_buffer_alignment(ppa_client_handle_t ppa_client, const void *pic_blk_config, bool is_input, uint32_t block_width);
/****************************** PPA DRIVER ***********************************/
struct ppa_platform_t {
+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
*/
@@ -89,6 +89,7 @@ bool ppa_srm_transaction_on_picked(uint32_t num_chans, const dma2d_trans_channel
dma2d_connect(dma2d_rx_chan, &trig_periph);
dma2d_transfer_ability_t dma_transfer_ability = {
.access_ext_mem = true, // in most cases the buffers are located in external memory, will not bother checking the memory region of the buffers
.data_burst_length = srm_trans_desc->data_burst_length,
.desc_burst_en = true,
.mb_size = DMA2D_MACRO_BLOCK_SIZE_NONE,
@@ -184,9 +185,6 @@ esp_err_t ppa_do_scale_rotate_mirror(ppa_client_handle_t ppa_client, const ppa_s
ESP_RETURN_ON_FALSE(config->mode <= PPA_TRANS_MODE_NON_BLOCKING, ESP_ERR_INVALID_ARG, TAG, "invalid mode");
// in_buffer could be anywhere (ram, flash, psram), out_buffer ptr cannot in flash region
ESP_RETURN_ON_FALSE(esp_ptr_internal(config->out.buffer) || esp_ptr_external_ram(config->out.buffer), ESP_ERR_INVALID_ARG, TAG, "invalid out.buffer addr");
uint32_t buf_alignment_size = (uint32_t)ppa_client->engine->platform->buf_alignment_size;
ESP_RETURN_ON_FALSE(((uint32_t)config->out.buffer & (buf_alignment_size - 1)) == 0 && (config->out.buffer_size & (buf_alignment_size - 1)) == 0,
ESP_ERR_INVALID_ARG, TAG, "out.buffer addr or out.buffer_size not aligned to cache line size");
ESP_RETURN_ON_FALSE(ppa_ll_srm_is_color_mode_supported(config->in.srm_cm) &&
(ppa_ll_srm_is_color_mode_supported(config->out.srm_cm) && config->out.srm_cm != PPA_SRM_COLOR_MODE_YUV444),
ESP_ERR_INVALID_ARG, TAG, "unsupported color mode");
@@ -218,18 +216,28 @@ esp_err_t ppa_do_scale_rotate_mirror(ppa_client_handle_t ppa_client, const ppa_s
ESP_RETURN_ON_FALSE(config->scale_x < PPA_LL_SRM_SCALING_INT_MAX && config->scale_x >= (1.0 / PPA_LL_SRM_SCALING_FRAG_MAX) &&
config->scale_y < PPA_LL_SRM_SCALING_INT_MAX && config->scale_y >= (1.0 / PPA_LL_SRM_SCALING_FRAG_MAX),
ESP_ERR_INVALID_ARG, TAG, "invalid scale");
uint32_t scale_x_int = (uint32_t)config->scale_x;
uint32_t scale_x_frag = (uint32_t)(config->scale_x * PPA_LL_SRM_SCALING_FRAG_MAX) & (PPA_LL_SRM_SCALING_FRAG_MAX - 1);
uint32_t scale_y_int = (uint32_t)config->scale_y;
uint32_t scale_y_frag = (uint32_t)(config->scale_y * PPA_LL_SRM_SCALING_FRAG_MAX) & (PPA_LL_SRM_SCALING_FRAG_MAX - 1);
uint32_t new_block_w = 0;
uint32_t new_block_h = 0;
if (config->rotation_angle == PPA_SRM_ROTATION_ANGLE_0 || config->rotation_angle == PPA_SRM_ROTATION_ANGLE_180) {
new_block_w = (uint32_t)(config->scale_x * config->in.block_w);
new_block_h = (uint32_t)(config->scale_y * config->in.block_h);
new_block_w = (uint32_t)(scale_x_int * config->in.block_w + scale_x_frag * config->in.block_w / PPA_LL_SRM_SCALING_FRAG_MAX);
new_block_h = (uint32_t)(scale_y_int * config->in.block_h + scale_y_frag * config->in.block_h / PPA_LL_SRM_SCALING_FRAG_MAX);
} else {
new_block_w = (uint32_t)(config->scale_y * config->in.block_h);
new_block_h = (uint32_t)(config->scale_x * config->in.block_w);
new_block_w = (uint32_t)(scale_y_int * config->in.block_h + scale_y_frag * config->in.block_h / PPA_LL_SRM_SCALING_FRAG_MAX);
new_block_h = (uint32_t)(scale_x_int * config->in.block_w + scale_x_frag * config->in.block_w / PPA_LL_SRM_SCALING_FRAG_MAX);
}
ESP_RETURN_ON_FALSE(new_block_w <= (config->out.pic_w - config->out.block_offset_x) &&
new_block_h <= (config->out.pic_h - config->out.block_offset_y),
ESP_ERR_INVALID_ARG, TAG, "scale does not fit in the out pic");
if (!ppa_check_buffer_alignment(ppa_client, &config->in, true, config->in.block_w) ||
!ppa_check_buffer_alignment(ppa_client, &config->out, false, new_block_w)) {
return ESP_ERR_INVALID_ARG;
}
if (config->byte_swap) {
PPA_CHECK_CM_SUPPORT_BYTE_SWAP("in.srm", (uint32_t)config->in.srm_cm);
}
@@ -248,6 +256,7 @@ esp_err_t ppa_do_scale_rotate_mirror(ppa_client_handle_t ppa_client, const ppa_s
// Write back and invalidate necessary data (note that the window content is not continuous in the buffer)
// Write back in_buffer extended window (alignment not necessary on C2M direction)
uint32_t buf_alignment_size = (uint32_t)ppa_client->engine->platform->buf_alignment_size;
uint32_t in_pixel_depth = color_hal_pixel_format_fourcc_get_bit_depth((esp_color_fourcc_t)config->in.srm_cm); // bits
uint32_t in_ext_window = (uint32_t)config->in.buffer + config->in.block_offset_y * config->in.pic_w * in_pixel_depth / 8;
uint32_t in_ext_window_len = config->in.pic_w * config->in.block_h * in_pixel_depth / 8;
@@ -269,10 +278,10 @@ esp_err_t ppa_do_scale_rotate_mirror(ppa_client_handle_t ppa_client, const ppa_s
ppa_srm_oper_t *srm_trans_desc = (ppa_srm_oper_t *)trans_on_picked_desc->srm_desc;
memcpy(srm_trans_desc, config, sizeof(ppa_srm_oper_config_t));
srm_trans_desc->scale_x_int = (uint32_t)srm_trans_desc->scale_x;
srm_trans_desc->scale_x_frag = (uint32_t)(srm_trans_desc->scale_x * PPA_LL_SRM_SCALING_FRAG_MAX) & (PPA_LL_SRM_SCALING_FRAG_MAX - 1);
srm_trans_desc->scale_y_int = (uint32_t)srm_trans_desc->scale_y;
srm_trans_desc->scale_y_frag = (uint32_t)(srm_trans_desc->scale_y * PPA_LL_SRM_SCALING_FRAG_MAX) & (PPA_LL_SRM_SCALING_FRAG_MAX - 1);
srm_trans_desc->scale_x_int = scale_x_int;
srm_trans_desc->scale_x_frag = scale_x_frag;
srm_trans_desc->scale_y_int = scale_y_int;
srm_trans_desc->scale_y_frag = scale_y_frag;
// SRM processes in blocks. Block x/(y) cannot be scaled to odd number when YUV422/YUV420 is the output color mode
// When block size is 16x16, odd number is possible, so needs to make them even
// When block size is 32x32, calculated frag values are always even
@@ -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)
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -19,6 +19,7 @@
#include "esp_cache.h"
#include "ppa_performance.h"
#include "esp_random.h"
#include "esp_efuse.h"
#define ALIGN_UP(num, align) (((num) + ((align) - 1)) & ~((align) - 1))
@@ -76,7 +77,9 @@ TEST_CASE("ppa_client_do_ppa_operation", "[PPA]")
.mode = PPA_TRANS_MODE_BLOCKING,
};
// A SRM client can request to do a SRM operation
TEST_ESP_OK(ppa_do_scale_rotate_mirror(ppa_client_srm_handle, &srm_oper_config));
if (!esp_efuse_is_flash_encryption_enabled()) {
TEST_ESP_OK(ppa_do_scale_rotate_mirror(ppa_client_srm_handle, &srm_oper_config));
}
// A non-SRM client can not request to do a SRM operation
TEST_ESP_ERR(ESP_ERR_INVALID_ARG, ppa_do_scale_rotate_mirror(ppa_client_blend_handle, &srm_oper_config));
@@ -159,6 +162,11 @@ static bool ppa_trans_done_cb(ppa_client_handle_t ppa_client, ppa_event_data_t *
TEST_CASE("ppa_pending_transactions_in_queue", "[PPA]")
{
// this test tests software correctness, and SRM does not work with flash encrypted if buffer is in external memory, so skip
if (esp_efuse_is_flash_encryption_enabled()) {
TEST_PASS_MESSAGE("Flash encryption is enabled, skip this test");
}
// A big picture block takes longer time to process, desired for this test case
const uint32_t w = 1920;
const uint32_t h = 1080;
@@ -267,7 +275,7 @@ TEST_CASE("ppa_srm_basic_data_correctness_check", "[PPA]")
const uint32_t buf_len = w * h * color_hal_pixel_format_fourcc_get_bit_depth((esp_color_fourcc_t)cm) / 8; // 32
uint32_t out_buf_size = ALIGN_UP(buf_len, 64);
uint8_t *out_buf = heap_caps_aligned_calloc(4, out_buf_size, sizeof(uint8_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT | MALLOC_CAP_DMA);
uint8_t *out_buf = heap_caps_aligned_calloc(4, out_buf_size, sizeof(uint8_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT | MALLOC_CAP_DMA); // located in internal RAM so even w/ flash encrypted, it won't be affected
TEST_ASSERT_NOT_NULL(out_buf);
esp_cache_msync((void *)out_buf, out_buf_size, ESP_CACHE_MSYNC_FLAG_DIR_C2M);
const uint16_t in_buf[16] = {
@@ -565,6 +573,11 @@ TEST_CASE("ppa_fill_basic_data_correctness_check", "[PPA]")
TEST_CASE("ppa_srm_performance", "[PPA]")
{
// SRM does not work with flash encrypted if buffer is in external memory, so skip
if (esp_efuse_is_flash_encryption_enabled()) {
TEST_PASS_MESSAGE("Flash encryption is enabled, skip this test");
}
// Configurable parameters
const uint32_t w = 1920; // 1920 / 1280 / 800 / 640
const uint32_t h = 1080; // 1080 / 720 / 480
@@ -655,8 +668,12 @@ TEST_CASE("ppa_blend_performance", "[PPA]")
const ppa_blend_color_mode_t in_fg_cm = PPA_BLEND_COLOR_MODE_ARGB8888;
const ppa_blend_color_mode_t out_cm = PPA_BLEND_COLOR_MODE_ARGB8888;
uint32_t in_bg_buf_size = w * h * color_hal_pixel_format_fourcc_get_bit_depth((esp_color_fourcc_t)in_bg_cm) / 8;
uint32_t in_fg_buf_size = w * h * color_hal_pixel_format_fourcc_get_bit_depth((esp_color_fourcc_t)in_fg_cm) / 8;
size_t in_buf_alignment = 4; // no special alignment requirement for input buffers
if (esp_efuse_is_flash_encryption_enabled()) {
in_buf_alignment = SOC_MEMSPI_ENCRYPTION_ALIGNMENT;
}
uint32_t in_bg_buf_size = ALIGN_UP(w * h * color_hal_pixel_format_fourcc_get_bit_depth((esp_color_fourcc_t)in_bg_cm) / 8, in_buf_alignment);
uint32_t in_fg_buf_size = ALIGN_UP(w * h * color_hal_pixel_format_fourcc_get_bit_depth((esp_color_fourcc_t)in_fg_cm) / 8, in_buf_alignment);
uint32_t out_buf_size = ALIGN_UP(w * h * color_hal_pixel_format_fourcc_get_bit_depth((esp_color_fourcc_t)out_cm) / 8, 64);
uint8_t *out_buf = heap_caps_aligned_calloc(4, out_buf_size, sizeof(uint8_t), MALLOC_CAP_SPIRAM | MALLOC_CAP_DMA);
TEST_ASSERT_NOT_NULL(out_buf);
@@ -722,10 +739,12 @@ TEST_CASE("ppa_blend_performance", "[PPA]")
printf("PPA Blend - Process Time: %lld us\n", oper_time);
// Check performance
uint64_t num_pixels_processed = block_w * block_h;
uint64_t px_per_second = (num_pixels_processed - PPA_BLEND_TIME_OFFSET) * 1000 * 1000 / oper_time;
printf("PPA Blend performance = %lld pixels/sec\n", px_per_second);
TEST_ASSERT_GREATER_THAN(PPA_BLEND_MIN_PERFORMANCE_PX_PER_SEC, px_per_second);
if (!esp_efuse_is_flash_encryption_enabled()) { // flash encryption slows down the performance, so skip the check
uint64_t num_pixels_processed = block_w * block_h;
uint64_t px_per_second = (num_pixels_processed - PPA_BLEND_TIME_OFFSET) * 1000 * 1000 / oper_time;
printf("PPA Blend performance = %lld pixels/sec\n", px_per_second);
TEST_ASSERT_GREATER_THAN(PPA_BLEND_MIN_PERFORMANCE_PX_PER_SEC, px_per_second);
}
TEST_ESP_OK(ppa_unregister_client(ppa_client_handle));
@@ -780,10 +799,12 @@ TEST_CASE("ppa_fill_performance", "[PPA]")
printf("PPA Fill - Process Time: %lld us\n", oper_time);
// Check performance
uint64_t num_pixels_processed = block_w * block_h;
uint64_t px_per_second = (num_pixels_processed - PPA_FILL_TIME_OFFSET) * 1000 * 1000 / oper_time;
printf("PPA Blend performance = %lld pixels/sec\n", px_per_second);
TEST_ASSERT_GREATER_THAN(PPA_FILL_MIN_PERFORMANCE_PX_PER_SEC, px_per_second);
if (!esp_efuse_is_flash_encryption_enabled()) { // flash encryption slows down the performance, so skip the check
uint64_t num_pixels_processed = block_w * block_h;
uint64_t px_per_second = (num_pixels_processed - PPA_FILL_TIME_OFFSET) * 1000 * 1000 / oper_time;
printf("PPA Blend performance = %lld pixels/sec\n", px_per_second);
TEST_ASSERT_GREATER_THAN(PPA_FILL_MIN_PERFORMANCE_PX_PER_SEC, px_per_second);
}
TEST_ESP_OK(ppa_unregister_client(ppa_client_handle));
@@ -792,6 +813,11 @@ TEST_CASE("ppa_fill_performance", "[PPA]")
TEST_CASE("ppa_srm_stress_test", "[PPA]")
{
// SRM does not work with flash encrypted if buffer is in external memory, so skip
if (esp_efuse_is_flash_encryption_enabled()) {
TEST_PASS_MESSAGE("Flash encryption is enabled, skip this test");
}
// Configurable parameters
const uint32_t w = 200;
const uint32_t h = 200;
@@ -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()
@@ -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
@@ -17,7 +17,6 @@
#define GDMA_LL_AHB_BURST_SIZE_ADJUSTABLE 1 // AHB GDMA supports adjustable burst size
#define GDMA_LL_MAX_BURST_SIZE_PSRAM 32 // PSRAM controller doesn't support burst access with size > 32 bytes
#define GDMA_LL_ACCESS_ENCRYPTION_MEM_ALIGNMENT 16 // The alignment of the memory and size when DMA accesses encrypted memory
#ifdef __cplusplus
extern "C" {
@@ -17,7 +17,6 @@
#define GDMA_LL_AHB_BURST_SIZE_ADJUSTABLE 1 // AHB GDMA supports adjustable burst size
#define GDMA_LL_MAX_BURST_SIZE_PSRAM 32 // PSRAM controller doesn't support burst access with size > 32 bytes
#define GDMA_LL_ACCESS_ENCRYPTION_MEM_ALIGNMENT 16 // The alignment of the memory and size when DMA accesses encrypted memory
#ifdef __cplusplus
extern "C" {
@@ -53,7 +53,6 @@ extern "C" {
#define GDMA_LL_AHB_DESC_ALIGNMENT 4
#define GDMA_LL_AHB_RX_BURST_NEEDS_ALIGNMENT 1
#define GDMA_LL_ACCESS_ENCRYPTION_MEM_ALIGNMENT 16 // The alignment of the memory and size when DMA accesses encrypted memory
#define GDMA_LL_AHB_M2M_CAPABLE_PAIR_MASK 0x07 // pair 0,1,2 are M2M capable
@@ -17,7 +17,6 @@
#define GDMA_LL_AHB_BURST_SIZE_ADJUSTABLE 1 // AHB GDMA supports adjustable burst size
#define GDMA_LL_MAX_BURST_SIZE_PSRAM 64 // PSRAM support INCR16
#define GDMA_LL_ACCESS_ENCRYPTION_MEM_ALIGNMENT 16 // The alignment of the memory and size when DMA accesses encrypted memory
#ifdef __cplusplus
extern "C" {
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -245,23 +245,23 @@ static inline void dma2d_ll_rx_enable_page_bound_wrap(dma2d_dev_t *dev, uint32_t
* @brief Set 2D-DMA RX channel maximum burst reading data length in bytes
*/
__attribute__((always_inline))
static inline void dma2d_ll_rx_set_data_burst_length(dma2d_dev_t *dev, uint32_t channel, dma2d_data_burst_length_t length)
static inline void dma2d_ll_rx_set_data_burst_length(dma2d_dev_t *dev, uint32_t channel, uint32_t length)
{
uint32_t sel;
switch (length) {
case DMA2D_DATA_BURST_LENGTH_8:
case 8:
sel = 0;
break;
case DMA2D_DATA_BURST_LENGTH_16:
case 16:
sel = 1;
break;
case DMA2D_DATA_BURST_LENGTH_32:
case 32:
sel = 2;
break;
case DMA2D_DATA_BURST_LENGTH_64:
case 64:
sel = 3;
break;
case DMA2D_DATA_BURST_LENGTH_128:
case 128:
sel = 4;
break;
default:
@@ -761,23 +761,23 @@ static inline void dma2d_ll_tx_enable_page_bound_wrap(dma2d_dev_t *dev, uint32_t
* @brief Set 2D-DMA TX channel maximum burst reading data length in bytes
*/
__attribute__((always_inline))
static inline void dma2d_ll_tx_set_data_burst_length(dma2d_dev_t *dev, uint32_t channel, dma2d_data_burst_length_t length)
static inline void dma2d_ll_tx_set_data_burst_length(dma2d_dev_t *dev, uint32_t channel, uint32_t length)
{
uint32_t sel;
switch (length) {
case DMA2D_DATA_BURST_LENGTH_8:
case 8:
sel = 0;
break;
case DMA2D_DATA_BURST_LENGTH_16:
case 16:
sel = 1;
break;
case DMA2D_DATA_BURST_LENGTH_32:
case 32:
sel = 2;
break;
case DMA2D_DATA_BURST_LENGTH_64:
case 64:
sel = 3;
break;
case DMA2D_DATA_BURST_LENGTH_128:
case 128:
sel = 4;
break;
default:
@@ -58,7 +58,6 @@
#define GDMA_LL_AHB_DESC_ALIGNMENT 4
#define GDMA_LL_AXI_DESC_ALIGNMENT 8
#define GDMA_LL_MAX_BURST_SIZE_PSRAM 128 // PSRAM controller doesn't support burst access with size > 128 bytes
#define GDMA_LL_ACCESS_ENCRYPTION_MEM_ALIGNMENT 16 // The alignment of the memory and size when DMA accesses encrypted memory
#if HAL_CONFIG(CHIP_SUPPORT_MIN_REV) >= 300
#define GDMA_LL_AHB_BURST_SIZE_ADJUSTABLE 1 // AHB GDMA supports adjustable burst size
@@ -71,7 +71,6 @@ extern "C" {
#define GDMA_LL_AHB_BURST_SIZE_ADJUSTABLE 1 // AHB GDMA supports adjustable burst size
#define GDMA_LL_AHB_RX_BURST_NEEDS_ALIGNMENT 1
#define GDMA_LL_MAX_BURST_SIZE_PSRAM 64 // PSRAM controller doesn't support burst access with size > 64 bytes
#define GDMA_LL_ACCESS_ENCRYPTION_MEM_ALIGNMENT 16 // The alignment of the memory and size when DMA accesses encrypted memory
#define GDMA_LL_AHB_M2M_CAPABLE_PAIR_MASK 0x1F // pair 0,1,2,3,4 are M2M capable
@@ -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)
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -8,7 +8,6 @@
#include <stdint.h>
#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
+1 -1
View File
@@ -84,7 +84,7 @@ HEAP_IRAM_ATTR void esp_heap_adjust_alignment_to_hw(size_t *p_alignment, size_t
#if SOC_HAS(GDMA) && (SOC_PSRAM_DMA_CAPABLE || SOC_DMA_CAN_ACCESS_FLASH)
if ((caps & MALLOC_CAP_DMA) && esp_efuse_is_flash_encryption_enabled()) {
alignment = (alignment > GDMA_LL_GET(ACCESS_ENCRYPTION_MEM_ALIGNMENT)) ? alignment : GDMA_LL_GET(ACCESS_ENCRYPTION_MEM_ALIGNMENT);
alignment = (alignment > SOC_MEMSPI_ENCRYPTION_ALIGNMENT) ? alignment : SOC_MEMSPI_ENCRYPTION_ALIGNMENT;
}
#endif
+3
View File
@@ -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));
@@ -178,9 +178,9 @@ TEST_CASE("MIPI DSI use DMA2D (EK79007)", "[mipi_dsi]")
uint8_t *img = NULL;
size_t buffer_alignment = 1;
// If flash encryption is enabled, the buffer address and size must be aligned to SOC_GDMA_EXT_MEM_ENC_ALIGNMENT.
// If flash encryption is enabled, the buffer address and size must be aligned to SOC_MEMSPI_ENCRYPTION_ALIGNMENT.
if (esp_efuse_is_flash_encryption_enabled()) {
buffer_alignment = SOC_GDMA_EXT_MEM_ENC_ALIGNMENT;
buffer_alignment = SOC_MEMSPI_ENCRYPTION_ALIGNMENT;
}
img = heap_caps_aligned_calloc(buffer_alignment, 1, TEST_IMG_SIZE, MALLOC_CAP_DMA | MALLOC_CAP_SPIRAM);
@@ -249,12 +249,12 @@ TEST_CASE("MIPI DSI use DMA2D (EK79007)", "[mipi_dsi]")
size_t start_alignment = 1;
size_t src_x_start = 50;
size_t src_y_start = 50;
// If flash encryption is enabled, the buffer address and size must be aligned to SOC_GDMA_EXT_MEM_ENC_ALIGNMENT.
// If flash encryption is enabled, the buffer address and size must be aligned to SOC_MEMSPI_ENCRYPTION_ALIGNMENT.
if (esp_efuse_is_flash_encryption_enabled()) {
test_block_size = ALIGN_DOWN(test_block_size, SOC_GDMA_EXT_MEM_ENC_ALIGNMENT);
start_alignment = SOC_GDMA_EXT_MEM_ENC_ALIGNMENT;
src_x_start = ALIGN_DOWN(src_x_start, SOC_GDMA_EXT_MEM_ENC_ALIGNMENT);
src_y_start = ALIGN_DOWN(src_y_start, SOC_GDMA_EXT_MEM_ENC_ALIGNMENT);
test_block_size = ALIGN_DOWN(test_block_size, SOC_MEMSPI_ENCRYPTION_ALIGNMENT);
start_alignment = SOC_MEMSPI_ENCRYPTION_ALIGNMENT;
src_x_start = ALIGN_DOWN(src_x_start, SOC_MEMSPI_ENCRYPTION_ALIGNMENT);
src_y_start = ALIGN_DOWN(src_y_start, SOC_MEMSPI_ENCRYPTION_ALIGNMENT);
}
printf("Add Built-in DMA2D draw bitmap hook\r\n");
@@ -531,6 +531,10 @@ config SOC_SPI_MAX_PRE_DIVIDER
int
default 8192
config SOC_MEMSPI_ENCRYPTION_ALIGNMENT
int
default 16
config SOC_LP_TIMER_BIT_WIDTH_LO
int
default 32
@@ -271,6 +271,8 @@
// Peripheral supports DIO, DOUT, QIO, or QOUT
#define SOC_SPI_PERIPH_SUPPORT_MULTILINE_MODE(spi_host) ({(void)spi_host; 1;})
#define SOC_MEMSPI_ENCRYPTION_ALIGNMENT 16 /*!< 16-byte alignment restriction to mem addr and size if encryption is enabled */
/*-------------------------- LP_TIMER CAPS ----------------------------------*/
#define SOC_LP_TIMER_BIT_WIDTH_LO 32 // Bit width of lp_timer low part
#define SOC_LP_TIMER_BIT_WIDTH_HI 16 // Bit width of lp_timer high part
@@ -555,6 +555,10 @@ config SOC_SYSTIMER_ALARM_MISS_COMPENSATE
bool
default y
config SOC_MEMSPI_ENCRYPTION_ALIGNMENT
int
default 16
config SOC_LP_TIMER_BIT_WIDTH_LO
int
default 32
@@ -256,6 +256,8 @@
#define SOC_SYSTIMER_INT_LEVEL 1 // Systimer peripheral uses level interrupt
#define SOC_SYSTIMER_ALARM_MISS_COMPENSATE 1 // Systimer peripheral can generate interrupt immediately if t(target) > t(current)
#define SOC_MEMSPI_ENCRYPTION_ALIGNMENT 16 /*!< 16-byte alignment restriction to mem addr and size if encryption is enabled */
/*-------------------------- LP_TIMER CAPS ----------------------------------*/
#define SOC_LP_TIMER_BIT_WIDTH_LO 32 // Bit width of lp_timer low part
#define SOC_LP_TIMER_BIT_WIDTH_HI 16 // Bit width of lp_timer high part
@@ -743,6 +743,10 @@ config SOC_SYSTIMER_ALARM_MISS_COMPENSATE
bool
default y
config SOC_MEMSPI_ENCRYPTION_ALIGNMENT
int
default 16
config SOC_LP_TIMER_BIT_WIDTH_LO
int
default 32
@@ -333,6 +333,8 @@
#define SOC_SYSTIMER_INT_LEVEL 1 // Systimer peripheral uses level interrupt
#define SOC_SYSTIMER_ALARM_MISS_COMPENSATE 1 // Systimer peripheral can generate interrupt immediately if t(target) > t(current)
#define SOC_MEMSPI_ENCRYPTION_ALIGNMENT 16 /*!< 16-byte alignment restriction to mem addr and size if encryption is enabled */
/*-------------------------- LP_TIMER CAPS ----------------------------------*/
#define SOC_LP_TIMER_BIT_WIDTH_LO 32 // Bit width of lp_timer low part
#define SOC_LP_TIMER_BIT_WIDTH_HI 16 // Bit width of lp_timer high part
@@ -1067,6 +1067,10 @@ config SOC_MEMSPI_TIMING_TUNING_BY_MSPI_DELAY
bool
default y
config SOC_MEMSPI_ENCRYPTION_ALIGNMENT
int
default 16
config SOC_SYSTIMER_COUNTER_NUM
int
default 2
@@ -437,6 +437,8 @@
#define SOC_SPI_MEM_FLASH_SUPPORT_HPM (1) /*!< Support High Performance Mode */
#define SOC_MEMSPI_TIMING_TUNING_BY_MSPI_DELAY (1)
#define SOC_MEMSPI_ENCRYPTION_ALIGNMENT 16 /*!< 16-byte alignment restriction to mem addr and size if encryption is enabled */
/*-------------------------- SYSTIMER CAPS ----------------------------------*/
// TODO: [ESP32C5] IDF-8707
#define SOC_SYSTIMER_COUNTER_NUM 2 // Number of counter units
@@ -911,6 +911,10 @@ config SOC_SPI_MEM_SUPPORT_WRAP
bool
default y
config SOC_MEMSPI_ENCRYPTION_ALIGNMENT
int
default 16
config SOC_SYSTIMER_COUNTER_NUM
int
default 2
@@ -385,6 +385,8 @@
#define SOC_SPI_MEM_SUPPORT_CHECK_SUS (1)
#define SOC_SPI_MEM_SUPPORT_WRAP (1)
#define SOC_MEMSPI_ENCRYPTION_ALIGNMENT 16 /*!< 16-byte alignment restriction to mem addr and size if encryption is enabled */
/*-------------------------- SYSTIMER CAPS ----------------------------------*/
#define SOC_SYSTIMER_COUNTER_NUM 2 // Number of counter units
#define SOC_SYSTIMER_ALARM_NUM 3 // Number of alarm units
@@ -807,6 +807,10 @@ config SOC_MEMSPI_TIMING_TUNING_BY_MSPI_DELAY
bool
default y
config SOC_MEMSPI_ENCRYPTION_ALIGNMENT
int
default 16
config SOC_SYSTIMER_COUNTER_NUM
int
default 2
@@ -341,6 +341,8 @@
#define SOC_SPI_MEM_FLASH_SUPPORT_HPM (1) /*!< Support High Performance Mode */
#define SOC_MEMSPI_TIMING_TUNING_BY_MSPI_DELAY (1)
#define SOC_MEMSPI_ENCRYPTION_ALIGNMENT 16 /*!< 16-byte alignment restriction to mem addr and size if encryption is enabled */
/*-------------------------- SYSTIMER CAPS ----------------------------------*/
#define SOC_SYSTIMER_COUNTER_NUM 2 // Number of counter units
#define SOC_SYSTIMER_ALARM_NUM 3 // Number of alarm units
@@ -915,6 +915,10 @@ config SOC_SPI_MEM_SUPPORT_WRAP
bool
default y
config SOC_MEMSPI_ENCRYPTION_ALIGNMENT
int
default 16
config SOC_SYSTIMER_COUNTER_NUM
int
default 2
@@ -401,6 +401,8 @@
#define SOC_SPI_MEM_SUPPORT_CHECK_SUS (1)
#define SOC_SPI_MEM_SUPPORT_WRAP (1)
#define SOC_MEMSPI_ENCRYPTION_ALIGNMENT 16 /*!< 16-byte alignment restriction to mem addr and size if encryption is enabled */
/*-------------------------- SYSTIMER CAPS ----------------------------------*/
#define SOC_SYSTIMER_COUNTER_NUM 2 // Number of counter units
#define SOC_SYSTIMER_ALARM_NUM 3 // Number of alarm units
@@ -651,6 +651,10 @@ config SOC_SPI_MEM_SUPPORT_WRAP
bool
default y
config SOC_MEMSPI_ENCRYPTION_ALIGNMENT
int
default 16
config SOC_SYSTIMER_COUNTER_NUM
int
default 2
@@ -387,6 +387,8 @@
#define SOC_SPI_MEM_SUPPORT_CHECK_SUS (1)
#define SOC_SPI_MEM_SUPPORT_WRAP (1)
#define SOC_MEMSPI_ENCRYPTION_ALIGNMENT 16 /*!< 16-byte alignment restriction to mem addr and size if encryption is enabled */
/*-------------------------- SYSTIMER CAPS ----------------------------------*/
#define SOC_SYSTIMER_COUNTER_NUM 2 // Number of counter units
#define SOC_SYSTIMER_ALARM_NUM 3 // Number of alarm units
@@ -691,6 +691,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
@@ -385,6 +385,8 @@
#define SOC_SPI_MEM_SUPPORT_CHECK_SUS (1)
#define SOC_SPI_MEM_SUPPORT_WRAP (1)
#define SOC_MEMSPI_ENCRYPTION_ALIGNMENT 16 /*!< 16-byte alignment restriction to mem addr and size if encryption is enabled */
/*-------------------------- SYSTIMER CAPS ----------------------------------*/
#define SOC_SYSTIMER_COUNTER_NUM 2 // Number of counter units
#define SOC_SYSTIMER_ALARM_NUM 3 // Number of alarm units
@@ -1439,6 +1439,10 @@ config SOC_SPI_MEM_FLASH_SUPPORT_HPM
bool
default y
config SOC_MEMSPI_ENCRYPTION_ALIGNMENT
int
default 16
config SOC_SYSTIMER_COUNTER_NUM
int
default 2
@@ -553,6 +553,8 @@
#define SOC_SPI_MEM_FLASH_SUPPORT_HPM (1) /*!< Support High Performance Mode */
#define SOC_MEMSPI_ENCRYPTION_ALIGNMENT 16 /*!< 16-byte alignment restriction to mem addr and size if encryption is enabled */
/*-------------------------- SYSTIMER CAPS ----------------------------------*/
#define SOC_SYSTIMER_COUNTER_NUM 2 // Number of counter units
#define SOC_SYSTIMER_ALARM_NUM 3 // Number of alarm units
@@ -632,6 +634,7 @@
#define SOC_FLASH_ENCRYPTION_XTS_AES_128 1 /* SOC_EFUSE_XTS_AES_KEY_128 (1) || SOC_KEY_MANAGER_FE_KEY_DEPLOY_XTS_AES_128 (1) */
#define SOC_FLASH_ENCRYPTION_XTS_AES_256 1 /* SOC_EFUSE_XTS_AES_KEY_256 (1) || SOC_KEY_MANAGER_FE_KEY_DEPLOY_XTS_AES_256 (1) */
#define SOC_FLASH_ENCRYPTION_XTS_AES_SUPPORT_PSEUDO_ROUND 1 /*!< Only available in chip version above 3.0 */
/*-------------------------- MEMPROT CAPS ------------------------------------*/
/*-------------------------- UART CAPS ---------------------------------------*/
@@ -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;
@@ -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;
@@ -627,6 +627,10 @@ config SOC_MEMSPI_IS_INDEPENDENT
bool
default y
config SOC_MEMSPI_ENCRYPTION_ALIGNMENT
int
default 16
config SOC_SYSTIMER_COUNTER_NUM
int
default 1
@@ -293,6 +293,8 @@
#define SOC_MEMSPI_IS_INDEPENDENT 1
#define SOC_MEMSPI_ENCRYPTION_ALIGNMENT 16 /*!< 16-byte alignment restriction to mem addr and size if encryption is enabled */
/*-------------------------- SYSTIMER CAPS ----------------------------------*/
#define SOC_SYSTIMER_COUNTER_NUM (1U) // Number of counter units
#define SOC_SYSTIMER_ALARM_NUM 3 // Number of alarm units
@@ -1179,6 +1179,10 @@ config SOC_SPI_MEM_FLASH_SUPPORT_HPM
bool
default y
config SOC_MEMSPI_ENCRYPTION_ALIGNMENT
int
default 16
config SOC_COEX_HW_PTI
bool
default y
@@ -484,6 +484,8 @@
#define SOC_SPI_MEM_FLASH_SUPPORT_HPM (1) /*!< Support High Performance Mode */
#define SOC_MEMSPI_ENCRYPTION_ALIGNMENT 16 /*!< 16-byte alignment restriction to mem addr and size if encryption is enabled */
/*-------------------------- COEXISTENCE HARDWARE PTI CAPS -------------------------------*/
#define SOC_COEX_HW_PTI (1)