mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-03 03:31:41 +03:00
feat(gptimer): use RCC atomic block to enable/reset peripheral
This commit is contained in:
@@ -32,6 +32,12 @@
|
||||
|
||||
static const char *TAG = "gptimer";
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32P4
|
||||
#define GPTIMER_CLOCK_SRC_ATOMIC() PERIPH_RCC_ATOMIC()
|
||||
#else
|
||||
#define GPTIMER_CLOCK_SRC_ATOMIC()
|
||||
#endif
|
||||
|
||||
typedef struct gptimer_platform_t {
|
||||
_lock_t mutex; // platform level mutex lock
|
||||
gptimer_group_t *groups[SOC_TIMER_GROUPS]; // timer group pool
|
||||
@@ -163,8 +169,13 @@ esp_err_t gptimer_del_timer(gptimer_handle_t timer)
|
||||
gptimer_clock_source_t clk_src = timer->clk_src;
|
||||
int group_id = group->group_id;
|
||||
int timer_id = timer->timer_id;
|
||||
timer_hal_context_t *hal = &timer->hal;
|
||||
ESP_LOGD(TAG, "del timer (%d,%d)", group_id, timer_id);
|
||||
timer_hal_deinit(&timer->hal);
|
||||
// disable the source clock
|
||||
GPTIMER_CLOCK_SRC_ATOMIC() {
|
||||
timer_ll_enable_clock(hal->dev, hal->timer_id, false);
|
||||
}
|
||||
timer_hal_deinit(hal);
|
||||
// recycle memory resource
|
||||
ESP_RETURN_ON_ERROR(gptimer_destroy(timer), TAG, "destroy gptimer failed");
|
||||
|
||||
@@ -382,8 +393,6 @@ static gptimer_group_t *gptimer_acquire_group_handle(int group_id)
|
||||
// initialize timer group members
|
||||
group->group_id = group_id;
|
||||
group->spinlock = (portMUX_TYPE)portMUX_INITIALIZER_UNLOCKED;
|
||||
// enable APB access timer registers
|
||||
periph_module_enable(timer_group_periph_signals.groups[group_id].module);
|
||||
}
|
||||
} else {
|
||||
group = s_platform.groups[group_id];
|
||||
@@ -395,6 +404,15 @@ static gptimer_group_t *gptimer_acquire_group_handle(int group_id)
|
||||
_lock_release(&s_platform.mutex);
|
||||
|
||||
if (new_group) {
|
||||
// !!! HARDWARE SHARED RESOURCE !!!
|
||||
// the gptimer and watchdog reside in the same the timer group
|
||||
// we need to increase/decrease the reference count before enable/disable/reset the peripheral
|
||||
PERIPH_RCC_ACQUIRE_ATOMIC(timer_group_periph_signals.groups[group_id].module, ref_count) {
|
||||
if (ref_count == 0) {
|
||||
timer_ll_enable_bus_clock(group_id, true);
|
||||
timer_ll_reset_register(group_id);
|
||||
}
|
||||
}
|
||||
ESP_LOGD(TAG, "new group (%d) @%p", group_id, group);
|
||||
}
|
||||
|
||||
@@ -412,11 +430,16 @@ static void gptimer_release_group_handle(gptimer_group_t *group)
|
||||
assert(s_platform.groups[group_id]);
|
||||
do_deinitialize = true;
|
||||
s_platform.groups[group_id] = NULL;
|
||||
periph_module_disable(timer_group_periph_signals.groups[group_id].module);
|
||||
}
|
||||
_lock_release(&s_platform.mutex);
|
||||
|
||||
if (do_deinitialize) {
|
||||
// disable bus clock for the timer group
|
||||
PERIPH_RCC_RELEASE_ATOMIC(timer_group_periph_signals.groups[group_id].module, ref_count) {
|
||||
if (ref_count == 0) {
|
||||
timer_ll_enable_bus_clock(group_id, false);
|
||||
}
|
||||
}
|
||||
free(group);
|
||||
ESP_LOGD(TAG, "del group (%d)", group_id);
|
||||
}
|
||||
@@ -476,9 +499,15 @@ static esp_err_t gptimer_select_periph_clock(gptimer_t *timer, gptimer_clock_sou
|
||||
}
|
||||
#endif // CONFIG_PM_ENABLE
|
||||
|
||||
timer_ll_set_clock_source(timer->hal.dev, timer_id, src_clk);
|
||||
// !!! HARDWARE SHARED RESOURCE !!!
|
||||
// on some ESP chip, different peripheral's clock source setting are mixed in the same register
|
||||
// so we need to make this done in an atomic way
|
||||
GPTIMER_CLOCK_SRC_ATOMIC() {
|
||||
timer_ll_set_clock_source(timer->hal.dev, timer_id, src_clk);
|
||||
timer_ll_enable_clock(timer->hal.dev, timer_id, true);
|
||||
}
|
||||
timer->clk_src = src_clk;
|
||||
unsigned int prescale = counter_src_hz / resolution_hz; // potential resolution loss here
|
||||
uint32_t prescale = counter_src_hz / resolution_hz; // potential resolution loss here
|
||||
timer_ll_set_clock_prescale(timer->hal.dev, timer_id, prescale);
|
||||
timer->resolution_hz = counter_src_hz / prescale; // this is the real resolution
|
||||
if (timer->resolution_hz != resolution_hz) {
|
||||
|
||||
Reference in New Issue
Block a user