ch56x_timer.c 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  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. * 2022-07-15 Emuzit first version
  9. */
  10. #include <rthw.h>
  11. #include <rtdebug.h>
  12. #include <drivers/hwtimer.h>
  13. #include "ch56x_sys.h"
  14. #include "ch56x_timer.h"
  15. #include "isr_sp.h"
  16. #if !defined(BSP_USING_TMR0) && !defined(BSP_USING_TMR1) && !defined(BSP_USING_TMR2)
  17. #error "Please define at least one TMRx"
  18. #endif
  19. struct hwtimer_device
  20. {
  21. struct rt_hwtimer_device parent;
  22. struct rt_hwtimer_info hwtimer_info;
  23. volatile struct timer_registers *reg_base;
  24. rt_hwtimer_mode_t tmode;
  25. irq_number_t irqn;
  26. char *name;
  27. };
  28. #ifdef BSP_USING_TMR0
  29. static struct hwtimer_device hwtimer_device_0 =
  30. {
  31. .hwtimer_info =
  32. {
  33. .maxfreq = 80000000,
  34. .minfreq = 80000000,
  35. .maxcnt = 0x3ffffff,
  36. .cntmode = HWTIMER_CNTMODE_UP,
  37. },
  38. .reg_base = (struct timer_registers *)TMR0_REG_BASE,
  39. .tmode = HWTIMER_MODE_PERIOD,
  40. .irqn = TMR0_IRQn,
  41. .name = "timer0",
  42. };
  43. #endif
  44. #ifdef BSP_USING_TMR1
  45. static struct hwtimer_device hwtimer_device_1 =
  46. {
  47. .hwtimer_info =
  48. {
  49. .maxfreq = 80000000,
  50. .minfreq = 80000000,
  51. .maxcnt = 0x3ffffff,
  52. .cntmode = HWTIMER_CNTMODE_UP,
  53. },
  54. .reg_base = (struct timer_registers *)TMR1_REG_BASE,
  55. .tmode = HWTIMER_MODE_PERIOD,
  56. .irqn = TMR1_IRQn,
  57. .name = "timer1",
  58. };
  59. #endif
  60. #ifdef BSP_USING_TMR2
  61. static struct hwtimer_device hwtimer_device_2 =
  62. {
  63. .hwtimer_info =
  64. {
  65. .maxfreq = 80000000,
  66. .minfreq = 80000000,
  67. .maxcnt = 0x3ffffff,
  68. .cntmode = HWTIMER_CNTMODE_UP,
  69. },
  70. .reg_base = (struct timer_registers *)TMR2_REG_BASE,
  71. .tmode = HWTIMER_MODE_PERIOD,
  72. .irqn = TMR2_IRQn,
  73. .name = "timer2",
  74. };
  75. #endif
  76. static void hwtimer_stop(struct rt_hwtimer_device *timer);
  77. static void hwtimer_init(struct rt_hwtimer_device *timer, uint32_t state)
  78. {
  79. struct hwtimer_device *hwtimer_device = (void *)timer;
  80. RT_ASSERT(hwtimer_device != RT_NULL);
  81. /* no resource processing, `state` ignored */
  82. hwtimer_stop(timer);
  83. if (hwtimer_device->irqn != TMR0_IRQn)
  84. {
  85. hwtimer_device->reg_base->CTRL_DMA.reg = 0;
  86. }
  87. }
  88. static rt_err_t hwtimer_start(struct rt_hwtimer_device *timer, uint32_t cnt, rt_hwtimer_mode_t mode)
  89. {
  90. struct hwtimer_device *hwtimer_device = (void *)timer;
  91. volatile struct timer_registers *txreg;
  92. RT_ASSERT(hwtimer_device != RT_NULL);
  93. /* hwtimer_device->tmode may be different from timer->mode.
  94. * For multi-cycle ONESHOT, tmode is set to PERIOD at hwtimer_start.
  95. */
  96. hwtimer_device->tmode = mode;
  97. sys_clk_off_by_irqn(hwtimer_device->irqn, SYS_SLP_CLK_ON);
  98. txreg = hwtimer_device->reg_base;
  99. txreg->CNT_END = cnt;
  100. txreg->CTRL_MOD.reg = RB_TMR_ALL_CLEAR;
  101. txreg->CTRL_MOD.reg = RB_TMR_COUNT_EN;
  102. txreg->INTER_EN.cyc_end = 1;
  103. rt_hw_interrupt_umask(hwtimer_device->irqn);
  104. return RT_EOK;
  105. }
  106. static void hwtimer_stop(struct rt_hwtimer_device *timer)
  107. {
  108. struct hwtimer_device *hwtimer_device = (void *)timer;
  109. volatile struct timer_registers *txreg;
  110. RT_ASSERT(hwtimer_device != RT_NULL);
  111. rt_hw_interrupt_mask(hwtimer_device->irqn);
  112. /* note: RB_TMR_COUNT_EN cleared */
  113. txreg = hwtimer_device->reg_base;
  114. txreg->CTRL_MOD.reg = RB_TMR_ALL_CLEAR;
  115. txreg->INTER_EN.reg = 0;
  116. sys_clk_off_by_irqn(hwtimer_device->irqn, SYS_SLP_CLK_OFF);
  117. }
  118. static uint32_t hwtimer_count_get(struct rt_hwtimer_device *timer)
  119. {
  120. struct hwtimer_device *hwtimer_device = (void *)timer;
  121. RT_ASSERT(hwtimer_device != RT_NULL);
  122. return hwtimer_device->reg_base->COUNT;
  123. }
  124. static rt_err_t hwtimer_control(
  125. struct rt_hwtimer_device *timer, uint32_t cmd, void *args)
  126. {
  127. struct hwtimer_device *hwtimer_device = (void *)timer;
  128. rt_err_t result = RT_EOK;
  129. RT_ASSERT(hwtimer_device != RT_NULL);
  130. switch (cmd)
  131. {
  132. case HWTIMER_CTRL_FREQ_SET:
  133. /* clocking for ch56x timers are fixed to Fsys */
  134. if (args == RT_NULL || *(uint32_t *)args != timer->info->minfreq)
  135. {
  136. result = -RT_EINVAL;
  137. }
  138. break;
  139. case HWTIMER_CTRL_STOP:
  140. case HWTIMER_CTRL_INFO_GET:
  141. case HWTIMER_CTRL_MODE_SET:
  142. default:
  143. result = -RT_ENOSYS;
  144. }
  145. return result;
  146. }
  147. static const struct rt_hwtimer_ops hwtimer_ops =
  148. {
  149. .init = hwtimer_init,
  150. .start = hwtimer_start,
  151. .stop = hwtimer_stop,
  152. .count_get = hwtimer_count_get,
  153. .control = hwtimer_control,
  154. };
  155. static int rt_hw_hwtimer_init(void)
  156. {
  157. struct hwtimer_device *devices[3];
  158. uint32_t Fsys = sys_hclk_get();
  159. int n = 0;
  160. #ifdef BSP_USING_TMR2
  161. devices[n++] = &hwtimer_device_2;
  162. #endif
  163. #ifdef BSP_USING_TMR1
  164. devices[n++] = &hwtimer_device_1;
  165. #endif
  166. #ifdef BSP_USING_TMR0
  167. devices[n++] = &hwtimer_device_0;
  168. #endif
  169. while (--n >= 0)
  170. {
  171. struct hwtimer_device *hwtimer_device = devices[n];
  172. /* counting frequency is fixed to Fsys */
  173. hwtimer_device->hwtimer_info.maxfreq = Fsys;
  174. hwtimer_device->hwtimer_info.minfreq = Fsys;
  175. hwtimer_device->parent.info = &hwtimer_device->hwtimer_info;
  176. hwtimer_device->parent.ops = &hwtimer_ops;
  177. rt_device_hwtimer_register(
  178. &hwtimer_device->parent, hwtimer_device->name, RT_NULL);
  179. }
  180. return RT_EOK;
  181. }
  182. INIT_DEVICE_EXPORT(rt_hw_hwtimer_init);
  183. static void _hwtimer_isr_common(struct hwtimer_device *hwtimer_device)
  184. {
  185. volatile struct timer_registers *txreg = hwtimer_device->reg_base;
  186. if (txreg->INT_FLAG.cyc_end)
  187. {
  188. if (hwtimer_device->tmode == HWTIMER_MODE_ONESHOT)
  189. {
  190. /* disable timer to emulate oneshot */
  191. txreg->CTRL_MOD.reg = 0;
  192. }
  193. rt_device_hwtimer_isr(&hwtimer_device->parent);
  194. txreg->INT_FLAG.cyc_end = 1;
  195. }
  196. }
  197. #ifdef BSP_USING_TMR0
  198. void tmr0_irq_handler(void) __attribute__((interrupt()));
  199. void tmr0_irq_handler(void)
  200. {
  201. isr_sp_enter();
  202. rt_interrupt_enter();
  203. _hwtimer_isr_common(&hwtimer_device_0);
  204. rt_interrupt_leave();
  205. isr_sp_leave();
  206. }
  207. #endif
  208. #ifdef BSP_USING_TMR1
  209. void tmr1_irq_handler(void) __attribute__((interrupt()));
  210. void tmr1_irq_handler(void)
  211. {
  212. isr_sp_enter();
  213. rt_interrupt_enter();
  214. _hwtimer_isr_common(&hwtimer_device_1);
  215. rt_interrupt_leave();
  216. isr_sp_leave();
  217. }
  218. #endif
  219. #ifdef BSP_USING_TMR2
  220. void tmr2_irq_handler(void) __attribute__((interrupt()));
  221. void tmr2_irq_handler(void)
  222. {
  223. isr_sp_enter();
  224. rt_interrupt_enter();
  225. _hwtimer_isr_common(&hwtimer_device_2);
  226. rt_interrupt_leave();
  227. isr_sp_leave();
  228. }
  229. #endif