esp_timer_impl_frc_legacy.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448
  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 "sys/param.h"
  15. #include "esp_timer_impl.h"
  16. #include "esp_timer.h"
  17. #include "esp_err.h"
  18. #include "esp_system.h"
  19. #include "esp_task.h"
  20. #include "esp_attr.h"
  21. #include "esp_intr_alloc.h"
  22. #include "esp_log.h"
  23. #include "esp32/clk.h"
  24. #include "soc/frc_timer_reg.h"
  25. #include "soc/rtc.h"
  26. #include "freertos/FreeRTOS.h"
  27. #include "freertos/task.h"
  28. #include "freertos/semphr.h"
  29. /**
  30. * @file esp_timer_frc.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 = NULL;
  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. #ifdef CONFIG_PM_USE_RTC_TIMER_REF
  119. // If DFS is enabled, upon the first frequency change this value is set to the
  120. // difference between esp_timer value and RTC timer value. On every subsequent
  121. // frequency change, s_time_base_us is adjusted to maintain the same difference
  122. // between esp_timer and RTC timer. (All mentioned values are in microseconds.)
  123. static uint64_t s_rtc_time_diff = 0;
  124. #endif
  125. // Spinlock used to protect access to static variables above and to the hardware
  126. // registers.
  127. portMUX_TYPE s_time_update_lock = portMUX_INITIALIZER_UNLOCKED;
  128. //Use FRC_TIMER_LOAD_VALUE(1) instead of UINT32_MAX, convenience to change FRC TIMER for future
  129. #define TIMER_IS_AFTER_OVERFLOW(a) (ALARM_OVERFLOW_VAL < (a) && (a) <= FRC_TIMER_LOAD_VALUE(1))
  130. // Check if timer overflow has happened (but was not handled by ISR yet)
  131. static inline bool IRAM_ATTR timer_overflow_happened(void)
  132. {
  133. return ((REG_READ(FRC_TIMER_CTRL_REG(1)) & FRC_TIMER_INT_STATUS) != 0 &&
  134. ((REG_READ(FRC_TIMER_ALARM_REG(1)) == ALARM_OVERFLOW_VAL && TIMER_IS_AFTER_OVERFLOW(REG_READ(FRC_TIMER_COUNT_REG(1))) && !s_mask_overflow) ||
  135. (!TIMER_IS_AFTER_OVERFLOW(REG_READ(FRC_TIMER_ALARM_REG(1))) && TIMER_IS_AFTER_OVERFLOW(REG_READ(FRC_TIMER_COUNT_REG(1))))));
  136. }
  137. static inline void IRAM_ATTR timer_count_reload(void)
  138. {
  139. //this function should be only called the real overflow happened. And the count cannot be very approach to 0xffffffff.
  140. assert(TIMER_IS_AFTER_OVERFLOW(REG_READ(FRC_TIMER_COUNT_REG(1))));
  141. /* Restart the timer count by current time count minus ALARM_OVERFLOW_VAL(0xefffffff), it may cause error, if current tick is near boundary.
  142. * But even if the error happen 100% per overflow(the distance of each real overflow is about 50 second),
  143. * the error is 0.0125us*N per 50s(the FRC time clock is 80MHz), the N is the ticks run by the line following,
  144. * Normally, N is less than 10, assume N is 10, so the error accumulation is only 6.48ms per month.
  145. * In fact, if the CPU frequency is large than 80MHz. The error accumulation will be more less than 6.48ms per month.
  146. * so It can be adopted.
  147. */
  148. REG_WRITE(FRC_TIMER_LOAD_REG(1), REG_READ(FRC_TIMER_COUNT_REG(1)) - ALARM_OVERFLOW_VAL);
  149. }
  150. void esp_timer_impl_lock(void)
  151. {
  152. portENTER_CRITICAL(&s_time_update_lock);
  153. }
  154. void esp_timer_impl_unlock(void)
  155. {
  156. portEXIT_CRITICAL(&s_time_update_lock);
  157. }
  158. int64_t IRAM_ATTR esp_timer_impl_get_time(void)
  159. {
  160. if (s_alarm_handler == NULL) {
  161. return 0;
  162. }
  163. uint32_t timer_val;
  164. uint64_t time_base;
  165. uint32_t ticks_per_us;
  166. bool overflow;
  167. do {
  168. /* Read all values needed to calculate current time */
  169. timer_val = REG_READ(FRC_TIMER_COUNT_REG(1));
  170. time_base = s_time_base_us;
  171. overflow = timer_overflow_happened();
  172. ticks_per_us = s_timer_ticks_per_us;
  173. /* Read them again and compare */
  174. /* In this function, do not call timer_count_reload() when overflow is true.
  175. * Because there's remain count enough to allow FRC_TIMER_COUNT_REG grow
  176. */
  177. if (REG_READ(FRC_TIMER_COUNT_REG(1)) > timer_val &&
  178. time_base == *((volatile uint64_t*) &s_time_base_us) &&
  179. ticks_per_us == *((volatile uint32_t*) &s_timer_ticks_per_us) &&
  180. overflow == timer_overflow_happened()) {
  181. break;
  182. }
  183. /* If any value has changed (other than the counter increasing), read again */
  184. } while(true);
  185. uint64_t result = time_base
  186. + timer_val / ticks_per_us;
  187. return result;
  188. }
  189. int64_t esp_timer_get_time(void) __attribute__((alias("esp_timer_impl_get_time")));
  190. void IRAM_ATTR esp_timer_impl_set_alarm_id(uint64_t timestamp, unsigned alarm_id)
  191. {
  192. static uint64_t timestamp_id[2] = { UINT64_MAX, UINT64_MAX };
  193. portENTER_CRITICAL_SAFE(&s_time_update_lock);
  194. timestamp_id[alarm_id] = timestamp;
  195. timestamp = MIN(timestamp_id[0], timestamp_id[1]);
  196. if (timestamp != UINT64_MAX) {
  197. // Use calculated alarm value if it is less than ALARM_OVERFLOW_VAL.
  198. // Note that if by the time we update ALARM_REG, COUNT_REG value is higher,
  199. // interrupt will not happen for another ALARM_OVERFLOW_VAL timer ticks,
  200. // so need to check if alarm value is too close in the future (e.g. <2 us away).
  201. int32_t offset = s_timer_ticks_per_us * 2;
  202. do {
  203. // Adjust current time if overflow has happened
  204. if (timer_overflow_happened() ||
  205. ((REG_READ(FRC_TIMER_COUNT_REG(1)) > ALARM_OVERFLOW_VAL) &&
  206. ((REG_READ(FRC_TIMER_CTRL_REG(1)) & FRC_TIMER_INT_STATUS) == 0))) {
  207. // 1. timer_overflow_happened() checks overflow with the interrupt flag.
  208. // 2. During several loops, the counter can be higher than the alarm and even step over ALARM_OVERFLOW_VAL boundary (the interrupt flag is not set).
  209. timer_count_reload();
  210. s_time_base_us += s_timer_us_per_overflow;
  211. }
  212. s_mask_overflow = false;
  213. int64_t cur_count = REG_READ(FRC_TIMER_COUNT_REG(1));
  214. // Alarm time relative to the moment when counter was 0
  215. int64_t time_after_timebase_us = (int64_t)timestamp - s_time_base_us;
  216. // Calculate desired timer compare value (may exceed 2^32-1)
  217. int64_t compare_val = time_after_timebase_us * s_timer_ticks_per_us;
  218. compare_val = MAX(compare_val, cur_count + offset);
  219. uint32_t alarm_reg_val = ALARM_OVERFLOW_VAL;
  220. if (compare_val < ALARM_OVERFLOW_VAL) {
  221. alarm_reg_val = (uint32_t) compare_val;
  222. }
  223. REG_WRITE(FRC_TIMER_ALARM_REG(1), alarm_reg_val);
  224. int64_t delta = (int64_t)alarm_reg_val - (int64_t)REG_READ(FRC_TIMER_COUNT_REG(1));
  225. if (delta <= 0) {
  226. /*
  227. When the timestamp is a bit less than the current counter then the alarm = current_counter + offset.
  228. But due to CPU_freq in some case can be equal APB_freq the offset time can not exceed the overhead
  229. (the alarm will be less than the counter) and it leads to the infinity loop.
  230. To exclude this behavior to the offset was added the delta to have the opportunity to go through it.
  231. */
  232. offset += abs((int)delta) + s_timer_ticks_per_us * 2;
  233. } else {
  234. break;
  235. }
  236. } while (1);
  237. }
  238. portEXIT_CRITICAL_SAFE(&s_time_update_lock);
  239. }
  240. void IRAM_ATTR esp_timer_impl_set_alarm(uint64_t timestamp)
  241. {
  242. esp_timer_impl_set_alarm_id(timestamp, 0);
  243. }
  244. static void IRAM_ATTR timer_alarm_isr(void *arg)
  245. {
  246. portENTER_CRITICAL_ISR(&s_time_update_lock);
  247. // Timekeeping: adjust s_time_base_us if counter has passed ALARM_OVERFLOW_VAL
  248. if (timer_overflow_happened()) {
  249. timer_count_reload();
  250. s_time_base_us += s_timer_us_per_overflow;
  251. }
  252. s_mask_overflow = false;
  253. // Clear interrupt status
  254. REG_WRITE(FRC_TIMER_INT_REG(1), FRC_TIMER_INT_CLR);
  255. // Set alarm to the next overflow moment. Later, upper layer function may
  256. // call esp_timer_impl_set_alarm to change this to an earlier value.
  257. REG_WRITE(FRC_TIMER_ALARM_REG(1), ALARM_OVERFLOW_VAL);
  258. if ((REG_READ(FRC_TIMER_COUNT_REG(1)) > ALARM_OVERFLOW_VAL) &&
  259. ((REG_READ(FRC_TIMER_CTRL_REG(1)) & FRC_TIMER_INT_STATUS) == 0)) {
  260. /*
  261. This check excludes the case when the alarm can be less than the counter.
  262. Without this check, it is possible because DPORT uses 4-lvl, and users can use the 5 Hi-interrupt,
  263. they can interrupt this function between FRC_TIMER_INT_CLR and setting the alarm = ALARM_OVERFLOW_VAL
  264. that lead to the counter will go ahead leaving the alarm behind.
  265. */
  266. timer_count_reload();
  267. s_time_base_us += s_timer_us_per_overflow;
  268. }
  269. portEXIT_CRITICAL_ISR(&s_time_update_lock);
  270. // Call the upper layer handler
  271. (*s_alarm_handler)(arg);
  272. }
  273. void IRAM_ATTR esp_timer_impl_update_apb_freq(uint32_t apb_ticks_per_us)
  274. {
  275. portENTER_CRITICAL_ISR(&s_time_update_lock);
  276. /* Bail out if the timer is not initialized yet */
  277. if (s_timer_interrupt_handle == NULL) {
  278. portEXIT_CRITICAL_ISR(&s_time_update_lock);
  279. return;
  280. }
  281. uint32_t new_ticks_per_us = apb_ticks_per_us / TIMER_DIV;
  282. uint32_t alarm = REG_READ(FRC_TIMER_ALARM_REG(1));
  283. uint32_t count = REG_READ(FRC_TIMER_COUNT_REG(1));
  284. uint64_t ticks_to_alarm = alarm - count;
  285. uint64_t new_ticks = (ticks_to_alarm * new_ticks_per_us) / s_timer_ticks_per_us;
  286. uint32_t new_alarm_val;
  287. if (alarm > count && new_ticks <= ALARM_OVERFLOW_VAL) {
  288. new_alarm_val = new_ticks;
  289. } else {
  290. new_alarm_val = ALARM_OVERFLOW_VAL;
  291. if (alarm != ALARM_OVERFLOW_VAL) {
  292. s_mask_overflow = true;
  293. }
  294. }
  295. REG_WRITE(FRC_TIMER_ALARM_REG(1), new_alarm_val);
  296. REG_WRITE(FRC_TIMER_LOAD_REG(1), 0);
  297. s_time_base_us += count / s_timer_ticks_per_us;
  298. #ifdef CONFIG_PM_USE_RTC_TIMER_REF
  299. // Due to the extra time required to read RTC time, don't attempt this
  300. // adjustment when switching to a higher frequency (which usually
  301. // happens in an interrupt).
  302. if (new_ticks_per_us < s_timer_ticks_per_us) {
  303. uint64_t rtc_time = esp_clk_rtc_time();
  304. uint64_t new_rtc_time_diff = s_time_base_us - rtc_time;
  305. if (s_rtc_time_diff != 0) {
  306. uint64_t correction = new_rtc_time_diff - s_rtc_time_diff;
  307. s_time_base_us -= correction;
  308. } else {
  309. s_rtc_time_diff = new_rtc_time_diff;
  310. }
  311. }
  312. #endif // CONFIG_PM_USE_RTC_TIMER_REF
  313. s_timer_ticks_per_us = new_ticks_per_us;
  314. s_timer_us_per_overflow = ALARM_OVERFLOW_VAL / new_ticks_per_us;
  315. portEXIT_CRITICAL_ISR(&s_time_update_lock);
  316. }
  317. void esp_timer_impl_advance(int64_t time_us)
  318. {
  319. assert(time_us > 0 && "negative adjustments not supported yet");
  320. portENTER_CRITICAL(&s_time_update_lock);
  321. uint64_t count = REG_READ(FRC_TIMER_COUNT_REG(1));
  322. /* Trigger an ISR to handle past alarms and set new one.
  323. * ISR handler will run once we exit the critical section.
  324. */
  325. REG_WRITE(FRC_TIMER_ALARM_REG(1), 0);
  326. REG_WRITE(FRC_TIMER_LOAD_REG(1), 0);
  327. s_time_base_us += count / s_timer_ticks_per_us + time_us;
  328. portEXIT_CRITICAL(&s_time_update_lock);
  329. }
  330. esp_err_t esp_timer_impl_init(intr_handler_t alarm_handler)
  331. {
  332. s_alarm_handler = alarm_handler;
  333. const int interrupt_lvl = (1 << CONFIG_ESP_TIMER_INTERRUPT_LEVEL) & ESP_INTR_FLAG_LEVELMASK;
  334. esp_err_t err = esp_intr_alloc(ETS_TIMER2_INTR_SOURCE,
  335. ESP_INTR_FLAG_INTRDISABLED | ESP_INTR_FLAG_IRAM | interrupt_lvl,
  336. &timer_alarm_isr, NULL, &s_timer_interrupt_handle);
  337. if (err != ESP_OK) {
  338. ESP_EARLY_LOGE(TAG, "esp_intr_alloc failed (0x%0x)", err);
  339. return err;
  340. }
  341. uint32_t apb_freq = rtc_clk_apb_freq_get();
  342. s_timer_ticks_per_us = apb_freq / 1000000 / TIMER_DIV;
  343. assert(s_timer_ticks_per_us > 0
  344. && apb_freq % TIMER_DIV == 0
  345. && "APB frequency does not result in a valid ticks_per_us value");
  346. s_timer_us_per_overflow = ALARM_OVERFLOW_VAL / s_timer_ticks_per_us;
  347. s_time_base_us = 0;
  348. REG_WRITE(FRC_TIMER_ALARM_REG(1), ALARM_OVERFLOW_VAL);
  349. REG_WRITE(FRC_TIMER_LOAD_REG(1), 0);
  350. REG_WRITE(FRC_TIMER_CTRL_REG(1),
  351. TIMER_DIV_CFG | FRC_TIMER_ENABLE | FRC_TIMER_LEVEL_INT);
  352. REG_WRITE(FRC_TIMER_INT_REG(1), FRC_TIMER_INT_CLR);
  353. ESP_ERROR_CHECK( esp_intr_enable(s_timer_interrupt_handle) );
  354. return ESP_OK;
  355. }
  356. void esp_timer_impl_deinit(void)
  357. {
  358. esp_intr_disable(s_timer_interrupt_handle);
  359. REG_WRITE(FRC_TIMER_CTRL_REG(1), 0);
  360. REG_WRITE(FRC_TIMER_ALARM_REG(1), 0);
  361. REG_WRITE(FRC_TIMER_LOAD_REG(1), 0);
  362. esp_intr_free(s_timer_interrupt_handle);
  363. s_timer_interrupt_handle = NULL;
  364. }
  365. // FIXME: This value is safe for 80MHz APB frequency.
  366. // Should be modified to depend on clock frequency.
  367. uint64_t IRAM_ATTR esp_timer_impl_get_min_period_us(void)
  368. {
  369. return 50;
  370. }
  371. #ifdef ESP_TIMER_DYNAMIC_OVERFLOW_VAL
  372. uint32_t esp_timer_impl_get_overflow_val(void)
  373. {
  374. return s_alarm_overflow_val;
  375. }
  376. void esp_timer_impl_set_overflow_val(uint32_t overflow_val)
  377. {
  378. s_alarm_overflow_val = overflow_val;
  379. /* update alarm value */
  380. esp_timer_impl_update_apb_freq(esp_clk_apb_freq() / 1000000);
  381. }
  382. #endif // ESP_TIMER_DYNAMIC_OVERFLOW_VAL
  383. uint64_t esp_timer_impl_get_counter_reg(void)
  384. {
  385. return (uint64_t)REG_READ(FRC_TIMER_COUNT_REG(1));
  386. }
  387. uint64_t esp_timer_impl_get_alarm_reg(void)
  388. {
  389. return (uint64_t)REG_READ(FRC_TIMER_ALARM_REG(1));
  390. }
  391. void esp_timer_private_update_apb_freq(uint32_t apb_ticks_per_us) __attribute__((alias("esp_timer_impl_update_apb_freq")));
  392. void esp_timer_private_advance(int64_t time_us) __attribute__((alias("esp_timer_impl_advance")));
  393. void esp_timer_private_lock(void) __attribute__((alias("esp_timer_impl_lock")));
  394. void esp_timer_private_unlock(void) __attribute__((alias("esp_timer_impl_unlock")));