From 3ac8063bb8fd25c82c05405a9efc92e78ea0d659 Mon Sep 17 00:00:00 2001 From: morris Date: Fri, 17 Dec 2021 10:02:33 +0800 Subject: [PATCH] timer: stop alarm if alarm value doesn't change in ISR handler Alarm will be disabled by hardware when alarm event happend. In the ISR, if auto-reload is enabled, we should re-enable the alarm. If the alarm target value is changed in user's callback, the alarm will be reenabled as well. Closes https://github.com/espressif/esp-idf/issues/7001 Closes https://github.com/espressif/esp-idf/issues/8095 --- components/driver/timer.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/components/driver/timer.c b/components/driver/timer.c index 55705d346d2..b9cc2e1a81a 100644 --- a/components/driver/timer.c +++ b/components/driver/timer.c @@ -212,12 +212,16 @@ static void IRAM_ATTR timer_isr_default(void *arg) timer_hal_context_t *hal = &timer_obj->hal; TIMER_ENTER_CRITICAL(&timer_spinlock[timer_obj->timer_isr_fun.isr_timer_group]); uint32_t intr_status = timer_ll_get_intr_status(hal->dev); + uint64_t old_alarm_value = timer_obj->alarm_value; if (intr_status & TIMER_LL_EVENT_ALARM(timer_id)) { - //Clear intrrupt status + // Clear interrupt status timer_ll_clear_intr_status(hal->dev, TIMER_LL_EVENT_ALARM(timer_id)); + // call user registered callback is_awoken = timer_obj->timer_isr_fun.fn(timer_obj->timer_isr_fun.args); - //If the timer is set to auto reload, we need enable it again, so it is triggered the next time - timer_ll_enable_alarm(hal->dev, timer_id, timer_obj->auto_reload_en); + // reenable alarm if required + uint64_t new_alarm_value = timer_obj->alarm_value; + bool reenable_alarm = (new_alarm_value != old_alarm_value) || timer_obj->auto_reload_en; + timer_ll_enable_alarm(hal->dev, timer_id, reenable_alarm); } TIMER_EXIT_CRITICAL(&timer_spinlock[timer_obj->timer_isr_fun.isr_timer_group]);