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

This commit is contained in:
Song Ruo Jing
2026-02-26 16:39:40 +08:00
parent 29d62fa6ae
commit 9362907287
71 changed files with 499 additions and 165 deletions
@@ -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++) {
@@ -15,6 +15,18 @@ from pytest_embedded_idf.utils import soc_filtered_targets
indirect=True,
)
@idf_parametrize('target', soc_filtered_targets('SOC_DMA2D_SUPPORTED == 1'), indirect=['target'])
@pytest.mark.temp_skip_ci(targets=['esp32p4'], reason='p4 rev3 migration')
def test_dma2d(dut: Dut) -> None:
dut.run_all_single_board_cases()
@pytest.mark.flash_encryption
@pytest.mark.parametrize(
'config',
[
'flash_enc',
],
indirect=True,
)
@idf_parametrize('target', soc_filtered_targets('SOC_DMA2D_SUPPORTED == 1'), indirect=['target'])
def test_dma2d_flash_encryption(dut: Dut) -> None:
dut.run_all_single_board_cases()
@@ -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