feat(ppa): add sleep retention support for DMA2D and PPA

This commit is contained in:
Song Ruo Jing
2026-07-03 20:36:32 +08:00
parent 69d6deb7e6
commit 9516083cb1
20 changed files with 569 additions and 118 deletions
@@ -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
*/
@@ -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.
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` */
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;
/**
+67
View File
@@ -30,7 +30,13 @@
#include "hal/ppa_hal.h"
#include "hal/ppa_ll.h"
#include "hal/ppa_types.h"
#include "soc/ppa_periph.h"
#include "hal/color_hal.h"
#include "hal/color_types.h"
#include "esp_private/periph_ctrl.h"
#include "hal/efuse_hal.h"
#include "esp_private/sleep_retention.h"
#include "soc/soc_caps.h"
static const char *TAG = "ppa_core";
@@ -50,6 +56,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 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)
{
esp_err_t ret = ESP_OK;
@@ -182,6 +207,35 @@ static esp_err_t ppa_engine_acquire(const ppa_engine_config_t *config, ppa_engin
ESP_LOGE(TAG, "install 2D-DMA failed");
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:
@@ -242,6 +296,17 @@ static esp_err_t ppa_engine_release(ppa_engine_t *ppa_engine)
if (!s_platform.srm && !s_platform.blending) {
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) {
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;
@@ -279,11 +344,13 @@ esp_err_t ppa_register_client(const ppa_client_config_t *config, ppa_client_hand
if (config->oper_type == PPA_OPERATION_SRM) {
ppa_engine_config_t engine_config = {
.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");
} else if (config->oper_type == PPA_OPERATION_BLEND || config->oper_type == PPA_OPERATION_FILL) {
ppa_engine_config_t engine_config = {
.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");
}
+7 -1
View File
@@ -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
*/
@@ -70,6 +70,9 @@ typedef struct ppa_blend_engine_t {
typedef struct {
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;
/******************************** CLIENT *************************************/
@@ -228,6 +231,9 @@ struct ppa_platform_t {
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
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
@@ -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 esp_pm
WHOLE_ARCHIVE)
@@ -18,6 +18,12 @@
#include "hal/color_hal.h"
#include "esp_cache.h"
#include "esp_random.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))
@@ -263,7 +269,20 @@ TEST_CASE("ppa_pending_transactions_in_queue", "[PPA]")
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 h = 4;
@@ -304,59 +323,111 @@ TEST_CASE("ppa_srm_basic_data_correctness_check", "[PPA]")
0x0000, 0x0000, 0x0000, 0x0000
};
#if CONFIG_PM_ENABLE
enable_pm_strategy(auto_light_sleep);
#endif
ppa_client_handle_t ppa_client_handle;
ppa_client_config_t ppa_client_config = {
.oper_type = PPA_OPERATION_SRM,
.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));
ppa_srm_oper_config_t oper_config = {
.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,
#if SOC_LIGHT_SLEEP_SUPPORTED
esp_sleep_context_t sleep_ctx;
esp_sleep_set_sleep_context(&sleep_ctx);
#endif
.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,
// loop 3 times if we are testing PPA sleep retention feature
int cnt = (auto_light_sleep ? 3 : 1);
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
.rotation_angle = rotation,
.scale_x = scale_x,
.scale_y = scale_y,
if (auto_light_sleep) {
vTaskDelay(pdMS_TO_TICKS(1000)); // enter auto light sleep here if we are testing PPA sleep retention feature
.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");
// 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);
}
printf("0x%02X ", out_buf[i]);
#endif
ppa_srm_oper_config_t oper_config = {
.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);
memset(out_buf, 0, out_buf_size);
esp_cache_msync((void *)out_buf, out_buf_size, ESP_CACHE_MSYNC_FLAG_DIR_C2M);
}
printf("\n");
TEST_ASSERT_EQUAL_UINT8_ARRAY((void *)out_buf_expected, (void *)out_buf, buf_len);
#if SOC_LIGHT_SLEEP_SUPPORTED
esp_sleep_set_sleep_context(NULL);
#endif
TEST_ESP_OK(ppa_unregister_client(ppa_client_handle));
#if CONFIG_PM_ENABLE
enable_pm_strategy(false);
#endif
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 h = 2;
@@ -389,7 +460,7 @@ TEST_CASE("ppa_blend_basic_data_correctness_check", "[PPA]")
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, /**/ 0x00, 0x80, 0x80, 0xC0, /**/
@@ -397,6 +468,10 @@ TEST_CASE("ppa_blend_basic_data_correctness_check", "[PPA]")
// /*******************************/
[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;
// Expected blend output
// Alpha Blending calculation:
@@ -412,67 +487,121 @@ 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_config_t ppa_client_config = {
.oper_type = PPA_OPERATION_BLEND,
.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));
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,
#if SOC_LIGHT_SLEEP_SUPPORTED
esp_sleep_context_t sleep_ctx;
esp_sleep_set_sleep_context(&sleep_ctx);
#endif
.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,
// loop 3 times if we are testing PPA sleep retention feature
int cnt = (auto_light_sleep ? 3 : 1);
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
.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,
if (auto_light_sleep) {
vTaskDelay(pdMS_TO_TICKS(1000)); // enter auto light sleep here if we are testing PPA sleep retention feature
.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");
// 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);
}
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");
TEST_ASSERT_EQUAL_UINT8_ARRAY((void *)out_buf_expected, (void *)out_buf, out_buf_len);
#if SOC_LIGHT_SLEEP_SUPPORTED
esp_sleep_set_sleep_context(NULL);
#endif
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 h = 120;
@@ -495,43 +624,93 @@ TEST_CASE("ppa_fill_basic_data_correctness_check", "[PPA]")
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_config_t ppa_client_config = {
.oper_type = PPA_OPERATION_FILL,
.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));
ppa_fill_oper_config_t oper_config = {
.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.fill_cm = out_cm,
#if SOC_LIGHT_SLEEP_SUPPORTED
esp_sleep_context_t sleep_ctx;
esp_sleep_set_sleep_context(&sleep_ctx);
#endif
.fill_block_w = block_w,
.fill_block_h = block_h,
.fill_argb_color = fill_color,
// loop 3 times if we are testing PPA sleep retention feature
int cnt = (auto_light_sleep ? 3 : 1);
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
const color_pixel_rgb565_data_t fill_pixel_expected = {.r = fill_color.r >> 3,
.g = fill_color.g >> 2,
.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);
ppa_fill_oper_config_t oper_config = {
.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.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);
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));
#if CONFIG_PM_ENABLE
enable_pm_strategy(false);
#endif
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:
* - Testing PPA speed where in_buffer(s) and out_buffer all located in PSRAM
* - Only 2D-DMA is using PSRAM
@@ -1,6 +1,7 @@
CONFIG_PM_ENABLE=y
CONFIG_FREERTOS_USE_TICKLESS_IDLE=y
CONFIG_PM_DFS_INIT_AUTO=y
CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP=y
CONFIG_COMPILER_OPTIMIZATION_SIZE=y
CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y
CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT=y
@@ -1,3 +1,5 @@
CONFIG_FREERTOS_HZ=1000
CONFIG_ESP_TASK_WDT_EN=n
CONFIG_IDF_EXPERIMENTAL_FEATURES=y
CONFIG_ESP_SLEEP_DEBUG=y