timer_ll.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433
  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. // The LL layer for Timer Group register operations.
  15. // Note that most of the register operations in this layer are non-atomic operations.
  16. #pragma once
  17. #ifdef __cplusplus
  18. extern "C" {
  19. #endif
  20. #include <stdlib.h>
  21. #include "hal/misc.h"
  22. #include "soc/timer_periph.h"
  23. #include "soc/timer_group_struct.h"
  24. #include "hal/timer_types.h"
  25. #include "hal/assert.h"
  26. _Static_assert(TIMER_INTR_T0 == TIMG_T0_INT_CLR, "Add mapping to LL interrupt handling, since it's no longer naturally compatible with the timer_intr_t");
  27. _Static_assert(TIMER_INTR_WDT == TIMG_WDT_INT_CLR, "Add mapping to LL interrupt handling, since it's no longer naturally compatible with the timer_intr_t");
  28. typedef struct {
  29. timg_dev_t *dev;
  30. timer_idx_t idx;
  31. } timer_ll_context_t;
  32. // Get timer group instance with giving group number
  33. #define TIMER_LL_GET_HW(num) ((num == 0) ? (&TIMERG0) : (&TIMERG1))
  34. /**
  35. * @brief Set timer clock prescale value
  36. *
  37. * @param hw Beginning address of the peripheral registers.
  38. * @param timer_num The timer number
  39. * @param divider Prescale value
  40. *
  41. * @return None
  42. */
  43. static inline void timer_ll_set_divider(timg_dev_t *hw, timer_idx_t timer_num, uint32_t divider)
  44. {
  45. HAL_ASSERT(divider >= 2 && divider <= 65536);
  46. if (divider >= 65536) {
  47. divider = 0;
  48. }
  49. int timer_en = hw->hw_timer[timer_num].config.tx_en;
  50. hw->hw_timer[timer_num].config.tx_en = 0;
  51. hw->hw_timer[timer_num].config.tx_divcnt_rst = 1;
  52. HAL_FORCE_MODIFY_U32_REG_FIELD(hw->hw_timer[timer_num].config, tx_divider, divider);
  53. hw->hw_timer[timer_num].config.tx_en = timer_en;
  54. }
  55. /**
  56. * @brief Get timer clock prescale value
  57. *
  58. * @param hw Beginning address of the peripheral registers.
  59. * @param timer_num The timer number
  60. * @param divider Pointer to accept the prescale value
  61. *
  62. * @return None
  63. */
  64. static inline void timer_ll_get_divider(timg_dev_t *hw, timer_idx_t timer_num, uint32_t *divider)
  65. {
  66. uint32_t d = HAL_FORCE_READ_U32_REG_FIELD(hw->hw_timer[timer_num].config, tx_divider);
  67. if (d == 0) {
  68. d = 65536;
  69. } else if (d == 1) {
  70. d = 2;
  71. }
  72. *divider = d;
  73. }
  74. /**
  75. * @brief Load counter value into time-base counter
  76. *
  77. * @param hw Beginning address of the peripheral registers.
  78. * @param timer_num The timer number
  79. * @param load_val Counter value
  80. *
  81. * @return None
  82. */
  83. static inline void timer_ll_set_counter_value(timg_dev_t *hw, timer_idx_t timer_num, uint64_t load_val)
  84. {
  85. hw->hw_timer[timer_num].loadhi.tx_load_hi = (uint32_t) (load_val >> 32);
  86. hw->hw_timer[timer_num].loadlo.tx_load_lo = (uint32_t) load_val;
  87. hw->hw_timer[timer_num].load.tx_load = 1;
  88. }
  89. /**
  90. * @brief Get counter value from time-base counter
  91. *
  92. * @param hw Beginning address of the peripheral registers.
  93. * @param timer_num The timer number
  94. * @param timer_val Pointer to accept the counter value
  95. *
  96. * @return None
  97. */
  98. FORCE_INLINE_ATTR void timer_ll_get_counter_value(timg_dev_t *hw, timer_idx_t timer_num, uint64_t *timer_val)
  99. {
  100. hw->hw_timer[timer_num].update.tx_update = 1;
  101. while (hw->hw_timer[timer_num].update.tx_update) {}
  102. *timer_val = ((uint64_t) hw->hw_timer[timer_num].hi.tx_hi << 32) | (hw->hw_timer[timer_num].lo.tx_lo);
  103. }
  104. /**
  105. * @brief Set counter mode, include increment mode and decrement mode.
  106. *
  107. * @param hw Beginning address of the peripheral registers.
  108. * @param timer_num The timer number
  109. * @param increase_en True to increment mode, fasle to decrement mode
  110. *
  111. * @return None
  112. */
  113. static inline void timer_ll_set_counter_increase(timg_dev_t *hw, timer_idx_t timer_num, bool increase_en)
  114. {
  115. hw->hw_timer[timer_num].config.tx_increase = increase_en;
  116. }
  117. /**
  118. * @brief Get counter mode, include increment mode and decrement mode.
  119. *
  120. * @param hw Beginning address of the peripheral registers.
  121. * @param timer_num The timer number
  122. *
  123. * @return
  124. * - true Increment mode
  125. * - false Decrement mode
  126. */
  127. static inline bool timer_ll_get_counter_increase(timg_dev_t *hw, timer_idx_t timer_num)
  128. {
  129. return hw->hw_timer[timer_num].config.tx_increase;
  130. }
  131. /**
  132. * @brief Set counter status, enable or disable counter.
  133. *
  134. * @param hw Beginning address of the peripheral registers.
  135. * @param timer_num The timer number
  136. * @param counter_en True to enable counter, false to disable counter
  137. *
  138. * @return None
  139. */
  140. FORCE_INLINE_ATTR void timer_ll_set_counter_enable(timg_dev_t *hw, timer_idx_t timer_num, bool counter_en)
  141. {
  142. hw->hw_timer[timer_num].config.tx_en = counter_en;
  143. }
  144. /**
  145. * @brief Get counter status.
  146. *
  147. * @param hw Beginning address of the peripheral registers.
  148. * @param timer_num The timer number
  149. *
  150. * @return
  151. * - true Enable counter
  152. * - false Disable conuter
  153. */
  154. static inline bool timer_ll_get_counter_enable(timg_dev_t *hw, timer_idx_t timer_num)
  155. {
  156. return hw->hw_timer[timer_num].config.tx_en;
  157. }
  158. /**
  159. * @brief Set auto reload mode.
  160. *
  161. * @param hw Beginning address of the peripheral registers.
  162. * @param timer_num The timer number
  163. * @param auto_reload_en True to enable auto reload mode, flase to disable auto reload mode
  164. *
  165. * @return None
  166. */
  167. static inline void timer_ll_set_auto_reload(timg_dev_t *hw, timer_idx_t timer_num, bool auto_reload_en)
  168. {
  169. hw->hw_timer[timer_num].config.tx_autoreload = auto_reload_en;
  170. }
  171. /**
  172. * @brief Get auto reload mode.
  173. *
  174. * @param hw Beginning address of the peripheral registers.
  175. * @param timer_num The timer number
  176. *
  177. * @return
  178. * - true Enable auto reload mode
  179. * - false Disable auto reload mode
  180. */
  181. FORCE_INLINE_ATTR bool timer_ll_get_auto_reload(timg_dev_t *hw, timer_idx_t timer_num)
  182. {
  183. return hw->hw_timer[timer_num].config.tx_autoreload;
  184. }
  185. /**
  186. * @brief Set the counter value to trigger the alarm.
  187. *
  188. * @param hw Beginning address of the peripheral registers.
  189. * @param timer_num The timer number
  190. * @param alarm_value Counter value to trigger the alarm
  191. *
  192. * @return None
  193. */
  194. FORCE_INLINE_ATTR void timer_ll_set_alarm_value(timg_dev_t *hw, timer_idx_t timer_num, uint64_t alarm_value)
  195. {
  196. hw->hw_timer[timer_num].alarmhi.tx_alarm_hi = (uint32_t) (alarm_value >> 32);
  197. hw->hw_timer[timer_num].alarmlo.tx_alarm_lo = (uint32_t) alarm_value;
  198. }
  199. /**
  200. * @brief Get the counter value to trigger the alarm.
  201. *
  202. * @param hw Beginning address of the peripheral registers.
  203. * @param timer_num The timer number
  204. * @param alarm_value Pointer to accept the counter value to trigger the alarm
  205. *
  206. * @return None
  207. */
  208. static inline void timer_ll_get_alarm_value(timg_dev_t *hw, timer_idx_t timer_num, uint64_t *alarm_value)
  209. {
  210. *alarm_value = ((uint64_t) hw->hw_timer[timer_num].alarmhi.tx_alarm_hi << 32) | (hw->hw_timer[timer_num].alarmlo.tx_alarm_lo);
  211. }
  212. /**
  213. * @brief Set the alarm status, enable or disable the alarm.
  214. *
  215. * @param hw Beginning address of the peripheral registers.
  216. * @param timer_num The timer number
  217. * @param alarm_en True to enable alarm, false to disable alarm
  218. *
  219. * @return None
  220. */
  221. FORCE_INLINE_ATTR void timer_ll_set_alarm_enable(timg_dev_t *hw, timer_idx_t timer_num, bool alarm_en)
  222. {
  223. hw->hw_timer[timer_num].config.tx_alarm_en = alarm_en;
  224. }
  225. /**
  226. * @brief Get the alarm status.
  227. *
  228. * @param hw Beginning address of the peripheral registers.
  229. * @param timer_num The timer number
  230. *
  231. * @return
  232. * - true Enable alarm
  233. * - false Disable alarm
  234. */
  235. static inline bool timer_ll_get_alarm_enable(timg_dev_t *hw, timer_idx_t timer_num)
  236. {
  237. return hw->hw_timer[timer_num].config.tx_alarm_en;
  238. }
  239. /**
  240. * @brief Enable timer interrupt.
  241. *
  242. * @param hw Beginning address of the peripheral registers.
  243. * @param timer_num The timer number
  244. *
  245. * @return None
  246. */
  247. FORCE_INLINE_ATTR void timer_ll_intr_enable(timg_dev_t *hw, timer_idx_t timer_num)
  248. {
  249. hw->int_ena_timers.val |= BIT(timer_num);
  250. }
  251. /**
  252. * @brief Disable timer interrupt.
  253. *
  254. * @param hw Beginning address of the peripheral registers.
  255. * @param timer_num The timer number
  256. *
  257. * @return None
  258. */
  259. FORCE_INLINE_ATTR void timer_ll_intr_disable(timg_dev_t *hw, timer_idx_t timer_num)
  260. {
  261. hw->int_ena_timers.val &= (~BIT(timer_num));
  262. }
  263. /**
  264. * @brief Disable timer interrupt.
  265. *
  266. * @param hw Beginning address of the peripheral registers.
  267. * @param timer_num The timer number
  268. *
  269. * @return None
  270. */
  271. FORCE_INLINE_ATTR void timer_ll_clear_intr_status(timg_dev_t *hw, timer_idx_t timer_num)
  272. {
  273. hw->int_clr_timers.val |= BIT(timer_num);
  274. }
  275. /**
  276. * @brief Get interrupt status.
  277. *
  278. * @param hw Beginning address of the peripheral registers.
  279. * @param intr_status Interrupt status
  280. *
  281. * @return None
  282. */
  283. FORCE_INLINE_ATTR void timer_ll_get_intr_status(timg_dev_t *hw, uint32_t *intr_status)
  284. {
  285. *intr_status = hw->int_st_timers.val & 0x01;
  286. }
  287. /**
  288. * @brief Get interrupt raw status.
  289. *
  290. * @param group_num Timer group number, 0 for TIMERG0 or 1 for TIMERG1
  291. * @param intr_raw_status Interrupt raw status
  292. *
  293. * @return None
  294. */
  295. FORCE_INLINE_ATTR void timer_ll_get_intr_raw_status(timer_group_t group_num, uint32_t *intr_raw_status)
  296. {
  297. timg_dev_t *hw = TIMER_LL_GET_HW(group_num);
  298. *intr_raw_status = hw->int_raw_timers.val & 0x01;
  299. }
  300. /**
  301. * @brief Set the level interrupt status, enable or disable the level interrupt.
  302. *
  303. * @param hw Beginning address of the peripheral registers.
  304. * @param timer_num The timer number
  305. * @param level_int_en True to enable level interrupt, false to disable level interrupt
  306. *
  307. * @return None
  308. */
  309. static inline void timer_ll_set_level_int_enable(timg_dev_t *hw, timer_idx_t timer_num, bool level_int_en)
  310. {
  311. // Only "level" interrupts are supported on this target
  312. }
  313. /**
  314. * @brief Get the level interrupt status.
  315. *
  316. * @param hw Beginning address of the peripheral registers.
  317. * @param timer_num The timer number
  318. *
  319. * @return
  320. * - true Enable level interrupt
  321. * - false Disable level interrupt
  322. */
  323. static inline bool timer_ll_get_level_int_enable(timg_dev_t *hw, timer_idx_t timer_num)
  324. {
  325. // Only "level" interrupts are supported on this target
  326. return true;
  327. }
  328. /**
  329. * @brief Set the edge interrupt status, enable or disable the edge interrupt.
  330. *
  331. * @param hw Beginning address of the peripheral registers.
  332. * @param timer_num The timer number
  333. * @param edge_int_en True to enable edge interrupt, false to disable edge interrupt
  334. *
  335. * @return None
  336. */
  337. static inline void timer_ll_set_edge_int_enable(timg_dev_t *hw, timer_idx_t timer_num, bool edge_int_en)
  338. {
  339. // edge interrupt is not supported on H2
  340. }
  341. /**
  342. * @brief Get the edge interrupt status.
  343. *
  344. * @param hw Beginning address of the peripheral registers.
  345. * @param timer_num The timer number
  346. *
  347. * @return
  348. * - true Enable edge interrupt
  349. * - false Disable edge interrupt
  350. */
  351. static inline bool timer_ll_get_edge_int_enable(timg_dev_t *hw, timer_idx_t timer_num)
  352. {
  353. // edge interrupt is not supported on H2
  354. return false;
  355. }
  356. /**
  357. * @brief Get interrupt status register address.
  358. *
  359. * @param hw Beginning address of the peripheral registers.
  360. *
  361. * @return uint32_t Interrupt status register address
  362. */
  363. static inline uint32_t timer_ll_get_intr_status_reg(timg_dev_t *hw)
  364. {
  365. return (uint32_t) & (hw->int_st_timers.val);
  366. }
  367. static inline uint32_t timer_ll_get_intr_mask_bit(timg_dev_t *hw, timer_idx_t timer_num)
  368. {
  369. return (1U << timer_num);
  370. }
  371. /**
  372. * @brief Set clock source.
  373. *
  374. * @param hal Context of the HAL layer
  375. * @param use_xtal_en True to use XTAL clock, flase to use APB clock
  376. *
  377. * @return None
  378. */
  379. static inline void timer_ll_set_use_xtal(timg_dev_t *hw, timer_idx_t timer_num, bool use_xtal_en)
  380. {
  381. hw->hw_timer[timer_num].config.tx_use_xtal = use_xtal_en;
  382. }
  383. /**
  384. * @brief Get clock source.
  385. *
  386. * @param hal Context of the HAL layer
  387. *
  388. * @return
  389. * - true Use XTAL clock
  390. * - false Use APB clock
  391. */
  392. static inline bool timer_ll_get_use_xtal(timg_dev_t *hw, timer_idx_t timer_num)
  393. {
  394. return hw->hw_timer[timer_num].config.tx_use_xtal;
  395. }
  396. #ifdef __cplusplus
  397. }
  398. #endif