mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-02 03:00:34 +03:00
feat(ppa): add sleep retention support for DMA2D and PPA
This commit is contained in:
@@ -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
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@@ -39,6 +39,11 @@ typedef struct {
|
|||||||
ppa_data_burst_length_t data_burst_length; /*!< The desired data burst length for all the transactions of the client.
|
ppa_data_burst_length_t data_burst_length; /*!< The desired data burst length for all the transactions of the client.
|
||||||
Use a small burst length will decrease PPA performance, but can save burst bandwidth for other peripheral usages.
|
Use a small burst length will decrease PPA performance, but can save burst bandwidth for other peripheral usages.
|
||||||
By default, it will be at the maximum burst length, `PPA_DATA_BURST_LENGTH_128` */
|
By default, it will be at the maximum burst length, `PPA_DATA_BURST_LENGTH_128` */
|
||||||
|
struct {
|
||||||
|
uint32_t allow_pd: 1; /*!< If set, driver allows the power domain to be powered off when system enters sleep mode.
|
||||||
|
This can save power, but at the expense of more RAM being consumed to save register context.
|
||||||
|
All clients must have the same value for this flag. */
|
||||||
|
} flags; /*!< Configuration flags */
|
||||||
} ppa_client_config_t;
|
} ppa_client_config_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -31,10 +31,12 @@
|
|||||||
#include "hal/ppa_hal.h"
|
#include "hal/ppa_hal.h"
|
||||||
#include "hal/ppa_ll.h"
|
#include "hal/ppa_ll.h"
|
||||||
#include "hal/ppa_types.h"
|
#include "hal/ppa_types.h"
|
||||||
|
#include "soc/ppa_periph.h"
|
||||||
#include "hal/color_hal.h"
|
#include "hal/color_hal.h"
|
||||||
#include "hal/color_types.h"
|
#include "hal/color_types.h"
|
||||||
#include "esp_private/periph_ctrl.h"
|
#include "esp_private/periph_ctrl.h"
|
||||||
#include "hal/efuse_hal.h"
|
#include "hal/efuse_hal.h"
|
||||||
|
#include "esp_private/sleep_retention.h"
|
||||||
#include "soc/soc_caps.h"
|
#include "soc/soc_caps.h"
|
||||||
|
|
||||||
static const char *TAG = "ppa_core";
|
static const char *TAG = "ppa_core";
|
||||||
@@ -55,6 +57,25 @@ const dma2d_trans_on_picked_callback_t ppa_oper_trans_on_picked_func[PPA_OPERATI
|
|||||||
[PPA_OPERATION_FILL] = ppa_fill_transaction_on_picked,
|
[PPA_OPERATION_FILL] = ppa_fill_transaction_on_picked,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** PPA Power Management Strategy
|
||||||
|
*
|
||||||
|
* SRM and Blending have separate CPU_FREQ_MAX PM locks, and each PM lock is acquired whenever there is PPA operation in process.
|
||||||
|
*
|
||||||
|
* When no PPA operation is in process, sleep can happen, and PPA domain can be powered down if allow_pd is set.
|
||||||
|
* Necessary register context will be saved and restored by sleep retention.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP
|
||||||
|
static esp_err_t ppa_create_sleep_retention_link_cb(void *arg)
|
||||||
|
{
|
||||||
|
sleep_retention_module_t module = ppa_reg_retention_info.module;
|
||||||
|
esp_err_t err = sleep_retention_entries_create(ppa_reg_retention_info.regdma_entry_array,
|
||||||
|
ppa_reg_retention_info.array_size,
|
||||||
|
REGDMA_LINK_PRI_PPA, module);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static esp_err_t ppa_engine_acquire(const ppa_engine_config_t *config, ppa_engine_t **ret_engine)
|
static esp_err_t ppa_engine_acquire(const ppa_engine_config_t *config, ppa_engine_t **ret_engine)
|
||||||
{
|
{
|
||||||
esp_err_t ret = ESP_OK;
|
esp_err_t ret = ESP_OK;
|
||||||
@@ -187,6 +208,35 @@ static esp_err_t ppa_engine_acquire(const ppa_engine_config_t *config, ppa_engin
|
|||||||
ESP_LOGE(TAG, "install 2D-DMA failed");
|
ESP_LOGE(TAG, "install 2D-DMA failed");
|
||||||
goto wrap_up;
|
goto wrap_up;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP
|
||||||
|
s_platform.flags.allow_pd = config->flags.allow_pd; // Uses the first acquired engine's allow_pd flag as the platform's allow_pd flag
|
||||||
|
|
||||||
|
// Initialize sleep retention module for PPA
|
||||||
|
sleep_retention_module_t module = ppa_reg_retention_info.module;
|
||||||
|
sleep_retention_module_init_param_t init_param = {
|
||||||
|
.cbs = {
|
||||||
|
.create = {
|
||||||
|
.handle = ppa_create_sleep_retention_link_cb,
|
||||||
|
.arg = NULL,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
.depends = RETENTION_MODULE_BITMAP_INIT(CLOCK_SYSTEM)
|
||||||
|
};
|
||||||
|
if (sleep_retention_module_init(module, &init_param) != ESP_OK) {
|
||||||
|
// even though the sleep retention module init failed, PPA driver should still work, so just warning here
|
||||||
|
ESP_LOGW(TAG, "init sleep retention failed, power domain may be turned off during sleep");
|
||||||
|
} else if (s_platform.flags.allow_pd) {
|
||||||
|
if (sleep_retention_module_allocate(module) != ESP_OK) {
|
||||||
|
ESP_LOGW(TAG, "fail to allocate retention link list");
|
||||||
|
// don't call sleep_retention_module_deinit here, otherwise PPA peripheral may be powered off during sleep
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (s_platform.flags.allow_pd != config->flags.allow_pd) {
|
||||||
|
ESP_LOGW(TAG, "allow_pd flag mismatch among clients, will follow flags.allow_pd = %d", s_platform.flags.allow_pd);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
wrap_up:
|
wrap_up:
|
||||||
@@ -247,6 +297,17 @@ static esp_err_t ppa_engine_release(ppa_engine_t *ppa_engine)
|
|||||||
if (!s_platform.srm && !s_platform.blending) {
|
if (!s_platform.srm && !s_platform.blending) {
|
||||||
assert(s_platform.srm_engine_ref_count == 0 && s_platform.blend_engine_ref_count == 0);
|
assert(s_platform.srm_engine_ref_count == 0 && s_platform.blend_engine_ref_count == 0);
|
||||||
|
|
||||||
|
#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP
|
||||||
|
sleep_retention_module_t module = ppa_reg_retention_info.module;
|
||||||
|
if (sleep_retention_is_module_created(module)) {
|
||||||
|
sleep_retention_module_free(module);
|
||||||
|
}
|
||||||
|
if (sleep_retention_is_module_inited(module)) {
|
||||||
|
sleep_retention_module_deinit(module);
|
||||||
|
}
|
||||||
|
s_platform.flags.allow_pd = false;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (s_platform.dma2d_pool_handle) {
|
if (s_platform.dma2d_pool_handle) {
|
||||||
dma2d_release_pool(s_platform.dma2d_pool_handle); // TODO: check return value. If not ESP_OK, then must be error on other 2D-DMA clients :( Give a warning log?
|
dma2d_release_pool(s_platform.dma2d_pool_handle); // TODO: check return value. If not ESP_OK, then must be error on other 2D-DMA clients :( Give a warning log?
|
||||||
s_platform.dma2d_pool_handle = NULL;
|
s_platform.dma2d_pool_handle = NULL;
|
||||||
@@ -288,11 +349,13 @@ esp_err_t ppa_register_client(const ppa_client_config_t *config, ppa_client_hand
|
|||||||
if (config->oper_type == PPA_OPERATION_SRM) {
|
if (config->oper_type == PPA_OPERATION_SRM) {
|
||||||
ppa_engine_config_t engine_config = {
|
ppa_engine_config_t engine_config = {
|
||||||
.engine = PPA_ENGINE_TYPE_SRM,
|
.engine = PPA_ENGINE_TYPE_SRM,
|
||||||
|
.flags.allow_pd = config->flags.allow_pd,
|
||||||
};
|
};
|
||||||
ESP_GOTO_ON_ERROR(ppa_engine_acquire(&engine_config, &client->engine), err, TAG, "unable to acquire SRM engine");
|
ESP_GOTO_ON_ERROR(ppa_engine_acquire(&engine_config, &client->engine), err, TAG, "unable to acquire SRM engine");
|
||||||
} else if (config->oper_type == PPA_OPERATION_BLEND || config->oper_type == PPA_OPERATION_FILL) {
|
} else if (config->oper_type == PPA_OPERATION_BLEND || config->oper_type == PPA_OPERATION_FILL) {
|
||||||
ppa_engine_config_t engine_config = {
|
ppa_engine_config_t engine_config = {
|
||||||
.engine = PPA_ENGINE_TYPE_BLEND,
|
.engine = PPA_ENGINE_TYPE_BLEND,
|
||||||
|
.flags.allow_pd = config->flags.allow_pd,
|
||||||
};
|
};
|
||||||
ESP_GOTO_ON_ERROR(ppa_engine_acquire(&engine_config, &client->engine), err, TAG, "unable to acquire Blending engine");
|
ESP_GOTO_ON_ERROR(ppa_engine_acquire(&engine_config, &client->engine), err, TAG, "unable to acquire Blending engine");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@@ -75,6 +75,9 @@ typedef struct ppa_blend_engine_t {
|
|||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
ppa_engine_type_t engine; // Engine type
|
ppa_engine_type_t engine; // Engine type
|
||||||
|
struct {
|
||||||
|
uint32_t allow_pd: 1; // If set, engine allows the power domain to be powered off when system enters sleep mode
|
||||||
|
} flags; // Configuration flags
|
||||||
} ppa_engine_config_t;
|
} ppa_engine_config_t;
|
||||||
|
|
||||||
/******************************** CLIENT *************************************/
|
/******************************** CLIENT *************************************/
|
||||||
@@ -240,6 +243,9 @@ struct ppa_platform_t {
|
|||||||
uint32_t blend_engine_ref_count; // Reference count used to protect PPA blending engine acquire and release
|
uint32_t blend_engine_ref_count; // Reference count used to protect PPA blending engine acquire and release
|
||||||
size_t buf_alignment_size; // Alignment requirement for the outgoing buffer addr and size to satisfy cache line size
|
size_t buf_alignment_size; // Alignment requirement for the outgoing buffer addr and size to satisfy cache line size
|
||||||
uint32_t dma_desc_mem_size; // Alignment requirement for the 2D-DMA descriptor to satisfy cache line size
|
uint32_t dma_desc_mem_size; // Alignment requirement for the 2D-DMA descriptor to satisfy cache line size
|
||||||
|
struct {
|
||||||
|
uint32_t allow_pd: 1; // If set, driver allows the power domain to be powered off when system enters sleep mode
|
||||||
|
} flags; // Configuration flags
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|||||||
@@ -5,5 +5,5 @@ set(srcs "test_app_main.c"
|
|||||||
# the component can be registered as WHOLE_ARCHIVE
|
# the component can be registered as WHOLE_ARCHIVE
|
||||||
idf_component_register(SRCS ${srcs}
|
idf_component_register(SRCS ${srcs}
|
||||||
INCLUDE_DIRS "."
|
INCLUDE_DIRS "."
|
||||||
PRIV_REQUIRES esp_driver_ppa esp_psram unity esp_mm efuse
|
PRIV_REQUIRES esp_driver_ppa esp_psram unity esp_mm efuse esp_pm
|
||||||
WHOLE_ARCHIVE)
|
WHOLE_ARCHIVE)
|
||||||
|
|||||||
@@ -20,6 +20,12 @@
|
|||||||
#include "ppa_performance.h"
|
#include "ppa_performance.h"
|
||||||
#include "esp_random.h"
|
#include "esp_random.h"
|
||||||
#include "hal/efuse_hal.h"
|
#include "hal/efuse_hal.h"
|
||||||
|
#include "sdkconfig.h"
|
||||||
|
#include "soc/soc_caps.h"
|
||||||
|
#include "esp_pm.h"
|
||||||
|
#include "esp_clk_tree.h"
|
||||||
|
#include "esp_private/esp_sleep_internal.h"
|
||||||
|
#include "esp_private/esp_pmu.h"
|
||||||
|
|
||||||
#define ALIGN_UP(num, align) (((num) + ((align) - 1)) & ~((align) - 1))
|
#define ALIGN_UP(num, align) (((num) + ((align) - 1)) & ~((align) - 1))
|
||||||
|
|
||||||
@@ -272,7 +278,20 @@ TEST_CASE("ppa_pending_transactions_in_queue", "[PPA]")
|
|||||||
free(buf_2);
|
free(buf_2);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("ppa_srm_basic_data_correctness_check", "[PPA]")
|
static __attribute__((unused)) void enable_pm_strategy(bool auto_light_sleep)
|
||||||
|
{
|
||||||
|
uint32_t xtal_hz = 0;
|
||||||
|
esp_clk_tree_src_get_freq_hz(SOC_MOD_CLK_XTAL, ESP_CLK_TREE_SRC_FREQ_PRECISION_EXACT, &xtal_hz);
|
||||||
|
esp_pm_config_t pm_config = {};
|
||||||
|
pm_config.max_freq_mhz = CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ;
|
||||||
|
pm_config.min_freq_mhz = xtal_hz / 1000000;
|
||||||
|
#if CONFIG_FREERTOS_USE_TICKLESS_IDLE
|
||||||
|
pm_config.light_sleep_enable = auto_light_sleep;
|
||||||
|
#endif
|
||||||
|
TEST_ESP_OK(esp_pm_configure(&pm_config));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ppa_srm_basic_data_correctness_check(bool auto_light_sleep)
|
||||||
{
|
{
|
||||||
const uint32_t w = 4;
|
const uint32_t w = 4;
|
||||||
const uint32_t h = 4;
|
const uint32_t h = 4;
|
||||||
@@ -313,92 +332,144 @@ TEST_CASE("ppa_srm_basic_data_correctness_check", "[PPA]")
|
|||||||
0x0000, 0x0000, 0x0000, 0x0000
|
0x0000, 0x0000, 0x0000, 0x0000
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#if CONFIG_PM_ENABLE
|
||||||
|
enable_pm_strategy(auto_light_sleep);
|
||||||
|
#endif
|
||||||
|
|
||||||
ppa_client_handle_t ppa_client_handle;
|
ppa_client_handle_t ppa_client_handle;
|
||||||
ppa_client_config_t ppa_client_config = {
|
ppa_client_config_t ppa_client_config = {
|
||||||
.oper_type = PPA_OPERATION_SRM,
|
.oper_type = PPA_OPERATION_SRM,
|
||||||
.max_pending_trans_num = 1,
|
.max_pending_trans_num = 1,
|
||||||
|
#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP
|
||||||
|
.flags.allow_pd = (auto_light_sleep ? true : false),
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
TEST_ESP_OK(ppa_register_client(&ppa_client_config, &ppa_client_handle));
|
TEST_ESP_OK(ppa_register_client(&ppa_client_config, &ppa_client_handle));
|
||||||
|
|
||||||
ppa_srm_oper_config_t oper_config = {
|
#if SOC_LIGHT_SLEEP_SUPPORTED
|
||||||
.in.buffer = in_buf,
|
esp_sleep_context_t sleep_ctx;
|
||||||
.in.pic_w = w,
|
esp_sleep_set_sleep_context(&sleep_ctx);
|
||||||
.in.pic_h = h,
|
#endif
|
||||||
.in.block_w = block_w,
|
|
||||||
.in.block_h = block_h,
|
|
||||||
.in.block_offset_x = in_block_offset_x,
|
|
||||||
.in.block_offset_y = in_block_offset_y,
|
|
||||||
.in.srm_cm = cm,
|
|
||||||
|
|
||||||
.out.buffer = out_buf,
|
// loop 3 times if we are testing PPA sleep retention feature
|
||||||
.out.buffer_size = out_buf_size,
|
int cnt = (auto_light_sleep ? 3 : 1);
|
||||||
.out.pic_w = w,
|
for (int i = 0; i < cnt; i++) {
|
||||||
.out.pic_h = h,
|
#if SOC_LIGHT_SLEEP_SUPPORTED
|
||||||
.out.block_offset_x = out_block_offset_x,
|
sleep_ctx.sleep_request_result = ESP_FAIL; // set back to fail for new iteration
|
||||||
.out.block_offset_y = out_block_offset_y,
|
sleep_ctx.sleep_flags = 0; // clear sleep flags for new iteration
|
||||||
.out.srm_cm = cm,
|
|
||||||
|
|
||||||
.rotation_angle = rotation,
|
if (auto_light_sleep) {
|
||||||
.scale_x = scale_x,
|
vTaskDelay(pdMS_TO_TICKS(1000)); // enter auto light sleep here if we are testing PPA sleep retention feature
|
||||||
.scale_y = scale_y,
|
|
||||||
|
|
||||||
.rgb_swap = 0,
|
// Check if the sleep happened as expected
|
||||||
.byte_swap = 0,
|
#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP
|
||||||
|
TEST_ASSERT_EQUAL(PMU_SLEEP_PD_TOP, sleep_ctx.sleep_flags & PMU_SLEEP_PD_TOP);
|
||||||
.mode = PPA_TRANS_MODE_BLOCKING,
|
#endif
|
||||||
};
|
TEST_ASSERT_EQUAL(ESP_OK, sleep_ctx.sleep_request_result);
|
||||||
|
|
||||||
TEST_ESP_OK(ppa_do_scale_rotate_mirror(ppa_client_handle, &oper_config));
|
|
||||||
|
|
||||||
// Check result
|
|
||||||
for (int i = 0; i < buf_len; i++) {
|
|
||||||
if (i % 8 == 0) {
|
|
||||||
printf("\n");
|
|
||||||
}
|
}
|
||||||
printf("0x%02X ", out_buf[i]);
|
#endif
|
||||||
}
|
|
||||||
printf("\n");
|
ppa_srm_oper_config_t oper_config = {
|
||||||
TEST_ASSERT_EQUAL_UINT8_ARRAY((void *)out_buf_expected, (void *)out_buf, buf_len);
|
.in.buffer = in_buf,
|
||||||
|
.in.pic_w = w,
|
||||||
|
.in.pic_h = h,
|
||||||
|
.in.block_w = block_w,
|
||||||
|
.in.block_h = block_h,
|
||||||
|
.in.block_offset_x = in_block_offset_x,
|
||||||
|
.in.block_offset_y = in_block_offset_y,
|
||||||
|
.in.srm_cm = cm,
|
||||||
|
|
||||||
|
.out.buffer = out_buf,
|
||||||
|
.out.buffer_size = out_buf_size,
|
||||||
|
.out.pic_w = w,
|
||||||
|
.out.pic_h = h,
|
||||||
|
.out.block_offset_x = out_block_offset_x,
|
||||||
|
.out.block_offset_y = out_block_offset_y,
|
||||||
|
.out.srm_cm = cm,
|
||||||
|
|
||||||
|
.rotation_angle = rotation,
|
||||||
|
.scale_x = scale_x,
|
||||||
|
.scale_y = scale_y,
|
||||||
|
|
||||||
|
.rgb_swap = 0,
|
||||||
|
.byte_swap = 0,
|
||||||
|
|
||||||
|
.mode = PPA_TRANS_MODE_BLOCKING,
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_ESP_OK(ppa_do_scale_rotate_mirror(ppa_client_handle, &oper_config));
|
||||||
|
|
||||||
|
// Check result
|
||||||
|
for (int i = 0; i < buf_len; i++) {
|
||||||
|
if (i % 8 == 0) {
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
printf("0x%02X ", out_buf[i]);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
TEST_ASSERT_EQUAL_UINT8_ARRAY((void *)out_buf_expected, (void *)out_buf, buf_len);
|
||||||
|
|
||||||
#if !(CONFIG_IDF_TARGET_ESP32P4 && CONFIG_ESP32P4_SELECTS_REV_LESS_V3)
|
#if !(CONFIG_IDF_TARGET_ESP32P4 && CONFIG_ESP32P4_SELECTS_REV_LESS_V3)
|
||||||
// Test a rgb2gray color conversion
|
// Test a rgb2gray color conversion
|
||||||
memset(out_buf, 0, out_buf_size);
|
memset(out_buf, 0, out_buf_size);
|
||||||
esp_cache_msync((void *)out_buf, out_buf_size, ESP_CACHE_MSYNC_FLAG_DIR_C2M);
|
esp_cache_msync((void *)out_buf, out_buf_size, ESP_CACHE_MSYNC_FLAG_DIR_C2M);
|
||||||
|
|
||||||
const uint8_t r_weight = 100;
|
const uint8_t r_weight = 100;
|
||||||
const uint8_t g_weight = 56;
|
const uint8_t g_weight = 56;
|
||||||
const uint8_t b_weight = 100;
|
const uint8_t b_weight = 100;
|
||||||
TEST_ESP_OK(ppa_set_rgb2gray_formula(r_weight, g_weight, b_weight));
|
TEST_ESP_OK(ppa_set_rgb2gray_formula(r_weight, g_weight, b_weight));
|
||||||
oper_config.out.srm_cm = PPA_SRM_COLOR_MODE_GRAY8;
|
oper_config.out.srm_cm = PPA_SRM_COLOR_MODE_GRAY8;
|
||||||
oper_config.rotation_angle = PPA_SRM_ROTATION_ANGLE_0;
|
oper_config.rotation_angle = PPA_SRM_ROTATION_ANGLE_0;
|
||||||
uint8_t out_buf_expected_gray[16] = {};
|
uint8_t out_buf_expected_gray[16] = {};
|
||||||
for (int i = 0; i < block_w * block_h; i++) {
|
for (int i = 0; i < block_w * block_h; i++) {
|
||||||
const uint16_t pix = in_buf[(i / block_w + in_block_offset_y) * w + (i % block_w + in_block_offset_x)];
|
const uint16_t pix = in_buf[(i / block_w + in_block_offset_y) * w + (i % block_w + in_block_offset_x)];
|
||||||
uint8_t _r = ((pix >> 8) & 0xF8);
|
uint8_t _r = ((pix >> 8) & 0xF8);
|
||||||
uint8_t _g = ((pix >> 3) & 0xFC);
|
uint8_t _g = ((pix >> 3) & 0xFC);
|
||||||
uint8_t _b = ((pix << 3) & 0xF8);
|
uint8_t _b = ((pix << 3) & 0xF8);
|
||||||
out_buf_expected_gray[(i / block_w + out_block_offset_y) * w + (i % block_w + out_block_offset_x)] = (_r * r_weight + _g * g_weight + _b * b_weight) >> 8;
|
out_buf_expected_gray[(i / block_w + out_block_offset_y) * w + (i % block_w + out_block_offset_x)] = (_r * r_weight + _g * g_weight + _b * b_weight) >> 8;
|
||||||
}
|
|
||||||
|
|
||||||
TEST_ESP_OK(ppa_do_scale_rotate_mirror(ppa_client_handle, &oper_config));
|
|
||||||
|
|
||||||
// Check result
|
|
||||||
for (int i = 0; i < w * h; i++) {
|
|
||||||
if (i % 4 == 0) {
|
|
||||||
printf("\n");
|
|
||||||
}
|
}
|
||||||
printf("0x%02X ", out_buf[i]);
|
|
||||||
}
|
TEST_ESP_OK(ppa_do_scale_rotate_mirror(ppa_client_handle, &oper_config));
|
||||||
printf("\n");
|
|
||||||
TEST_ASSERT_EQUAL_UINT8_ARRAY((void *)out_buf_expected_gray, (void *)out_buf, w * h);
|
// Check result
|
||||||
|
for (int i = 0; i < w * h; i++) {
|
||||||
|
if (i % 4 == 0) {
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
printf("0x%02X ", out_buf[i]);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
TEST_ASSERT_EQUAL_UINT8_ARRAY((void *)out_buf_expected_gray, (void *)out_buf, w * h);
|
||||||
#endif // !(CONFIG_IDF_TARGET_ESP32P4 && CONFIG_ESP32P4_SELECTS_REV_LESS_V3)
|
#endif // !(CONFIG_IDF_TARGET_ESP32P4 && CONFIG_ESP32P4_SELECTS_REV_LESS_V3)
|
||||||
|
|
||||||
|
memset(out_buf, 0, out_buf_size);
|
||||||
|
esp_cache_msync((void *)out_buf, out_buf_size, ESP_CACHE_MSYNC_FLAG_DIR_C2M);
|
||||||
|
}
|
||||||
|
#if SOC_LIGHT_SLEEP_SUPPORTED
|
||||||
|
esp_sleep_set_sleep_context(NULL);
|
||||||
|
#endif
|
||||||
|
|
||||||
TEST_ESP_OK(ppa_unregister_client(ppa_client_handle));
|
TEST_ESP_OK(ppa_unregister_client(ppa_client_handle));
|
||||||
|
|
||||||
|
#if CONFIG_PM_ENABLE
|
||||||
|
enable_pm_strategy(false);
|
||||||
|
#endif
|
||||||
|
|
||||||
free(out_buf);
|
free(out_buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("ppa_blend_basic_data_correctness_check", "[PPA]")
|
TEST_CASE("ppa_srm_basic_data_correctness_check", "[PPA]")
|
||||||
|
{
|
||||||
|
ppa_srm_basic_data_correctness_check(false);
|
||||||
|
#if CONFIG_PM_ENABLE
|
||||||
|
#if !(CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP && !SOC_PM_FPU_RETENTION_BY_SW) // SRM uses FPU
|
||||||
|
printf("\nTest again with auto light sleep...\n");
|
||||||
|
ppa_srm_basic_data_correctness_check(true);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ppa_blend_basic_data_correctness_check(bool auto_light_sleep)
|
||||||
{
|
{
|
||||||
const uint32_t w = 2;
|
const uint32_t w = 2;
|
||||||
const uint32_t h = 2;
|
const uint32_t h = 2;
|
||||||
@@ -431,7 +502,7 @@ TEST_CASE("ppa_blend_basic_data_correctness_check", "[PPA]")
|
|||||||
0xFF, 0xFF, 0xFF, /**/ 0x80, 0x40, 0xA0, /**/
|
0xFF, 0xFF, 0xFF, /**/ 0x80, 0x40, 0xA0, /**/
|
||||||
// /*************************/
|
// /*************************/
|
||||||
};
|
};
|
||||||
uint8_t in_fg_buf[64] __attribute__((aligned(64))) = {
|
const uint8_t in_fg_buf_template[64] __attribute__((aligned(64))) = {
|
||||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
// /*******************************/
|
// /*******************************/
|
||||||
0xFF, 0xFF, 0xFF, 0xFF, /**/ 0x00, 0x80, 0x80, 0xC0, /**/
|
0xFF, 0xFF, 0xFF, 0xFF, /**/ 0x00, 0x80, 0x80, 0xC0, /**/
|
||||||
@@ -439,6 +510,10 @@ TEST_CASE("ppa_blend_basic_data_correctness_check", "[PPA]")
|
|||||||
// /*******************************/
|
// /*******************************/
|
||||||
[16 ... 63] = 0,
|
[16 ... 63] = 0,
|
||||||
};
|
};
|
||||||
|
uint8_t *in_fg_buf = heap_caps_aligned_calloc(4, 64, sizeof(uint8_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT | MALLOC_CAP_DMA);
|
||||||
|
TEST_ASSERT_NOT_NULL(in_fg_buf);
|
||||||
|
memcpy(in_fg_buf, in_fg_buf_template, 64);
|
||||||
|
esp_cache_msync((void *)in_fg_buf, 64, ESP_CACHE_MSYNC_FLAG_DIR_C2M);
|
||||||
uint8_t *out_buf = in_fg_buf;
|
uint8_t *out_buf = in_fg_buf;
|
||||||
// Expected blend output
|
// Expected blend output
|
||||||
// Alpha Blending calculation:
|
// Alpha Blending calculation:
|
||||||
@@ -454,62 +529,99 @@ TEST_CASE("ppa_blend_basic_data_correctness_check", "[PPA]")
|
|||||||
// /*******************************/
|
// /*******************************/
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#if CONFIG_PM_ENABLE
|
||||||
|
enable_pm_strategy(auto_light_sleep);
|
||||||
|
#endif
|
||||||
|
|
||||||
ppa_client_handle_t ppa_client_handle;
|
ppa_client_handle_t ppa_client_handle;
|
||||||
ppa_client_config_t ppa_client_config = {
|
ppa_client_config_t ppa_client_config = {
|
||||||
.oper_type = PPA_OPERATION_BLEND,
|
.oper_type = PPA_OPERATION_BLEND,
|
||||||
.max_pending_trans_num = 1,
|
.max_pending_trans_num = 1,
|
||||||
|
#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP
|
||||||
|
.flags.allow_pd = (auto_light_sleep ? true : false),
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
TEST_ESP_OK(ppa_register_client(&ppa_client_config, &ppa_client_handle));
|
TEST_ESP_OK(ppa_register_client(&ppa_client_config, &ppa_client_handle));
|
||||||
|
|
||||||
ppa_blend_oper_config_t oper_config = {
|
#if SOC_LIGHT_SLEEP_SUPPORTED
|
||||||
.in_bg.buffer = in_bg_buf,
|
esp_sleep_context_t sleep_ctx;
|
||||||
.in_bg.pic_w = w,
|
esp_sleep_set_sleep_context(&sleep_ctx);
|
||||||
.in_bg.pic_h = h,
|
#endif
|
||||||
.in_bg.block_w = block_w,
|
|
||||||
.in_bg.block_h = block_h,
|
|
||||||
.in_bg.block_offset_x = block_offset_x,
|
|
||||||
.in_bg.block_offset_y = block_offset_y,
|
|
||||||
.in_bg.blend_cm = in_bg_cm,
|
|
||||||
|
|
||||||
.in_fg.buffer = in_fg_buf,
|
// loop 3 times if we are testing PPA sleep retention feature
|
||||||
.in_fg.pic_w = w,
|
int cnt = (auto_light_sleep ? 3 : 1);
|
||||||
.in_fg.pic_h = h,
|
for (int i = 0; i < cnt; i++) {
|
||||||
.in_fg.block_w = block_w,
|
#if SOC_LIGHT_SLEEP_SUPPORTED
|
||||||
.in_fg.block_h = block_h,
|
sleep_ctx.sleep_request_result = ESP_FAIL; // set back to fail for new iteration
|
||||||
.in_fg.block_offset_x = block_offset_x,
|
sleep_ctx.sleep_flags = 0; // clear sleep flags for new iteration
|
||||||
.in_fg.block_offset_y = block_offset_y,
|
|
||||||
.in_fg.blend_cm = in_fg_cm,
|
|
||||||
|
|
||||||
.out.buffer = out_buf,
|
if (auto_light_sleep) {
|
||||||
.out.buffer_size = out_buf_size,
|
vTaskDelay(pdMS_TO_TICKS(1000)); // enter auto light sleep here if we are testing PPA sleep retention feature
|
||||||
.out.pic_w = w,
|
|
||||||
.out.pic_h = h,
|
|
||||||
.out.block_offset_x = block_offset_x,
|
|
||||||
.out.block_offset_y = block_offset_y,
|
|
||||||
.out.blend_cm = out_cm,
|
|
||||||
|
|
||||||
.bg_alpha_update_mode = PPA_ALPHA_SCALE,
|
// Check if the sleep happened as expected
|
||||||
.bg_alpha_scale_ratio = bg_alpha_scale_ratio,
|
#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP
|
||||||
|
TEST_ASSERT_EQUAL(PMU_SLEEP_PD_TOP, sleep_ctx.sleep_flags & PMU_SLEEP_PD_TOP);
|
||||||
.fg_alpha_update_mode = PPA_ALPHA_INVERT,
|
#endif
|
||||||
|
TEST_ASSERT_EQUAL(ESP_OK, sleep_ctx.sleep_request_result);
|
||||||
.bg_ck_en = false,
|
|
||||||
.fg_ck_en = false,
|
|
||||||
|
|
||||||
.mode = PPA_TRANS_MODE_BLOCKING,
|
|
||||||
};
|
|
||||||
|
|
||||||
TEST_ESP_OK(ppa_do_blend(ppa_client_handle, &oper_config));
|
|
||||||
|
|
||||||
// Check result
|
|
||||||
for (int i = 0; i < out_buf_len; i++) {
|
|
||||||
if (i % 8 == 0) {
|
|
||||||
printf("\n");
|
|
||||||
}
|
}
|
||||||
printf("0x%02X ", out_buf[i]);
|
#endif
|
||||||
|
|
||||||
|
ppa_blend_oper_config_t oper_config = {
|
||||||
|
.in_bg.buffer = in_bg_buf,
|
||||||
|
.in_bg.pic_w = w,
|
||||||
|
.in_bg.pic_h = h,
|
||||||
|
.in_bg.block_w = block_w,
|
||||||
|
.in_bg.block_h = block_h,
|
||||||
|
.in_bg.block_offset_x = block_offset_x,
|
||||||
|
.in_bg.block_offset_y = block_offset_y,
|
||||||
|
.in_bg.blend_cm = in_bg_cm,
|
||||||
|
|
||||||
|
.in_fg.buffer = in_fg_buf,
|
||||||
|
.in_fg.pic_w = w,
|
||||||
|
.in_fg.pic_h = h,
|
||||||
|
.in_fg.block_w = block_w,
|
||||||
|
.in_fg.block_h = block_h,
|
||||||
|
.in_fg.block_offset_x = block_offset_x,
|
||||||
|
.in_fg.block_offset_y = block_offset_y,
|
||||||
|
.in_fg.blend_cm = in_fg_cm,
|
||||||
|
|
||||||
|
.out.buffer = out_buf,
|
||||||
|
.out.buffer_size = out_buf_size,
|
||||||
|
.out.pic_w = w,
|
||||||
|
.out.pic_h = h,
|
||||||
|
.out.block_offset_x = block_offset_x,
|
||||||
|
.out.block_offset_y = block_offset_y,
|
||||||
|
.out.blend_cm = out_cm,
|
||||||
|
|
||||||
|
.bg_alpha_update_mode = PPA_ALPHA_SCALE,
|
||||||
|
.bg_alpha_scale_ratio = bg_alpha_scale_ratio,
|
||||||
|
|
||||||
|
.fg_alpha_update_mode = PPA_ALPHA_INVERT,
|
||||||
|
|
||||||
|
.bg_ck_en = false,
|
||||||
|
.fg_ck_en = false,
|
||||||
|
|
||||||
|
.mode = PPA_TRANS_MODE_BLOCKING,
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_ESP_OK(ppa_do_blend(ppa_client_handle, &oper_config));
|
||||||
|
|
||||||
|
// Check result
|
||||||
|
for (int i = 0; i < out_buf_len; i++) {
|
||||||
|
if (i % 8 == 0) {
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
printf("0x%02X ", out_buf[i]);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
TEST_ASSERT_EQUAL_UINT8_ARRAY((void *)out_buf_expected, (void *)out_buf, out_buf_len);
|
||||||
|
|
||||||
|
memcpy(in_fg_buf, in_fg_buf_template, 64);
|
||||||
|
esp_cache_msync((void *)in_fg_buf, 64, ESP_CACHE_MSYNC_FLAG_DIR_C2M);
|
||||||
}
|
}
|
||||||
printf("\n");
|
#if SOC_LIGHT_SLEEP_SUPPORTED
|
||||||
TEST_ASSERT_EQUAL_UINT8_ARRAY((void *)out_buf_expected, (void *)out_buf, out_buf_len);
|
esp_sleep_set_sleep_context(NULL);
|
||||||
|
#endif
|
||||||
|
|
||||||
#if !(CONFIG_IDF_TARGET_ESP32P4 && CONFIG_ESP32P4_SELECTS_REV_LESS_V3)
|
#if !(CONFIG_IDF_TARGET_ESP32P4 && CONFIG_ESP32P4_SELECTS_REV_LESS_V3)
|
||||||
// Test YUV422/YUV420 blend
|
// Test YUV422/YUV420 blend
|
||||||
@@ -588,9 +700,26 @@ TEST_CASE("ppa_blend_basic_data_correctness_check", "[PPA]")
|
|||||||
#endif // !(CONFIG_IDF_TARGET_ESP32P4 && CONFIG_ESP32P4_SELECTS_REV_LESS_V3)
|
#endif // !(CONFIG_IDF_TARGET_ESP32P4 && CONFIG_ESP32P4_SELECTS_REV_LESS_V3)
|
||||||
|
|
||||||
TEST_ESP_OK(ppa_unregister_client(ppa_client_handle));
|
TEST_ESP_OK(ppa_unregister_client(ppa_client_handle));
|
||||||
|
|
||||||
|
#if CONFIG_PM_ENABLE
|
||||||
|
enable_pm_strategy(false);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
free(in_fg_buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("ppa_fill_basic_data_correctness_check", "[PPA]")
|
TEST_CASE("ppa_blend_basic_data_correctness_check", "[PPA]")
|
||||||
|
{
|
||||||
|
ppa_blend_basic_data_correctness_check(false);
|
||||||
|
#if CONFIG_PM_ENABLE
|
||||||
|
#if !(CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP && !SOC_PM_FPU_RETENTION_BY_SW) // Blend uses FPU
|
||||||
|
printf("\nTest again with auto light sleep...\n");
|
||||||
|
ppa_blend_basic_data_correctness_check(true);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ppa_fill_basic_data_correctness_check(bool auto_light_sleep)
|
||||||
{
|
{
|
||||||
const uint32_t w = 80;
|
const uint32_t w = 80;
|
||||||
const uint32_t h = 120;
|
const uint32_t h = 120;
|
||||||
@@ -613,57 +742,110 @@ TEST_CASE("ppa_fill_basic_data_correctness_check", "[PPA]")
|
|||||||
|
|
||||||
memset(out_buf, 0xFF, out_buf_len);
|
memset(out_buf, 0xFF, out_buf_len);
|
||||||
|
|
||||||
|
#if CONFIG_PM_ENABLE
|
||||||
|
enable_pm_strategy(auto_light_sleep);
|
||||||
|
#endif
|
||||||
|
|
||||||
ppa_client_handle_t ppa_client_handle;
|
ppa_client_handle_t ppa_client_handle;
|
||||||
ppa_client_config_t ppa_client_config = {
|
ppa_client_config_t ppa_client_config = {
|
||||||
.oper_type = PPA_OPERATION_FILL,
|
.oper_type = PPA_OPERATION_FILL,
|
||||||
.max_pending_trans_num = 1,
|
.max_pending_trans_num = 1,
|
||||||
|
#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP
|
||||||
|
.flags.allow_pd = (auto_light_sleep ? true : false),
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
TEST_ESP_OK(ppa_register_client(&ppa_client_config, &ppa_client_handle));
|
TEST_ESP_OK(ppa_register_client(&ppa_client_config, &ppa_client_handle));
|
||||||
|
|
||||||
ppa_fill_oper_config_t oper_config = {
|
#if SOC_LIGHT_SLEEP_SUPPORTED
|
||||||
.out.buffer = out_buf,
|
esp_sleep_context_t sleep_ctx;
|
||||||
.out.buffer_size = out_buf_size,
|
esp_sleep_set_sleep_context(&sleep_ctx);
|
||||||
.out.pic_w = w,
|
#endif
|
||||||
.out.pic_h = h,
|
|
||||||
.out.block_offset_x = block_offset_x,
|
|
||||||
.out.block_offset_y = block_offset_y,
|
|
||||||
.out.fill_cm = out_cm,
|
|
||||||
|
|
||||||
.fill_block_w = block_w,
|
// loop 3 times if we are testing PPA sleep retention feature
|
||||||
.fill_block_h = block_h,
|
int cnt = (auto_light_sleep ? 3 : 1);
|
||||||
.fill_argb_color = fill_color,
|
for (int i = 0; i < cnt; i++) {
|
||||||
|
#if SOC_LIGHT_SLEEP_SUPPORTED
|
||||||
|
sleep_ctx.sleep_request_result = ESP_FAIL; // set back to fail for new iteration
|
||||||
|
sleep_ctx.sleep_flags = 0; // clear sleep flags for new iteration
|
||||||
|
|
||||||
.mode = PPA_TRANS_MODE_BLOCKING,
|
if (auto_light_sleep) {
|
||||||
};
|
vTaskDelay(pdMS_TO_TICKS(1000)); // enter auto light sleep here if we are testing PPA sleep retention feature
|
||||||
|
|
||||||
TEST_ESP_OK(ppa_do_fill(ppa_client_handle, &oper_config));
|
// Check if the sleep happened as expected
|
||||||
|
#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP
|
||||||
|
TEST_ASSERT_EQUAL(PMU_SLEEP_PD_TOP, sleep_ctx.sleep_flags & PMU_SLEEP_PD_TOP);
|
||||||
|
#endif
|
||||||
|
TEST_ASSERT_EQUAL(ESP_OK, sleep_ctx.sleep_request_result);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// Check result
|
ppa_fill_oper_config_t oper_config = {
|
||||||
const color_pixel_rgb565_data_t fill_pixel_expected = {.r = fill_color.r >> 3,
|
.out.buffer = out_buf,
|
||||||
.g = fill_color.g >> 2,
|
.out.buffer_size = out_buf_size,
|
||||||
.b = fill_color.b >> 3,
|
.out.pic_w = w,
|
||||||
};
|
.out.pic_h = h,
|
||||||
TEST_ASSERT_EACH_EQUAL_UINT16(fill_pixel_expected.val, (void *)((uint32_t)out_buf + w * block_offset_y * out_pixel_depth / 8), block_w * block_h);
|
.out.block_offset_x = block_offset_x,
|
||||||
|
.out.block_offset_y = block_offset_y,
|
||||||
|
.out.fill_cm = out_cm,
|
||||||
|
|
||||||
|
.fill_block_w = block_w,
|
||||||
|
.fill_block_h = block_h,
|
||||||
|
.fill_argb_color = fill_color,
|
||||||
|
|
||||||
|
.mode = PPA_TRANS_MODE_BLOCKING,
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_ESP_OK(ppa_do_fill(ppa_client_handle, &oper_config));
|
||||||
|
|
||||||
|
// Check result
|
||||||
|
color_pixel_rgb565_data_t fill_pixel_expected = {};
|
||||||
|
fill_pixel_expected.r = fill_color.r >> 3;
|
||||||
|
fill_pixel_expected.g = fill_color.g >> 2;
|
||||||
|
fill_pixel_expected.b = fill_color.b >> 3;
|
||||||
|
TEST_ASSERT_EACH_EQUAL_UINT16(fill_pixel_expected.val, (void *)((uint32_t)out_buf + w * block_offset_y * out_pixel_depth / 8), block_w * block_h);
|
||||||
|
|
||||||
#if !(CONFIG_IDF_TARGET_ESP32P4 && CONFIG_ESP32P4_SELECTS_REV_LESS_V3)
|
#if !(CONFIG_IDF_TARGET_ESP32P4 && CONFIG_ESP32P4_SELECTS_REV_LESS_V3)
|
||||||
// Test a yuv color fill
|
// Test a yuv color fill
|
||||||
oper_config.out.fill_cm = PPA_FILL_COLOR_MODE_YUV422_UYVY; // output YUV422 is with UYVY packed order
|
oper_config.out.fill_cm = PPA_FILL_COLOR_MODE_YUV422_UYVY; // output YUV422 is with UYVY packed order
|
||||||
const color_macroblock_yuv_data_t fill_yuv_color = {.y = 0xFF, .u = 0x55, .v = 0xAA};
|
color_macroblock_yuv_data_t fill_yuv_color = {};
|
||||||
oper_config.fill_yuv_color = fill_yuv_color;
|
fill_yuv_color.y = 0xFF;
|
||||||
out_pixel_format.color_type_id = PPA_FILL_COLOR_MODE_YUV422_UYVY;
|
fill_yuv_color.u = 0x55;
|
||||||
out_pixel_depth = color_hal_pixel_format_get_bit_depth(out_pixel_format); // bits
|
fill_yuv_color.v = 0xAA;
|
||||||
TEST_ESP_OK(ppa_do_fill(ppa_client_handle, &oper_config));
|
oper_config.fill_yuv_color = fill_yuv_color;
|
||||||
|
out_pixel_format.color_type_id = PPA_FILL_COLOR_MODE_YUV422_UYVY;
|
||||||
|
out_pixel_depth = color_hal_pixel_format_get_bit_depth(out_pixel_format); // bits
|
||||||
|
TEST_ESP_OK(ppa_do_fill(ppa_client_handle, &oper_config));
|
||||||
|
|
||||||
// Check result (2 pixels per macro pixel)
|
// Check result (2 pixels per macro pixel)
|
||||||
const uint32_t fill_pixel_expected_yuv422 = ((fill_yuv_color.y << 24) | (fill_yuv_color.v << 16) | (fill_yuv_color.y << 8) | (fill_yuv_color.u));
|
const uint32_t fill_pixel_expected_yuv422 = ((fill_yuv_color.y << 24) | (fill_yuv_color.v << 16) | (fill_yuv_color.y << 8) | (fill_yuv_color.u));
|
||||||
TEST_ASSERT_EACH_EQUAL_UINT32(fill_pixel_expected_yuv422, (void *)((uint32_t)out_buf + w * block_offset_y * out_pixel_depth / 8), block_w * block_h / 2);
|
TEST_ASSERT_EACH_EQUAL_UINT32(fill_pixel_expected_yuv422, (void *)((uint32_t)out_buf + w * block_offset_y * out_pixel_depth / 8), block_w * block_h / 2);
|
||||||
#endif // !(CONFIG_IDF_TARGET_ESP32P4 && CONFIG_ESP32P4_SELECTS_REV_LESS_V3)
|
#endif // !(CONFIG_IDF_TARGET_ESP32P4 && CONFIG_ESP32P4_SELECTS_REV_LESS_V3)
|
||||||
|
|
||||||
|
memset(out_buf, 0xFF, out_buf_size);
|
||||||
|
esp_cache_msync((void *)out_buf, out_buf_size, ESP_CACHE_MSYNC_FLAG_DIR_C2M);
|
||||||
|
}
|
||||||
|
#if SOC_LIGHT_SLEEP_SUPPORTED
|
||||||
|
esp_sleep_set_sleep_context(NULL);
|
||||||
|
#endif
|
||||||
|
|
||||||
TEST_ESP_OK(ppa_unregister_client(ppa_client_handle));
|
TEST_ESP_OK(ppa_unregister_client(ppa_client_handle));
|
||||||
|
|
||||||
|
#if CONFIG_PM_ENABLE
|
||||||
|
enable_pm_strategy(false);
|
||||||
|
#endif
|
||||||
|
|
||||||
free(out_buf);
|
free(out_buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("ppa_fill_basic_data_correctness_check", "[PPA]")
|
||||||
|
{
|
||||||
|
ppa_fill_basic_data_correctness_check(false);
|
||||||
|
#if CONFIG_PM_ENABLE
|
||||||
|
printf("\nTest again with auto light sleep...\n");
|
||||||
|
ppa_fill_basic_data_correctness_check(true);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
/* All performance tests are tested under the following situations:
|
/* All performance tests are tested under the following situations:
|
||||||
* - Testing PPA speed where in_buffer(s) and out_buffer all located in PSRAM
|
* - Testing PPA speed where in_buffer(s) and out_buffer all located in PSRAM
|
||||||
* - Only 2D-DMA is using PSRAM
|
* - Only 2D-DMA is using PSRAM
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
CONFIG_PM_ENABLE=y
|
CONFIG_PM_ENABLE=y
|
||||||
CONFIG_FREERTOS_USE_TICKLESS_IDLE=y
|
CONFIG_FREERTOS_USE_TICKLESS_IDLE=y
|
||||||
CONFIG_PM_DFS_INIT_AUTO=y
|
CONFIG_PM_DFS_INIT_AUTO=y
|
||||||
|
CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP=y
|
||||||
CONFIG_COMPILER_OPTIMIZATION_SIZE=y
|
CONFIG_COMPILER_OPTIMIZATION_SIZE=y
|
||||||
CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y
|
CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y
|
||||||
CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT=y
|
CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT=y
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
CONFIG_FREERTOS_HZ=1000
|
CONFIG_FREERTOS_HZ=1000
|
||||||
CONFIG_ESP_TASK_WDT_EN=n
|
CONFIG_ESP_TASK_WDT_EN=n
|
||||||
CONFIG_IDF_EXPERIMENTAL_FEATURES=y
|
CONFIG_IDF_EXPERIMENTAL_FEATURES=y
|
||||||
|
|
||||||
|
CONFIG_ESP_SLEEP_DEBUG=y
|
||||||
|
|||||||
@@ -25,6 +25,7 @@
|
|||||||
#include "soc/dma2d_periph.h"
|
#include "soc/dma2d_periph.h"
|
||||||
#include "esp_bit_defs.h"
|
#include "esp_bit_defs.h"
|
||||||
#include "hal/efuse_hal.h"
|
#include "hal/efuse_hal.h"
|
||||||
|
#include "esp_private/sleep_retention.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The 2D-DMA driver is designed with a pool & client model + queue design pattern.
|
* The 2D-DMA driver is designed with a pool & client model + queue design pattern.
|
||||||
@@ -350,6 +351,17 @@ static void dma2d_default_isr(void *args)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP
|
||||||
|
static esp_err_t dma2d_create_sleep_retention_link_cb(void *arg)
|
||||||
|
{
|
||||||
|
sleep_retention_module_t module = dma2d_reg_retention_info.module;
|
||||||
|
esp_err_t err = sleep_retention_entries_create(dma2d_reg_retention_info.regdma_entry_array,
|
||||||
|
dma2d_reg_retention_info.array_size,
|
||||||
|
REGDMA_LINK_PRI_DMA2D, module);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
esp_err_t dma2d_acquire_pool(const dma2d_pool_config_t *config, dma2d_pool_handle_t *ret_pool)
|
esp_err_t dma2d_acquire_pool(const dma2d_pool_config_t *config, dma2d_pool_handle_t *ret_pool)
|
||||||
{
|
{
|
||||||
esp_err_t ret = ESP_OK;
|
esp_err_t ret = ESP_OK;
|
||||||
@@ -404,6 +416,29 @@ esp_err_t dma2d_acquire_pool(const dma2d_pool_config_t *config, dma2d_pool_handl
|
|||||||
dma2d_hal_init(&pre_alloc_group->hal, group_id); // initialize HAL context
|
dma2d_hal_init(&pre_alloc_group->hal, group_id); // initialize HAL context
|
||||||
// Enable 2D-DMA module clock
|
// Enable 2D-DMA module clock
|
||||||
dma2d_ll_hw_enable(s_platform.groups[group_id]->hal.dev, true);
|
dma2d_ll_hw_enable(s_platform.groups[group_id]->hal.dev, true);
|
||||||
|
|
||||||
|
#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP
|
||||||
|
// acquire sleep retention
|
||||||
|
sleep_retention_module_t module = dma2d_reg_retention_info.module;
|
||||||
|
sleep_retention_module_init_param_t init_param = {
|
||||||
|
.cbs = {
|
||||||
|
.create = {
|
||||||
|
.handle = dma2d_create_sleep_retention_link_cb,
|
||||||
|
.arg = NULL,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
.depends = RETENTION_MODULE_BITMAP_INIT(CLOCK_SYSTEM)
|
||||||
|
};
|
||||||
|
if (sleep_retention_module_init(module, &init_param) != ESP_OK) {
|
||||||
|
// even though the sleep retention module init failed, DMA2D driver should still work, so just warning here
|
||||||
|
ESP_LOGW(TAG, "init sleep retention failed, power domain may be turned off during sleep");
|
||||||
|
} else {
|
||||||
|
if (sleep_retention_module_allocate(module) != ESP_OK) {
|
||||||
|
ESP_LOGW(TAG, "fail to allocate retention link list");
|
||||||
|
// don't call sleep_retention_module_deinit here, otherwise DMA2D peripheral may be powered off during sleep
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
} else {
|
} else {
|
||||||
ret = ESP_ERR_NO_MEM;
|
ret = ESP_ERR_NO_MEM;
|
||||||
free(pre_alloc_tx_channels);
|
free(pre_alloc_tx_channels);
|
||||||
@@ -507,6 +542,16 @@ esp_err_t dma2d_release_pool(dma2d_pool_handle_t dma2d_pool)
|
|||||||
PERIPH_RCC_ATOMIC() {
|
PERIPH_RCC_ATOMIC() {
|
||||||
dma2d_ll_enable_bus_clock(group_id, false);
|
dma2d_ll_enable_bus_clock(group_id, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP
|
||||||
|
sleep_retention_module_t module = dma2d_reg_retention_info.module;
|
||||||
|
if (sleep_retention_is_module_created(module)) {
|
||||||
|
sleep_retention_module_free(module);
|
||||||
|
}
|
||||||
|
if (sleep_retention_is_module_inited(module)) {
|
||||||
|
sleep_retention_module_deinit(module);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
if (do_deinitialize) {
|
if (do_deinitialize) {
|
||||||
|
|||||||
@@ -27,8 +27,13 @@
|
|||||||
#include "soc/pvt_reg.h"
|
#include "soc/pvt_reg.h"
|
||||||
|
|
||||||
/* Interrupt Matrix Registers Context */
|
/* Interrupt Matrix Registers Context */
|
||||||
|
#if (CONFIG_ESP_REV_MIN_FULL < 300)
|
||||||
#define N_REGS_INTR_CORE0() (((INTERRUPT_CORE0_CLOCK_GATE_REG - DR_REG_INTERRUPT_CORE0_BASE) / 4) + 1)
|
#define N_REGS_INTR_CORE0() (((INTERRUPT_CORE0_CLOCK_GATE_REG - DR_REG_INTERRUPT_CORE0_BASE) / 4) + 1)
|
||||||
#define N_REGS_INTR_CORE1() (((INTERRUPT_CORE1_CLOCK_GATE_REG - DR_REG_INTERRUPT_CORE1_BASE) / 4) + 1)
|
#define N_REGS_INTR_CORE1() (((INTERRUPT_CORE1_CLOCK_GATE_REG - DR_REG_INTERRUPT_CORE1_BASE) / 4) + 1)
|
||||||
|
#else
|
||||||
|
#define N_REGS_INTR_CORE0() (((INTERRUPT_CORE0_INTR_SIG_IDX_ASSERT_IN_SEC_REG - DR_REG_INTERRUPT_CORE0_BASE) / 4) + 1)
|
||||||
|
#define N_REGS_INTR_CORE1() (((INTERRUPT_CORE1_INTR_SIG_IDX_ASSERT_IN_SEC_REG - DR_REG_INTERRUPT_CORE1_BASE) / 4) + 1)
|
||||||
|
#endif
|
||||||
const regdma_entries_config_t intr_matrix_regs_retention[] = {
|
const regdma_entries_config_t intr_matrix_regs_retention[] = {
|
||||||
[0] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_INTMTX_LINK(0x00), DR_REG_INTERRUPT_CORE0_BASE, DR_REG_INTERRUPT_CORE0_BASE, N_REGS_INTR_CORE0(), 0, 0), .owner = ENTRY(0) }, /* intr matrix */
|
[0] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_INTMTX_LINK(0x00), DR_REG_INTERRUPT_CORE0_BASE, DR_REG_INTERRUPT_CORE0_BASE, N_REGS_INTR_CORE0(), 0, 0), .owner = ENTRY(0) }, /* intr matrix */
|
||||||
[1] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_INTMTX_LINK(0x01), DR_REG_INTERRUPT_CORE1_BASE, DR_REG_INTERRUPT_CORE1_BASE, N_REGS_INTR_CORE1(), 0, 0), .owner = ENTRY(0) } /* intr matrix */
|
[1] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_INTMTX_LINK(0x01), DR_REG_INTERRUPT_CORE1_BASE, DR_REG_INTERRUPT_CORE1_BASE, N_REGS_INTR_CORE1(), 0, 0), .owner = ENTRY(0) } /* intr matrix */
|
||||||
|
|||||||
@@ -298,6 +298,14 @@ bool peripheral_domain_pd_allowed(void)
|
|||||||
mask.bitmap[SLEEP_RETENTION_MODULE_LCDCAM >> 5] |= BIT(SLEEP_RETENTION_MODULE_LCDCAM % 32);
|
mask.bitmap[SLEEP_RETENTION_MODULE_LCDCAM >> 5] |= BIT(SLEEP_RETENTION_MODULE_LCDCAM % 32);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if SOC_DMA2D_SUPPORTED
|
||||||
|
mask.bitmap[SLEEP_RETENTION_MODULE_DMA2D >> 5] |= BIT(SLEEP_RETENTION_MODULE_DMA2D % 32);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if SOC_PPA_SUPPORTED
|
||||||
|
mask.bitmap[SLEEP_RETENTION_MODULE_PPA >> 5] |= BIT(SLEEP_RETENTION_MODULE_PPA % 32);
|
||||||
|
#endif
|
||||||
|
|
||||||
const sleep_retention_module_bitmap_t peripheral_domain_inited_modules = sleep_retention_module_bitmap_and(inited_modules, mask);
|
const sleep_retention_module_bitmap_t peripheral_domain_inited_modules = sleep_retention_module_bitmap_and(inited_modules, mask);
|
||||||
const sleep_retention_module_bitmap_t peripheral_domain_created_modules = sleep_retention_module_bitmap_and(created_modules, mask);
|
const sleep_retention_module_bitmap_t peripheral_domain_created_modules = sleep_retention_module_bitmap_and(created_modules, mask);
|
||||||
return sleep_retention_module_bitmap_eq(peripheral_domain_inited_modules, peripheral_domain_created_modules);
|
return sleep_retention_module_bitmap_eq(peripheral_domain_inited_modules, peripheral_domain_created_modules);
|
||||||
|
|||||||
@@ -744,3 +744,7 @@ TEST_CASE("DMA2D_M2M_2D_window", "[DMA2D]")
|
|||||||
|
|
||||||
TEST_ESP_OK(dma2d_m2m_deinit());
|
TEST_ESP_OK(dma2d_m2m_deinit());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Note:
|
||||||
|
// Sleep retention functionality test is not covered yet, since all basic test cases can survive with 2D-DMA registers reset to default value.
|
||||||
|
// It shall be tested when arbiter feature is supported and its test case is added.
|
||||||
|
|||||||
@@ -92,7 +92,7 @@ extern "C" {
|
|||||||
* @param group_id Group ID
|
* @param group_id Group ID
|
||||||
* @param enable True to enable; false to disable
|
* @param enable True to enable; false to disable
|
||||||
*/
|
*/
|
||||||
static inline void dma2d_ll_enable_bus_clock(int group_id, bool enable)
|
static inline void _dma2d_ll_enable_bus_clock(int group_id, bool enable)
|
||||||
{
|
{
|
||||||
(void)group_id;
|
(void)group_id;
|
||||||
HP_SYS_CLKRST.soc_clk_ctrl1.reg_dma2d_sys_clk_en = enable;
|
HP_SYS_CLKRST.soc_clk_ctrl1.reg_dma2d_sys_clk_en = enable;
|
||||||
@@ -100,14 +100,14 @@ static inline void dma2d_ll_enable_bus_clock(int group_id, bool enable)
|
|||||||
|
|
||||||
/// use a macro to wrap the function, force the caller to use it in a critical section
|
/// use a macro to wrap the function, force the caller to use it in a critical section
|
||||||
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
|
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
|
||||||
#define dma2d_ll_enable_bus_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; dma2d_ll_enable_bus_clock(__VA_ARGS__)
|
#define dma2d_ll_enable_bus_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; _dma2d_ll_enable_bus_clock(__VA_ARGS__)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Reset the 2D-DMA module
|
* @brief Reset the 2D-DMA module
|
||||||
*
|
*
|
||||||
* @param group_id Group ID
|
* @param group_id Group ID
|
||||||
*/
|
*/
|
||||||
static inline void dma2d_ll_reset_register(int group_id)
|
static inline void _dma2d_ll_reset_register(int group_id)
|
||||||
{
|
{
|
||||||
(void)group_id;
|
(void)group_id;
|
||||||
HP_SYS_CLKRST.hp_rst_en0.reg_rst_en_dma2d = 1;
|
HP_SYS_CLKRST.hp_rst_en0.reg_rst_en_dma2d = 1;
|
||||||
@@ -116,7 +116,7 @@ static inline void dma2d_ll_reset_register(int group_id)
|
|||||||
|
|
||||||
/// use a macro to wrap the function, force the caller to use it in a critical section
|
/// use a macro to wrap the function, force the caller to use it in a critical section
|
||||||
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
|
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
|
||||||
#define dma2d_ll_reset_register(...) (void)__DECLARE_RCC_ATOMIC_ENV; dma2d_ll_reset_register(__VA_ARGS__)
|
#define dma2d_ll_reset_register(...) (void)__DECLARE_RCC_ATOMIC_ENV; _dma2d_ll_reset_register(__VA_ARGS__)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Check if the bus clock is enabled for the DMA module
|
* @brief Check if the bus clock is enabled for the DMA module
|
||||||
|
|||||||
@@ -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
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@@ -53,19 +53,19 @@ typedef enum {
|
|||||||
*
|
*
|
||||||
* @param enable Set true to enable, false to disable
|
* @param enable Set true to enable, false to disable
|
||||||
*/
|
*/
|
||||||
static inline void ppa_ll_enable_bus_clock(bool enable)
|
static inline void _ppa_ll_enable_bus_clock(bool enable)
|
||||||
{
|
{
|
||||||
HP_SYS_CLKRST.soc_clk_ctrl1.reg_ppa_sys_clk_en = enable;
|
HP_SYS_CLKRST.soc_clk_ctrl1.reg_ppa_sys_clk_en = enable;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// use a macro to wrap the function, force the caller to use it in a critical section
|
/// use a macro to wrap the function, force the caller to use it in a critical section
|
||||||
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
|
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
|
||||||
#define ppa_ll_enable_bus_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; ppa_ll_enable_bus_clock(__VA_ARGS__)
|
#define ppa_ll_enable_bus_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; _ppa_ll_enable_bus_clock(__VA_ARGS__)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Reset the PPA module
|
* @brief Reset the PPA module
|
||||||
*/
|
*/
|
||||||
static inline void ppa_ll_reset_register(void)
|
static inline void _ppa_ll_reset_register(void)
|
||||||
{
|
{
|
||||||
HP_SYS_CLKRST.hp_rst_en1.reg_rst_en_ppa = 1;
|
HP_SYS_CLKRST.hp_rst_en1.reg_rst_en_ppa = 1;
|
||||||
HP_SYS_CLKRST.hp_rst_en1.reg_rst_en_ppa = 0;
|
HP_SYS_CLKRST.hp_rst_en1.reg_rst_en_ppa = 0;
|
||||||
@@ -73,7 +73,7 @@ static inline void ppa_ll_reset_register(void)
|
|||||||
|
|
||||||
/// use a macro to wrap the function, force the caller to use it in a critical section
|
/// use a macro to wrap the function, force the caller to use it in a critical section
|
||||||
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
|
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
|
||||||
#define ppa_ll_reset_register(...) (void)__DECLARE_RCC_ATOMIC_ENV; ppa_ll_reset_register(__VA_ARGS__)
|
#define ppa_ll_reset_register(...) (void)__DECLARE_RCC_ATOMIC_ENV; _ppa_ll_reset_register(__VA_ARGS__)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Configure the RGB888 to GRAY8 color conversion coefficients for SRM and Blending (excluding Fill)
|
* @brief Configure the RGB888 to GRAY8 color conversion coefficients for SRM and Blending (excluding Fill)
|
||||||
|
|||||||
@@ -67,6 +67,10 @@ if(CONFIG_SOC_DMA2D_SUPPORTED)
|
|||||||
list(APPEND srcs "${target_folder}/dma2d_periph.c")
|
list(APPEND srcs "${target_folder}/dma2d_periph.c")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(CONFIG_SOC_PPA_SUPPORTED)
|
||||||
|
list(APPEND srcs "${target_folder}/ppa_periph.c")
|
||||||
|
endif()
|
||||||
|
|
||||||
if(CONFIG_SOC_GPSPI_SUPPORTED)
|
if(CONFIG_SOC_GPSPI_SUPPORTED)
|
||||||
list(APPEND srcs "${target_folder}/spi_periph.c")
|
list(APPEND srcs "${target_folder}/spi_periph.c")
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "soc/dma2d_periph.h"
|
#include "soc/dma2d_periph.h"
|
||||||
|
#include "soc/dma2d_reg.h"
|
||||||
#include "soc/interrupts.h"
|
#include "soc/interrupts.h"
|
||||||
|
|
||||||
const dma2d_signal_conn_t dma2d_periph_signals = {
|
const dma2d_signal_conn_t dma2d_periph_signals = {
|
||||||
@@ -24,3 +25,32 @@ const dma2d_signal_conn_t dma2d_periph_signals = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** DMA2D Registers to be saved during sleep retention
|
||||||
|
*
|
||||||
|
* DMA2D driver is implemented in the way that channels are used as a pool,
|
||||||
|
* therefore, only general registers are needed to be saved during sleep retention.
|
||||||
|
*
|
||||||
|
* DMA2D_RST_CONF_REG,
|
||||||
|
* DMA2D_INTR_MEM_START_ADDR_REG, DMA2D_INTR_MEM_END_ADDR_REG, DMA2D_EXTR_MEM_START_ADDR_REG, DMA2D_EXTR_MEM_END_ADDR_REG
|
||||||
|
* DMA2D_OUT_ARB_CONFIG_REG, DMA2D_IN_ARB_CONFIG_REG
|
||||||
|
*/
|
||||||
|
#define DMA2D_RETENTION_REGS_CNT 7
|
||||||
|
#define DMA2D_RETENTION_REGS_BASE DMA2D_RST_CONF_REG
|
||||||
|
static const uint32_t dma2d_regs_map[4] = {0x7f, 0x0, 0x0, 0x0};
|
||||||
|
static const regdma_entries_config_t dma2d_regdma_entries[] = {
|
||||||
|
[0] = {
|
||||||
|
.config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_DMA2D_LINK(0x00),
|
||||||
|
DMA2D_RETENTION_REGS_BASE, DMA2D_RETENTION_REGS_BASE,
|
||||||
|
DMA2D_RETENTION_REGS_CNT, 0, 0,
|
||||||
|
dma2d_regs_map[0], dma2d_regs_map[1],
|
||||||
|
dma2d_regs_map[2], dma2d_regs_map[3]),
|
||||||
|
.owner = ENTRY(0),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const dma2d_reg_retention_info_t dma2d_reg_retention_info = {
|
||||||
|
.module = SLEEP_RETENTION_MODULE_DMA2D,
|
||||||
|
.regdma_entry_array = dma2d_regdma_entries,
|
||||||
|
.array_size = ARRAY_SIZE(dma2d_regdma_entries),
|
||||||
|
};
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@@ -61,6 +61,8 @@ typedef enum periph_retention_module {
|
|||||||
SLEEP_RETENTION_MODULE_MCPWM1 = 35,
|
SLEEP_RETENTION_MODULE_MCPWM1 = 35,
|
||||||
SLEEP_RETENTION_MODULE_PCNT0 = 36,
|
SLEEP_RETENTION_MODULE_PCNT0 = 36,
|
||||||
SLEEP_RETENTION_MODULE_LCDCAM = 39,
|
SLEEP_RETENTION_MODULE_LCDCAM = 39,
|
||||||
|
SLEEP_RETENTION_MODULE_DMA2D = 41,
|
||||||
|
SLEEP_RETENTION_MODULE_PPA = 42,
|
||||||
|
|
||||||
SLEEP_RETENTION_MODULE_MAX = SOC_PM_RETENTION_MODULE_NUM - 1
|
SLEEP_RETENTION_MODULE_MAX = SOC_PM_RETENTION_MODULE_NUM - 1
|
||||||
} periph_retention_module_t;
|
} periph_retention_module_t;
|
||||||
@@ -104,6 +106,8 @@ typedef enum periph_retention_module {
|
|||||||
: ((m) == SLEEP_RETENTION_MODULE_MCPWM1) ? true \
|
: ((m) == SLEEP_RETENTION_MODULE_MCPWM1) ? true \
|
||||||
: ((m) == SLEEP_RETENTION_MODULE_PCNT0) ? true \
|
: ((m) == SLEEP_RETENTION_MODULE_PCNT0) ? true \
|
||||||
: ((m) == SLEEP_RETENTION_MODULE_LCDCAM) ? true \
|
: ((m) == SLEEP_RETENTION_MODULE_LCDCAM) ? true \
|
||||||
|
: ((m) == SLEEP_RETENTION_MODULE_DMA2D) ? true \
|
||||||
|
: ((m) == SLEEP_RETENTION_MODULE_PPA) ? true \
|
||||||
: false)
|
: false)
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|||||||
@@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "soc/ppa_periph.h"
|
||||||
|
#include "soc/ppa_reg.h"
|
||||||
|
|
||||||
|
/** PPA Registers to be saved during sleep retention
|
||||||
|
*
|
||||||
|
* For CLUT mem, we shall choose not to power down the CLUT mem domain; Otherwise, there are two blocks of memory that needs to be restored by writing to mem addr directly.
|
||||||
|
* Since PPA driver is operation based, most of the registers are configured per operation, so no need to save/restore.
|
||||||
|
*
|
||||||
|
* PPA_CLUT_CONF_REG,
|
||||||
|
* PPA_INT_ENA_REG,
|
||||||
|
* PPA_SR_MEM_PD_REG, PPA_REG_CONF_REG, PPA_SRAM_CTRL_REG,
|
||||||
|
* PPA_RGB2GRAY_REG (> rev3 only, but ok to include it for < rev3 chips)
|
||||||
|
*/
|
||||||
|
#define PPA_RETENTION_REGS_CNT 6
|
||||||
|
#define PPA_RETENTION_REGS_BASE PPA_CLUT_CONF_REG
|
||||||
|
static const uint32_t ppa_regs_map[4] = {0x1800009, 0x9, 0x0, 0x0};
|
||||||
|
static const regdma_entries_config_t ppa_regdma_entries[] = {
|
||||||
|
[0] = {
|
||||||
|
.config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_PPA_LINK(0x00),
|
||||||
|
PPA_RETENTION_REGS_BASE, PPA_RETENTION_REGS_BASE,
|
||||||
|
PPA_RETENTION_REGS_CNT, 0, 0,
|
||||||
|
ppa_regs_map[0], ppa_regs_map[1],
|
||||||
|
ppa_regs_map[2], ppa_regs_map[3]),
|
||||||
|
.owner = ENTRY(0),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const ppa_reg_retention_info_t ppa_reg_retention_info = {
|
||||||
|
.module = SLEEP_RETENTION_MODULE_PPA,
|
||||||
|
.regdma_entry_array = ppa_regdma_entries,
|
||||||
|
.array_size = ARRAY_SIZE(ppa_regdma_entries),
|
||||||
|
};
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@@ -9,6 +9,11 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "soc/soc_caps.h"
|
#include "soc/soc_caps.h"
|
||||||
|
|
||||||
|
#if SOC_PAU_SUPPORTED
|
||||||
|
#include "soc/regdma.h"
|
||||||
|
#include "soc/retention_periph_defs.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
@@ -22,6 +27,16 @@ typedef struct {
|
|||||||
} dma2d_signal_conn_t;
|
} dma2d_signal_conn_t;
|
||||||
|
|
||||||
extern const dma2d_signal_conn_t dma2d_periph_signals;
|
extern const dma2d_signal_conn_t dma2d_periph_signals;
|
||||||
|
|
||||||
|
#if SOC_LIGHT_SLEEP_SUPPORTED
|
||||||
|
typedef struct {
|
||||||
|
const periph_retention_module_t module;
|
||||||
|
const regdma_entries_config_t *regdma_entry_array;
|
||||||
|
uint32_t array_size;
|
||||||
|
} dma2d_reg_retention_info_t;
|
||||||
|
|
||||||
|
extern const dma2d_reg_retention_info_t dma2d_reg_retention_info;
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "soc/soc_caps.h"
|
||||||
|
#if SOC_PAU_SUPPORTED
|
||||||
|
#include "soc/regdma.h"
|
||||||
|
#include "soc/retention_periph_defs.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if SOC_PPA_SUPPORTED
|
||||||
|
#if SOC_LIGHT_SLEEP_SUPPORTED
|
||||||
|
typedef struct {
|
||||||
|
const periph_retention_module_t module;
|
||||||
|
const regdma_entries_config_t *regdma_entry_array;
|
||||||
|
uint32_t array_size;
|
||||||
|
} ppa_reg_retention_info_t;
|
||||||
|
|
||||||
|
extern const ppa_reg_retention_info_t ppa_reg_retention_info;
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@@ -65,6 +65,8 @@ extern "C" {
|
|||||||
#define REGDMA_PCNT_LINK(_pri) ((0x25 << 8) | _pri)
|
#define REGDMA_PCNT_LINK(_pri) ((0x25 << 8) | _pri)
|
||||||
#define REGDMA_MCPWM_LINK(_pri) ((0x26 << 8) | _pri)
|
#define REGDMA_MCPWM_LINK(_pri) ((0x26 << 8) | _pri)
|
||||||
#define REGDMA_LCDCAM_LINK(_pri) ((0x29 << 8) | _pri)
|
#define REGDMA_LCDCAM_LINK(_pri) ((0x29 << 8) | _pri)
|
||||||
|
#define REGDMA_PPA_LINK(_pri) ((0x2B << 8) | _pri)
|
||||||
|
#define REGDMA_DMA2D_LINK(_pri) ((0x2C << 8) | _pri)
|
||||||
|
|
||||||
#define REGDMA_MODEM_FE_LINK(_pri) ((0xFF << 8) | _pri)
|
#define REGDMA_MODEM_FE_LINK(_pri) ((0xFF << 8) | _pri)
|
||||||
|
|
||||||
@@ -93,6 +95,8 @@ extern "C" {
|
|||||||
#define REGDMA_LINK_PRI_LEDC REGDMA_LINK_PRI_GENERAL_PERIPH
|
#define REGDMA_LINK_PRI_LEDC REGDMA_LINK_PRI_GENERAL_PERIPH
|
||||||
#define REGDMA_LINK_PRI_MCPWM REGDMA_LINK_PRI_GENERAL_PERIPH
|
#define REGDMA_LINK_PRI_MCPWM REGDMA_LINK_PRI_GENERAL_PERIPH
|
||||||
#define REGDMA_LINK_PRI_LCDCAM REGDMA_LINK_PRI_GENERAL_PERIPH
|
#define REGDMA_LINK_PRI_LCDCAM REGDMA_LINK_PRI_GENERAL_PERIPH
|
||||||
|
#define REGDMA_LINK_PRI_PPA REGDMA_LINK_PRI_GENERAL_PERIPH
|
||||||
|
#define REGDMA_LINK_PRI_DMA2D REGDMA_LINK_PRI_GENERAL_PERIPH
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
REGDMA_LINK_PRI_0 = 0,
|
REGDMA_LINK_PRI_0 = 0,
|
||||||
|
|||||||
Reference in New Issue
Block a user