drv_epwm_capture.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336
  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-10-19 Wayne First version
  10. *
  11. ******************************************************************************/
  12. #include <rtconfig.h>
  13. #if defined(BSP_USING_EPWM_CAPTURE)
  14. #include <rtdevice.h>
  15. #include "drv_sys.h"
  16. /* Private typedef --------------------------------------------------------------*/
  17. enum
  18. {
  19. EPWM_START = -1,
  20. #if defined(BSP_USING_EPWM0_CAPTURE)
  21. EPWM0I0_IDX,
  22. EPWM0I1_IDX,
  23. EPWM0I2_IDX,
  24. EPWM0I3_IDX,
  25. EPWM0I4_IDX,
  26. EPWM0I5_IDX,
  27. #endif
  28. #if defined(BSP_USING_EPWM1_CAPTURE)
  29. EPWM1I0_IDX,
  30. EPWM1I1_IDX,
  31. EPWM1I2_IDX,
  32. EPWM1I3_IDX,
  33. EPWM1I4_IDX,
  34. EPWM1I5_IDX,
  35. #endif
  36. EPWM_CNT
  37. };
  38. struct nu_epwmcap
  39. {
  40. struct rt_inputcapture_device parent;
  41. EPWM_T *base;
  42. char *name;
  43. IRQn_Type irqn;
  44. uint32_t rstidx;
  45. uint32_t modid;
  46. uint8_t u8Channel;
  47. uint32_t u32CurrentRisingCnt;
  48. uint32_t u32CurrentFallingCnt;
  49. rt_bool_t input_data_level;
  50. };
  51. typedef struct nu_epwmcap *nu_epwmcap_t;
  52. /* Private functions ------------------------------------------------------------*/
  53. static rt_err_t nu_epwmcap_init(struct rt_inputcapture_device *inputcapture);
  54. static rt_err_t nu_epwmcap_open(struct rt_inputcapture_device *inputcapture);
  55. static rt_err_t nu_epwmcap_close(struct rt_inputcapture_device *inputcapture);
  56. static rt_err_t nu_epwmcap_get_pulsewidth(struct rt_inputcapture_device *inputcapture, rt_uint32_t *pulsewidth_us);
  57. static rt_err_t CalPulseWidth(nu_epwmcap_t psNuEpwmCap);
  58. static void nu_epwmcap_isr(nu_epwmcap_t psNuEpwmCap);
  59. /* Public functions -------------------------------------------------------------*/
  60. /* Private variables ------------------------------------------------------------*/
  61. static struct nu_epwmcap nu_epwmcap_arr [] =
  62. {
  63. #if defined(BSP_USING_EPWM0_CAPTURE)
  64. { .base = EPWM0, .name = "epwm0i0", .irqn = EPWM0P0_IRQn, .rstidx = EPWM0_RST, .modid = EPWM0_MODULE },
  65. { .base = EPWM0, .name = "epwm0i1", .irqn = EPWM0P0_IRQn, .rstidx = EPWM0_RST, .modid = EPWM0_MODULE },
  66. { .base = EPWM0, .name = "epwm0i2", .irqn = EPWM0P1_IRQn, .rstidx = EPWM0_RST, .modid = EPWM0_MODULE },
  67. { .base = EPWM0, .name = "epwm0i3", .irqn = EPWM0P1_IRQn, .rstidx = EPWM0_RST, .modid = EPWM0_MODULE },
  68. { .base = EPWM0, .name = "epwm0i4", .irqn = EPWM0P2_IRQn, .rstidx = EPWM0_RST, .modid = EPWM0_MODULE },
  69. { .base = EPWM0, .name = "epwm0i5", .irqn = EPWM0P2_IRQn, .rstidx = EPWM0_RST, .modid = EPWM0_MODULE },
  70. #endif
  71. #if defined(BSP_USING_EPWM1_CAPTURE)
  72. { .base = EPWM1, .name = "epwm1i0", .irqn = EPWM1P0_IRQn, .rstidx = EPWM1_RST, .modid = EPWM1_MODULE },
  73. { .base = EPWM1, .name = "epwm1i1", .irqn = EPWM1P0_IRQn, .rstidx = EPWM1_RST, .modid = EPWM1_MODULE },
  74. { .base = EPWM1, .name = "epwm1i2", .irqn = EPWM1P1_IRQn, .rstidx = EPWM1_RST, .modid = EPWM1_MODULE },
  75. { .base = EPWM1, .name = "epwm1i3", .irqn = EPWM1P1_IRQn, .rstidx = EPWM1_RST, .modid = EPWM1_MODULE },
  76. { .base = EPWM1, .name = "epwm1i4", .irqn = EPWM1P2_IRQn, .rstidx = EPWM1_RST, .modid = EPWM1_MODULE },
  77. { .base = EPWM1, .name = "epwm1i5", .irqn = EPWM1P2_IRQn, .rstidx = EPWM1_RST, .modid = EPWM1_MODULE },
  78. #endif
  79. #if (EPWM_CNT==0)
  80. 0
  81. #endif
  82. };
  83. static struct rt_inputcapture_ops nu_epwmcap_ops =
  84. {
  85. .init = nu_epwmcap_init,
  86. .open = nu_epwmcap_open,
  87. .close = nu_epwmcap_close,
  88. .get_pulsewidth = nu_epwmcap_get_pulsewidth,
  89. };
  90. /* Functions define ------------------------------------------------------------*/
  91. #if defined(BSP_USING_EPWM0_CAPTURE)
  92. void EPWM0P0_IRQHandler(void)
  93. {
  94. rt_interrupt_enter();
  95. nu_epwmcap_isr(&nu_epwmcap_arr[EPWM0I0_IDX]);
  96. nu_epwmcap_isr(&nu_epwmcap_arr[EPWM0I1_IDX]);
  97. rt_interrupt_leave();
  98. }
  99. void EPWM0P1_IRQHandler(void)
  100. {
  101. rt_interrupt_enter();
  102. nu_epwmcap_isr(&nu_epwmcap_arr[EPWM0I2_IDX]);
  103. nu_epwmcap_isr(&nu_epwmcap_arr[EPWM0I3_IDX]);
  104. rt_interrupt_leave();
  105. }
  106. void EPWM0P2_IRQHandler(void)
  107. {
  108. rt_interrupt_enter();
  109. nu_epwmcap_isr(&nu_epwmcap_arr[EPWM0I4_IDX]);
  110. nu_epwmcap_isr(&nu_epwmcap_arr[EPWM0I5_IDX]);
  111. rt_interrupt_leave();
  112. }
  113. #endif
  114. #if defined(BSP_USING_EPWM1_CAPTURE)
  115. void EPWM1P0_IRQHandler(void)
  116. {
  117. rt_interrupt_enter();
  118. nu_epwmcap_isr(&nu_epwmcap_arr[EPWM1I0_IDX]);
  119. nu_epwmcap_isr(&nu_epwmcap_arr[EPWM1I1_IDX]);
  120. rt_interrupt_leave();
  121. }
  122. void EPWM1P1_IRQHandler(void)
  123. {
  124. rt_interrupt_enter();
  125. nu_epwmcap_isr(&nu_epwmcap_arr[EPWM1I2_IDX]);
  126. nu_epwmcap_isr(&nu_epwmcap_arr[EPWM1I3_IDX]);
  127. rt_interrupt_leave();
  128. }
  129. void EPWM1P2_IRQHandler(void)
  130. {
  131. rt_interrupt_enter();
  132. nu_epwmcap_isr(&nu_epwmcap_arr[EPWM1I4_IDX]);
  133. nu_epwmcap_isr(&nu_epwmcap_arr[EPWM1I5_IDX]);
  134. rt_interrupt_leave();
  135. }
  136. #endif
  137. static void nu_epwmcap_isr(nu_epwmcap_t psNuEpwmCap)
  138. {
  139. if (EPWM_GetCaptureIntFlag(psNuEpwmCap->base, psNuEpwmCap->u8Channel) != 0)
  140. {
  141. /* Calculate pulse width */
  142. if (CalPulseWidth(psNuEpwmCap) == RT_EOK)
  143. {
  144. rt_hw_inputcapture_isr(&psNuEpwmCap->parent, psNuEpwmCap->input_data_level);
  145. }
  146. }
  147. }
  148. static rt_err_t CalPulseWidth(nu_epwmcap_t psNuEpwmCap)
  149. {
  150. rt_bool_t bWrapAroundFlag = RT_FALSE;
  151. /* Check rising/falling capture counter is overflow or not */
  152. if (EPWM_GetWrapAroundFlag(psNuEpwmCap->base, psNuEpwmCap->u8Channel))
  153. {
  154. EPWM_ClearWrapAroundFlag(psNuEpwmCap->base, psNuEpwmCap->u8Channel);
  155. bWrapAroundFlag = RT_TRUE;
  156. }
  157. /* Read the capture counter value if falling/rising edge */
  158. if (EPWM_GetCaptureIntFlag(psNuEpwmCap->base, psNuEpwmCap->u8Channel) == 1)//Rising edge
  159. {
  160. EPWM_ClearCaptureIntFlag(psNuEpwmCap->base, psNuEpwmCap->u8Channel, EPWM_CAPTURE_INT_RISING_LATCH);
  161. if (bWrapAroundFlag)
  162. {
  163. psNuEpwmCap->u32CurrentRisingCnt = 0x10000;
  164. }
  165. psNuEpwmCap->u32CurrentRisingCnt += EPWM_GET_CAPTURE_RISING_DATA(psNuEpwmCap->base, psNuEpwmCap->u8Channel);
  166. }
  167. else if (EPWM_GetCaptureIntFlag(psNuEpwmCap->base, psNuEpwmCap->u8Channel) == 2)//Falling edge
  168. {
  169. EPWM_ClearCaptureIntFlag(psNuEpwmCap->base, psNuEpwmCap->u8Channel, EPWM_CAPTURE_INT_FALLING_LATCH);
  170. if (bWrapAroundFlag)
  171. {
  172. psNuEpwmCap->u32CurrentFallingCnt = 0x10000;
  173. }
  174. psNuEpwmCap->u32CurrentFallingCnt += EPWM_GET_CAPTURE_FALLING_DATA(psNuEpwmCap->base, psNuEpwmCap->u8Channel);
  175. }
  176. else //Rising & Falling edge
  177. {
  178. EPWM_ClearCaptureIntFlag(psNuEpwmCap->base, psNuEpwmCap->u8Channel, EPWM_CAPTURE_INT_RISING_LATCH);
  179. EPWM_ClearCaptureIntFlag(psNuEpwmCap->base, psNuEpwmCap->u8Channel, EPWM_CAPTURE_INT_FALLING_LATCH);
  180. return -(RT_ERROR);
  181. }
  182. return RT_EOK;
  183. }
  184. static rt_err_t nu_epwmcap_get_pulsewidth(struct rt_inputcapture_device *inputcapture, rt_uint32_t *pulsewidth_us)
  185. {
  186. rt_err_t ret = RT_EOK;
  187. nu_epwmcap_t psNuEpwmCap = (nu_epwmcap_t)inputcapture;
  188. RT_ASSERT(psNuEpwmCap != RT_NULL);
  189. if (psNuEpwmCap->u32CurrentFallingCnt)
  190. {
  191. *pulsewidth_us = psNuEpwmCap->u32CurrentFallingCnt;
  192. psNuEpwmCap->input_data_level = RT_FALSE;
  193. psNuEpwmCap->u32CurrentFallingCnt = 0;
  194. }
  195. else if (psNuEpwmCap->u32CurrentRisingCnt)
  196. {
  197. *pulsewidth_us = psNuEpwmCap->u32CurrentRisingCnt;
  198. psNuEpwmCap->input_data_level = RT_TRUE;
  199. psNuEpwmCap->u32CurrentRisingCnt = 0;
  200. }
  201. else
  202. {
  203. ret = -RT_ERROR;
  204. }
  205. return -(ret);
  206. }
  207. static rt_err_t nu_epwmcap_init(struct rt_inputcapture_device *inputcapture)
  208. {
  209. return RT_EOK;
  210. }
  211. static rt_err_t nu_epwmcap_open(struct rt_inputcapture_device *inputcapture)
  212. {
  213. rt_err_t ret = RT_EOK;
  214. nu_epwmcap_t psNuEpwmCap = (nu_epwmcap_t) inputcapture;
  215. RT_ASSERT(psNuEpwmCap != RT_NULL);
  216. /* Set capture time as 1000 nanosecond */
  217. EPWM_ConfigCaptureChannel(psNuEpwmCap->base, psNuEpwmCap->u8Channel, 1000, 0);
  218. /* Enable capture rising/falling edge interrupt */
  219. EPWM_EnableCaptureInt(psNuEpwmCap->base, psNuEpwmCap->u8Channel, EPWM_CAPTURE_INT_FALLING_LATCH | EPWM_CAPTURE_INT_RISING_LATCH);
  220. /* Enable Capture Function for EPWM */
  221. EPWM_EnableCapture(psNuEpwmCap->base, 0x1 << psNuEpwmCap->u8Channel);
  222. /* Enable rising/falling capture reload */
  223. psNuEpwmCap->base->CAPCTL |= (0x1 << (EPWM_CAPCTL_RCRLDEN0_Pos + psNuEpwmCap->u8Channel))
  224. | (0x1 << (EPWM_CAPCTL_FCRLDEN0_Pos + psNuEpwmCap->u8Channel));
  225. /* Set counter type as down count */
  226. EPWM_SET_ALIGNED_TYPE(psNuEpwmCap->base, 0x1 << psNuEpwmCap->u8Channel, EPWM_UP_COUNTER);
  227. /* Enable EPWM Timer */
  228. EPWM_Start(psNuEpwmCap->base, 0x1 << psNuEpwmCap->u8Channel);
  229. /* Enable EPWMxPx interrupt. */
  230. NVIC_EnableIRQ(psNuEpwmCap->irqn);
  231. return ret;
  232. }
  233. static rt_err_t nu_epwmcap_close(struct rt_inputcapture_device *inputcapture)
  234. {
  235. rt_err_t ret = RT_EOK;
  236. nu_epwmcap_t psNuEpwmCap = (nu_epwmcap_t) inputcapture;
  237. RT_ASSERT(psNuEpwmCap != RT_NULL);
  238. /* Disable capture rising/falling edge interrupt */
  239. EPWM_DisableCaptureInt(psNuEpwmCap->base, psNuEpwmCap->u8Channel, EPWM_CAPTURE_INT_FALLING_LATCH | EPWM_CAPTURE_INT_RISING_LATCH);
  240. /* Stop EPWM Timer */
  241. EPWM_ForceStop(psNuEpwmCap->base, 0x1 << psNuEpwmCap->u8Channel);
  242. /* Disable EPWMxPx interrupt */
  243. if ((psNuEpwmCap->base->CNTEN & (0x3 << (psNuEpwmCap->u8Channel / 2 * 2))) == 0u)
  244. NVIC_DisableIRQ(psNuEpwmCap->irqn);
  245. return ret;
  246. }
  247. /* Init and register epwm capture */
  248. int rt_hw_epwmcap_init(void)
  249. {
  250. int i;
  251. rt_err_t ret = RT_EOK;
  252. for (i = (EPWM_START + 1); i < EPWM_CNT; i++)
  253. {
  254. nu_epwmcap_t psNuEpwmCap = &nu_epwmcap_arr[i];
  255. psNuEpwmCap->u8Channel = i % EPWM_CHANNEL_NUM;
  256. psNuEpwmCap->u32CurrentRisingCnt = 0;
  257. psNuEpwmCap->u32CurrentFallingCnt = 0;
  258. psNuEpwmCap->parent.ops = &nu_epwmcap_ops;
  259. if ((psNuEpwmCap->u8Channel % EPWM_CHANNEL_NUM) == 0)
  260. {
  261. /* Enable epwm module */
  262. CLK_EnableModuleClock(psNuEpwmCap->modid);
  263. SYS_ResetModule(psNuEpwmCap->rstidx);
  264. }
  265. /* register inputcapture device */
  266. ret = rt_device_inputcapture_register(&psNuEpwmCap->parent, psNuEpwmCap->name, psNuEpwmCap);
  267. RT_ASSERT(ret == RT_EOK);
  268. }
  269. return 0;
  270. }
  271. INIT_DEVICE_EXPORT(rt_hw_epwmcap_init);
  272. #endif //#if defined(BSP_USING_EPWM_CAPTURE)