timer_ll.h 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. /*
  2. * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. // Note that most of the register operations in this layer are non-atomic operations.
  7. #pragma once
  8. #include <stdbool.h>
  9. #include "hal/assert.h"
  10. #include "hal/misc.h"
  11. #include "hal/timer_types.h"
  12. #include "soc/timer_group_struct.h"
  13. #ifdef __cplusplus
  14. extern "C" {
  15. #endif
  16. // Get timer group register base address with giving group number
  17. #define TIMER_LL_GET_HW(group_id) ((group_id == 0) ? (&TIMERG0) : (&TIMERG1))
  18. #define TIMER_LL_EVENT_ALARM(timer_id) (1 << (timer_id))
  19. /**
  20. * @brief Set clock source for timer
  21. *
  22. * @param hw Timer Group register base address
  23. * @param timer_num Timer number in the group
  24. * @param clk_src Clock source
  25. */
  26. static inline void timer_ll_set_clock_source(timg_dev_t *hw, uint32_t timer_num, gptimer_clock_source_t clk_src)
  27. {
  28. switch (clk_src) {
  29. case GPTIMER_CLK_SRC_APB:
  30. break;
  31. default:
  32. HAL_ASSERT(false && "unsupported clock source");
  33. break;
  34. }
  35. }
  36. /**
  37. * @brief Enable alarm event
  38. *
  39. * @param hw Timer Group register base address
  40. * @param timer_num Timer number in the group
  41. * @param en True: enable alarm
  42. * False: disable alarm
  43. */
  44. __attribute__((always_inline))
  45. static inline void timer_ll_enable_alarm(timg_dev_t *hw, uint32_t timer_num, bool en)
  46. {
  47. hw->hw_timer[timer_num].config.tx_alarm_en = en;
  48. // use level type interrupt
  49. hw->hw_timer[timer_num].config.tx_level_int_en = en;
  50. }
  51. /**
  52. * @brief Set clock prescale for timer
  53. *
  54. * @param hw Timer Group register base address
  55. * @param timer_num Timer number in the group
  56. * @param divider Prescale value (0 and 1 are not valid)
  57. */
  58. static inline void timer_ll_set_clock_prescale(timg_dev_t *hw, uint32_t timer_num, uint32_t divider)
  59. {
  60. HAL_ASSERT(divider >= 2 && divider <= 65536);
  61. if (divider >= 65536) {
  62. divider = 0;
  63. }
  64. HAL_FORCE_MODIFY_U32_REG_FIELD(hw->hw_timer[timer_num].config, tx_divider, divider);
  65. }
  66. /**
  67. * @brief Enable auto-reload mode
  68. *
  69. * @param hw Timer Group register base address
  70. * @param timer_num Timer number in the group
  71. * @param en True: enable auto reload mode
  72. * False: disable auto reload mode
  73. */
  74. static inline void timer_ll_enable_auto_reload(timg_dev_t *hw, uint32_t timer_num, bool en)
  75. {
  76. hw->hw_timer[timer_num].config.tx_autoreload = en;
  77. }
  78. /**
  79. * @brief Set count direction
  80. *
  81. * @param hw Timer peripheral register base address
  82. * @param timer_num Timer number in the group
  83. * @param direction Count direction
  84. */
  85. static inline void timer_ll_set_count_direction(timg_dev_t *hw, uint32_t timer_num, gptimer_count_direction_t direction)
  86. {
  87. hw->hw_timer[timer_num].config.tx_increase = direction == GPTIMER_COUNT_UP;
  88. }
  89. /**
  90. * @brief Enable timer, start couting
  91. *
  92. * @param hw Timer Group register base address
  93. * @param timer_num Timer number in the group
  94. * @param en True: enable the counter
  95. * False: disable the counter
  96. */
  97. __attribute__((always_inline))
  98. static inline void timer_ll_enable_counter(timg_dev_t *hw, uint32_t timer_num, bool en)
  99. {
  100. hw->hw_timer[timer_num].config.tx_en = en;
  101. }
  102. /**
  103. * @brief Get counter value
  104. *
  105. * @param hw Timer Group register base address
  106. * @param timer_num Timer number in the group
  107. *
  108. * @return counter value
  109. */
  110. __attribute__((always_inline))
  111. static inline uint64_t timer_ll_get_counter_value(timg_dev_t *hw, uint32_t timer_num)
  112. {
  113. hw->hw_timer[timer_num].update.tx_update = 1;
  114. // Timer register is in a different clock domain from Timer hardware logic
  115. // We need to wait for the update to take effect before fetching the count value
  116. while (hw->hw_timer[timer_num].update.tx_update) {
  117. }
  118. return ((uint64_t) hw->hw_timer[timer_num].hi.tx_hi << 32) | (hw->hw_timer[timer_num].lo.tx_lo);
  119. }
  120. /**
  121. * @brief Set alarm value
  122. *
  123. * @param hw Timer Group register base address
  124. * @param timer_num Timer number in the group
  125. * @param alarm_value When counter reaches alarm value, alarm event will be triggered
  126. */
  127. __attribute__((always_inline))
  128. static inline void timer_ll_set_alarm_value(timg_dev_t *hw, uint32_t timer_num, uint64_t alarm_value)
  129. {
  130. hw->hw_timer[timer_num].alarmhi.tx_alarm_hi = (uint32_t) (alarm_value >> 32);
  131. hw->hw_timer[timer_num].alarmlo.tx_alarm_lo = (uint32_t) alarm_value;
  132. }
  133. /**
  134. * @brief Set reload value
  135. *
  136. * @param hw Timer Group register base address
  137. * @param timer_num Timer number in the group
  138. * @param reload_val Reload counter value
  139. */
  140. static inline void timer_ll_set_reload_value(timg_dev_t *hw, uint32_t timer_num, uint64_t load_val)
  141. {
  142. hw->hw_timer[timer_num].loadhi.tx_load_hi = (uint32_t) (load_val >> 32);
  143. hw->hw_timer[timer_num].loadlo.tx_load_lo = (uint32_t) load_val;
  144. }
  145. /**
  146. * @brief Get reload value
  147. *
  148. * @param hw Timer Group register base address
  149. * @param timer_num Timer number in the group
  150. * @return reload count value
  151. */
  152. static inline uint64_t timer_ll_get_reload_value(timg_dev_t *hw, uint32_t timer_num)
  153. {
  154. return ((uint64_t)hw->hw_timer[timer_num].loadhi.tx_load_hi << 32) | (hw->hw_timer[timer_num].loadlo.tx_load_lo);
  155. }
  156. /**
  157. * @brief Trigger software reload, value set by `timer_ll_set_reload_value()` will be reflected into counter immediately
  158. *
  159. * @param hw Timer Group register base address
  160. * @param timer_num Timer number in the group
  161. */
  162. static inline void timer_ll_trigger_soft_reload(timg_dev_t *hw, uint32_t timer_num)
  163. {
  164. hw->hw_timer[timer_num].load.tx_load = 1;
  165. }
  166. /**
  167. * @brief Enable timer interrupt by mask
  168. *
  169. * @param hw Timer Group register base address
  170. * @param mask Mask of interrupt events
  171. * @param en True: enable interrupt
  172. * False: disable interrupt
  173. */
  174. __attribute__((always_inline))
  175. static inline void timer_ll_enable_intr(timg_dev_t *hw, uint32_t mask, bool en)
  176. {
  177. if (en) {
  178. hw->int_ena_timers.val |= mask;
  179. } else {
  180. hw->int_ena_timers.val &= ~mask;
  181. }
  182. }
  183. /**
  184. * @brief Get interrupt status
  185. *
  186. * @param hw Timer Group register base address
  187. *
  188. * @return Interrupt status
  189. */
  190. __attribute__((always_inline))
  191. static inline uint32_t timer_ll_get_intr_status(timg_dev_t *hw)
  192. {
  193. return hw->int_st_timers.val & 0x03;
  194. }
  195. /**
  196. * @brief Clear interrupt status by mask
  197. *
  198. * @param hw Timer Group register base address
  199. * @param mask Interrupt events mask
  200. */
  201. __attribute__((always_inline))
  202. static inline void timer_ll_clear_intr_status(timg_dev_t *hw, uint32_t mask)
  203. {
  204. hw->int_clr_timers.val = mask;
  205. }
  206. /**
  207. * @brief Enable the register clock forever
  208. *
  209. * @param hw Timer Group register base address
  210. * @param en True: Enable the register clock forever
  211. * False: Register clock is enabled only when register operation happens
  212. */
  213. static inline void timer_ll_enable_register_clock_always_on(timg_dev_t *hw, bool en)
  214. {
  215. hw->regclk.clk_en = en;
  216. }
  217. /**
  218. * @brief Get interrupt status register address.
  219. *
  220. * @param hw Beginning address of the peripheral registers.
  221. *
  222. * @return Interrupt status register address
  223. */
  224. static inline volatile void *timer_ll_get_intr_status_reg(timg_dev_t *hw)
  225. {
  226. return &hw->int_st_timers.val;
  227. }
  228. #ifdef __cplusplus
  229. }
  230. #endif