drv_timer.c 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  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. * 2020-12-3 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. #include <drv_sys.h>
  17. #include "nu_timer.h"
  18. /* Private define ---------------------------------------------------------------*/
  19. #define NU_TIMER_DEVICE(timer) (nu_timer_t)(timer)
  20. enum
  21. {
  22. TIMER_START = -1,
  23. #if defined(BSP_USING_TIMER0)
  24. TIMER0_IDX,
  25. #endif
  26. #if defined(BSP_USING_TIMER1)
  27. TIMER1_IDX,
  28. #endif
  29. #if defined(BSP_USING_TIMER2)
  30. TIMER2_IDX,
  31. #endif
  32. #if defined(BSP_USING_TIMER3)
  33. TIMER3_IDX,
  34. #endif
  35. /* BSP_USING_TIMER4 is reserved for Systick usage. */
  36. TIMER_CNT
  37. };
  38. /* Private typedef --------------------------------------------------------------*/
  39. struct nu_timer
  40. {
  41. rt_hwtimer_t parent;
  42. char *name;
  43. uint32_t idx;
  44. IRQn_Type irqn;
  45. E_SYS_IPRST rstidx;
  46. E_SYS_IPCLK clkidx;
  47. };
  48. typedef struct nu_timer *nu_timer_t;
  49. /* Private functions ------------------------------------------------------------*/
  50. static void nu_timer_init(rt_hwtimer_t *timer, rt_uint32_t state);
  51. static rt_err_t nu_timer_start(rt_hwtimer_t *timer, rt_uint32_t cnt, rt_hwtimer_mode_t opmode);
  52. static void nu_timer_stop(rt_hwtimer_t *timer);
  53. static rt_uint32_t nu_timer_count_get(rt_hwtimer_t *timer);
  54. static rt_err_t nu_timer_control(rt_hwtimer_t *timer, rt_uint32_t cmd, void *args);
  55. /* Public functions -------------------------------------------------------------*/
  56. /* Private variables ------------------------------------------------------------*/
  57. static struct nu_timer nu_timer_arr [] =
  58. {
  59. #if defined(BSP_USING_TIMER0)
  60. {
  61. .name = "timer0",
  62. .idx = 0,
  63. .irqn = IRQ_TMR0,
  64. .rstidx = TIMER0RST,
  65. .clkidx = TIMER0CKEN,
  66. },
  67. #endif
  68. #if defined(BSP_USING_TIMER1)
  69. {
  70. .name = "timer1",
  71. .idx = 1,
  72. .irqn = IRQ_TMR1,
  73. .rstidx = TIMER1RST,
  74. .clkidx = TIMER1CKEN,
  75. },
  76. #endif
  77. #if defined(BSP_USING_TIMER2)
  78. {
  79. .name = "timer2",
  80. .idx = 2,
  81. .irqn = IRQ_TMR2,
  82. .rstidx = TIMER2RST,
  83. .clkidx = TIMER2CKEN,
  84. },
  85. #endif
  86. #if defined(BSP_USING_TIMER3)
  87. {
  88. .name = "timer3",
  89. .idx = 3,
  90. .irqn = IRQ_TMR3,
  91. .rstidx = TIMER3RST,
  92. .clkidx = TIMER3CKEN,
  93. },
  94. #endif
  95. /* BSP_USING_TIMER4 is reserved for Systick usage. */
  96. };
  97. static struct rt_hwtimer_info nu_timer_info =
  98. {
  99. 12000000, /* maximum count frequency */
  100. 46875, /* minimum count frequency */
  101. 0xFFFFFF, /* the maximum counter value */
  102. HWTIMER_CNTMODE_UP, /* Increment or Decreasing count mode */
  103. };
  104. static struct rt_hwtimer_ops nu_timer_ops =
  105. {
  106. nu_timer_init,
  107. nu_timer_start,
  108. nu_timer_stop,
  109. nu_timer_count_get,
  110. nu_timer_control
  111. };
  112. /* Functions define ------------------------------------------------------------*/
  113. static void nu_timer_init(rt_hwtimer_t *timer, rt_uint32_t state)
  114. {
  115. nu_timer_t psNuTmr = NU_TIMER_DEVICE(timer);
  116. RT_ASSERT(psNuTmr != RT_NULL);
  117. if (1 == state)
  118. {
  119. uint32_t timer_clk;
  120. struct rt_hwtimer_info *info = &nu_timer_info;
  121. timer_clk = TIMER_GetModuleClock(psNuTmr->idx);
  122. info->maxfreq = timer_clk;
  123. info->minfreq = timer_clk / 256;
  124. TIMER_Open(psNuTmr->idx, TIMER_ONESHOT_MODE, 1);
  125. TIMER_EnableInt(psNuTmr->idx);
  126. rt_hw_interrupt_umask(psNuTmr->irqn);
  127. }
  128. else
  129. {
  130. rt_hw_interrupt_mask(psNuTmr->irqn);
  131. TIMER_DisableInt(psNuTmr->idx);
  132. TIMER_Close(psNuTmr->idx);
  133. }
  134. }
  135. static rt_err_t nu_timer_start(rt_hwtimer_t *timer, rt_uint32_t cnt, rt_hwtimer_mode_t opmode)
  136. {
  137. rt_err_t ret = RT_EINVAL;
  138. rt_uint32_t u32OpMode;
  139. nu_timer_t psNuTmr = NU_TIMER_DEVICE(timer);
  140. RT_ASSERT(psNuTmr != RT_NULL);
  141. if (cnt <= 1 || cnt > 0xFFFFFF)
  142. {
  143. goto exit_nu_timer_start;
  144. }
  145. switch (opmode)
  146. {
  147. case HWTIMER_MODE_PERIOD:
  148. u32OpMode = TIMER_PERIODIC_MODE;
  149. break;
  150. case HWTIMER_MODE_ONESHOT:
  151. u32OpMode = TIMER_ONESHOT_MODE;
  152. break;
  153. default:
  154. goto exit_nu_timer_start;
  155. }
  156. TIMER_SET_CMP_VALUE(psNuTmr->idx, cnt);
  157. TIMER_SET_OPMODE(psNuTmr->idx, u32OpMode);
  158. TIMER_EnableInt(psNuTmr->idx);
  159. rt_hw_interrupt_umask(psNuTmr->irqn);
  160. TIMER_Start(psNuTmr->idx);
  161. ret = RT_EOK;
  162. exit_nu_timer_start:
  163. return -(ret);
  164. }
  165. static void nu_timer_stop(rt_hwtimer_t *timer)
  166. {
  167. nu_timer_t psNuTmr = NU_TIMER_DEVICE(timer);
  168. RT_ASSERT(psNuTmr != RT_NULL);
  169. rt_hw_interrupt_mask(psNuTmr->irqn);
  170. TIMER_DisableInt(psNuTmr->idx);
  171. TIMER_Stop(psNuTmr->idx);
  172. TIMER_ClearCounter(psNuTmr->idx);
  173. }
  174. static rt_uint32_t nu_timer_count_get(rt_hwtimer_t *timer)
  175. {
  176. nu_timer_t psNuTmr = NU_TIMER_DEVICE(timer);
  177. RT_ASSERT(psNuTmr != RT_NULL);
  178. return TIMER_GetCounter(psNuTmr->idx);
  179. }
  180. static rt_err_t nu_timer_control(rt_hwtimer_t *timer, rt_uint32_t cmd, void *args)
  181. {
  182. rt_err_t ret = RT_EOK;
  183. nu_timer_t psNuTmr = NU_TIMER_DEVICE(timer);
  184. RT_ASSERT(psNuTmr != RT_NULL);
  185. switch (cmd)
  186. {
  187. case HWTIMER_CTRL_FREQ_SET:
  188. {
  189. uint32_t clk;
  190. uint32_t pre;
  191. clk = TIMER_GetModuleClock(psNuTmr->idx);
  192. pre = clk / *((uint32_t *)args) - 1;
  193. TIMER_SET_PRESCALE_VALUE(psNuTmr->idx, pre);
  194. *((uint32_t *)args) = clk / (pre + 1) ;
  195. }
  196. break;
  197. case HWTIMER_CTRL_STOP:
  198. TIMER_Stop(psNuTmr->idx);
  199. break;
  200. default:
  201. ret = RT_EINVAL;
  202. break;
  203. }
  204. return -(ret);
  205. }
  206. /**
  207. * All UART interrupt service routine
  208. */
  209. static void nu_timer_isr(int vector, void *param)
  210. {
  211. nu_timer_t psNuTmr = NU_TIMER_DEVICE(param);
  212. RT_ASSERT(psNuTmr != RT_NULL);
  213. if (TIMER_GetIntFlag(psNuTmr->idx))
  214. {
  215. TIMER_ClearIntFlag(psNuTmr->idx);
  216. rt_device_hwtimer_isr(&psNuTmr->parent);
  217. }
  218. }
  219. int rt_hw_timer_init(void)
  220. {
  221. int i;
  222. rt_err_t ret = RT_EOK;
  223. for (i = (TIMER_START + 1); i < TIMER_CNT; i++)
  224. {
  225. nu_sys_ipclk_enable(nu_timer_arr[i].clkidx);
  226. nu_sys_ip_reset(nu_timer_arr[i].rstidx);
  227. /* Register Etimer information. */
  228. nu_timer_arr[i].parent.info = &nu_timer_info;
  229. /* Register Etimer operation. */
  230. nu_timer_arr[i].parent.ops = &nu_timer_ops;
  231. /* Register Etimer interrupt service routine. */
  232. rt_hw_interrupt_install(nu_timer_arr[i].irqn, nu_timer_isr, &nu_timer_arr[i], nu_timer_arr[i].name);
  233. /* Register RT hwtimer device. */
  234. ret = rt_device_hwtimer_register(&nu_timer_arr[i].parent, nu_timer_arr[i].name, &nu_timer_arr[i]);
  235. RT_ASSERT(ret == RT_EOK);
  236. }
  237. return 0;
  238. }
  239. INIT_BOARD_EXPORT(rt_hw_timer_init);
  240. #endif //#if defined(BSP_USING_TIMER) && defined(RT_USING_HWTIMER)