drv_timer.c 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  1. /**************************************************************************//**
  2. *
  3. * @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0
  6. *
  7. * Change Logs:
  8. * Date Author Notes
  9. * 2022-3-15 Wayne First version
  10. *
  11. ******************************************************************************/
  12. #include <rtconfig.h>
  13. #if defined(BSP_USING_TIMER) && defined(RT_USING_HWTIMER)
  14. #include <rtdevice.h>
  15. #include "NuMicro.h"
  16. /* Private define ---------------------------------------------------------------*/
  17. #define NU_TIMER_DEVICE(timer) (nu_timer_t)(timer)
  18. enum
  19. {
  20. TIMER_START = -1,
  21. #if defined(BSP_USING_TIMER0)
  22. TIMER0_IDX,
  23. #endif
  24. #if defined(BSP_USING_TIMER1)
  25. TIMER1_IDX,
  26. #endif
  27. #if defined(BSP_USING_TIMER2)
  28. TIMER2_IDX,
  29. #endif
  30. #if defined(BSP_USING_TIMER3)
  31. TIMER3_IDX,
  32. #endif
  33. TIMER_CNT
  34. };
  35. /* Private typedef --------------------------------------------------------------*/
  36. struct nu_timer
  37. {
  38. rt_hwtimer_t parent;
  39. char *name;
  40. TIMER_T *base;
  41. IRQn_Type irqn;
  42. uint32_t rstidx;
  43. uint32_t modid;
  44. };
  45. typedef struct nu_timer *nu_timer_t;
  46. /* Private functions ------------------------------------------------------------*/
  47. static void nu_timer_init(rt_hwtimer_t *timer, rt_uint32_t state);
  48. static rt_err_t nu_timer_start(rt_hwtimer_t *timer, rt_uint32_t cnt, rt_hwtimer_mode_t opmode);
  49. static void nu_timer_stop(rt_hwtimer_t *timer);
  50. static rt_uint32_t nu_timer_count_get(rt_hwtimer_t *timer);
  51. static rt_err_t nu_timer_control(rt_hwtimer_t *timer, rt_uint32_t cmd, void *args);
  52. /* Public functions -------------------------------------------------------------*/
  53. /* Private variables ------------------------------------------------------------*/
  54. static struct nu_timer nu_timer_arr [] =
  55. {
  56. #if defined(BSP_USING_TIMER0)
  57. { .name = "timer0", .base = TIMER0, .irqn = TMR0_IRQn, .rstidx = TMR0_RST, .modid = TMR0_MODULE },
  58. #endif
  59. #if defined(BSP_USING_TIMER1)
  60. { .name = "timer1", .base = TIMER1, .irqn = TMR1_IRQn, .rstidx = TMR1_RST, .modid = TMR1_MODULE },
  61. #endif
  62. #if defined(BSP_USING_TIMER2)
  63. { .name = "timer2", .base = TIMER2, .irqn = TMR2_IRQn, .rstidx = TMR2_RST, .modid = TMR2_MODULE },
  64. #endif
  65. #if defined(BSP_USING_TIMER3)
  66. { .name = "timer3", .base = TIMER3, .irqn = TMR3_IRQn, .rstidx = TMR3_RST, .modid = TMR3_MODULE },
  67. #endif
  68. };
  69. static struct rt_hwtimer_info nu_timer_info =
  70. {
  71. 12000000, /* maximum count frequency */
  72. 46875, /* minimum count frequency */
  73. 0xFFFFFF, /* the maximum counter value */
  74. HWTIMER_CNTMODE_UP, /* Increment or Decreasing count mode */
  75. };
  76. static struct rt_hwtimer_ops nu_timer_ops =
  77. {
  78. nu_timer_init,
  79. nu_timer_start,
  80. nu_timer_stop,
  81. nu_timer_count_get,
  82. nu_timer_control
  83. };
  84. /* Functions define ------------------------------------------------------------*/
  85. static void nu_timer_init(rt_hwtimer_t *timer, rt_uint32_t state)
  86. {
  87. nu_timer_t psNuTmr = NU_TIMER_DEVICE(timer);
  88. RT_ASSERT(psNuTmr != RT_NULL);
  89. if (1 == state)
  90. {
  91. uint32_t timer_clk;
  92. struct rt_hwtimer_info *info = &nu_timer_info;
  93. timer_clk = TIMER_GetModuleClock(psNuTmr->base);
  94. info->maxfreq = timer_clk;
  95. info->minfreq = timer_clk / 256;
  96. TIMER_Open(psNuTmr->base, TIMER_ONESHOT_MODE, 1);
  97. TIMER_EnableInt(psNuTmr->base);
  98. NVIC_EnableIRQ(psNuTmr->irqn);
  99. }
  100. else
  101. {
  102. NVIC_DisableIRQ(psNuTmr->irqn);
  103. TIMER_DisableInt(psNuTmr->base);
  104. TIMER_Close(psNuTmr->base);
  105. }
  106. }
  107. static rt_err_t nu_timer_start(rt_hwtimer_t *timer, rt_uint32_t cnt, rt_hwtimer_mode_t opmode)
  108. {
  109. rt_err_t ret = -RT_EINVAL;
  110. rt_uint32_t u32OpMode;
  111. nu_timer_t psNuTmr = NU_TIMER_DEVICE(timer);
  112. RT_ASSERT(psNuTmr != RT_NULL);
  113. if (cnt <= 1 || cnt > 0xFFFFFF)
  114. {
  115. goto exit_nu_timer_start;
  116. }
  117. switch (opmode)
  118. {
  119. case HWTIMER_MODE_PERIOD:
  120. u32OpMode = TIMER_PERIODIC_MODE;
  121. break;
  122. case HWTIMER_MODE_ONESHOT:
  123. u32OpMode = TIMER_ONESHOT_MODE;
  124. break;
  125. default:
  126. goto exit_nu_timer_start;
  127. }
  128. TIMER_SET_CMP_VALUE(psNuTmr->base, cnt);
  129. TIMER_SET_OPMODE(psNuTmr->base, u32OpMode);
  130. TIMER_EnableInt(psNuTmr->base);
  131. NVIC_EnableIRQ(psNuTmr->irqn);
  132. TIMER_Start(psNuTmr->base);
  133. ret = RT_EOK;
  134. exit_nu_timer_start:
  135. return -(ret);
  136. }
  137. static void nu_timer_stop(rt_hwtimer_t *timer)
  138. {
  139. nu_timer_t psNuTmr = NU_TIMER_DEVICE(timer);
  140. RT_ASSERT(psNuTmr != RT_NULL);
  141. NVIC_DisableIRQ(psNuTmr->irqn);
  142. TIMER_DisableInt(psNuTmr->base);
  143. TIMER_Stop(psNuTmr->base);
  144. TIMER_ResetCounter(psNuTmr->base);
  145. }
  146. static rt_uint32_t nu_timer_count_get(rt_hwtimer_t *timer)
  147. {
  148. nu_timer_t psNuTmr = NU_TIMER_DEVICE(timer);
  149. RT_ASSERT(psNuTmr != RT_NULL);
  150. return TIMER_GetCounter(psNuTmr->base);
  151. }
  152. static rt_err_t nu_timer_control(rt_hwtimer_t *timer, rt_uint32_t cmd, void *args)
  153. {
  154. rt_err_t ret = RT_EOK;
  155. nu_timer_t psNuTmr = NU_TIMER_DEVICE(timer);
  156. RT_ASSERT(psNuTmr != RT_NULL);
  157. switch (cmd)
  158. {
  159. case HWTIMER_CTRL_FREQ_SET:
  160. {
  161. uint32_t clk;
  162. uint32_t pre;
  163. clk = TIMER_GetModuleClock(psNuTmr->base);
  164. pre = clk / *((uint32_t *)args) - 1;
  165. TIMER_SET_PRESCALE_VALUE(psNuTmr->base, pre);
  166. *((uint32_t *)args) = clk / (pre + 1) ;
  167. }
  168. break;
  169. case HWTIMER_CTRL_STOP:
  170. TIMER_Stop(psNuTmr->base);
  171. break;
  172. default:
  173. ret = -RT_EINVAL;
  174. break;
  175. }
  176. return -(ret);
  177. }
  178. /**
  179. * All UART interrupt service routine
  180. */
  181. static void nu_timer_isr(nu_timer_t psNuTmr)
  182. {
  183. RT_ASSERT(psNuTmr != RT_NULL);
  184. if (TIMER_GetIntFlag(psNuTmr->base))
  185. {
  186. TIMER_ClearIntFlag(psNuTmr->base);
  187. rt_device_hwtimer_isr(&psNuTmr->parent);
  188. }
  189. }
  190. int rt_hw_timer_init(void)
  191. {
  192. int i;
  193. rt_err_t ret = RT_EOK;
  194. for (i = (TIMER_START + 1); i < TIMER_CNT; i++)
  195. {
  196. CLK_EnableModuleClock(nu_timer_arr[i].modid);
  197. SYS_ResetModule(nu_timer_arr[i].rstidx);
  198. /* Register Timer information. */
  199. nu_timer_arr[i].parent.info = &nu_timer_info;
  200. /* Register Timer operation. */
  201. nu_timer_arr[i].parent.ops = &nu_timer_ops;
  202. /* Register RT hwtimer device. */
  203. ret = rt_device_hwtimer_register(&nu_timer_arr[i].parent, nu_timer_arr[i].name, &nu_timer_arr[i]);
  204. RT_ASSERT(ret == RT_EOK);
  205. }
  206. return 0;
  207. }
  208. INIT_BOARD_EXPORT(rt_hw_timer_init);
  209. #if defined(BSP_USING_TIMER0)
  210. void TMR0_IRQHandler(void)
  211. {
  212. rt_interrupt_enter();
  213. nu_timer_isr((void *)&nu_timer_arr[TIMER0_IDX]);
  214. rt_interrupt_leave();
  215. }
  216. #endif
  217. #if defined(BSP_USING_TIMER1)
  218. void TMR1_IRQHandler(void)
  219. {
  220. rt_interrupt_enter();
  221. nu_timer_isr((void *)&nu_timer_arr[TIMER1_IDX]);
  222. rt_interrupt_leave();
  223. }
  224. #endif
  225. #if defined(BSP_USING_TIMER2)
  226. void TMR2_IRQHandler(void)
  227. {
  228. rt_interrupt_enter();
  229. nu_timer_isr((void *)&nu_timer_arr[TIMER2_IDX]);
  230. rt_interrupt_leave();
  231. }
  232. #endif
  233. #if defined(BSP_USING_TIMER3)
  234. void TMR3_IRQHandler(void)
  235. {
  236. rt_interrupt_enter();
  237. nu_timer_isr((void *)&nu_timer_arr[TIMER3_IDX]);
  238. rt_interrupt_leave();
  239. }
  240. #endif
  241. #endif //#if (defined(BSP_USING_TIMER) && defined(RT_USING_HWTIMER))