esp_timer_esp32s2beta.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407
  1. // Copyright 2017 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. #include "esp_err.h"
  15. #include "esp_timer.h"
  16. #include "esp_system.h"
  17. #include "esp_task.h"
  18. #include "esp_attr.h"
  19. #include "esp_intr_alloc.h"
  20. #include "esp_log.h"
  21. #include "esp32s2beta/clk.h"
  22. #include "esp_private/esp_timer_impl.h"
  23. #include "soc/frc_timer_reg.h"
  24. #include "soc/rtc.h"
  25. #include "soc/periph_defs.h"
  26. #include "freertos/FreeRTOS.h"
  27. #include "freertos/task.h"
  28. #include "freertos/semphr.h"
  29. /**
  30. * @file esp_timer_esp32.c
  31. * @brief Implementation of chip-specific part of esp_timer
  32. *
  33. * This implementation uses FRC2 (legacy) timer of the ESP32. This timer is
  34. * a 32-bit up-counting timer, with a programmable compare value (called 'alarm'
  35. * hereafter). When the timer reaches compare value, interrupt is raised.
  36. * The timer can be configured to produce an edge or a level interrupt.
  37. *
  38. * In this implementation the timer is used for two purposes:
  39. * 1. To generate interrupts at certain moments — the upper layer of esp_timer
  40. * uses this to trigger callbacks of esp_timer objects.
  41. *
  42. * 2. To keep track of time relative to application start. This facility is
  43. * used both by the upper layer of esp_timer and by time functions, such as
  44. * gettimeofday.
  45. *
  46. * Whenever an esp_timer timer is armed (configured to fire once or
  47. * periodically), timer_insert function of the upper layer calls
  48. * esp_timer_impl_set_alarm to enable the interrupt at the required moment.
  49. * This implementation sets up the timer interrupt to fire at the earliest of
  50. * two moments:
  51. * a) the time requested by upper layer
  52. * b) the time when the timer count reaches 0xffffffff (i.e. is about to overflow)
  53. *
  54. * Whenever the interrupt fires and timer overflow is detected, interrupt hander
  55. * increments s_time_base_us variable, which is used for timekeeping.
  56. *
  57. * When the interrupt fires, the upper layer is notified, and it dispatches
  58. * the callbacks (if any timers have expired) and sets new alarm value (if any
  59. * timers are still active).
  60. *
  61. * At any point in time, esp_timer_impl_get_time will return the current timer
  62. * value (expressed in microseconds) plus s_time_base_us. To account for the
  63. * case when the timer counter has overflown, but the interrupt has not fired
  64. * yet (for example, because interupts are temporarily disabled),
  65. * esp_timer_impl_get_time will also check timer overflow flag, and will add
  66. * s_timer_us_per_overflow to the returned value.
  67. *
  68. */
  69. /* Timer is clocked from APB. To allow for integer scaling factor between ticks
  70. * and microseconds, divider 1 is used. 16 or 256 would not work for APB
  71. * frequencies such as 40 or 26 or 2 MHz.
  72. */
  73. #define TIMER_DIV 1
  74. #define TIMER_DIV_CFG FRC_TIMER_PRESCALER_1
  75. /* ALARM_OVERFLOW_VAL is used as timer alarm value when there are not timers
  76. * enabled which need to fire within the next timer overflow period. This alarm
  77. * is used to perform timekeeping (i.e. to track timer overflows).
  78. * Due to the 0xffffffff cannot recognize the real overflow or the scenario that
  79. * ISR happens follow set_alarm, so change the ALARM_OVERFLOW_VAL to resolve this problem.
  80. * Set it to 0xefffffffUL. The remain 0x10000000UL(about 3 second) is enough to handle ISR.
  81. */
  82. #define DEFAULT_ALARM_OVERFLOW_VAL 0xefffffffUL
  83. /* Provision to set lower overflow value for unit testing. Lowering the
  84. * overflow value helps check for race conditions which occur near overflow
  85. * moment.
  86. */
  87. #ifndef ESP_TIMER_DYNAMIC_OVERFLOW_VAL
  88. #define ALARM_OVERFLOW_VAL DEFAULT_ALARM_OVERFLOW_VAL
  89. #else
  90. static uint32_t s_alarm_overflow_val = DEFAULT_ALARM_OVERFLOW_VAL;
  91. #define ALARM_OVERFLOW_VAL (s_alarm_overflow_val)
  92. #endif
  93. static const char* TAG = "esp_timer_impl";
  94. // Interrupt handle returned by the interrupt allocator
  95. static intr_handle_t s_timer_interrupt_handle;
  96. // Function from the upper layer to be called when the interrupt happens.
  97. // Registered in esp_timer_impl_init.
  98. static intr_handler_t s_alarm_handler;
  99. // Time in microseconds from startup to the moment
  100. // when timer counter was last equal to 0. This variable is updated each time
  101. // when timer overflows, and when APB frequency switch is performed.
  102. static uint64_t s_time_base_us;
  103. // Number of timer ticks per microsecond. Calculated from APB frequency.
  104. static uint32_t s_timer_ticks_per_us;
  105. // Period between timer overflows, in microseconds.
  106. // Equal to 2^32 / s_timer_ticks_per_us.
  107. static uint32_t s_timer_us_per_overflow;
  108. // When frequency switch happens, timer counter is reset to 0, s_time_base_us
  109. // is updated, and alarm value is re-calculated based on the new APB frequency.
  110. // However because the frequency switch can happen before the final
  111. // interrupt handler is invoked, interrupt handler may see a different alarm
  112. // value than the one which caused an interrupt. This can cause interrupt handler
  113. // to consider that the interrupt has happened due to timer overflow, incrementing
  114. // s_time_base_us. To avoid this, frequency switch hook sets this flag if
  115. // it needs to set timer alarm value to ALARM_OVERFLOW_VAL. Interrupt handler
  116. // will not increment s_time_base_us if this flag is set.
  117. static bool s_mask_overflow;
  118. //The timer_overflow_happened read alarm register to tell if overflow happened.
  119. //However, there is a monent that overflow happens, and before ISR function called
  120. //alarm register is set to another value, then you call timer_overflow_happened,
  121. //it will return false.
  122. //So we store the overflow value when new alarm is to be set.
  123. static bool s_overflow_happened;
  124. #ifdef CONFIG_PM_DFS_USE_RTC_TIMER_REF
  125. // If DFS is enabled, upon the first frequency change this value is set to the
  126. // difference between esp_timer value and RTC timer value. On every subsequent
  127. // frequency change, s_time_base_us is adjusted to maintain the same difference
  128. // between esp_timer and RTC timer. (All mentioned values are in microseconds.)
  129. static uint64_t s_rtc_time_diff = 0;
  130. #endif
  131. // Spinlock used to protect access to static variables above and to the hardware
  132. // registers.
  133. portMUX_TYPE s_time_update_lock = portMUX_INITIALIZER_UNLOCKED;
  134. //Use FRC_TIMER_LOAD_VALUE(1) instead of UINT32_MAX, convenience to change FRC TIMER for future
  135. #define TIMER_IS_AFTER_OVERFLOW(a) (ALARM_OVERFLOW_VAL < (a) && (a) <= FRC_TIMER_LOAD_VALUE(1))
  136. // Check if timer overflow has happened (but was not handled by ISR yet)
  137. static inline bool IRAM_ATTR timer_overflow_happened(void)
  138. {
  139. if (s_overflow_happened) {
  140. return true;
  141. }
  142. return ((REG_READ(FRC_TIMER_CTRL_REG(1)) & FRC_TIMER_INT_STATUS) != 0 &&
  143. ((REG_READ(FRC_TIMER_ALARM_REG(1)) == ALARM_OVERFLOW_VAL && TIMER_IS_AFTER_OVERFLOW(REG_READ(FRC_TIMER_COUNT_REG(1))) && !s_mask_overflow) ||
  144. (!TIMER_IS_AFTER_OVERFLOW(REG_READ(FRC_TIMER_ALARM_REG(1))) && TIMER_IS_AFTER_OVERFLOW(REG_READ(FRC_TIMER_COUNT_REG(1))))));
  145. }
  146. static inline void IRAM_ATTR timer_count_reload(void)
  147. {
  148. //this function should be only called the real overflow happened. And the count cannot be very approach to 0xffffffff.
  149. assert(TIMER_IS_AFTER_OVERFLOW(REG_READ(FRC_TIMER_COUNT_REG(1))));
  150. /* Restart the timer count by current time count minus ALARM_OVERFLOW_VAL(0xefffffff), it may cause error, if current tick is near boundary.
  151. * But even if the error happen 100% per overflow(the distance of each real overflow is about 50 second),
  152. * the error is 0.0125us*N per 50s(the FRC time clock is 80MHz), the N is the ticks run by the line following,
  153. * Normally, N is less than 10, assume N is 10, so the error accumulation is only 6.48ms per month.
  154. * In fact, if the CPU frequency is large than 80MHz. The error accumulation will be more less than 6.48ms per month.
  155. * so It can be adopted.
  156. */
  157. REG_WRITE(FRC_TIMER_LOAD_REG(1), REG_READ(FRC_TIMER_COUNT_REG(1)) - ALARM_OVERFLOW_VAL);
  158. }
  159. void esp_timer_impl_lock(void)
  160. {
  161. portENTER_CRITICAL(&s_time_update_lock);
  162. }
  163. void esp_timer_impl_unlock(void)
  164. {
  165. portEXIT_CRITICAL(&s_time_update_lock);
  166. }
  167. uint64_t IRAM_ATTR esp_timer_impl_get_time(void)
  168. {
  169. uint32_t timer_val;
  170. uint64_t time_base;
  171. uint32_t ticks_per_us;
  172. bool overflow;
  173. do {
  174. /* Read all values needed to calculate current time */
  175. timer_val = REG_READ(FRC_TIMER_COUNT_REG(1));
  176. time_base = s_time_base_us;
  177. overflow = timer_overflow_happened();
  178. ticks_per_us = s_timer_ticks_per_us;
  179. /* Read them again and compare */
  180. /* In this function, do not call timer_count_reload() when overflow is true.
  181. * Because there's remain count enough to allow FRC_TIMER_COUNT_REG grow
  182. */
  183. if (REG_READ(FRC_TIMER_COUNT_REG(1)) > timer_val &&
  184. time_base == *((volatile uint64_t*) &s_time_base_us) &&
  185. ticks_per_us == *((volatile uint32_t*) &s_timer_ticks_per_us) &&
  186. overflow == timer_overflow_happened()) {
  187. break;
  188. }
  189. /* If any value has changed (other than the counter increasing), read again */
  190. } while(true);
  191. uint64_t result = time_base
  192. + timer_val / ticks_per_us;
  193. return result;
  194. }
  195. void IRAM_ATTR esp_timer_impl_set_alarm(uint64_t timestamp)
  196. {
  197. portENTER_CRITICAL_SAFE(&s_time_update_lock);
  198. // Alarm time relative to the moment when counter was 0
  199. uint64_t time_after_timebase_us = timestamp - s_time_base_us;
  200. // Adjust current time if overflow has happened
  201. bool overflow = timer_overflow_happened();
  202. uint64_t cur_count = REG_READ(FRC_TIMER_COUNT_REG(1));
  203. if (overflow) {
  204. assert(time_after_timebase_us > s_timer_us_per_overflow);
  205. time_after_timebase_us -= s_timer_us_per_overflow;
  206. s_overflow_happened = true;
  207. }
  208. // Calculate desired timer compare value (may exceed 2^32-1)
  209. uint64_t compare_val = time_after_timebase_us * s_timer_ticks_per_us;
  210. uint32_t alarm_reg_val = ALARM_OVERFLOW_VAL;
  211. // Use calculated alarm value if it is less than ALARM_OVERFLOW_VAL.
  212. // Note that if by the time we update ALARM_REG, COUNT_REG value is higher,
  213. // interrupt will not happen for another ALARM_OVERFLOW_VAL timer ticks,
  214. // so need to check if alarm value is too close in the future (e.g. <2 us away).
  215. const uint32_t offset = s_timer_ticks_per_us * 2;
  216. if (compare_val < ALARM_OVERFLOW_VAL) {
  217. if (compare_val < cur_count + offset) {
  218. compare_val = cur_count + offset;
  219. if (compare_val > ALARM_OVERFLOW_VAL) {
  220. compare_val = ALARM_OVERFLOW_VAL;
  221. }
  222. }
  223. alarm_reg_val = (uint32_t) compare_val;
  224. }
  225. REG_WRITE(FRC_TIMER_ALARM_REG(1), alarm_reg_val);
  226. portEXIT_CRITICAL_SAFE(&s_time_update_lock);
  227. }
  228. static void IRAM_ATTR timer_alarm_isr(void *arg)
  229. {
  230. portENTER_CRITICAL_ISR(&s_time_update_lock);
  231. // Timekeeping: adjust s_time_base_us if counter has passed ALARM_OVERFLOW_VAL
  232. if (timer_overflow_happened()) {
  233. timer_count_reload();
  234. s_time_base_us += s_timer_us_per_overflow;
  235. s_overflow_happened = false;
  236. }
  237. s_mask_overflow = false;
  238. // Clear interrupt status
  239. REG_WRITE(FRC_TIMER_INT_REG(1), FRC_TIMER_INT_CLR);
  240. // Set alarm to the next overflow moment. Later, upper layer function may
  241. // call esp_timer_impl_set_alarm to change this to an earlier value.
  242. REG_WRITE(FRC_TIMER_ALARM_REG(1), ALARM_OVERFLOW_VAL);
  243. portEXIT_CRITICAL_ISR(&s_time_update_lock);
  244. // Call the upper layer handler
  245. (*s_alarm_handler)(arg);
  246. }
  247. void IRAM_ATTR esp_timer_impl_update_apb_freq(uint32_t apb_ticks_per_us)
  248. {
  249. portENTER_CRITICAL_ISR(&s_time_update_lock);
  250. /* Bail out if the timer is not initialized yet */
  251. if (s_timer_interrupt_handle == NULL) {
  252. portEXIT_CRITICAL_ISR(&s_time_update_lock);
  253. return;
  254. }
  255. uint32_t new_ticks_per_us = apb_ticks_per_us / TIMER_DIV;
  256. uint32_t alarm = REG_READ(FRC_TIMER_ALARM_REG(1));
  257. uint32_t count = REG_READ(FRC_TIMER_COUNT_REG(1));
  258. uint64_t ticks_to_alarm = alarm - count;
  259. uint64_t new_ticks = (ticks_to_alarm * new_ticks_per_us) / s_timer_ticks_per_us;
  260. uint32_t new_alarm_val;
  261. if (alarm > count && new_ticks <= ALARM_OVERFLOW_VAL) {
  262. new_alarm_val = new_ticks;
  263. } else {
  264. new_alarm_val = ALARM_OVERFLOW_VAL;
  265. if (alarm != ALARM_OVERFLOW_VAL) {
  266. s_mask_overflow = true;
  267. }
  268. }
  269. REG_WRITE(FRC_TIMER_ALARM_REG(1), new_alarm_val);
  270. REG_WRITE(FRC_TIMER_LOAD_REG(1), 0);
  271. s_time_base_us += count / s_timer_ticks_per_us;
  272. #ifdef CONFIG_PM_DFS_USE_RTC_TIMER_REF
  273. // Due to the extra time required to read RTC time, don't attempt this
  274. // adjustment when switching to a higher frequency (which usually
  275. // happens in an interrupt).
  276. if (new_ticks_per_us < s_timer_ticks_per_us) {
  277. uint64_t rtc_time = esp_clk_rtc_time();
  278. uint64_t new_rtc_time_diff = s_time_base_us - rtc_time;
  279. if (s_rtc_time_diff != 0) {
  280. uint64_t correction = new_rtc_time_diff - s_rtc_time_diff;
  281. s_time_base_us -= correction;
  282. } else {
  283. s_rtc_time_diff = new_rtc_time_diff;
  284. }
  285. }
  286. #endif // CONFIG_PM_DFS_USE_RTC_TIMER_REF
  287. s_timer_ticks_per_us = new_ticks_per_us;
  288. s_timer_us_per_overflow = ALARM_OVERFLOW_VAL / new_ticks_per_us;
  289. portEXIT_CRITICAL_ISR(&s_time_update_lock);
  290. }
  291. void esp_timer_impl_advance(int64_t time_us)
  292. {
  293. assert(time_us > 0 && "negative adjustments not supported yet");
  294. portENTER_CRITICAL(&s_time_update_lock);
  295. uint64_t count = REG_READ(FRC_TIMER_COUNT_REG(1));
  296. /* Trigger an ISR to handle past alarms and set new one.
  297. * ISR handler will run once we exit the critical section.
  298. */
  299. REG_WRITE(FRC_TIMER_ALARM_REG(1), 0);
  300. REG_WRITE(FRC_TIMER_LOAD_REG(1), 0);
  301. s_time_base_us += count / s_timer_ticks_per_us + time_us;
  302. s_overflow_happened = false;
  303. portEXIT_CRITICAL(&s_time_update_lock);
  304. }
  305. esp_err_t esp_timer_impl_init(intr_handler_t alarm_handler)
  306. {
  307. s_alarm_handler = alarm_handler;
  308. esp_err_t err = esp_intr_alloc(ETS_TIMER2_INTR_SOURCE,
  309. ESP_INTR_FLAG_INTRDISABLED | ESP_INTR_FLAG_IRAM,
  310. &timer_alarm_isr, NULL, &s_timer_interrupt_handle);
  311. if (err != ESP_OK) {
  312. ESP_EARLY_LOGE(TAG, "esp_intr_alloc failed (0x%0x)", err);
  313. return err;
  314. }
  315. uint32_t apb_freq = rtc_clk_apb_freq_get();
  316. s_timer_ticks_per_us = apb_freq / 1000000 / TIMER_DIV;
  317. assert(s_timer_ticks_per_us > 0
  318. && apb_freq % TIMER_DIV == 0
  319. && "APB frequency does not result in a valid ticks_per_us value");
  320. s_timer_us_per_overflow = ALARM_OVERFLOW_VAL / s_timer_ticks_per_us;
  321. s_time_base_us = 0;
  322. REG_WRITE(FRC_TIMER_ALARM_REG(1), ALARM_OVERFLOW_VAL);
  323. REG_WRITE(FRC_TIMER_LOAD_REG(1), 0);
  324. REG_WRITE(FRC_TIMER_CTRL_REG(1),
  325. TIMER_DIV_CFG | FRC_TIMER_ENABLE | FRC_TIMER_LEVEL_INT);
  326. REG_WRITE(FRC_TIMER_INT_REG(1), FRC_TIMER_INT_CLR);
  327. ESP_ERROR_CHECK( esp_intr_enable(s_timer_interrupt_handle) );
  328. return ESP_OK;
  329. }
  330. void esp_timer_impl_deinit(void)
  331. {
  332. esp_intr_disable(s_timer_interrupt_handle);
  333. REG_WRITE(FRC_TIMER_CTRL_REG(1), 0);
  334. REG_WRITE(FRC_TIMER_ALARM_REG(1), 0);
  335. REG_WRITE(FRC_TIMER_LOAD_REG(1), 0);
  336. esp_intr_free(s_timer_interrupt_handle);
  337. s_timer_interrupt_handle = NULL;
  338. }
  339. // FIXME: This value is safe for 80MHz APB frequency.
  340. // Should be modified to depend on clock frequency.
  341. uint64_t IRAM_ATTR esp_timer_impl_get_min_period_us(void)
  342. {
  343. return 50;
  344. }
  345. #ifdef ESP_TIMER_DYNAMIC_OVERFLOW_VAL
  346. uint32_t esp_timer_impl_get_overflow_val(void)
  347. {
  348. return s_alarm_overflow_val;
  349. }
  350. void esp_timer_impl_set_overflow_val(uint32_t overflow_val)
  351. {
  352. s_alarm_overflow_val = overflow_val;
  353. /* update alarm value */
  354. esp_timer_impl_update_apb_freq(esp_clk_apb_freq() / 1000000);
  355. }
  356. #endif // ESP_TIMER_DYNAMIC_OVERFLOW_VAL