From 791360a0f2bf4a8e6c78fc12d36aa37497aef7c4 Mon Sep 17 00:00:00 2001 From: wuzhenghui Date: Thu, 6 Aug 2026 15:58:07 +0800 Subject: [PATCH 1/6] change(esp_hw_support): optimize retention driver RAM cost (cherry picked from commit 11c590c053feb764e9e52c753ba3c1e61b4bb947) Co-authored-by: Cursor --- .../include/esp_private/sleep_retention.h | 2 +- components/esp_hw_support/sleep_retention.c | 34 +++++++++++-------- .../esp32c5/include/soc/Kconfig.soc_caps.in | 4 --- .../include/soc/retention_periph_defs.h | 3 +- components/soc/esp32c5/include/soc/soc_caps.h | 1 - .../esp32c6/include/soc/Kconfig.soc_caps.in | 4 --- .../include/soc/retention_periph_defs.h | 3 +- components/soc/esp32c6/include/soc/soc_caps.h | 1 - .../esp32c61/include/soc/Kconfig.soc_caps.in | 4 --- .../include/soc/retention_periph_defs.h | 3 +- .../soc/esp32c61/include/soc/soc_caps.h | 1 - .../esp32h2/include/soc/Kconfig.soc_caps.in | 4 --- .../include/soc/retention_periph_defs.h | 3 +- components/soc/esp32h2/include/soc/soc_caps.h | 2 -- .../esp32p4/include/soc/Kconfig.soc_caps.in | 4 --- .../include/soc/retention_periph_defs.h | 3 +- components/soc/esp32p4/include/soc/soc_caps.h | 1 - components/soc/include/soc/regdma.h | 12 ++++--- 18 files changed, 32 insertions(+), 57 deletions(-) diff --git a/components/esp_hw_support/include/esp_private/sleep_retention.h b/components/esp_hw_support/include/esp_private/sleep_retention.h index 7290c165443..375cfeb8cee 100644 --- a/components/esp_hw_support/include/esp_private/sleep_retention.h +++ b/components/esp_hw_support/include/esp_private/sleep_retention.h @@ -17,7 +17,7 @@ extern "C" { #include "esp_regdma.h" #include "soc/retention_periph_defs.h" -#define SLEEP_RETENTION_MODULE_BITMAP_SZ ((SLEEP_RETENTION_MODULE_MAX >> 5) + 1) +#define SLEEP_RETENTION_MODULE_BITMAP_SZ (((SLEEP_RETENTION_MODULE_MAX - 1) >> 5) + 1) /** * @file sleep_retention.h diff --git a/components/esp_hw_support/sleep_retention.c b/components/esp_hw_support/sleep_retention.c index ecb0c28f0c6..81e6a2c753e 100644 --- a/components/esp_hw_support/sleep_retention.c +++ b/components/esp_hw_support/sleep_retention.c @@ -184,7 +184,7 @@ typedef struct { #define SLEEP_RETENTION_REGDMA_LINK_NR_PRIORITIES (8u) #define SLEEP_RETENTION_REGDMA_LINK_HIGHEST_PRIORITY (0) #define SLEEP_RETENTION_REGDMA_LINK_LOWEST_PRIORITY (SLEEP_RETENTION_REGDMA_LINK_NR_PRIORITIES - 1) -#define SLEEP_RETENTION_MODULE_INVALID ((sleep_retention_module_t)(-1)) /* the final node does not belong to any module */ +#define SLEEP_RETENTION_MODULE_INVALID ((sleep_retention_module_t)(SLEEP_RETENTION_MODULE_MAX)) /* the final node does not belong to any module */ struct { sleep_retention_entries_t entries; uint32_t entries_bitmap: REGDMA_LINK_ENTRY_NUM; @@ -199,7 +199,7 @@ typedef struct { sleep_retention_module_bitmap_t inited_modules; sleep_retention_module_bitmap_t created_modules; - struct sleep_retention_module_object instance[SLEEP_RETENTION_MODULE_MAX + 1]; + struct sleep_retention_module_object instance[SLEEP_RETENTION_MODULE_MAX]; #define EXTRA_LINK_NUM (REGDMA_LINK_ENTRY_NUM - 1) } sleep_retention_t; @@ -325,7 +325,7 @@ static void sleep_retention_entries_stats(void) void sleep_retention_dump_modules(FILE *out) { - for (int i = SLEEP_RETENTION_MODULE_MIN; i <= SLEEP_RETENTION_MODULE_MAX; i++) { + for (int i = SLEEP_RETENTION_MODULE_MIN; i < SLEEP_RETENTION_MODULE_MAX; i++) { bool inited = sleep_retention_is_module_inited(i); bool created = sleep_retention_is_module_created(i); bool is_top = is_top_domain_module(i); @@ -489,13 +489,17 @@ static void sleep_retention_entries_all_destroy_wrapper(sleep_retention_module_t priority++; } } while (priority < SLEEP_RETENTION_REGDMA_LINK_NR_PRIORITIES); - s_retention.created_modules.bitmap[module >> 5] &= ~BIT(module % 32); + /* INVALID (== MAX) is a non-module sentinel; skip bitmap updates. */ + if (module < SLEEP_RETENTION_MODULE_MAX) { + s_retention.created_modules.bitmap[module >> 5] &= ~BIT(module % 32); + } _lock_release_recursive(&s_retention.lock); } static void sleep_retention_entries_do_destroy(sleep_retention_module_t module) { - assert(SLEEP_RETENTION_MODULE_MIN <= module && module <= SLEEP_RETENTION_MODULE_MAX); + /* Allow SLEEP_RETENTION_MODULE_INVALID for final-default rollback. */ + assert(SLEEP_RETENTION_MODULE_MIN <= module && module <= SLEEP_RETENTION_MODULE_INVALID); _lock_acquire_recursive(&s_retention.lock); sleep_retention_entries_join(); sleep_retention_entries_stats(); @@ -505,7 +509,7 @@ static void sleep_retention_entries_do_destroy(sleep_retention_module_t module) static void sleep_retention_entries_destroy(sleep_retention_module_t module) { - assert(SLEEP_RETENTION_MODULE_MIN <= module && module <= SLEEP_RETENTION_MODULE_MAX); + assert(SLEEP_RETENTION_MODULE_MIN <= module && module < SLEEP_RETENTION_MODULE_MAX); _lock_acquire_recursive(&s_retention.lock); sleep_retention_entries_do_destroy(module); uint32_t created_modules = 0; @@ -634,7 +638,7 @@ esp_err_t sleep_retention_entries_create(const sleep_retention_entries_config_t if (priority >= SLEEP_RETENTION_REGDMA_LINK_NR_PRIORITIES) { return ESP_ERR_INVALID_ARG; } - if (module < SLEEP_RETENTION_MODULE_MIN || module > SLEEP_RETENTION_MODULE_MAX) { + if (module < SLEEP_RETENTION_MODULE_MIN || module >= SLEEP_RETENTION_MODULE_MAX) { return ESP_ERR_INVALID_ARG; } esp_err_t err = sleep_retention_entries_check_and_create_final_default(); @@ -671,7 +675,7 @@ sleep_retention_module_bitmap_t IRAM_ATTR sleep_retention_get_created_modules(vo bool sleep_retention_is_module_inited(sleep_retention_module_t module) { - if (module < SLEEP_RETENTION_MODULE_MIN || module > SLEEP_RETENTION_MODULE_MAX) { + if (module < SLEEP_RETENTION_MODULE_MIN || module >= SLEEP_RETENTION_MODULE_MAX) { return false; } _lock_acquire_recursive(&s_retention.lock); @@ -682,7 +686,7 @@ bool sleep_retention_is_module_inited(sleep_retention_module_t module) bool sleep_retention_is_module_created(sleep_retention_module_t module) { - if (module < SLEEP_RETENTION_MODULE_MIN || module > SLEEP_RETENTION_MODULE_MAX) { + if (module < SLEEP_RETENTION_MODULE_MIN || module >= SLEEP_RETENTION_MODULE_MAX) { return false; } _lock_acquire_recursive(&s_retention.lock); @@ -727,7 +731,7 @@ bool IRAM_ATTR sleep_retention_module_bitmap_eq(sleep_retention_module_bitmap_t esp_err_t sleep_retention_module_init(sleep_retention_module_t module, sleep_retention_module_init_param_t *param) { - if (module < SLEEP_RETENTION_MODULE_MIN || module > SLEEP_RETENTION_MODULE_MAX) { + if (module < SLEEP_RETENTION_MODULE_MIN || module >= SLEEP_RETENTION_MODULE_MAX) { return ESP_ERR_INVALID_ARG; } if (param == NULL || param->cbs.create.handle == NULL) { @@ -760,7 +764,7 @@ esp_err_t sleep_retention_module_init(sleep_retention_module_t module, sleep_ret esp_err_t sleep_retention_module_deinit(sleep_retention_module_t module) { - if (module < SLEEP_RETENTION_MODULE_MIN || module > SLEEP_RETENTION_MODULE_MAX) { + if (module < SLEEP_RETENTION_MODULE_MIN || module >= SLEEP_RETENTION_MODULE_MAX) { return ESP_ERR_INVALID_ARG; } @@ -791,7 +795,7 @@ esp_err_t sleep_retention_module_deinit(sleep_retention_module_t module) static esp_err_t sleep_retention_passive_module_allocate(sleep_retention_module_t module) { - assert(module >= SLEEP_RETENTION_MODULE_MIN && module <= SLEEP_RETENTION_MODULE_MAX); + assert(module >= SLEEP_RETENTION_MODULE_MIN && module < SLEEP_RETENTION_MODULE_MAX); esp_err_t err = ESP_OK; _lock_acquire_recursive(&s_retention.lock); @@ -821,7 +825,7 @@ static esp_err_t sleep_retention_passive_module_allocate(sleep_retention_module_ esp_err_t sleep_retention_module_allocate(sleep_retention_module_t module) { - if (module < SLEEP_RETENTION_MODULE_MIN || module > SLEEP_RETENTION_MODULE_MAX) { + if (module < SLEEP_RETENTION_MODULE_MIN || module >= SLEEP_RETENTION_MODULE_MAX) { return ESP_ERR_INVALID_ARG; } @@ -859,7 +863,7 @@ esp_err_t sleep_retention_module_allocate(sleep_retention_module_t module) static esp_err_t sleep_retention_passive_module_free(sleep_retention_module_t module) { - assert(module >= SLEEP_RETENTION_MODULE_MIN && module <= SLEEP_RETENTION_MODULE_MAX); + assert(module >= SLEEP_RETENTION_MODULE_MIN && module < SLEEP_RETENTION_MODULE_MAX); esp_err_t err = ESP_OK; _lock_acquire_recursive(&s_retention.lock); @@ -887,7 +891,7 @@ static esp_err_t sleep_retention_passive_module_free(sleep_retention_module_t mo esp_err_t sleep_retention_module_free(sleep_retention_module_t module) { - if (module < SLEEP_RETENTION_MODULE_MIN || module > SLEEP_RETENTION_MODULE_MAX) { + if (module < SLEEP_RETENTION_MODULE_MIN || module >= SLEEP_RETENTION_MODULE_MAX) { return ESP_ERR_INVALID_ARG; } diff --git a/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in index b720ab1c1d7..b0b14a32b3e 100644 --- a/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in @@ -1415,10 +1415,6 @@ config SOC_PM_PMU_MIN_SLP_SLOW_CLK_CYCLE_FIXED bool default y -config SOC_PM_RETENTION_MODULE_NUM - int - default 32 - config SOC_CLK_RC_FAST_SUPPORT_CALIBRATION bool default y diff --git a/components/soc/esp32c5/include/soc/retention_periph_defs.h b/components/soc/esp32c5/include/soc/retention_periph_defs.h index 0f021d3a913..36134f48076 100644 --- a/components/soc/esp32c5/include/soc/retention_periph_defs.h +++ b/components/soc/esp32c5/include/soc/retention_periph_defs.h @@ -7,7 +7,6 @@ #pragma once #include -#include "soc_caps.h" #ifdef __cplusplus extern "C" { @@ -54,7 +53,7 @@ typedef enum periph_retention_module { SLEEP_RETENTION_MODULE_802154_MAC = 30, SLEEP_RETENTION_MODULE_MODEM_PHY = 31, - SLEEP_RETENTION_MODULE_MAX = SOC_PM_RETENTION_MODULE_NUM - 1 + SLEEP_RETENTION_MODULE_MAX, } periph_retention_module_t; #define is_top_domain_module(m) \ diff --git a/components/soc/esp32c5/include/soc/soc_caps.h b/components/soc/esp32c5/include/soc/soc_caps.h index 03ce4f17ea6..200c7f46d36 100644 --- a/components/soc/esp32c5/include/soc/soc_caps.h +++ b/components/soc/esp32c5/include/soc/soc_caps.h @@ -591,7 +591,6 @@ #define SOC_PM_PAU_REGDMA_UPDATE_CACHE_BEFORE_WAIT_COMPARE (1) #define SOC_PM_PMU_MIN_SLP_SLOW_CLK_CYCLE_FIXED (1) -#define SOC_PM_RETENTION_MODULE_NUM (32) /*-------------------------- CLOCK SUBSYSTEM CAPS ----------------------------------------*/ #define SOC_CLK_RC_FAST_SUPPORT_CALIBRATION (1) diff --git a/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in index 232f8eb1f88..b37df3d2668 100644 --- a/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in @@ -1475,10 +1475,6 @@ config SOC_PM_PMU_MIN_SLP_SLOW_CLK_CYCLE_FIXED bool default y -config SOC_PM_RETENTION_MODULE_NUM - int - default 32 - config SOC_CLK_RC_FAST_SUPPORT_CALIBRATION bool default y diff --git a/components/soc/esp32c6/include/soc/retention_periph_defs.h b/components/soc/esp32c6/include/soc/retention_periph_defs.h index ad485f09998..4b3bfa3a663 100644 --- a/components/soc/esp32c6/include/soc/retention_periph_defs.h +++ b/components/soc/esp32c6/include/soc/retention_periph_defs.h @@ -7,7 +7,6 @@ #pragma once #include -#include "soc_caps.h" #ifdef __cplusplus extern "C" { @@ -56,7 +55,7 @@ typedef enum periph_retention_module { SLEEP_RETENTION_MODULE_802154_MAC = 30, SLEEP_RETENTION_MODULE_PHY_FE = 31, - SLEEP_RETENTION_MODULE_MAX = SOC_PM_RETENTION_MODULE_NUM - 1 + SLEEP_RETENTION_MODULE_MAX, } periph_retention_module_t; #define is_top_domain_module(m) \ diff --git a/components/soc/esp32c6/include/soc/soc_caps.h b/components/soc/esp32c6/include/soc/soc_caps.h index 2d998d465fd..82b0e1a0766 100644 --- a/components/soc/esp32c6/include/soc/soc_caps.h +++ b/components/soc/esp32c6/include/soc/soc_caps.h @@ -575,7 +575,6 @@ #define SOC_PM_PAU_REGDMA_UPDATE_CACHE_BEFORE_WAIT_COMPARE (1) #define SOC_PM_PMU_MIN_SLP_SLOW_CLK_CYCLE_FIXED (1) -#define SOC_PM_RETENTION_MODULE_NUM (32) /*-------------------------- CLOCK SUBSYSTEM CAPS ----------------------------------------*/ #define SOC_CLK_RC_FAST_SUPPORT_CALIBRATION (1) diff --git a/components/soc/esp32c61/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c61/include/soc/Kconfig.soc_caps.in index 7b535111908..fe1671550a9 100644 --- a/components/soc/esp32c61/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c61/include/soc/Kconfig.soc_caps.in @@ -1015,10 +1015,6 @@ config SOC_PM_PMU_MIN_SLP_SLOW_CLK_CYCLE_FIXED bool default y -config SOC_PM_RETENTION_MODULE_NUM - int - default 32 - config SOC_CLK_RC_FAST_SUPPORT_CALIBRATION bool default y diff --git a/components/soc/esp32c61/include/soc/retention_periph_defs.h b/components/soc/esp32c61/include/soc/retention_periph_defs.h index c64b243b6e9..d0923a33a39 100644 --- a/components/soc/esp32c61/include/soc/retention_periph_defs.h +++ b/components/soc/esp32c61/include/soc/retention_periph_defs.h @@ -7,7 +7,6 @@ #pragma once #include -#include "soc_caps.h" #ifdef __cplusplus extern "C" { @@ -47,7 +46,7 @@ typedef enum periph_retention_module { SLEEP_RETENTION_MODULE_BT_BB = 29, SLEEP_RETENTION_MODULE_802154_MAC = 30, - SLEEP_RETENTION_MODULE_MAX = SOC_PM_RETENTION_MODULE_NUM - 1 + SLEEP_RETENTION_MODULE_MAX, } periph_retention_module_t; #define is_top_domain_module(m) \ diff --git a/components/soc/esp32c61/include/soc/soc_caps.h b/components/soc/esp32c61/include/soc/soc_caps.h index 371722a67b7..beaafc07315 100644 --- a/components/soc/esp32c61/include/soc/soc_caps.h +++ b/components/soc/esp32c61/include/soc/soc_caps.h @@ -458,7 +458,6 @@ #define SOC_PM_PAU_REGDMA_UPDATE_CACHE_BEFORE_WAIT_COMPARE (1) #define SOC_PM_PMU_MIN_SLP_SLOW_CLK_CYCLE_FIXED (1) -#define SOC_PM_RETENTION_MODULE_NUM (32) /*-------------------------- CLOCK SUBSYSTEM CAPS ----------------------------------------*/ #define SOC_CLK_RC_FAST_SUPPORT_CALIBRATION (1) diff --git a/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in b/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in index e9455a8a01b..8be698fb681 100644 --- a/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in @@ -1423,10 +1423,6 @@ config SOC_PM_PAU_REGDMA_UPDATE_CACHE_BEFORE_WAIT_COMPARE bool default y -config SOC_PM_RETENTION_MODULE_NUM - int - default 32 - config SOC_EXT_MEM_CACHE_TAG_IN_CPU_DOMAIN bool default y diff --git a/components/soc/esp32h2/include/soc/retention_periph_defs.h b/components/soc/esp32h2/include/soc/retention_periph_defs.h index cb32eff66c0..ba48fef0941 100644 --- a/components/soc/esp32h2/include/soc/retention_periph_defs.h +++ b/components/soc/esp32h2/include/soc/retention_periph_defs.h @@ -7,7 +7,6 @@ #pragma once #include -#include "soc_caps.h" #ifdef __cplusplus extern "C" { @@ -53,7 +52,7 @@ typedef enum periph_retention_module { SLEEP_RETENTION_MODULE_BT_BB = 29, SLEEP_RETENTION_MODULE_802154_MAC = 30, - SLEEP_RETENTION_MODULE_MAX = SOC_PM_RETENTION_MODULE_NUM - 1 + SLEEP_RETENTION_MODULE_MAX, } periph_retention_module_t; #define is_top_domain_module(m) \ diff --git a/components/soc/esp32h2/include/soc/soc_caps.h b/components/soc/esp32h2/include/soc/soc_caps.h index ce6be19ed0d..f170e737464 100644 --- a/components/soc/esp32h2/include/soc/soc_caps.h +++ b/components/soc/esp32h2/include/soc/soc_caps.h @@ -574,8 +574,6 @@ #define SOC_PM_PAU_REGDMA_UPDATE_CACHE_BEFORE_WAIT_COMPARE (1) -#define SOC_PM_RETENTION_MODULE_NUM (32) - #define SOC_EXT_MEM_CACHE_TAG_IN_CPU_DOMAIN (1) #define SOC_PM_CPU_RETENTION_BY_SW (1) #define SOC_PM_MODEM_RETENTION_BY_REGDMA (1) diff --git a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in index d84e79e68a2..b2d6761021d 100644 --- a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in @@ -2051,10 +2051,6 @@ config SOC_SLEEP_TGWDT_STOP_WORKAROUND bool default y -config SOC_PM_RETENTION_MODULE_NUM - int - default 64 - config SOC_PSRAM_VDD_POWER_MPLL bool default y diff --git a/components/soc/esp32p4/include/soc/retention_periph_defs.h b/components/soc/esp32p4/include/soc/retention_periph_defs.h index c35e5effa79..973334d3ed0 100644 --- a/components/soc/esp32p4/include/soc/retention_periph_defs.h +++ b/components/soc/esp32p4/include/soc/retention_periph_defs.h @@ -7,7 +7,6 @@ #pragma once #include -#include "soc_caps.h" #ifdef __cplusplus extern "C" { @@ -63,7 +62,7 @@ typedef enum periph_retention_module { SLEEP_RETENTION_MODULE_DMA2D = 41, SLEEP_RETENTION_MODULE_PPA = 42, - SLEEP_RETENTION_MODULE_MAX = SOC_PM_RETENTION_MODULE_NUM - 1 + SLEEP_RETENTION_MODULE_MAX, } periph_retention_module_t; #define is_top_domain_module(m) \ diff --git a/components/soc/esp32p4/include/soc/soc_caps.h b/components/soc/esp32p4/include/soc/soc_caps.h index 7751e8ba02b..b7b002e2eee 100644 --- a/components/soc/esp32p4/include/soc/soc_caps.h +++ b/components/soc/esp32p4/include/soc/soc_caps.h @@ -757,7 +757,6 @@ #define SOC_SLEEP_SYSTIMER_STALL_WORKAROUND 1 //TODO IDF-11381: replace with all xtal field clk gate control #define SOC_SLEEP_TGWDT_STOP_WORKAROUND 1 //TODO IDF-11381: replace with all xtal field clk gate control -#define SOC_PM_RETENTION_MODULE_NUM (64) /*-------------------------- PSRAM CAPS ----------------------------*/ #define SOC_PSRAM_VDD_POWER_MPLL (1) diff --git a/components/soc/include/soc/regdma.h b/components/soc/include/soc/regdma.h index cc0a322f159..1c3d6c4d90e 100644 --- a/components/soc/include/soc/regdma.h +++ b/components/soc/include/soc/regdma.h @@ -18,6 +18,8 @@ extern "C" { #if SOC_PAU_SUPPORTED +#include "soc/retention_periph_defs.h" + #define REGDMA_LINK_ENTRY_NUM (SOC_PM_PAU_LINK_NUM) /* Maximum number of REG DMA linked list entries */ #ifndef ARRAY_SIZE @@ -179,15 +181,15 @@ typedef struct regdma_link_branch_write_wait_body { volatile uint32_t mask; } regdma_link_branch_write_wait_body_t; -ESP_STATIC_ASSERT(REGDMA_LINK_ENTRY_NUM <= 16, "regdma link entry number should equal to and less than 16"); +ESP_STATIC_ASSERT(REGDMA_LINK_ENTRY_NUM < 16, "regdma link entry number must be less than 16 to pack module into stats"); typedef struct regdma_link_stats { volatile uint32_t ref: REGDMA_LINK_ENTRY_NUM, /* a bitmap, identifies which entry has referenced the current link */ -#if REGDMA_LINK_ENTRY_NUM < 16 - reserve: 16-REGDMA_LINK_ENTRY_NUM, -#endif + module: 16 - REGDMA_LINK_ENTRY_NUM, /* module id; width leaves room beside ref within the low 16 bits */ id: 16; /* REGDMA linked list node unique identifier */ - volatile int module; /* a number used to identify the module to which the current node belongs */ } regdma_link_stats_t; +ESP_STATIC_ASSERT(sizeof(regdma_link_stats_t) == 4, "regdma_link_stats_t must be 4 bytes"); +ESP_STATIC_ASSERT(SLEEP_RETENTION_MODULE_MAX < (1u << (16 - REGDMA_LINK_ENTRY_NUM)), + "module id exceeds bitfield width"); typedef struct regdma_link_continuous { regdma_link_stats_t stat; From 4cd8895f1f4f70890df2f4b5a887223a0f0275cb Mon Sep 17 00:00:00 2001 From: wuzhenghui Date: Mon, 10 Aug 2026 22:04:28 +0800 Subject: [PATCH 2/6] change(esp_hw_support): optimize sleep_phy retention static RAM cost --- .../lowpower/port/esp32c5/sleep_phy.c | 13 +++++++++++-- .../lowpower/port/esp32c6/sleep_phy.c | 19 ++++++++++++++----- .../lowpower/port/esp32c61/sleep_phy.c | 13 +++++++++++-- 3 files changed, 36 insertions(+), 9 deletions(-) diff --git a/components/esp_hw_support/lowpower/port/esp32c5/sleep_phy.c b/components/esp_hw_support/lowpower/port/esp32c5/sleep_phy.c index 72b0879912a..0b3ab248187 100644 --- a/components/esp_hw_support/lowpower/port/esp32c5/sleep_phy.c +++ b/components/esp_hw_support/lowpower/port/esp32c5/sleep_phy.c @@ -3,6 +3,8 @@ * * SPDX-License-Identifier: Apache-2.0 */ +#include +#include #include "esp_log.h" #include "esp_check.h" #include "esp_attr.h" @@ -49,7 +51,7 @@ static esp_err_t sleep_phy_retention_init(void *arg) { #define WIFIMAC_ENTRY() (BIT(SOC_PM_PAU_REGDMA_LINK_IDX_WIFIMAC)) - static sleep_retention_entries_config_t wifi_modem_config[] = { + static const sleep_retention_entries_config_t wifi_modem_config_template[] = { [0] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_PHY_LINK(0x00), MODEM_LPCON_CLK_CONF_REG, MODEM_LPCON_CLK_I2C_MST_EN, MODEM_LPCON_CLK_I2C_MST_EN_M, 1, 0), .owner = WIFIMAC_ENTRY() }, /* I2C MST enable */ /* PMU or software to trigger enable RF PHY */ @@ -87,10 +89,17 @@ static esp_err_t sleep_phy_retention_init(void *arg) [24] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_PHY_LINK(0x18), PMU_SLP_WAKEUP_CNTL7_REG, 0x200000, 0xffff0000, 1, 0), .owner = WIFIMAC_ENTRY() }, [25] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_PHY_LINK(0x19), PMU_SLP_WAKEUP_CNTL7_REG, 0x9730000, 0xffff0000, 0, 1), .owner = WIFIMAC_ENTRY() } }; + sleep_retention_entries_config_t *wifi_modem_config = malloc(sizeof(wifi_modem_config_template)); + if (wifi_modem_config == NULL) { + return ESP_ERR_NO_MEM; + } + memcpy(wifi_modem_config, wifi_modem_config_template, sizeof(wifi_modem_config_template)); + extern uint32_t phy_ana_i2c_master_burst_rf_onoff(bool on); wifi_modem_config[4].config.write_wait.value = phy_ana_i2c_master_burst_rf_onoff(true); wifi_modem_config[15].config.write_wait.value = phy_ana_i2c_master_burst_rf_onoff(false); - esp_err_t err = sleep_retention_entries_create(wifi_modem_config, ARRAY_SIZE(wifi_modem_config), 7, SLEEP_RETENTION_MODULE_MODEM_PHY); + esp_err_t err = sleep_retention_entries_create(wifi_modem_config, ARRAY_SIZE(wifi_modem_config_template), 7, SLEEP_RETENTION_MODULE_MODEM_PHY); + free(wifi_modem_config); ESP_RETURN_ON_ERROR(err, TAG, "failed to allocate modem phy link for wifi modem state"); return ESP_OK; } diff --git a/components/esp_hw_support/lowpower/port/esp32c6/sleep_phy.c b/components/esp_hw_support/lowpower/port/esp32c6/sleep_phy.c index ad22ebc030c..d079b98f8d6 100644 --- a/components/esp_hw_support/lowpower/port/esp32c6/sleep_phy.c +++ b/components/esp_hw_support/lowpower/port/esp32c6/sleep_phy.c @@ -3,6 +3,8 @@ * * SPDX-License-Identifier: Apache-2.0 */ +#include +#include #include "esp_attr.h" #include "soc/soc_caps.h" @@ -51,7 +53,7 @@ esp_err_t sleep_phy_link_init(void **link_context) esp_err_t err = ESP_OK; #if SOC_PM_PAU_REGDMA_LINK_MODEM - static regdma_link_config_t phy_modem_config[] = { + static const regdma_link_config_t wifi_modem_config_template[] = { [0] = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_MODEM_FE_LINK(0), MODEM_FE_DATA_BASE, MODEM_FE_DATA_BASE, 41, 0, 0), [1] = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_MODEM_FE_LINK(1), MODEM_FE_CTRL_BASE, MODEM_FE_CTRL_BASE, 87, 0, 0), @@ -106,13 +108,19 @@ esp_err_t sleep_phy_link_init(void **link_context) [39] = REGDMA_LINK_WRITE_INIT(REGDMA_PHY_LINK(0x25), PMU_SLP_WAKEUP_CNTL7_REG, 0x200000, 0xffff0000, 1, 0), [40] = REGDMA_LINK_WRITE_INIT(REGDMA_PHY_LINK(0x26), PMU_SLP_WAKEUP_CNTL7_REG, 0x9730000, 0xffff0000, 0, 1) }; + regdma_link_config_t *wifi_modem_config = malloc(sizeof(wifi_modem_config_template)); + if (wifi_modem_config == NULL) { + return ESP_ERR_NO_MEM; + } + memcpy(wifi_modem_config, wifi_modem_config_template, sizeof(wifi_modem_config_template)); + extern uint32_t phy_ana_i2c_master_burst_rf_onoff(bool on); - phy_modem_config[8].write_wait.value = phy_ana_i2c_master_burst_rf_onoff(true); - phy_modem_config[24].write_wait.value = phy_ana_i2c_master_burst_rf_onoff(false); + wifi_modem_config[8].write_wait.value = phy_ana_i2c_master_burst_rf_onoff(true); + wifi_modem_config[24].write_wait.value = phy_ana_i2c_master_burst_rf_onoff(false); void *link = NULL; - for (int i = ARRAY_SIZE(phy_modem_config) - 1; (err == ESP_OK) && (i >= 0); i--) { - void *next = regdma_link_init_safe(&phy_modem_config[i], false, 0, link); + for (int i = ARRAY_SIZE(wifi_modem_config) - 1; (err == ESP_OK) && (i >= 0); i--) { + void *next = regdma_link_init_safe(&wifi_modem_config[i], false, 0, link); if (next) { link = next; } else { @@ -120,6 +128,7 @@ esp_err_t sleep_phy_link_init(void **link_context) err = ESP_ERR_NO_MEM; } } + free(wifi_modem_config); if (err == ESP_OK) { pau_regdma_set_modem_link_addr(link); diff --git a/components/esp_hw_support/lowpower/port/esp32c61/sleep_phy.c b/components/esp_hw_support/lowpower/port/esp32c61/sleep_phy.c index 3205314f40c..c723eb37d06 100644 --- a/components/esp_hw_support/lowpower/port/esp32c61/sleep_phy.c +++ b/components/esp_hw_support/lowpower/port/esp32c61/sleep_phy.c @@ -3,6 +3,8 @@ * * SPDX-License-Identifier: Apache-2.0 */ +#include +#include #include "esp_attr.h" #include "soc/soc_caps.h" @@ -44,7 +46,7 @@ esp_err_t sleep_phy_link_init(void **link_context) esp_err_t err = ESP_OK; #if SOC_PM_PAU_REGDMA_LINK_WIFIMAC - static regdma_link_config_t wifi_modem_config[] = { + static const regdma_link_config_t wifi_modem_config_template[] = { [0] = REGDMA_LINK_WRITE_INIT(REGDMA_PHY_LINK(0x00), MODEM_LPCON_CLK_CONF_REG, MODEM_LPCON_CLK_I2C_MST_EN, MODEM_LPCON_CLK_I2C_MST_EN_M, 1, 0), /* I2C MST enable */ /* PMU or software to trigger enable RF PHY */ @@ -94,12 +96,18 @@ esp_err_t sleep_phy_link_init(void **link_context) [34] = REGDMA_LINK_WRITE_INIT(REGDMA_PHY_LINK(0x22), PMU_SLP_WAKEUP_CNTL7_REG, 0x200000, 0xffff0000, 1, 0), [35] = REGDMA_LINK_WRITE_INIT(REGDMA_PHY_LINK(0x23), PMU_SLP_WAKEUP_CNTL7_REG, 0x9730000, 0xffff0000, 0, 1) }; + regdma_link_config_t *wifi_modem_config = malloc(sizeof(wifi_modem_config_template)); + if (wifi_modem_config == NULL) { + return ESP_ERR_NO_MEM; + } + memcpy(wifi_modem_config, wifi_modem_config_template, sizeof(wifi_modem_config_template)); + extern uint32_t phy_ana_i2c_master_burst_rf_onoff(bool on); wifi_modem_config[4].write_wait.value = phy_ana_i2c_master_burst_rf_onoff(true); wifi_modem_config[19].write_wait.value = phy_ana_i2c_master_burst_rf_onoff(false); void *link = NULL; - for (int i = ARRAY_SIZE(wifi_modem_config) - 1; (err == ESP_OK) && (i >= 0); i--) { + for (int i = ARRAY_SIZE(wifi_modem_config_template) - 1; (err == ESP_OK) && (i >= 0); i--) { void *next = regdma_link_init_safe(&wifi_modem_config[i], false, 0, link); if (next) { link = next; @@ -108,6 +116,7 @@ esp_err_t sleep_phy_link_init(void **link_context) err = ESP_ERR_NO_MEM; } } + free(wifi_modem_config); if (err == ESP_OK) { pau_regdma_set_modem_link_addr(link); From bb6411463a867146b70cee8cfe51f60d47b7171a Mon Sep 17 00:00:00 2001 From: wuzhenghui Date: Mon, 10 Aug 2026 22:06:00 +0800 Subject: [PATCH 3/6] change(esp_hw_support): optimize pmu_sleep RAM cost (cherry picked from commit 3c2a0cb4f64b34bc153d4ddf29ead6aabb2d39ef) --- components/esp_hw_support/linker.lf | 8 +++++++- components/esp_hw_support/port/esp32h2/pmu_sleep.c | 2 +- components/hal/esp32c5/include/hal/lp_aon_ll.h | 3 ++- components/hal/esp32c6/include/hal/lp_aon_ll.h | 3 ++- components/hal/esp32c61/include/hal/lp_aon_ll.h | 3 ++- components/hal/esp32h2/include/hal/lp_aon_ll.h | 3 ++- 6 files changed, 16 insertions(+), 6 deletions(-) diff --git a/components/esp_hw_support/linker.lf b/components/esp_hw_support/linker.lf index 7aa7f6cb162..4854f086a3c 100644 --- a/components/esp_hw_support/linker.lf +++ b/components/esp_hw_support/linker.lf @@ -21,7 +21,13 @@ entries: rtc_sleep (noflash_text) rtc_time (noflash_text) if SOC_PMU_SUPPORTED = y && SOC_LIGHT_SLEEP_SUPPORTED = y: - pmu_sleep (noflash) + if SPIRAM_FLASH_LOAD_TO_PSRAM = y || PM_SLP_IRAM_OPT = y: + pmu_sleep (noflash) + else: + if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE != y: + pmu_sleep:pmu_sleep_start (noflash) + pmu_sleep:pmu_sleep_finish (noflash) + pmu_sleep:pmu_sleep_get_wakup_retention_cost (noflash) sleep_mspi (noflash) if SPIRAM_FLASH_LOAD_TO_PSRAM = y: pmu_init (noflash) diff --git a/components/esp_hw_support/port/esp32h2/pmu_sleep.c b/components/esp_hw_support/port/esp32h2/pmu_sleep.c index 4cdd6880513..42af9c02da6 100644 --- a/components/esp_hw_support/port/esp32h2/pmu_sleep.c +++ b/components/esp_hw_support/port/esp32h2/pmu_sleep.c @@ -57,7 +57,7 @@ void pmu_sleep_enable_regdma_backup(void) pmu_hal_hp_set_sleep_active_backup_enable(PMU_instance()->hal); } -void pmu_sleep_disable_regdma_backup(void) +IRAM_ATTR void pmu_sleep_disable_regdma_backup(void) { assert(PMU_instance()->hal); pmu_hal_hp_set_sleep_active_backup_disable(PMU_instance()->hal); diff --git a/components/hal/esp32c5/include/hal/lp_aon_ll.h b/components/hal/esp32c5/include/hal/lp_aon_ll.h index 62a9d630bc8..9739c760ffa 100644 --- a/components/hal/esp32c5/include/hal/lp_aon_ll.h +++ b/components/hal/esp32c5/include/hal/lp_aon_ll.h @@ -12,6 +12,7 @@ #include "soc/soc.h" #include "soc/lp_aon_struct.h" #include "hal/misc.h" +#include "esp_attr.h" #include "esp32c5/rom/rtc.h" @@ -75,7 +76,7 @@ static inline uint32_t lp_aon_ll_ext1_get_wakeup_pins(void) * Set the flag to inform * @param true: deepsleep false: lightsleep */ -static inline void lp_aon_ll_inform_wakeup_type(bool dslp) +FORCE_INLINE_ATTR void lp_aon_ll_inform_wakeup_type(bool dslp) { if (dslp) { REG_SET_BIT(RTC_SLEEP_MODE_REG, BIT(0)); /* Tell rom to run deep sleep wake stub */ diff --git a/components/hal/esp32c6/include/hal/lp_aon_ll.h b/components/hal/esp32c6/include/hal/lp_aon_ll.h index 87c73b489ee..c457a36b47d 100644 --- a/components/hal/esp32c6/include/hal/lp_aon_ll.h +++ b/components/hal/esp32c6/include/hal/lp_aon_ll.h @@ -12,6 +12,7 @@ #include "soc/soc.h" #include "soc/lp_aon_struct.h" #include "hal/misc.h" +#include "esp_attr.h" #include "esp32c6/rom/rtc.h" @@ -75,7 +76,7 @@ static inline uint32_t lp_aon_ll_ext1_get_wakeup_pins(void) * Set the flag to inform * @param true: deepsleep false: lightsleep */ -static inline void lp_aon_ll_inform_wakeup_type(bool dslp) +FORCE_INLINE_ATTR void lp_aon_ll_inform_wakeup_type(bool dslp) { if (dslp) { REG_SET_BIT(RTC_SLEEP_MODE_REG, BIT(0)); /* Tell rom to run deep sleep wake stub */ diff --git a/components/hal/esp32c61/include/hal/lp_aon_ll.h b/components/hal/esp32c61/include/hal/lp_aon_ll.h index 1cb447faade..864d6427831 100644 --- a/components/hal/esp32c61/include/hal/lp_aon_ll.h +++ b/components/hal/esp32c61/include/hal/lp_aon_ll.h @@ -12,6 +12,7 @@ #include "soc/soc.h" #include "soc/lp_aon_struct.h" #include "hal/misc.h" +#include "esp_attr.h" #include "esp32c61/rom/rtc.h" @@ -75,7 +76,7 @@ static inline uint32_t lp_aon_ll_ext1_get_wakeup_pins(void) * Set the flag to inform * @param true: deepsleep false: lightsleep */ -static inline void lp_aon_ll_inform_wakeup_type(bool dslp) +FORCE_INLINE_ATTR void lp_aon_ll_inform_wakeup_type(bool dslp) { if (dslp) { REG_SET_BIT(RTC_SLEEP_MODE_REG, BIT(0)); /* Tell rom to run deep sleep wake stub */ diff --git a/components/hal/esp32h2/include/hal/lp_aon_ll.h b/components/hal/esp32h2/include/hal/lp_aon_ll.h index 1b4fa75a3c2..92faa21c642 100644 --- a/components/hal/esp32h2/include/hal/lp_aon_ll.h +++ b/components/hal/esp32h2/include/hal/lp_aon_ll.h @@ -12,6 +12,7 @@ #include "soc/soc.h" #include "soc/lp_aon_struct.h" #include "hal/misc.h" +#include "esp_attr.h" #include "esp32h2/rom/rtc.h" @@ -75,7 +76,7 @@ static inline uint32_t lp_aon_ll_ext1_get_wakeup_pins(void) * Set the flag to inform * @param true: deepsleep false: lightsleep */ -static inline void lp_aon_ll_inform_wakeup_type(bool dslp) +FORCE_INLINE_ATTR void lp_aon_ll_inform_wakeup_type(bool dslp) { if (dslp) { REG_SET_BIT(RTC_SLEEP_MODE_REG, BIT(0)); /* Tell rom to run deep sleep wake stub */ From 070ae7df8da7814d409da24cc0c4a74294a3888f Mon Sep 17 00:00:00 2001 From: wuzhenghui Date: Tue, 25 Aug 2026 21:11:05 +0800 Subject: [PATCH 4/6] feat(esp_hw_support): use dynamic memory allocation for retention module instances (cherry picked from commit a9dee592d6e56098289b2d5579915724aca2a51f) Co-authored-by: Cursor --- components/esp_hw_support/sleep_retention.c | 128 ++++++++++++++------ 1 file changed, 89 insertions(+), 39 deletions(-) diff --git a/components/esp_hw_support/sleep_retention.c b/components/esp_hw_support/sleep_retention.c index 81e6a2c753e..26a2388d07b 100644 --- a/components/esp_hw_support/sleep_retention.c +++ b/components/esp_hw_support/sleep_retention.c @@ -110,6 +110,7 @@ static inline sleep_retention_module_attribute_t get_attributes(struct sleep_ret static inline bool module_is_passive(struct sleep_retention_module_object * const self) { + assert(self); return (get_attributes(self) & SLEEP_RETENTION_MODULE_ATTR_PASSIVE) ? true : false; } @@ -199,7 +200,7 @@ typedef struct { sleep_retention_module_bitmap_t inited_modules; sleep_retention_module_bitmap_t created_modules; - struct sleep_retention_module_object instance[SLEEP_RETENTION_MODULE_MAX]; + struct sleep_retention_module_object *instance[SLEEP_RETENTION_MODULE_MAX]; #define EXTRA_LINK_NUM (REGDMA_LINK_ENTRY_NUM - 1) } sleep_retention_t; @@ -213,6 +214,33 @@ static DRAM_ATTR __attribute__((unused)) sleep_retention_t s_retention = { #define SLEEP_RETENTION_ENTRY_BITMAP_MASK (BIT(REGDMA_LINK_ENTRY_NUM) - 1) #define SLEEP_RETENTION_ENTRY_BITMAP(bitmap) ((bitmap) & SLEEP_RETENTION_ENTRY_BITMAP_MASK) + +static struct sleep_retention_module_object * instance(sleep_retention_module_t module) +{ + return (module >= SLEEP_RETENTION_MODULE_MAX) ? NULL : s_retention.instance[module]; +} + +static esp_err_t instance_allocate(sleep_retention_module_t module) +{ + if (s_retention.instance[module] != NULL) { + return ESP_ERR_INVALID_STATE; + } + struct sleep_retention_module_object *obj = (struct sleep_retention_module_object *)heap_caps_calloc( + 1, sizeof(struct sleep_retention_module_object), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); + if (obj == NULL) { + return ESP_ERR_NO_MEM; + } + s_retention.instance[module] = obj; + return ESP_OK; +} + +static void instance_free(sleep_retention_module_t module) +{ + heap_caps_free(s_retention.instance[module]); + s_retention.instance[module] = NULL; +} + + static esp_err_t sleep_retention_entries_create_impl(const sleep_retention_entries_config_t retent[], int num, regdma_link_priority_t priority, sleep_retention_module_t module); static void sleep_retention_entries_join(void); @@ -518,7 +546,7 @@ static void sleep_retention_entries_destroy(sleep_retention_module_t module) } if (created_modules == 0) { sleep_retention_entries_check_and_distroy_final_default(); - pmu_sleep_disable_regdma_backup(); +pmu_sleep_disable_regdma_backup(); memset((void *)s_retention.lists, 0, sizeof(s_retention.lists)); s_retention.highpri = (uint8_t)-1; } @@ -645,7 +673,7 @@ esp_err_t sleep_retention_entries_create(const sleep_retention_entries_config_t if (err) goto error; err = sleep_retention_entries_create_wrapper(retent, num, priority, module); if (err) goto error; - pmu_sleep_enable_regdma_backup(); +pmu_sleep_enable_regdma_backup(); ESP_ERROR_CHECK(esp_deep_sleep_register_hook(&pmu_sleep_disable_regdma_backup)); error: @@ -753,10 +781,14 @@ esp_err_t sleep_retention_module_init(sleep_retention_module_t module, sleep_ret if (module_is_created(module) || module_is_inited(module)) { err = ESP_ERR_INVALID_STATE; } else { - sleep_retention_module_object_ctor(&s_retention.instance[module], ¶m->cbs); - set_dependencies(&s_retention.instance[module], param->depends); - set_attributes(&s_retention.instance[module], param->attribute); - s_retention.inited_modules.bitmap[module >> 5] |= BIT(module % 32); + err = instance_allocate(module); + if (err == ESP_OK) { + struct sleep_retention_module_object *mod = instance(module); + sleep_retention_module_object_ctor(mod, ¶m->cbs); + set_dependencies(mod, param->depends); + set_attributes(mod, param->attribute); + s_retention.inited_modules.bitmap[module >> 5] |= BIT(module % 32); + } } _lock_release_recursive(&s_retention.lock); return err; @@ -774,9 +806,11 @@ esp_err_t sleep_retention_module_deinit(sleep_retention_module_t module) if (module_is_created(module) || !module_is_inited(module)) { err = ESP_ERR_INVALID_STATE; } else { - clr_attributes(&s_retention.instance[module]); - clr_dependencies(&s_retention.instance[module]); - sleep_retention_module_object_dtor(&s_retention.instance[module]); + struct sleep_retention_module_object *mod = instance(module); + clr_attributes(mod); + clr_dependencies(mod); + sleep_retention_module_object_dtor(mod); + instance_free(module); s_retention.inited_modules.bitmap[module >> 5] &= ~BIT(module % 32); uint32_t inited_modules = 0; for (int i = 0; i < SLEEP_RETENTION_MODULE_BITMAP_SZ; i++) { @@ -799,23 +833,26 @@ static esp_err_t sleep_retention_passive_module_allocate(sleep_retention_module_ esp_err_t err = ESP_OK; _lock_acquire_recursive(&s_retention.lock); - assert(module_is_passive(&s_retention.instance[module]) && "Illegal dependency"); assert(module_is_inited(module) && "All passive module must be inited first!"); + struct sleep_retention_module_object *mod = instance(module); + assert(module_is_passive(mod) && "Illegal dependency"); if (!module_is_created(module)) { - sleep_retention_module_bitmap_t depends = get_dependencies(&s_retention.instance[module]); + sleep_retention_module_bitmap_t depends = get_dependencies(mod); for (int i = 0; ((err == ESP_OK) && (i < SLEEP_RETENTION_MODULE_BITMAP_SZ)); i++) { uint32_t bitmap = depends.bitmap[i]; for (int j = 0; (err == ESP_OK) && bitmap; bitmap >>= 1, j++) { if (bitmap & BIT(0)) { - set_reference(&s_retention.instance[(i << 5) + j], module); - err = sleep_retention_passive_module_allocate((i << 5) + j); + sleep_retention_module_t dep_module = (sleep_retention_module_t)((i << 5) + j); + assert(module_is_inited(dep_module)); + set_reference(instance(dep_module), module); + err = sleep_retention_passive_module_allocate(dep_module); } } } if (err == ESP_OK) { - sleep_retention_callback_t fn = s_retention.instance[module].cbs.create.handle; + sleep_retention_callback_t fn = mod->cbs.create.handle; if (fn) { - err = (*fn)(s_retention.instance[module].cbs.create.arg); + err = (*fn)(mod->cbs.create.arg); } } } @@ -831,31 +868,36 @@ esp_err_t sleep_retention_module_allocate(sleep_retention_module_t module) esp_err_t err = ESP_OK; _lock_acquire_recursive(&s_retention.lock); - if (!module_is_passive(&s_retention.instance[module])) { - if (module_is_inited(module) && !module_is_created(module)) { - sleep_retention_module_bitmap_t depends = get_dependencies(&s_retention.instance[module]); + if (!module_is_inited(module)) { + err = ESP_ERR_INVALID_STATE; + } else { + struct sleep_retention_module_object *mod = instance(module); + if (module_is_passive(mod)) { + err = ESP_ERR_NOT_ALLOWED; + } else if (!module_is_created(module)) { + sleep_retention_module_bitmap_t depends = get_dependencies(mod); for (int i = 0; ((err == ESP_OK) && (i < SLEEP_RETENTION_MODULE_BITMAP_SZ)); i++) { uint32_t bitmap = depends.bitmap[i]; for (int j = 0; (err == ESP_OK) && bitmap; bitmap >>= 1, j++) { if (bitmap & BIT(0)) { - set_reference(&s_retention.instance[(i << 5) + j], module); - if (module_is_passive(&s_retention.instance[(i << 5) + j])) { /* the callee ensures this module is inited */ - err = sleep_retention_passive_module_allocate((i << 5) + j); + sleep_retention_module_t dep_module = (sleep_retention_module_t)((i << 5) + j); + assert(module_is_inited(dep_module)); + set_reference(instance(dep_module), module); + if (module_is_inited(dep_module) && module_is_passive(instance(dep_module))) { + err = sleep_retention_passive_module_allocate(dep_module); } } } } if (err == ESP_OK) { - sleep_retention_callback_t fn = s_retention.instance[module].cbs.create.handle; + sleep_retention_callback_t fn = mod->cbs.create.handle; if (fn) { - err = (*fn)(s_retention.instance[module].cbs.create.arg); + err = (*fn)(mod->cbs.create.arg); } } } else { err = ESP_ERR_INVALID_STATE; } - } else { - err = ESP_ERR_NOT_ALLOWED; } _lock_release_recursive(&s_retention.lock); return err; @@ -867,19 +909,22 @@ static esp_err_t sleep_retention_passive_module_free(sleep_retention_module_t mo esp_err_t err = ESP_OK; _lock_acquire_recursive(&s_retention.lock); - assert(module_is_passive(&s_retention.instance[module]) && "Illegal dependency"); assert(module_is_inited(module) && "All passive module must be inited first!"); + struct sleep_retention_module_object *mod = instance(module); + assert(module_is_passive(mod) && "Illegal dependency"); if (module_is_created(module)) { - if (!references_exist(&s_retention.instance[module])) { + if (!references_exist(mod)) { sleep_retention_entries_destroy(module); - sleep_retention_module_bitmap_t depends = get_dependencies(&s_retention.instance[module]); + sleep_retention_module_bitmap_t depends = get_dependencies(mod); for (int i = 0; ((err == ESP_OK) && (i < SLEEP_RETENTION_MODULE_BITMAP_SZ)); i++) { uint32_t bitmap = depends.bitmap[i]; for (int j = 0; (err == ESP_OK) && bitmap; bitmap >>= 1, j++) { if (bitmap & BIT(0)) { - clr_reference(&s_retention.instance[(i << 5) + j], module); - err = sleep_retention_passive_module_free((i << 5) + j); + sleep_retention_module_t dep_module = (sleep_retention_module_t)((i << 5) + j); + assert(module_is_inited(dep_module)); + clr_reference(instance(dep_module), module); + err = sleep_retention_passive_module_free(dep_module); } } } @@ -897,18 +942,25 @@ esp_err_t sleep_retention_module_free(sleep_retention_module_t module) esp_err_t err = ESP_OK; _lock_acquire_recursive(&s_retention.lock); - if (!module_is_passive(&s_retention.instance[module])) { - if (module_is_inited(module) && module_is_created(module)) { + if (!module_is_inited(module)) { + err = ESP_ERR_INVALID_STATE; + } else { + struct sleep_retention_module_object *mod = instance(module); + if (module_is_passive(mod)) { + err = ESP_ERR_NOT_ALLOWED; + } else if (module_is_created(module)) { sleep_retention_entries_destroy(module); - sleep_retention_module_bitmap_t depends = get_dependencies(&s_retention.instance[module]); + sleep_retention_module_bitmap_t depends = get_dependencies(mod); for (int i = 0; ((err == ESP_OK) && (i < SLEEP_RETENTION_MODULE_BITMAP_SZ)); i++) { uint32_t bitmap = depends.bitmap[i]; for (int j = 0; (err == ESP_OK) && bitmap; bitmap >>= 1, j++) { if (bitmap & BIT(0)) { - clr_reference(&s_retention.instance[(i << 5) + j], module); - if (module_is_passive(&s_retention.instance[(i << 5) + j])) { - err = sleep_retention_passive_module_free((i << 5) + j); + sleep_retention_module_t dep_module = (sleep_retention_module_t)((i << 5) + j); + assert(module_is_inited(dep_module)); + clr_reference(instance(dep_module), module); + if (module_is_inited(dep_module) && module_is_passive(instance(dep_module))) { + err = sleep_retention_passive_module_free(dep_module); } } } @@ -916,8 +968,6 @@ esp_err_t sleep_retention_module_free(sleep_retention_module_t module) } else { err = ESP_ERR_INVALID_STATE; } - } else { - err = ESP_ERR_NOT_ALLOWED; } _lock_release_recursive(&s_retention.lock); return err; From d8d6577c93dc9b35198f73640c5f91b4722261eb Mon Sep 17 00:00:00 2001 From: wuzhenghui Date: Fri, 4 Sep 2026 14:51:17 +0800 Subject: [PATCH 5/6] fix(esp_hw_support): fix regdma link dump to print module number Co-authored-by: Cursor --- components/esp_hw_support/port/regdma_link.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/components/esp_hw_support/port/regdma_link.c b/components/esp_hw_support/port/regdma_link.c index f72c99e13d2..2a1c40a624d 100644 --- a/components/esp_hw_support/port/regdma_link.c +++ b/components/esp_hw_support/port/regdma_link.c @@ -753,7 +753,7 @@ static void print_info_continuous_wrapper(FILE *out, void *link) regdma_link_head_t head = REGDMA_LINK_HEAD(link); regdma_link_continuous_t *cons = __containerof(link, regdma_link_continuous_t, head); fprintf(out, LOG_COLOR_I " [%02d/%04x] link_ptr:%p, head: {mode:%s len:%d branch:%s skip_r:%s skip_b:%s eof:%s}, next:%p, backup start:%p, restore start:%p, buff_ptr:%p\n" LOG_RESET_COLOR, - __builtin_ffs(cons->stat.module) - 1, cons->stat.id, link, + cons->stat.module, cons->stat.id, link, s_link_mode_str[cons->head.mode], cons->head.length, s_boolean_str[cons->head.branch], s_boolean_str[cons->head.skip_r], s_boolean_str[cons->head.skip_b], s_boolean_str[cons->head.eof], cons->body.next, cons->body.backup, cons->body.restore, @@ -766,7 +766,7 @@ static void print_info_addr_map_wrapper(FILE *out, void *link) regdma_link_head_t head = REGDMA_LINK_HEAD(link); regdma_link_addr_map_t *map = __containerof(link, regdma_link_addr_map_t, head); fprintf(out, LOG_COLOR_I " [%02d/%04x] link_ptr:%p, head: {mode:%s len:%d branch:%s skip_r:%s skip_b:%s eof:%s}, next:%p, backup start:%p, restore start:%p, buff_ptr:%p, map:{%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32"}\n" LOG_RESET_COLOR, - __builtin_ffs(map->stat.module) - 1, map->stat.id, link, + map->stat.module, map->stat.id, link, s_link_mode_str[map->head.mode], map->head.length, s_boolean_str[map->head.branch], s_boolean_str[map->head.skip_r], s_boolean_str[map->head.skip_b], s_boolean_str[map->head.eof], map->body.next, map->body.backup, map->body.restore, @@ -778,7 +778,7 @@ static void print_info_write_wait_wrapper(FILE *out, void *link) { regdma_link_write_wait_t *ww = __containerof(link, regdma_link_write_wait_t, head); fprintf(out, LOG_COLOR_I " [%02d/%04x] link_ptr:%p, head: {mode:%s len:%d branch:%s skip_r:%s skip_b:%s eof:%s}, next:%p, backup start:%p, value:%"PRIx32", mask:%"PRIx32"\n" LOG_RESET_COLOR, - __builtin_ffs(ww->stat.module) - 1, ww->stat.id, link, + ww->stat.module, ww->stat.id, link, s_link_mode_str[ww->head.mode], ww->head.length, s_boolean_str[ww->head.branch], s_boolean_str[ww->head.skip_r], s_boolean_str[ww->head.skip_b], s_boolean_str[ww->head.eof], ww->body.next, ww->body.backup, ww->body.value, ww->body.mask); @@ -789,7 +789,7 @@ static void print_info_branch_continuous_wrapper(FILE *out, void *link) regdma_link_head_t head = REGDMA_LINK_HEAD(link); regdma_link_branch_continuous_t *cons = __containerof(link, regdma_link_branch_continuous_t, head); fprintf(out, LOG_COLOR_I " [%02d/%04x] link_ptr:%p, head: {mode:%s len:%d branch:%s skip_r:%s skip_b:%s eof:%s}, next:{%p, %p, %p, %p}, backup start:%p, restore start:%p, buff_ptr:%p\n" LOG_RESET_COLOR, - __builtin_ffs(cons->stat.module) - 1, cons->stat.id, link, + cons->stat.module, cons->stat.id, link, s_link_mode_str[cons->head.mode], cons->head.length, s_boolean_str[cons->head.branch], s_boolean_str[cons->head.skip_r], s_boolean_str[cons->head.skip_b], s_boolean_str[cons->head.eof], cons->body.next[0], cons->body.next[1], cons->body.next[2], cons->body.next[3], cons->body.backup, cons->body.restore, @@ -802,7 +802,7 @@ static void print_info_branch_addr_map_wrapper(FILE *out, void *link) regdma_link_head_t head = REGDMA_LINK_HEAD(link); regdma_link_branch_addr_map_t *map = __containerof(link, regdma_link_branch_addr_map_t, head); fprintf(out, LOG_COLOR_I " [%02d/%04x] link_ptr:%p, head: {mode:%s len:%d branch:%s skip_r:%s skip_b:%s eof:%s}, next:{%p, %p, %p, %p}, backup start:%p, restore start:%p, buff_ptr:%p, map:{%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32"}\n" LOG_RESET_COLOR, - __builtin_ffs(map->stat.module) - 1, map->stat.id, link, + map->stat.module, map->stat.id, link, s_link_mode_str[map->head.mode], map->head.length, s_boolean_str[map->head.branch], s_boolean_str[map->head.skip_r], s_boolean_str[map->head.skip_b], s_boolean_str[map->head.eof], map->body.next[0], map->body.next[1], map->body.next[2], map->body.next[3], map->body.backup, map->body.restore, @@ -814,7 +814,7 @@ static void print_info_branch_write_wait_wrapper(FILE *out, void *link) { regdma_link_branch_write_wait_t *ww = __containerof(link, regdma_link_branch_write_wait_t, head); fprintf(out, LOG_COLOR_I " [%02d/%04x] link_ptr:%p, head: {mode:%s len:%d branch:%s skip_r:%s skip_b:%s eof:%s}, next:{%p, %p, %p, %p}, backup start:%p, value:%"PRIx32", mask:%"PRIx32"\n" LOG_RESET_COLOR, - __builtin_ffs(ww->stat.module) - 1, ww->stat.id, link, + ww->stat.module, ww->stat.id, link, s_link_mode_str[ww->head.mode], ww->head.length, s_boolean_str[ww->head.branch], s_boolean_str[ww->head.skip_r], s_boolean_str[ww->head.skip_b], s_boolean_str[ww->head.eof], ww->body.next[0], ww->body.next[1], ww->body.next[2], ww->body.next[3], ww->body.backup, ww->body.value, ww->body.mask); From b1126f4e6d0e3b1570860492abed78dc1811d7f0 Mon Sep 17 00:00:00 2001 From: wuzhenghui Date: Tue, 15 Sep 2026 18:50:29 +0800 Subject: [PATCH 6/6] fix(esp_hw_support): fix sleep_modem C6 workaround to pmu_sleep cache safe call path --- components/esp_hw_support/linker.lf | 2 ++ components/esp_hw_support/lowpower/port/esp32c6/sleep_phy.c | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/components/esp_hw_support/linker.lf b/components/esp_hw_support/linker.lf index 4854f086a3c..3d9fdc98208 100644 --- a/components/esp_hw_support/linker.lf +++ b/components/esp_hw_support/linker.lf @@ -27,6 +27,8 @@ entries: if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE != y: pmu_sleep:pmu_sleep_start (noflash) pmu_sleep:pmu_sleep_finish (noflash) + if SOC_PM_RETENTION_HAS_CLOCK_BUG = y && ESP_PHY_MAC_BB_PD = y: + pmu_sleep:pmu_sleep_pll_already_enabled (noflash) pmu_sleep:pmu_sleep_get_wakup_retention_cost (noflash) sleep_mspi (noflash) if SPIRAM_FLASH_LOAD_TO_PSRAM = y: diff --git a/components/esp_hw_support/lowpower/port/esp32c6/sleep_phy.c b/components/esp_hw_support/lowpower/port/esp32c6/sleep_phy.c index d079b98f8d6..a53896f042a 100644 --- a/components/esp_hw_support/lowpower/port/esp32c6/sleep_phy.c +++ b/components/esp_hw_support/lowpower/port/esp32c6/sleep_phy.c @@ -119,7 +119,7 @@ esp_err_t sleep_phy_link_init(void **link_context) wifi_modem_config[24].write_wait.value = phy_ana_i2c_master_burst_rf_onoff(false); void *link = NULL; - for (int i = ARRAY_SIZE(wifi_modem_config) - 1; (err == ESP_OK) && (i >= 0); i--) { + for (int i = ARRAY_SIZE(wifi_modem_config_template) - 1; (err == ESP_OK) && (i >= 0); i--) { void *next = regdma_link_init_safe(&wifi_modem_config[i], false, 0, link); if (next) { link = next;