]> granicus.if.org Git - esp-idf/commitdiff
esp_timer: reduce overflow value in unit tests
authorIvan Grokhotkov <ivan@espressif.com>
Wed, 23 May 2018 14:39:49 +0000 (22:39 +0800)
committerbot <bot@espressif.com>
Mon, 11 Jun 2018 02:37:19 +0000 (02:37 +0000)
This allows testing for race conditions which occur near timer
overflow point more effectively.

components/esp32/Makefile.projbuild
components/esp32/esp_timer_esp32.c
components/esp32/test/test_esp_timer.c

index 63318dd66bb3ee8a4a71ca686fb0159b59ecd54f..8f85c93961a3f852b984b65705c7918bb295feac 100644 (file)
@@ -38,3 +38,7 @@ CFLAGS+=-mfix-esp32-psram-cache-issue
 CXXFLAGS+=-mfix-esp32-psram-cache-issue
 endif
 
+# Enable dynamic esp_timer overflow value if building unit tests 
+ifneq ("$(TEST_COMPONENTS_LIST)","")
+CPPFLAGS += -DESP_TIMER_DYNAMIC_OVERFLOW_VAL
+endif
index 83d27b950e682675c013e35d7ca105d2ec2e7ca5..3d63cf2bd85fc2a372b1469d438339a4de5e4cd9 100644 (file)
  * ISR happens follow set_alarm, so change the ALARM_OVERFLOW_VAL to resolve this problem.
  * Set it to 0xefffffffUL. The remain 0x10000000UL(about 3 second) is enough to handle ISR.
  */
-#define ALARM_OVERFLOW_VAL  0xefffffffUL
+#define DEFAULT_ALARM_OVERFLOW_VAL 0xefffffffUL
+
+/* Provision to set lower overflow value for unit testing. Lowering the
+ * overflow value helps check for race conditions which occur near overflow
+ * moment.
+ */
+#ifndef ESP_TIMER_DYNAMIC_OVERFLOW_VAL
+#define ALARM_OVERFLOW_VAL  DEFAULT_ALARM_OVERFLOW_VAL
+#else
+static uint32_t s_alarm_overflow_val = DEFAULT_ALARM_OVERFLOW_VAL;
+#define ALARM_OVERFLOW_VAL (s_alarm_overflow_val)
+#endif
 
 static const char* TAG = "esp_timer_impl";
 
@@ -379,3 +390,17 @@ uint64_t IRAM_ATTR esp_timer_impl_get_min_period_us()
 {
     return 50;
 }
+
+#ifdef ESP_TIMER_DYNAMIC_OVERFLOW_VAL
+uint32_t esp_timer_impl_get_overflow_val()
+{
+    return s_alarm_overflow_val;
+}
+
+void esp_timer_impl_set_overflow_val(uint32_t overflow_val)
+{
+    s_alarm_overflow_val = overflow_val;
+    /* update alarm value */
+    esp_timer_impl_update_apb_freq(esp_clk_apb_freq() / 1000000);
+}
+#endif // ESP_TIMER_DYNAMIC_OVERFLOW_VAL
index da8d8951cf42d3680fc0210aaf79a2831b455d75..40b7be4e95c88b9beaaff2ed3dc18c0cc87f048b 100644 (file)
@@ -2,6 +2,7 @@
 #include <stdlib.h>
 #include <time.h>
 #include <sys/time.h>
+#include <sys/param.h>
 #include "unity.h"
 #include "esp_timer.h"
 #include "esp_heap_caps.h"
 #define WITH_PROFILING 1
 #endif
 
+extern uint32_t esp_timer_impl_get_overflow_val();
+extern void esp_timer_impl_set_overflow_val(uint32_t overflow_val);
+
+static uint32_t s_old_overflow_val;
+
+static void setup_overflow()
+{
+    s_old_overflow_val = esp_timer_impl_get_overflow_val();
+    esp_timer_impl_set_overflow_val(0x7fffff); /* overflow every ~0.1 sec */}
+
+static void teardown_overflow()
+{
+    esp_timer_impl_set_overflow_val(s_old_overflow_val);
+}
 
 TEST_CASE("esp_timer orders timers correctly", "[esp_timer]")
 {
@@ -27,6 +42,7 @@ TEST_CASE("esp_timer orders timers correctly", "[esp_timer]")
     const size_t num_timers = sizeof(timeouts)/sizeof(timeouts[0]);
     esp_timer_handle_t handles[num_timers];
     char* names[num_timers];
+    setup_overflow();
     for (size_t i = 0; i < num_timers; ++i) {
         asprintf(&names[i], "timer%d", i);
         esp_timer_create_args_t args = {
@@ -36,6 +52,7 @@ TEST_CASE("esp_timer orders timers correctly", "[esp_timer]")
         TEST_ESP_OK(esp_timer_create(&args, &handles[i]));
         TEST_ESP_OK(esp_timer_start_once(handles[i], timeouts[i] * 100));
     }
+    teardown_overflow();
     char* stream_str[1024];
     FILE* stream = fmemopen(stream_str, sizeof(stream_str), "r+");
     TEST_ESP_OK(esp_timer_dump(stream));
@@ -90,6 +107,7 @@ TEST_CASE("esp_timer produces correct delay", "[esp_timer]")
     const size_t delays_count = sizeof(delays_ms)/sizeof(delays_ms[0]);
 
     ref_clock_init();
+    setup_overflow();
     for (size_t i = 0; i < delays_count; ++i) {
         t_end = 0;
         int64_t t_start = ref_clock_get();
@@ -103,6 +121,7 @@ TEST_CASE("esp_timer produces correct delay", "[esp_timer]")
 
         TEST_ASSERT_INT32_WITHIN(portTICK_PERIOD_MS, delays_ms[i], ms_diff);
     }
+    teardown_overflow();
     ref_clock_deinit();
 
     TEST_ESP_OK( esp_timer_dump(stdout) );
@@ -150,6 +169,7 @@ TEST_CASE("periodic esp_timer produces correct delays", "[esp_timer]")
     };
     TEST_ESP_OK(esp_timer_create(&create_args, &timer1));
     ref_clock_init();
+    setup_overflow();
     args.timer = timer1;
     args.t_start = ref_clock_get();
     args.done = xSemaphoreCreateBinary();
@@ -161,6 +181,7 @@ TEST_CASE("periodic esp_timer produces correct delays", "[esp_timer]")
     for (size_t i = 0; i < NUM_INTERVALS; ++i) {
         TEST_ASSERT_INT32_WITHIN(portTICK_PERIOD_MS, (i + 1) * delay_ms, args.intervals[i]);
     }
+    teardown_overflow();
     ref_clock_deinit();
     TEST_ESP_OK( esp_timer_dump(stdout) );
 
@@ -317,6 +338,7 @@ TEST_CASE("esp_timer for very short intervals", "[esp_timer]")
     esp_timer_handle_t timer1, timer2;
     ESP_ERROR_CHECK( esp_timer_create(&timer_args, &timer1) );
     ESP_ERROR_CHECK( esp_timer_create(&timer_args, &timer2) );
+    setup_overflow();
     const int timeout_ms = 10;
     for (int timeout_delta_us = -150; timeout_delta_us < 150; timeout_delta_us++) {
         printf("delta=%d", timeout_delta_us);
@@ -329,6 +351,7 @@ TEST_CASE("esp_timer for very short intervals", "[esp_timer]")
         TEST_ESP_ERR(ESP_ERR_INVALID_STATE, esp_timer_stop(timer2));
     }
 
+    teardown_overflow();
     vSemaphoreDelete(semaphore);
 }