Merge branch 'feat/lcd_sleep_retention_p4' into 'master'

feat(lcd): support i80 lcd sleep retention on p4

Closes IDF-9925, IDF-10965, and IDF-10703

See merge request espressif/esp-idf!45549
This commit is contained in:
Chen Ji Chang
2026-02-25 11:09:23 +08:00
16 changed files with 319 additions and 7 deletions
+38 -1
View File
@@ -1,11 +1,12 @@
/*
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "hal/lcd_periph.h"
#include "soc/gpio_sig_map.h"
#include "soc/lcd_cam_reg.h"
const soc_lcd_i80_signal_desc_t soc_lcd_i80_signals[1] = {
[0] = {
@@ -80,3 +81,39 @@ const soc_lcd_rgb_signal_desc_t soc_lcd_rgb_signals[1] = {
.disp_sig = SIG_GPIO_OUT_IDX,
}
};
/**
* LCD_CAM Registers to be saved during sleep retention
* - LCD Clock Configuration registers: LCDCAM_LCD_CLOCK_REG (0x0)
* - LCD RGB/YUV Configuration registers: LCDCAM_LCD_RGB_YUV_REG (0x10)
* - LCD User Configuration registers: LCDCAM_LCD_USER_REG (0x14), LCDCAM_LCD_MISC_REG (0x18)
* - LCD Control registers: LCDCAM_LCD_CTRL_REG (0x1c), LCDCAM_LCD_CTRL1_REG (0x20), LCDCAM_LCD_CTRL2_REG (0x24)
* - LCD Command Value registers: LCDCAM_LCD_FIRST_CMD_VAL_REG (0x28), LCDCAM_LCD_LATTER_CMD_VAL_REG (0x2c)
* - LCD Delay Mode Configuration registers: LCDCAM_LCD_DLY_MODE_CFG1_REG (0x30), LCDCAM_LCD_DLY_MODE_CFG2_REG (0x38)
* - LCD DMA Interrupt Enable register: LCDCAM_LC_DMA_INT_ENA_REG (0x64)
*
* NOTE: Only I80 LCD supports sleep retention, not RGB LCD.
*/
#define LCD_RETENTION_REGS_CNT 12
#define LCD_RETENTION_REGS_BASE (DR_REG_LCDCAM_BASE + 0x0)
static const uint32_t lcd_cam_regs_map[4] = {0x2005ff1, 0x0, 0x0, 0x0};
static const regdma_entries_config_t lcd_regs_retention[] = {
// backup stage: save configuration registers
// restore stage: restore the configuration registers
[0] = {
.config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_LCDCAM_LINK(0x00),
LCD_RETENTION_REGS_BASE, LCD_RETENTION_REGS_BASE,
LCD_RETENTION_REGS_CNT, 0, 0,
lcd_cam_regs_map[0], lcd_cam_regs_map[1],
lcd_cam_regs_map[2], lcd_cam_regs_map[3]),
.owner = ENTRY(0),
},
};
const soc_i80_lcd_retention_info_t soc_i80_lcd_retention_info[1] = {
[0] = {
.regdma_entry_array = lcd_regs_retention,
.array_size = ARRAY_SIZE(lcd_regs_retention),
.retention_module = SLEEP_RETENTION_MODULE_LCDCAM
},
};
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -61,6 +61,17 @@ typedef struct {
extern const soc_lcd_i2s_signal_desc_t soc_lcd_i2s_signals[I2S_LL_GET(INST_NUM)];
#endif // SOC_HAS(I2S_I80_LCD)
#if SOC_HAS(PAU) && SOC_HAS(LCDCAM_I80_LCD)
// Only LCDCAM I80 LCD supports sleep retention
typedef struct {
const periph_retention_module_t retention_module;
const regdma_entries_config_t *regdma_entry_array;
uint32_t array_size;
} soc_i80_lcd_retention_info_t;
extern const soc_i80_lcd_retention_info_t soc_i80_lcd_retention_info[LCD_LL_GET(I80_BUS_NUM)];
#endif // SOC_HAS(PAU) && SOC_HAS(LCDCAM_I80_LCD)
#ifdef __cplusplus
}
#endif
@@ -99,6 +99,9 @@ bool peripheral_domain_pd_allowed(void)
// ESP32P4 supports JPEG sleep retention
RETENTION_MODULE_BITMAP_SET(&mask, SLEEP_RETENTION_MODULE_JPEG);
// ESP32P4 supports LCDCAM sleep retention
RETENTION_MODULE_BITMAP_SET(&mask, SLEEP_RETENTION_MODULE_LCDCAM);
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);
return sleep_retention_module_bitmap_eq(peripheral_domain_inited_modules, peripheral_domain_created_modules);
@@ -10,6 +10,10 @@
#include "hal/lcd_hal.h"
#include "hal/cache_ll.h"
#include "hal/cache_hal.h"
#include "esp_private/sleep_retention.h"
// Use retention link only when the target supports sleep retention is enabled
#define I80_USE_RETENTION_LINK (SOC_LCDCAM_LCD_SUPPORT_SLEEP_RETENTION && CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP)
#if defined(SOC_GDMA_TRIG_PERIPH_LCD0_BUS) && (SOC_GDMA_TRIG_PERIPH_LCD0_BUS == SOC_GDMA_BUS_AHB)
#define LCD_GDMA_NEW_CHANNEL gdma_new_ahb_channel
@@ -31,6 +35,11 @@ typedef struct esp_lcd_i80_bus_t esp_lcd_i80_bus_t;
typedef struct lcd_panel_io_i80_t lcd_panel_io_i80_t;
typedef struct lcd_i80_trans_descriptor_t lcd_i80_trans_descriptor_t;
#if I80_USE_RETENTION_LINK
static esp_err_t lcd_i80_create_sleep_retention_link_cb(void *arg);
static void lcd_i80_create_retention_module(esp_lcd_i80_bus_t *bus);
#endif // I80_USE_RETENTION_LINK
static esp_err_t panel_io_i80_tx_param(esp_lcd_panel_io_t *io, int lcd_cmd, const void *param, size_t param_size);
static esp_err_t panel_io_i80_tx_color(esp_lcd_panel_io_t *io, int lcd_cmd, const void *color, size_t color_size);
static esp_err_t panel_io_i80_del(esp_lcd_panel_io_t *io);
@@ -117,6 +126,10 @@ esp_err_t esp_lcd_new_i80_bus(const esp_lcd_i80_bus_config_t *bus_config, esp_lc
// although LCD_CAM can support up to 24 data lines, we restrict users to only use 8 or 16 bit width
ESP_RETURN_ON_FALSE(bus_config->bus_width == 8 || bus_config->bus_width == 16, ESP_ERR_INVALID_ARG,
TAG, "invalid bus width:%d", bus_config->bus_width);
#if !SOC_LCDCAM_LCD_SUPPORT_SLEEP_RETENTION
ESP_RETURN_ON_FALSE(bus_config->flags.allow_pd == 0, ESP_ERR_NOT_SUPPORTED, TAG, "register back up is not supported");
#endif // SOC_LCDCAM_LCD_SUPPORT_SLEEP_RETENTION
// allocate i80 bus memory
bus = heap_caps_calloc(1, sizeof(esp_lcd_i80_bus_t), LCD_I80_MEM_ALLOC_CAPS);
ESP_GOTO_ON_FALSE(bus, ESP_ERR_NO_MEM, err, TAG, "no mem for i80 bus");
@@ -143,6 +156,26 @@ esp_err_t esp_lcd_new_i80_bus(const esp_lcd_i80_bus_config_t *bus_config, esp_lc
lcd_ll_reset_register(bus_id);
}
}
#if I80_USE_RETENTION_LINK
// no need to acquire mutex, because the bus is exclusive
sleep_retention_module_t module_id = soc_i80_lcd_retention_info[bus_id].retention_module;
sleep_retention_module_init_param_t init_param = {
.cbs = {
.create = {
.handle = lcd_i80_create_sleep_retention_link_cb,
.arg = bus,
},
},
.depends = RETENTION_MODULE_BITMAP_INIT(CLOCK_SYSTEM)
};
if (sleep_retention_module_init(module_id, &init_param) != ESP_OK) {
// even though the sleep retention module init failed, LCD driver should still work, so just warning here
ESP_LOGW(TAG, "init sleep retention failed, power domain may be turned off during sleep");
}
if (bus_config->flags.allow_pd) {
lcd_i80_create_retention_module(bus);
}
#endif // I80_USE_RETENTION_LINK
// initialize HAL layer, so we can call LL APIs later
lcd_hal_init(&bus->hal, bus_id);
PERIPH_RCC_ATOMIC() {
@@ -240,6 +273,16 @@ esp_err_t esp_lcd_del_i80_bus(esp_lcd_i80_bus_handle_t bus)
ESP_GOTO_ON_FALSE(bus, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument");
ESP_GOTO_ON_FALSE(LIST_EMPTY(&bus->device_list), ESP_ERR_INVALID_STATE, err, TAG, "device list not empty");
int bus_id = bus->bus_id;
#if I80_USE_RETENTION_LINK
const periph_retention_module_t module_id = soc_i80_lcd_retention_info[bus_id].retention_module;
if (sleep_retention_is_module_created(module_id)) {
assert(sleep_retention_is_module_inited(module_id));
sleep_retention_module_free(module_id);
}
if (sleep_retention_is_module_inited(module_id)) {
sleep_retention_module_deinit(module_id);
}
#endif // I80_USE_RETENTION_LINK
lcd_com_remove_device(LCD_COM_DEVICE_TYPE_I80, bus_id);
PERIPH_RCC_RELEASE_ATOMIC(soc_lcd_i80_signals[bus_id].module, ref_count) {
if (ref_count == 0) {
@@ -546,6 +589,33 @@ static esp_err_t panel_io_i80_tx_color(esp_lcd_panel_io_t *io, int lcd_cmd, cons
return ESP_OK;
}
#if I80_USE_RETENTION_LINK
static esp_err_t lcd_i80_create_sleep_retention_link_cb(void *arg)
{
esp_lcd_i80_bus_t *bus = (esp_lcd_i80_bus_t *)arg;
int bus_id = bus->bus_id;
sleep_retention_module_t module_id = soc_i80_lcd_retention_info[bus_id].retention_module;
esp_err_t err = sleep_retention_entries_create(soc_i80_lcd_retention_info[bus_id].regdma_entry_array,
soc_i80_lcd_retention_info[bus_id].array_size,
REGDMA_LINK_PRI_LCDCAM, module_id);
ESP_RETURN_ON_ERROR(err, TAG, "create retention link failed");
return ESP_OK;
}
static void lcd_i80_create_retention_module(esp_lcd_i80_bus_t *bus)
{
int bus_id = bus->bus_id;
sleep_retention_module_t module_id = soc_i80_lcd_retention_info[bus_id].retention_module;
if (sleep_retention_is_module_inited(module_id) && !sleep_retention_is_module_created(module_id)) {
if (sleep_retention_module_allocate(module_id) != ESP_OK) {
// even though the sleep retention module create failed, LCD driver should still work, so just warning here
ESP_LOGW(TAG, "create retention module failed, power domain can't turn off");
}
}
}
#endif // I80_USE_RETENTION_LINK
static esp_err_t lcd_i80_select_periph_clock(esp_lcd_i80_bus_handle_t bus, lcd_clock_source_t clk_src)
{
// get clock source frequency
+11 -4
View File
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -30,6 +30,11 @@ typedef struct {
size_t bus_width; /*!< Number of data lines, 8 or 16 */
size_t max_transfer_bytes; /*!< Maximum transfer size, this determines the length of internal DMA link */
size_t dma_burst_size; /*!< DMA burst size, in bytes */
/// Extra configuration flags for I80 bus
struct extra_i80_bus_flags {
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. */
} flags; /*!< Extra bus config flags */
} esp_lcd_i80_bus_config_t;
/**
@@ -67,19 +72,21 @@ typedef struct {
void *user_ctx; /*!< User private data, passed directly to on_color_trans_done's user_ctx */
int lcd_cmd_bits; /*!< Bit-width of LCD command */
int lcd_param_bits; /*!< Bit-width of LCD parameter */
struct {
/// D/C line levels configuration
struct i80_panel_io_dc_levels {
unsigned int dc_idle_level: 1; /*!< Level of DC line in IDLE phase */
unsigned int dc_cmd_level: 1; /*!< Level of DC line in CMD phase */
unsigned int dc_dummy_level: 1; /*!< Level of DC line in DUMMY phase */
unsigned int dc_data_level: 1; /*!< Level of DC line in DATA phase */
} dc_levels; /*!< Each i80 device might have its own D/C control logic */
struct {
/// Extra configuration flags for I80 panel IO
struct extra_i80_panel_io_flags {
unsigned int cs_active_high: 1; /*!< If set, a high level of CS line will select the device, otherwise, CS line is low level active */
unsigned int reverse_color_bits: 1; /*!< Reverse the data bits, D[N:0] -> D[0:N] */
unsigned int swap_color_bytes: 1; /*!< Swap adjacent two color bytes */
unsigned int pclk_active_neg: 1; /*!< The display will write data lines when there's a falling edge on WR signal (a.k.a the PCLK) */
unsigned int pclk_idle_low: 1; /*!< The WR signal (a.k.a the PCLK) stays at low level in IDLE phase */
} flags; /*!< Panel IO config flags */
} flags; /*!< Extra panel IO config flags */
} esp_lcd_panel_io_i80_config_t;
/**
+11 -1
View File
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -48,6 +48,7 @@
#include "hal/cache_ll.h"
#include "hal/color_hal.h"
#include "rgb_lcd_rotation_sw.h"
#include "esp_private/sleep_retention.h"
// hardware issue workaround
#if CONFIG_IDF_TARGET_ESP32S3
@@ -284,6 +285,9 @@ static esp_err_t lcd_rgb_panel_destroy(esp_rgb_panel_t *rgb_panel)
esp_pm_lock_release(rgb_panel->pm_lock);
esp_pm_lock_delete(rgb_panel->pm_lock);
}
#endif
#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP
sleep_retention_power_lock_release();
#endif
free(rgb_panel);
return ESP_OK;
@@ -342,6 +346,11 @@ esp_err_t esp_lcd_new_rgb_panel(const esp_lcd_rgb_panel_config_t *rgb_panel_conf
expect_bb_eof_count = fb_size / bb_size;
}
#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP
// acquire the retention power lock to prevent the power domain from being turned off during light sleep
sleep_retention_power_lock_acquire();
#endif
// calculate the number of DMA descriptors
size_t num_dma_nodes = 0;
// allocate memory for rgb panel
@@ -379,6 +388,7 @@ esp_err_t esp_lcd_new_rgb_panel(const esp_lcd_rgb_panel_config_t *rgb_panel_conf
// set clock source
ret = lcd_rgb_panel_select_clock_src(rgb_panel, rgb_panel_config->clk_src);
ESP_GOTO_ON_ERROR(ret, err, TAG, "set source clock failed");
// reset peripheral and FIFO after we select a correct clock source
lcd_ll_fifo_reset(hal->dev);
lcd_ll_reset(hal->dev);
@@ -1,6 +1,10 @@
set(srcs "test_app_main.c"
"test_i80_lcd_panel.c")
if(CONFIG_SOC_LIGHT_SLEEP_SUPPORTED AND CONFIG_PM_ENABLE)
list(APPEND srcs "test_i80_lcd_panel_sleep.c")
endif()
# In order for the cases defined by `TEST_CASE` to be linked into the final elf,
# the component can be registered as WHOLE_ARCHIVE
idf_component_register(SRCS ${srcs}
@@ -0,0 +1,153 @@
/*
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: CC0-1.0
*/
#include <stdio.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "unity.h"
#include "esp_random.h"
#include "esp_lcd_panel_io.h"
#include "esp_lcd_panel_vendor.h"
#include "esp_lcd_panel_ops.h"
#include "esp_lcd_panel_commands.h"
#include "soc/soc_caps.h"
#include "driver/gpio.h"
#include "test_i80_board.h"
#include "esp_private/sleep_cpu.h"
#include "esp_private/esp_sleep_internal.h"
#include "esp_private/esp_pmu.h"
static void test_i80_lcd_sleep_retention(bool allow_pd)
{
#define TEST_IMG_SIZE (100 * 100 * sizeof(uint16_t))
uint8_t *img = heap_caps_malloc(TEST_IMG_SIZE, MALLOC_CAP_DMA);
TEST_ASSERT_NOT_NULL(img);
gpio_config_t bk_gpio_config = {
.mode = GPIO_MODE_OUTPUT,
.pin_bit_mask = 1ULL << TEST_LCD_BK_LIGHT_GPIO
};
TEST_ESP_OK(gpio_config(&bk_gpio_config));
esp_lcd_i80_bus_handle_t i80_bus = NULL;
esp_lcd_i80_bus_config_t bus_config = {
.dc_gpio_num = TEST_LCD_DC_GPIO,
.wr_gpio_num = TEST_LCD_PCLK_GPIO,
.clk_src = LCD_CLK_SRC_DEFAULT,
.data_gpio_nums = {
TEST_LCD_DATA0_GPIO,
TEST_LCD_DATA1_GPIO,
TEST_LCD_DATA2_GPIO,
TEST_LCD_DATA3_GPIO,
TEST_LCD_DATA4_GPIO,
TEST_LCD_DATA5_GPIO,
TEST_LCD_DATA6_GPIO,
TEST_LCD_DATA7_GPIO,
},
.bus_width = 8,
.max_transfer_bytes = TEST_IMG_SIZE + 10,
.flags = {
.allow_pd = allow_pd,
},
};
TEST_ESP_OK(esp_lcd_new_i80_bus(&bus_config, &i80_bus));
esp_lcd_panel_io_handle_t io_handle = NULL;
esp_lcd_panel_io_i80_config_t io_config = {
.cs_gpio_num = TEST_LCD_CS_GPIO,
.pclk_hz = 8000000, // 8MHz
.trans_queue_depth = 10,
.dc_levels = {
.dc_idle_level = 0,
.dc_cmd_level = 0,
.dc_dummy_level = 0,
.dc_data_level = 1,
},
.lcd_cmd_bits = 8,
.lcd_param_bits = 8,
};
TEST_ESP_OK(esp_lcd_new_panel_io_i80(i80_bus, &io_config, &io_handle));
esp_lcd_panel_handle_t panel_handle = NULL;
esp_lcd_panel_dev_config_t panel_config = {
.reset_gpio_num = TEST_LCD_RST_GPIO,
.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB,
.bits_per_pixel = 16,
};
TEST_ESP_OK(esp_lcd_new_panel_st7789(io_handle, &panel_config, &panel_handle));
// turn off backlight
gpio_set_level(TEST_LCD_BK_LIGHT_GPIO, 0);
esp_lcd_panel_reset(panel_handle);
esp_lcd_panel_init(panel_handle);
esp_lcd_panel_invert_color(panel_handle, true);
// the gap is LCD panel specific, even panels with the same driver IC, can have different gap value
esp_lcd_panel_set_gap(panel_handle, 0, 20);
// turn on display
esp_lcd_panel_disp_on_off(panel_handle, true);
// turn on backlight
gpio_set_level(TEST_LCD_BK_LIGHT_GPIO, 1);
for (int i = 0; i < 200; i++) {
uint8_t color_byte = esp_random() & 0xFF;
int x_start = esp_random() % (TEST_LCD_H_RES - 100);
int y_start = esp_random() % (TEST_LCD_V_RES - 100);
memset(img, color_byte, TEST_IMG_SIZE);
esp_lcd_panel_draw_bitmap(panel_handle, x_start, y_start, x_start + 100, y_start + 100, img);
}
// turn off screen
esp_lcd_panel_disp_on_off(panel_handle, false);
// go to sleep
esp_sleep_context_t sleep_ctx;
esp_sleep_set_sleep_context(&sleep_ctx);
printf("go to light sleep for 2 seconds\r\n");
#if CONFIG_PM_ESP_SLEEP_POWER_DOWN_CPU
TEST_ESP_OK(sleep_cpu_configure(true));
#endif
TEST_ESP_OK(esp_sleep_enable_timer_wakeup(2 * 1000 * 1000));
TEST_ESP_OK(esp_light_sleep_start());
printf("Waked up! Let's see if I80 LCD driver can still work...\r\n");
#if CONFIG_PM_ESP_SLEEP_POWER_DOWN_CPU
TEST_ESP_OK(sleep_cpu_configure(false));
#endif
printf("check if the sleep happened as expected\r\n");
TEST_ASSERT_EQUAL(0, sleep_ctx.sleep_request_result);
#if SOC_LCDCAM_LCD_SUPPORT_SLEEP_RETENTION
// check if the power domain also is powered down
TEST_ASSERT_EQUAL(allow_pd ? PMU_SLEEP_PD_TOP : 0, (sleep_ctx.sleep_flags) & PMU_SLEEP_PD_TOP);
#endif
esp_sleep_set_sleep_context(NULL);
// turn on screen
esp_lcd_panel_disp_on_off(panel_handle, true);
printf("Testing I80 LCD after sleep...\n");
for (int i = 0; i < 200; i++) {
uint8_t color_byte = esp_random() & 0xFF;
int x_start = esp_random() % (TEST_LCD_H_RES - 100);
int y_start = esp_random() % (TEST_LCD_V_RES - 100);
memset(img, color_byte, TEST_IMG_SIZE);
esp_lcd_panel_draw_bitmap(panel_handle, x_start, y_start, x_start + 100, y_start + 100, img);
}
TEST_ESP_OK(esp_lcd_panel_del(panel_handle));
TEST_ESP_OK(esp_lcd_panel_io_del(io_handle));
TEST_ESP_OK(esp_lcd_del_i80_bus(i80_bus));
TEST_ESP_OK(gpio_reset_pin(TEST_LCD_BK_LIGHT_GPIO));
free(img);
#undef TEST_IMG_SIZE
}
TEST_CASE("i80_lcd light sleep", "[lcd]")
{
test_i80_lcd_sleep_retention(false);
#if SOC_LCDCAM_LCD_SUPPORT_SLEEP_RETENTION
test_i80_lcd_sleep_retention(true);
#endif
}
@@ -1,4 +1,5 @@
CONFIG_PM_ENABLE=y
CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP=y
CONFIG_FREERTOS_USE_TICKLESS_IDLE=y
CONFIG_COMPILER_OPTIMIZATION_SIZE=y
CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y
@@ -3,3 +3,6 @@
#
# CONFIG_ESP_TASK_WDT_INIT is not set
CONFIG_FREERTOS_HZ=1000
# primitives for checking sleep internal state
CONFIG_ESP_SLEEP_DEBUG=y
@@ -1871,6 +1871,10 @@ config SOC_LCDCAM_CAM_SUPPORT_RGB_YUV_CONV
bool
default y
config SOC_LCDCAM_LCD_SUPPORT_SLEEP_RETENTION
bool
default y
config SOC_LP_CORE_SUPPORT_ETM
bool
default y
@@ -62,6 +62,7 @@ typedef enum periph_retention_module {
SLEEP_RETENTION_MODULE_SDM0 = 36,
SLEEP_RETENTION_MODULE_EMAC = 37,
SLEEP_RETENTION_MODULE_JPEG = 38,
SLEEP_RETENTION_MODULE_LCDCAM = 39,
SLEEP_RETENTION_MODULE_MAX = SOC_PM_RETENTION_MODULE_NUM - 1
} periph_retention_module_t;
@@ -105,6 +106,7 @@ typedef enum periph_retention_module {
: ((m) == SLEEP_RETENTION_MODULE_MCPWM1) ? true \
: ((m) == SLEEP_RETENTION_MODULE_SDM0) ? true \
: ((m) == SLEEP_RETENTION_MODULE_JPEG) ? true \
: ((m) == SLEEP_RETENTION_MODULE_LCDCAM) ? true \
: false)
#ifdef __cplusplus
@@ -716,6 +716,9 @@
/*--------------------------- CAM ---------------------------------*/
#define SOC_LCDCAM_CAM_SUPPORT_RGB_YUV_CONV (1)
/*--------------------------- LCD ---------------------------------*/
#define SOC_LCDCAM_LCD_SUPPORT_SLEEP_RETENTION (1) /*!< Support back up registers before sleep */
/*------------------------------------- ULP CAPS -------------------------------------*/
#define SOC_LP_CORE_SUPPORT_ETM (1) /*!< LP Core supports ETM */
#define SOC_LP_CORE_SUPPORT_LP_ADC (1) /*!< LP ADC can be accessed from the LP-Core */
+2
View File
@@ -67,6 +67,7 @@ extern "C" {
#define REGDMA_SDM_LINK(_pri) ((0x26 << 8) | _pri)
#define REGDMA_EMAC_LINK(_pri) ((0x27 << 8) | _pri)
#define REGDMA_JPEG_LINK(_pri) ((0x28 << 8) | _pri)
#define REGDMA_LCDCAM_LINK(_pri) ((0x29 << 8) | _pri)
#define REGDMA_MODEM_FE_LINK(_pri) ((0xFF << 8) | _pri)
@@ -96,6 +97,7 @@ extern "C" {
#define REGDMA_LINK_PRI_SDM REGDMA_LINK_PRI_GENERAL_PERIPH
#define REGDMA_LINK_PRI_EMAC REGDMA_LINK_PRI_GENERAL_PERIPH
#define REGDMA_LINK_PRI_JPEG REGDMA_LINK_PRI_GENERAL_PERIPH
#define REGDMA_LINK_PRI_LCDCAM REGDMA_LINK_PRI_GENERAL_PERIPH
typedef enum {
REGDMA_LINK_PRI_0 = 0,
@@ -193,6 +193,7 @@ The following drivers hold the ``ESP_PM_APB_FREQ_MAX`` lock while the driver is
:SOC_PARLIO_SUPPORT_SLEEP_RETENTION: - PARL_IO
:SOC_SPI_SUPPORT_SLEEP_RETENTION: - All GPSPIs
:SOC_EMAC_SUPPORT_SLEEP_RETENTION: - EMAC
:SOC_LCDCAM_LCD_SUPPORT_SLEEP_RETENTION: - I80 LCD
Some peripherals haven't support Light-sleep context retention, or it cannot survive from the register lose. They will prevent the power-down of peripherals even when the feature is enabled.
@@ -193,6 +193,7 @@ ESP-IDF 使用预测性时间补偿机制来实现自动 Light-sleep。系统会
:SOC_PARLIO_SUPPORT_SLEEP_RETENTION: - PARL_IO
:SOC_SPI_SUPPORT_SLEEP_RETENTION: - All GPSPIs
:SOC_EMAC_SUPPORT_SLEEP_RETENTION: - EMAC
:SOC_LCDCAM_LCD_SUPPORT_SLEEP_RETENTION: - I80 LCD
一些外设尚未支持睡眠上下文恢复,或者寄存器丢失后根本无法恢复。即使外设下电功能被启用,它们也会阻止外设下电的发生: