|
|
@@ -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) {
|