drv_timer_capture.c 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327
  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. * 2021-02-08 klcheng 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. TIMER_EnableCapture(nu_timer_capture->timer, TIMER_CAPTURE_COUNTER_RESET_MODE, TIMER_CAPTURE_FALLING_AND_RISING_EDGE);
  65. nu_timer_capture->first_edge = RT_FALSE;
  66. nu_timer_capture->input_data_level = RT_FALSE;
  67. }
  68. else
  69. {
  70. nu_timer_capture->input_data_level = !nu_timer_capture->input_data_level;
  71. nu_timer_capture->u32CurrentCnt = TIMER_GetCaptureData(nu_timer_capture->timer);
  72. rt_hw_inputcapture_isr(&nu_timer_capture->parent, nu_timer_capture->input_data_level);
  73. }
  74. }
  75. #if defined(BSP_USING_TIMER0_CAPTURE)
  76. void TMR0_IRQHandler(void)
  77. {
  78. /* enter interrupt */
  79. rt_interrupt_enter();
  80. timer_interrupt_handler(nu_timer_capture[0]);
  81. /* leave interrupt */
  82. rt_interrupt_leave();
  83. }
  84. #endif //defined(BSP_USING_TIMER0_CAPTURE)
  85. #if defined(BSP_USING_TIMER1_CAPTURE)
  86. void TMR1_IRQHandler(void)
  87. {
  88. /* enter interrupt */
  89. rt_interrupt_enter();
  90. timer_interrupt_handler(nu_timer_capture[1]);
  91. /* leave interrupt */
  92. rt_interrupt_leave();
  93. }
  94. #endif //defined(BSP_USING_TIMER1_CAPTURE)
  95. #if defined(BSP_USING_TIMER2_CAPTURE)
  96. void TMR2_IRQHandler(void)
  97. {
  98. /* enter interrupt */
  99. rt_interrupt_enter();
  100. timer_interrupt_handler(nu_timer_capture[2]);
  101. /* leave interrupt */
  102. rt_interrupt_leave();
  103. }
  104. #endif //defined(BSP_USING_TIMER2_CAPTURE)
  105. #if defined(BSP_USING_TIMER3_CAPTURE)
  106. void TMR3_IRQHandler(void)
  107. {
  108. /* enter interrupt */
  109. rt_interrupt_enter();
  110. timer_interrupt_handler(nu_timer_capture[3]);
  111. /* leave interrupt */
  112. rt_interrupt_leave();
  113. }
  114. #endif //defined(BSP_USING_TIMER3_CAPTURE)
  115. static rt_err_t nu_capture_get_pulsewidth(struct rt_inputcapture_device *inputcapture, rt_uint32_t *pulsewidth_us)
  116. {
  117. rt_err_t ret = RT_EOK;
  118. nu_capture_t *nu_capture;
  119. nu_capture = (nu_capture_t *)inputcapture;
  120. *pulsewidth_us = nu_capture->u32CurrentCnt / PSC_DIV;
  121. return -(ret);
  122. }
  123. static rt_err_t nu_timer_init(nu_capture_t *nu_capture)
  124. {
  125. SYS_UnlockReg();
  126. #if defined(BSP_USING_TIMER0_CAPTURE)
  127. if (nu_capture->timer == TIMER0)
  128. {
  129. /* Enable TIMER0 clock */
  130. CLK_EnableModuleClock(TMR0_MODULE);
  131. CLK_SetModuleClock(TMR0_MODULE, CLK_CLKSEL1_TMR0SEL_PCLK0, 0);
  132. goto exit_nu_timer_init;
  133. }
  134. #endif
  135. #if defined(BSP_USING_TIMER1_CAPTURE)
  136. if (nu_capture->timer == TIMER1)
  137. {
  138. /* Enable TIMER1 clock */
  139. CLK_EnableModuleClock(TMR1_MODULE);
  140. CLK_SetModuleClock(TMR1_MODULE, CLK_CLKSEL1_TMR1SEL_PCLK0, 0);
  141. goto exit_nu_timer_init;
  142. }
  143. #endif
  144. #if defined(BSP_USING_TIMER2_CAPTURE)
  145. if (nu_capture->timer == TIMER2)
  146. {
  147. /* Enable TIMER2 clock */
  148. CLK_EnableModuleClock(TMR2_MODULE);
  149. CLK_SetModuleClock(TMR2_MODULE, CLK_CLKSEL1_TMR2SEL_PCLK1, 0);
  150. goto exit_nu_timer_init;
  151. }
  152. #endif
  153. #if defined(BSP_USING_TIMER3_CAPTURE)
  154. if (nu_capture->timer == TIMER3)
  155. {
  156. /* Enable TIMER3 clock */
  157. CLK_EnableModuleClock(TMR3_MODULE);
  158. CLK_SetModuleClock(TMR3_MODULE, CLK_CLKSEL1_TMR3SEL_PCLK1, 0);
  159. goto exit_nu_timer_init;
  160. }
  161. #endif
  162. SYS_LockReg();
  163. return -(RT_ERROR);
  164. exit_nu_timer_init:
  165. SYS_LockReg();
  166. return RT_EOK;
  167. }
  168. static rt_err_t nu_capture_init(struct rt_inputcapture_device *inputcapture)
  169. {
  170. rt_err_t ret = RT_EOK;
  171. nu_capture_t *nu_capture;
  172. RT_ASSERT(inputcapture != RT_NULL);
  173. nu_capture = (nu_capture_t *) inputcapture;
  174. if (nu_timer_init(nu_capture) != RT_EOK)
  175. {
  176. rt_kprintf("Failed to initialize TIMER.\n");
  177. ret = RT_ERROR;
  178. }
  179. return -(ret);
  180. }
  181. static uint8_t cal_time_prescale(nu_capture_t *nu_capture)
  182. {
  183. uint32_t u32Clk = TIMER_GetModuleClock(nu_capture->timer);
  184. /* 1 tick = 1/PSC_DIV us */
  185. return (u32Clk / 1000000 / PSC_DIV) - 1;
  186. }
  187. static rt_err_t nu_capture_open(struct rt_inputcapture_device *inputcapture)
  188. {
  189. rt_err_t ret = RT_EOK;
  190. nu_capture_t *nu_capture;
  191. RT_ASSERT(inputcapture != RT_NULL);
  192. nu_capture = (nu_capture_t *) inputcapture;
  193. nu_capture->first_edge = RT_TRUE;
  194. /* Enable Timer NVIC */
  195. NVIC_EnableIRQ(nu_capture->irq);
  196. /* Reset counter before openning. */
  197. TIMER_ResetCounter(nu_capture->timer);
  198. TIMER_Open(nu_capture->timer, TIMER_CONTINUOUS_MODE, 1);
  199. TIMER_SET_PRESCALE_VALUE(nu_capture->timer, cal_time_prescale(nu_capture));
  200. TIMER_SET_CMP_VALUE(nu_capture->timer, 0xFFFFFF);
  201. TIMER_EnableCapture(nu_capture->timer, TIMER_CAPTURE_COUNTER_RESET_MODE, TIMER_CAPTURE_RISING_EDGE);
  202. TIMER_EnableInt(nu_capture->timer);
  203. TIMER_EnableCaptureInt(nu_capture->timer);
  204. TIMER_Start(nu_capture->timer);
  205. return ret;
  206. }
  207. static rt_err_t nu_capture_close(struct rt_inputcapture_device *inputcapture)
  208. {
  209. rt_err_t ret = RT_EOK;
  210. nu_capture_t *nu_capture;
  211. RT_ASSERT(inputcapture != RT_NULL);
  212. nu_capture = (nu_capture_t *) inputcapture;
  213. TIMER_Stop(nu_capture->timer);
  214. TIMER_DisableCaptureInt(nu_capture->timer);
  215. TIMER_DisableInt(nu_capture->timer);
  216. TIMER_Close(nu_capture->timer);
  217. NVIC_DisableIRQ(nu_capture->irq);
  218. return ret;
  219. }
  220. /* Init and register timer capture */
  221. static int nu_timer_capture_device_init(void)
  222. {
  223. uint8_t TIMER_MSK = 0;
  224. #if defined(BSP_USING_TIMER0_CAPTURE)
  225. TIMER_MSK |= (0x1 << 0);
  226. #endif
  227. #if defined(BSP_USING_TIMER1_CAPTURE)
  228. TIMER_MSK |= (0x1 << 1);
  229. #endif
  230. #if defined(BSP_USING_TIMER2_CAPTURE)
  231. TIMER_MSK |= (0x1 << 2);
  232. #endif
  233. #if defined(BSP_USING_TIMER3_CAPTURE)
  234. TIMER_MSK |= (0x1 << 3);
  235. #endif
  236. for (int i = 0; i < TIMER_CHANNEL_NUM; i++)
  237. {
  238. if (TIMER_MSK & (0x1 << i))
  239. {
  240. nu_timer_capture[i] = (nu_capture_t *)rt_malloc(sizeof(nu_capture_t));
  241. nu_timer_capture[i]->timer = nu_timer_base[i];
  242. nu_timer_capture[i]->u8Channel = i;
  243. nu_timer_capture[i]->irq = nu_timer_irq[i];
  244. nu_timer_capture[i]->u32CurrentCnt = 0;
  245. nu_timer_capture[i]->parent.ops = &nu_capture_ops;
  246. nu_timer_capture[i]->first_edge = RT_TRUE;
  247. /* register inputcapture device */
  248. rt_device_inputcapture_register(&nu_timer_capture[i]->parent, nu_timer_device_name[i], &nu_timer_capture[i]);
  249. }
  250. }
  251. return 0;
  252. }
  253. INIT_DEVICE_EXPORT(nu_timer_capture_device_init);
  254. #endif //#if defined(BSP_USING_TIMER*_CAPTURE)
  255. #endif //#if defined(BSP_USING_TIMER_CAPTURE)