From 32ec2750e051a27825ce2fb819984161bc4f34d2 Mon Sep 17 00:00:00 2001 From: KonstantinKondrashov Date: Tue, 10 Dec 2019 04:25:38 +0800 Subject: [PATCH 1/2] esp_timer: Fix set_alarm. Case when timestamp < now_time arg1 = MAX(int64_t arg1, uint64_t arg2) gave the wrong result, if arg1 < 0, it was presented as a larger value. And ALARM_REG = (uin32_t)arg1. This leads to an infinite loop. Fixed: both args are int64_t. Closes: WIFI-1511 --- components/esp32/esp_timer_esp32.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/esp32/esp_timer_esp32.c b/components/esp32/esp_timer_esp32.c index 7f26bb47e..892588973 100644 --- a/components/esp32/esp_timer_esp32.c +++ b/components/esp32/esp_timer_esp32.c @@ -216,7 +216,7 @@ void IRAM_ATTR esp_timer_impl_set_alarm(uint64_t timestamp) // 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, // so need to check if alarm value is too close in the future (e.g. <2 us away). - const uint32_t offset = s_timer_ticks_per_us * 2; + const int32_t offset = s_timer_ticks_per_us * 2; do { // Adjust current time if overflow has happened if (timer_overflow_happened()) { @@ -224,7 +224,7 @@ void IRAM_ATTR esp_timer_impl_set_alarm(uint64_t timestamp) s_time_base_us += s_timer_us_per_overflow; } s_mask_overflow = false; - uint64_t cur_count = REG_READ(FRC_TIMER_COUNT_REG(1)); + int64_t cur_count = REG_READ(FRC_TIMER_COUNT_REG(1)); // Alarm time relative to the moment when counter was 0 int64_t time_after_timebase_us = (int64_t)timestamp - s_time_base_us; // Calculate desired timer compare value (may exceed 2^32-1) From d071cd11c83b106bec9fda5ea0f5d8b1a6e9dbb9 Mon Sep 17 00:00:00 2001 From: KonstantinKondrashov Date: Wed, 11 Dec 2019 21:57:10 +0800 Subject: [PATCH 2/2] esp_timer: Add Test case when set_alarm needs set timer < now_time --- components/esp32/test/test_esp_timer.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/components/esp32/test/test_esp_timer.c b/components/esp32/test/test_esp_timer.c index 2001d7b5e..ae9eb9025 100644 --- a/components/esp32/test/test_esp_timer.c +++ b/components/esp32/test/test_esp_timer.c @@ -4,6 +4,7 @@ #include #include #include "unity.h" +#include "soc/frc_timer_reg.h" #include "esp_timer.h" #include "esp_heap_caps.h" #include "freertos/FreeRTOS.h" @@ -779,3 +780,21 @@ TEST_CASE("esp_timer_impl_set_alarm and using start_once do not lead that the Sy } #endif // !defined(CONFIG_FREERTOS_UNICORE) && defined(CONFIG_ESP32_DPORT_WORKAROUND) + +TEST_CASE("Test case when esp_timer_impl_set_alarm needs set timer < now_time", "[esp_timer]") +{ + REG_WRITE(FRC_TIMER_LOAD_REG(1), 0); + esp_timer_impl_advance(50331648); // 0xefffffff/80 = 50331647 + + ets_delay_us(2); + + portDISABLE_INTERRUPTS(); + esp_timer_impl_set_alarm(50331647); + uint32_t alarm_reg = REG_READ(FRC_TIMER_ALARM_REG(1)); + uint32_t count_reg = REG_READ(FRC_TIMER_COUNT_REG(1)); + portENABLE_INTERRUPTS(); + + const uint32_t offset = 80 * 2; // s_timer_ticks_per_us + printf("alarm_reg = 0x%x, count_reg 0x%x\n", alarm_reg, count_reg); + TEST_ASSERT(alarm_reg <= (count_reg + offset)); +}