drv_hwtimer.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. /*
  2. * Copyright (c) 2006-2023, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2023-04-01 wcx1024979076 first version
  9. */
  10. #include "drv_hwtimer.h"
  11. #include <rtthread.h>
  12. #include <rtdevice.h>
  13. #ifdef BSP_USING_HWTIMER
  14. #define DBG_LEVEL DBG_LOG
  15. #include <rtdbg.h>
  16. #define LOG_TAG "DRV.HWTIMER"
  17. typedef struct _gptimer
  18. {
  19. const char *name;
  20. rt_hwtimer_t timer;
  21. struct bflb_device_s *bflb_timer;
  22. } _gptimer_t;
  23. static void _hwtimer_init(rt_hwtimer_t *timer, rt_uint32_t state);
  24. static rt_err_t _hwtimer_start(rt_hwtimer_t *timer, rt_uint32_t cnt, rt_hwtimer_mode_t mode);
  25. static void _hwtimer_stop(rt_hwtimer_t *timer);
  26. static rt_uint32_t _hwtimer_count_get(rt_hwtimer_t *timer);
  27. static rt_err_t _hwtimer_control(rt_hwtimer_t *timer, rt_uint32_t cmd, void *args);
  28. static void _hwtmr_isr(_gptimer_t *gptmr);
  29. static const struct rt_hwtimer_ops _hwtimer_ops = {
  30. .init = _hwtimer_init,
  31. .start = _hwtimer_start,
  32. .stop = _hwtimer_stop,
  33. .count_get = _hwtimer_count_get,
  34. .control = _hwtimer_control
  35. };
  36. static const struct rt_hwtimer_info _hwtimer_info = {
  37. .maxfreq = 1000000UL,
  38. .minfreq = 1000000UL,
  39. .maxcnt = 0xFFFFFFFFUL,
  40. .cntmode = HWTIMER_MODE_PERIOD
  41. };
  42. #ifdef BSP_USING_TIMER0
  43. static _gptimer_t timer0 = {.name = "timer0"};
  44. #endif /* BSP_USING_TIMER0 */
  45. #ifdef BSP_USING_TIMER1
  46. static _gptimer_t timer1 = {.name = "timer1" };
  47. #endif /* BSP_USING_TIMER1 */
  48. static _gptimer_t *s_gptimers[] = {
  49. #ifdef BSP_USING_TIMER0
  50. &timer0,
  51. #endif /* BSP_USING_TIMER0 */
  52. #ifdef BSP_USING_TIMER1
  53. &timer1,
  54. #endif /* BSP_USING_TIMER1 */
  55. };
  56. #ifdef BSP_USING_TIMER0
  57. void timer0_isr(int irq, void *arg)
  58. {
  59. _hwtmr_isr(&timer0);
  60. }
  61. #endif /* BSP_USING_TIMER0 */
  62. #ifdef BSP_USING_TIMER1
  63. void timer1_isr(int irq, void *arg)
  64. {
  65. _hwtmr_isr(&timer1);
  66. }
  67. #endif /* BSP_USING_TIMER1 */
  68. static void _hwtmr_isr(_gptimer_t *timer)
  69. {
  70. bool hwtmr_stat = bflb_timer_get_compint_status(timer->bflb_timer, TIMER_COMP_ID_0);
  71. if (hwtmr_stat)
  72. {
  73. rt_device_hwtimer_isr(&timer->timer);
  74. bflb_timer_compint_clear(timer->bflb_timer, TIMER_COMP_ID_0);
  75. }
  76. }
  77. static void _hwtimer_init(rt_hwtimer_t *timer, rt_uint32_t state)
  78. {
  79. _gptimer_t *_gptmr = (_gptimer_t*)timer->parent.user_data;
  80. struct bflb_timer_config_s cfg;
  81. cfg.counter_mode = TIMER_COUNTER_MODE_PROLOAD;
  82. cfg.clock_source = TIMER_CLKSRC_XTAL;
  83. cfg.clock_div = 40;
  84. cfg.trigger_comp_id = TIMER_COMP_ID_0;
  85. cfg.comp0_val = 0;
  86. cfg.comp1_val = 0;
  87. cfg.comp2_val = 0;
  88. cfg.preload_val = 0;
  89. bflb_timer_init(_gptmr->bflb_timer, &cfg);
  90. }
  91. static rt_err_t _hwtimer_start(rt_hwtimer_t *timer, rt_uint32_t cnt, rt_hwtimer_mode_t mode)
  92. {
  93. _gptimer_t *_gptmr = (_gptimer_t*) timer->parent.user_data;
  94. struct bflb_timer_config_s cfg;
  95. if(mode == HWTIMER_MODE_ONESHOT)
  96. cfg.counter_mode = TIMER_COUNTER_MODE_UP;
  97. else
  98. cfg.counter_mode = TIMER_COUNTER_MODE_PROLOAD;
  99. cfg.clock_source = TIMER_CLKSRC_XTAL;
  100. cfg.clock_div = 40;
  101. cfg.trigger_comp_id = TIMER_COMP_ID_0;
  102. cfg.comp0_val = cnt;
  103. cfg.comp1_val = cnt;
  104. cfg.comp2_val = cnt;
  105. cfg.preload_val = 0;
  106. bflb_timer_init(_gptmr->bflb_timer, &cfg);
  107. bflb_irq_enable(_gptmr->bflb_timer->irq_num);
  108. bflb_timer_start(_gptmr->bflb_timer);
  109. return RT_EOK;
  110. }
  111. static void _hwtimer_stop(rt_hwtimer_t *timer)
  112. {
  113. _gptimer_t *_gptmr = (_gptimer_t*)timer->parent.user_data;
  114. bflb_timer_stop(_gptmr->bflb_timer);
  115. }
  116. static rt_uint32_t _hwtimer_count_get(rt_hwtimer_t *timer)
  117. {
  118. _gptimer_t *_gptmr = (_gptimer_t*)timer->parent.user_data;
  119. rt_uint32_t current_cnt = bflb_timer_get_countervalue(_gptmr->bflb_timer);
  120. return current_cnt;
  121. }
  122. static rt_err_t _hwtimer_control(rt_hwtimer_t *timer, rt_uint32_t cmd, void *args)
  123. {
  124. rt_err_t err = RT_EOK;
  125. _gptimer_t *_gptmr = (_gptimer_t*) timer->parent.user_data;
  126. switch (cmd)
  127. {
  128. case HWTIMER_CTRL_FREQ_SET:
  129. err = -RT_ERROR;
  130. break;
  131. case HWTIMER_CTRL_INFO_GET:
  132. *(rt_hwtimer_t*)args = _gptmr->timer;
  133. break;
  134. case HWTIMER_CTRL_MODE_SET:
  135. _gptmr->timer.mode = *(rt_uint32_t*)args;
  136. break;
  137. case HWTIMER_CTRL_STOP:
  138. bflb_timer_stop(_gptmr->bflb_timer);
  139. break;
  140. }
  141. return err;
  142. }
  143. int rt_hw_hwtimer_init(void)
  144. {
  145. int ret = RT_EOK;
  146. for (uint32_t i = 0; i < sizeof(s_gptimers) / sizeof(s_gptimers[0]); i++)
  147. {
  148. s_gptimers[i]->timer.info = &_hwtimer_info;
  149. s_gptimers[i]->timer.ops = &_hwtimer_ops;
  150. s_gptimers[i]->bflb_timer = bflb_device_get_by_name(s_gptimers[i]->name);
  151. ret = rt_device_hwtimer_register(&s_gptimers[i]->timer, s_gptimers[i]->name, s_gptimers[i]);
  152. if (ret != RT_EOK)
  153. {
  154. LOG_E("%s register failed", s_gptimers[i]->name);
  155. }
  156. }
  157. #ifdef BSP_USING_TIMER0
  158. bflb_irq_attach(bflb_device_get_by_name("timer0")->irq_num, timer0_isr, NULL);
  159. #endif /* BSP_USING_TIMER0 */
  160. #ifdef BSP_USING_TIMER1
  161. bflb_irq_attach(bflb_device_get_by_name("timer1")->irq_num, timer1_isr, NULL);
  162. #endif /* BSP_USING_TIMER1 */
  163. return ret;
  164. }
  165. INIT_DEVICE_EXPORT(rt_hw_hwtimer_init);
  166. #endif /* BSP_USING_HWTIMER */