timer_ll.h 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550
  1. // Copyright 2015-2019 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/timer_types.h"
  22. #include "soc/timer_periph.h"
  23. _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");
  24. _Static_assert(TIMER_INTR_T1 == TIMG_T1_INT_CLR, "Add mapping to LL interrupt handling, since it's no longer naturally compatible with the timer_intr_t");
  25. _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");
  26. // Get timer group instance with giving group number
  27. #define TIMER_LL_GET_HW(num) ((num == 0) ? (&TIMERG0) : (&TIMERG1))
  28. /**
  29. * @brief Set timer clock prescale value
  30. *
  31. * @param hw Beginning address of the peripheral registers.
  32. * @param timer_num The timer number
  33. * @param divider Prescale value (0 and 1 are not valid)
  34. *
  35. * @return None
  36. */
  37. static inline void timer_ll_set_divider(timg_dev_t *hw, timer_idx_t timer_num, uint32_t divider)
  38. {
  39. // refer to TRM 18.2.1
  40. if (divider == 65536) {
  41. divider = 0;
  42. } else if (divider == 1) {
  43. divider = 2;
  44. }
  45. int timer_en = hw->hw_timer[timer_num].config.enable;
  46. hw->hw_timer[timer_num].config.enable = 0;
  47. hw->hw_timer[timer_num].config.divider = divider;
  48. hw->hw_timer[timer_num].config.enable = timer_en;
  49. }
  50. /**
  51. * @brief Get timer clock prescale value
  52. *
  53. * @param hw Beginning address of the peripheral registers.
  54. * @param timer_num The timer number
  55. * @param divider Pointer to accept the prescale value
  56. *
  57. * @return None
  58. */
  59. static inline void timer_ll_get_divider(timg_dev_t *hw, timer_idx_t timer_num, uint32_t *divider)
  60. {
  61. uint32_t d = hw->hw_timer[timer_num].config.divider;
  62. if (d == 0) {
  63. d = 65536;
  64. } else if (d == 1) {
  65. d = 2;
  66. }
  67. *divider = d;
  68. }
  69. /**
  70. * @brief Load counter value into time-base counter
  71. *
  72. * @param hw Beginning address of the peripheral registers.
  73. * @param timer_num The timer number
  74. * @param load_val Counter value
  75. *
  76. * @return None
  77. */
  78. static inline void timer_ll_set_counter_value(timg_dev_t *hw, timer_idx_t timer_num, uint64_t load_val)
  79. {
  80. hw->hw_timer[timer_num].load_high = (uint32_t) (load_val >> 32);
  81. hw->hw_timer[timer_num].load_low = (uint32_t) load_val;
  82. hw->hw_timer[timer_num].reload = 1;
  83. }
  84. /**
  85. * @brief Get counter value from time-base counter
  86. *
  87. * @param hw Beginning address of the peripheral registers.
  88. * @param timer_num The timer number
  89. * @param timer_val Pointer to accept the counter value
  90. *
  91. * @return None
  92. */
  93. FORCE_INLINE_ATTR void timer_ll_get_counter_value(timg_dev_t *hw, timer_idx_t timer_num, uint64_t *timer_val)
  94. {
  95. hw->hw_timer[timer_num].update = 1;
  96. *timer_val = ((uint64_t) hw->hw_timer[timer_num].cnt_high << 32) | (hw->hw_timer[timer_num].cnt_low);
  97. }
  98. /**
  99. * @brief Set counter mode, include increment mode and decrement mode.
  100. *
  101. * @param hw Beginning address of the peripheral registers.
  102. * @param timer_num The timer number
  103. * @param increase_en True to increment mode, fasle to decrement mode
  104. *
  105. * @return None
  106. */
  107. static inline void timer_ll_set_counter_increase(timg_dev_t *hw, timer_idx_t timer_num, bool increase_en)
  108. {
  109. hw->hw_timer[timer_num].config.increase = increase_en;
  110. }
  111. /**
  112. * @brief Get counter mode, include increment mode and decrement mode.
  113. *
  114. * @param hw Beginning address of the peripheral registers.
  115. * @param timer_num The timer number
  116. *
  117. * @return
  118. * - true Increment mode
  119. * - false Decrement mode
  120. */
  121. static inline bool timer_ll_get_counter_increase(timg_dev_t *hw, timer_idx_t timer_num)
  122. {
  123. return hw->hw_timer[timer_num].config.increase;
  124. }
  125. /**
  126. * @brief Set counter status, enable or disable counter.
  127. *
  128. * @param hw Beginning address of the peripheral registers.
  129. * @param timer_num The timer number
  130. * @param counter_en True to enable counter, false to disable counter
  131. *
  132. * @return None
  133. */
  134. FORCE_INLINE_ATTR void timer_ll_set_counter_enable(timg_dev_t *hw, timer_idx_t timer_num, bool counter_en)
  135. {
  136. hw->hw_timer[timer_num].config.enable = counter_en;
  137. }
  138. /**
  139. * @brief Get counter status.
  140. *
  141. * @param hw Beginning address of the peripheral registers.
  142. * @param timer_num The timer number
  143. *
  144. * @return
  145. * - true Enable counter
  146. * - false Disable conuter
  147. */
  148. static inline bool timer_ll_get_counter_enable(timg_dev_t *hw, timer_idx_t timer_num)
  149. {
  150. return hw->hw_timer[timer_num].config.enable;
  151. }
  152. /**
  153. * @brief Set auto reload mode.
  154. *
  155. * @param hw Beginning address of the peripheral registers.
  156. * @param timer_num The timer number
  157. * @param auto_reload_en True to enable auto reload mode, flase to disable auto reload mode
  158. *
  159. * @return None
  160. */
  161. static inline void timer_ll_set_auto_reload(timg_dev_t *hw, timer_idx_t timer_num, bool auto_reload_en)
  162. {
  163. hw->hw_timer[timer_num].config.autoreload = auto_reload_en;
  164. }
  165. /**
  166. * @brief Get auto reload mode.
  167. *
  168. * @param hw Beginning address of the peripheral registers.
  169. * @param timer_num The timer number
  170. *
  171. * @return
  172. * - true Enable auto reload mode
  173. * - false Disable auto reload mode
  174. */
  175. FORCE_INLINE_ATTR bool timer_ll_get_auto_reload(timg_dev_t *hw, timer_idx_t timer_num)
  176. {
  177. return hw->hw_timer[timer_num].config.autoreload;
  178. }
  179. /**
  180. * @brief Set the counter value to trigger the alarm.
  181. *
  182. * @param hw Beginning address of the peripheral registers.
  183. * @param timer_num The timer number
  184. * @param alarm_value Counter value to trigger the alarm
  185. *
  186. * @return None
  187. */
  188. FORCE_INLINE_ATTR void timer_ll_set_alarm_value(timg_dev_t *hw, timer_idx_t timer_num, uint64_t alarm_value)
  189. {
  190. hw->hw_timer[timer_num].alarm_high = (uint32_t) (alarm_value >> 32);
  191. hw->hw_timer[timer_num].alarm_low = (uint32_t) alarm_value;
  192. }
  193. /**
  194. * @brief Get the counter value to trigger the alarm.
  195. *
  196. * @param hw Beginning address of the peripheral registers.
  197. * @param timer_num The timer number
  198. * @param alarm_value Pointer to accept the counter value to trigger the alarm
  199. *
  200. * @return None
  201. */
  202. static inline void timer_ll_get_alarm_value(timg_dev_t *hw, timer_idx_t timer_num, uint64_t *alarm_value)
  203. {
  204. *alarm_value = ((uint64_t) hw->hw_timer[timer_num].alarm_high << 32) | (hw->hw_timer[timer_num].alarm_low);
  205. }
  206. /**
  207. * @brief Set the alarm status, enable or disable the alarm.
  208. *
  209. * @param hw Beginning address of the peripheral registers.
  210. * @param timer_num The timer number
  211. * @param alarm_en True to enable alarm, false to disable alarm
  212. *
  213. * @return None
  214. */
  215. FORCE_INLINE_ATTR void timer_ll_set_alarm_enable(timg_dev_t *hw, timer_idx_t timer_num, bool alarm_en)
  216. {
  217. hw->hw_timer[timer_num].config.alarm_en = alarm_en;
  218. }
  219. /**
  220. * @brief Get the alarm status.
  221. *
  222. * @param hw Beginning address of the peripheral registers.
  223. * @param timer_num The timer number
  224. *
  225. * @return
  226. * - true Enable alarm
  227. * - false Disable alarm
  228. */
  229. static inline bool timer_ll_get_alarm_enable(timg_dev_t *hw, timer_idx_t timer_num)
  230. {
  231. return hw->hw_timer[timer_num].config.alarm_en;
  232. }
  233. /**
  234. * @brief Enable timer interrupt.
  235. *
  236. * @param hw Beginning address of the peripheral registers.
  237. * @param timer_num The timer number
  238. *
  239. * @return None
  240. */
  241. FORCE_INLINE_ATTR void timer_ll_intr_enable(timg_dev_t *hw, timer_idx_t timer_num)
  242. {
  243. hw->int_ena.val |= BIT(timer_num);
  244. hw->hw_timer[timer_num].config.level_int_en = 1;
  245. }
  246. /**
  247. * @brief Disable timer interrupt.
  248. *
  249. * @param hw Beginning address of the peripheral registers.
  250. * @param timer_num The timer number
  251. *
  252. * @return None
  253. */
  254. FORCE_INLINE_ATTR void timer_ll_intr_disable(timg_dev_t *hw, timer_idx_t timer_num)
  255. {
  256. hw->int_ena.val &= (~BIT(timer_num));
  257. hw->hw_timer[timer_num].config.level_int_en = 0;
  258. }
  259. /**
  260. * @brief Disable timer interrupt.
  261. *
  262. * @param hw Beginning address of the peripheral registers.
  263. * @param timer_num The timer number
  264. *
  265. * @return None
  266. */
  267. FORCE_INLINE_ATTR void timer_ll_clear_intr_status(timg_dev_t *hw, timer_idx_t timer_num)
  268. {
  269. hw->int_clr_timers.val |= BIT(timer_num);
  270. }
  271. /**
  272. * @brief Get interrupt status.
  273. *
  274. * @param hw Beginning address of the peripheral registers.
  275. * @param intr_status Interrupt status
  276. *
  277. * @return None
  278. */
  279. FORCE_INLINE_ATTR void timer_ll_get_intr_status(timg_dev_t *hw, uint32_t *intr_status)
  280. {
  281. *intr_status = hw->int_st_timers.val;
  282. }
  283. /**
  284. * @brief Get interrupt raw status.
  285. *
  286. * @param group_num Timer group number, 0 for TIMERG0 or 1 for TIMERG1
  287. * @param intr_raw_status Interrupt raw status
  288. *
  289. * @return None
  290. */
  291. FORCE_INLINE_ATTR void timer_ll_get_intr_raw_status(timer_group_t group_num, uint32_t *intr_raw_status)
  292. {
  293. timg_dev_t *hw = TIMER_LL_GET_HW(group_num);
  294. *intr_raw_status = hw->int_raw.val;
  295. }
  296. /**
  297. * @brief Set the level interrupt status, enable or disable the level interrupt.
  298. *
  299. * @param hw Beginning address of the peripheral registers.
  300. * @param timer_num The timer number
  301. * @param level_int_en True to enable level interrupt, false to disable level interrupt
  302. *
  303. * @return None
  304. */
  305. static inline void timer_ll_set_level_int_enable(timg_dev_t *hw, timer_idx_t timer_num, bool level_int_en)
  306. {
  307. hw->hw_timer[timer_num].config.level_int_en = level_int_en;
  308. }
  309. /**
  310. * @brief Get the level interrupt status.
  311. *
  312. * @param hw Beginning address of the peripheral registers.
  313. * @param timer_num The timer number
  314. *
  315. * @return
  316. * - true Enable level interrupt
  317. * - false Disable level interrupt
  318. */
  319. static inline bool timer_ll_get_level_int_enable(timg_dev_t *hw, timer_idx_t timer_num)
  320. {
  321. return hw->hw_timer[timer_num].config.level_int_en;
  322. }
  323. /**
  324. * @brief Set the edge interrupt status, enable or disable the edge interrupt.
  325. *
  326. * @param hw Beginning address of the peripheral registers.
  327. * @param timer_num The timer number
  328. * @param edge_int_en True to enable edge interrupt, false to disable edge interrupt
  329. *
  330. * @return None
  331. */
  332. static inline void timer_ll_set_edge_int_enable(timg_dev_t *hw, timer_idx_t timer_num, bool edge_int_en)
  333. {
  334. hw->hw_timer[timer_num].config.edge_int_en = edge_int_en;
  335. }
  336. /**
  337. * @brief Get the edge interrupt status.
  338. *
  339. * @param hw Beginning address of the peripheral registers.
  340. * @param timer_num The timer number
  341. *
  342. * @return
  343. * - true Enable edge interrupt
  344. * - false Disable edge interrupt
  345. */
  346. static inline bool timer_ll_get_edge_int_enable(timg_dev_t *hw, timer_idx_t timer_num)
  347. {
  348. return hw->hw_timer[timer_num].config.edge_int_en;
  349. }
  350. /**
  351. * @brief Get interrupt status register address.
  352. *
  353. * @param hw Beginning address of the peripheral registers.
  354. *
  355. * @return Interrupt status register address
  356. */
  357. static inline uint32_t timer_ll_get_intr_status_reg(timg_dev_t *hw)
  358. {
  359. return (uint32_t) & (hw->int_st_timers.val);
  360. }
  361. static inline uint32_t timer_ll_get_intr_mask_bit(timg_dev_t *hw, timer_idx_t timer_num)
  362. {
  363. return (1U << timer_num);
  364. }
  365. /* WDT operations */
  366. /**
  367. * @brief Unlock/lock the WDT register in case of mis-operations.
  368. *
  369. * @param hw Beginning address of the peripheral registers.
  370. * @param protect true to lock, false to unlock before operations.
  371. */
  372. FORCE_INLINE_ATTR void timer_ll_wdt_set_protect(timg_dev_t* hw, bool protect)
  373. {
  374. hw->wdt_wprotect=(protect? 0: TIMG_WDT_WKEY_VALUE);
  375. }
  376. /**
  377. * @brief Initialize WDT.
  378. *
  379. * @param hw Beginning address of the peripheral registers.
  380. *
  381. * @note Call `timer_ll_wdt_set_protect` first
  382. */
  383. FORCE_INLINE_ATTR void timer_ll_wdt_init(timg_dev_t* hw)
  384. {
  385. hw->wdt_config0.sys_reset_length=7; //3.2uS
  386. hw->wdt_config0.cpu_reset_length=7; //3.2uS
  387. //currently only level interrupt is supported
  388. hw->wdt_config0.level_int_en = 1;
  389. hw->wdt_config0.edge_int_en = 0;
  390. }
  391. /**
  392. * @brief Set the WDT tick time.
  393. *
  394. * @param hw Beginning address of the peripheral registers.
  395. * @param tick_time_us Tick time.
  396. */
  397. FORCE_INLINE_ATTR void timer_ll_wdt_set_tick(timg_dev_t* hw, int tick_time_us)
  398. {
  399. hw->wdt_config1.clk_prescale=80*tick_time_us;
  400. }
  401. /**
  402. * @brief Feed the WDT.
  403. *
  404. * @param hw Beginning address of the peripheral registers.
  405. */
  406. FORCE_INLINE_ATTR void timer_ll_wdt_feed(timg_dev_t* hw)
  407. {
  408. hw->wdt_feed = 1;
  409. }
  410. /**
  411. * @brief Set the WDT timeout.
  412. *
  413. * @param hw Beginning address of the peripheral registers.
  414. * @param stage Stage number of WDT.
  415. * @param timeout_Tick tick threshold of timeout.
  416. */
  417. FORCE_INLINE_ATTR void timer_ll_wdt_set_timeout(timg_dev_t* hw, int stage, uint32_t timeout_tick)
  418. {
  419. switch (stage) {
  420. case 0:
  421. hw->wdt_config2=timeout_tick;
  422. break;
  423. case 1:
  424. hw->wdt_config3=timeout_tick;
  425. break;
  426. case 2:
  427. hw->wdt_config4=timeout_tick;
  428. break;
  429. case 3:
  430. hw->wdt_config5=timeout_tick;
  431. break;
  432. default:
  433. abort();
  434. }
  435. }
  436. _Static_assert(TIMER_WDT_OFF == TIMG_WDT_STG_SEL_OFF, "Add mapping to LL watchdog timeout behavior, since it's no longer naturally compatible with the timer_wdt_behavior_t");
  437. _Static_assert(TIMER_WDT_INT == TIMG_WDT_STG_SEL_INT, "Add mapping to LL watchdog timeout behavior, since it's no longer naturally compatible with the timer_wdt_behavior_t");
  438. _Static_assert(TIMER_WDT_RESET_CPU == TIMG_WDT_STG_SEL_RESET_CPU, "Add mapping to LL watchdog timeout behavior, since it's no longer naturally compatible with the timer_wdt_behavior_t");
  439. _Static_assert(TIMER_WDT_RESET_SYSTEM == TIMG_WDT_STG_SEL_RESET_SYSTEM, "Add mapping to LL watchdog timeout behavior, since it's no longer naturally compatible with the timer_wdt_behavior_t");
  440. /**
  441. * @brief Set the WDT timeout behavior.
  442. *
  443. * @param hw Beginning address of the peripheral registers.
  444. * @param stage Stage number of WDT.
  445. * @param behavior Behavior of WDT, please see enum timer_wdt_behavior_t.
  446. */
  447. FORCE_INLINE_ATTR void timer_ll_wdt_set_timeout_behavior(timg_dev_t* hw, int stage, timer_wdt_behavior_t behavior)
  448. {
  449. switch (stage) {
  450. case 0:
  451. hw->wdt_config0.stg0 = behavior;
  452. break;
  453. case 1:
  454. hw->wdt_config0.stg1 = behavior;
  455. break;
  456. case 2:
  457. hw->wdt_config0.stg2 = behavior;
  458. break;
  459. case 3:
  460. hw->wdt_config0.stg3 = behavior;
  461. break;
  462. default:
  463. abort();
  464. }
  465. }
  466. /**
  467. * @brief Enable/Disable the WDT enable.
  468. *
  469. * @param hw Beginning address of the peripheral registers.
  470. * @param enable True to enable WDT, false to disable WDT.
  471. */
  472. FORCE_INLINE_ATTR void timer_ll_wdt_set_enable(timg_dev_t* hw, bool enable)
  473. {
  474. hw->wdt_config0.en = enable;
  475. }
  476. /**
  477. * @brief Enable/Disable the WDT flashboot mode.
  478. *
  479. * @param hw Beginning address of the peripheral registers.
  480. * @param enable True to enable WDT flashboot mode, false to disable WDT flashboot mode.
  481. */
  482. FORCE_INLINE_ATTR void timer_ll_wdt_flashboot_en(timg_dev_t* hw, bool enable)
  483. {
  484. hw->wdt_config0.flashboot_mod_en = enable;
  485. }
  486. /**
  487. * @brief Clear the WDT interrupt status.
  488. *
  489. * @param hw Beginning address of the peripheral registers.
  490. */
  491. FORCE_INLINE_ATTR void timer_ll_wdt_clear_intr_status(timg_dev_t* hw)
  492. {
  493. hw->int_clr_timers.wdt = 1;
  494. }
  495. /**
  496. * @brief Enable the WDT interrupt.
  497. *
  498. * @param hw Beginning address of the peripheral registers.
  499. */
  500. FORCE_INLINE_ATTR void timer_ll_wdt_enable_intr(timg_dev_t* hw)
  501. {
  502. hw->int_ena.wdt = 1;
  503. }
  504. #ifdef __cplusplus
  505. }
  506. #endif