]> granicus.if.org Git - esp-idf/commitdiff
esp_timer: fix esp_timer_impl_advance not triggering expired timers
authorIvan Grokhotkov <ivan@espressif.com>
Thu, 3 May 2018 16:57:24 +0000 (00:57 +0800)
committerIvan Grokhotkov <ivan@espressif.com>
Wed, 9 May 2018 14:52:41 +0000 (22:52 +0800)
components/esp32/esp_timer_esp32.c
components/esp32/test/test_esp_timer.c

index 1bc4885756545724be2cd9e04649d366947098cb..4f1200515acec036422fbcdef1996167d5dd3207 100644 (file)
@@ -317,9 +317,13 @@ void esp_timer_impl_advance(int64_t time_us)
 
     portENTER_CRITICAL(&s_time_update_lock);
     uint64_t count = REG_READ(FRC_TIMER_COUNT_REG(1));
+    /* Trigger an ISR to handle past alarms and set new one.
+     * ISR handler will run once we exit the critical section.
+     */
+    REG_WRITE(FRC_TIMER_ALARM_REG(1), 0);
     REG_WRITE(FRC_TIMER_LOAD_REG(1), 0);
     s_time_base_us += count / s_timer_ticks_per_us + time_us;
-    esp_timer_impl_set_alarm(esp_timer_get_next_alarm());
+    s_overflow_happened = false;
     portEXIT_CRITICAL(&s_time_update_lock);
 }
 
index 4007528bd1ddc6f12a6787f761e10d7e7588755a..da8d8951cf42d3680fc0210aaf79a2831b455d75 100644 (file)
@@ -9,6 +9,7 @@
 #include "freertos/task.h"
 #include "freertos/semphr.h"
 #include "test_utils.h"
+#include "../esp_timer_impl.h"
 
 #ifdef CONFIG_ESP_TIMER_PROFILING
 #define WITH_PROFILING 1
@@ -418,3 +419,62 @@ TEST_CASE("Can delete timer from callback", "[esp_timer]")
 
     vSemaphoreDelete(args.notify_from_timer_cb);
 }
+
+TEST_CASE("esp_timer_impl_advance moves time base correctly", "[esp_timer]")
+{
+    ref_clock_init();
+    int64_t t0 = esp_timer_get_time();
+    const int64_t diff_us = 1000000;
+    esp_timer_impl_advance(diff_us);
+    int64_t t1 = esp_timer_get_time();
+    int64_t t_delta = t1 - t0;
+    printf("diff_us=%lld t1-t0=%lld\n", diff_us, t_delta);
+    TEST_ASSERT_INT_WITHIN(1000, diff_us, (int) t_delta);
+    ref_clock_deinit();
+}
+
+
+TEST_CASE("after esp_timer_impl_advance, timers run when expected", "[esp_timer]")
+{
+    typedef struct {
+        int64_t cb_time;
+    } test_state_t;
+
+    void timer_func(void* varg) {
+        test_state_t* arg = (test_state_t*) varg;
+        arg->cb_time = ref_clock_get();
+    }
+
+    ref_clock_init();
+
+    test_state_t state = { 0 };
+
+    esp_timer_create_args_t timer_args = {
+            .callback = &timer_func,
+            .arg = &state
+    };
+    esp_timer_handle_t timer;
+    TEST_ESP_OK(esp_timer_create(&timer_args, &timer));
+
+    const int64_t interval = 10000;
+    const int64_t advance = 2000;
+
+    printf("test 1\n");
+    int64_t t_start = ref_clock_get();
+    esp_timer_start_once(timer, interval);
+    esp_timer_impl_advance(advance);
+    vTaskDelay(2 * interval / 1000 / portTICK_PERIOD_MS);
+
+    TEST_ASSERT_INT_WITHIN(portTICK_PERIOD_MS * 1000, interval - advance, state.cb_time - t_start);
+
+    printf("test 2\n");
+    state.cb_time = 0;
+    t_start = ref_clock_get();
+    esp_timer_start_once(timer, interval);
+    esp_timer_impl_advance(interval);
+    vTaskDelay(1);
+
+    TEST_ASSERT(state.cb_time > t_start);
+
+    ref_clock_deinit();
+}