mirror of
https://github.com/espressif/esp-idf.git
synced 2026-04-27 19:13:21 +00:00
feat(dma2d,ppa): Support flash encryption for DMA2D and PPA
This commit is contained in:
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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:
|
||||
- esp_driver_dma
|
||||
- esp_hal_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
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -687,6 +687,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)
|
||||
|
||||
|
||||
@@ -94,7 +94,7 @@ MIPI DSI Interfaced LCD
|
||||
|
||||
.. note::
|
||||
|
||||
Due to hardware limitation, if external memory encryption is enabled, DMA2D can only access address and length that are aligned to 16 bytes. You need to ensure that your draw buffer's address and length are aligned to 16 bytes. :example:`peripherals/lcd/mipi_dsi` shows how to use LVGL to constrain the redrawn area to ensure alignment.
|
||||
Due to hardware limitation, if external memory encryption is enabled, DMA2D can only access address and length that are aligned to {IDF_TARGET_SOC_MEMSPI_ENCRYPTION_ALIGNMENT} bytes. You need to ensure that your draw buffer's address and length are aligned to {IDF_TARGET_SOC_MEMSPI_ENCRYPTION_ALIGNMENT} bytes. :example:`peripherals/lcd/mipi_dsi` shows how to use LVGL to constrain the redrawn area to ensure alignment.
|
||||
|
||||
If you need more advanced applications, you can add a custom hook for draw bitmap, such as using PPA to implement rotation, scaling, etc.
|
||||
|
||||
|
||||
@@ -44,6 +44,7 @@ The following sections detail the design of the PPA driver:
|
||||
- :ref:`ppa-client-registration` - Covers how to register a PPA client to perform any PPA operations.
|
||||
- :ref:`ppa-register-callback` - Covers how to hook user specific code to PPA driver event callback function.
|
||||
- :ref:`ppa-perform-operation` - Covers how to perform a PPA operation.
|
||||
- :ref:`ppa-buffer-alignment` - Covers the buffer alignment requirements for PPA input and output buffers.
|
||||
- :ref:`ppa-thread-safety` - Covers the usage of the PPA operation APIs in thread safety aspect.
|
||||
- :ref:`ppa-performance-overview` - Covers the performance of PPA operations.
|
||||
|
||||
@@ -129,6 +130,28 @@ Call :cpp:func:`ppa_do_fill` to fill a target block inside a picture.
|
||||
|
||||
:cpp:type:`ppa_trans_mode_t` is a field configurable to all the PPA operation APIs. It decides whether you want the call to the PPA operation API to block until the transaction finishes or to return immediately after the transaction is pushed to the internal queue.
|
||||
|
||||
.. _ppa-buffer-alignment:
|
||||
|
||||
Buffer Alignment
|
||||
^^^^^^^^^^^^^^^^
|
||||
|
||||
The PPA requires certain buffer alignment rules to ensure memory access correctness:
|
||||
|
||||
- Cache line alignment (output buffer only):
|
||||
|
||||
- The ``out.buffer`` address and ``out.buffer_size`` must be aligned to the cache line size (see Kconfig option :ref:`CONFIG_CACHE_L2_CACHE_LINE_SIZE`).
|
||||
|
||||
- Flash encryption alignment (when flash encryption is enabled and the buffers are located in external memory):
|
||||
|
||||
- The byte width of the block must be aligned to {IDF_TARGET_SOC_MEMSPI_ENCRYPTION_ALIGNMENT} bytes.
|
||||
- The starting address of each row of the block must be aligned to {IDF_TARGET_SOC_MEMSPI_ENCRYPTION_ALIGNMENT} bytes.
|
||||
|
||||
Additionally, when accessing encrypted external memory, the PPA's DMA data burst length must be greater than or equal to {IDF_TARGET_SOC_MEMSPI_ENCRYPTION_ALIGNMENT} bytes. If a smaller burst length is configured, the driver will automatically increase it to meet this requirement.
|
||||
|
||||
.. warning::
|
||||
|
||||
SRM engine processes the picture by macro blocks, where the alignment of the macro blocks is uncontrollable, thus if the buffer is in external memory, SRM operation is unable to work with flash encrypted.
|
||||
|
||||
.. _ppa-thread-safety:
|
||||
|
||||
Thread Safety
|
||||
|
||||
@@ -94,7 +94,7 @@ MIPI DSI 接口的 LCD
|
||||
|
||||
.. note::
|
||||
|
||||
由于硬件限制,如果启用了外部存储加密,则 DMA2D 只能访问地址和长度都对齐到 16 字节的地址空间。你需要确保你的绘制 buffer 的地址和长度都对齐到 16 字节。 :example:`peripherals/lcd/mipi_dsi` 演示了如何使用 LVGL 控制重新绘制区域来确保对齐。
|
||||
由于硬件限制,如果启用了外部存储加密,则 DMA2D 只能访问地址和长度都对齐到 {IDF_TARGET_SOC_MEMSPI_ENCRYPTION_ALIGNMENT} 字节的地址空间。你需要确保你的绘制 buffer 的地址和长度都对齐到 {IDF_TARGET_SOC_MEMSPI_ENCRYPTION_ALIGNMENT} 字节。 :example:`peripherals/lcd/mipi_dsi` 演示了如何使用 LVGL 控制重新绘制区域来确保对齐。
|
||||
|
||||
若需更高级的应用,用户可为绘制位图添加自定义钩子,例如通过 PPA 实现旋转、缩放等操作。
|
||||
|
||||
|
||||
@@ -44,6 +44,7 @@
|
||||
- :ref:`ppa-client-registration` - 涵盖如何注册 PPA 客户端来执行一切 PPA 操作。
|
||||
- :ref:`ppa-register-callback` - 涵盖如何将用户特定代码挂接到 PPA 驱动程序事件回调函数。
|
||||
- :ref:`ppa-perform-operation` - 涵盖如何执行 PPA 操作。
|
||||
- :ref:`ppa-buffer-alignment` - 涵盖 PPA 输入和输出缓冲区的内存对齐要求。
|
||||
- :ref:`ppa-thread-safety`- 涵盖在线程安全方面使用 PPA 操作 API 的情况。
|
||||
- :ref:`ppa-performance-overview` - 涵盖 PPA 操作的性能。
|
||||
|
||||
@@ -129,6 +130,28 @@ PPA 操作包括:
|
||||
|
||||
:cpp:type:`ppa_trans_mode_t` 为可配置字段,适用于所有 PPA 操作 API。可以配置该字段,在调用 PPA 操作 API 时等待操作完成后再返回,或者在事务推送到内部队列后立即返回。
|
||||
|
||||
.. _ppa-buffer-alignment:
|
||||
|
||||
缓存区对齐要求
|
||||
^^^^^^^^^^^^^^
|
||||
|
||||
PPA 缓存区需要满足以下对齐要求,以确保存储器访问的正确性:
|
||||
|
||||
- 缓冲行对齐(仅针对输出缓存区):
|
||||
|
||||
- ``out.buffer`` 地址和 ``out.buffer_size`` 大小必须与缓冲行大小对齐(请参阅 Kconfig 选项 :ref:`CONFIG_CACHE_L2_CACHE_LINE_SIZE`)。
|
||||
|
||||
- 存储加密对齐(当存储加密启用且缓冲区位于外部存储空间时):
|
||||
|
||||
- 块的字节宽度必须与 {IDF_TARGET_SOC_MEMSPI_ENCRYPTION_ALIGNMENT} 字节对齐。
|
||||
- 块每行的起始地址必须与 {IDF_TARGET_SOC_MEMSPI_ENCRYPTION_ALIGNMENT} 字节对齐。
|
||||
|
||||
此外,当访问加密外部存储空间时,PPA 的 DMA 数据突发长度必须大于或等于 {IDF_TARGET_SOC_MEMSPI_ENCRYPTION_ALIGNMENT} 字节。如果配置的突发长度小于该值,驱动程序将自动增加到满足该要求。
|
||||
|
||||
.. warning::
|
||||
|
||||
SRM 引擎以宏块为单位处理图片,而宏块的对齐无法受到控制,因此如果缓冲区位于外部存储空间,则 SRM 操作在存储加密的情况下无法正常工作。
|
||||
|
||||
.. _ppa-thread-safety:
|
||||
|
||||
线程安全
|
||||
|
||||
Reference in New Issue
Block a user