test_esp_timer.cpp 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. // Copyright 2020 Espressif Systems (Shanghai) PTE LTD
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. #ifdef __cpp_exceptions
  15. #include "unity.h"
  16. #include "unity_cxx.hpp"
  17. #include <limits>
  18. #include <stdio.h>
  19. #include <iostream>
  20. #include "test_utils.h" // ref clock
  21. #include "freertos/FreeRTOS.h"
  22. #include "freertos/task.h"
  23. #include "freertos/semphr.h"
  24. #include "esp_timer_cxx.hpp"
  25. #include "esp_exception.hpp"
  26. using namespace std;
  27. using namespace idf;
  28. using namespace idf::esp_timer;
  29. struct RefClock {
  30. RefClock()
  31. {
  32. ref_clock_init();
  33. };
  34. ~RefClock()
  35. {
  36. ref_clock_deinit();
  37. }
  38. };
  39. TEST_CASE("ESPTimer null function", "[ESPTimer]")
  40. {
  41. TEST_THROW(ESPTimer(nullptr), ESPException);
  42. }
  43. TEST_CASE("ESPTimer empty std::function", "[ESPTimer]")
  44. {
  45. function<void()> nothing;
  46. TEST_THROW(ESPTimer(nothing, "test"), ESPException);
  47. }
  48. TEST_CASE("ESPTimer starting twice throws", "[ESPTimer]")
  49. {
  50. function<void()> timer_cb = [&]() { };
  51. ESPTimer timer(timer_cb);
  52. timer.start(chrono::microseconds(5000));
  53. TEST_THROW(timer.start(chrono::microseconds(5000)), ESPException);
  54. }
  55. TEST_CASE("ESPTimer periodically starting twice throws", "[ESPTimer]")
  56. {
  57. function<void()> timer_cb = [&]() { };
  58. ESPTimer timer(timer_cb);
  59. timer.start_periodic(chrono::microseconds(5000));
  60. TEST_THROW(timer.start_periodic(chrono::microseconds(5000)), ESPException);
  61. }
  62. TEST_CASE("ESPTimer stopping non-started timer throws", "[ESPTimer]")
  63. {
  64. function<void()> timer_cb = [&]() { };
  65. ESPTimer timer(timer_cb);
  66. TEST_THROW(timer.stop(), ESPException);
  67. }
  68. TEST_CASE("ESPTimer calls callback", "[ESPTimer]")
  69. {
  70. bool called = false;
  71. function<void()> timer_cb = [&]() {
  72. called = true;
  73. };
  74. ESPTimer timer(timer_cb);
  75. timer.start(chrono::microseconds(5000));
  76. vTaskDelay(10 / portTICK_PERIOD_MS);
  77. TEST_ASSERT(called);
  78. }
  79. TEST_CASE("ESPTimer periodically calls callback", "[ESPTimer]")
  80. {
  81. size_t called = 0;
  82. function<void()> timer_cb = [&]() {
  83. called++;
  84. };
  85. ESPTimer timer(timer_cb);
  86. timer.start_periodic(chrono::microseconds(2000));
  87. vTaskDelay(10 / portTICK_PERIOD_MS);
  88. TEST_ASSERT(called >= 4u);
  89. }
  90. TEST_CASE("ESPTimer produces correct delay", "[ESPTimer]")
  91. {
  92. int64_t t_end;
  93. RefClock ref_clock;
  94. function<void()> timer_cb = [&t_end]() {
  95. t_end = ref_clock_get();
  96. };
  97. ESPTimer timer(timer_cb, "timer1");
  98. const int delays_ms[] = {20, 100, 200, 250};
  99. const size_t delays_count = sizeof(delays_ms)/sizeof(delays_ms[0]);
  100. for (size_t i = 0; i < delays_count; ++i) {
  101. t_end = 0;
  102. int64_t t_start = ref_clock_get();
  103. timer.start(chrono::microseconds(delays_ms[i] * 1000));
  104. vTaskDelay(delays_ms[i] * 2 / portTICK_PERIOD_MS);
  105. TEST_ASSERT(t_end != 0);
  106. int32_t ms_diff = (t_end - t_start) / 1000;
  107. printf("%d %d\n", delays_ms[i], ms_diff);
  108. TEST_ASSERT_INT32_WITHIN(portTICK_PERIOD_MS, delays_ms[i], ms_diff);
  109. }
  110. }
  111. TEST_CASE("ESPtimer produces correct periodic delays", "[ESPTimer]")
  112. {
  113. const size_t NUM_INTERVALS = 3u;
  114. size_t cur_interval = 0;
  115. int intervals[NUM_INTERVALS];
  116. int64_t t_start;
  117. SemaphoreHandle_t done;
  118. const int DELAY_MS = 100;
  119. function<void()> timer_cb = [&]() {
  120. int64_t t_end = ref_clock_get();
  121. int32_t ms_diff = (t_end - t_start) / 1000;
  122. printf("timer #%d %dms\n", cur_interval, ms_diff);
  123. if (cur_interval < NUM_INTERVALS) {
  124. intervals[cur_interval++] = ms_diff;
  125. }
  126. // Deliberately make timer handler run longer.
  127. // We check that this doesn't affect the result.
  128. esp_rom_delay_us(10*1000);
  129. if (cur_interval == NUM_INTERVALS) {
  130. printf("done\n");
  131. xSemaphoreGive(done);
  132. }
  133. };
  134. ESPTimer timer(timer_cb, "timer1");
  135. RefClock ref_clock;
  136. t_start = ref_clock_get();
  137. done = xSemaphoreCreateBinary();
  138. timer.start_periodic(chrono::microseconds(DELAY_MS * 1000));
  139. TEST_ASSERT(xSemaphoreTake(done, DELAY_MS * NUM_INTERVALS * 2));
  140. timer.stop();
  141. TEST_ASSERT_EQUAL_UINT32(NUM_INTERVALS, cur_interval);
  142. for (size_t i = 0; i < NUM_INTERVALS; ++i) {
  143. TEST_ASSERT_INT32_WITHIN(portTICK_PERIOD_MS, (i + 1) * DELAY_MS, intervals[i]);
  144. }
  145. TEST_ESP_OK(esp_timer_dump(stdout));
  146. vSemaphoreDelete(done);
  147. #undef NUM_INTERVALS
  148. }
  149. #endif // __cpp_exceptions