drv_timer_capture.c 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326
  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-5-21 Philo First version
  10. *
  11. ******************************************************************************/
  12. #include <rtconfig.h>
  13. #if defined(BSP_USING_TIMER_CAPTURE)
  14. #if defined(BSP_USING_TIMER0_CAPTURE)|| \
  15. defined(BSP_USING_TIMER1_CAPTURE)|| \
  16. defined(BSP_USING_TIMER2_CAPTURE)|| \
  17. defined(BSP_USING_TIMER3_CAPTURE)
  18. #include <rtdevice.h>
  19. #include "NuMicro.h"
  20. /* Private typedef --------------------------------------------------------------*/
  21. typedef struct _timer
  22. {
  23. struct rt_inputcapture_device parent;
  24. TIMER_T *timer;
  25. uint8_t u8Channel;
  26. IRQn_Type irq;
  27. uint32_t u32CurrentCnt;
  28. rt_bool_t input_data_level;
  29. rt_bool_t first_edge;
  30. } nu_capture_t;
  31. /* Private functions ------------------------------------------------------------*/
  32. static rt_err_t nu_capture_init(struct rt_inputcapture_device *inputcapture);
  33. static rt_err_t nu_capture_open(struct rt_inputcapture_device *inputcapture);
  34. static rt_err_t nu_capture_close(struct rt_inputcapture_device *inputcapture);
  35. static rt_err_t nu_capture_get_pulsewidth(struct rt_inputcapture_device *inputcapture, rt_uint32_t *pulsewidth_us);
  36. /* Private define ---------------------------------------------------------------*/
  37. #define TIMER_CHANNEL_NUM (4)
  38. #define TIMER0_POS (0)
  39. #define TIMER1_POS (1)
  40. #define TIMER2_POS (2)
  41. #define TIMER3_POS (3)
  42. /* Timer prescale setting. Since it will affect the pulse width of measure, it is recommended to set to 2. */
  43. #define PSC_DIV (2)
  44. /* Public functions -------------------------------------------------------------*/
  45. /* Private variables ------------------------------------------------------------*/
  46. static const char *nu_timer_device_name[TIMER_CHANNEL_NUM] = { "timer0i0", "timer1i0", "timer2i0", "timer3i0"};
  47. static const IRQn_Type nu_timer_irq[TIMER_CHANNEL_NUM] = { TMR0_IRQn, TMR1_IRQn, TMR2_IRQn, TMR3_IRQn};
  48. static TIMER_T *nu_timer_base[TIMER_CHANNEL_NUM] = { TIMER0, TIMER1, TIMER2, TIMER3};
  49. static nu_capture_t *nu_timer_capture[TIMER_CHANNEL_NUM] = {0};
  50. static struct rt_inputcapture_ops nu_capture_ops =
  51. {
  52. .init = nu_capture_init,
  53. .open = nu_capture_open,
  54. .close = nu_capture_close,
  55. .get_pulsewidth = nu_capture_get_pulsewidth,
  56. };
  57. /* Functions define ------------------------------------------------------------*/
  58. void timer_interrupt_handler(nu_capture_t *nu_timer_capture)
  59. {
  60. TIMER_ClearCaptureIntFlag(nu_timer_capture->timer);
  61. /* First event is rising edge */
  62. if (nu_timer_capture->first_edge == RT_TRUE)
  63. {
  64. nu_timer_capture->first_edge = RT_FALSE;
  65. nu_timer_capture->input_data_level = RT_FALSE;
  66. }
  67. else
  68. {
  69. nu_timer_capture->input_data_level = !nu_timer_capture->input_data_level;
  70. nu_timer_capture->u32CurrentCnt = TIMER_GetCaptureData(nu_timer_capture->timer);
  71. rt_hw_inputcapture_isr(&nu_timer_capture->parent, nu_timer_capture->input_data_level);
  72. }
  73. }
  74. #if defined(BSP_USING_TIMER0_CAPTURE)
  75. void TMR0_IRQHandler(void)
  76. {
  77. /* enter interrupt */
  78. rt_interrupt_enter();
  79. timer_interrupt_handler(nu_timer_capture[0]);
  80. /* leave interrupt */
  81. rt_interrupt_leave();
  82. }
  83. #endif //defined(BSP_USING_TIMER0_CAPTURE)
  84. #if defined(BSP_USING_TIMER1_CAPTURE)
  85. void TMR1_IRQHandler(void)
  86. {
  87. /* enter interrupt */
  88. rt_interrupt_enter();
  89. timer_interrupt_handler(nu_timer_capture[1]);
  90. /* leave interrupt */
  91. rt_interrupt_leave();
  92. }
  93. #endif //defined(BSP_USING_TIMER1_CAPTURE)
  94. #if defined(BSP_USING_TIMER2_CAPTURE)
  95. void TMR2_IRQHandler(void)
  96. {
  97. /* enter interrupt */
  98. rt_interrupt_enter();
  99. timer_interrupt_handler(nu_timer_capture[2]);
  100. /* leave interrupt */
  101. rt_interrupt_leave();
  102. }
  103. #endif //defined(BSP_USING_TIMER2_CAPTURE)
  104. #if defined(BSP_USING_TIMER3_CAPTURE)
  105. void TMR3_IRQHandler(void)
  106. {
  107. /* enter interrupt */
  108. rt_interrupt_enter();
  109. timer_interrupt_handler(nu_timer_capture[3]);
  110. /* leave interrupt */
  111. rt_interrupt_leave();
  112. }
  113. #endif //defined(BSP_USING_TIMER3_CAPTURE)
  114. static rt_err_t nu_capture_get_pulsewidth(struct rt_inputcapture_device *inputcapture, rt_uint32_t *pulsewidth_us)
  115. {
  116. rt_err_t ret = RT_EOK;
  117. nu_capture_t *nu_capture;
  118. nu_capture = (nu_capture_t *)inputcapture;
  119. *pulsewidth_us = nu_capture->u32CurrentCnt / PSC_DIV;
  120. return -(ret);
  121. }
  122. static rt_err_t nu_timer_init(nu_capture_t *nu_capture)
  123. {
  124. SYS_UnlockReg();
  125. #if defined(BSP_USING_TIMER0_CAPTURE)
  126. if (nu_capture->timer == TIMER0)
  127. {
  128. /* Enable TIMER0 clock */
  129. CLK_EnableModuleClock(TMR0_MODULE);
  130. CLK_SetModuleClock(TMR0_MODULE, CLK_CLKSEL1_TMR0SEL_PCLK0, 0);
  131. goto exit_nu_timer_init;
  132. }
  133. #endif
  134. #if defined(BSP_USING_TIMER1_CAPTURE)
  135. if (nu_capture->timer == TIMER1)
  136. {
  137. /* Enable TIMER1 clock */
  138. CLK_EnableModuleClock(TMR1_MODULE);
  139. CLK_SetModuleClock(TMR1_MODULE, CLK_CLKSEL1_TMR1SEL_PCLK0, 0);
  140. goto exit_nu_timer_init;
  141. }
  142. #endif
  143. #if defined(BSP_USING_TIMER2_CAPTURE)
  144. if (nu_capture->timer == TIMER2)
  145. {
  146. /* Enable TIMER2 clock */
  147. CLK_EnableModuleClock(TMR2_MODULE);
  148. CLK_SetModuleClock(TMR2_MODULE, CLK_CLKSEL1_TMR2SEL_PCLK1, 0);
  149. goto exit_nu_timer_init;
  150. }
  151. #endif
  152. #if defined(BSP_USING_TIMER3_CAPTURE)
  153. if (nu_capture->timer == TIMER3)
  154. {
  155. /* Enable TIMER3 clock */
  156. CLK_EnableModuleClock(TMR3_MODULE);
  157. CLK_SetModuleClock(TMR3_MODULE, CLK_CLKSEL1_TMR3SEL_PCLK1, 0);
  158. goto exit_nu_timer_init;
  159. }
  160. #endif
  161. SYS_LockReg();
  162. return -(RT_ERROR);
  163. exit_nu_timer_init:
  164. SYS_LockReg();
  165. return RT_EOK;
  166. }
  167. static rt_err_t nu_capture_init(struct rt_inputcapture_device *inputcapture)
  168. {
  169. rt_err_t ret = RT_EOK;
  170. nu_capture_t *nu_capture;
  171. RT_ASSERT(inputcapture != RT_NULL);
  172. nu_capture = (nu_capture_t *) inputcapture;
  173. if (nu_timer_init(nu_capture) != RT_EOK)
  174. {
  175. rt_kprintf("Failed to initialize TIMER.\n");
  176. ret = RT_ERROR;
  177. }
  178. return -(ret);
  179. }
  180. static uint8_t cal_time_prescale(nu_capture_t *nu_capture)
  181. {
  182. uint32_t u32Clk = TIMER_GetModuleClock(nu_capture->timer);
  183. /* 1 tick = 1/PSC_DIV us */
  184. return (u32Clk / 1000000 / PSC_DIV) - 1;
  185. }
  186. static rt_err_t nu_capture_open(struct rt_inputcapture_device *inputcapture)
  187. {
  188. rt_err_t ret = RT_EOK;
  189. nu_capture_t *nu_capture;
  190. RT_ASSERT(inputcapture != RT_NULL);
  191. nu_capture = (nu_capture_t *) inputcapture;
  192. nu_capture->first_edge = RT_TRUE;
  193. /* Enable Timer NVIC */
  194. NVIC_EnableIRQ(nu_capture->irq);
  195. /* Reset counter before openning. */
  196. TIMER_ResetCounter(nu_capture->timer);
  197. TIMER_Open(nu_capture->timer, TIMER_CONTINUOUS_MODE, 1);
  198. TIMER_SET_PRESCALE_VALUE(nu_capture->timer, cal_time_prescale(nu_capture));
  199. TIMER_SET_CMP_VALUE(nu_capture->timer, 0xFFFFFF);
  200. TIMER_EnableCapture(nu_capture->timer, TIMER_CAPTURE_COUNTER_RESET_MODE, TIMER_CAPTURE_EVENT_RISING_FALLING);
  201. TIMER_EnableInt(nu_capture->timer);
  202. TIMER_EnableCaptureInt(nu_capture->timer);
  203. TIMER_Start(nu_capture->timer);
  204. return ret;
  205. }
  206. static rt_err_t nu_capture_close(struct rt_inputcapture_device *inputcapture)
  207. {
  208. rt_err_t ret = RT_EOK;
  209. nu_capture_t *nu_capture;
  210. RT_ASSERT(inputcapture != RT_NULL);
  211. nu_capture = (nu_capture_t *) inputcapture;
  212. TIMER_Stop(nu_capture->timer);
  213. TIMER_DisableCaptureInt(nu_capture->timer);
  214. TIMER_DisableInt(nu_capture->timer);
  215. TIMER_Close(nu_capture->timer);
  216. NVIC_DisableIRQ(nu_capture->irq);
  217. return ret;
  218. }
  219. /* Init and register timer capture */
  220. static int nu_timer_capture_device_init(void)
  221. {
  222. uint8_t TIMER_MSK = 0;
  223. #if defined(BSP_USING_TIMER0_CAPTURE)
  224. TIMER_MSK |= (0x1 << 0);
  225. #endif
  226. #if defined(BSP_USING_TIMER1_CAPTURE)
  227. TIMER_MSK |= (0x1 << 1);
  228. #endif
  229. #if defined(BSP_USING_TIMER2_CAPTURE)
  230. TIMER_MSK |= (0x1 << 2);
  231. #endif
  232. #if defined(BSP_USING_TIMER3_CAPTURE)
  233. TIMER_MSK |= (0x1 << 3);
  234. #endif
  235. for (int i = 0; i < TIMER_CHANNEL_NUM; i++)
  236. {
  237. if (TIMER_MSK & (0x1 << i))
  238. {
  239. nu_timer_capture[i] = (nu_capture_t *)rt_malloc(sizeof(nu_capture_t));
  240. nu_timer_capture[i]->timer = nu_timer_base[i];
  241. nu_timer_capture[i]->u8Channel = i;
  242. nu_timer_capture[i]->irq = nu_timer_irq[i];
  243. nu_timer_capture[i]->u32CurrentCnt = 0;
  244. nu_timer_capture[i]->parent.ops = &nu_capture_ops;
  245. nu_timer_capture[i]->first_edge = RT_TRUE;
  246. /* register inputcapture device */
  247. rt_device_inputcapture_register(&nu_timer_capture[i]->parent, nu_timer_device_name[i], &nu_timer_capture[i]);
  248. }
  249. }
  250. return 0;
  251. }
  252. INIT_DEVICE_EXPORT(nu_timer_capture_device_init);
  253. #endif //#if defined(BSP_USING_TIMER*_CAPTURE)
  254. #endif //#if defined(BSP_USING_TIMER_CAPTURE)