drv_bpwm_capture.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331
  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-8-19 Philo First version
  10. *
  11. ******************************************************************************/
  12. #include <rtconfig.h>
  13. #if defined(BSP_USING_BPWM_CAPTURE)
  14. #include <rtdevice.h>
  15. #include "NuMicro.h"
  16. /* Private typedef --------------------------------------------------------------*/
  17. enum
  18. {
  19. BPWM_START = -1,
  20. #if defined(BSP_USING_BPWM0_CAPTURE)
  21. BPWM0I0_IDX,
  22. BPWM0I1_IDX,
  23. BPWM0I2_IDX,
  24. BPWM0I3_IDX,
  25. BPWM0I4_IDX,
  26. BPWM0I5_IDX,
  27. #endif
  28. #if defined(BSP_USING_BPWM1_CAPTURE)
  29. BPWM1I0_IDX,
  30. BPWM1I1_IDX,
  31. BPWM1I2_IDX,
  32. BPWM1I3_IDX,
  33. BPWM1I4_IDX,
  34. BPWM1I5_IDX,
  35. #endif
  36. BPWM_CNT
  37. };
  38. struct nu_bpwmcap
  39. {
  40. struct rt_inputcapture_device parent;
  41. BPWM_T *base;
  42. char *name;
  43. IRQn_Type irqn;
  44. uint32_t rstidx;
  45. uint32_t modid;
  46. float fUsPerTick;
  47. uint8_t u8Channel;
  48. uint8_t u8DummyData;
  49. uint32_t u32CurrentRisingCnt;
  50. uint32_t u32CurrentFallingCnt;
  51. uint32_t u32LastRisingCnt;
  52. uint32_t u32LastFallingCnt;
  53. rt_bool_t input_data_level;
  54. };
  55. typedef struct nu_bpwmcap *nu_bpwmcap_t;
  56. /* Private functions ------------------------------------------------------------*/
  57. static rt_err_t nu_bpwmcap_init(struct rt_inputcapture_device *inputcapture);
  58. static rt_err_t nu_bpwmcap_open(struct rt_inputcapture_device *inputcapture);
  59. static rt_err_t nu_bpwmcap_close(struct rt_inputcapture_device *inputcapture);
  60. static rt_err_t nu_bpwmcap_get_pulsewidth(struct rt_inputcapture_device *inputcapture, rt_uint32_t *pulsewidth_us);
  61. /* Private define ---------------------------------------------------------------*/
  62. #define NU_DUMMY_DATA 2 /* First rising and falling edge should be ignore */
  63. #define NU_NO_EDGE 0
  64. #define NU_RISING_EDGE 1
  65. #define NU_FALLING_EDGE 2
  66. /* Public functions -------------------------------------------------------------*/
  67. /* Private variables ------------------------------------------------------------*/
  68. static struct nu_bpwmcap nu_bpwmcap_arr [] =
  69. {
  70. #if defined(BSP_USING_BPWM0_CAPTURE)
  71. { .base = BPWM0, .name = "bpwm0i0", .irqn = BPWM0_IRQn, .rstidx = BPWM0_RST, .modid = BPWM0_MODULE },
  72. { .base = BPWM0, .name = "bpwm0i1", .irqn = BPWM0_IRQn, .rstidx = BPWM0_RST, .modid = BPWM0_MODULE },
  73. { .base = BPWM0, .name = "bpwm0i2", .irqn = BPWM0_IRQn, .rstidx = BPWM0_RST, .modid = BPWM0_MODULE },
  74. { .base = BPWM0, .name = "bpwm0i3", .irqn = BPWM0_IRQn, .rstidx = BPWM0_RST, .modid = BPWM0_MODULE },
  75. { .base = BPWM0, .name = "bpwm0i4", .irqn = BPWM0_IRQn, .rstidx = BPWM0_RST, .modid = BPWM0_MODULE },
  76. { .base = BPWM0, .name = "bpwm0i5", .irqn = BPWM0_IRQn, .rstidx = BPWM0_RST, .modid = BPWM0_MODULE },
  77. #endif
  78. #if defined(BSP_USING_BPWM1_CAPTURE)
  79. { .base = BPWM1, .name = "bpwm1i0", .irqn = BPWM1_IRQn, .rstidx = BPWM1_RST, .modid = BPWM1_MODULE },
  80. { .base = BPWM1, .name = "bpwm1i1", .irqn = BPWM1_IRQn, .rstidx = BPWM1_RST, .modid = BPWM1_MODULE },
  81. { .base = BPWM1, .name = "bpwm1i2", .irqn = BPWM1_IRQn, .rstidx = BPWM1_RST, .modid = BPWM1_MODULE },
  82. { .base = BPWM1, .name = "bpwm1i3", .irqn = BPWM1_IRQn, .rstidx = BPWM1_RST, .modid = BPWM1_MODULE },
  83. { .base = BPWM1, .name = "bpwm1i4", .irqn = BPWM1_IRQn, .rstidx = BPWM1_RST, .modid = BPWM1_MODULE },
  84. { .base = BPWM1, .name = "bpwm1i5", .irqn = BPWM1_IRQn, .rstidx = BPWM1_RST, .modid = BPWM1_MODULE },
  85. #endif
  86. #if (BPWM_CNT==0)
  87. 0
  88. #endif
  89. };
  90. static struct rt_inputcapture_ops nu_bpwmcap_ops =
  91. {
  92. .init = nu_bpwmcap_init,
  93. .open = nu_bpwmcap_open,
  94. .close = nu_bpwmcap_close,
  95. .get_pulsewidth = nu_bpwmcap_get_pulsewidth,
  96. };
  97. /* Functions define ------------------------------------------------------------*/
  98. static void nu_bpwmcap_isr(nu_bpwmcap_t psNuBpwmCapBase)
  99. {
  100. uint32_t u32Status;
  101. int i;
  102. for (i = 0; i < BPWM_CHANNEL_NUM ; i++)
  103. {
  104. nu_bpwmcap_t psNuBpwmCap = psNuBpwmCapBase + i;
  105. if (psNuBpwmCap->u8DummyData < NU_DUMMY_DATA)
  106. {
  107. psNuBpwmCap->u8DummyData++;
  108. }
  109. else
  110. {
  111. u32Status = BPWM_GetCaptureIntFlag(psNuBpwmCap->base, psNuBpwmCap->u8Channel);
  112. switch (u32Status)
  113. {
  114. case NU_NO_EDGE:
  115. break;
  116. case NU_RISING_EDGE:
  117. BPWM_ClearCaptureIntFlag(psNuBpwmCap->base, psNuBpwmCap->u8Channel, BPWM_CAPTURE_INT_RISING_LATCH);
  118. psNuBpwmCap->u32CurrentRisingCnt = BPWM_GET_CAPTURE_RISING_DATA(psNuBpwmCap->base, psNuBpwmCap->u8Channel);
  119. rt_hw_inputcapture_isr(&psNuBpwmCap->parent, psNuBpwmCap->input_data_level);
  120. break;
  121. case NU_FALLING_EDGE:
  122. BPWM_ClearCaptureIntFlag(psNuBpwmCap->base, psNuBpwmCap->u8Channel, BPWM_CAPTURE_INT_FALLING_LATCH);
  123. psNuBpwmCap->u32CurrentFallingCnt = BPWM_GET_CAPTURE_FALLING_DATA(psNuBpwmCap->base, psNuBpwmCap->u8Channel);
  124. rt_hw_inputcapture_isr(&psNuBpwmCap->parent, psNuBpwmCap->input_data_level);
  125. break;
  126. default:
  127. BPWM_ClearCaptureIntFlag(psNuBpwmCap->base, psNuBpwmCap->u8Channel, BPWM_CAPTURE_INT_RISING_LATCH | BPWM_CAPTURE_INT_FALLING_LATCH);
  128. BPWM_GET_CAPTURE_RISING_DATA(psNuBpwmCap->base, psNuBpwmCap->u8Channel);
  129. BPWM_GET_CAPTURE_FALLING_DATA(psNuBpwmCap->base, psNuBpwmCap->u8Channel);
  130. break;
  131. }
  132. }
  133. }
  134. }
  135. #if defined(BSP_USING_BPWM0_CAPTURE)
  136. void BPWM0_IRQHandler(void)
  137. {
  138. /* enter interrupt */
  139. rt_interrupt_enter();
  140. nu_bpwmcap_isr(&nu_bpwmcap_arr[BPWM0I0_IDX]);
  141. /* leave interrupt */
  142. rt_interrupt_leave();
  143. }
  144. #endif //defined(BSP_USING_BPWM0_CAPTURE)
  145. #if defined(BSP_USING_BPWM1_CAPTURE)
  146. void BPWM1_IRQHandler(void)
  147. {
  148. /* enter interrupt */
  149. rt_interrupt_enter();
  150. nu_bpwmcap_isr(&nu_bpwmcap_arr[BPWM1I0_IDX]);
  151. /* leave interrupt */
  152. rt_interrupt_leave();
  153. }
  154. #endif //defined(BSP_USING_BPWM1_CAPTURE)
  155. static rt_err_t nu_bpwmcap_get_pulsewidth(struct rt_inputcapture_device *inputcapture, rt_uint32_t *pulsewidth_us)
  156. {
  157. rt_err_t ret = RT_EOK;
  158. nu_bpwmcap_t psNuBpwmCap;
  159. float fTempCnt;
  160. psNuBpwmCap = (nu_bpwmcap_t)inputcapture;
  161. if (psNuBpwmCap->u32CurrentFallingCnt)
  162. {
  163. if (psNuBpwmCap->u32CurrentFallingCnt > psNuBpwmCap->u32LastRisingCnt)
  164. fTempCnt = psNuBpwmCap->u32CurrentFallingCnt - psNuBpwmCap->u32LastRisingCnt;
  165. else /* Overrun case */
  166. fTempCnt = psNuBpwmCap->u32CurrentFallingCnt + (0x10000 - psNuBpwmCap->u32LastRisingCnt);
  167. *pulsewidth_us = fTempCnt * psNuBpwmCap->fUsPerTick;
  168. psNuBpwmCap->input_data_level = RT_FALSE;
  169. psNuBpwmCap->u32LastFallingCnt = psNuBpwmCap->u32CurrentFallingCnt;
  170. psNuBpwmCap->u32CurrentFallingCnt = 0;
  171. }
  172. else if (psNuBpwmCap->u32CurrentRisingCnt)
  173. {
  174. if (psNuBpwmCap->u32CurrentRisingCnt > psNuBpwmCap->u32LastFallingCnt)
  175. fTempCnt = psNuBpwmCap->u32CurrentRisingCnt - psNuBpwmCap->u32LastFallingCnt;
  176. else /* Overrun case */
  177. fTempCnt = psNuBpwmCap->u32CurrentRisingCnt + (0x10000 - psNuBpwmCap->u32LastFallingCnt);
  178. *pulsewidth_us = fTempCnt * psNuBpwmCap->fUsPerTick;
  179. psNuBpwmCap->input_data_level = RT_TRUE;
  180. psNuBpwmCap->u32LastRisingCnt = psNuBpwmCap->u32CurrentRisingCnt;
  181. psNuBpwmCap->u32CurrentRisingCnt = 0;
  182. }
  183. else
  184. {
  185. ret = RT_ERROR;
  186. }
  187. return -(ret);
  188. }
  189. static rt_err_t nu_bpwmcap_init(struct rt_inputcapture_device *inputcapture)
  190. {
  191. rt_err_t ret = RT_EOK;
  192. nu_bpwmcap_t psNuBpwmCap;
  193. RT_ASSERT(inputcapture);
  194. psNuBpwmCap = (nu_bpwmcap_t) inputcapture;
  195. psNuBpwmCap->u8DummyData = 0;
  196. psNuBpwmCap->u32CurrentFallingCnt = 0;
  197. psNuBpwmCap->u32CurrentRisingCnt = 0;
  198. psNuBpwmCap->u32LastRisingCnt = 0;
  199. psNuBpwmCap->u32LastFallingCnt = 0;
  200. psNuBpwmCap->parent.ops = &nu_bpwmcap_ops;
  201. if ((psNuBpwmCap->u8Channel % BPWM_CHANNEL_NUM) == 0)
  202. {
  203. /* Enable bpwm module */
  204. CLK_EnableModuleClock(psNuBpwmCap->modid);
  205. SYS_ResetModule(psNuBpwmCap->rstidx);
  206. }
  207. return -(ret);
  208. }
  209. static rt_err_t nu_bpwmcap_open(struct rt_inputcapture_device *inputcapture)
  210. {
  211. nu_bpwmcap_t psNuBpwmCap;
  212. RT_ASSERT(inputcapture);
  213. psNuBpwmCap = (nu_bpwmcap_t) inputcapture;
  214. /* Set capture time as 500 nano second */
  215. psNuBpwmCap->fUsPerTick = (float)BPWM_ConfigCaptureChannel(psNuBpwmCap->base, 0, 500, 0) / 1000;
  216. /* Set counter type as up count */
  217. BPWM_SET_ALIGNED_TYPE(psNuBpwmCap->base, 0, BPWM_UP_COUNTER);
  218. /* Enable BPWM Timer */
  219. BPWM_Start(psNuBpwmCap->base, 0);
  220. /* Enable capture rising/falling edge interrupt */
  221. BPWM_EnableCaptureInt(psNuBpwmCap->base, psNuBpwmCap->u8Channel, BPWM_CAPTURE_INT_FALLING_LATCH | BPWM_CAPTURE_INT_RISING_LATCH);
  222. /* Enable Capture Function for BPWM */
  223. BPWM_EnableCapture(psNuBpwmCap->base, 0x1 << psNuBpwmCap->u8Channel);
  224. /* Enable BPWM NVIC interrupt */
  225. if ((psNuBpwmCap->base->CAPCTL & ((0x1 << BPWM_CHANNEL_NUM) - 1)) != 0u)
  226. NVIC_EnableIRQ(psNuBpwmCap->irqn);
  227. return RT_EOK;
  228. }
  229. static rt_err_t nu_bpwmcap_close(struct rt_inputcapture_device *inputcapture)
  230. {
  231. nu_bpwmcap_t psNuBpwmCap;
  232. RT_ASSERT(inputcapture);
  233. psNuBpwmCap = (nu_bpwmcap_t) inputcapture;
  234. /* Enable Capture Function for BPWM */
  235. BPWM_DisableCapture(psNuBpwmCap->base, 0x1 << psNuBpwmCap->u8Channel);
  236. /* Disable capture rising/falling edge interrupt */
  237. BPWM_DisableCaptureInt(psNuBpwmCap->base, psNuBpwmCap->u8Channel, BPWM_CAPTURE_INT_FALLING_LATCH | BPWM_CAPTURE_INT_RISING_LATCH);
  238. /* Disable BPWM NVIC interrupt */
  239. if ((psNuBpwmCap->base->CAPCTL & ((0x1 << BPWM_CHANNEL_NUM) - 1)) == 0u)
  240. NVIC_DisableIRQ(psNuBpwmCap->irqn);
  241. return RT_EOK;
  242. }
  243. /* Init and register bpwm capture */
  244. static int nu_bpwm_capture_device_init(void)
  245. {
  246. int i;
  247. rt_err_t ret = RT_EOK;
  248. for (i = (BPWM_START + 1); i < BPWM_CNT; i++)
  249. {
  250. nu_bpwmcap_t psNuBpwmCap = &nu_bpwmcap_arr[i];
  251. psNuBpwmCap->u8Channel = i % BPWM_CHANNEL_NUM;
  252. psNuBpwmCap->u8DummyData = 0;
  253. psNuBpwmCap->u32CurrentFallingCnt = 0;
  254. psNuBpwmCap->u32CurrentRisingCnt = 0;
  255. psNuBpwmCap->u32LastRisingCnt = 0;
  256. psNuBpwmCap->u32LastFallingCnt = 0;
  257. psNuBpwmCap->parent.ops = &nu_bpwmcap_ops;
  258. if ((psNuBpwmCap->u8Channel % BPWM_CHANNEL_NUM) == 0)
  259. {
  260. /* Enable bpwm module */
  261. CLK_EnableModuleClock(psNuBpwmCap->modid);
  262. SYS_ResetModule(psNuBpwmCap->rstidx);
  263. }
  264. /* register inputcapture device */
  265. ret = rt_device_inputcapture_register(&psNuBpwmCap->parent, psNuBpwmCap->name, psNuBpwmCap);
  266. RT_ASSERT(ret == RT_EOK);
  267. }
  268. return 0;
  269. }
  270. INIT_DEVICE_EXPORT(nu_bpwm_capture_device_init);
  271. #endif //#if defined(BSP_USING_BPWM_CAPTURE)