From c4a8b106ce28662df5e62c0160ef0b563f4f76a5 Mon Sep 17 00:00:00 2001 From: Li Shuai Date: Fri, 20 Mar 2026 10:51:20 +0800 Subject: [PATCH 01/22] change(esp_hw_support): duplicate module sleep retention entries context to support module attach and detach --- .../include/esp_private/sleep_retention.h | 18 +- components/esp_hw_support/sleep_retention.c | 533 ++++++++++-------- 2 files changed, 325 insertions(+), 226 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 e10199af0b8..00387b19dae 100644 --- a/components/esp_hw_support/include/esp_private/sleep_retention.h +++ b/components/esp_hw_support/include/esp_private/sleep_retention.h @@ -56,7 +56,8 @@ typedef struct { } sleep_retention_module_callbacks_t; typedef enum { - SLEEP_RETENTION_MODULE_ATTR_PASSIVE = 0x1 + SLEEP_RETENTION_MODULE_ATTR_PASSIVE = 0x1, + SLEEP_RETENTION_MODULE_ATTR_ATTACH = 0x2 } sleep_retention_module_attribute_t; /** @@ -202,6 +203,19 @@ sleep_retention_module_bitmap_t sleep_retention_get_inited_modules(void); */ sleep_retention_module_bitmap_t sleep_retention_get_created_modules(void); +/** + * @brief Get all retainted modules that require sleep retention + * + * This is an unprotected interface for getting a bitmap of all modules that + * require sleep retention. + * + * It can only be called by the sleep procedure. + * + * @return the bitmap for all modules that have successfully created a sleep + * retention context + */ +sleep_retention_module_bitmap_t sleep_retention_get_retained_modules(void); + /** * @brief Get the initialization state of module * @@ -222,6 +236,8 @@ bool sleep_retention_is_module_inited(sleep_retention_module_t module); */ bool sleep_retention_is_module_created(sleep_retention_module_t module); +bool sleep_retention_is_module_attached(sleep_retention_module_t module); + /** * @brief Calculates the bitwise logical and of the module bitmap and return results * diff --git a/components/esp_hw_support/sleep_retention.c b/components/esp_hw_support/sleep_retention.c index eb4232a3e8b..3bcfc7c4094 100644 --- a/components/esp_hw_support/sleep_retention.c +++ b/components/esp_hw_support/sleep_retention.c @@ -108,26 +108,38 @@ static inline sleep_retention_module_attribute_t get_attributes(struct sleep_ret return self->attributes; } +static inline bool module_runtime_attach(struct sleep_retention_module_object * const self) +{ + if (self) { + return (get_attributes(self) & SLEEP_RETENTION_MODULE_ATTR_ATTACH) ? true : false; + } + return false; /* for SLEEP_RETENTION_MODULE_INVALID */ +} + static inline bool module_is_passive(struct sleep_retention_module_object * const self) { return (get_attributes(self) & SLEEP_RETENTION_MODULE_ATTR_PASSIVE) ? true : false; } -static inline bool module_is_inited(sleep_retention_module_t module) -{ - sleep_retention_module_bitmap_t inited_modules = sleep_retention_get_inited_modules(); - return (inited_modules.bitmap[module >> 5] & BIT(module % 32)) ? true : false; -} - -static inline bool module_is_created(sleep_retention_module_t module) -{ - sleep_retention_module_bitmap_t created_modules = sleep_retention_get_created_modules(); - return (created_modules.bitmap[module >> 5] & BIT(module % 32)) ? true : false; -} - /** * Internal structure which holds all requested sleep retention parameters */ +struct module_sleep_retention_context { +#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 */ + struct { + sleep_retention_entries_t entries; + uint32_t entries_bitmap: REGDMA_LINK_ENTRY_NUM; + uint32_t runtime_bitmap: REGDMA_LINK_ENTRY_NUM; +#if REGDMA_LINK_ENTRY_NUM < 16 + uint32_t reserved: 32-(2*REGDMA_LINK_ENTRY_NUM); +#endif + void *entries_tail; + } lists[SLEEP_RETENTION_REGDMA_LINK_NR_PRIORITIES]; +}; + typedef struct { /* The hardware retention module (REGDMA and PMU) uses 4 linked lists to * record the hardware context information that needs to be backed up and @@ -181,23 +193,15 @@ typedef struct { * restore the register context, which ensures only one backup or restore * when multiple modules (BLE and 15.4) exists. */ -#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 */ - struct { - sleep_retention_entries_t entries; - uint32_t entries_bitmap: REGDMA_LINK_ENTRY_NUM; - uint32_t runtime_bitmap: REGDMA_LINK_ENTRY_NUM; -#if REGDMA_LINK_ENTRY_NUM < 16 - uint32_t reserved: 32-(2*REGDMA_LINK_ENTRY_NUM); -#endif - void *entries_tail; - } lists[SLEEP_RETENTION_REGDMA_LINK_NR_PRIORITIES]; + union { + struct module_sleep_retention_context retention; + struct module_sleep_retention_context context[2]; + }; _lock_t lock; regdma_link_priority_t highpri; sleep_retention_module_bitmap_t inited_modules; sleep_retention_module_bitmap_t created_modules; + sleep_retention_module_bitmap_t retention_modules; struct sleep_retention_module_object instance[SLEEP_RETENTION_MODULE_MAX + 1]; @@ -207,122 +211,158 @@ typedef struct { static DRAM_ATTR __attribute__((unused)) sleep_retention_t s_retention = { .highpri = (uint8_t)-1, .inited_modules = (sleep_retention_module_bitmap_t){ .bitmap = { 0 } }, - .created_modules = (sleep_retention_module_bitmap_t){ .bitmap = { 0 } } + .created_modules = (sleep_retention_module_bitmap_t){ .bitmap = { 0 } }, + .retention_modules = (sleep_retention_module_bitmap_t){ .bitmap = { 0 } } }; #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 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); +static esp_err_t entries_create(const sleep_retention_entries_config_t retent[], int num, regdma_link_priority_t priority, sleep_retention_module_t module); +static void retention_entries_join(void); -static inline bool sleep_retention_entries_require_branch(uint32_t owner, uint32_t runtime_bitmap) +static struct sleep_retention_module_object * instance(sleep_retention_module_t module) +{ + return (module == SLEEP_RETENTION_MODULE_INVALID) ? NULL : &s_retention.instance[module]; +} + +static inline bool module_is_inited(sleep_retention_module_t module) +{ + sleep_retention_module_bitmap_t inited_modules = sleep_retention_get_inited_modules(); + return (inited_modules.bitmap[module >> 5] & BIT(module % 32)) ? true : false; +} + +static inline bool module_is_created(sleep_retention_module_t module) +{ + sleep_retention_module_bitmap_t created_modules = sleep_retention_get_created_modules(); + return (created_modules.bitmap[module >> 5] & BIT(module % 32)) ? true : false; +} + +static inline bool module_is_retained(sleep_retention_module_t module) +{ + if (module_runtime_attach(instance(module))) { + sleep_retention_module_bitmap_t retained_modules = sleep_retention_get_retained_modules(); + return (retained_modules.bitmap[module >> 5] & BIT(module % 32)) ? true : false; + } else { + return false; + } +} + +static inline bool entries_require_branch(uint32_t owner, uint32_t runtime_bitmap) { bool use_new_entry = SLEEP_RETENTION_ENTRY_BITMAP(owner & ~runtime_bitmap) ? true : false; bool intersection_exist = SLEEP_RETENTION_ENTRY_BITMAP(owner & runtime_bitmap) ? true : false; return use_new_entry && intersection_exist; } -static esp_err_t sleep_retention_entries_check_and_create_default(uint32_t owner, uint32_t runtime_bitmap, uint32_t entries_bitmap, regdma_link_priority_t priority, sleep_retention_module_t module) +static esp_err_t check_and_create_default(uint32_t owner, uint32_t runtime_bitmap, uint32_t entries_bitmap, regdma_link_priority_t priority, sleep_retention_module_t module) { - assert(sleep_retention_entries_require_branch(owner, runtime_bitmap)); + assert(entries_require_branch(owner, runtime_bitmap)); static sleep_retention_entries_config_t dummy = { REGDMA_LINK_WAIT_INIT(0xffff, 0, 0, 0, 1, 1), 0 }; dummy.owner = SLEEP_RETENTION_ENTRY_BITMAP(owner & ~entries_bitmap); if (dummy.owner) { - return sleep_retention_entries_create_impl(&dummy, 1, priority, module); + return entries_create(&dummy, 1, priority, module); } return ESP_OK; } -static esp_err_t sleep_retention_entries_check_and_create_final_default(void) +static esp_err_t check_and_create_final_default(void) { static const sleep_retention_entries_config_t final_dummy = { REGDMA_LINK_WAIT_INIT(0xffff, 0, 0, 0, 1, 1), SLEEP_RETENTION_ENTRY_BITMAP_MASK }; esp_err_t err = ESP_OK; _lock_acquire_recursive(&s_retention.lock); - if (s_retention.lists[SLEEP_RETENTION_REGDMA_LINK_LOWEST_PRIORITY].entries_bitmap == 0) { - err = sleep_retention_entries_create_impl(&final_dummy, 1, SLEEP_RETENTION_REGDMA_LINK_LOWEST_PRIORITY, SLEEP_RETENTION_MODULE_INVALID); + if (s_retention.retention.lists[SLEEP_RETENTION_REGDMA_LINK_LOWEST_PRIORITY].entries_bitmap == 0) { + err = entries_create(&final_dummy, 1, SLEEP_RETENTION_REGDMA_LINK_LOWEST_PRIORITY, SLEEP_RETENTION_MODULE_INVALID); } _lock_release_recursive(&s_retention.lock); return err; } -static void sleep_retention_entries_update(uint32_t owner, void *new_link, regdma_link_priority_t priority) +static void entries_stats(struct module_sleep_retention_context *ctx) { _lock_acquire_recursive(&s_retention.lock); - sleep_retention_entries_t retention_entries = { - (owner & BIT(0)) ? new_link : s_retention.lists[priority].entries[0], - (owner & BIT(1)) ? new_link : s_retention.lists[priority].entries[1], - (owner & BIT(2)) ? new_link : s_retention.lists[priority].entries[2], - (owner & BIT(3)) ? new_link : s_retention.lists[priority].entries[3] -#if (REGDMA_LINK_ENTRY_NUM == 5) - , (owner & BIT(4)) ? new_link : s_retention.lists[priority].entries[4] -#endif - }; - if (s_retention.lists[priority].entries_bitmap == 0) { - s_retention.lists[priority].entries_tail = new_link; + for (regdma_link_priority_t priority = 0; priority < SLEEP_RETENTION_REGDMA_LINK_NR_PRIORITIES; priority++) { + for (int entry = 0; entry < ARRAY_SIZE(ctx->lists[s_retention.highpri].entries); entry++) { + regdma_link_stats(ctx->lists[priority].entries[entry], entry); + } } - memcpy(s_retention.lists[priority].entries, retention_entries, sizeof(sleep_retention_entries_t)); - s_retention.lists[priority].runtime_bitmap = owner; - s_retention.lists[priority].entries_bitmap |= owner; _lock_release_recursive(&s_retention.lock); } -static void * sleep_retention_entries_try_create(const regdma_link_config_t *config, uint32_t owner, regdma_link_priority_t priority, sleep_retention_module_t module) +static void entries_context_update(struct module_sleep_retention_context *ctx, uint32_t owner, void *new_link, regdma_link_priority_t priority) +{ + _lock_acquire_recursive(&s_retention.lock); + sleep_retention_entries_t entries = { + (owner & BIT(0)) ? new_link : ctx->lists[priority].entries[0], + (owner & BIT(1)) ? new_link : ctx->lists[priority].entries[1], + (owner & BIT(2)) ? new_link : ctx->lists[priority].entries[2], + (owner & BIT(3)) ? new_link : ctx->lists[priority].entries[3] +#if (REGDMA_LINK_ENTRY_NUM == 5) + , (owner & BIT(4)) ? new_link : ctx->lists[priority].entries[4] +#endif + }; + if (ctx->lists[priority].entries_bitmap == 0) { + ctx->lists[priority].entries_tail = new_link; + } + memcpy(ctx->lists[priority].entries, entries, sizeof(sleep_retention_entries_t)); + ctx->lists[priority].runtime_bitmap = owner; + ctx->lists[priority].entries_bitmap |= owner; + entries_stats(ctx); + _lock_release_recursive(&s_retention.lock); +} + +static void * entries_try_create(const regdma_link_config_t *config, uint32_t owner, regdma_link_priority_t priority, sleep_retention_module_t module) { void *link = NULL; assert(owner > 0 && owner < BIT(REGDMA_LINK_ENTRY_NUM)); _lock_acquire_recursive(&s_retention.lock); - if (sleep_retention_entries_require_branch(owner, s_retention.lists[priority].runtime_bitmap)) { - if (sleep_retention_entries_check_and_create_default(owner, s_retention.lists[priority].runtime_bitmap, - s_retention.lists[priority].entries_bitmap, priority, module) == ESP_OK) { /* branch node can't as tail node */ + int index = module_runtime_attach(instance(module)) ? 1 : 0; + struct module_sleep_retention_context *ctx = &s_retention.context[index]; + uint32_t bm_runtime = ctx->lists[priority].runtime_bitmap; + uint32_t bm_entries = ctx->lists[priority].entries_bitmap; + if (entries_require_branch(owner, bm_runtime)) { + /* branch node can't as tail node */ + esp_err_t err = check_and_create_default(owner, bm_runtime, bm_entries, priority, module); + if (err == ESP_OK) { link = regdma_link_init_safe(config, true, module, - (owner & BIT(0)) ? s_retention.lists[priority].entries[0] : NULL, - (owner & BIT(1)) ? s_retention.lists[priority].entries[1] : NULL, - (owner & BIT(2)) ? s_retention.lists[priority].entries[2] : NULL, - (owner & BIT(3)) ? s_retention.lists[priority].entries[3] : NULL + (owner & BIT(0)) ? ctx->lists[priority].entries[0] : NULL, + (owner & BIT(1)) ? ctx->lists[priority].entries[1] : NULL, + (owner & BIT(2)) ? ctx->lists[priority].entries[2] : NULL, + (owner & BIT(3)) ? ctx->lists[priority].entries[3] : NULL #if (REGDMA_LINK_ENTRY_NUM == 5) - , (owner & BIT(4)) ? s_retention.lists[priority].entries[4] : NULL + , (owner & BIT(4)) ? ctx->lists[priority].entries[4] : NULL #endif ); } } else { - link = regdma_link_init_safe(config, false, module, s_retention.lists[priority].entries[__builtin_ffs(owner) - 1]); + link = regdma_link_init_safe(config, false, module, ctx->lists[priority].entries[__builtin_ffs(owner) - 1]); } _lock_release_recursive(&s_retention.lock); return link; } -static void * sleep_retention_entries_try_create_bonding(const regdma_link_config_t *config, uint32_t owner, regdma_link_priority_t priority, sleep_retention_module_t module) +static void * entries_try_create_bonding(const regdma_link_config_t *config, uint32_t owner, regdma_link_priority_t priority, sleep_retention_module_t module) { assert(owner > 0 && owner < BIT(REGDMA_LINK_ENTRY_NUM)); _lock_acquire_recursive(&s_retention.lock); + int index = module_runtime_attach(instance(module)) ? 1 : 0; + struct module_sleep_retention_context *ctx = &s_retention.context[index]; void *link = regdma_link_init_safe(config, true, module, - (owner & BIT(0)) ? s_retention.lists[priority].entries[0] : NULL, - (owner & BIT(1)) ? s_retention.lists[priority].entries[1] : NULL, - (owner & BIT(2)) ? s_retention.lists[priority].entries[2] : NULL, - (owner & BIT(3)) ? s_retention.lists[priority].entries[3] : NULL + (owner & BIT(0)) ? ctx->lists[priority].entries[0] : NULL, + (owner & BIT(1)) ? ctx->lists[priority].entries[1] : NULL, + (owner & BIT(2)) ? ctx->lists[priority].entries[2] : NULL, + (owner & BIT(3)) ? ctx->lists[priority].entries[3] : NULL #if (REGDMA_LINK_ENTRY_NUM == 5) - , (owner & BIT(4)) ? s_retention.lists[priority].entries[4] : NULL + , (owner & BIT(4)) ? ctx->lists[priority].entries[4] : NULL #endif ); _lock_release_recursive(&s_retention.lock); return link; } -static void sleep_retention_entries_stats(void) -{ - _lock_acquire_recursive(&s_retention.lock); - if (s_retention.highpri >= SLEEP_RETENTION_REGDMA_LINK_HIGHEST_PRIORITY && s_retention.highpri <= SLEEP_RETENTION_REGDMA_LINK_LOWEST_PRIORITY) { - for (int entry = 0; entry < ARRAY_SIZE(s_retention.lists[s_retention.highpri].entries); entry++) { - regdma_link_stats(s_retention.lists[s_retention.highpri].entries[entry], entry); - } - } - _lock_release_recursive(&s_retention.lock); -} - void sleep_retention_dump_modules(FILE *out) { for (int i = SLEEP_RETENTION_MODULE_MIN; i <= SLEEP_RETENTION_MODULE_MAX; i++) { @@ -342,9 +382,9 @@ void sleep_retention_dump_entries(FILE *out) { _lock_acquire_recursive(&s_retention.lock); if (s_retention.highpri >= SLEEP_RETENTION_REGDMA_LINK_HIGHEST_PRIORITY && s_retention.highpri <= SLEEP_RETENTION_REGDMA_LINK_LOWEST_PRIORITY) { - for (int entry = 0; entry < ARRAY_SIZE(s_retention.lists[s_retention.highpri].entries); entry++) { + for (int entry = 0; entry < ARRAY_SIZE(s_retention.retention.lists[s_retention.highpri].entries); entry++) { fprintf(out, "\nsleep retention entries[%d] context:\n", entry); - regdma_link_dump(out, s_retention.lists[s_retention.highpri].entries[entry], entry); + regdma_link_dump(out, s_retention.retention.lists[s_retention.highpri].entries[entry], entry); } } fflush(out); @@ -357,15 +397,15 @@ void * sleep_retention_find_link_by_id(int id) _lock_acquire_recursive(&s_retention.lock); if (s_retention.highpri >= SLEEP_RETENTION_REGDMA_LINK_HIGHEST_PRIORITY && s_retention.highpri <= SLEEP_RETENTION_REGDMA_LINK_LOWEST_PRIORITY) { - for (int entry = 0; (link == NULL && entry < ARRAY_SIZE(s_retention.lists[s_retention.highpri].entries)); entry++) { - link = regdma_find_link_by_id(s_retention.lists[s_retention.highpri].entries[entry], entry, id); + for (int entry = 0; (link == NULL && entry < ARRAY_SIZE(s_retention.retention.lists[s_retention.highpri].entries)); entry++) { + link = regdma_find_link_by_id(s_retention.retention.lists[s_retention.highpri].entries[entry], entry, id); } } _lock_release_recursive(&s_retention.lock); return link; } -static uint32_t sleep_retention_entries_owner_bitmap(sleep_retention_entries_t *entries, sleep_retention_entries_t *tails) +static uint32_t entries_owner_bitmap(sleep_retention_entries_t *entries, sleep_retention_entries_t *tails) { uint32_t owner = 0; _lock_acquire_recursive(&s_retention.lock); @@ -376,61 +416,78 @@ static uint32_t sleep_retention_entries_owner_bitmap(sleep_retention_entries_t * return owner; } -static bool sleep_retention_entries_get_destroy_context(regdma_link_priority_t priority, sleep_retention_module_t module, sleep_retention_entries_t *destroy_entries, void **destroy_tail, sleep_retention_entries_t *next_entries, void **prev_tail) +static bool module_entries_get(struct module_sleep_retention_context *ctx, regdma_link_priority_t priority, sleep_retention_module_t module, sleep_retention_entries_t *entries, void **tail, sleep_retention_entries_t *next_entries, void **prev_tail) { bool exist = false; - sleep_retention_entries_t destroy_tails, prev_tails; + sleep_retention_entries_t tails, prev_tails; - memset(&destroy_tails, 0, sizeof(sleep_retention_entries_t)); + memset(&tails, 0, sizeof(sleep_retention_entries_t)); memset(&prev_tails, 0, sizeof(sleep_retention_entries_t)); _lock_acquire_recursive(&s_retention.lock); - for (int entry = 0; entry < ARRAY_SIZE(s_retention.lists[priority].entries); entry++) { - (*destroy_entries)[entry] = regdma_find_module_link_head( - s_retention.lists[priority].entries[entry], s_retention.lists[priority].entries_tail, entry, module); - destroy_tails [entry] = regdma_find_module_link_tail( - s_retention.lists[priority].entries[entry], s_retention.lists[priority].entries_tail, entry, module); + for (int entry = 0; entry < ARRAY_SIZE(ctx->lists[priority].entries); entry++) { + (*entries)[entry] = regdma_find_module_link_head( + ctx->lists[priority].entries[entry], + ctx->lists[priority].entries_tail, + entry, module); + tails [entry] = regdma_find_module_link_tail( + ctx->lists[priority].entries[entry], + ctx->lists[priority].entries_tail, + entry, module); (*next_entries) [entry] = regdma_find_next_module_link_head( - s_retention.lists[priority].entries[entry], s_retention.lists[priority].entries_tail, entry, module); + ctx->lists[priority].entries[entry], + ctx->lists[priority].entries_tail, + entry, module); prev_tails [entry] = regdma_find_prev_module_link_tail( - s_retention.lists[priority].entries[entry], s_retention.lists[priority].entries_tail, entry, module); - if ((*destroy_entries)[entry] && destroy_tails[entry]) { + ctx->lists[priority].entries[entry], + ctx->lists[priority].entries_tail, + entry, module); + if ((*entries)[entry] && tails[entry]) { exist = true; } - assert(destroy_tails[entry] == destroy_tails[0]); + assert(tails[entry] == tails[0]); assert(prev_tails[entry] == prev_tails[0]); } - *destroy_tail = destroy_tails[0]; + *tail = tails[0]; *prev_tail = prev_tails[0]; _lock_release_recursive(&s_retention.lock); return exist; } -static void sleep_retention_entries_context_update(regdma_link_priority_t priority) +static void entries_context_refresh(struct module_sleep_retention_context *ctx, regdma_link_priority_t priority) { _lock_acquire_recursive(&s_retention.lock); sleep_retention_entries_t tails = { - s_retention.lists[priority].entries_tail, s_retention.lists[priority].entries_tail, - s_retention.lists[priority].entries_tail, s_retention.lists[priority].entries_tail + ctx->lists[priority].entries_tail, ctx->lists[priority].entries_tail, + ctx->lists[priority].entries_tail, ctx->lists[priority].entries_tail +#if (REGDMA_LINK_ENTRY_NUM == 5) + , ctx->lists[priority].entries_tail +#endif }; - s_retention.lists[priority].entries_bitmap = sleep_retention_entries_owner_bitmap(&s_retention.lists[priority].entries, &tails); - s_retention.lists[priority].runtime_bitmap = sleep_retention_entries_owner_bitmap(&s_retention.lists[priority].entries, &s_retention.lists[priority].entries); + ctx->lists[priority].entries_bitmap = entries_owner_bitmap(&ctx->lists[priority].entries, &tails); + ctx->lists[priority].runtime_bitmap = entries_owner_bitmap(&ctx->lists[priority].entries, &ctx->lists[priority].entries); _lock_release_recursive(&s_retention.lock); } -static bool sleep_retention_entries_dettach(regdma_link_priority_t priority, sleep_retention_entries_t *destroy_entries, void *destroy_tail, sleep_retention_entries_t *next_entries, void *prev_tail) +static bool entries_detach(struct module_sleep_retention_context *ctx, regdma_link_priority_t priority, + sleep_retention_entries_t *entries, void *tail, sleep_retention_entries_t *next_entries, void *prev_tail) { _lock_acquire_recursive(&s_retention.lock); - bool is_head = (memcmp(destroy_entries, &s_retention.lists[priority].entries, sizeof(sleep_retention_entries_t)) == 0); - bool is_tail = (destroy_tail == s_retention.lists[priority].entries_tail); + bool is_head = (memcmp(entries, ctx->lists[priority].entries, sizeof(sleep_retention_entries_t)) == 0); + bool is_tail = (tail == ctx->lists[priority].entries_tail); if (is_head && is_tail) { - memset(s_retention.lists[priority].entries, 0, sizeof(sleep_retention_entries_t)); - s_retention.lists[priority].entries_tail = NULL; + memset(ctx->lists[priority].entries, 0, sizeof(sleep_retention_entries_t)); + ctx->lists[priority].entries_tail = NULL; } else if (is_head) { - memcpy(&s_retention.lists[priority].entries, next_entries, sizeof(sleep_retention_entries_t)); + memcpy(ctx->lists[priority].entries, next_entries, sizeof(sleep_retention_entries_t)); } else if (is_tail) { - s_retention.lists[priority].entries_tail = prev_tail; + ctx->lists[priority].entries_tail = prev_tail; +#if (REGDMA_LINK_ENTRY_NUM == 5) + regdma_link_update_next_safe(prev_tail, NULL, NULL, NULL, NULL, NULL); +#else + regdma_link_update_next_safe(prev_tail, NULL, NULL, NULL, NULL); +#endif } else { #if (REGDMA_LINK_ENTRY_NUM == 5) regdma_link_update_next_safe(prev_tail, (*next_entries)[0], (*next_entries)[1], (*next_entries)[2], (*next_entries)[3], (*next_entries)[4]); @@ -438,24 +495,24 @@ static bool sleep_retention_entries_dettach(regdma_link_priority_t priority, sle regdma_link_update_next_safe(prev_tail, (*next_entries)[0], (*next_entries)[1], (*next_entries)[2], (*next_entries)[3]); #endif } - sleep_retention_entries_context_update(priority); + entries_context_refresh(ctx, priority); #if (REGDMA_LINK_ENTRY_NUM == 5) - regdma_link_update_next_safe(destroy_tail, NULL, NULL, NULL, NULL, NULL); + regdma_link_update_next_safe(tail, NULL, NULL, NULL, NULL, NULL); #else - regdma_link_update_next_safe(destroy_tail, NULL, NULL, NULL, NULL); + regdma_link_update_next_safe(tail, NULL, NULL, NULL, NULL); #endif _lock_release_recursive(&s_retention.lock); return (is_head || is_tail); } -static void sleep_retention_entries_destroy_wrapper(sleep_retention_entries_t *destroy_entries) +static void module_entries_destroy(sleep_retention_entries_t *entries) { - for (int entry = 0; entry < ARRAY_SIZE(*destroy_entries); entry++) { - regdma_link_destroy((*destroy_entries)[entry], entry); + for (int entry = 0; entry < ARRAY_SIZE(*entries); entry++) { + regdma_link_destroy((*entries)[entry], entry); } } -static void sleep_retention_entries_check_and_distroy_final_default(void) +static void check_and_destroy_final_default(void) { _lock_acquire_recursive(&s_retention.lock); assert(s_retention.highpri == SLEEP_RETENTION_REGDMA_LINK_LOWEST_PRIORITY); @@ -464,27 +521,31 @@ static void sleep_retention_entries_check_and_distroy_final_default(void) created_modules |= s_retention.created_modules.bitmap[i]; } assert(created_modules == 0); - sleep_retention_entries_destroy_wrapper(&s_retention.lists[SLEEP_RETENTION_REGDMA_LINK_LOWEST_PRIORITY].entries); + module_entries_destroy(&s_retention.retention.lists[SLEEP_RETENTION_REGDMA_LINK_LOWEST_PRIORITY].entries); _lock_release_recursive(&s_retention.lock); } -static void sleep_retention_entries_all_destroy_wrapper(sleep_retention_module_t module) +static void entries_do_destroy(sleep_retention_module_t module) { - void *destroy_tail = NULL, *prev_tail = NULL; - sleep_retention_entries_t destroy_entries, next_entries; + void *tail = NULL, *prev_tail = NULL; + sleep_retention_entries_t entries, next_entries; - memset(&destroy_entries, 0, sizeof(sleep_retention_entries_t)); + memset(&entries, 0, sizeof(sleep_retention_entries_t)); memset(&next_entries, 0, sizeof(sleep_retention_entries_t)); _lock_acquire_recursive(&s_retention.lock); + int index = module_runtime_attach(instance(module)) ? 1 : 0; + struct module_sleep_retention_context *ctx = &s_retention.context[index]; regdma_link_priority_t priority = 0; do { - bool exist = sleep_retention_entries_get_destroy_context(priority, module, &destroy_entries, &destroy_tail, &next_entries, &prev_tail); - if (s_retention.lists[priority].entries_bitmap && exist) { - if (sleep_retention_entries_dettach(priority, &destroy_entries, destroy_tail, &next_entries, prev_tail)) { - sleep_retention_entries_join(); + bool exist = module_entries_get(ctx, priority, module, &entries, &tail, &next_entries, &prev_tail); + if (exist) { + if (entries_detach(ctx, priority, &entries, tail, &next_entries, prev_tail)) { + if (!module_runtime_attach(instance(module))) { + retention_entries_join(); + } } - sleep_retention_entries_destroy_wrapper(&destroy_entries); + module_entries_destroy(&entries); } else { priority++; } @@ -493,13 +554,16 @@ static void sleep_retention_entries_all_destroy_wrapper(sleep_retention_module_t _lock_release_recursive(&s_retention.lock); } -static void sleep_retention_entries_do_destroy(sleep_retention_module_t module) +static void entries_destroy(sleep_retention_module_t module) { assert(SLEEP_RETENTION_MODULE_MIN <= module && module <= SLEEP_RETENTION_MODULE_MAX); _lock_acquire_recursive(&s_retention.lock); - sleep_retention_entries_join(); - sleep_retention_entries_stats(); - sleep_retention_entries_all_destroy_wrapper(module); + if (!module_runtime_attach(instance(module))) { + retention_entries_join(); + } + int index = module_runtime_attach(instance(module)) ? 1 : 0; + entries_stats(&s_retention.context[index]); + entries_do_destroy(module); _lock_release_recursive(&s_retention.lock); } @@ -507,23 +571,23 @@ static void sleep_retention_entries_destroy(sleep_retention_module_t module) { assert(SLEEP_RETENTION_MODULE_MIN <= module && module <= SLEEP_RETENTION_MODULE_MAX); _lock_acquire_recursive(&s_retention.lock); - sleep_retention_entries_do_destroy(module); + entries_destroy(module); uint32_t created_modules = 0; for (int i = 0; i < SLEEP_RETENTION_MODULE_BITMAP_SZ; i++) { created_modules |= s_retention.created_modules.bitmap[i]; } if (created_modules == 0) { - sleep_retention_entries_check_and_distroy_final_default(); + check_and_destroy_final_default(); #if SOC_LIGHT_SLEEP_SUPPORTED pmu_sleep_disable_regdma_backup(); #endif - memset((void *)s_retention.lists, 0, sizeof(s_retention.lists)); + memset((void *)s_retention.context, 0, sizeof(struct module_sleep_retention_context) * 2); s_retention.highpri = (uint8_t)-1; } _lock_release_recursive(&s_retention.lock); } -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 esp_err_t entries_create(const sleep_retention_entries_config_t retent[], int num, regdma_link_priority_t priority, sleep_retention_module_t module) { esp_err_t err = ESP_OK; _lock_acquire_recursive(&s_retention.lock); @@ -531,7 +595,7 @@ static esp_err_t sleep_retention_entries_create_impl(const sleep_retention_entri #if SOC_PM_RETENTION_HAS_CLOCK_BUG if ((retent[i].owner > BIT(EXTRA_LINK_NUM)) && (retent[i].config.id != 0xffff)) { _lock_release_recursive(&s_retention.lock); - sleep_retention_entries_do_destroy(module); + entries_destroy(module); return ESP_ERR_NOT_SUPPORTED; } #endif @@ -552,77 +616,83 @@ static esp_err_t sleep_retention_entries_create_impl(const sleep_retention_entri [0] = { .config = REGDMA_LINK_WRITE_INIT(0xfffe, PMU_DATE_REG, ~value, mask, skip_b, skip_r), .owner = retent[i].owner }, [1] = { .config = REGDMA_LINK_WAIT_INIT (0xfffe, PMU_DATE_REG, ~value, mask, skip_b, skip_r), .owner = retent[i].owner } }; - err = sleep_retention_entries_create_impl(wait_bug_workaround, ARRAY_SIZE(wait_bug_workaround), priority, module); + err = entries_create(wait_bug_workaround, ARRAY_SIZE(wait_bug_workaround), priority, module); } #endif if (err == ESP_OK) { - void *link = sleep_retention_entries_try_create(&retent[i].config, retent[i].owner, priority, module); + void *link = entries_try_create(&retent[i].config, retent[i].owner, priority, module); if (link == NULL) { _lock_release_recursive(&s_retention.lock); - sleep_retention_entries_do_destroy(module); + entries_destroy(module); return ESP_ERR_NO_MEM; } - sleep_retention_entries_update(retent[i].owner, link, priority); + + int index = module_runtime_attach(instance(module)) ? 1 : 0; + struct module_sleep_retention_context *ctx = &s_retention.context[index]; + entries_context_update(ctx, retent[i].owner, link, priority); } } _lock_release_recursive(&s_retention.lock); return err; } -static esp_err_t sleep_retention_entries_create_bonding(regdma_link_priority_t priority, sleep_retention_module_t module) +static esp_err_t entries_create_bonding(regdma_link_priority_t priority, sleep_retention_module_t module) { static const sleep_retention_entries_config_t bonding_dummy = { REGDMA_LINK_WAIT_INIT(0xffff, 0, 0, 0, 1, 1), SLEEP_RETENTION_ENTRY_BITMAP_MASK }; _lock_acquire_recursive(&s_retention.lock); - void *link = sleep_retention_entries_try_create_bonding(&bonding_dummy.config, bonding_dummy.owner, priority, module); + void *link = entries_try_create_bonding(&bonding_dummy.config, bonding_dummy.owner, priority, module); if (link == NULL) { _lock_release_recursive(&s_retention.lock); - sleep_retention_entries_do_destroy(module); + entries_destroy(module); return ESP_ERR_NO_MEM; } - sleep_retention_entries_update(bonding_dummy.owner, link, priority); + int index = module_runtime_attach(instance(module)) ? 1 : 0; + struct module_sleep_retention_context *ctx = &s_retention.context[index]; + entries_context_update(ctx, bonding_dummy.owner, link, priority); _lock_release_recursive(&s_retention.lock); return ESP_OK; } -static void sleep_retention_entries_join(void) +static void retention_entries_join(void) { void *entries_tail = NULL; _lock_acquire_recursive(&s_retention.lock); s_retention.highpri = SLEEP_RETENTION_REGDMA_LINK_LOWEST_PRIORITY; for (regdma_link_priority_t priority = 0; priority < SLEEP_RETENTION_REGDMA_LINK_NR_PRIORITIES; priority++) { - if (s_retention.lists[priority].entries_bitmap == 0) continue; + if (s_retention.retention.lists[priority].entries_bitmap == 0) continue; if (priority < s_retention.highpri) { s_retention.highpri = priority; } if (entries_tail) { regdma_link_update_next_safe( entries_tail, - s_retention.lists[priority].entries[0], - s_retention.lists[priority].entries[1], - s_retention.lists[priority].entries[2], - s_retention.lists[priority].entries[3] + s_retention.retention.lists[priority].entries[0], + s_retention.retention.lists[priority].entries[1], + s_retention.retention.lists[priority].entries[2], + s_retention.retention.lists[priority].entries[3] #if (REGDMA_LINK_ENTRY_NUM == 5) - , s_retention.lists[priority].entries[4] + , s_retention.retention.lists[priority].entries[4] #endif ); } - entries_tail = s_retention.lists[priority].entries_tail; + entries_tail = s_retention.retention.lists[priority].entries_tail; } - pau_regdma_set_entry_link_addr(&(s_retention.lists[s_retention.highpri].entries)); + pau_regdma_set_entry_link_addr(&(s_retention.retention.lists[s_retention.highpri].entries)); _lock_release_recursive(&s_retention.lock); } -static esp_err_t sleep_retention_entries_create_wrapper(const sleep_retention_entries_config_t retent[], int num, regdma_link_priority_t priority, sleep_retention_module_t module) +static esp_err_t entries_create_wrapper(const sleep_retention_entries_config_t retent[], int num, regdma_link_priority_t priority, sleep_retention_module_t module) { _lock_acquire_recursive(&s_retention.lock); - esp_err_t err = sleep_retention_entries_create_bonding(priority, module); + esp_err_t err = entries_create_bonding(priority, module); if(err) goto error; - err = sleep_retention_entries_create_impl(retent, num, priority, module); + err = entries_create(retent, num, priority, module); if(err) goto error; - err = sleep_retention_entries_create_bonding(priority, module); + err = entries_create_bonding(priority, module); if(err) goto error; s_retention.created_modules.bitmap[module >> 5] |= BIT(module % 32); - sleep_retention_entries_join(); - + if (!module_runtime_attach(instance(module))) { + retention_entries_join(); + } error: _lock_release_recursive(&s_retention.lock); return err; @@ -639,9 +709,9 @@ esp_err_t sleep_retention_entries_create(const sleep_retention_entries_config_t 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(); + esp_err_t err = check_and_create_final_default(); if (err) goto error; - err = sleep_retention_entries_create_wrapper(retent, num, priority, module); + err = entries_create_wrapper(retent, num, priority, module); if (err) goto error; #if SOC_LIGHT_SLEEP_SUPPORTED pmu_sleep_enable_regdma_backup(); @@ -660,7 +730,7 @@ void sleep_retention_entries_get(sleep_retention_entries_t *entries) _lock_acquire_recursive(&s_retention.lock); if (s_retention.highpri >= SLEEP_RETENTION_REGDMA_LINK_HIGHEST_PRIORITY && s_retention.highpri <= SLEEP_RETENTION_REGDMA_LINK_LOWEST_PRIORITY) { - memcpy(entries, &s_retention.lists[s_retention.highpri].entries, sizeof(sleep_retention_entries_t)); + memcpy(entries, &s_retention.retention.lists[s_retention.highpri].entries, sizeof(sleep_retention_entries_t)); } _lock_release_recursive(&s_retention.lock); } @@ -675,6 +745,11 @@ sleep_retention_module_bitmap_t IRAM_ATTR sleep_retention_get_created_modules(vo return s_retention.created_modules; } +sleep_retention_module_bitmap_t IRAM_ATTR sleep_retention_get_retained_modules(void) +{ + return s_retention.retention_modules; +} + bool sleep_retention_is_module_inited(sleep_retention_module_t module) { if (module < SLEEP_RETENTION_MODULE_MIN || module > SLEEP_RETENTION_MODULE_MAX) { @@ -697,6 +772,17 @@ bool sleep_retention_is_module_created(sleep_retention_module_t module) return created; } +bool sleep_retention_is_module_attached(sleep_retention_module_t module) +{ + if (module < SLEEP_RETENTION_MODULE_MIN || module > SLEEP_RETENTION_MODULE_MAX) { + return false; + } + _lock_acquire_recursive(&s_retention.lock); + bool attached = module_is_retained(module); + _lock_release_recursive(&s_retention.lock); + return attached; +} + sleep_retention_module_bitmap_t IRAM_ATTR sleep_retention_module_bitmap_and(sleep_retention_module_bitmap_t op0, sleep_retention_module_bitmap_t op1) { sleep_retention_module_bitmap_t and; @@ -731,6 +817,41 @@ bool IRAM_ATTR sleep_retention_module_bitmap_eq(sleep_retention_module_bitmap_t return true; } + +static void module_action(sleep_retention_module_t module, sleep_retention_module_t dep_module, int action) +{ + switch (action) + { + case 0: break; /* Nothing to do */ + case 1: set_reference(instance(dep_module), module); break; /* allocate */ + case 2: clr_reference(instance(dep_module), module); break; /* free */ + default: break; + } +} + +static esp_err_t module_action_wrapper(sleep_retention_module_t module, int arg, esp_err_t (*rec)(sleep_retention_module_t)) +{ + esp_err_t err = ESP_OK; + + sleep_retention_module_bitmap_t depends = get_dependencies(instance(module)); + 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)) { + sleep_retention_module_t dep_module = (sleep_retention_module_t)((i << 5) + j); + + #define action(x) ((x) & 0xf) + module_action(module, dep_module, action(arg)); + + if ((arg & BIT(31)) || module_is_passive(instance(dep_module))) { + err = (*rec)(dep_module); + } + } + } + } + return err; +} + 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) { @@ -755,9 +876,9 @@ 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); + sleep_retention_module_object_ctor(instance(module), ¶m->cbs); + set_dependencies(instance(module), param->depends); + set_attributes(instance(module), param->attribute); s_retention.inited_modules.bitmap[module >> 5] |= BIT(module % 32); } _lock_release_recursive(&s_retention.lock); @@ -776,9 +897,9 @@ 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]); + clr_attributes(instance(module)); + clr_dependencies(instance(module)); + sleep_retention_module_object_dtor(instance(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++) { @@ -795,29 +916,20 @@ esp_err_t sleep_retention_module_deinit(sleep_retention_module_t module) return err; } -static esp_err_t sleep_retention_passive_module_allocate(sleep_retention_module_t module) +static esp_err_t passive_module_allocate(sleep_retention_module_t module) { assert(module >= SLEEP_RETENTION_MODULE_MIN && module <= SLEEP_RETENTION_MODULE_MAX); 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_passive(instance(module)) && "Illegal dependency"); assert(module_is_inited(module) && "All passive module must be inited first!"); if (!module_is_created(module)) { - sleep_retention_module_bitmap_t depends = get_dependencies(&s_retention.instance[module]); - 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); - } - } - } + err = module_action_wrapper(module, (BIT(31) | action(1)), passive_module_allocate); if (err == ESP_OK) { - sleep_retention_callback_t fn = s_retention.instance[module].cbs.create.handle; + sleep_retention_callback_t fn = instance(module)->cbs.create.handle; if (fn) { - err = (*fn)(s_retention.instance[module].cbs.create.arg); + err = (*fn)(instance(module)->cbs.create.arg); } } } @@ -833,24 +945,13 @@ 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_passive(instance(module))) { if (module_is_inited(module) && !module_is_created(module)) { - sleep_retention_module_bitmap_t depends = get_dependencies(&s_retention.instance[module]); - 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); - } - } - } - } + err = module_action_wrapper(module, action(1), passive_module_allocate); if (err == ESP_OK) { - sleep_retention_callback_t fn = s_retention.instance[module].cbs.create.handle; + sleep_retention_callback_t fn = instance(module)->cbs.create.handle; if (fn) { - err = (*fn)(s_retention.instance[module].cbs.create.arg); + err = (*fn)(instance(module)->cbs.create.arg); } } } else { @@ -863,27 +964,21 @@ esp_err_t sleep_retention_module_allocate(sleep_retention_module_t module) return err; } -static esp_err_t sleep_retention_passive_module_free(sleep_retention_module_t module) +static esp_err_t passive_module_free(sleep_retention_module_t module) { assert(module >= SLEEP_RETENTION_MODULE_MIN && module <= SLEEP_RETENTION_MODULE_MAX); 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_passive(instance(module)) && "Illegal dependency"); assert(module_is_inited(module) && "All passive module must be inited first!"); if (module_is_created(module)) { - if (!references_exist(&s_retention.instance[module])) { - sleep_retention_entries_destroy(module); - - sleep_retention_module_bitmap_t depends = get_dependencies(&s_retention.instance[module]); - 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); - } - } + if (!references_exist(instance(module))) { + if (!module_is_retained(module)) { + sleep_retention_entries_destroy(module); + err = module_action_wrapper(module, (BIT(31) | action(2)), passive_module_free); + } else { + err = ESP_ERR_INVALID_STATE; } } } @@ -899,22 +994,10 @@ 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_passive(instance(module))) { + if (module_is_inited(module) && module_is_created(module) && !module_is_retained(module)) { sleep_retention_entries_destroy(module); - - sleep_retention_module_bitmap_t depends = get_dependencies(&s_retention.instance[module]); - 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); - } - } - } - } + err = module_action_wrapper(module, action(2), passive_module_free); } else { err = ESP_ERR_INVALID_STATE; } @@ -971,7 +1054,7 @@ void IRAM_ATTR sleep_retention_do_extra_retention(bool backup_or_restore) bool origin_bypass_en = pau_regdma_enable_aon_link_entry(false); #endif // Set extra linked list head pointer to hardware - pau_regdma_set_extra_link_addr(s_retention.lists[s_retention.highpri].entries[EXTRA_LINK_NUM]); + pau_regdma_set_extra_link_addr(s_retention.retention.lists[s_retention.highpri].entries[EXTRA_LINK_NUM]); #if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE /* Data of retention link may be temporarily stored in L1 DCache, which is not accessible by REGDMA, write it back to L2MEM before starting REGDMA. */ @@ -994,7 +1077,7 @@ void IRAM_ATTR sleep_retention_do_system_retention(bool backup_or_restore) if (s_retention.highpri >= SLEEP_RETENTION_REGDMA_LINK_HIGHEST_PRIORITY && s_retention.highpri <= SLEEP_RETENTION_REGDMA_LINK_LOWEST_PRIORITY) { // Set extra linked list head pointer to hardware - pau_regdma_set_system_link_addr(s_retention.lists[s_retention.highpri].entries[SYSTEM_LINK_NUM]); + pau_regdma_set_system_link_addr(s_retention.retention.lists[s_retention.highpri].entries[SYSTEM_LINK_NUM]); // When PD TOP, we need to prevent the PMU from triggering the REGDMA backup, because REGDMA will power off pmu_sleep_disable_regdma_backup(); if (backup_or_restore) { From aa56e1af2ea617a8a91e1d8becd7144ddc162145 Mon Sep 17 00:00:00 2001 From: Li Shuai Date: Fri, 20 Mar 2026 10:51:20 +0800 Subject: [PATCH 02/22] feat(esp_hw_support): support sleep retention module runtime attach and detach --- .../include/esp_private/sleep_retention.h | 3 + components/esp_hw_support/sleep_retention.c | 140 ++++++++++++++++++ 2 files changed, 143 insertions(+) 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 00387b19dae..0e8ba7418e2 100644 --- a/components/esp_hw_support/include/esp_private/sleep_retention.h +++ b/components/esp_hw_support/include/esp_private/sleep_retention.h @@ -161,6 +161,9 @@ esp_err_t sleep_retention_module_allocate(sleep_retention_module_t module); */ esp_err_t sleep_retention_module_free(sleep_retention_module_t module); +esp_err_t sleep_retention_module_attach(sleep_retention_module_t module); +esp_err_t sleep_retention_module_detach(sleep_retention_module_t module); + /** * @brief Force take the power lock so that during sleep the power domain won't be powered off. * diff --git a/components/esp_hw_support/sleep_retention.c b/components/esp_hw_support/sleep_retention.c index 3bcfc7c4094..b5b69cd328e 100644 --- a/components/esp_hw_support/sleep_retention.c +++ b/components/esp_hw_support/sleep_retention.c @@ -387,6 +387,16 @@ void sleep_retention_dump_entries(FILE *out) regdma_link_dump(out, s_retention.retention.lists[s_retention.highpri].entries[entry], entry); } } + for (int n = 0; n < ARRAY_SIZE(s_retention.context); n++) { + for (regdma_link_priority_t priority = 0; priority < SLEEP_RETENTION_REGDMA_LINK_NR_PRIORITIES; priority++) { + for (int e = 0; e < ARRAY_SIZE(s_retention.context[0].lists[priority].entries); e++) { + fprintf(out, "\nsleep retention context[%d] priority %d entries[%d] context:\n", n, priority, e); + void *head = s_retention.context[n].lists[priority].entries[e]; + void *tail = s_retention.context[n].lists[priority].entries_tail; + regdma_link_dump_sublink(out, head, tail, e); + } + } + } fflush(out); _lock_release_recursive(&s_retention.lock); } @@ -505,6 +515,23 @@ static bool entries_detach(struct module_sleep_retention_context *ctx, regdma_li return (is_head || is_tail); } +static void entries_attach(struct module_sleep_retention_context *ctx, regdma_link_priority_t priority, sleep_retention_entries_t *entries, void *tail) +{ + _lock_acquire_recursive(&s_retention.lock); + regdma_link_update_next_safe(tail, ctx->lists[priority].entries[0], ctx->lists[priority].entries[1], + ctx->lists[priority].entries[2], ctx->lists[priority].entries[3] +#if (REGDMA_LINK_ENTRY_NUM == 5) + , ctx->lists[priority].entries[4] +#endif + ); + memcpy(ctx->lists[priority].entries, entries, sizeof(sleep_retention_entries_t)); + if (ctx->lists[priority].entries_tail == NULL) { + ctx->lists[priority].entries_tail = tail; + } + entries_context_refresh(ctx, priority); + _lock_release_recursive(&s_retention.lock); +} + static void module_entries_destroy(sleep_retention_entries_t *entries) { for (int entry = 0; entry < ARRAY_SIZE(*entries); entry++) { @@ -1008,6 +1035,119 @@ esp_err_t sleep_retention_module_free(sleep_retention_module_t module) return err; } +static void module_entries_move(sleep_retention_module_t module, struct module_sleep_retention_context *s, struct module_sleep_retention_context *d) +{ + void *tail = NULL, *prev_tail = NULL; + sleep_retention_entries_t entries, next_entries; + regdma_link_priority_t priority = 0; + + memset(&entries, 0, sizeof(sleep_retention_entries_t)); + memset(&next_entries, 0, sizeof(sleep_retention_entries_t)); + + _lock_acquire_recursive(&s_retention.lock); + do { + bool exist = module_entries_get(s, priority, module, &entries, &tail, &next_entries, &prev_tail); + if (exist) { + entries_detach(s, priority, &entries, tail, &next_entries, prev_tail); + entries_attach(d, priority, &entries, tail); + } else { + priority++; + } + retention_entries_join(); + } while (priority < SLEEP_RETENTION_REGDMA_LINK_NR_PRIORITIES); + _lock_release_recursive(&s_retention.lock); +} + +static esp_err_t passive_module_attach(sleep_retention_module_t module) +{ + assert(module >= SLEEP_RETENTION_MODULE_MIN && module <= SLEEP_RETENTION_MODULE_MAX); + + esp_err_t err = ESP_OK; + _lock_acquire_recursive(&s_retention.lock); + assert(module_is_passive(instance(module)) && "Illegal dependency"); + assert(module_runtime_attach(instance(module)) && "Illegal dependency"); + assert(module_is_inited(module) && "All passive module must be inited first!"); + if (module_is_inited(module) && module_is_created(module) && !module_is_retained(module)) { + module_entries_move(module, &s_retention.context[1], &s_retention.retention); + s_retention.retention_modules.bitmap[module >> 5] |= BIT(module % 32); + err = module_action_wrapper(module, (BIT(31) | action(0)), passive_module_attach); + } + _lock_release_recursive(&s_retention.lock); + return err; +} + +esp_err_t sleep_retention_module_attach(sleep_retention_module_t module) +{ + if (module < SLEEP_RETENTION_MODULE_MIN || module > SLEEP_RETENTION_MODULE_MAX) { + return ESP_ERR_INVALID_ARG; + } + + esp_err_t err = ESP_OK; + _lock_acquire_recursive(&s_retention.lock); + if (!module_is_passive(instance(module))) { + if (module_is_inited(module) && module_is_created(module) && !module_is_retained(module)) { + if (module_runtime_attach(instance(module))) { + module_entries_move(module, &s_retention.context[1], &s_retention.retention); + s_retention.retention_modules.bitmap[module >> 5] |= BIT(module % 32); + err = module_action_wrapper(module, action(0), passive_module_attach); + } else { + err = ESP_ERR_NOT_SUPPORTED; + } + } else { + err = ESP_ERR_INVALID_STATE; + } + } else { + err = ESP_ERR_NOT_ALLOWED; + } + _lock_release_recursive(&s_retention.lock); + return err; +} + +static esp_err_t passive_module_detach(sleep_retention_module_t module) +{ + assert(module >= SLEEP_RETENTION_MODULE_MIN && module <= SLEEP_RETENTION_MODULE_MAX); + + esp_err_t err = ESP_OK; + _lock_acquire_recursive(&s_retention.lock); + assert(module_is_passive(instance(module)) && "Illegal dependency"); + assert(module_runtime_attach(instance(module)) && "Illegal dependency"); + assert(module_is_inited(module) && "All passive module must be inited first!"); + if (module_is_inited(module) && module_is_created(module) && module_is_retained(module)) { + module_entries_move(module, &s_retention.retention, &s_retention.context[1]); + s_retention.retention_modules.bitmap[module >> 5] &= ~BIT(module % 32); + err = module_action_wrapper(module, (BIT(31) | action(0)), passive_module_detach); + } + _lock_release_recursive(&s_retention.lock); + return err; +} + +esp_err_t sleep_retention_module_detach(sleep_retention_module_t module) +{ + if (module < SLEEP_RETENTION_MODULE_MIN || module > SLEEP_RETENTION_MODULE_MAX) { + return ESP_ERR_INVALID_ARG; + } + + esp_err_t err = ESP_OK; + _lock_acquire_recursive(&s_retention.lock); + if (!module_is_passive(instance(module))) { + if (module_is_inited(module) && module_is_created(module) && module_is_retained(module)) { + if (module_runtime_attach(instance(module))) { + module_entries_move(module, &s_retention.retention, &s_retention.context[1]); + s_retention.retention_modules.bitmap[module >> 5] &= ~BIT(module % 32); + err = module_action_wrapper(module, action(0), passive_module_detach); + } else { + err = ESP_ERR_NOT_SUPPORTED; + } + } else { + err = ESP_ERR_INVALID_STATE; + } + } else { + err = ESP_ERR_NOT_ALLOWED; + } + _lock_release_recursive(&s_retention.lock); + return err; +} + static esp_err_t empty_create(void *args) { return ESP_OK; From 648916ce418c44c6da6c7b88aa0ea53210601513 Mon Sep 17 00:00:00 2001 From: Li Shuai Date: Tue, 31 Mar 2026 19:28:48 +0800 Subject: [PATCH 03/22] change(esp_hw_support): add reference bitmap for multiple module attach/detach --- components/esp_hw_support/sleep_retention.c | 70 +++++++++++++++++---- 1 file changed, 59 insertions(+), 11 deletions(-) diff --git a/components/esp_hw_support/sleep_retention.c b/components/esp_hw_support/sleep_retention.c index b5b69cd328e..eb80a41f9f3 100644 --- a/components/esp_hw_support/sleep_retention.c +++ b/components/esp_hw_support/sleep_retention.c @@ -33,10 +33,19 @@ static int acquire_cnt; //for the force acquire lock struct sleep_retention_module_object { - sleep_retention_module_callbacks_t cbs; /* A callback list that can extend more sleep retention event callbacks */ - sleep_retention_module_bitmap_t dependents; /* A bitmap identifying all modules that the current module depends on */ - sleep_retention_module_bitmap_t references; /* A bitmap indicating all other modules that depend on (or reference) the current module, - * It will update at runtime based on whether the module is referenced by other modules */ + sleep_retention_module_callbacks_t cbs; /* A callback list that can extend more sleep retention event callbacks */ + sleep_retention_module_bitmap_t dependents; /* A bitmap identifying all modules that the current module depends on */ + union { + sleep_retention_module_bitmap_t references; /* A bitmap indicating all other modules that depend on (or reference) + * the current module, It will update at runtime (allocate or free) + * based on whether the module is referenced by other modules */ + sleep_retention_module_bitmap_t refarray[2]; /* Bitmap array to indicating all other modules that depend on (or + * reference) the current module, It will update at runtime (allocate/ + * attach or free/detach) based on whether the module is referenced by + * other modules, refarray[0] is equivalent to references and is used to + * indicate allocate/free operations, and refarray[1] is used to indicate + * attach/detach operations.*/ + }; sleep_retention_module_attribute_t attributes; /* A bitmap indicating attribute of the current module */ }; @@ -45,6 +54,7 @@ static inline void sleep_retention_module_object_ctor(struct sleep_retention_mod self->cbs = *cbs; self->dependents = (sleep_retention_module_bitmap_t){ .bitmap = { 0 } }; self->references = (sleep_retention_module_bitmap_t){ .bitmap = { 0 } }; + self->refarray[1] = (sleep_retention_module_bitmap_t){ .bitmap = { 0 } }; self->attributes = 0; } @@ -83,6 +93,41 @@ static inline sleep_retention_module_bitmap_t get_references(struct sleep_retent return self->references; } +static inline void refarray_set_bit(struct sleep_retention_module_object * const self, int n, sleep_retention_module_t module) +{ + if (n >= 0 && n < ARRAY_SIZE(self->refarray)) { + self->refarray[n].bitmap[module >> 5] |= BIT(module % 32); + } +} + +static inline void refarray_clr_bit(struct sleep_retention_module_object * const self, int n, sleep_retention_module_t module) +{ + if (n >= 0 && n < ARRAY_SIZE(self->refarray)) { + self->refarray[n].bitmap[module >> 5] &= ~BIT(module % 32); + } +} + +static inline sleep_retention_module_bitmap_t refarray_get(struct sleep_retention_module_object * const self, int n) +{ + if (n >= 0 && n < ARRAY_SIZE(self->refarray)) { + return self->refarray[n]; + } + return (sleep_retention_module_bitmap_t){ .bitmap = { 0 } }; +} + +static inline bool refarray_zero(struct sleep_retention_module_object * const self, int n) +{ + if (n >= 0 && n < ARRAY_SIZE(self->refarray)) { + uint32_t val = 0; + sleep_retention_module_bitmap_t map = refarray_get(self, n); + for (int i = 0; i < SLEEP_RETENTION_MODULE_BITMAP_SZ; i++) { + val |= map.bitmap[i]; + } + return (val == 0); + } + return false; +} + static inline bool references_exist(struct sleep_retention_module_object * const self) { uint32_t references = 0; @@ -844,7 +889,6 @@ bool IRAM_ATTR sleep_retention_module_bitmap_eq(sleep_retention_module_bitmap_t return true; } - static void module_action(sleep_retention_module_t module, sleep_retention_module_t dep_module, int action) { switch (action) @@ -852,6 +896,8 @@ static void module_action(sleep_retention_module_t module, sleep_retention_modul case 0: break; /* Nothing to do */ case 1: set_reference(instance(dep_module), module); break; /* allocate */ case 2: clr_reference(instance(dep_module), module); break; /* free */ + case 3: refarray_set_bit(instance(dep_module), 1, module); break; /* attach */ + case 4: refarray_clr_bit(instance(dep_module), 1, module); break; /* detach */ default: break; } } @@ -1070,7 +1116,7 @@ static esp_err_t passive_module_attach(sleep_retention_module_t module) if (module_is_inited(module) && module_is_created(module) && !module_is_retained(module)) { module_entries_move(module, &s_retention.context[1], &s_retention.retention); s_retention.retention_modules.bitmap[module >> 5] |= BIT(module % 32); - err = module_action_wrapper(module, (BIT(31) | action(0)), passive_module_attach); + err = module_action_wrapper(module, (BIT(31) | action(3)), passive_module_attach); } _lock_release_recursive(&s_retention.lock); return err; @@ -1089,7 +1135,7 @@ esp_err_t sleep_retention_module_attach(sleep_retention_module_t module) if (module_runtime_attach(instance(module))) { module_entries_move(module, &s_retention.context[1], &s_retention.retention); s_retention.retention_modules.bitmap[module >> 5] |= BIT(module % 32); - err = module_action_wrapper(module, action(0), passive_module_attach); + err = module_action_wrapper(module, action(3), passive_module_attach); } else { err = ESP_ERR_NOT_SUPPORTED; } @@ -1113,9 +1159,11 @@ static esp_err_t passive_module_detach(sleep_retention_module_t module) assert(module_runtime_attach(instance(module)) && "Illegal dependency"); assert(module_is_inited(module) && "All passive module must be inited first!"); if (module_is_inited(module) && module_is_created(module) && module_is_retained(module)) { - module_entries_move(module, &s_retention.retention, &s_retention.context[1]); - s_retention.retention_modules.bitmap[module >> 5] &= ~BIT(module % 32); - err = module_action_wrapper(module, (BIT(31) | action(0)), passive_module_detach); + if (refarray_zero(instance(module), 1)) { + module_entries_move(module, &s_retention.retention, &s_retention.context[1]); + s_retention.retention_modules.bitmap[module >> 5] &= ~BIT(module % 32); + err = module_action_wrapper(module, (BIT(31) | action(4)), passive_module_detach); + } } _lock_release_recursive(&s_retention.lock); return err; @@ -1134,7 +1182,7 @@ esp_err_t sleep_retention_module_detach(sleep_retention_module_t module) if (module_runtime_attach(instance(module))) { module_entries_move(module, &s_retention.retention, &s_retention.context[1]); s_retention.retention_modules.bitmap[module >> 5] &= ~BIT(module % 32); - err = module_action_wrapper(module, action(0), passive_module_detach); + err = module_action_wrapper(module, action(4), passive_module_detach); } else { err = ESP_ERR_NOT_SUPPORTED; } From 710a04f649c90bc83421db3c2b5a79d2babe00d9 Mon Sep 17 00:00:00 2001 From: Li Shuai Date: Wed, 1 Apr 2026 12:27:00 +0800 Subject: [PATCH 04/22] change(esp_hw_support): attribute assert check in module retention allocate and free --- components/esp_hw_support/sleep_retention.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/components/esp_hw_support/sleep_retention.c b/components/esp_hw_support/sleep_retention.c index eb80a41f9f3..5e729abfa93 100644 --- a/components/esp_hw_support/sleep_retention.c +++ b/components/esp_hw_support/sleep_retention.c @@ -894,8 +894,20 @@ static void module_action(sleep_retention_module_t module, sleep_retention_modul switch (action) { case 0: break; /* Nothing to do */ - case 1: set_reference(instance(dep_module), module); break; /* allocate */ - case 2: clr_reference(instance(dep_module), module); break; /* free */ + case 1: { /* allocate */ + set_reference(instance(dep_module), module); + if (module_is_passive(instance(dep_module)) && module_runtime_attach(instance(dep_module))) { + assert(module_runtime_attach(instance(module))); + } + } + break; + case 2: { /* free */ + clr_reference(instance(dep_module), module); + if (module_is_passive(instance(dep_module)) && module_runtime_attach(instance(dep_module))) { + assert(module_runtime_attach(instance(module))); + } + } + break; case 3: refarray_set_bit(instance(dep_module), 1, module); break; /* attach */ case 4: refarray_clr_bit(instance(dep_module), 1, module); break; /* detach */ default: break; From 3bef3296c9ea3f5fc5c27935f606ca900bb75ad4 Mon Sep 17 00:00:00 2001 From: Li Shuai Date: Wed, 15 Apr 2026 21:09:43 +0800 Subject: [PATCH 05/22] fix(esp_hw_support): fix regdma link dump to print module number --- .../include/esp_private/esp_regdma.h | 8 +++++ components/esp_hw_support/port/regdma_link.c | 35 ++++++++++++------- 2 files changed, 31 insertions(+), 12 deletions(-) diff --git a/components/esp_hw_support/include/esp_private/esp_regdma.h b/components/esp_hw_support/include/esp_private/esp_regdma.h index ff47aa943c8..0e51158c8d1 100644 --- a/components/esp_hw_support/include/esp_private/esp_regdma.h +++ b/components/esp_hw_support/include/esp_private/esp_regdma.h @@ -336,6 +336,14 @@ void regdma_link_set_write_wait_content(void *link, uint32_t value, uint32_t mas */ void regdma_link_set_skip_flag(void *link, bool skip_backup, bool skip_restore); +/** + * @brief Dump all node information of the REGDMA linked list from link to tail indicated by the entry argument + * @param link The REGDMA linkded list head pointer + * @param tail Dump end linked list node pointer + * @param entry For nodes that support branching, use the branch specified by entry argument recursively + */ +void regdma_link_dump_sublink(FILE *out, void *link, void *tail, int entry); + /** * @brief Dump all node information of the REGDMA linked list indicated by the entry argument * @param link The REGDMA linkded list head pointer diff --git a/components/esp_hw_support/port/regdma_link.c b/components/esp_hw_support/port/regdma_link.c index 1fb365877f1..a4933d3581d 100644 --- a/components/esp_hw_support/port/regdma_link.c +++ b/components/esp_hw_support/port/regdma_link.c @@ -755,7 +755,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, @@ -768,7 +768,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, @@ -780,7 +780,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); @@ -791,7 +791,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, @@ -804,7 +804,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, @@ -816,7 +816,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); @@ -844,20 +844,31 @@ static void print_link_info(FILE *out, void *args, int entry, int depth) (*prinf_fn[it])(out, args); } -void regdma_link_dump(FILE *out, void *link, int entry) +void regdma_link_dump_sublink(FILE *out, void *link, void *tail, int entry) { assert(entry < REGDMA_LINK_ENTRY_NUM); - void *next = link; if (link) { - do { - print_link_info(out, next, entry, 0); - } while ((next = regdma_link_get_next(next, entry)) != NULL); + if (link != tail) { + void *next = link; + do { + print_link_info(out, next, entry, 0); + } while ((next = regdma_link_get_next(next, entry)) != tail); + } + if (tail) { + print_link_info(out, tail, entry, 0); + } } else { - fprintf(out, "This REGDMA linked list is empty!\n"); + fprintf(out, "This REGDMA linked list (entry[%d]) is empty!\n", entry); } } +void regdma_link_dump(FILE *out, void *link, int entry) +{ + assert(entry < REGDMA_LINK_ENTRY_NUM); + regdma_link_dump_sublink(out, link, NULL, entry); +} + regdma_link_mode_t regdma_link_get_config_mode(const regdma_link_config_t *config) { From 0d9587952d6aabd29dc67f4f5c16f6dd3fcf12b4 Mon Sep 17 00:00:00 2001 From: Li Shuai Date: Thu, 16 Apr 2026 20:26:15 +0800 Subject: [PATCH 06/22] change(esp_wifi): support wifi module retention runtime attach and detach --- .../lowpower/port/esp32c5/sleep_clock.c | 4 ++-- components/esp_hw_support/sleep_modem.c | 6 +++++- components/esp_phy/esp32c5/phy_init_data.c | 13 ++++++++++++- components/esp_wifi/src/wifi_init.c | 11 ++++++++++- 4 files changed, 29 insertions(+), 5 deletions(-) diff --git a/components/esp_hw_support/lowpower/port/esp32c5/sleep_clock.c b/components/esp_hw_support/lowpower/port/esp32c5/sleep_clock.c index f8c71f4e6e1..2ca8d5defc5 100644 --- a/components/esp_hw_support/lowpower/port/esp32c5/sleep_clock.c +++ b/components/esp_hw_support/lowpower/port/esp32c5/sleep_clock.c @@ -142,7 +142,7 @@ ESP_SYSTEM_INIT_FN(sleep_clock_startup_init, SECONDARY, BIT(0), 106) { sleep_retention_module_init_param_t init_param = { .cbs = { .create = { .handle = sleep_clock_system_retention_init, .arg = NULL } }, - .attribute = SLEEP_RETENTION_MODULE_ATTR_PASSIVE + .attribute = SLEEP_RETENTION_MODULE_ATTR_PASSIVE | SLEEP_RETENTION_MODULE_ATTR_ATTACH }; sleep_retention_module_init(SLEEP_RETENTION_MODULE_CLOCK_SYSTEM, &init_param); @@ -150,7 +150,7 @@ ESP_SYSTEM_INIT_FN(sleep_clock_startup_init, SECONDARY, BIT(0), 106) init_param = (sleep_retention_module_init_param_t) { .cbs = { .create = { .handle = sleep_clock_modem_retention_init, .arg = NULL } }, .depends.bitmap[SLEEP_RETENTION_MODULE_CLOCK_SYSTEM >> 5] = BIT(SLEEP_RETENTION_MODULE_CLOCK_SYSTEM % 32), - .attribute = SLEEP_RETENTION_MODULE_ATTR_PASSIVE + .attribute = SLEEP_RETENTION_MODULE_ATTR_PASSIVE | SLEEP_RETENTION_MODULE_ATTR_ATTACH }; sleep_retention_module_init(SLEEP_RETENTION_MODULE_CLOCK_MODEM, &init_param); #endif diff --git a/components/esp_hw_support/sleep_modem.c b/components/esp_hw_support/sleep_modem.c index fb318afd660..72d9cc20ef0 100644 --- a/components/esp_hw_support/sleep_modem.c +++ b/components/esp_hw_support/sleep_modem.c @@ -198,6 +198,7 @@ bool modem_domain_pd_allowed(void) #if SOC_PM_MODEM_RETENTION_BY_REGDMA && SOC_PAU_SUPPORTED const sleep_retention_module_bitmap_t inited_modules = sleep_retention_get_inited_modules(); const sleep_retention_module_bitmap_t created_modules = sleep_retention_get_created_modules(); + const sleep_retention_module_bitmap_t retained_modules = sleep_retention_get_retained_modules(); sleep_retention_module_bitmap_t mask = (sleep_retention_module_bitmap_t){ .bitmap = { 0 } }; #if SOC_WIFI_SUPPORTED @@ -215,7 +216,10 @@ bool modem_domain_pd_allowed(void) const sleep_retention_module_bitmap_t modem_domain_inited_modules = sleep_retention_module_bitmap_and(inited_modules, mask); const sleep_retention_module_bitmap_t modem_domain_created_modules = sleep_retention_module_bitmap_and(created_modules, mask); - return sleep_retention_module_bitmap_eq(modem_domain_inited_modules, modem_domain_created_modules); + const sleep_retention_module_bitmap_t modem_domain_retained_modules = sleep_retention_module_bitmap_and(retained_modules, mask); + bool ic = sleep_retention_module_bitmap_eq(modem_domain_inited_modules, modem_domain_created_modules); + bool cr = sleep_retention_module_bitmap_eq(modem_domain_created_modules, modem_domain_retained_modules); + return ic && cr; #else return false; /* MODEM power domain is controlled by each module (WiFi, Bluetooth or 15.4) of modem */ #endif diff --git a/components/esp_phy/esp32c5/phy_init_data.c b/components/esp_phy/esp32c5/phy_init_data.c index fcf1e743e2b..a216a678c0b 100644 --- a/components/esp_phy/esp32c5/phy_init_data.c +++ b/components/esp_phy/esp32c5/phy_init_data.c @@ -316,6 +316,7 @@ void esp_phy_sleep_data_init(void) { sleep_retention_module_init_param_t init_param = { .cbs = { .create = { .handle = sleep_retention_wifi_bb_init, .arg = NULL } }, + .attribute = SLEEP_RETENTION_MODULE_ATTR_ATTACH, .depends = RETENTION_MODULE_BITMAP_INIT(CLOCK_MODEM) }; esp_err_t err = sleep_retention_module_init(SLEEP_RETENTION_MODULE_WIFI_BB, &init_param); @@ -326,12 +327,22 @@ void esp_phy_sleep_data_init(void) err = sleep_retention_module_allocate(SLEEP_RETENTION_MODULE_WIFI_BB); if (err != ESP_OK) { ESP_LOGW(TAG, "failed to allocate sleep retention linked list for wifi bb retention"); + return; + } + err = sleep_retention_module_attach(SLEEP_RETENTION_MODULE_WIFI_BB); + if (err != ESP_OK) { + ESP_LOGW(TAG, "failed to attach sleep retention linked list for wifi bb retention"); } } void esp_phy_sleep_data_deinit(void) { - esp_err_t err = sleep_retention_module_free(SLEEP_RETENTION_MODULE_WIFI_BB); + esp_err_t err = sleep_retention_module_detach(SLEEP_RETENTION_MODULE_WIFI_BB); + if (err != ESP_OK) { + ESP_LOGW(TAG, "failed to detach sleep retention linked list for wifi bb retention"); + return; + } + err = sleep_retention_module_free(SLEEP_RETENTION_MODULE_WIFI_BB); if (err != ESP_OK) { ESP_LOGW(TAG, "failed to free sleep retention linked list for wifi bb retention"); return; diff --git a/components/esp_wifi/src/wifi_init.c b/components/esp_wifi/src/wifi_init.c index 37e2552bfad..81394283272 100644 --- a/components/esp_wifi/src/wifi_init.c +++ b/components/esp_wifi/src/wifi_init.c @@ -162,6 +162,10 @@ static void esp_wifi_mac_pd_mem_init(void) if (err != ESP_OK) { ESP_LOGW(TAG, "failed to allocate sleep retention linked list for wifi mac retention"); } + err = sleep_retention_module_attach(SLEEP_RETENTION_MODULE_WIFI_MAC); + if (err != ESP_OK) { + ESP_LOGW(TAG, "failed to attach sleep retention linked list for wifi mac retention"); + } #endif esp_wifi_internal_set_mac_sleep(true); } @@ -169,7 +173,11 @@ static void esp_wifi_mac_pd_mem_deinit(void) { esp_wifi_internal_set_mac_sleep(false); #if SOC_PM_MODEM_RETENTION_BY_REGDMA - esp_err_t err = sleep_retention_module_free(SLEEP_RETENTION_MODULE_WIFI_MAC); + esp_err_t err = sleep_retention_module_detach(SLEEP_RETENTION_MODULE_WIFI_MAC); + if (err != ESP_OK) { + ESP_LOGW(TAG, "failed to detach sleep retention linked list for wifi mac retention"); + } + err = sleep_retention_module_free(SLEEP_RETENTION_MODULE_WIFI_MAC); if (err != ESP_OK) { ESP_LOGW(TAG, "failed to free sleep retention linked list for wifi mac retention"); } @@ -385,6 +393,7 @@ esp_err_t esp_wifi_init(const wifi_init_config_t *config) #if SOC_PM_MODEM_RETENTION_BY_REGDMA sleep_retention_module_init_param_t init_param = { .cbs = { .create = { .handle = init_wifi_mac_sleep_retention, .arg = NULL } }, + .attribute = SLEEP_RETENTION_MODULE_ATTR_ATTACH }; init_param.depends.bitmap[SLEEP_RETENTION_MODULE_WIFI_BB >> 5] |= BIT(SLEEP_RETENTION_MODULE_WIFI_BB % 32); init_param.depends.bitmap[SLEEP_RETENTION_MODULE_CLOCK_MODEM >> 5] |= BIT(SLEEP_RETENTION_MODULE_CLOCK_MODEM % 32); From ec1705c362e65c1aa777ba3625539e51090090fc Mon Sep 17 00:00:00 2001 From: Li Shuai Date: Thu, 16 Apr 2026 20:39:56 +0800 Subject: [PATCH 07/22] change(esp_system): support system minimum digital peripherals retention runtime attach and detach --- components/esp_hw_support/sleep_system_peripheral.c | 7 +++++++ components/esp_system/int_wdt.c | 6 ++++++ .../esp_system/task_wdt/task_wdt_impl_timergroup.c | 13 +++++++++++-- 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/components/esp_hw_support/sleep_system_peripheral.c b/components/esp_hw_support/sleep_system_peripheral.c index 81d6569e414..0a76f5550a2 100644 --- a/components/esp_hw_support/sleep_system_peripheral.c +++ b/components/esp_hw_support/sleep_system_peripheral.c @@ -172,6 +172,7 @@ ESP_SYSTEM_INIT_FN(sleep_sys_periph_startup_init, SECONDARY, BIT(0), 107) { sleep_retention_module_init_param_t init_param = { .cbs = { .create = { .handle = sleep_sys_periph_retention_init, .arg = NULL } }, + .attribute = SLEEP_RETENTION_MODULE_ATTR_ATTACH, .depends.bitmap[SLEEP_RETENTION_MODULE_CLOCK_SYSTEM >> 5] = BIT(SLEEP_RETENTION_MODULE_CLOCK_SYSTEM % 32) }; esp_err_t err = sleep_retention_module_init(SLEEP_RETENTION_MODULE_SYS_PERIPH, &init_param); @@ -180,6 +181,12 @@ ESP_SYSTEM_INIT_FN(sleep_sys_periph_startup_init, SECONDARY, BIT(0), 107) if (err != ESP_OK) { ESP_LOGW(TAG, "failed to allocate sleep retention linked list for system peripherals retention"); } + if (err == ESP_OK) { + err = sleep_retention_module_attach(SLEEP_RETENTION_MODULE_SYS_PERIPH); + if (err != ESP_OK) { + ESP_LOGW(TAG, "failed to attach sleep retention linked list for system peripherals retention"); + } + } } return ESP_OK; } diff --git a/components/esp_system/int_wdt.c b/components/esp_system/int_wdt.c index 6c460cd1fec..7a1dca6439e 100644 --- a/components/esp_system/int_wdt.c +++ b/components/esp_system/int_wdt.c @@ -73,6 +73,7 @@ static esp_err_t esp_int_wdt_retention_enable(uint32_t group_id) { sleep_retention_module_init_param_t init_param = { .cbs = { .create = { .handle = sleep_int_wdt_retention_init, .arg = &group_id } }, + .attribute = SLEEP_RETENTION_MODULE_ATTR_ATTACH, .depends = RETENTION_MODULE_BITMAP_INIT(CLOCK_SYSTEM) }; esp_err_t err = sleep_retention_module_init((group_id == 0) ? SLEEP_RETENTION_MODULE_TG0_WDT : SLEEP_RETENTION_MODULE_TG1_WDT, &init_param); @@ -80,6 +81,11 @@ static esp_err_t esp_int_wdt_retention_enable(uint32_t group_id) err = sleep_retention_module_allocate((group_id == 0) ? SLEEP_RETENTION_MODULE_TG0_WDT : SLEEP_RETENTION_MODULE_TG1_WDT); if (err != ESP_OK) { ESP_LOGW(TAG, "Failed to allocate sleep retention linked list for interrupt watchdog timer retention"); + } else { + err = sleep_retention_module_attach((group_id == 0) ? SLEEP_RETENTION_MODULE_TG0_WDT : SLEEP_RETENTION_MODULE_TG1_WDT); + if (err != ESP_OK) { + ESP_LOGW(TAG, "Failed to attach sleep retention linked list for interrupt watchdog timer retention"); + } } } return err; diff --git a/components/esp_system/task_wdt/task_wdt_impl_timergroup.c b/components/esp_system/task_wdt/task_wdt_impl_timergroup.c index dba9c705d10..26b6beb636d 100644 --- a/components/esp_system/task_wdt/task_wdt_impl_timergroup.c +++ b/components/esp_system/task_wdt/task_wdt_impl_timergroup.c @@ -71,6 +71,7 @@ static esp_err_t esp_task_wdt_retention_enable(uint32_t group_id) { sleep_retention_module_init_param_t init_param = { .cbs = { .create = { .handle = sleep_task_wdt_retention_init, .arg = &group_id } }, + .attribute = SLEEP_RETENTION_MODULE_ATTR_ATTACH, .depends = RETENTION_MODULE_BITMAP_INIT(CLOCK_SYSTEM) }; esp_err_t err = sleep_retention_module_init((group_id == 0) ? SLEEP_RETENTION_MODULE_TG0_WDT : SLEEP_RETENTION_MODULE_TG1_WDT, &init_param); @@ -78,6 +79,11 @@ static esp_err_t esp_task_wdt_retention_enable(uint32_t group_id) err = sleep_retention_module_allocate((group_id == 0) ? SLEEP_RETENTION_MODULE_TG0_WDT : SLEEP_RETENTION_MODULE_TG1_WDT); if (err != ESP_OK) { ESP_LOGW(TAG, "Failed to allocate sleep retention linked list for task watchdog timer retention"); + } else { + err = sleep_retention_module_attach((group_id == 0) ? SLEEP_RETENTION_MODULE_TG0_WDT : SLEEP_RETENTION_MODULE_TG1_WDT); + if (err != ESP_OK) { + ESP_LOGW(TAG, "Failed to attach sleep retention linked list for task watchdog timer retention"); + } } } return err; @@ -85,9 +91,12 @@ static esp_err_t esp_task_wdt_retention_enable(uint32_t group_id) static esp_err_t esp_task_wdt_retention_disable(uint32_t group_id) { - esp_err_t err = sleep_retention_module_free((group_id == 0) ? SLEEP_RETENTION_MODULE_TG0_WDT : SLEEP_RETENTION_MODULE_TG1_WDT); + esp_err_t err = sleep_retention_module_detach((group_id == 0) ? SLEEP_RETENTION_MODULE_TG0_WDT : SLEEP_RETENTION_MODULE_TG1_WDT); if (err == ESP_OK) { - err = sleep_retention_module_deinit((group_id == 0) ? SLEEP_RETENTION_MODULE_TG0_WDT : SLEEP_RETENTION_MODULE_TG1_WDT); + err = sleep_retention_module_free((group_id == 0) ? SLEEP_RETENTION_MODULE_TG0_WDT : SLEEP_RETENTION_MODULE_TG1_WDT); + if (err == ESP_OK) { + err = sleep_retention_module_deinit((group_id == 0) ? SLEEP_RETENTION_MODULE_TG0_WDT : SLEEP_RETENTION_MODULE_TG1_WDT); + } } return err; } From e7921ed7dc0f4963c5d12d808e0d4ed9d03dbf0a Mon Sep 17 00:00:00 2001 From: cjin Date: Mon, 20 Apr 2026 08:49:38 +0800 Subject: [PATCH 08/22] feat(sleep): added attach attribute to system and modem clock retention --- .../esp_hw_support/lowpower/port/esp32c5/sleep_clock.c | 6 +++++- .../esp_hw_support/lowpower/port/esp32c6/sleep_clock.c | 10 +++++++--- .../lowpower/port/esp32c61/sleep_clock.c | 10 +++++++--- .../esp_hw_support/lowpower/port/esp32h2/sleep_clock.c | 10 +++++++--- .../lowpower/port/esp32h21/sleep_clock.c | 10 +++++++--- .../esp_hw_support/lowpower/port/esp32h4/sleep_clock.c | 10 +++++++--- .../esp_hw_support/lowpower/port/esp32p4/sleep_clock.c | 8 ++++++-- .../lowpower/port/esp32s31/sleep_clock.c | 10 +++++++--- 8 files changed, 53 insertions(+), 21 deletions(-) diff --git a/components/esp_hw_support/lowpower/port/esp32c5/sleep_clock.c b/components/esp_hw_support/lowpower/port/esp32c5/sleep_clock.c index 2ca8d5defc5..a4a587993ad 100644 --- a/components/esp_hw_support/lowpower/port/esp32c5/sleep_clock.c +++ b/components/esp_hw_support/lowpower/port/esp32c5/sleep_clock.c @@ -96,6 +96,7 @@ bool clock_domain_pd_allowed(void) { const sleep_retention_module_bitmap_t inited_modules = sleep_retention_get_inited_modules(); const sleep_retention_module_bitmap_t created_modules = sleep_retention_get_created_modules(); + const sleep_retention_module_bitmap_t retained_modules = sleep_retention_get_retained_modules(); const sleep_retention_module_bitmap_t sys_clk_dep_modules = (sleep_retention_module_bitmap_t){ .bitmap[SLEEP_RETENTION_MODULE_SYS_PERIPH >> 5] = BIT(SLEEP_RETENTION_MODULE_SYS_PERIPH % 32) }; /* The clock and reset of MODEM (WiFi, BLE and 15.4) modules are managed @@ -135,7 +136,10 @@ bool clock_domain_pd_allowed(void) const sleep_retention_module_bitmap_t clock_domain_inited_modules = sleep_retention_module_bitmap_and(inited_modules, mask); const sleep_retention_module_bitmap_t clock_domain_created_modules = sleep_retention_module_bitmap_and(created_modules, mask); - return sleep_retention_module_bitmap_eq(clock_domain_inited_modules, clock_domain_created_modules); + const sleep_retention_module_bitmap_t clock_domain_retained_modules = sleep_retention_module_bitmap_and(retained_modules, mask); + bool ic = sleep_retention_module_bitmap_eq(clock_domain_inited_modules, clock_domain_created_modules); + bool cr = sleep_retention_module_bitmap_eq(clock_domain_created_modules, clock_domain_retained_modules); + return ic && cr; } ESP_SYSTEM_INIT_FN(sleep_clock_startup_init, SECONDARY, BIT(0), 106) diff --git a/components/esp_hw_support/lowpower/port/esp32c6/sleep_clock.c b/components/esp_hw_support/lowpower/port/esp32c6/sleep_clock.c index f6b72e5bffd..a0733638893 100644 --- a/components/esp_hw_support/lowpower/port/esp32c6/sleep_clock.c +++ b/components/esp_hw_support/lowpower/port/esp32c6/sleep_clock.c @@ -63,6 +63,7 @@ bool clock_domain_pd_allowed(void) { const sleep_retention_module_bitmap_t inited_modules = sleep_retention_get_inited_modules(); const sleep_retention_module_bitmap_t created_modules = sleep_retention_get_created_modules(); + const sleep_retention_module_bitmap_t retained_modules = sleep_retention_get_retained_modules(); const sleep_retention_module_bitmap_t sys_clk_dep_modules = (sleep_retention_module_bitmap_t){ .bitmap[SLEEP_RETENTION_MODULE_SYS_PERIPH >> 5] = BIT(SLEEP_RETENTION_MODULE_SYS_PERIPH % 32) }; /* The clock and reset of MODEM (WiFi, BLE and 15.4) modules are managed @@ -100,21 +101,24 @@ bool clock_domain_pd_allowed(void) const sleep_retention_module_bitmap_t clock_domain_inited_modules = sleep_retention_module_bitmap_and(inited_modules, mask); const sleep_retention_module_bitmap_t clock_domain_created_modules = sleep_retention_module_bitmap_and(created_modules, mask); - return sleep_retention_module_bitmap_eq(clock_domain_inited_modules, clock_domain_created_modules); + const sleep_retention_module_bitmap_t clock_domain_retained_modules = sleep_retention_module_bitmap_and(retained_modules, mask); + bool ic = sleep_retention_module_bitmap_eq(clock_domain_inited_modules, clock_domain_created_modules); + bool cr = sleep_retention_module_bitmap_eq(clock_domain_created_modules, clock_domain_retained_modules); + return ic && cr; } ESP_SYSTEM_INIT_FN(sleep_clock_startup_init, SECONDARY, BIT(0), 106) { sleep_retention_module_init_param_t init_param = { .cbs = { .create = { .handle = sleep_clock_system_retention_init, .arg = NULL } }, - .attribute = SLEEP_RETENTION_MODULE_ATTR_PASSIVE + .attribute = SLEEP_RETENTION_MODULE_ATTR_PASSIVE | SLEEP_RETENTION_MODULE_ATTR_ATTACH }; sleep_retention_module_init(SLEEP_RETENTION_MODULE_CLOCK_SYSTEM, &init_param); #if CONFIG_MAC_BB_PD || CONFIG_BT_LE_SLEEP_ENABLE || CONFIG_IEEE802154_SLEEP_ENABLE init_param = (sleep_retention_module_init_param_t) { .cbs = { .create = { .handle = sleep_clock_modem_retention_init, .arg = NULL } }, - .attribute = SLEEP_RETENTION_MODULE_ATTR_PASSIVE + .attribute = SLEEP_RETENTION_MODULE_ATTR_PASSIVE | SLEEP_RETENTION_MODULE_ATTR_ATTACH }; sleep_retention_module_init(SLEEP_RETENTION_MODULE_CLOCK_MODEM, &init_param); #endif diff --git a/components/esp_hw_support/lowpower/port/esp32c61/sleep_clock.c b/components/esp_hw_support/lowpower/port/esp32c61/sleep_clock.c index aede05755e6..d06f93c616c 100644 --- a/components/esp_hw_support/lowpower/port/esp32c61/sleep_clock.c +++ b/components/esp_hw_support/lowpower/port/esp32c61/sleep_clock.c @@ -74,6 +74,7 @@ bool clock_domain_pd_allowed(void) { const sleep_retention_module_bitmap_t inited_modules = sleep_retention_get_inited_modules(); const sleep_retention_module_bitmap_t created_modules = sleep_retention_get_created_modules(); + const sleep_retention_module_bitmap_t retained_modules = sleep_retention_get_retained_modules(); const sleep_retention_module_bitmap_t sys_clk_dep_modules = (sleep_retention_module_bitmap_t){ .bitmap[SLEEP_RETENTION_MODULE_SYS_PERIPH >> 5] = BIT(SLEEP_RETENTION_MODULE_SYS_PERIPH % 32) }; /* The clock and reset of MODEM (WiFi, BLE and 15.4) modules are managed @@ -109,14 +110,17 @@ bool clock_domain_pd_allowed(void) const sleep_retention_module_bitmap_t clock_domain_inited_modules = sleep_retention_module_bitmap_and(inited_modules, mask); const sleep_retention_module_bitmap_t clock_domain_created_modules = sleep_retention_module_bitmap_and(created_modules, mask); - return sleep_retention_module_bitmap_eq(clock_domain_inited_modules, clock_domain_created_modules); + const sleep_retention_module_bitmap_t clock_domain_retained_modules = sleep_retention_module_bitmap_and(retained_modules, mask); + bool ic = sleep_retention_module_bitmap_eq(clock_domain_inited_modules, clock_domain_created_modules); + bool cr = sleep_retention_module_bitmap_eq(clock_domain_created_modules, clock_domain_retained_modules); + return ic && cr; } ESP_SYSTEM_INIT_FN(sleep_clock_startup_init, SECONDARY, BIT(0), 106) { sleep_retention_module_init_param_t init_param = { .cbs = { .create = { .handle = sleep_clock_system_retention_init, .arg = NULL } }, - .attribute = SLEEP_RETENTION_MODULE_ATTR_PASSIVE + .attribute = SLEEP_RETENTION_MODULE_ATTR_PASSIVE | SLEEP_RETENTION_MODULE_ATTR_ATTACH }; sleep_retention_module_init(SLEEP_RETENTION_MODULE_CLOCK_SYSTEM, &init_param); @@ -124,7 +128,7 @@ ESP_SYSTEM_INIT_FN(sleep_clock_startup_init, SECONDARY, BIT(0), 106) init_param = (sleep_retention_module_init_param_t) { .cbs = { .create = { .handle = sleep_clock_modem_retention_init, .arg = NULL } }, .depends.bitmap[SLEEP_RETENTION_MODULE_CLOCK_SYSTEM >> 5] = BIT(SLEEP_RETENTION_MODULE_CLOCK_SYSTEM % 32), - .attribute = SLEEP_RETENTION_MODULE_ATTR_PASSIVE + .attribute = SLEEP_RETENTION_MODULE_ATTR_PASSIVE | SLEEP_RETENTION_MODULE_ATTR_ATTACH }; sleep_retention_module_init(SLEEP_RETENTION_MODULE_CLOCK_MODEM, &init_param); #endif diff --git a/components/esp_hw_support/lowpower/port/esp32h2/sleep_clock.c b/components/esp_hw_support/lowpower/port/esp32h2/sleep_clock.c index c9a0f8dfb89..25051828638 100644 --- a/components/esp_hw_support/lowpower/port/esp32h2/sleep_clock.c +++ b/components/esp_hw_support/lowpower/port/esp32h2/sleep_clock.c @@ -70,6 +70,7 @@ bool clock_domain_pd_allowed(void) { const sleep_retention_module_bitmap_t inited_modules = sleep_retention_get_inited_modules(); const sleep_retention_module_bitmap_t created_modules = sleep_retention_get_created_modules(); + const sleep_retention_module_bitmap_t retained_modules = sleep_retention_get_retained_modules(); const sleep_retention_module_bitmap_t sys_clk_dep_modules = (sleep_retention_module_bitmap_t){ .bitmap[SLEEP_RETENTION_MODULE_SYS_PERIPH >> 5] = BIT(SLEEP_RETENTION_MODULE_SYS_PERIPH % 32) }; /* The clock and reset of MODEM (WiFi, BLE and 15.4) modules are managed @@ -103,21 +104,24 @@ bool clock_domain_pd_allowed(void) const sleep_retention_module_bitmap_t clock_domain_inited_modules = sleep_retention_module_bitmap_and(inited_modules, mask); const sleep_retention_module_bitmap_t clock_domain_created_modules = sleep_retention_module_bitmap_and(created_modules, mask); - return sleep_retention_module_bitmap_eq(clock_domain_inited_modules, clock_domain_created_modules); + const sleep_retention_module_bitmap_t clock_domain_retained_modules = sleep_retention_module_bitmap_and(retained_modules, mask); + bool ic = sleep_retention_module_bitmap_eq(clock_domain_inited_modules, clock_domain_created_modules); + bool cr = sleep_retention_module_bitmap_eq(clock_domain_created_modules, clock_domain_retained_modules); + return ic && cr; } ESP_SYSTEM_INIT_FN(sleep_clock_startup_init, SECONDARY, BIT(0), 106) { sleep_retention_module_init_param_t init_param = { .cbs = { .create = { .handle = sleep_clock_system_retention_init, .arg = NULL } }, - .attribute = SLEEP_RETENTION_MODULE_ATTR_PASSIVE + .attribute = SLEEP_RETENTION_MODULE_ATTR_PASSIVE | SLEEP_RETENTION_MODULE_ATTR_ATTACH }; sleep_retention_module_init(SLEEP_RETENTION_MODULE_CLOCK_SYSTEM, &init_param); #if CONFIG_MAC_BB_PD || CONFIG_BT_LE_SLEEP_ENABLE || CONFIG_IEEE802154_SLEEP_ENABLE init_param = (sleep_retention_module_init_param_t) { .cbs = { .create = { .handle = sleep_clock_modem_retention_init, .arg = NULL } }, - .attribute = SLEEP_RETENTION_MODULE_ATTR_PASSIVE + .attribute = SLEEP_RETENTION_MODULE_ATTR_PASSIVE | SLEEP_RETENTION_MODULE_ATTR_ATTACH }; sleep_retention_module_init(SLEEP_RETENTION_MODULE_CLOCK_MODEM, &init_param); #endif diff --git a/components/esp_hw_support/lowpower/port/esp32h21/sleep_clock.c b/components/esp_hw_support/lowpower/port/esp32h21/sleep_clock.c index 3222682b249..3060e6adc57 100644 --- a/components/esp_hw_support/lowpower/port/esp32h21/sleep_clock.c +++ b/components/esp_hw_support/lowpower/port/esp32h21/sleep_clock.c @@ -71,6 +71,7 @@ bool clock_domain_pd_allowed(void) { const sleep_retention_module_bitmap_t inited_modules = sleep_retention_get_inited_modules(); const sleep_retention_module_bitmap_t created_modules = sleep_retention_get_created_modules(); + const sleep_retention_module_bitmap_t retained_modules = sleep_retention_get_retained_modules(); const sleep_retention_module_bitmap_t sys_clk_dep_modules = (sleep_retention_module_bitmap_t){ .bitmap[SLEEP_RETENTION_MODULE_SYS_PERIPH >> 5] = BIT(SLEEP_RETENTION_MODULE_SYS_PERIPH % 32) }; /* The clock and reset of MODEM (BLE and 15.4) modules are managed @@ -108,14 +109,17 @@ bool clock_domain_pd_allowed(void) #endif const sleep_retention_module_bitmap_t clock_domain_inited_modules = sleep_retention_module_bitmap_and(inited_modules, mask); const sleep_retention_module_bitmap_t clock_domain_created_modules = sleep_retention_module_bitmap_and(created_modules, mask); - return sleep_retention_module_bitmap_eq(clock_domain_inited_modules, clock_domain_created_modules); + const sleep_retention_module_bitmap_t clock_domain_retained_modules = sleep_retention_module_bitmap_and(retained_modules, mask); + bool ic = sleep_retention_module_bitmap_eq(clock_domain_inited_modules, clock_domain_created_modules); + bool cr = sleep_retention_module_bitmap_eq(clock_domain_created_modules, clock_domain_retained_modules); + return ic && cr; } ESP_SYSTEM_INIT_FN(sleep_clock_startup_init, SECONDARY, BIT(0), 106) { sleep_retention_module_init_param_t init_param = { .cbs = { .create = { .handle = sleep_clock_system_retention_init, .arg = NULL } }, - .attribute = SLEEP_RETENTION_MODULE_ATTR_PASSIVE + .attribute = SLEEP_RETENTION_MODULE_ATTR_PASSIVE | SLEEP_RETENTION_MODULE_ATTR_ATTACH }; sleep_retention_module_init(SLEEP_RETENTION_MODULE_CLOCK_SYSTEM, &init_param); @@ -123,7 +127,7 @@ ESP_SYSTEM_INIT_FN(sleep_clock_startup_init, SECONDARY, BIT(0), 106) init_param = (sleep_retention_module_init_param_t) { .cbs = { .create = { .handle = sleep_clock_modem_retention_init, .arg = NULL } }, #if !SOC_PM_MODEM_CLK_CONF_RETENTION - .attribute = SLEEP_RETENTION_MODULE_ATTR_PASSIVE + .attribute = SLEEP_RETENTION_MODULE_ATTR_PASSIVE | SLEEP_RETENTION_MODULE_ATTR_ATTACH #endif }; sleep_retention_module_init(SLEEP_RETENTION_MODULE_CLOCK_MODEM, &init_param); diff --git a/components/esp_hw_support/lowpower/port/esp32h4/sleep_clock.c b/components/esp_hw_support/lowpower/port/esp32h4/sleep_clock.c index 4570fd9df9f..60db037050e 100644 --- a/components/esp_hw_support/lowpower/port/esp32h4/sleep_clock.c +++ b/components/esp_hw_support/lowpower/port/esp32h4/sleep_clock.c @@ -72,6 +72,7 @@ bool clock_domain_pd_allowed(void) { const sleep_retention_module_bitmap_t inited_modules = sleep_retention_get_inited_modules(); const sleep_retention_module_bitmap_t created_modules = sleep_retention_get_created_modules(); + const sleep_retention_module_bitmap_t retained_modules = sleep_retention_get_retained_modules(); const sleep_retention_module_bitmap_t sys_clk_dep_modules = (sleep_retention_module_bitmap_t){ .bitmap[SLEEP_RETENTION_MODULE_SYS_PERIPH >> 5] = BIT(SLEEP_RETENTION_MODULE_SYS_PERIPH % 32) }; /* The clock and reset of MODEM (BLE and 15.4) modules are managed @@ -109,14 +110,17 @@ bool clock_domain_pd_allowed(void) #endif const sleep_retention_module_bitmap_t clock_domain_inited_modules = sleep_retention_module_bitmap_and(inited_modules, mask); const sleep_retention_module_bitmap_t clock_domain_created_modules = sleep_retention_module_bitmap_and(created_modules, mask); - return sleep_retention_module_bitmap_eq(clock_domain_inited_modules, clock_domain_created_modules); + const sleep_retention_module_bitmap_t clock_domain_retained_modules = sleep_retention_module_bitmap_and(retained_modules, mask); + bool ic = sleep_retention_module_bitmap_eq(clock_domain_inited_modules, clock_domain_created_modules); + bool cr = sleep_retention_module_bitmap_eq(clock_domain_created_modules, clock_domain_retained_modules); + return ic && cr; } ESP_SYSTEM_INIT_FN(sleep_clock_startup_init, SECONDARY, BIT(0), 106) { sleep_retention_module_init_param_t init_param = { .cbs = { .create = { .handle = sleep_clock_system_retention_init, .arg = NULL } }, - .attribute = SLEEP_RETENTION_MODULE_ATTR_PASSIVE + .attribute = SLEEP_RETENTION_MODULE_ATTR_PASSIVE | SLEEP_RETENTION_MODULE_ATTR_ATTACH }; sleep_retention_module_init(SLEEP_RETENTION_MODULE_CLOCK_SYSTEM, &init_param); @@ -124,7 +128,7 @@ ESP_SYSTEM_INIT_FN(sleep_clock_startup_init, SECONDARY, BIT(0), 106) init_param = (sleep_retention_module_init_param_t) { .cbs = { .create = { .handle = sleep_clock_modem_retention_init, .arg = NULL } }, #if !SOC_PM_MODEM_CLK_CONF_RETENTION - .attribute = SLEEP_RETENTION_MODULE_ATTR_PASSIVE + .attribute = SLEEP_RETENTION_MODULE_ATTR_PASSIVE | SLEEP_RETENTION_MODULE_ATTR_ATTACH #endif }; sleep_retention_module_init(SLEEP_RETENTION_MODULE_CLOCK_MODEM, &init_param); diff --git a/components/esp_hw_support/lowpower/port/esp32p4/sleep_clock.c b/components/esp_hw_support/lowpower/port/esp32p4/sleep_clock.c index bc765058a53..1467c4d52b7 100644 --- a/components/esp_hw_support/lowpower/port/esp32p4/sleep_clock.c +++ b/components/esp_hw_support/lowpower/port/esp32p4/sleep_clock.c @@ -45,6 +45,7 @@ bool clock_domain_pd_allowed(void) { const sleep_retention_module_bitmap_t inited_modules = sleep_retention_get_inited_modules(); const sleep_retention_module_bitmap_t created_modules = sleep_retention_get_created_modules(); + const sleep_retention_module_bitmap_t retained_modules = sleep_retention_get_retained_modules(); const sleep_retention_module_bitmap_t sys_clk_dep_modules = (sleep_retention_module_bitmap_t){ .bitmap[SLEEP_RETENTION_MODULE_SYS_PERIPH >> 5] = BIT(SLEEP_RETENTION_MODULE_SYS_PERIPH % 32) }; const sleep_retention_module_bitmap_t null_module = (sleep_retention_module_bitmap_t){ .bitmap = { 0 } }; @@ -57,14 +58,17 @@ bool clock_domain_pd_allowed(void) const sleep_retention_module_bitmap_t clock_domain_inited_modules = sleep_retention_module_bitmap_and(inited_modules, mask); const sleep_retention_module_bitmap_t clock_domain_created_modules = sleep_retention_module_bitmap_and(created_modules, mask); - return sleep_retention_module_bitmap_eq(clock_domain_inited_modules, clock_domain_created_modules); + const sleep_retention_module_bitmap_t clock_domain_retained_modules = sleep_retention_module_bitmap_and(retained_modules, mask); + bool ic = sleep_retention_module_bitmap_eq(clock_domain_inited_modules, clock_domain_created_modules); + bool cr = sleep_retention_module_bitmap_eq(clock_domain_created_modules, clock_domain_retained_modules); + return ic && cr; } ESP_SYSTEM_INIT_FN(sleep_clock_startup_init, SECONDARY, BIT(0), 106) { sleep_retention_module_init_param_t init_param = { .cbs = { .create = { .handle = sleep_clock_system_retention_init, .arg = NULL } }, - .attribute = SLEEP_RETENTION_MODULE_ATTR_PASSIVE + .attribute = SLEEP_RETENTION_MODULE_ATTR_PASSIVE | SLEEP_RETENTION_MODULE_ATTR_ATTACH }; sleep_retention_module_init(SLEEP_RETENTION_MODULE_CLOCK_SYSTEM, &init_param); return ESP_OK; diff --git a/components/esp_hw_support/lowpower/port/esp32s31/sleep_clock.c b/components/esp_hw_support/lowpower/port/esp32s31/sleep_clock.c index 8449f7dbc41..9f2392b21ee 100644 --- a/components/esp_hw_support/lowpower/port/esp32s31/sleep_clock.c +++ b/components/esp_hw_support/lowpower/port/esp32s31/sleep_clock.c @@ -68,6 +68,7 @@ bool clock_domain_pd_allowed(void) { const sleep_retention_module_bitmap_t inited_modules = sleep_retention_get_inited_modules(); const sleep_retention_module_bitmap_t created_modules = sleep_retention_get_created_modules(); + const sleep_retention_module_bitmap_t retained_modules = sleep_retention_get_retained_modules(); const sleep_retention_module_bitmap_t sys_clk_dep_modules = (sleep_retention_module_bitmap_t){ .bitmap[SLEEP_RETENTION_MODULE_SYS_PERIPH >> 5] = BIT(SLEEP_RETENTION_MODULE_SYS_PERIPH % 32) }; /* The clock and reset of MODEM (WiFi, BLE and 15.4) modules are managed * through MODEM_SYSCON, when one or more MODEMs are initialized, it is @@ -105,21 +106,24 @@ bool clock_domain_pd_allowed(void) const sleep_retention_module_bitmap_t clock_domain_inited_modules = sleep_retention_module_bitmap_and(inited_modules, mask); const sleep_retention_module_bitmap_t clock_domain_created_modules = sleep_retention_module_bitmap_and(created_modules, mask); - return sleep_retention_module_bitmap_eq(clock_domain_inited_modules, clock_domain_created_modules); + const sleep_retention_module_bitmap_t clock_domain_retained_modules = sleep_retention_module_bitmap_and(retained_modules, mask); + bool ic = sleep_retention_module_bitmap_eq(clock_domain_inited_modules, clock_domain_created_modules); + bool cr = sleep_retention_module_bitmap_eq(clock_domain_created_modules, clock_domain_retained_modules); + return ic && cr; } ESP_SYSTEM_INIT_FN(sleep_clock_startup_init, SECONDARY, BIT(0), 106) { sleep_retention_module_init_param_t init_param = { .cbs = { .create = { .handle = sleep_clock_system_retention_init, .arg = NULL } }, - .attribute = SLEEP_RETENTION_MODULE_ATTR_PASSIVE + .attribute = SLEEP_RETENTION_MODULE_ATTR_PASSIVE | SLEEP_RETENTION_MODULE_ATTR_ATTACH }; sleep_retention_module_init(SLEEP_RETENTION_MODULE_CLOCK_SYSTEM, &init_param); #if CONFIG_MAC_BB_PD || CONFIG_BT_CTRL_SLEEP_ENABLE || CONFIG_IEEE802154_SLEEP_ENABLE init_param = (sleep_retention_module_init_param_t) { .cbs = { .create = { .handle = sleep_clock_modem_retention_init, .arg = NULL } }, - .attribute = SLEEP_RETENTION_MODULE_ATTR_PASSIVE + .attribute = SLEEP_RETENTION_MODULE_ATTR_PASSIVE | SLEEP_RETENTION_MODULE_ATTR_ATTACH }; sleep_retention_module_init(SLEEP_RETENTION_MODULE_CLOCK_MODEM, &init_param); #endif From 9521182c67f23a746623b68333fabc246e4e1884 Mon Sep 17 00:00:00 2001 From: cjin Date: Mon, 20 Apr 2026 08:47:09 +0800 Subject: [PATCH 09/22] feat(ble): support retention attach/detach to bt module --- components/bt/controller/esp32c5/bt.c | 35 ++++++++++++++--- components/bt/controller/esp32c6/bt.c | 35 ++++++++++++++--- components/bt/controller/esp32h2/bt.c | 35 ++++++++++++++--- .../controller/btdm_common/src/btdm_lp.c | 39 ++++++++++++++++--- components/esp_phy/src/btbb_init.c | 1 + 5 files changed, 124 insertions(+), 21 deletions(-) diff --git a/components/bt/controller/esp32c5/bt.c b/components/bt/controller/esp32c5/bt.c index c0188b0471d..5983adb06d9 100644 --- a/components/bt/controller/esp32c5/bt.c +++ b/components/bt/controller/esp32c5/bt.c @@ -737,20 +737,45 @@ static esp_err_t sleep_modem_ble_mac_modem_state_init(uint8_t extra) int retention_args = extra; sleep_retention_module_init_param_t init_param = { .cbs = { .create = { .handle = sleep_modem_ble_mac_retention_init, .arg = &retention_args } }, + .attribute = SLEEP_RETENTION_MODULE_ATTR_ATTACH, .depends = RETENTION_MODULE_BITMAP_INIT(BT_BB) }; esp_err_t err = sleep_retention_module_init(SLEEP_RETENTION_MODULE_BLE_MAC, &init_param); - if (err == ESP_OK) { - err = sleep_retention_module_allocate(SLEEP_RETENTION_MODULE_BLE_MAC); + if (err != ESP_OK) { + ESP_LOGE(NIMBLE_PORT_LOG_TAG, "BT sleep retention init error"); + return err; + } + + err = sleep_retention_module_allocate(SLEEP_RETENTION_MODULE_BLE_MAC); + if (err != ESP_OK) { + ESP_LOGE(NIMBLE_PORT_LOG_TAG, "BT sleep retention allocate error"); + return err; + } + + err = sleep_retention_module_attach(SLEEP_RETENTION_MODULE_BLE_MAC); + if (err != ESP_OK) { + ESP_LOGE(NIMBLE_PORT_LOG_TAG, "BT sleep retention attach error"); } return err; } static void sleep_modem_ble_mac_modem_state_deinit(void) { - esp_err_t err = sleep_retention_module_free(SLEEP_RETENTION_MODULE_BLE_MAC); - if (err == ESP_OK) { - err = sleep_retention_module_deinit(SLEEP_RETENTION_MODULE_BLE_MAC); + esp_err_t err = sleep_retention_module_detach(SLEEP_RETENTION_MODULE_BLE_MAC); + if (err != ESP_OK) { + ESP_LOGE(NIMBLE_PORT_LOG_TAG, "BT sleep retention detach error"); + assert(err == ESP_OK); + } + + err = sleep_retention_module_free(SLEEP_RETENTION_MODULE_BLE_MAC); + if (err != ESP_OK) { + ESP_LOGE(NIMBLE_PORT_LOG_TAG, "BT sleep retention free error"); + assert(err == ESP_OK); + } + + err = sleep_retention_module_deinit(SLEEP_RETENTION_MODULE_BLE_MAC); + if (err != ESP_OK) { + ESP_LOGE(NIMBLE_PORT_LOG_TAG, "BT sleep retention deinit error"); assert(err == ESP_OK); } } diff --git a/components/bt/controller/esp32c6/bt.c b/components/bt/controller/esp32c6/bt.c index 71ceaaa25fc..9263d5d2944 100644 --- a/components/bt/controller/esp32c6/bt.c +++ b/components/bt/controller/esp32c6/bt.c @@ -797,20 +797,45 @@ static esp_err_t sleep_modem_ble_mac_modem_state_init(uint8_t extra) int retention_args = extra; sleep_retention_module_init_param_t init_param = { .cbs = { .create = { .handle = sleep_modem_ble_mac_retention_init, .arg = &retention_args } }, + .attribute = SLEEP_RETENTION_MODULE_ATTR_ATTACH, .depends = RETENTION_MODULE_BITMAP_INIT(BT_BB) }; esp_err_t err = sleep_retention_module_init(SLEEP_RETENTION_MODULE_BLE_MAC, &init_param); - if (err == ESP_OK) { - err = sleep_retention_module_allocate(SLEEP_RETENTION_MODULE_BLE_MAC); + if (err != ESP_OK) { + ESP_LOGE(NIMBLE_PORT_LOG_TAG, "BT sleep retention init error"); + return err; + } + + err = sleep_retention_module_allocate(SLEEP_RETENTION_MODULE_BLE_MAC); + if (err != ESP_OK) { + ESP_LOGE(NIMBLE_PORT_LOG_TAG, "BT sleep retention allocate error"); + return err; + } + + err = sleep_retention_module_attach(SLEEP_RETENTION_MODULE_BLE_MAC); + if (err != ESP_OK) { + ESP_LOGE(NIMBLE_PORT_LOG_TAG, "BT sleep retention attach error"); } return err; } static void sleep_modem_ble_mac_modem_state_deinit(void) { - esp_err_t err = sleep_retention_module_free(SLEEP_RETENTION_MODULE_BLE_MAC); - if (err == ESP_OK) { - err = sleep_retention_module_deinit(SLEEP_RETENTION_MODULE_BLE_MAC); + esp_err_t err = sleep_retention_module_detach(SLEEP_RETENTION_MODULE_BLE_MAC); + if (err != ESP_OK) { + ESP_LOGE(NIMBLE_PORT_LOG_TAG, "BT sleep retention detach error"); + assert(err == ESP_OK); + } + + err = sleep_retention_module_free(SLEEP_RETENTION_MODULE_BLE_MAC); + if (err != ESP_OK) { + ESP_LOGE(NIMBLE_PORT_LOG_TAG, "BT sleep retention free error"); + assert(err == ESP_OK); + } + + err = sleep_retention_module_deinit(SLEEP_RETENTION_MODULE_BLE_MAC); + if (err != ESP_OK) { + ESP_LOGE(NIMBLE_PORT_LOG_TAG, "BT sleep retention deinit error"); assert(err == ESP_OK); } } diff --git a/components/bt/controller/esp32h2/bt.c b/components/bt/controller/esp32h2/bt.c index 913e41f1ebd..34cc9ad267c 100644 --- a/components/bt/controller/esp32h2/bt.c +++ b/components/bt/controller/esp32h2/bt.c @@ -767,20 +767,45 @@ static esp_err_t sleep_modem_ble_mac_modem_state_init(uint8_t extra) int retention_args = extra; sleep_retention_module_init_param_t init_param = { .cbs = { .create = { .handle = sleep_modem_ble_mac_retention_init, .arg = &retention_args } }, + .attribute = SLEEP_RETENTION_MODULE_ATTR_ATTACH, .depends = RETENTION_MODULE_BITMAP_INIT(BT_BB) }; esp_err_t err = sleep_retention_module_init(SLEEP_RETENTION_MODULE_BLE_MAC, &init_param); - if (err == ESP_OK) { - err = sleep_retention_module_allocate(SLEEP_RETENTION_MODULE_BLE_MAC); + if (err != ESP_OK) { + ESP_LOGE(NIMBLE_PORT_LOG_TAG, "BT sleep retention init error"); + return err; + } + + err = sleep_retention_module_allocate(SLEEP_RETENTION_MODULE_BLE_MAC); + if (err != ESP_OK) { + ESP_LOGE(NIMBLE_PORT_LOG_TAG, "BT sleep retention allocate error"); + return err; + } + + err = sleep_retention_module_attach(SLEEP_RETENTION_MODULE_BLE_MAC); + if (err != ESP_OK) { + ESP_LOGE(NIMBLE_PORT_LOG_TAG, "BT sleep retention attach error"); } return err; } static void sleep_modem_ble_mac_modem_state_deinit(void) { - esp_err_t err = sleep_retention_module_free(SLEEP_RETENTION_MODULE_BLE_MAC); - if (err == ESP_OK) { - err = sleep_retention_module_deinit(SLEEP_RETENTION_MODULE_BLE_MAC); + esp_err_t err = sleep_retention_module_detach(SLEEP_RETENTION_MODULE_BLE_MAC); + if (err != ESP_OK) { + ESP_LOGE(NIMBLE_PORT_LOG_TAG, "BT sleep retention detach error"); + assert(err == ESP_OK); + } + + err = sleep_retention_module_free(SLEEP_RETENTION_MODULE_BLE_MAC); + if (err != ESP_OK) { + ESP_LOGE(NIMBLE_PORT_LOG_TAG, "BT sleep retention free error"); + assert(err == ESP_OK); + } + + err = sleep_retention_module_deinit(SLEEP_RETENTION_MODULE_BLE_MAC); + if (err != ESP_OK) { + ESP_LOGE(NIMBLE_PORT_LOG_TAG, "BT sleep retention deinit error"); assert(err == ESP_OK); } } diff --git a/components/bt/porting_btdm/controller/btdm_common/src/btdm_lp.c b/components/bt/porting_btdm/controller/btdm_common/src/btdm_lp.c index 5c76d348221..ed2dfd8a8a6 100644 --- a/components/bt/porting_btdm/controller/btdm_common/src/btdm_lp.c +++ b/components/bt/porting_btdm/controller/btdm_common/src/btdm_lp.c @@ -253,10 +253,25 @@ btdm_lp_modem_state_init(void) { sleep_retention_module_init_param_t init_param = { .cbs = {.create = {.handle = (void *)btdm_lp_modem_retention_create, .arg = NULL}}, - .depends = RETENTION_MODULE_BITMAP_INIT(BT_BB)}; + .attribute = SLEEP_RETENTION_MODULE_ATTR_ATTACH, + .depends = RETENTION_MODULE_BITMAP_INIT(BT_BB) + }; + esp_err_t err = sleep_retention_module_init(SLEEP_RETENTION_MODULE_BLE_MAC, &init_param); - if (err == ESP_OK) { - err = sleep_retention_module_allocate(SLEEP_RETENTION_MODULE_BLE_MAC); + if (err != ESP_OK) { + ESP_LOGE(NIMBLE_PORT_LOG_TAG, "BT sleep retention init error"); + return err; + } + + err = sleep_retention_module_allocate(SLEEP_RETENTION_MODULE_BLE_MAC); + if (err != ESP_OK) { + ESP_LOGE(NIMBLE_PORT_LOG_TAG, "BT sleep retention allocate error"); + return err; + } + + err = sleep_retention_module_attach(SLEEP_RETENTION_MODULE_BLE_MAC); + if (err != ESP_OK) { + ESP_LOGE(NIMBLE_PORT_LOG_TAG, "BT sleep retention attach error"); } return err; } @@ -264,9 +279,21 @@ btdm_lp_modem_state_init(void) static void btdm_lp_modem_state_deinit(void) { - esp_err_t err = sleep_retention_module_free(SLEEP_RETENTION_MODULE_BLE_MAC); - if (err == ESP_OK) { - err = sleep_retention_module_deinit(SLEEP_RETENTION_MODULE_BLE_MAC); + esp_err_t err = sleep_retention_module_detach(SLEEP_RETENTION_MODULE_BLE_MAC); + if (err != ESP_OK) { + ESP_LOGE(NIMBLE_PORT_LOG_TAG, "BT sleep retention detach error"); + assert(err == ESP_OK); + } + + err = sleep_retention_module_free(SLEEP_RETENTION_MODULE_BLE_MAC); + if (err != ESP_OK) { + ESP_LOGE(NIMBLE_PORT_LOG_TAG, "BT sleep retention free error"); + assert(err == ESP_OK); + } + + err = sleep_retention_module_deinit(SLEEP_RETENTION_MODULE_BLE_MAC); + if (err != ESP_OK) { + ESP_LOGE(NIMBLE_PORT_LOG_TAG, "BT sleep retention deinit error"); assert(err == ESP_OK); } } diff --git a/components/esp_phy/src/btbb_init.c b/components/esp_phy/src/btbb_init.c index 023be89809f..a4e67296aaa 100644 --- a/components/esp_phy/src/btbb_init.c +++ b/components/esp_phy/src/btbb_init.c @@ -68,6 +68,7 @@ void esp_btbb_enable(void) #if SOC_PM_MODEM_RETENTION_BY_REGDMA && CONFIG_FREERTOS_USE_TICKLESS_IDLE sleep_retention_module_init_param_t init_param = { .cbs = { .create = { .handle = btbb_sleep_retention_init, .arg = NULL } }, + .attribute = SLEEP_RETENTION_MODULE_ATTR_ATTACH, .depends = RETENTION_MODULE_BITMAP_INIT(CLOCK_MODEM) }; esp_err_t err = sleep_retention_module_init(SLEEP_RETENTION_MODULE_BT_BB, &init_param); From ba0c441716d0a4424190252364d5d4f41e914322 Mon Sep 17 00:00:00 2001 From: Li Shuai Date: Mon, 20 Apr 2026 20:15:51 +0800 Subject: [PATCH 10/22] change(esp_hw_support): bypass regdma process when retention entries link final default only --- components/esp_hw_support/sleep_retention.c | 36 +++++++++++++-------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/components/esp_hw_support/sleep_retention.c b/components/esp_hw_support/sleep_retention.c index 5e729abfa93..9a9274daf48 100644 --- a/components/esp_hw_support/sleep_retention.c +++ b/components/esp_hw_support/sleep_retention.c @@ -248,6 +248,8 @@ typedef struct { sleep_retention_module_bitmap_t created_modules; sleep_retention_module_bitmap_t retention_modules; + void *final_default; + struct sleep_retention_module_object instance[SLEEP_RETENTION_MODULE_MAX + 1]; #define EXTRA_LINK_NUM (REGDMA_LINK_ENTRY_NUM - 1) @@ -257,7 +259,8 @@ static DRAM_ATTR __attribute__((unused)) sleep_retention_t s_retention = { .highpri = (uint8_t)-1, .inited_modules = (sleep_retention_module_bitmap_t){ .bitmap = { 0 } }, .created_modules = (sleep_retention_module_bitmap_t){ .bitmap = { 0 } }, - .retention_modules = (sleep_retention_module_bitmap_t){ .bitmap = { 0 } } + .retention_modules = (sleep_retention_module_bitmap_t){ .bitmap = { 0 } }, + .final_default = NULL }; #define SLEEP_RETENTION_ENTRY_BITMAP_MASK (BIT(REGDMA_LINK_ENTRY_NUM) - 1) @@ -320,6 +323,9 @@ static esp_err_t check_and_create_final_default(void) _lock_acquire_recursive(&s_retention.lock); if (s_retention.retention.lists[SLEEP_RETENTION_REGDMA_LINK_LOWEST_PRIORITY].entries_bitmap == 0) { err = entries_create(&final_dummy, 1, SLEEP_RETENTION_REGDMA_LINK_LOWEST_PRIORITY, SLEEP_RETENTION_MODULE_INVALID); + if (err == ESP_OK) { + s_retention.final_default = s_retention.retention.lists[SLEEP_RETENTION_REGDMA_LINK_LOWEST_PRIORITY].entries[0]; + } } _lock_release_recursive(&s_retention.lock); return err; @@ -655,6 +661,7 @@ static void sleep_retention_entries_destroy(sleep_retention_module_t module) #endif memset((void *)s_retention.context, 0, sizeof(struct module_sleep_retention_context) * 2); s_retention.highpri = (uint8_t)-1; + s_retention.final_default = NULL; } _lock_release_recursive(&s_retention.lock); } @@ -748,7 +755,18 @@ static void retention_entries_join(void) } entries_tail = s_retention.retention.lists[priority].entries_tail; } - pau_regdma_set_entry_link_addr(&(s_retention.retention.lists[s_retention.highpri].entries)); + + bool final_default = s_retention.final_default == s_retention.retention.lists[SLEEP_RETENTION_REGDMA_LINK_LOWEST_PRIORITY].entries[0]; + bool ready = (s_retention.highpri != SLEEP_RETENTION_REGDMA_LINK_LOWEST_PRIORITY) || !final_default; + if (ready) { + pau_regdma_set_entry_link_addr(&(s_retention.retention.lists[s_retention.highpri].entries)); +#if SOC_LIGHT_SLEEP_SUPPORTED + pmu_sleep_enable_regdma_backup(); +#endif +#if SOC_LIGHT_SLEEP_SUPPORTED && SOC_DEEP_SLEEP_SUPPORTED + ESP_ERROR_CHECK(esp_deep_sleep_register_hook(&pmu_sleep_disable_regdma_backup)); +#endif + } _lock_release_recursive(&s_retention.lock); } @@ -782,17 +800,9 @@ esp_err_t sleep_retention_entries_create(const sleep_retention_entries_config_t return ESP_ERR_INVALID_ARG; } esp_err_t err = check_and_create_final_default(); - if (err) goto error; - err = entries_create_wrapper(retent, num, priority, module); - if (err) goto error; -#if SOC_LIGHT_SLEEP_SUPPORTED - pmu_sleep_enable_regdma_backup(); -#endif -#if SOC_LIGHT_SLEEP_SUPPORTED && SOC_DEEP_SLEEP_SUPPORTED - ESP_ERROR_CHECK(esp_deep_sleep_register_hook(&pmu_sleep_disable_regdma_backup)); -#endif - -error: + if (err == ESP_OK) { + err = entries_create_wrapper(retent, num, priority, module); + } return err; } From d1aaeb25e7109fa964cfb9202fd060c5fa5922c4 Mon Sep 17 00:00:00 2001 From: Li Shuai Date: Tue, 21 Apr 2026 21:01:56 +0800 Subject: [PATCH 11/22] fix(ci): error: dereference of NULL 'args' --- components/esp_hw_support/port/regdma_link.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/components/esp_hw_support/port/regdma_link.c b/components/esp_hw_support/port/regdma_link.c index a4933d3581d..49190083fa4 100644 --- a/components/esp_hw_support/port/regdma_link.c +++ b/components/esp_hw_support/port/regdma_link.c @@ -824,6 +824,8 @@ static void print_info_branch_write_wait_wrapper(FILE *out, void *link) static void print_link_info(FILE *out, void *args, int entry, int depth) { + assert(args && "Invalid argument: args is NULL"); + typedef void (*prinf_fn_t)(FILE *, void *); const static prinf_fn_t prinf_fn[] = { From e28ee420acc94e169ffb64b754af771ee244779e Mon Sep 17 00:00:00 2001 From: Li Shuai Date: Wed, 22 Apr 2026 20:47:10 +0800 Subject: [PATCH 12/22] fix(ci): some digital peripherals support sleep retention attach and detach --- components/driver/twai/twai.c | 6 +++++ components/esp_driver_dma/src/gdma_sleep.c | 24 +++++++++++++------ components/esp_driver_gptimer/src/gptimer.c | 8 +++++++ components/esp_driver_i2s/i2s_common.c | 5 ++++ components/esp_driver_ledc/src/ledc.c | 6 +++++ .../test_apps/ledc/main/test_ledc_sleep.cpp | 1 + components/esp_driver_mcpwm/src/mcpwm_com.c | 6 +++++ .../esp_driver_parlio/src/parlio_common.c | 6 +++++ components/esp_driver_rmt/src/rmt_common.c | 6 +++++ components/esp_driver_sdm/src/sdm.c | 6 +++++ .../esp_driver_spi/src/gpspi/spi_common.c | 14 ++++++++--- .../esp_driver_spi/src/gpspi/spi_slave.c | 14 ++++++++--- .../esp_driver_spi/src/gpspi/spi_slave_hd.c | 14 ++++++++--- components/esp_driver_twai/esp_twai_onchip.c | 12 ++++++++-- components/esp_driver_uart/src/uart.c | 7 ++++++ components/esp_hw_support/etm/esp_etm.c | 8 +++++++ .../port/esp32c5/peripheral_domain_pd.c | 11 ++++++++- .../port/esp32c6/peripheral_domain_pd.c | 11 ++++++++- .../port/esp32c61/peripheral_domain_pd.c | 11 ++++++++- .../port/esp32h2/peripheral_domain_pd.c | 12 +++++++++- .../port/esp32h21/peripheral_domain_pd.c | 11 ++++++++- .../port/esp32h4/peripheral_domain_pd.c | 11 ++++++++- .../port/esp32p4/peripheral_domain_pd.c | 6 ++++- .../port/esp32s31/peripheral_domain_pd.c | 6 ++++- 24 files changed, 196 insertions(+), 26 deletions(-) diff --git a/components/driver/twai/twai.c b/components/driver/twai/twai.c index 4e45592baa4..6cfa5e34513 100644 --- a/components/driver/twai/twai.c +++ b/components/driver/twai/twai.c @@ -370,6 +370,7 @@ static void twai_free_driver_obj(twai_obj_t *p_obj) #if TWAI_USE_RETENTION_LINK const periph_retention_module_t retention_id = twai_reg_retention_info[p_obj->controller_id].module_id; + sleep_retention_module_detach(retention_id); if (sleep_retention_is_module_created(retention_id)) { assert(sleep_retention_is_module_inited(retention_id)); sleep_retention_module_free(retention_id); @@ -443,6 +444,7 @@ static esp_err_t twai_alloc_driver_obj(const twai_general_config_t *g_config, tw .arg = p_obj, }, }, + .attribute = SLEEP_RETENTION_MODULE_ATTR_ATTACH, .depends = RETENTION_MODULE_BITMAP_INIT(CLOCK_SYSTEM) }; if (sleep_retention_module_init(module, &init_param) != ESP_OK) { @@ -452,6 +454,10 @@ static esp_err_t twai_alloc_driver_obj(const twai_general_config_t *g_config, tw if (g_config->general_flags.sleep_allow_pd) { if (sleep_retention_module_allocate(module) != ESP_OK) { ESP_LOGW(TWAI_TAG, "create retention module failed, power domain can't turn off"); + } else { + if (sleep_retention_module_attach(module) != ESP_OK) { + ESP_LOGW(TWAI_TAG, "attach retention module failed, power domain can't turn off"); + } } } #endif diff --git a/components/esp_driver_dma/src/gdma_sleep.c b/components/esp_driver_dma/src/gdma_sleep.c index 35243416c02..c96435f84ba 100644 --- a/components/esp_driver_dma/src/gdma_sleep.c +++ b/components/esp_driver_dma/src/gdma_sleep.c @@ -37,6 +37,7 @@ void gdma_acquire_sleep_retention(gdma_pair_t* pair) int pair_id = pair->pair_id; sleep_retention_module_init_param_t init_param = { .cbs = { .create = { .handle = sleep_gdma_channel_retention_init, .arg = pair } }, + .attribute = SLEEP_RETENTION_MODULE_ATTR_ATTACH, .depends = RETENTION_MODULE_BITMAP_INIT(CLOCK_SYSTEM) }; sleep_retention_module_t module = gdma_retention_infos[group_id][pair_id].module_id; @@ -52,6 +53,10 @@ void gdma_acquire_sleep_retention(gdma_pair_t* pair) if (err != ESP_OK) { ESP_LOGW(TAG, "fail to allocate retention link list for pair (%d, %d)", group_id, pair_id); // don't call sleep_retention_module_deinit here, otherwise GDMA peripheral may be powered off during sleep + } else { + if (sleep_retention_module_attach(module) != ESP_OK) { + ESP_LOGW(TAG, "fail to attach retention link list for pair (%d, %d)", group_id, pair_id); + } } } } @@ -69,13 +74,18 @@ void gdma_release_sleep_retention(gdma_pair_t* pair) pair_ref_counts[group_id][pair_id]--; // Last reference, free the module if (pair_ref_counts[group_id][pair_id] == 0) { - esp_err_t err = sleep_retention_module_free(module); - if (err != ESP_OK) { - ESP_LOGW(TAG, "fail to free the retention link list for pair (%d, %d)", group_id, pair_id); - } - err = sleep_retention_module_deinit(module); - if (err != ESP_OK) { - ESP_LOGW(TAG, "fail to deinit the retention module for pair (%d, %d)", group_id, pair_id); + esp_err_t err = sleep_retention_module_detach(module); + if (err == ESP_OK) { + err = sleep_retention_module_free(module); + if (err != ESP_OK) { + ESP_LOGW(TAG, "fail to free the retention link list for pair (%d, %d)", group_id, pair_id); + } + err = sleep_retention_module_deinit(module); + if (err != ESP_OK) { + ESP_LOGW(TAG, "fail to deinit the retention module for pair (%d, %d)", group_id, pair_id); + } + } else { + ESP_LOGW(TAG, "fail to detach the retention link list for pair (%d, %d)", group_id, pair_id); } } _lock_release(&gdma_sleep_retention_lock); diff --git a/components/esp_driver_gptimer/src/gptimer.c b/components/esp_driver_gptimer/src/gptimer.c index cabbecf78de..308695f5e5e 100644 --- a/components/esp_driver_gptimer/src/gptimer.c +++ b/components/esp_driver_gptimer/src/gptimer.c @@ -32,6 +32,10 @@ static void gptimer_create_retention_module(gptimer_t *timer) if (sleep_retention_module_allocate(module) != ESP_OK) { // even though the sleep retention module create failed, GPTimer driver should still work, so just warning here ESP_LOGW(TAG, "create retention link failed on TimerGroup%d Timer%d, power domain won't be turned off during sleep", group_id, timer_id); + return; + } + if (sleep_retention_module_attach(module) != ESP_OK) { + ESP_LOGW(TAG, "attach retention link failed on TimerGroup%d Timer%d, power domain won't be turned off during sleep", group_id, timer_id); } } } @@ -73,6 +77,7 @@ static esp_err_t gptimer_register_to_group(gptimer_t *timer) .arg = (void *)timer }, }, + .attribute = SLEEP_RETENTION_MODULE_ATTR_ATTACH, .depends = RETENTION_MODULE_BITMAP_INIT(CLOCK_SYSTEM) }; if (sleep_retention_module_init(module, &init_param) != ESP_OK) { @@ -94,6 +99,9 @@ static void gptimer_unregister_from_group(gptimer_t *timer) #if GPTIMER_USE_RETENTION_LINK sleep_retention_module_t module = gptimer_retention_infos[group->group_id][timer_id].module; + if (sleep_retention_is_module_attached(module)) { + sleep_retention_module_detach(module); + } if (sleep_retention_is_module_created(module)) { sleep_retention_module_free(module); } diff --git a/components/esp_driver_i2s/i2s_common.c b/components/esp_driver_i2s/i2s_common.c index e25ffd33aa0..eb6217e36d4 100644 --- a/components/esp_driver_i2s/i2s_common.c +++ b/components/esp_driver_i2s/i2s_common.c @@ -110,6 +110,9 @@ static void s_i2s_create_retention_module(i2s_controller_t *i2s_obj) ESP_LOGW(TAG, "create retention module failed, power domain can't turn off"); } else { i2s_obj->retention_link_created = true; + if (sleep_retention_module_attach(module) != ESP_OK) { + ESP_LOGW(TAG, "attach retention module failed, power domain can't turn off"); + } } } _lock_release(&i2s_obj->mutex); @@ -209,6 +212,7 @@ static esp_err_t i2s_destroy_controller_obj(i2s_controller_t **i2s_obj) #if I2S_USE_RETENTION_LINK if ((*i2s_obj)->slp_retention_mod) { if ((*i2s_obj)->retention_link_created) { + sleep_retention_module_detach((*i2s_obj)->slp_retention_mod); sleep_retention_module_free((*i2s_obj)->slp_retention_mod); } sleep_retention_module_deinit((*i2s_obj)->slp_retention_mod); @@ -268,6 +272,7 @@ static i2s_controller_t *i2s_acquire_controller_obj(int id) .arg = i2s_obj, }, }, + .attribute = SLEEP_RETENTION_MODULE_ATTR_ATTACH, .depends = RETENTION_MODULE_BITMAP_INIT(CLOCK_SYSTEM) }; if (sleep_retention_module_init(module, &init_param) == ESP_OK) { diff --git a/components/esp_driver_ledc/src/ledc.c b/components/esp_driver_ledc/src/ledc.c index 4430a18384f..9dbc35599ba 100644 --- a/components/esp_driver_ledc/src/ledc.c +++ b/components/esp_driver_ledc/src/ledc.c @@ -439,6 +439,7 @@ static bool ledc_speed_mode_ctx_create(ledc_mode_t speed_mode) .arg = NULL, }, }, + .attribute = SLEEP_RETENTION_MODULE_ATTR_ATTACH, .depends = RETENTION_MODULE_BITMAP_INIT(CLOCK_SYSTEM) }; if (sleep_retention_module_init(module, &init_param) != ESP_OK) { @@ -971,9 +972,14 @@ esp_err_t ledc_channel_config(const ledc_channel_config_t *ledc_conf) if (slp_retention_alloc) { if (sleep_retention_module_allocate(ledc_reg_retention_info[0].module_id) != ESP_OK) { ESP_LOGW(LEDC_TAG, "create retention module failed, power domain can't turn off"); + } else { + if (sleep_retention_module_attach(ledc_reg_retention_info[0].module_id) != ESP_OK) { + ESP_LOGW(LEDC_TAG, "attach retention module failed, power domain can't turn off"); + } } } if (slp_retention_free) { + sleep_retention_module_detach(ledc_reg_retention_info[0].module_id); sleep_retention_module_free(ledc_reg_retention_info[0].module_id); } #endif diff --git a/components/esp_driver_ledc/test_apps/ledc/main/test_ledc_sleep.cpp b/components/esp_driver_ledc/test_apps/ledc/main/test_ledc_sleep.cpp index 5c6beeaa51e..f771f000254 100644 --- a/components/esp_driver_ledc/test_apps/ledc/main/test_ledc_sleep.cpp +++ b/components/esp_driver_ledc/test_apps/ledc/main/test_ledc_sleep.cpp @@ -87,6 +87,7 @@ TEST_CASE("ledc can output after light sleep (LEDC power domain pd)", "[ledc]") // ledc driver does not have channel release, we will do retention release here to avoid memory leak sleep_retention_module_t module = ledc_reg_retention_info[0].module_id; + sleep_retention_module_detach(module); sleep_retention_module_free(module); sleep_retention_module_deinit(module); } diff --git a/components/esp_driver_mcpwm/src/mcpwm_com.c b/components/esp_driver_mcpwm/src/mcpwm_com.c index 3c4ccb69cbe..49a4492c5d6 100644 --- a/components/esp_driver_mcpwm/src/mcpwm_com.c +++ b/components/esp_driver_mcpwm/src/mcpwm_com.c @@ -45,6 +45,7 @@ mcpwm_group_t *mcpwm_acquire_group_handle(int group_id) .arg = group, }, }, + .attribute = SLEEP_RETENTION_MODULE_ATTR_ATTACH, .depends = RETENTION_MODULE_BITMAP_INIT(CLOCK_SYSTEM) }; // we only do retention init here. Allocate retention module in the unit initialization @@ -114,6 +115,7 @@ void mcpwm_release_group_handle(mcpwm_group_t *group) #endif #if MCPWM_USE_RETENTION_LINK const periph_retention_module_t module_id = mcpwm_retention_infos[group_id].retention_module; + sleep_retention_module_detach(module_id); if (sleep_retention_is_module_created(module_id)) { sleep_retention_module_free(module_id); } @@ -263,6 +265,10 @@ void mcpwm_create_retention_module(mcpwm_group_t *group) if (sleep_retention_module_allocate(module_id) != ESP_OK) { // even though the sleep retention module create failed, MCPWM driver should still work, so just warning here ESP_LOGW(TAG, "create retention module failed, power domain can't turn off"); + } else { + if (sleep_retention_module_attach(module_id) != ESP_OK) { + ESP_LOGW(TAG, "attach retention module failed, power domain can't turn off"); + } } } _lock_release(&s_platform.mutex); diff --git a/components/esp_driver_parlio/src/parlio_common.c b/components/esp_driver_parlio/src/parlio_common.c index 3078d400ce3..7f42005f42a 100644 --- a/components/esp_driver_parlio/src/parlio_common.c +++ b/components/esp_driver_parlio/src/parlio_common.c @@ -42,6 +42,7 @@ parlio_group_t *parlio_acquire_group_handle(int group_id) .arg = group, }, }, + .attribute = SLEEP_RETENTION_MODULE_ATTR_ATTACH, .depends = RETENTION_MODULE_BITMAP_INIT(CLOCK_SYSTEM) }; // we only do retention init here. Allocate retention module in the unit initialization @@ -93,6 +94,7 @@ void parlio_release_group_handle(parlio_group_t *group) if (do_deinitialize) { #if PARLIO_USE_RETENTION_LINK const periph_retention_module_t module_id = parlio_retention_infos[group_id].retention_module; + sleep_retention_module_detach(module_id); if (sleep_retention_is_module_created(module_id)) { assert(sleep_retention_is_module_inited(module_id)); sleep_retention_module_free(module_id); @@ -185,6 +187,10 @@ void parlio_create_retention_module(parlio_group_t *group) if (sleep_retention_module_allocate(module_id) != ESP_OK) { // even though the sleep retention module create failed, PARLIO driver should still work, so just warning here ESP_LOGW(TAG, "create retention module failed, power domain can't turn off"); + } else { + if (sleep_retention_module_attach(module_id) != ESP_OK) { + ESP_LOGW(TAG, "attach retention module failed, power domain can't turn off"); + } } } _lock_release(&s_platform.mutex); diff --git a/components/esp_driver_rmt/src/rmt_common.c b/components/esp_driver_rmt/src/rmt_common.c index 8cec373f142..29f28a3d575 100644 --- a/components/esp_driver_rmt/src/rmt_common.c +++ b/components/esp_driver_rmt/src/rmt_common.c @@ -53,6 +53,7 @@ rmt_group_t *rmt_acquire_group_handle(int group_id) .arg = group, }, }, + .attribute = SLEEP_RETENTION_MODULE_ATTR_ATTACH, .depends = RETENTION_MODULE_BITMAP_INIT(CLOCK_SYSTEM) }; if (sleep_retention_module_init(module, &init_param) != ESP_OK) { @@ -105,6 +106,7 @@ void rmt_release_group_handle(rmt_group_t *group) if (do_deinitialize) { #if RMT_USE_RETENTION_LINK sleep_retention_module_t module = rmt_retention_infos[group_id].module; + sleep_retention_module_detach(module); if (sleep_retention_is_module_created(module)) { sleep_retention_module_free(module); } @@ -294,6 +296,10 @@ void rmt_create_retention_module(rmt_group_t *group) if (sleep_retention_module_allocate(module) != ESP_OK) { // even though the sleep retention module create failed, RMT driver should still work, so just warning here ESP_LOGW(TAG, "create retention link failed, power domain won't be turned off during sleep"); + } else { + if (sleep_retention_module_attach(module) != ESP_OK) { + ESP_LOGW(TAG, "attach retention link failed, power domain won't be turned off during sleep"); + } } } _lock_release(&s_platform.mutex); diff --git a/components/esp_driver_sdm/src/sdm.c b/components/esp_driver_sdm/src/sdm.c index 57d352301e3..b01bc3fda84 100644 --- a/components/esp_driver_sdm/src/sdm.c +++ b/components/esp_driver_sdm/src/sdm.c @@ -103,6 +103,10 @@ static void sdm_create_retention_module(sdm_group_t *group) if (sleep_retention_module_allocate(module) != ESP_OK) { // even though the sleep retention module create failed, SDM driver should still work, so just warning here ESP_LOGW(TAG, "create retention link failed on SDM Group%d, power domain won't be turned off during sleep", group_id); + } else { + if (sleep_retention_module_attach(module) != ESP_OK) { + ESP_LOGW(TAG, "attach retention link failed on SDM Group%d, power domain won't be turned off during sleep", group_id); + } } } _lock_release(&s_platform.mutex); @@ -135,6 +139,7 @@ static sdm_group_t *sdm_acquire_group_handle(int group_id, sdm_clock_source_t cl .arg = group, }, }, + .attribute = SLEEP_RETENTION_MODULE_ATTR_ATTACH, .depends = RETENTION_MODULE_BITMAP_INIT(CLOCK_SYSTEM) }; // retention module init must be called BEFORE the hal init @@ -192,6 +197,7 @@ static void sdm_release_group_handle(sdm_group_t *group) #if SDM_USE_RETENTION_LINK sleep_retention_module_t module = soc_sdm_retention_infos[group_id].module; + sleep_retention_module_detach(module); if (sleep_retention_is_module_created(module)) { sleep_retention_module_free(module); } diff --git a/components/esp_driver_spi/src/gpspi/spi_common.c b/components/esp_driver_spi/src/gpspi/spi_common.c index 24d8f468c65..d202119dad5 100644 --- a/components/esp_driver_spi/src/gpspi/spi_common.c +++ b/components/esp_driver_spi/src/gpspi/spi_common.c @@ -946,14 +946,21 @@ esp_err_t spi_bus_initialize(spi_host_device_t host_id, const spi_bus_config_t * .arg = ctx, }, }, + .attribute = SLEEP_RETENTION_MODULE_ATTR_ATTACH, .depends = RETENTION_MODULE_BITMAP_INIT(CLOCK_SYSTEM) }; _lock_acquire(&ctx->mutex); if (sleep_retention_module_init(spi_reg_retention_info[host_id - 1].module_id, &init_param) == ESP_OK) { - if ((bus_config->flags & SPICOMMON_BUSFLAG_SLP_ALLOW_PD) && (sleep_retention_module_allocate(spi_reg_retention_info[host_id - 1].module_id) != ESP_OK)) { - // even though the sleep retention create failed, SPI driver should still work, so just warning here - ESP_LOGW(SPI_TAG, "alloc sleep recover failed, peripherals may hold power on"); + if ((bus_config->flags & SPICOMMON_BUSFLAG_SLP_ALLOW_PD)) { + if (sleep_retention_module_allocate(spi_reg_retention_info[host_id - 1].module_id) != ESP_OK) { + // even though the sleep retention create failed, SPI driver should still work, so just warning here + ESP_LOGW(SPI_TAG, "alloc sleep recover failed, peripherals may hold power on"); + } else { + if (sleep_retention_module_attach(spi_reg_retention_info[host_id - 1].module_id) != ESP_OK) { + ESP_LOGW(SPI_TAG, "attach sleep recover failed, peripherals may hold power on"); + } + } } } else { // even the sleep retention init failed, SPI driver should still work, so just warning here @@ -1055,6 +1062,7 @@ esp_err_t spi_bus_free(spi_host_device_t host_id) #if SOC_SPI_SUPPORT_SLEEP_RETENTION && CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP const periph_retention_module_t retention_id = spi_reg_retention_info[host_id - 1].module_id; _lock_acquire(&ctx->mutex); + sleep_retention_module_detach(retention_id); if (sleep_retention_is_module_created(retention_id)) { assert(sleep_retention_is_module_inited(retention_id)); sleep_retention_module_free(retention_id); diff --git a/components/esp_driver_spi/src/gpspi/spi_slave.c b/components/esp_driver_spi/src/gpspi/spi_slave.c index 1dc44fcf526..667d2b4995d 100644 --- a/components/esp_driver_spi/src/gpspi/spi_slave.c +++ b/components/esp_driver_spi/src/gpspi/spi_slave.c @@ -242,13 +242,20 @@ esp_err_t spi_slave_initialize(spi_host_device_t host, const spi_bus_config_t *b .arg = spihost[host], }, }, + .attribute = SLEEP_RETENTION_MODULE_ATTR_ATTACH, .depends = RETENTION_MODULE_BITMAP_INIT(CLOCK_SYSTEM), }; if (ESP_OK == sleep_retention_module_init(spi_reg_retention_info[host - 1].module_id, &init_param)) { - if ((bus_config->flags & SPICOMMON_BUSFLAG_SLP_ALLOW_PD) && (sleep_retention_module_allocate(spi_reg_retention_info[host - 1].module_id) != ESP_OK)) { - // even though the sleep retention create failed, SPI driver should still work, so just warning here - ESP_LOGW(SPI_TAG, "Alloc sleep recover failed, spi may hold power on"); + if ((bus_config->flags & SPICOMMON_BUSFLAG_SLP_ALLOW_PD)) { + if (sleep_retention_module_allocate(spi_reg_retention_info[host - 1].module_id) != ESP_OK) { + // even though the sleep retention create failed, SPI driver should still work, so just warning here + ESP_LOGW(SPI_TAG, "Alloc sleep recover failed, spi may hold power on"); + } else { + if (sleep_retention_module_attach(spi_reg_retention_info[host - 1].module_id) != ESP_OK) { + ESP_LOGW(SPI_TAG, "attach sleep recover failed, spi may hold power on"); + } + } } } else { // even the sleep retention init failed, SPI driver should still work, so just warning here @@ -332,6 +339,7 @@ esp_err_t spi_slave_free(spi_host_device_t host) #if SOC_SPI_SUPPORT_SLEEP_RETENTION && CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP const periph_retention_module_t retention_id = spi_reg_retention_info[spihost[host]->id - 1].module_id; + sleep_retention_module_detach(retention_id); if (sleep_retention_is_module_created(retention_id)) { assert(sleep_retention_is_module_inited(retention_id)); sleep_retention_module_free(retention_id); diff --git a/components/esp_driver_spi/src/gpspi/spi_slave_hd.c b/components/esp_driver_spi/src/gpspi/spi_slave_hd.c index 8eb484ef579..bd4d4cec0c7 100644 --- a/components/esp_driver_spi/src/gpspi/spi_slave_hd.c +++ b/components/esp_driver_spi/src/gpspi/spi_slave_hd.c @@ -200,13 +200,20 @@ esp_err_t spi_slave_hd_init(spi_host_device_t host_id, const spi_bus_config_t *b .arg = host, }, }, + .attribute = SLEEP_RETENTION_MODULE_ATTR_ATTACH, .depends = RETENTION_MODULE_BITMAP_INIT(CLOCK_SYSTEM), }; if (ESP_OK == sleep_retention_module_init(spi_reg_retention_info[host_id - 1].module_id, &init_param)) { - if ((bus_config->flags & SPICOMMON_BUSFLAG_SLP_ALLOW_PD) && (sleep_retention_module_allocate(spi_reg_retention_info[host_id - 1].module_id) != ESP_OK)) { - // even though the sleep retention create failed, SPI driver should still work, so just warning here - ESP_LOGW(TAG, "Alloc sleep recover failed, spi may hold power on"); + if ((bus_config->flags & SPICOMMON_BUSFLAG_SLP_ALLOW_PD)) { + if (sleep_retention_module_allocate(spi_reg_retention_info[host_id - 1].module_id) != ESP_OK) { + // even though the sleep retention create failed, SPI driver should still work, so just warning here + ESP_LOGW(TAG, "Alloc sleep recover failed, spi may hold power on"); + } else { + if (sleep_retention_module_attach(spi_reg_retention_info[host_id - 1].module_id) != ESP_OK) { + ESP_LOGW(TAG, "attach sleep recover failed, spi may hold power on"); + } + } } } else { // even the sleep retention init failed, SPI driver should still work, so just warning here @@ -322,6 +329,7 @@ esp_err_t spi_slave_hd_deinit(spi_host_device_t host_id) #if SOC_SPI_SUPPORT_SLEEP_RETENTION && CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP const periph_retention_module_t retention_id = spi_reg_retention_info[host_id - 1].module_id; + sleep_retention_module_detach(retention_id); if (sleep_retention_is_module_created(retention_id)) { assert(sleep_retention_is_module_inited(retention_id)); sleep_retention_module_free(retention_id); diff --git a/components/esp_driver_twai/esp_twai_onchip.c b/components/esp_driver_twai/esp_twai_onchip.c index 516c4e2c446..06b90b2b813 100644 --- a/components/esp_driver_twai/esp_twai_onchip.c +++ b/components/esp_driver_twai/esp_twai_onchip.c @@ -293,6 +293,7 @@ static void _node_destroy(twai_onchip_ctx_t *twai_ctx) #endif #if SOC_TWAI_SUPPORT_SLEEP_RETENTION && CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP const sleep_retention_module_t retention_id = twai_reg_retention_info[twai_ctx->ctrlr_id].module_id; + sleep_retention_module_detach(retention_id); if (sleep_retention_is_module_created(retention_id)) { assert(sleep_retention_is_module_inited(retention_id)); sleep_retention_module_free(retention_id); @@ -707,11 +708,18 @@ esp_err_t twai_new_node_onchip(const twai_onchip_node_config_t *node_config, twa .arg = node, }, }, + .attribute = SLEEP_RETENTION_MODULE_ATTR_ATTACH, .depends = RETENTION_MODULE_BITMAP_INIT(CLOCK_SYSTEM) }; if (sleep_retention_module_init(retention_id, &init_param) == ESP_OK) { - if ((node_config->flags.sleep_allow_pd) && (sleep_retention_module_allocate(retention_id) != ESP_OK)) { - ESP_LOGW(TAG, "sleep retention prepare failed, power will hold on"); + if (node_config->flags.sleep_allow_pd) { + if (sleep_retention_module_allocate(retention_id) != ESP_OK) { + ESP_LOGW(TAG, "sleep retention allocate failed, power will hold on"); + } else { + if (sleep_retention_module_attach(retention_id) != ESP_OK) { + ESP_LOGW(TAG, "sleep retention attach failed, power will hold on"); + } + } } } else { ESP_LOGW(TAG, "sleep retention init failed, twai may offline after sleep"); diff --git a/components/esp_driver_uart/src/uart.c b/components/esp_driver_uart/src/uart.c index c7eb9b2721b..f10546a2375 100644 --- a/components/esp_driver_uart/src/uart.c +++ b/components/esp_driver_uart/src/uart.c @@ -252,6 +252,7 @@ static bool uart_module_enable(uart_port_t uart_num) .arg = &uart_context[uart_num], }, }, + .attribute = SLEEP_RETENTION_MODULE_ATTR_ATTACH, .depends = RETENTION_MODULE_BITMAP_INIT(CLOCK_SYSTEM) }; if (sleep_retention_module_init(module, &init_param) != ESP_OK) { @@ -1140,12 +1141,17 @@ esp_err_t uart_param_config(uart_port_t uart_num, const uart_config_t *uart_conf if (sleep_retention_module_allocate(module) != ESP_OK) { // Even though the sleep retention module create failed, UART driver should still work, so just warning here ESP_LOGW(UART_TAG, "create retention module failed, power domain can't turn off"); + } else { + if (sleep_retention_module_attach(module) != ESP_OK) { + ESP_LOGW(UART_TAG, "attach retention module failed, power domain can't turn off"); + } } } else { ESP_LOGW(UART_TAG, "retention module not initialized first, unable to create retention module"); } } else if (!allow_pd && sleep_retention_is_module_created(module)) { assert(sleep_retention_is_module_inited(module)); + sleep_retention_module_detach(module); sleep_retention_module_free(module); } _lock_release(&(uart_context[uart_num].mutex)); @@ -2146,6 +2152,7 @@ esp_err_t uart_driver_delete(uart_port_t uart_num) _lock_acquire(&(uart_context[uart_num].mutex)); if (sleep_retention_is_module_created(module)) { assert(sleep_retention_is_module_inited(module)); + sleep_retention_module_detach(module); sleep_retention_module_free(module); } _lock_release(&(uart_context[uart_num].mutex)); diff --git a/components/esp_hw_support/etm/esp_etm.c b/components/esp_hw_support/etm/esp_etm.c index dc2a8c7c577..8bb34071ae2 100644 --- a/components/esp_hw_support/etm/esp_etm.c +++ b/components/esp_hw_support/etm/esp_etm.c @@ -88,6 +88,10 @@ static void etm_create_retention_module(etm_group_t *group) if (sleep_retention_module_allocate(module) != ESP_OK) { // even though the sleep retention module create failed, ETM driver should still work, so just warning here ESP_LOGW(TAG, "create retention link failed on ETM Group%d, power domain won't be turned off during sleep", group_id); + } else { + if (sleep_retention_module_attach(module) != ESP_OK) { + ESP_LOGW(TAG, "attach retention link failed on ETM Group%d, power domain won't be turned off during sleep", group_id); + } } } _lock_release(&s_platform.mutex); @@ -125,6 +129,7 @@ static etm_group_t *etm_acquire_group_handle(int group_id) .arg = group, }, }, + .attribute = SLEEP_RETENTION_MODULE_ATTR_ATTACH, .depends = RETENTION_MODULE_BITMAP_INIT(CLOCK_SYSTEM) }; // retention module init must be called BEFORE the hal init @@ -172,6 +177,9 @@ static void etm_release_group_handle(etm_group_t *group) #if ETM_USE_RETENTION_LINK sleep_retention_module_t module = soc_etm_retention_info[group_id].module; + if (sleep_retention_is_module_attached(module)) { + sleep_retention_module_detach(module); + } if (sleep_retention_is_module_created(module)) { sleep_retention_module_free(module); } diff --git a/components/esp_hw_support/port/esp32c5/peripheral_domain_pd.c b/components/esp_hw_support/port/esp32c5/peripheral_domain_pd.c index 7f75dca6395..9764fa61790 100644 --- a/components/esp_hw_support/port/esp32c5/peripheral_domain_pd.c +++ b/components/esp_hw_support/port/esp32c5/peripheral_domain_pd.c @@ -15,6 +15,7 @@ bool peripheral_domain_pd_allowed(void) #if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP const sleep_retention_module_bitmap_t inited_modules = sleep_retention_get_inited_modules(); const sleep_retention_module_bitmap_t created_modules = sleep_retention_get_created_modules(); + const sleep_retention_module_bitmap_t retained_modules = sleep_retention_get_retained_modules(); sleep_retention_module_bitmap_t mask = RETENTION_MODULE_BITMAP_INIT(NULL); RETENTION_MODULE_BITMAP_SET(&mask, SLEEP_RETENTION_MODULE_SYS_PERIPH); @@ -82,7 +83,15 @@ bool peripheral_domain_pd_allowed(void) 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); + bool ic = sleep_retention_module_bitmap_eq(peripheral_domain_inited_modules, peripheral_domain_created_modules); + + sleep_retention_module_bitmap_t mask_ign = mask; + mask_ign.bitmap[SLEEP_RETENTION_MODULE_TEMP_SENSOR >> 5] &= ~BIT(SLEEP_RETENTION_MODULE_TEMP_SENSOR % 32); + + const sleep_retention_module_bitmap_t peripheral_domain_created_ign_modules = sleep_retention_module_bitmap_and(created_modules, mask_ign); + const sleep_retention_module_bitmap_t peripheral_domain_retained_modules = sleep_retention_module_bitmap_and(retained_modules, mask_ign); + bool cr = sleep_retention_module_bitmap_eq(peripheral_domain_created_ign_modules, peripheral_domain_retained_modules); + return ic && cr; #else return false; #endif diff --git a/components/esp_hw_support/port/esp32c6/peripheral_domain_pd.c b/components/esp_hw_support/port/esp32c6/peripheral_domain_pd.c index 9d3742a9614..846d433b8b3 100644 --- a/components/esp_hw_support/port/esp32c6/peripheral_domain_pd.c +++ b/components/esp_hw_support/port/esp32c6/peripheral_domain_pd.c @@ -15,6 +15,7 @@ bool peripheral_domain_pd_allowed(void) #if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP const sleep_retention_module_bitmap_t inited_modules = sleep_retention_get_inited_modules(); const sleep_retention_module_bitmap_t created_modules = sleep_retention_get_created_modules(); + const sleep_retention_module_bitmap_t retained_modules = sleep_retention_get_retained_modules(); sleep_retention_module_bitmap_t mask = RETENTION_MODULE_BITMAP_INIT(NULL); RETENTION_MODULE_BITMAP_SET(&mask, SLEEP_RETENTION_MODULE_SYS_PERIPH); @@ -79,7 +80,15 @@ bool peripheral_domain_pd_allowed(void) 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); + bool ic = sleep_retention_module_bitmap_eq(peripheral_domain_inited_modules, peripheral_domain_created_modules); + + sleep_retention_module_bitmap_t mask_ign = mask; + mask_ign.bitmap[SLEEP_RETENTION_MODULE_TEMP_SENSOR >> 5] &= ~BIT(SLEEP_RETENTION_MODULE_TEMP_SENSOR % 32); + + const sleep_retention_module_bitmap_t peripheral_domain_created_ign_modules = sleep_retention_module_bitmap_and(created_modules, mask_ign); + const sleep_retention_module_bitmap_t peripheral_domain_retained_modules = sleep_retention_module_bitmap_and(retained_modules, mask_ign); + bool cr = sleep_retention_module_bitmap_eq(peripheral_domain_created_ign_modules, peripheral_domain_retained_modules); + return ic && cr; #else return false; #endif diff --git a/components/esp_hw_support/port/esp32c61/peripheral_domain_pd.c b/components/esp_hw_support/port/esp32c61/peripheral_domain_pd.c index 715d747c7f8..bf9de2cd096 100644 --- a/components/esp_hw_support/port/esp32c61/peripheral_domain_pd.c +++ b/components/esp_hw_support/port/esp32c61/peripheral_domain_pd.c @@ -15,6 +15,7 @@ bool peripheral_domain_pd_allowed(void) #if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP const sleep_retention_module_bitmap_t inited_modules = sleep_retention_get_inited_modules(); const sleep_retention_module_bitmap_t created_modules = sleep_retention_get_created_modules(); + const sleep_retention_module_bitmap_t retained_modules = sleep_retention_get_retained_modules(); sleep_retention_module_bitmap_t mask = RETENTION_MODULE_BITMAP_INIT(NULL); RETENTION_MODULE_BITMAP_SET(&mask, SLEEP_RETENTION_MODULE_SYS_PERIPH); @@ -62,7 +63,15 @@ bool peripheral_domain_pd_allowed(void) 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); + bool ic = sleep_retention_module_bitmap_eq(peripheral_domain_inited_modules, peripheral_domain_created_modules); + + sleep_retention_module_bitmap_t mask_ign = mask; + mask_ign.bitmap[SLEEP_RETENTION_MODULE_TEMP_SENSOR >> 5] &= ~BIT(SLEEP_RETENTION_MODULE_TEMP_SENSOR % 32); + + const sleep_retention_module_bitmap_t peripheral_domain_created_ign_modules = sleep_retention_module_bitmap_and(created_modules, mask_ign); + const sleep_retention_module_bitmap_t peripheral_domain_retained_modules = sleep_retention_module_bitmap_and(retained_modules, mask_ign); + bool cr = sleep_retention_module_bitmap_eq(peripheral_domain_created_ign_modules, peripheral_domain_retained_modules); + return ic && cr; #else return false; #endif diff --git a/components/esp_hw_support/port/esp32h2/peripheral_domain_pd.c b/components/esp_hw_support/port/esp32h2/peripheral_domain_pd.c index e0c8050bd4a..c5169ab5f37 100644 --- a/components/esp_hw_support/port/esp32h2/peripheral_domain_pd.c +++ b/components/esp_hw_support/port/esp32h2/peripheral_domain_pd.c @@ -15,6 +15,7 @@ bool peripheral_domain_pd_allowed(void) #if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP const sleep_retention_module_bitmap_t inited_modules = sleep_retention_get_inited_modules(); const sleep_retention_module_bitmap_t created_modules = sleep_retention_get_created_modules(); + const sleep_retention_module_bitmap_t retained_modules = sleep_retention_get_retained_modules(); sleep_retention_module_bitmap_t mask = RETENTION_MODULE_BITMAP_INIT(NULL); RETENTION_MODULE_BITMAP_SET(&mask, SLEEP_RETENTION_MODULE_SYS_PERIPH); @@ -80,7 +81,16 @@ bool peripheral_domain_pd_allowed(void) 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); + bool ic = sleep_retention_module_bitmap_eq(peripheral_domain_inited_modules, peripheral_domain_created_modules); + + sleep_retention_module_bitmap_t mask_ign = mask; + mask_ign.bitmap[SLEEP_RETENTION_MODULE_TEMP_SENSOR >> 5] &= ~BIT(SLEEP_RETENTION_MODULE_TEMP_SENSOR % 32); + + const sleep_retention_module_bitmap_t peripheral_domain_created_ign_modules = sleep_retention_module_bitmap_and(created_modules, mask_ign); + + const sleep_retention_module_bitmap_t peripheral_domain_retained_modules = sleep_retention_module_bitmap_and(retained_modules, mask_ign); + bool cr = sleep_retention_module_bitmap_eq(peripheral_domain_created_ign_modules, peripheral_domain_retained_modules); + return ic && cr; #else return false; #endif diff --git a/components/esp_hw_support/port/esp32h21/peripheral_domain_pd.c b/components/esp_hw_support/port/esp32h21/peripheral_domain_pd.c index 4a6d2657ec8..1f3e68f0890 100644 --- a/components/esp_hw_support/port/esp32h21/peripheral_domain_pd.c +++ b/components/esp_hw_support/port/esp32h21/peripheral_domain_pd.c @@ -15,6 +15,7 @@ bool peripheral_domain_pd_allowed(void) #if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP const sleep_retention_module_bitmap_t inited_modules = sleep_retention_get_inited_modules(); const sleep_retention_module_bitmap_t created_modules = sleep_retention_get_created_modules(); + const sleep_retention_module_bitmap_t retained_modules = sleep_retention_get_retained_modules(); sleep_retention_module_bitmap_t mask = RETENTION_MODULE_BITMAP_INIT(NULL); RETENTION_MODULE_BITMAP_SET(&mask, SLEEP_RETENTION_MODULE_SYS_PERIPH); @@ -79,7 +80,15 @@ bool peripheral_domain_pd_allowed(void) 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); + bool ic = sleep_retention_module_bitmap_eq(peripheral_domain_inited_modules, peripheral_domain_created_modules); + + sleep_retention_module_bitmap_t mask_ign = mask; + mask_ign.bitmap[SLEEP_RETENTION_MODULE_TEMP_SENSOR >> 5] &= ~BIT(SLEEP_RETENTION_MODULE_TEMP_SENSOR % 32); + + const sleep_retention_module_bitmap_t peripheral_domain_created_ign_modules = sleep_retention_module_bitmap_and(created_modules, mask_ign); + const sleep_retention_module_bitmap_t peripheral_domain_retained_modules = sleep_retention_module_bitmap_and(retained_modules, mask_ign); + bool cr = sleep_retention_module_bitmap_eq(peripheral_domain_created_ign_modules, peripheral_domain_retained_modules); + return ic && cr; #else return false; #endif diff --git a/components/esp_hw_support/port/esp32h4/peripheral_domain_pd.c b/components/esp_hw_support/port/esp32h4/peripheral_domain_pd.c index a8aa135d8ec..00ace077271 100644 --- a/components/esp_hw_support/port/esp32h4/peripheral_domain_pd.c +++ b/components/esp_hw_support/port/esp32h4/peripheral_domain_pd.c @@ -15,6 +15,7 @@ bool peripheral_domain_pd_allowed(void) #if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP const sleep_retention_module_bitmap_t inited_modules = sleep_retention_get_inited_modules(); const sleep_retention_module_bitmap_t created_modules = sleep_retention_get_created_modules(); + const sleep_retention_module_bitmap_t retained_modules = sleep_retention_get_retained_modules(); sleep_retention_module_bitmap_t mask = RETENTION_MODULE_BITMAP_INIT(NULL); RETENTION_MODULE_BITMAP_SET(&mask, SLEEP_RETENTION_MODULE_SYS_PERIPH); @@ -83,7 +84,15 @@ bool peripheral_domain_pd_allowed(void) 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); + bool ic = sleep_retention_module_bitmap_eq(peripheral_domain_inited_modules, peripheral_domain_created_modules); + + sleep_retention_module_bitmap_t mask_ign = mask; + mask_ign.bitmap[SLEEP_RETENTION_MODULE_TEMP_SENSOR >> 5] &= ~BIT(SLEEP_RETENTION_MODULE_TEMP_SENSOR % 32); + + const sleep_retention_module_bitmap_t peripheral_domain_created_ign_modules = sleep_retention_module_bitmap_and(created_modules, mask_ign); + const sleep_retention_module_bitmap_t peripheral_domain_retained_modules = sleep_retention_module_bitmap_and(retained_modules, mask_ign); + bool cr = sleep_retention_module_bitmap_eq(peripheral_domain_created_ign_modules, peripheral_domain_retained_modules); + return ic && cr; #else return false; #endif diff --git a/components/esp_hw_support/port/esp32p4/peripheral_domain_pd.c b/components/esp_hw_support/port/esp32p4/peripheral_domain_pd.c index a18a1749ae2..147de4f11bc 100644 --- a/components/esp_hw_support/port/esp32p4/peripheral_domain_pd.c +++ b/components/esp_hw_support/port/esp32p4/peripheral_domain_pd.c @@ -15,6 +15,7 @@ bool peripheral_domain_pd_allowed(void) #if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP const sleep_retention_module_bitmap_t inited_modules = sleep_retention_get_inited_modules(); const sleep_retention_module_bitmap_t created_modules = sleep_retention_get_created_modules(); + const sleep_retention_module_bitmap_t retained_modules = sleep_retention_get_retained_modules(); sleep_retention_module_bitmap_t mask = RETENTION_MODULE_BITMAP_INIT(NULL); RETENTION_MODULE_BITMAP_SET(&mask, SLEEP_RETENTION_MODULE_SYS_PERIPH); @@ -107,7 +108,10 @@ bool peripheral_domain_pd_allowed(void) 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); + const sleep_retention_module_bitmap_t peripheral_domain_retained_modules = sleep_retention_module_bitmap_and(retained_modules, mask); + bool ic = sleep_retention_module_bitmap_eq(peripheral_domain_inited_modules, peripheral_domain_created_modules); + bool cr = sleep_retention_module_bitmap_eq(peripheral_domain_created_modules, peripheral_domain_retained_modules); + return ic && cr; #else return false; #endif diff --git a/components/esp_hw_support/port/esp32s31/peripheral_domain_pd.c b/components/esp_hw_support/port/esp32s31/peripheral_domain_pd.c index 4fdbde18c3d..9d6c43311b2 100644 --- a/components/esp_hw_support/port/esp32s31/peripheral_domain_pd.c +++ b/components/esp_hw_support/port/esp32s31/peripheral_domain_pd.c @@ -15,6 +15,7 @@ bool peripheral_domain_pd_allowed(void) #if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP const sleep_retention_module_bitmap_t inited_modules = sleep_retention_get_inited_modules(); const sleep_retention_module_bitmap_t created_modules = sleep_retention_get_created_modules(); + const sleep_retention_module_bitmap_t retained_modules = sleep_retention_get_retained_modules(); sleep_retention_module_bitmap_t mask = RETENTION_MODULE_BITMAP_INIT(NULL); RETENTION_MODULE_BITMAP_SET(&mask, SLEEP_RETENTION_MODULE_SYS_PERIPH); @@ -97,7 +98,10 @@ bool peripheral_domain_pd_allowed(void) 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); + const sleep_retention_module_bitmap_t peripheral_domain_retained_modules = sleep_retention_module_bitmap_and(retained_modules, mask); + bool ic = sleep_retention_module_bitmap_eq(peripheral_domain_inited_modules, peripheral_domain_created_modules); + bool cr = sleep_retention_module_bitmap_eq(peripheral_domain_created_modules, peripheral_domain_retained_modules); + return ic && cr; #else return false; #endif From 03686080ac5e7796a0af33ff8b1f74262bd6d043 Mon Sep 17 00:00:00 2001 From: cjin Date: Thu, 7 May 2026 14:06:22 +0800 Subject: [PATCH 13/22] fix(btbb): add sleep retention attach/detach at btbb enable/disable --- components/esp_driver_jpeg/jpeg_common.c | 5 ++ components/esp_lcd/i80/esp_lcd_panel_io_i80.c | 6 +++ components/esp_phy/src/btbb_init.c | 54 +++++++++++++------ 3 files changed, 48 insertions(+), 17 deletions(-) diff --git a/components/esp_driver_jpeg/jpeg_common.c b/components/esp_driver_jpeg/jpeg_common.c index 1be1eafcd36..5028c864442 100644 --- a/components/esp_driver_jpeg/jpeg_common.c +++ b/components/esp_driver_jpeg/jpeg_common.c @@ -54,6 +54,9 @@ void jpeg_create_retention_module(jpeg_codec_handle_t jpeg_codec) ESP_LOGW(TAG, "create retention module failed, power domain can't turn off"); } else { jpeg_codec->retention_link_created = true; + if (sleep_retention_module_attach(jpeg_regs_retention.module_id) != ESP_OK) { + ESP_LOGW(TAG, "attach retention module failed, power domain can't turn off"); + } } } _lock_release(&s_jpeg_platform.mutex); @@ -90,6 +93,7 @@ esp_err_t jpeg_acquire_codec_handle(jpeg_codec_handle_t *jpeg_new_codec) .arg = (void *)codec }, }, + .attribute = SLEEP_RETENTION_MODULE_ATTR_ATTACH, .depends = RETENTION_MODULE_BITMAP_INIT(CLOCK_SYSTEM) }; esp_err_t err = sleep_retention_module_init(jpeg_regs_retention.module_id, &init_param); @@ -147,6 +151,7 @@ esp_err_t jpeg_release_codec_handle(jpeg_codec_handle_t jpeg_codec) #if JPEG_USE_RETENTION_LINK if (jpeg_codec->retention_link_created) { + sleep_retention_module_detach(jpeg_regs_retention.module_id); sleep_retention_module_free(jpeg_regs_retention.module_id); } sleep_retention_module_deinit(jpeg_regs_retention.module_id); diff --git a/components/esp_lcd/i80/esp_lcd_panel_io_i80.c b/components/esp_lcd/i80/esp_lcd_panel_io_i80.c index d6d82583f73..9274b53cd25 100644 --- a/components/esp_lcd/i80/esp_lcd_panel_io_i80.c +++ b/components/esp_lcd/i80/esp_lcd_panel_io_i80.c @@ -170,6 +170,7 @@ esp_err_t esp_lcd_new_i80_bus(const esp_lcd_i80_bus_config_t *bus_config, esp_lc .arg = bus, }, }, + .attribute = SLEEP_RETENTION_MODULE_ATTR_ATTACH, .depends = RETENTION_MODULE_BITMAP_INIT(CLOCK_SYSTEM) }; if (sleep_retention_module_init(module_id, &init_param) != ESP_OK) { @@ -282,6 +283,7 @@ esp_err_t esp_lcd_del_i80_bus(esp_lcd_i80_bus_handle_t bus) } #if I80_USE_RETENTION_LINK const periph_retention_module_t module_id = soc_i80_lcd_retention_info[bus_id].retention_module; + sleep_retention_module_detach(module_id); if (sleep_retention_is_module_created(module_id)) { assert(sleep_retention_is_module_inited(module_id)); sleep_retention_module_free(module_id); @@ -618,6 +620,10 @@ static void lcd_i80_create_retention_module(esp_lcd_i80_bus_t *bus) 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"); + } else { + if (sleep_retention_module_attach(module_id) != ESP_OK) { + ESP_LOGW(TAG, "attach retention module failed, power domain can't turn off"); + } } } } diff --git a/components/esp_phy/src/btbb_init.c b/components/esp_phy/src/btbb_init.c index a4e67296aaa..d0d3b535101 100644 --- a/components/esp_phy/src/btbb_init.c +++ b/components/esp_phy/src/btbb_init.c @@ -47,17 +47,45 @@ static esp_err_t btbb_sleep_retention_init(void *arg) return ESP_OK; } -static void btbb_sleep_retention_deinit(void) +static void btbb_sleep_retention_disable(void) { - esp_err_t err = sleep_retention_module_free(SLEEP_RETENTION_MODULE_BT_BB); + esp_err_t err = sleep_retention_module_detach(SLEEP_RETENTION_MODULE_BT_BB); if (err != ESP_OK) { - ESP_LOGW(TAG, "failed to destroy sleep retention linked list for btbb retention"); + ESP_LOGW(TAG, "failed to detach sleep retention linked list for btbb retention"); + } + err = sleep_retention_module_free(SLEEP_RETENTION_MODULE_BT_BB); + if (err != ESP_OK) { + ESP_LOGW(TAG, "failed to free sleep retention linked list for btbb retention"); } err = sleep_retention_module_deinit(SLEEP_RETENTION_MODULE_BT_BB); if (err != ESP_OK) { ESP_LOGW(TAG, "Modem BT BB retention callback unregister failed"); } } + +static esp_err_t btbb_sleep_retention_enable(void) +{ + sleep_retention_module_init_param_t init_param = { + .cbs = { .create = { .handle = btbb_sleep_retention_init, .arg = NULL } }, + .attribute = SLEEP_RETENTION_MODULE_ATTR_ATTACH, + .depends = RETENTION_MODULE_BITMAP_INIT(CLOCK_MODEM) + }; + esp_err_t err = sleep_retention_module_init(SLEEP_RETENTION_MODULE_BT_BB, &init_param); + if (err != ESP_OK) { + ESP_LOGW(TAG, "Modem BT BB retention callback register failed"); + return err; + } + err = sleep_retention_module_allocate(SLEEP_RETENTION_MODULE_BT_BB); + if (err != ESP_OK) { + ESP_LOGW(TAG, "failed to allocate sleep retention linked list for btbb retention"); + return err; + } + err = sleep_retention_module_attach(SLEEP_RETENTION_MODULE_BT_BB); + if (err != ESP_OK) { + ESP_LOGW(TAG, "failed to attach sleep retention linked list for btbb retention"); + } + return err; +} #endif // SOC_PM_MODEM_RETENTION_BY_REGDMA && CONFIG_FREERTOS_USE_TICKLESS_IDLE void esp_btbb_enable(void) @@ -66,19 +94,11 @@ void esp_btbb_enable(void) if (s_btbb_access_ref == 0) { bt_bb_v2_init_cmplx(BTBB_ENABLE_VERSION_PRINT); #if SOC_PM_MODEM_RETENTION_BY_REGDMA && CONFIG_FREERTOS_USE_TICKLESS_IDLE - sleep_retention_module_init_param_t init_param = { - .cbs = { .create = { .handle = btbb_sleep_retention_init, .arg = NULL } }, - .attribute = SLEEP_RETENTION_MODULE_ATTR_ATTACH, - .depends = RETENTION_MODULE_BITMAP_INIT(CLOCK_MODEM) - }; - esp_err_t err = sleep_retention_module_init(SLEEP_RETENTION_MODULE_BT_BB, &init_param); - if (err == ESP_OK) { - err = sleep_retention_module_allocate(SLEEP_RETENTION_MODULE_BT_BB); - if (err != ESP_OK) { - ESP_LOGW(TAG, "failed to allocate sleep retention linked list for btbb retention"); - } - } else { - ESP_LOGW(TAG, "Modem BT BB retention callback register failed"); + esp_err_t err = btbb_sleep_retention_enable(); + if (err != ESP_OK) { + btbb_sleep_retention_disable(); + _lock_release(&s_btbb_access_lock); + return; } #endif // SOC_PM_MODEM_RETENTION_BY_REGDMA && CONFIG_FREERTOS_USE_TICKLESS_IDLE } @@ -91,7 +111,7 @@ void esp_btbb_disable(void) _lock_acquire(&s_btbb_access_lock); if (s_btbb_access_ref && (--s_btbb_access_ref == 0)) { #if SOC_PM_MODEM_RETENTION_BY_REGDMA && CONFIG_FREERTOS_USE_TICKLESS_IDLE - btbb_sleep_retention_deinit(); + btbb_sleep_retention_disable(); #endif // SOC_PM_MODEM_RETENTION_BY_REGDMA && CONFIG_FREERTOS_USE_TICKLESS_IDLE } _lock_release(&s_btbb_access_lock); From 60cd0833965991a4055a2232e0a50be44c0a7157 Mon Sep 17 00:00:00 2001 From: zwx Date: Wed, 6 May 2026 19:39:33 +0800 Subject: [PATCH 14/22] feat(ieee802154): support sleep retention attaching feature --- .../ieee802154/driver/esp_ieee802154_dev.c | 22 ++++++++++++------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/components/ieee802154/driver/esp_ieee802154_dev.c b/components/ieee802154/driver/esp_ieee802154_dev.c index ee3ebe7bcf1..4502fa4b8dc 100644 --- a/components/ieee802154/driver/esp_ieee802154_dev.c +++ b/components/ieee802154/driver/esp_ieee802154_dev.c @@ -1118,14 +1118,18 @@ static esp_err_t ieee802154_sleep_init(void) { esp_err_t err = ESP_OK; #if CONFIG_PM_ENABLE - sleep_retention_module_init_param_t init_param = { .cbs = { .create = { .handle = ieee802154_sleep_retention_init, .arg = NULL } } }; + sleep_retention_module_init_param_t init_param = { + .cbs = { .create = { .handle = ieee802154_sleep_retention_init, .arg = NULL } }, + .attribute = SLEEP_RETENTION_MODULE_ATTR_ATTACH + }; init_param.depends.bitmap[SLEEP_RETENTION_MODULE_BT_BB >> 5] |= BIT(SLEEP_RETENTION_MODULE_BT_BB % 32); init_param.depends.bitmap[SLEEP_RETENTION_MODULE_CLOCK_MODEM >> 5] |= BIT(SLEEP_RETENTION_MODULE_CLOCK_MODEM % 32); err = sleep_retention_module_init(SLEEP_RETENTION_MODULE_802154_MAC, &init_param); - if (err == ESP_OK) { - err = sleep_retention_module_allocate(SLEEP_RETENTION_MODULE_802154_MAC); - } - ESP_RETURN_ON_ERROR(err, IEEE802154_TAG, "failed to create sleep retention linked list for ieee802154 mac retention"); + ESP_RETURN_ON_ERROR(err, IEEE802154_TAG, "ieee802154 sleep retention init error"); + err = sleep_retention_module_allocate(SLEEP_RETENTION_MODULE_802154_MAC); + ESP_RETURN_ON_ERROR(err, IEEE802154_TAG, "ieee802154 sleep retention allocate error"); + err = sleep_retention_module_attach(SLEEP_RETENTION_MODULE_802154_MAC); + ESP_RETURN_ON_ERROR(err, IEEE802154_TAG, "ieee802154 sleep retention attach error"); #if SOC_PM_RETENTION_HAS_CLOCK_BUG && CONFIG_MAC_BB_PD sleep_modem_register_mac_bb_module_prepare_callback(sleep_modem_mac_bb_power_down_prepare, sleep_modem_mac_bb_power_up_prepare); @@ -1138,10 +1142,12 @@ static esp_err_t ieee802154_sleep_deinit(void) { esp_err_t err = ESP_OK; #if CONFIG_PM_ENABLE + err = sleep_retention_module_detach(SLEEP_RETENTION_MODULE_802154_MAC); + ESP_RETURN_ON_ERROR(err, IEEE802154_TAG, "ieee802154 sleep retention detach error"); err = sleep_retention_module_free(SLEEP_RETENTION_MODULE_802154_MAC); - if (err == ESP_OK) { - err = sleep_retention_module_deinit(SLEEP_RETENTION_MODULE_802154_MAC); - } + ESP_RETURN_ON_ERROR(err, IEEE802154_TAG, "ieee802154 sleep retention free error"); + err = sleep_retention_module_deinit(SLEEP_RETENTION_MODULE_802154_MAC); + ESP_RETURN_ON_ERROR(err, IEEE802154_TAG, "ieee802154 sleep retention deinit error"); #if SOC_PM_RETENTION_HAS_CLOCK_BUG && CONFIG_MAC_BB_PD sleep_modem_unregister_mac_bb_module_prepare_callback(sleep_modem_mac_bb_power_down_prepare, sleep_modem_mac_bb_power_up_prepare); From 7892eff854ae1050e4dee3431a9d2aef9e4831e5 Mon Sep 17 00:00:00 2001 From: Li Shuai Date: Wed, 13 May 2026 11:43:30 +0800 Subject: [PATCH 15/22] fix(ci): fix top domain power down not allow caused by ble power save not done --- .../esp_driver_gptimer/test_apps/gptimer/pytest_gptimer.py | 1 + components/esp_driver_ledc/test_apps/ledc/pytest_ledc.py | 1 + components/esp_driver_mcpwm/test_apps/mcpwm/pytest_mcpwm.py | 1 + components/esp_driver_rmt/test_apps/rmt/pytest_rmt.py | 1 + .../esp_driver_sdm/test_apps/sigma_delta/pytest_sigma_delta.py | 1 + 5 files changed, 5 insertions(+) diff --git a/components/esp_driver_gptimer/test_apps/gptimer/pytest_gptimer.py b/components/esp_driver_gptimer/test_apps/gptimer/pytest_gptimer.py index 041a83c36f3..246c934a2ed 100644 --- a/components/esp_driver_gptimer/test_apps/gptimer/pytest_gptimer.py +++ b/components/esp_driver_gptimer/test_apps/gptimer/pytest_gptimer.py @@ -7,6 +7,7 @@ from pytest_embedded_idf.utils import soc_filtered_targets @pytest.mark.generic +@pytest.mark.temp_skip_ci(targets=['esp32h4'], reason='BLE power save bringup is not done') @pytest.mark.parametrize( 'config', [ diff --git a/components/esp_driver_ledc/test_apps/ledc/pytest_ledc.py b/components/esp_driver_ledc/test_apps/ledc/pytest_ledc.py index 2a4453af593..84e2be2efff 100644 --- a/components/esp_driver_ledc/test_apps/ledc/pytest_ledc.py +++ b/components/esp_driver_ledc/test_apps/ledc/pytest_ledc.py @@ -7,6 +7,7 @@ from pytest_embedded_idf.utils import soc_filtered_targets @pytest.mark.temp_skip_ci(targets=['esp32s3'], reason='skip due to duplication with test_ledc_psram') +@pytest.mark.temp_skip_ci(targets=['esp32h4'], reason='BLE power save bringup is not done') @pytest.mark.generic @pytest.mark.parametrize( 'config', diff --git a/components/esp_driver_mcpwm/test_apps/mcpwm/pytest_mcpwm.py b/components/esp_driver_mcpwm/test_apps/mcpwm/pytest_mcpwm.py index 597caef05eb..bd4f9cded61 100644 --- a/components/esp_driver_mcpwm/test_apps/mcpwm/pytest_mcpwm.py +++ b/components/esp_driver_mcpwm/test_apps/mcpwm/pytest_mcpwm.py @@ -6,6 +6,7 @@ from pytest_embedded_idf.utils import idf_parametrize @pytest.mark.generic +@pytest.mark.temp_skip_ci(targets=['esp32h4'], reason='BLE power save bringup is not done') @pytest.mark.parametrize( 'config', [ diff --git a/components/esp_driver_rmt/test_apps/rmt/pytest_rmt.py b/components/esp_driver_rmt/test_apps/rmt/pytest_rmt.py index af2479efcb5..2c8ae27286a 100644 --- a/components/esp_driver_rmt/test_apps/rmt/pytest_rmt.py +++ b/components/esp_driver_rmt/test_apps/rmt/pytest_rmt.py @@ -7,6 +7,7 @@ from pytest_embedded_idf.utils import soc_filtered_targets @pytest.mark.generic +@pytest.mark.temp_skip_ci(targets=['esp32h4'], reason='BLE power save bringup is not done') @pytest.mark.parametrize( 'config', [ diff --git a/components/esp_driver_sdm/test_apps/sigma_delta/pytest_sigma_delta.py b/components/esp_driver_sdm/test_apps/sigma_delta/pytest_sigma_delta.py index efd82d173ad..f4b39199e46 100644 --- a/components/esp_driver_sdm/test_apps/sigma_delta/pytest_sigma_delta.py +++ b/components/esp_driver_sdm/test_apps/sigma_delta/pytest_sigma_delta.py @@ -12,6 +12,7 @@ CONFIGS = [ @pytest.mark.generic +@pytest.mark.temp_skip_ci(targets=['esp32h4'], reason='BLE power save bringup is not done') @pytest.mark.parametrize('config', CONFIGS, indirect=True) @idf_parametrize( 'target', From 2c33426d334a153c837b86d7a180750476889b1b Mon Sep 17 00:00:00 2001 From: Li Shuai Date: Thu, 14 May 2026 10:37:36 +0800 Subject: [PATCH 16/22] change(esp_hw_support): changes for suggestion --- components/esp_hw_support/sleep_retention.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/esp_hw_support/sleep_retention.c b/components/esp_hw_support/sleep_retention.c index 9a9274daf48..557c69a2a98 100644 --- a/components/esp_hw_support/sleep_retention.c +++ b/components/esp_hw_support/sleep_retention.c @@ -335,7 +335,7 @@ static void entries_stats(struct module_sleep_retention_context *ctx) { _lock_acquire_recursive(&s_retention.lock); for (regdma_link_priority_t priority = 0; priority < SLEEP_RETENTION_REGDMA_LINK_NR_PRIORITIES; priority++) { - for (int entry = 0; entry < ARRAY_SIZE(ctx->lists[s_retention.highpri].entries); entry++) { + for (int entry = 0; entry < ARRAY_SIZE(ctx->lists[priority].entries); entry++) { regdma_link_stats(ctx->lists[priority].entries[entry], entry); } } From 36b9f73e11b80b3c13551e203394b0db5c6ba099 Mon Sep 17 00:00:00 2001 From: cjin Date: Thu, 14 May 2026 14:09:00 +0800 Subject: [PATCH 17/22] fix(ble): fix btdm lp log tags compilation error --- .../controller/btdm_common/src/btdm_lp.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/components/bt/porting_btdm/controller/btdm_common/src/btdm_lp.c b/components/bt/porting_btdm/controller/btdm_common/src/btdm_lp.c index ed2dfd8a8a6..7046b2f5698 100644 --- a/components/bt/porting_btdm/controller/btdm_common/src/btdm_lp.c +++ b/components/bt/porting_btdm/controller/btdm_common/src/btdm_lp.c @@ -259,19 +259,19 @@ btdm_lp_modem_state_init(void) esp_err_t err = sleep_retention_module_init(SLEEP_RETENTION_MODULE_BLE_MAC, &init_param); if (err != ESP_OK) { - ESP_LOGE(NIMBLE_PORT_LOG_TAG, "BT sleep retention init error"); + ESP_LOGE(BTDM_LOG_TAG, "BT sleep retention init error"); return err; } err = sleep_retention_module_allocate(SLEEP_RETENTION_MODULE_BLE_MAC); if (err != ESP_OK) { - ESP_LOGE(NIMBLE_PORT_LOG_TAG, "BT sleep retention allocate error"); + ESP_LOGE(BTDM_LOG_TAG, "BT sleep retention allocate error"); return err; } err = sleep_retention_module_attach(SLEEP_RETENTION_MODULE_BLE_MAC); if (err != ESP_OK) { - ESP_LOGE(NIMBLE_PORT_LOG_TAG, "BT sleep retention attach error"); + ESP_LOGE(BTDM_LOG_TAG, "BT sleep retention attach error"); } return err; } @@ -281,19 +281,19 @@ btdm_lp_modem_state_deinit(void) { esp_err_t err = sleep_retention_module_detach(SLEEP_RETENTION_MODULE_BLE_MAC); if (err != ESP_OK) { - ESP_LOGE(NIMBLE_PORT_LOG_TAG, "BT sleep retention detach error"); + ESP_LOGE(BTDM_LOG_TAG, "BT sleep retention detach error"); assert(err == ESP_OK); } err = sleep_retention_module_free(SLEEP_RETENTION_MODULE_BLE_MAC); if (err != ESP_OK) { - ESP_LOGE(NIMBLE_PORT_LOG_TAG, "BT sleep retention free error"); + ESP_LOGE(BTDM_LOG_TAG, "BT sleep retention free error"); assert(err == ESP_OK); } err = sleep_retention_module_deinit(SLEEP_RETENTION_MODULE_BLE_MAC); if (err != ESP_OK) { - ESP_LOGE(NIMBLE_PORT_LOG_TAG, "BT sleep retention deinit error"); + ESP_LOGE(BTDM_LOG_TAG, "BT sleep retention deinit error"); assert(err == ESP_OK); } } From f01e818c40d0ab7209169508e10dcb6133af1276 Mon Sep 17 00:00:00 2001 From: Li Shuai Date: Fri, 15 May 2026 17:50:58 +0800 Subject: [PATCH 18/22] add comment for sleep_retention_module_attach interface --- .../include/esp_private/sleep_retention.h | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) 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 0e8ba7418e2..3c748c06388 100644 --- a/components/esp_hw_support/include/esp_private/sleep_retention.h +++ b/components/esp_hw_support/include/esp_private/sleep_retention.h @@ -161,6 +161,23 @@ esp_err_t sleep_retention_module_allocate(sleep_retention_module_t module); */ esp_err_t sleep_retention_module_free(sleep_retention_module_t module); +/** + * @brief Attach a module's sleep retention entries to the PMU REGDMA linked list + * + * After attachment, PMU REGDMA will execute backup and restore operations for + * this module during the SoC system's light sleep. The module must have been + * initialized with SLEEP_RETENTION_MODULE_ATTR_ATTACH attribute and its + * retention entries must have been allocated before calling this function. + * + * @param module the module number for the retention context to attach + * + * @return + * - ESP_OK on success + * - ESP_ERR_INVALID_ARG if the module is not valid or not initialized with attach attribute + * - ESP_ERR_NOT_SUPPORTED if the module does not support attachment + * - ESP_ERR_NOT_ALLOWED if the module state is not allowed + * - ESP_ERR_INVALID_STATE if the module's retention entries have not been allocated + */ esp_err_t sleep_retention_module_attach(sleep_retention_module_t module); esp_err_t sleep_retention_module_detach(sleep_retention_module_t module); From 7b541be9d52c59e51d8dbecbc5b8507ff1f3c044 Mon Sep 17 00:00:00 2001 From: Li Shuai Date: Fri, 15 May 2026 17:51:24 +0800 Subject: [PATCH 19/22] add comment for sleep_retention_module_detach interface --- .../include/esp_private/sleep_retention.h | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) 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 3c748c06388..aed019c1202 100644 --- a/components/esp_hw_support/include/esp_private/sleep_retention.h +++ b/components/esp_hw_support/include/esp_private/sleep_retention.h @@ -179,6 +179,23 @@ esp_err_t sleep_retention_module_free(sleep_retention_module_t module); * - ESP_ERR_INVALID_STATE if the module's retention entries have not been allocated */ esp_err_t sleep_retention_module_attach(sleep_retention_module_t module); + /** + * @brief Detach a module's sleep retention entries from the PMU REGDMA linked list + * + * After detachment, PMU REGDMA will no longer execute backup and restore + * operations for this module during the SoC system's light sleep. The + * retention entries are not freed and can be re-attached later via + * sleep_retention_module_attach(). + * + * @param module the module number for the retention context to detach + * + * @return + * - ESP_OK on success + * - ESP_ERR_INVALID_ARG if the module is not valid or not initialized with attach attribute + * - ESP_ERR_NOT_SUPPORTED if the module does not support detachment + * - ESP_ERR_NOT_ALLOWED if the module state is not allowed + * - ESP_ERR_INVALID_STATE if the module is not currently attached + */ esp_err_t sleep_retention_module_detach(sleep_retention_module_t module); /** From 68c9de209b6d9cdce37a955e153eb8164c4add15 Mon Sep 17 00:00:00 2001 From: sibeibei Date: Fri, 17 Apr 2026 19:22:25 +0800 Subject: [PATCH 20/22] feat(wifi): add sleep retention attach/detach in hw start/stop --- components/esp_phy/esp32c5/phy_init_data.c | 32 ++++++++----- components/esp_phy/esp32c6/phy_init_data.c | 21 ++++++++- components/esp_phy/esp32c61/phy_init_data.c | 21 ++++++++- components/esp_phy/esp32s31/phy_init_data.c | 19 ++++++++ components/esp_phy/include/esp_private/phy.h | 18 +++++++ components/esp_wifi/esp32c5/esp_adapter.c | 47 +++++++++++++++++++ components/esp_wifi/esp32c6/esp_adapter.c | 47 +++++++++++++++++++ components/esp_wifi/esp32c61/esp_adapter.c | 47 +++++++++++++++++++ components/esp_wifi/esp32s31/esp_adapter.c | 47 +++++++++++++++++++ .../esp_wifi/include/esp_private/wifi.h | 20 ++++++++ .../include/esp_private/wifi_os_adapter.h | 8 +++- components/esp_wifi/lib | 2 +- components/esp_wifi/src/wifi_init.c | 40 +++++++++++----- 13 files changed, 341 insertions(+), 28 deletions(-) diff --git a/components/esp_phy/esp32c5/phy_init_data.c b/components/esp_phy/esp32c5/phy_init_data.c index a216a678c0b..0ee2aa51599 100644 --- a/components/esp_phy/esp32c5/phy_init_data.c +++ b/components/esp_phy/esp32c5/phy_init_data.c @@ -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 */ @@ -312,6 +312,24 @@ static esp_err_t sleep_retention_wifi_bb_init(void *arg) return ESP_OK; } +esp_err_t esp_phy_wifi_bb_sleep_retention_attach(void) +{ + esp_err_t err = sleep_retention_module_attach(SLEEP_RETENTION_MODULE_WIFI_BB); + if (err != ESP_OK) { + ESP_LOGW(TAG, "failed to attach sleep retention linked list for wifi bb retention"); + } + return err; +} + +esp_err_t esp_phy_wifi_bb_sleep_retention_detach(void) +{ + esp_err_t err = sleep_retention_module_detach(SLEEP_RETENTION_MODULE_WIFI_BB); + if (err != ESP_OK) { + ESP_LOGW(TAG, "failed to detach sleep retention linked list for wifi bb retention"); + } + return err; +} + void esp_phy_sleep_data_init(void) { sleep_retention_module_init_param_t init_param = { @@ -327,22 +345,12 @@ void esp_phy_sleep_data_init(void) err = sleep_retention_module_allocate(SLEEP_RETENTION_MODULE_WIFI_BB); if (err != ESP_OK) { ESP_LOGW(TAG, "failed to allocate sleep retention linked list for wifi bb retention"); - return; - } - err = sleep_retention_module_attach(SLEEP_RETENTION_MODULE_WIFI_BB); - if (err != ESP_OK) { - ESP_LOGW(TAG, "failed to attach sleep retention linked list for wifi bb retention"); } } void esp_phy_sleep_data_deinit(void) { - esp_err_t err = sleep_retention_module_detach(SLEEP_RETENTION_MODULE_WIFI_BB); - if (err != ESP_OK) { - ESP_LOGW(TAG, "failed to detach sleep retention linked list for wifi bb retention"); - return; - } - err = sleep_retention_module_free(SLEEP_RETENTION_MODULE_WIFI_BB); + esp_err_t err = sleep_retention_module_free(SLEEP_RETENTION_MODULE_WIFI_BB); if (err != ESP_OK) { ESP_LOGW(TAG, "failed to free sleep retention linked list for wifi bb retention"); return; diff --git a/components/esp_phy/esp32c6/phy_init_data.c b/components/esp_phy/esp32c6/phy_init_data.c index a32c3c4668d..068b66a6088 100644 --- a/components/esp_phy/esp32c6/phy_init_data.c +++ b/components/esp_phy/esp32c6/phy_init_data.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2016-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2016-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -176,10 +176,29 @@ static esp_err_t sleep_retention_wifi_bb_init(void *arg) return ESP_OK; } +esp_err_t esp_phy_wifi_bb_sleep_retention_attach(void) +{ + esp_err_t err = sleep_retention_module_attach(SLEEP_RETENTION_MODULE_WIFI_BB); + if (err != ESP_OK) { + ESP_LOGW(TAG, "failed to attach sleep retention linked list for wifi bb retention"); + } + return err; +} + +esp_err_t esp_phy_wifi_bb_sleep_retention_detach(void) +{ + esp_err_t err = sleep_retention_module_detach(SLEEP_RETENTION_MODULE_WIFI_BB); + if (err != ESP_OK) { + ESP_LOGW(TAG, "failed to detach sleep retention linked list for wifi bb retention"); + } + return err; +} + void esp_phy_sleep_data_init(void) { sleep_retention_module_init_param_t init_param = { .cbs = { .create = { .handle = sleep_retention_wifi_bb_init, .arg = NULL } }, + .attribute = SLEEP_RETENTION_MODULE_ATTR_ATTACH, .depends = RETENTION_MODULE_BITMAP_INIT(CLOCK_MODEM) }; esp_err_t err = sleep_retention_module_init(SLEEP_RETENTION_MODULE_WIFI_BB, &init_param); diff --git a/components/esp_phy/esp32c61/phy_init_data.c b/components/esp_phy/esp32c61/phy_init_data.c index b06b158688d..081df9a8261 100644 --- a/components/esp_phy/esp32c61/phy_init_data.c +++ b/components/esp_phy/esp32c61/phy_init_data.c @@ -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 */ @@ -184,10 +184,29 @@ static esp_err_t sleep_retention_wifi_bb_init(void *arg) return ESP_OK; } +esp_err_t esp_phy_wifi_bb_sleep_retention_attach(void) +{ + esp_err_t err = sleep_retention_module_attach(SLEEP_RETENTION_MODULE_WIFI_BB); + if (err != ESP_OK) { + ESP_LOGW(TAG, "failed to attach sleep retention linked list for wifi bb retention"); + } + return err; +} + +esp_err_t esp_phy_wifi_bb_sleep_retention_detach(void) +{ + esp_err_t err = sleep_retention_module_detach(SLEEP_RETENTION_MODULE_WIFI_BB); + if (err != ESP_OK) { + ESP_LOGW(TAG, "failed to detach sleep retention linked list for wifi bb retention"); + } + return err; +} + void esp_phy_sleep_data_init(void) { sleep_retention_module_init_param_t init_param = { .cbs = { .create = { .handle = sleep_retention_wifi_bb_init, .arg = NULL } }, + .attribute = SLEEP_RETENTION_MODULE_ATTR_ATTACH, .depends = RETENTION_MODULE_BITMAP_INIT(CLOCK_MODEM) }; esp_err_t err = sleep_retention_module_init(SLEEP_RETENTION_MODULE_WIFI_BB, &init_param); diff --git a/components/esp_phy/esp32s31/phy_init_data.c b/components/esp_phy/esp32s31/phy_init_data.c index 8b732ddeb5c..e6a2b1eac44 100644 --- a/components/esp_phy/esp32s31/phy_init_data.c +++ b/components/esp_phy/esp32s31/phy_init_data.c @@ -184,10 +184,29 @@ static esp_err_t sleep_retention_wifi_bb_init(void *arg) return ESP_OK; } +esp_err_t esp_phy_wifi_bb_sleep_retention_attach(void) +{ + esp_err_t err = sleep_retention_module_attach(SLEEP_RETENTION_MODULE_WIFI_BB); + if (err != ESP_OK) { + ESP_LOGW(TAG, "failed to attach sleep retention linked list for wifi bb retention"); + } + return err; +} + +esp_err_t esp_phy_wifi_bb_sleep_retention_detach(void) +{ + esp_err_t err = sleep_retention_module_detach(SLEEP_RETENTION_MODULE_WIFI_BB); + if (err != ESP_OK) { + ESP_LOGW(TAG, "failed to detach sleep retention linked list for wifi bb retention"); + } + return err; +} + void esp_phy_sleep_data_init(void) { sleep_retention_module_init_param_t init_param = { .cbs = { .create = { .handle = sleep_retention_wifi_bb_init, .arg = NULL } }, + .attribute = SLEEP_RETENTION_MODULE_ATTR_ATTACH, .depends = RETENTION_MODULE_BITMAP_INIT(CLOCK_MODEM) }; esp_err_t err = sleep_retention_module_init(SLEEP_RETENTION_MODULE_WIFI_BB, &init_param); diff --git a/components/esp_phy/include/esp_private/phy.h b/components/esp_phy/include/esp_private/phy.h index de9a9820227..dcbafcab296 100644 --- a/components/esp_phy/include/esp_private/phy.h +++ b/components/esp_phy/include/esp_private/phy.h @@ -261,6 +261,24 @@ void esp_phy_modem_rf_flag_update(void); */ void esp_phy_sleep_data_init(void); +/** + * @brief Attach WiFi BB sleep retention linked list (REGDMA) after entries are allocated in `esp_phy_sleep_data_init()`. + * + * @return + * - ESP_OK on success + * - error code from sleep retention otherwise + */ +esp_err_t esp_phy_wifi_bb_sleep_retention_attach(void); + +/** + * @brief Detach WiFi BB sleep retention linked list (REGDMA) before `sleep_retention_module_free()` in `esp_phy_sleep_data_deinit()`. + * + * @return + * - ESP_OK on success + * - error code from sleep retention otherwise + */ +esp_err_t esp_phy_wifi_bb_sleep_retention_detach(void); + /** * @brief PHY module sleep data de-initialize. */ diff --git a/components/esp_wifi/esp32c5/esp_adapter.c b/components/esp_wifi/esp32c5/esp_adapter.c index 3d3030f2d09..e21354640b7 100644 --- a/components/esp_wifi/esp32c5/esp_adapter.c +++ b/components/esp_wifi/esp32c5/esp_adapter.c @@ -35,6 +35,9 @@ #include "esp_phy_init.h" #include "phy_init_data.h" #endif +#if CONFIG_MAC_BB_PD && SOC_PM_MODEM_RETENTION_BY_REGDMA +#include "esp_private/phy.h" +#endif #include "soc/rtc_cntl_periph.h" #include "soc/rtc.h" #include "esp_private/periph_ctrl.h" @@ -646,6 +649,44 @@ static bool esp_wifi_disable_ac_ax_wrapper(void) return false; // disable 11ac and 11ax is not supported on esp32c5. } +#if SOC_PM_MODEM_RETENTION_BY_REGDMA +static int32_t esp_phy_wifi_bb_sleep_retention_attach_wrapper(void) +{ +#if CONFIG_MAC_BB_PD + return (int32_t)esp_phy_wifi_bb_sleep_retention_attach(); +#else + return 1; +#endif +} + +static int32_t esp_phy_wifi_bb_sleep_retention_detach_wrapper(void) +{ +#if CONFIG_MAC_BB_PD + return (int32_t)esp_phy_wifi_bb_sleep_retention_detach(); +#else + return 1; +#endif +} + +static int32_t esp_wifi_mac_sleep_retention_attach_wrapper(void) +{ +#if CONFIG_MAC_BB_PD + return (int32_t)esp_wifi_internal_mac_sleep_retention_attach(); +#else + return 1; +#endif +} + +static int32_t esp_wifi_mac_sleep_retention_detach_wrapper(void) +{ +#if CONFIG_MAC_BB_PD + return (int32_t)esp_wifi_internal_mac_sleep_retention_detach(); +#else + return 1; +#endif +} +#endif + wifi_osi_funcs_t g_wifi_osi_funcs = { ._version = ESP_WIFI_OS_ADAPTER_VERSION, ._env_is_chip = esp_coex_common_env_is_chip_wrapper, @@ -770,5 +811,11 @@ wifi_osi_funcs_t g_wifi_osi_funcs = { ._coex_schm_flexible_period_get = coex_schm_flexible_period_get_wrapper, ._coex_schm_get_phase_by_idx = coex_schm_get_phase_by_idx_wrapper, ._wifi_disable_ac_ax = esp_wifi_disable_ac_ax_wrapper, +#if SOC_PM_MODEM_RETENTION_BY_REGDMA + ._wifi_bb_sleep_retention_attach = esp_phy_wifi_bb_sleep_retention_attach_wrapper, + ._wifi_bb_sleep_retention_detach = esp_phy_wifi_bb_sleep_retention_detach_wrapper, + ._wifi_mac_sleep_retention_attach = esp_wifi_mac_sleep_retention_attach_wrapper, + ._wifi_mac_sleep_retention_detach = esp_wifi_mac_sleep_retention_detach_wrapper, +#endif ._magic = ESP_WIFI_OS_ADAPTER_MAGIC, }; diff --git a/components/esp_wifi/esp32c6/esp_adapter.c b/components/esp_wifi/esp32c6/esp_adapter.c index 3b1af40aa1a..f3eafd771ca 100644 --- a/components/esp_wifi/esp32c6/esp_adapter.c +++ b/components/esp_wifi/esp32c6/esp_adapter.c @@ -36,6 +36,9 @@ #include "esp_phy_init.h" #include "phy_init_data.h" #endif +#if CONFIG_MAC_BB_PD && SOC_PM_MODEM_RETENTION_BY_REGDMA +#include "esp_private/phy.h" +#endif #include "soc/rtc_cntl_periph.h" #include "soc/rtc.h" #include "esp_private/periph_ctrl.h" @@ -584,6 +587,44 @@ static bool esp_wifi_disable_ac_ax_wrapper(void) return false; // disable 11ac and 11ax is not supported on esp32c6. } +#if SOC_PM_MODEM_RETENTION_BY_REGDMA +static int32_t esp_phy_wifi_bb_sleep_retention_attach_wrapper(void) +{ +#if CONFIG_MAC_BB_PD + return (int32_t)esp_phy_wifi_bb_sleep_retention_attach(); +#else + return 1; +#endif +} + +static int32_t esp_phy_wifi_bb_sleep_retention_detach_wrapper(void) +{ +#if CONFIG_MAC_BB_PD + return (int32_t)esp_phy_wifi_bb_sleep_retention_detach(); +#else + return 1; +#endif +} + +static int32_t esp_wifi_mac_sleep_retention_attach_wrapper(void) +{ +#if CONFIG_MAC_BB_PD + return (int32_t)esp_wifi_internal_mac_sleep_retention_attach(); +#else + return 1; +#endif +} + +static int32_t esp_wifi_mac_sleep_retention_detach_wrapper(void) +{ +#if CONFIG_MAC_BB_PD + return (int32_t)esp_wifi_internal_mac_sleep_retention_detach(); +#else + return 1; +#endif +} +#endif + wifi_osi_funcs_t g_wifi_osi_funcs = { ._version = ESP_WIFI_OS_ADAPTER_VERSION, ._env_is_chip = esp_coex_common_env_is_chip_wrapper, @@ -708,5 +749,11 @@ wifi_osi_funcs_t g_wifi_osi_funcs = { ._coex_schm_flexible_period_get = coex_schm_flexible_period_get_wrapper, ._coex_schm_get_phase_by_idx = coex_schm_get_phase_by_idx_wrapper, ._wifi_disable_ac_ax = esp_wifi_disable_ac_ax_wrapper, +#if SOC_PM_MODEM_RETENTION_BY_REGDMA + ._wifi_bb_sleep_retention_attach = esp_phy_wifi_bb_sleep_retention_attach_wrapper, + ._wifi_bb_sleep_retention_detach = esp_phy_wifi_bb_sleep_retention_detach_wrapper, + ._wifi_mac_sleep_retention_attach = esp_wifi_mac_sleep_retention_attach_wrapper, + ._wifi_mac_sleep_retention_detach = esp_wifi_mac_sleep_retention_detach_wrapper, +#endif ._magic = ESP_WIFI_OS_ADAPTER_MAGIC, }; diff --git a/components/esp_wifi/esp32c61/esp_adapter.c b/components/esp_wifi/esp32c61/esp_adapter.c index f62435ef0d4..2b11cf6f64b 100644 --- a/components/esp_wifi/esp32c61/esp_adapter.c +++ b/components/esp_wifi/esp32c61/esp_adapter.c @@ -35,6 +35,9 @@ #include "esp_phy_init.h" #include "phy_init_data.h" #endif +#if CONFIG_MAC_BB_PD && SOC_PM_MODEM_RETENTION_BY_REGDMA +#include "esp_private/phy.h" +#endif #include "soc/rtc_cntl_periph.h" #include "soc/rtc.h" #include "esp_private/periph_ctrl.h" @@ -648,6 +651,44 @@ static bool esp_wifi_disable_ac_ax_wrapper(void) return esp_efuse_read_field_bit(ESP_EFUSE_DIS_WIFI6); } +#if SOC_PM_MODEM_RETENTION_BY_REGDMA +static int32_t esp_phy_wifi_bb_sleep_retention_attach_wrapper(void) +{ +#if CONFIG_MAC_BB_PD + return (int32_t)esp_phy_wifi_bb_sleep_retention_attach(); +#else + return 1; +#endif +} + +static int32_t esp_phy_wifi_bb_sleep_retention_detach_wrapper(void) +{ +#if CONFIG_MAC_BB_PD + return (int32_t)esp_phy_wifi_bb_sleep_retention_detach(); +#else + return 1; +#endif +} + +static int32_t esp_wifi_mac_sleep_retention_attach_wrapper(void) +{ +#if CONFIG_MAC_BB_PD + return (int32_t)esp_wifi_internal_mac_sleep_retention_attach(); +#else + return 1; +#endif +} + +static int32_t esp_wifi_mac_sleep_retention_detach_wrapper(void) +{ +#if CONFIG_MAC_BB_PD + return (int32_t)esp_wifi_internal_mac_sleep_retention_detach(); +#else + return 1; +#endif +} +#endif + wifi_osi_funcs_t g_wifi_osi_funcs = { ._version = ESP_WIFI_OS_ADAPTER_VERSION, ._env_is_chip = esp_coex_common_env_is_chip_wrapper, @@ -772,5 +813,11 @@ wifi_osi_funcs_t g_wifi_osi_funcs = { ._coex_schm_flexible_period_get = coex_schm_flexible_period_get_wrapper, ._coex_schm_get_phase_by_idx = coex_schm_get_phase_by_idx_wrapper, ._wifi_disable_ac_ax = esp_wifi_disable_ac_ax_wrapper, +#if SOC_PM_MODEM_RETENTION_BY_REGDMA + ._wifi_bb_sleep_retention_attach = esp_phy_wifi_bb_sleep_retention_attach_wrapper, + ._wifi_bb_sleep_retention_detach = esp_phy_wifi_bb_sleep_retention_detach_wrapper, + ._wifi_mac_sleep_retention_attach = esp_wifi_mac_sleep_retention_attach_wrapper, + ._wifi_mac_sleep_retention_detach = esp_wifi_mac_sleep_retention_detach_wrapper, +#endif ._magic = ESP_WIFI_OS_ADAPTER_MAGIC, }; diff --git a/components/esp_wifi/esp32s31/esp_adapter.c b/components/esp_wifi/esp32s31/esp_adapter.c index 6e732d27f87..625f4b4b016 100644 --- a/components/esp_wifi/esp32s31/esp_adapter.c +++ b/components/esp_wifi/esp32s31/esp_adapter.c @@ -35,6 +35,9 @@ #include "esp_phy_init.h" #include "phy_init_data.h" #endif +#if CONFIG_MAC_BB_PD && SOC_PM_MODEM_RETENTION_BY_REGDMA +#include "esp_private/phy.h" +#endif #include "soc/rtc_cntl_periph.h" #include "soc/rtc.h" #include "esp_private/periph_ctrl.h" @@ -655,6 +658,44 @@ static bool esp_wifi_disable_ac_ax_wrapper(void) return false; // disable 11ac and 11ax is not supported on esp32s31. } +#if SOC_PM_MODEM_RETENTION_BY_REGDMA +static int32_t esp_phy_wifi_bb_sleep_retention_attach_wrapper(void) +{ +#if CONFIG_MAC_BB_PD + return (int32_t)esp_phy_wifi_bb_sleep_retention_attach(); +#else + return 1; +#endif +} + +static int32_t esp_phy_wifi_bb_sleep_retention_detach_wrapper(void) +{ +#if CONFIG_MAC_BB_PD + return (int32_t)esp_phy_wifi_bb_sleep_retention_detach(); +#else + return 1; +#endif +} + +static int32_t esp_wifi_mac_sleep_retention_attach_wrapper(void) +{ +#if CONFIG_MAC_BB_PD + return (int32_t)esp_wifi_internal_mac_sleep_retention_attach(); +#else + return 1; +#endif +} + +static int32_t esp_wifi_mac_sleep_retention_detach_wrapper(void) +{ +#if CONFIG_MAC_BB_PD + return (int32_t)esp_wifi_internal_mac_sleep_retention_detach(); +#else + return 1; +#endif +} +#endif + wifi_osi_funcs_t g_wifi_osi_funcs = { ._version = ESP_WIFI_OS_ADAPTER_VERSION, ._env_is_chip = esp_coex_common_env_is_chip_wrapper, @@ -780,5 +821,11 @@ wifi_osi_funcs_t g_wifi_osi_funcs = { ._coex_schm_get_phase_by_idx = coex_schm_get_phase_by_idx_wrapper, ._coex_configure_preemption_end_cb = coex_configure_preemption_end_cb_wrapper, ._wifi_disable_ac_ax = esp_wifi_disable_ac_ax_wrapper, +#if SOC_PM_MODEM_RETENTION_BY_REGDMA + ._wifi_bb_sleep_retention_attach = esp_phy_wifi_bb_sleep_retention_attach_wrapper, + ._wifi_bb_sleep_retention_detach = esp_phy_wifi_bb_sleep_retention_detach_wrapper, + ._wifi_mac_sleep_retention_attach = esp_wifi_mac_sleep_retention_attach_wrapper, + ._wifi_mac_sleep_retention_detach = esp_wifi_mac_sleep_retention_detach_wrapper, +#endif ._magic = ESP_WIFI_OS_ADAPTER_MAGIC, }; diff --git a/components/esp_wifi/include/esp_private/wifi.h b/components/esp_wifi/include/esp_private/wifi.h index 077f1d1354b..2d783a08d21 100644 --- a/components/esp_wifi/include/esp_private/wifi.h +++ b/components/esp_wifi/include/esp_private/wifi.h @@ -854,6 +854,26 @@ void esp_wifi_power_domain_off(void); void * esp_wifi_internal_mac_retention_context_get(int *config_size); #endif +#if CONFIG_MAC_BB_PD && SOC_PM_MODEM_RETENTION_BY_REGDMA +/** + * @brief Attach Wi-Fi MAC sleep retention (REGDMA) linked list after allocation. + * + * @return + * - ESP_OK on success + * - error code from sleep retention otherwise + */ +esp_err_t esp_wifi_internal_mac_sleep_retention_attach(void); + +/** + * @brief Detach Wi-Fi MAC sleep retention (REGDMA) linked list before free. + * + * @return + * - ESP_OK on success + * - error code from sleep retention otherwise + */ +esp_err_t esp_wifi_internal_mac_sleep_retention_detach(void); +#endif + #if CONFIG_MAC_BB_PD /** * @brief Enable or disable powering down MAC and baseband when Wi-Fi is sleeping. diff --git a/components/esp_wifi/include/esp_private/wifi_os_adapter.h b/components/esp_wifi/include/esp_private/wifi_os_adapter.h index 3315044ab23..0c9ec1e06b8 100644 --- a/components/esp_wifi/include/esp_private/wifi_os_adapter.h +++ b/components/esp_wifi/include/esp_private/wifi_os_adapter.h @@ -17,7 +17,7 @@ extern "C" { #endif -#define ESP_WIFI_OS_ADAPTER_VERSION 0x00000008 +#define ESP_WIFI_OS_ADAPTER_VERSION 0x00000009 #define ESP_WIFI_OS_ADAPTER_MAGIC 0xDEADBEAF #define OSI_FUNCS_TIME_BLOCKING 0xffffffff @@ -161,6 +161,12 @@ typedef struct wifi_osi_funcs_t { #endif #if CONFIG_SOC_WIFI_HE_SUPPORT bool (*_wifi_disable_ac_ax)(void); +#endif +#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32C5 || CONFIG_IDF_TARGET_ESP32C61 || CONFIG_IDF_TARGET_ESP32S31 + int32_t (* _wifi_bb_sleep_retention_attach)(void); + int32_t (* _wifi_bb_sleep_retention_detach)(void); + int32_t (* _wifi_mac_sleep_retention_attach)(void); + int32_t (* _wifi_mac_sleep_retention_detach)(void); #endif int32_t _magic; } wifi_osi_funcs_t; diff --git a/components/esp_wifi/lib b/components/esp_wifi/lib index bf7ccb11fe8..e61a56b9e6d 160000 --- a/components/esp_wifi/lib +++ b/components/esp_wifi/lib @@ -1 +1 @@ -Subproject commit bf7ccb11fe8125539f3709dc49e6d7523f3cdeb0 +Subproject commit e61a56b9e6d1a522a2f47a43ef4e7db1684c6825 diff --git a/components/esp_wifi/src/wifi_init.c b/components/esp_wifi/src/wifi_init.c index 81394283272..216c9dfff2b 100644 --- a/components/esp_wifi/src/wifi_init.c +++ b/components/esp_wifi/src/wifi_init.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -154,6 +154,28 @@ static esp_err_t init_wifi_mac_sleep_retention(void *arg) } #endif +#if CONFIG_MAC_BB_PD && SOC_PM_MODEM_RETENTION_BY_REGDMA +esp_err_t esp_wifi_internal_mac_sleep_retention_attach(void) +{ + esp_err_t err = sleep_retention_module_attach(SLEEP_RETENTION_MODULE_WIFI_MAC); + if (err != ESP_OK) { + ESP_LOGW(TAG, "failed to attach sleep retention linked list for wifi mac retention"); + } + esp_wifi_internal_set_mac_sleep(true); + return err; +} + +esp_err_t esp_wifi_internal_mac_sleep_retention_detach(void) +{ + esp_wifi_internal_set_mac_sleep(false); + esp_err_t err = sleep_retention_module_detach(SLEEP_RETENTION_MODULE_WIFI_MAC); + if (err != ESP_OK) { + ESP_LOGW(TAG, "failed to detach sleep retention linked list for wifi mac retention"); + } + return err; +} +#endif + #if CONFIG_MAC_BB_PD static void esp_wifi_mac_pd_mem_init(void) { @@ -162,25 +184,19 @@ static void esp_wifi_mac_pd_mem_init(void) if (err != ESP_OK) { ESP_LOGW(TAG, "failed to allocate sleep retention linked list for wifi mac retention"); } - err = sleep_retention_module_attach(SLEEP_RETENTION_MODULE_WIFI_MAC); - if (err != ESP_OK) { - ESP_LOGW(TAG, "failed to attach sleep retention linked list for wifi mac retention"); - } -#endif +#else esp_wifi_internal_set_mac_sleep(true); +#endif } static void esp_wifi_mac_pd_mem_deinit(void) { - esp_wifi_internal_set_mac_sleep(false); #if SOC_PM_MODEM_RETENTION_BY_REGDMA - esp_err_t err = sleep_retention_module_detach(SLEEP_RETENTION_MODULE_WIFI_MAC); - if (err != ESP_OK) { - ESP_LOGW(TAG, "failed to detach sleep retention linked list for wifi mac retention"); - } - err = sleep_retention_module_free(SLEEP_RETENTION_MODULE_WIFI_MAC); + esp_err_t err = sleep_retention_module_free(SLEEP_RETENTION_MODULE_WIFI_MAC); if (err != ESP_OK) { ESP_LOGW(TAG, "failed to free sleep retention linked list for wifi mac retention"); } +#else + esp_wifi_internal_set_mac_sleep(false); #endif } #endif From 5c7a8c0dc3b011f1cb295eb9bafbd7a1c79cfc37 Mon Sep 17 00:00:00 2001 From: Jack Date: Tue, 19 May 2026 15:21:58 +0800 Subject: [PATCH 21/22] fix the ci issue Test target MISMATCH --- components/esp_driver_ledc/test_apps/.build-test-rules.yml | 4 ++++ components/esp_driver_mcpwm/test_apps/.build-test-rules.yml | 4 ++++ components/esp_driver_rmt/test_apps/.build-test-rules.yml | 4 ++++ components/esp_driver_sdm/test_apps/.build-test-rules.yml | 4 ++++ 4 files changed, 16 insertions(+) diff --git a/components/esp_driver_ledc/test_apps/.build-test-rules.yml b/components/esp_driver_ledc/test_apps/.build-test-rules.yml index e98bab30649..4a4d8d46126 100644 --- a/components/esp_driver_ledc/test_apps/.build-test-rules.yml +++ b/components/esp_driver_ledc/test_apps/.build-test-rules.yml @@ -3,6 +3,10 @@ components/esp_driver_ledc/test_apps/ledc: disable: - if: SOC_LEDC_SUPPORTED != 1 + disable_test: + - if: IDF_TARGET in ["esp32h4"] + temporary: true + reason: BLE power save bringup is not done depends_components: - esp_driver_ledc - esp_hal_ledc diff --git a/components/esp_driver_mcpwm/test_apps/.build-test-rules.yml b/components/esp_driver_mcpwm/test_apps/.build-test-rules.yml index c3027046e53..474af4efadf 100644 --- a/components/esp_driver_mcpwm/test_apps/.build-test-rules.yml +++ b/components/esp_driver_mcpwm/test_apps/.build-test-rules.yml @@ -3,6 +3,10 @@ components/esp_driver_mcpwm/test_apps/mcpwm: disable: - if: SOC_MCPWM_SUPPORTED != 1 + disable_test: + - if: IDF_TARGET in ["esp32h4"] + temporary: true + reason: BLE power save bringup is not done depends_components: - esp_driver_mcpwm - esp_hal_mcpwm diff --git a/components/esp_driver_rmt/test_apps/.build-test-rules.yml b/components/esp_driver_rmt/test_apps/.build-test-rules.yml index dc519798388..9450905225d 100644 --- a/components/esp_driver_rmt/test_apps/.build-test-rules.yml +++ b/components/esp_driver_rmt/test_apps/.build-test-rules.yml @@ -3,6 +3,10 @@ components/esp_driver_rmt/test_apps/rmt: disable: - if: SOC_RMT_SUPPORTED != 1 + disable_test: + - if: IDF_TARGET in ["esp32h4"] + temporary: true + reason: BLE power save bringup is not done depends_components: - esp_driver_rmt - esp_driver_dma diff --git a/components/esp_driver_sdm/test_apps/.build-test-rules.yml b/components/esp_driver_sdm/test_apps/.build-test-rules.yml index 1f632d478ae..cdbacc941c8 100644 --- a/components/esp_driver_sdm/test_apps/.build-test-rules.yml +++ b/components/esp_driver_sdm/test_apps/.build-test-rules.yml @@ -3,6 +3,10 @@ components/esp_driver_sdm/test_apps/sigma_delta: disable: - if: SOC_SDM_SUPPORTED != 1 + disable_test: + - if: IDF_TARGET in ["esp32h4"] + temporary: true + reason: BLE power save bringup is not done depends_components: - esp_driver_gpio - esp_driver_sdm From 00c03f61f042ad6b3365b4a6e8b2629fce7e6e31 Mon Sep 17 00:00:00 2001 From: Li Shuai Date: Wed, 20 May 2026 20:22:52 +0800 Subject: [PATCH 22/22] fix(ci): fix the ci issue of Test target MISMATCH by esp32h21 --- components/esp_driver_rmt/test_apps/.build-test-rules.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/esp_driver_rmt/test_apps/.build-test-rules.yml b/components/esp_driver_rmt/test_apps/.build-test-rules.yml index 9450905225d..1c644a6c78a 100644 --- a/components/esp_driver_rmt/test_apps/.build-test-rules.yml +++ b/components/esp_driver_rmt/test_apps/.build-test-rules.yml @@ -4,7 +4,7 @@ components/esp_driver_rmt/test_apps/rmt: disable: - if: SOC_RMT_SUPPORTED != 1 disable_test: - - if: IDF_TARGET in ["esp32h4"] + - if: IDF_TARGET in ["esp32h21"] temporary: true reason: BLE power save bringup is not done depends_components: