fix(esp_driver_gptimer): do gptimer retention by timer unit rather than timer group

This commit is contained in:
wuzhenghui
2024-12-02 20:32:54 +08:00
parent 97d9f01134
commit 1a23d3cd53
16 changed files with 308 additions and 232 deletions

View File

@@ -25,6 +25,31 @@ static const char *TAG = "gptimer";
static void gptimer_default_isr(void *args);
#if GPTIMER_USE_RETENTION_LINK
static esp_err_t gptimer_create_sleep_retention_link_cb(void *timer)
{
int group_id = ((gptimer_t *)timer)->group->group_id;
int timer_id = ((gptimer_t *)timer)->timer_id;
esp_err_t err = sleep_retention_entries_create(tg_timer_reg_retention_info[group_id][timer_id].regdma_entry_array,
tg_timer_reg_retention_info[group_id][timer_id].array_size,
REGDMA_LINK_PRI_GPTIMER, tg_timer_reg_retention_info[group_id][timer_id].module);
return err;
}
static void gptimer_create_retention_module(gptimer_t *timer)
{
int group_id = timer->group->group_id;
int timer_id = timer->timer_id;
sleep_retention_module_t module = tg_timer_reg_retention_info[group_id][timer_id].module;
if ((sleep_retention_get_inited_modules() & BIT(module)) && !(sleep_retention_get_created_modules() & BIT(module))) {
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);
}
}
}
#endif // GPTIMER_USE_RETENTION_LINK
static esp_err_t gptimer_register_to_group(gptimer_t *timer)
{
gptimer_group_t *group = NULL;
@@ -51,6 +76,24 @@ static esp_err_t gptimer_register_to_group(gptimer_t *timer)
}
}
ESP_RETURN_ON_FALSE(timer_id != -1, ESP_ERR_NOT_FOUND, TAG, "no free timer");
#if GPTIMER_USE_RETENTION_LINK
sleep_retention_module_t module = tg_timer_reg_retention_info[group->group_id][timer_id].module;
sleep_retention_module_init_param_t init_param = {
.cbs = {
.create = {
.handle = gptimer_create_sleep_retention_link_cb,
.arg = (void *)timer
},
},
.depends = BIT(SLEEP_RETENTION_MODULE_CLOCK_SYSTEM)
};
if (sleep_retention_module_init(module, &init_param) != ESP_OK) {
// even though the sleep retention module init failed, RMT driver should still work, so just warning here
ESP_LOGW(TAG, "init sleep retention failed on TimerGroup%d Timer%d, power domain may be turned off during sleep", group->group_id, timer_id);
}
#endif // GPTIMER_USE_RETENTION_LINK
return ESP_OK;
}
@@ -61,6 +104,15 @@ static void gptimer_unregister_from_group(gptimer_t *timer)
portENTER_CRITICAL(&group->spinlock);
group->timers[timer_id] = NULL;
portEXIT_CRITICAL(&group->spinlock);
#if GPTIMER_USE_RETENTION_LINK
sleep_retention_module_t module = tg_timer_reg_retention_info[group->group_id][timer_id].module;
if (sleep_retention_get_created_modules() & BIT(module)) {
sleep_retention_module_free(module);
}
sleep_retention_module_deinit(module);
#endif
// timer has a reference on group, release it now
gptimer_release_group_handle(group);
}
@@ -108,7 +160,7 @@ esp_err_t gptimer_new_timer(const gptimer_config_t *config, gptimer_handle_t *re
#if GPTIMER_USE_RETENTION_LINK
if (config->flags.backup_before_sleep != 0) {
gptimer_create_retention_module(group);
gptimer_create_retention_module(timer);
}
#endif // GPTIMER_USE_RETENTION_LINK

View File

@@ -20,35 +20,6 @@ typedef struct gptimer_platform_t {
// gptimer driver platform, it's always a singleton
static gptimer_platform_t s_platform;
#if GPTIMER_USE_RETENTION_LINK
static esp_err_t gptimer_create_sleep_retention_link_cb(void *arg)
{
gptimer_group_t *group = (gptimer_group_t *)arg;
int group_id = group->group_id;
sleep_retention_module_t module = group->sleep_retention_module;
esp_err_t err = sleep_retention_entries_create(tg_timer_reg_retention_info[group_id].regdma_entry_array,
tg_timer_reg_retention_info[group_id].array_size,
REGDMA_LINK_PRI_GPTIMER, module);
ESP_RETURN_ON_ERROR(err, TAG, "create retention link failed");
return ESP_OK;
}
void gptimer_create_retention_module(gptimer_group_t *group)
{
sleep_retention_module_t module = group->sleep_retention_module;
_lock_acquire(&s_platform.mutex);
if (group->retention_link_created == false) {
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 module for group %d retention, power domain can't turn off", group->group_id);
} else {
group->retention_link_created = true;
}
}
_lock_release(&s_platform.mutex);
}
#endif // GPTIMER_USE_RETENTION_LINK
gptimer_group_t *gptimer_acquire_group_handle(int group_id)
{
bool new_group = false;
@@ -84,24 +55,6 @@ gptimer_group_t *gptimer_acquire_group_handle(int group_id)
timer_ll_reset_register(group_id);
}
}
#if GPTIMER_USE_RETENTION_LINK
sleep_retention_module_t module = TIMER_LL_SLEEP_RETENTION_MODULE_ID(group_id);
sleep_retention_module_init_param_t init_param = {
.cbs = {
.create = {
.handle = gptimer_create_sleep_retention_link_cb,
.arg = group
},
},
.depends = BIT(SLEEP_RETENTION_MODULE_CLOCK_SYSTEM)
};
if (sleep_retention_module_init(module, &init_param) == ESP_OK) {
group->sleep_retention_module = module;
} else {
// even though the sleep retention module init failed, RMT driver should still work, so just warning here
ESP_LOGW(TAG, "init sleep retention failed %d, power domain may be turned off during sleep", group_id);
}
#endif // GPTIMER_USE_RETENTION_LINK
ESP_LOGD(TAG, "new group (%d) @%p", group_id, group);
}
@@ -129,14 +82,6 @@ void gptimer_release_group_handle(gptimer_group_t *group)
timer_ll_enable_bus_clock(group_id, false);
}
}
#if GPTIMER_USE_RETENTION_LINK
if (group->sleep_retention_module) {
if (group->retention_link_created) {
sleep_retention_module_free(group->sleep_retention_module);
}
sleep_retention_module_deinit(group->sleep_retention_module);
}
#endif
free(group);
ESP_LOGD(TAG, "del group (%d)", group_id);
}

View File

@@ -59,10 +59,6 @@ typedef struct gptimer_group_t {
int group_id;
portMUX_TYPE spinlock; // to protect per-group register level concurrent access
gptimer_t *timers[SOC_TIMER_GROUP_TIMERS_PER_GROUP];
#if GPTIMER_USE_RETENTION_LINK
sleep_retention_module_t sleep_retention_module; // sleep retention module
bool retention_link_created; // mark if the retention link is created
#endif
} gptimer_group_t;
typedef enum {
@@ -102,7 +98,6 @@ struct gptimer_t {
gptimer_group_t *gptimer_acquire_group_handle(int group_id);
void gptimer_release_group_handle(gptimer_group_t *group);
esp_err_t gptimer_select_periph_clock(gptimer_t *timer, gptimer_clock_source_t src_clk, uint32_t resolution_hz);
void gptimer_create_retention_module(gptimer_group_t *group);
#ifdef __cplusplus
}