diff --git a/components/esp_hw_support/sleep_retention.c b/components/esp_hw_support/sleep_retention.c index ad8f40150d5..e9198c93411 100644 --- a/components/esp_hw_support/sleep_retention.c +++ b/components/esp_hw_support/sleep_retention.c @@ -170,6 +170,7 @@ static inline bool module_runtime_attach(struct sleep_retention_module_object * static inline bool module_is_passive(struct sleep_retention_module_object * const self) { + assert(self); return (get_attributes(self) & SLEEP_RETENTION_MODULE_ATTR_PASSIVE) ? true : false; } @@ -258,7 +259,7 @@ typedef struct { void *final_default; - struct sleep_retention_module_object instance[SLEEP_RETENTION_MODULE_MAX]; + struct sleep_retention_module_object *instance[SLEEP_RETENTION_MODULE_MAX]; #define EXTRA_LINK_NUM (REGDMA_LINK_ENTRY_NUM - 1) } sleep_retention_t; @@ -280,7 +281,27 @@ static void retention_entries_join(void); static struct sleep_retention_module_object * instance(sleep_retention_module_t module) { - return (module == SLEEP_RETENTION_MODULE_INVALID) ? NULL : &s_retention.instance[module]; + return (module >= SLEEP_RETENTION_MODULE_MAX) ? NULL : s_retention.instance[module]; +} + +static esp_err_t instance_allocate(sleep_retention_module_t module) +{ + if (s_retention.instance[module] != NULL) { + return ESP_ERR_INVALID_STATE; + } + struct sleep_retention_module_object *obj = (struct sleep_retention_module_object *)heap_caps_calloc( + 1, sizeof(struct sleep_retention_module_object), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); + if (obj == NULL) { + return ESP_ERR_NO_MEM; + } + s_retention.instance[module] = obj; + return ESP_OK; +} + +static void instance_free(sleep_retention_module_t module) +{ + heap_caps_free(s_retention.instance[module]); + s_retention.instance[module] = NULL; } static inline bool module_is_inited(sleep_retention_module_t module) @@ -926,25 +947,28 @@ bool IRAM_ATTR sleep_retention_module_bitmap_eq(sleep_retention_module_bitmap_t static void module_action(sleep_retention_module_t module, sleep_retention_module_t dep_module, int action) { + assert(module_is_inited(dep_module)); + struct sleep_retention_module_object *dep = instance(dep_module); + assert(dep); switch (action) { case 0: break; /* Nothing to do */ case 1: { /* allocate */ - set_reference(instance(dep_module), module); - if (module_is_passive(instance(dep_module)) && module_runtime_attach(instance(dep_module))) { + set_reference(dep, module); + if (module_is_passive(dep) && module_runtime_attach(dep)) { 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))) { + clr_reference(dep, module); + if (module_is_passive(dep) && module_runtime_attach(dep)) { 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 */ + case 3: refarray_set_bit(dep, 1, module); break; /* attach */ + case 4: refarray_clr_bit(dep, 1, module); break; /* detach */ default: break; } } @@ -963,7 +987,7 @@ static esp_err_t module_action_wrapper(sleep_retention_module_t module, int arg, #define action(x) ((x) & 0xf) module_action(module, dep_module, action(arg)); - if ((arg & BIT(31)) || module_is_passive(instance(dep_module))) { + if ((arg & BIT(31)) || (module_is_inited(dep_module) && module_is_passive(instance(dep_module)))) { err = (*rec)(dep_module); } } @@ -996,10 +1020,14 @@ esp_err_t sleep_retention_module_init(sleep_retention_module_t module, sleep_ret if (module_is_created(module) || module_is_inited(module)) { err = ESP_ERR_INVALID_STATE; } else { - sleep_retention_module_object_ctor(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); + err = instance_allocate(module); + if (err == ESP_OK) { + struct sleep_retention_module_object *mod = instance(module); + sleep_retention_module_object_ctor(mod, ¶m->cbs); + set_dependencies(mod, param->depends); + set_attributes(mod, param->attribute); + s_retention.inited_modules.bitmap[module >> 5] |= BIT(module % 32); + } } _lock_release_recursive(&s_retention.lock); return err; @@ -1017,9 +1045,11 @@ esp_err_t sleep_retention_module_deinit(sleep_retention_module_t module) if (module_is_created(module) || !module_is_inited(module)) { err = ESP_ERR_INVALID_STATE; } else { - clr_attributes(instance(module)); - clr_dependencies(instance(module)); - sleep_retention_module_object_dtor(instance(module)); + struct sleep_retention_module_object *mod = instance(module); + clr_attributes(mod); + clr_dependencies(mod); + sleep_retention_module_object_dtor(mod); + instance_free(module); s_retention.inited_modules.bitmap[module >> 5] &= ~BIT(module % 32); uint32_t inited_modules = 0; for (int i = 0; i < SLEEP_RETENTION_MODULE_BITMAP_SZ; i++) { @@ -1042,14 +1072,15 @@ static esp_err_t passive_module_allocate(sleep_retention_module_t module) esp_err_t err = ESP_OK; _lock_acquire_recursive(&s_retention.lock); - assert(module_is_passive(instance(module)) && "Illegal dependency"); assert(module_is_inited(module) && "All passive module must be inited first!"); + struct sleep_retention_module_object *mod = instance(module); + assert(module_is_passive(mod) && "Illegal dependency"); if (!module_is_created(module)) { err = module_action_wrapper(module, (BIT(31) | action(1)), passive_module_allocate); if (err == ESP_OK) { - sleep_retention_callback_t fn = instance(module)->cbs.create.handle; + sleep_retention_callback_t fn = mod->cbs.create.handle; if (fn) { - err = (*fn)(instance(module)->cbs.create.arg); + err = (*fn)(mod->cbs.create.arg); } } } @@ -1065,20 +1096,23 @@ 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(instance(module))) { - if (module_is_inited(module) && !module_is_created(module)) { + if (!module_is_inited(module)) { + err = ESP_ERR_INVALID_STATE; + } else { + struct sleep_retention_module_object *mod = instance(module); + if (module_is_passive(mod)) { + err = ESP_ERR_NOT_ALLOWED; + } else if (!module_is_created(module)) { err = module_action_wrapper(module, action(1), passive_module_allocate); if (err == ESP_OK) { - sleep_retention_callback_t fn = instance(module)->cbs.create.handle; + sleep_retention_callback_t fn = mod->cbs.create.handle; if (fn) { - err = (*fn)(instance(module)->cbs.create.arg); + err = (*fn)(mod->cbs.create.arg); } } } else { err = ESP_ERR_INVALID_STATE; } - } else { - err = ESP_ERR_NOT_ALLOWED; } _lock_release_recursive(&s_retention.lock); return err; @@ -1090,14 +1124,15 @@ static esp_err_t passive_module_free(sleep_retention_module_t module) esp_err_t err = ESP_OK; _lock_acquire_recursive(&s_retention.lock); - assert(module_is_passive(instance(module)) && "Illegal dependency"); assert(module_is_inited(module) && "All passive module must be inited first!"); + struct sleep_retention_module_object *mod = instance(module); + assert(module_is_passive(mod) && "Illegal dependency"); if (module_is_created(module)) { - if (!references_exist(instance(module))) { + if (!references_exist(mod)) { if (!module_is_retained(module)) { sleep_retention_entries_destroy(module); - if (instance(module)->cbs.destroy.handle) { - err = instance(module)->cbs.destroy.handle(instance(module)->cbs.destroy.arg); + if (mod->cbs.destroy.handle) { + err = mod->cbs.destroy.handle(mod->cbs.destroy.arg); } if (err == ESP_OK) { err = module_action_wrapper(module, (BIT(31) | action(2)), passive_module_free); @@ -1119,11 +1154,16 @@ 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(instance(module))) { - if (module_is_inited(module) && module_is_created(module) && !module_is_retained(module)) { + if (!module_is_inited(module)) { + err = ESP_ERR_INVALID_STATE; + } else { + struct sleep_retention_module_object *mod = instance(module); + if (module_is_passive(mod)) { + err = ESP_ERR_NOT_ALLOWED; + } else if (module_is_created(module) && !module_is_retained(module)) { sleep_retention_entries_destroy(module); - if (instance(module)->cbs.destroy.handle) { - err = instance(module)->cbs.destroy.handle(instance(module)->cbs.destroy.arg); + if (mod->cbs.destroy.handle) { + err = mod->cbs.destroy.handle(mod->cbs.destroy.arg); } if (err == ESP_OK) { err = module_action_wrapper(module, action(2), passive_module_free); @@ -1131,8 +1171,6 @@ esp_err_t sleep_retention_module_free(sleep_retention_module_t module) } else { err = ESP_ERR_INVALID_STATE; } - } else { - err = ESP_ERR_NOT_ALLOWED; } _lock_release_recursive(&s_retention.lock); return err; @@ -1167,10 +1205,11 @@ static esp_err_t passive_module_attach(sleep_retention_module_t module) 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)) { + __attribute__((unused)) struct sleep_retention_module_object *mod = instance(module); + assert(module_is_passive(mod) && "Illegal dependency"); + assert(module_runtime_attach(mod) && "Illegal dependency"); + if (module_is_created(module) && !module_is_retained(module)) { s_retention.attached_modules.bitmap[module >> 5] |= BIT(module % 32); s_retention.retention_modules.bitmap[module >> 5] |= BIT(module % 32); module_entries_move(module, &s_retention.context[1], &s_retention.retention); @@ -1188,9 +1227,14 @@ esp_err_t sleep_retention_module_attach(sleep_retention_module_t module) 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))) { + if (!module_is_inited(module)) { + err = ESP_ERR_INVALID_STATE; + } else { + struct sleep_retention_module_object *mod = instance(module); + if (module_is_passive(mod)) { + err = ESP_ERR_NOT_ALLOWED; + } else if (module_is_created(module) && !module_is_retained(module)) { + if (module_runtime_attach(mod)) { s_retention.attached_modules.bitmap[module >> 5] |= BIT(module % 32); s_retention.retention_modules.bitmap[module >> 5] |= BIT(module % 32); module_entries_move(module, &s_retention.context[1], &s_retention.retention); @@ -1201,8 +1245,6 @@ esp_err_t sleep_retention_module_attach(sleep_retention_module_t module) } else { err = ESP_ERR_INVALID_STATE; } - } else { - err = ESP_ERR_NOT_ALLOWED; } _lock_release_recursive(&s_retention.lock); return err; @@ -1214,11 +1256,12 @@ static esp_err_t passive_module_detach(sleep_retention_module_t module) 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)) { - if (refarray_zero(instance(module), 1)) { + struct sleep_retention_module_object *mod = instance(module); + assert(module_is_passive(mod) && "Illegal dependency"); + assert(module_runtime_attach(mod) && "Illegal dependency"); + if (module_is_created(module) && module_is_retained(module)) { + if (refarray_zero(mod, 1)) { s_retention.retention_modules.bitmap[module >> 5] &= ~BIT(module % 32); s_retention.attached_modules.bitmap[module >> 5] &= ~BIT(module % 32); module_entries_move(module, &s_retention.retention, &s_retention.context[1]); @@ -1237,9 +1280,14 @@ esp_err_t sleep_retention_module_detach(sleep_retention_module_t module) 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))) { + if (!module_is_inited(module)) { + err = ESP_ERR_INVALID_STATE; + } else { + struct sleep_retention_module_object *mod = instance(module); + if (module_is_passive(mod)) { + err = ESP_ERR_NOT_ALLOWED; + } else if (module_is_created(module) && module_is_retained(module)) { + if (module_runtime_attach(mod)) { s_retention.retention_modules.bitmap[module >> 5] &= ~BIT(module % 32); s_retention.attached_modules.bitmap[module >> 5] &= ~BIT(module % 32); module_entries_move(module, &s_retention.retention, &s_retention.context[1]); @@ -1250,8 +1298,6 @@ esp_err_t sleep_retention_module_detach(sleep_retention_module_t module) } else { err = ESP_ERR_INVALID_STATE; } - } else { - err = ESP_ERR_NOT_ALLOWED; } _lock_release_recursive(&s_retention.lock); return err;