drv_bpwm_capture.c 11 KB

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