drv_etimer_capture.c 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  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-1-28 Wayne First version
  10. *
  11. ******************************************************************************/
  12. #include <rtconfig.h>
  13. #if defined(BSP_USING_TIMER_CAPTURE)
  14. #include <rtdevice.h>
  15. #include "NuMicro.h"
  16. #include <drv_sys.h>
  17. /* Private define ---------------------------------------------------------------*/
  18. /* Timer prescale setting. Since it will affect the pulse width of measure, it is recommended to set to 2. */
  19. #define PSC_DIV (2)
  20. #define NU_TCAP_DEVICE(etimer) (nu_capture_t*)(etimer)
  21. enum
  22. {
  23. TCAP_START = -1,
  24. #if defined(BSP_USING_TIMER0_CAPTURE)
  25. TCAP0_IDX,
  26. #endif
  27. #if defined(BSP_USING_TIMER1_CAPTURE)
  28. TCAP1_IDX,
  29. #endif
  30. #if defined(BSP_USING_TIMER2_CAPTURE)
  31. TCAP2_IDX,
  32. #endif
  33. #if defined(BSP_USING_TIMER3_CAPTURE)
  34. TCAP3_IDX,
  35. #endif
  36. #if defined(BSP_USING_TIMER4_CAPTURE)
  37. TCAP4_IDX,
  38. #endif
  39. /* BSP_USING_TIMER5 is reserved for Systick usage. */
  40. TCAP_CNT
  41. };
  42. /* Private typedef --------------------------------------------------------------*/
  43. typedef struct _timer
  44. {
  45. struct rt_inputcapture_device parent;
  46. char *name;
  47. uint32_t idx;
  48. IRQn_Type irqn;
  49. E_SYS_IPRST rstidx;
  50. E_SYS_IPCLK clkidx;
  51. uint32_t u32CurrentCnt;
  52. } nu_capture_t;
  53. /* Private functions ------------------------------------------------------------*/
  54. static rt_err_t nu_capture_init(struct rt_inputcapture_device *inputcapture);
  55. static rt_err_t nu_capture_open(struct rt_inputcapture_device *inputcapture);
  56. static rt_err_t nu_capture_close(struct rt_inputcapture_device *inputcapture);
  57. static rt_err_t nu_capture_get_pulsewidth(struct rt_inputcapture_device *inputcapture, rt_uint32_t *pulsewidth_us);
  58. /* Public functions -------------------------------------------------------------*/
  59. /* Private variables ------------------------------------------------------------*/
  60. static nu_capture_t nu_etcap_arr [] =
  61. {
  62. #if defined(BSP_USING_TIMER0_CAPTURE)
  63. {
  64. .name = "timer0i0",
  65. .idx = 0,
  66. .irqn = IRQ_TIMER0,
  67. .rstidx = TIMER0RST,
  68. .clkidx = TIMER0CKEN,
  69. },
  70. #endif
  71. #if defined(BSP_USING_TIMER1_CAPTURE)
  72. {
  73. .name = "timer1i0",
  74. .idx = 1,
  75. .irqn = IRQ_TIMER1,
  76. .rstidx = TIMER1RST,
  77. .clkidx = TIMER1CKEN,
  78. },
  79. #endif
  80. #if defined(BSP_USING_TIMER2_CAPTURE)
  81. {
  82. .name = "timer2i0",
  83. .idx = 2,
  84. .irqn = IRQ_TIMER2,
  85. .rstidx = TIMER2RST,
  86. .clkidx = TIMER2CKEN,
  87. },
  88. #endif
  89. #if defined(BSP_USING_TIMER3_CAPTURE)
  90. {
  91. .name = "timer3i0",
  92. .idx = 3,
  93. .irqn = IRQ_TIMER3,
  94. .rstidx = TIMER3RST,
  95. .clkidx = TIMER3CKEN,
  96. },
  97. #endif
  98. #if defined(BSP_USING_TIMER4_CAPTURE)
  99. {
  100. .name = "timer4i0",
  101. .idx = 4,
  102. .irqn = IRQ_TIMER4,
  103. .rstidx = TIMER4RST,
  104. .clkidx = TIMER4CKEN,
  105. },
  106. #endif
  107. /* BSP_USING_TIMER5 is reserved for Systick usage. */
  108. };
  109. static struct rt_inputcapture_ops nu_capture_ops =
  110. {
  111. .init = nu_capture_init,
  112. .open = nu_capture_open,
  113. .close = nu_capture_close,
  114. .get_pulsewidth = nu_capture_get_pulsewidth,
  115. };
  116. /* Functions define ------------------------------------------------------------*/
  117. static void nu_tcap_isr(int vector, void *param)
  118. {
  119. nu_capture_t *psNuTCap = NU_TCAP_DEVICE(param);
  120. RT_ASSERT(psNuTCap != RT_NULL);
  121. ETIMER_ClearCaptureIntFlag(psNuTCap->idx);
  122. /* Report caputring data and level. */
  123. psNuTCap->u32CurrentCnt = ETIMER_GetCaptureData(psNuTCap->idx);
  124. rt_hw_inputcapture_isr(&psNuTCap->parent, ETIMER_GetCaptureFallingEdgeFlag(psNuTCap->idx));
  125. }
  126. static rt_err_t nu_capture_get_pulsewidth(struct rt_inputcapture_device *inputcapture, rt_uint32_t *pulsewidth_us)
  127. {
  128. nu_capture_t *psNuTCap = NU_TCAP_DEVICE(inputcapture);
  129. RT_ASSERT(inputcapture != RT_NULL);
  130. RT_ASSERT(pulsewidth_us != RT_NULL);
  131. *pulsewidth_us = psNuTCap->u32CurrentCnt / PSC_DIV;
  132. return RT_EOK;
  133. }
  134. static rt_err_t nu_capture_init(struct rt_inputcapture_device *inputcapture)
  135. {
  136. nu_capture_t *psNuTCap = NU_TCAP_DEVICE(inputcapture);
  137. RT_ASSERT(inputcapture != RT_NULL);
  138. nu_sys_ipclk_enable(psNuTCap->clkidx);
  139. nu_sys_ip_reset(psNuTCap->rstidx);
  140. return RT_EOK;
  141. }
  142. static uint8_t cal_time_prescale(nu_capture_t *psNuTCap)
  143. {
  144. uint32_t u32Clk = ETIMER_GetModuleClock(psNuTCap->idx);
  145. /* 1 tick = 1/PSC_DIV us */
  146. return (u32Clk / 1000000 / PSC_DIV) - 1;
  147. }
  148. static rt_err_t nu_capture_open(struct rt_inputcapture_device *inputcapture)
  149. {
  150. nu_capture_t *psNuTCap = NU_TCAP_DEVICE(inputcapture);
  151. RT_ASSERT(inputcapture != RT_NULL);
  152. /* Enable Timer Interrupt */
  153. rt_hw_interrupt_umask(psNuTCap->irqn);
  154. /* Clear counter before openning. */
  155. ETIMER_ClearCounter(psNuTCap->idx);
  156. ETIMER_Open(psNuTCap->idx, ETIMER_CONTINUOUS_MODE, 1);
  157. ETIMER_SET_PRESCALE_VALUE(psNuTCap->idx, cal_time_prescale(psNuTCap));
  158. ETIMER_SET_CMP_VALUE(psNuTCap->idx, 0xFFFFFF);
  159. ETIMER_EnableCapture(psNuTCap->idx, ETIMER_CAPTURE_COUNTER_RESET_MODE, ETIMER_CAPTURE_RISING_THEN_FALLING_EDGE);
  160. ETIMER_EnableCaptureInt(psNuTCap->idx);
  161. ETIMER_Start(psNuTCap->idx);
  162. return RT_EOK;
  163. }
  164. static rt_err_t nu_capture_close(struct rt_inputcapture_device *inputcapture)
  165. {
  166. nu_capture_t *psNuTCap = NU_TCAP_DEVICE(inputcapture);
  167. RT_ASSERT(inputcapture != RT_NULL);
  168. ETIMER_Stop(psNuTCap->idx);
  169. ETIMER_DisableCaptureInt(psNuTCap->idx);
  170. ETIMER_Close(psNuTCap->idx);
  171. rt_hw_interrupt_mask(psNuTCap->irqn);
  172. return RT_EOK;
  173. }
  174. /* Init and register timer capture */
  175. static int nu_timer_capture_device_init(void)
  176. {
  177. int i;
  178. for (i = (TCAP_START + 1); i < TCAP_CNT; i++)
  179. {
  180. /* Register operations */
  181. nu_etcap_arr[i].parent.ops = &nu_capture_ops;
  182. /* Install ISR */
  183. rt_hw_interrupt_install(nu_etcap_arr[i].irqn, nu_tcap_isr, &nu_etcap_arr[i], nu_etcap_arr[i].name);
  184. /* Register inputcapture device */
  185. rt_device_inputcapture_register(&nu_etcap_arr[i].parent, nu_etcap_arr[i].name, &nu_etcap_arr[i]);
  186. }
  187. return 0;
  188. }
  189. INIT_DEVICE_EXPORT(nu_timer_capture_device_init);
  190. #endif //#if defined(BSP_USING_TIMER_CAPTURE)