diff --git a/components/esp32/esp_timer_esp32.c b/components/esp32/esp_timer_esp32.c index 37981a2e4..68b84f561 100644 --- a/components/esp32/esp_timer_esp32.c +++ b/components/esp32/esp_timer_esp32.c @@ -211,7 +211,7 @@ uint64_t IRAM_ATTR esp_timer_impl_get_time(void) void IRAM_ATTR esp_timer_impl_set_alarm(uint64_t timestamp) { - portENTER_CRITICAL(&s_time_update_lock); + portENTER_CRITICAL_SAFE(&s_time_update_lock); // Use calculated alarm value if it is less than ALARM_OVERFLOW_VAL. // Note that if by the time we update ALARM_REG, COUNT_REG value is higher, // interrupt will not happen for another ALARM_OVERFLOW_VAL timer ticks, @@ -237,7 +237,7 @@ void IRAM_ATTR esp_timer_impl_set_alarm(uint64_t timestamp) } REG_WRITE(FRC_TIMER_ALARM_REG(1), alarm_reg_val); } while (REG_READ(FRC_TIMER_ALARM_REG(1)) <= REG_READ(FRC_TIMER_COUNT_REG(1))); - portEXIT_CRITICAL(&s_time_update_lock); + portEXIT_CRITICAL_SAFE(&s_time_update_lock); } static void IRAM_ATTR timer_alarm_isr(void *arg) diff --git a/components/esp32/test/test_esp_timer.c b/components/esp32/test/test_esp_timer.c index 4512f42b8..e50a2f177 100644 --- a/components/esp32/test/test_esp_timer.c +++ b/components/esp32/test/test_esp_timer.c @@ -11,6 +11,7 @@ #include "freertos/semphr.h" #include "test_utils.h" #include "esp_private/esp_timer_impl.h" +#include "esp_freertos_hooks.h" #ifdef CONFIG_ESP_TIMER_PROFILING #define WITH_PROFILING 1 @@ -650,6 +651,43 @@ TEST_CASE("after esp_timer_impl_advance, timers run when expected", "[esp_timer] ref_clock_deinit(); } +static esp_timer_handle_t timer1; +static SemaphoreHandle_t sem; +static void IRAM_ATTR test_tick_hook(void) +{ + static int i; + const int iterations = 16; + + if (++i <= iterations) { + if (i & 0x1) { + TEST_ESP_OK(esp_timer_start_once(timer1, 5000)); + } else { + TEST_ESP_OK(esp_timer_stop(timer1)); + } + } else { + xSemaphoreGiveFromISR(sem, 0); + } +} + +TEST_CASE("Can start/stop timer from ISR context", "[esp_timer]") +{ + void timer_func(void* arg) + { + printf("timer cb\n"); + } + + esp_timer_create_args_t create_args = { + .callback = &timer_func, + }; + TEST_ESP_OK(esp_timer_create(&create_args, &timer1)); + sem = xSemaphoreCreateBinary(); + esp_register_freertos_tick_hook(test_tick_hook); + TEST_ASSERT(xSemaphoreTake(sem, portMAX_DELAY)); + esp_deregister_freertos_tick_hook(test_tick_hook); + TEST_ESP_OK( esp_timer_delete(timer1) ); + vSemaphoreDelete(sem); +} + #if !defined(CONFIG_FREERTOS_UNICORE) && defined(CONFIG_ESP32_DPORT_WORKAROUND) #include "soc/dport_reg.h" diff --git a/components/esp32s2beta/esp_timer_esp32s2beta.c b/components/esp32s2beta/esp_timer_esp32s2beta.c index ff01cfe70..82be232e7 100644 --- a/components/esp32s2beta/esp_timer_esp32s2beta.c +++ b/components/esp32s2beta/esp_timer_esp32s2beta.c @@ -222,7 +222,7 @@ uint64_t IRAM_ATTR esp_timer_impl_get_time(void) void IRAM_ATTR esp_timer_impl_set_alarm(uint64_t timestamp) { - portENTER_CRITICAL(&s_time_update_lock); + portENTER_CRITICAL_SAFE(&s_time_update_lock); // Alarm time relative to the moment when counter was 0 uint64_t time_after_timebase_us = timestamp - s_time_base_us; // Adjust current time if overflow has happened @@ -252,7 +252,7 @@ void IRAM_ATTR esp_timer_impl_set_alarm(uint64_t timestamp) alarm_reg_val = (uint32_t) compare_val; } REG_WRITE(FRC_TIMER_ALARM_REG(1), alarm_reg_val); - portEXIT_CRITICAL(&s_time_update_lock); + portEXIT_CRITICAL_SAFE(&s_time_update_lock); } static void IRAM_ATTR timer_alarm_isr(void *arg) diff --git a/components/esp_common/src/esp_timer.c b/components/esp_common/src/esp_timer.c index 8a343e34d..b24976b9c 100644 --- a/components/esp_common/src/esp_timer.c +++ b/components/esp_common/src/esp_timer.c @@ -264,12 +264,12 @@ static IRAM_ATTR bool timer_armed(esp_timer_handle_t timer) static IRAM_ATTR void timer_list_lock(void) { - portENTER_CRITICAL(&s_timer_lock); + portENTER_CRITICAL_SAFE(&s_timer_lock); } static IRAM_ATTR void timer_list_unlock(void) { - portEXIT_CRITICAL(&s_timer_lock); + portEXIT_CRITICAL_SAFE(&s_timer_lock); } static void timer_process_alarm(esp_timer_dispatch_t dispatch_method)