drv_etimer_capture.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  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_ETIMER0_CAPTURE)
  25. TCAP0_IDX,
  26. #endif
  27. #if defined(BSP_USING_ETIMER1_CAPTURE)
  28. TCAP1_IDX,
  29. #endif
  30. #if defined(BSP_USING_ETIMER2_CAPTURE)
  31. TCAP2_IDX,
  32. #endif
  33. #if defined(BSP_USING_ETIMER3_CAPTURE)
  34. TCAP3_IDX,
  35. #endif
  36. TCAP_CNT
  37. };
  38. /* Private typedef --------------------------------------------------------------*/
  39. typedef struct _timer
  40. {
  41. struct rt_inputcapture_device parent;
  42. char *name;
  43. uint32_t idx;
  44. IRQn_Type irqn;
  45. E_SYS_IPRST rstidx;
  46. E_SYS_IPCLK clkidx;
  47. uint32_t u32CurrentCnt;
  48. } nu_capture_t;
  49. /* Private functions ------------------------------------------------------------*/
  50. static rt_err_t nu_capture_init(struct rt_inputcapture_device *inputcapture);
  51. static rt_err_t nu_capture_open(struct rt_inputcapture_device *inputcapture);
  52. static rt_err_t nu_capture_close(struct rt_inputcapture_device *inputcapture);
  53. static rt_err_t nu_capture_get_pulsewidth(struct rt_inputcapture_device *inputcapture, rt_uint32_t *pulsewidth_us);
  54. /* Public functions -------------------------------------------------------------*/
  55. /* Private variables ------------------------------------------------------------*/
  56. static nu_capture_t nu_etcap_arr [] =
  57. {
  58. #if defined(BSP_USING_ETIMER0_CAPTURE)
  59. {
  60. .name = "etmr0i0",
  61. .idx = 0,
  62. .irqn = IRQ_ETMR0,
  63. .rstidx = ETIMER0RST,
  64. .clkidx = ETIMER0CKEN,
  65. },
  66. #endif
  67. #if defined(BSP_USING_ETIMER1_CAPTURE)
  68. {
  69. .name = "etmr1i0",
  70. .idx = 1,
  71. .irqn = IRQ_ETMR1,
  72. .rstidx = ETIMER1RST,
  73. .clkidx = ETIMER1CKEN,
  74. },
  75. #endif
  76. #if defined(BSP_USING_ETIMER2_CAPTURE)
  77. {
  78. .name = "etmr2i0",
  79. .idx = 2,
  80. .irqn = IRQ_ETMR2,
  81. .rstidx = ETIMER2RST,
  82. .clkidx = ETIMER2CKEN,
  83. },
  84. #endif
  85. #if defined(BSP_USING_ETIMER3_CAPTURE)
  86. {
  87. .name = "etmr3i0",
  88. .idx = 3,
  89. .irqn = IRQ_ETMR3,
  90. .rstidx = ETIMER3RST,
  91. .clkidx = ETIMER3CKEN,
  92. },
  93. #endif
  94. };
  95. static struct rt_inputcapture_ops nu_capture_ops =
  96. {
  97. .init = nu_capture_init,
  98. .open = nu_capture_open,
  99. .close = nu_capture_close,
  100. .get_pulsewidth = nu_capture_get_pulsewidth,
  101. };
  102. /* Functions define ------------------------------------------------------------*/
  103. static void nu_tcap_isr(int vector, void *param)
  104. {
  105. nu_capture_t *psNuTCap = NU_TCAP_DEVICE(param);
  106. RT_ASSERT(psNuTCap != RT_NULL);
  107. ETIMER_ClearCaptureIntFlag(psNuTCap->idx);
  108. /* Report caputring data and level. */
  109. psNuTCap->u32CurrentCnt = ETIMER_GetCaptureData(psNuTCap->idx);
  110. rt_hw_inputcapture_isr(&psNuTCap->parent, ETIMER_GetCaptureFallingEdgeFlag(psNuTCap->idx));
  111. }
  112. static rt_err_t nu_capture_get_pulsewidth(struct rt_inputcapture_device *inputcapture, rt_uint32_t *pulsewidth_us)
  113. {
  114. nu_capture_t *psNuTCap = NU_TCAP_DEVICE(inputcapture);
  115. RT_ASSERT(inputcapture != RT_NULL);
  116. RT_ASSERT(pulsewidth_us != RT_NULL);
  117. *pulsewidth_us = psNuTCap->u32CurrentCnt / PSC_DIV;
  118. return RT_EOK;
  119. }
  120. static rt_err_t nu_capture_init(struct rt_inputcapture_device *inputcapture)
  121. {
  122. nu_capture_t *psNuTCap = NU_TCAP_DEVICE(inputcapture);
  123. RT_ASSERT(inputcapture != RT_NULL);
  124. nu_sys_ipclk_enable(psNuTCap->clkidx);
  125. nu_sys_ip_reset(psNuTCap->rstidx);
  126. return RT_EOK;
  127. }
  128. static uint8_t cal_time_prescale(nu_capture_t *psNuTCap)
  129. {
  130. uint32_t u32Clk = ETIMER_GetModuleClock(psNuTCap->idx);
  131. /* 1 tick = 1/PSC_DIV us */
  132. return (u32Clk / 1000000 / PSC_DIV) - 1;
  133. }
  134. static rt_err_t nu_capture_open(struct rt_inputcapture_device *inputcapture)
  135. {
  136. nu_capture_t *psNuTCap = NU_TCAP_DEVICE(inputcapture);
  137. RT_ASSERT(inputcapture != RT_NULL);
  138. /* Enable Timer Interrupt */
  139. rt_hw_interrupt_umask(psNuTCap->irqn);
  140. /* Clear counter before openning. */
  141. ETIMER_ClearCounter(psNuTCap->idx);
  142. ETIMER_Open(psNuTCap->idx, ETIMER_CONTINUOUS_MODE, 1);
  143. ETIMER_SET_PRESCALE_VALUE(psNuTCap->idx, cal_time_prescale(psNuTCap));
  144. ETIMER_SET_CMP_VALUE(psNuTCap->idx, 0xFFFFFF);
  145. ETIMER_EnableCapture(psNuTCap->idx, ETIMER_CAPTURE_COUNTER_RESET_MODE, ETIMER_CAPTURE_RISING_THEN_FALLING_EDGE);
  146. ETIMER_EnableCaptureInt(psNuTCap->idx);
  147. ETIMER_Start(psNuTCap->idx);
  148. return RT_EOK;
  149. }
  150. static rt_err_t nu_capture_close(struct rt_inputcapture_device *inputcapture)
  151. {
  152. nu_capture_t *psNuTCap = NU_TCAP_DEVICE(inputcapture);
  153. RT_ASSERT(inputcapture != RT_NULL);
  154. ETIMER_Stop(psNuTCap->idx);
  155. ETIMER_DisableCaptureInt(psNuTCap->idx);
  156. ETIMER_Close(psNuTCap->idx);
  157. rt_hw_interrupt_mask(psNuTCap->irqn);
  158. return RT_EOK;
  159. }
  160. /* Init and register timer capture */
  161. static int nu_etimer_capture_device_init(void)
  162. {
  163. int i;
  164. for (i = (TCAP_START + 1); i < TCAP_CNT; i++)
  165. {
  166. /* Register operations */
  167. nu_etcap_arr[i].parent.ops = &nu_capture_ops;
  168. /* Install ISR */
  169. rt_hw_interrupt_install(nu_etcap_arr[i].irqn, nu_tcap_isr, &nu_etcap_arr[i], nu_etcap_arr[i].name);
  170. /* Register inputcapture device */
  171. rt_device_inputcapture_register(&nu_etcap_arr[i].parent, nu_etcap_arr[i].name, &nu_etcap_arr[i]);
  172. }
  173. return 0;
  174. }
  175. INIT_DEVICE_EXPORT(nu_etimer_capture_device_init);
  176. #endif //#if defined(BSP_USING_ETIMER_CAPTURE)