drv_ecap.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340
  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-7 Wayne First version
  10. *
  11. ******************************************************************************/
  12. #include <rtconfig.h>
  13. #if defined(BSP_USING_ECAP)
  14. #include <rtdevice.h>
  15. #include "drv_sys.h"
  16. #include "drv_common.h"
  17. #include "nu_bitutil.h"
  18. #define ECAP_CHANNEL_NUM 0x3
  19. #define ECAP_CHANNEL_MSK ((1<<ECAP_CHANNEL_NUM)-1)
  20. #define ECAP_CLK_DIV ECAP_CAPTURE_TIMER_CLKDIV_32
  21. /* Private typedef --------------------------------------------------------------*/
  22. enum
  23. {
  24. ECAP_START = -1,
  25. #if defined(BSP_USING_ECAP0)
  26. ECAP0_IDX,
  27. ECAP1_IDX,
  28. ECAP2_IDX,
  29. #endif
  30. #if defined(BSP_USING_ECAP1)
  31. ECAP3_IDX,
  32. ECAP4_IDX,
  33. ECAP5_IDX,
  34. #endif
  35. #if defined(BSP_USING_ECAP2)
  36. ECAP6_IDX,
  37. ECAP7_IDX,
  38. ECAP8_IDX,
  39. #endif
  40. #if defined(BSP_USING_ECAP3)
  41. ECAP9_IDX,
  42. ECAP10_IDX,
  43. ECAP11_IDX,
  44. #endif
  45. ECAP_CNT
  46. };
  47. struct nu_ecap
  48. {
  49. struct rt_inputcapture_device parent;
  50. ECAP_T *base;
  51. char *name;
  52. IRQn_Type irqn;
  53. uint32_t rstidx;
  54. uint32_t modid;
  55. float fUsPerTick;
  56. uint8_t u8Channel;
  57. rt_bool_t bfirstData;
  58. uint32_t u32CurrentCnt;
  59. uint32_t u32LastCnt;
  60. rt_bool_t input_data_level;
  61. } ;
  62. typedef struct nu_ecap *nu_ecap_t;
  63. /* Private functions ------------------------------------------------------------*/
  64. static rt_err_t nu_ecap_init(struct rt_inputcapture_device *inputcapture);
  65. static rt_err_t nu_ecap_open(struct rt_inputcapture_device *inputcapture);
  66. static rt_err_t nu_ecap_close(struct rt_inputcapture_device *inputcapture);
  67. static rt_err_t nu_ecap_get_pulsewidth(struct rt_inputcapture_device *inputcapture, rt_uint32_t *pulsewidth_us);
  68. static void nu_ecap_isr(nu_ecap_t psNuEcap);
  69. /* Private define ---------------------------------------------------------------*/
  70. #define NU_ECAP_GET_LEVEL(status, channel) ((status & (1<<(ECAP_STATUS_CAP0_Pos+channel)))?0:1)
  71. #define ECAP_GET_CLK_DIV_INDEX(ecap) ((ecap)->CTL1 = ((ecap)->CTL1 & ECAP_CTL1_CLKSEL_Msk)>>ECAP_CTL1_CLKSEL_Pos)
  72. /* Public functions -------------------------------------------------------------*/
  73. /* Private variables ------------------------------------------------------------*/
  74. static struct nu_ecap nu_ecap_arr [] =
  75. {
  76. #if defined(BSP_USING_ECAP0)
  77. { .base = ECAP0, .name = "ecap0i0", .irqn = ECAP0_IRQn, .rstidx = ECAP0_RST, .modid = ECAP0_MODULE },
  78. { .base = ECAP0, .name = "ecap0i1", .irqn = ECAP0_IRQn, .rstidx = ECAP0_RST, .modid = ECAP0_MODULE },
  79. { .base = ECAP0, .name = "ecap0i2", .irqn = ECAP0_IRQn, .rstidx = ECAP0_RST, .modid = ECAP0_MODULE },
  80. #endif
  81. #if defined(BSP_USING_ECAP1)
  82. { .base = ECAP1, .name = "ecap1i0", .irqn = ECAP1_IRQn, .rstidx = ECAP1_RST, .modid = ECAP1_MODULE },
  83. { .base = ECAP1, .name = "ecap1i1", .irqn = ECAP1_IRQn, .rstidx = ECAP1_RST, .modid = ECAP1_MODULE },
  84. { .base = ECAP1, .name = "ecap1i2", .irqn = ECAP1_IRQn, .rstidx = ECAP1_RST, .modid = ECAP1_MODULE },
  85. #endif
  86. #if defined(BSP_USING_ECAP2)
  87. { .base = ECAP2, .name = "ecap2i0", .irqn = ECAP2_IRQn, .rstidx = ECAP1_RST, .modid = ECAP2_MODULE },
  88. { .base = ECAP2, .name = "ecap2i1", .irqn = ECAP2_IRQn, .rstidx = ECAP1_RST, .modid = ECAP2_MODULE },
  89. { .base = ECAP2, .name = "ecap2i2", .irqn = ECAP2_IRQn, .rstidx = ECAP1_RST, .modid = ECAP2_MODULE },
  90. #endif
  91. #if defined(BSP_USING_ECAP3)
  92. { .base = ECAP3, .name = "ecap3i0", .irqn = ECAP3_IRQn, .rstidx = ECAP3_RST, .modid = ECAP3_MODULE },
  93. { .base = ECAP3, .name = "ecap3i1", .irqn = ECAP3_IRQn, .rstidx = ECAP3_RST, .modid = ECAP3_MODULE },
  94. { .base = ECAP3, .name = "ecap3i2", .irqn = ECAP3_IRQn, .rstidx = ECAP3_RST, .modid = ECAP3_MODULE },
  95. #endif
  96. };
  97. static struct rt_inputcapture_ops nu_ecap_ops =
  98. {
  99. .init = nu_ecap_init,
  100. .open = nu_ecap_open,
  101. .close = nu_ecap_close,
  102. .get_pulsewidth = nu_ecap_get_pulsewidth,
  103. };
  104. /* Functions define ------------------------------------------------------------*/
  105. #if defined(BSP_USING_ECAP0)
  106. void ECAP0_IRQHandler(void)
  107. {
  108. rt_interrupt_enter();
  109. nu_ecap_isr((void *)&nu_ecap_arr[ECAP0_IDX]);
  110. rt_interrupt_leave();
  111. }
  112. #endif
  113. #if defined(BSP_USING_ECAP1)
  114. void ECAP1_IRQHandler(void)
  115. {
  116. rt_interrupt_enter();
  117. nu_ecap_isr((void *)&nu_ecap_arr[ECAP3_IDX]);
  118. rt_interrupt_leave();
  119. }
  120. #endif
  121. #if defined(BSP_USING_ECAP2)
  122. void ECAP2_IRQHandler(void)
  123. {
  124. rt_interrupt_enter();
  125. nu_ecap_isr((void *)&nu_ecap_arr[ECAP6_IDX]);
  126. rt_interrupt_leave();
  127. }
  128. #endif
  129. #if defined(BSP_USING_ECAP3)
  130. void ECAP3_IRQHandler(void)
  131. {
  132. rt_interrupt_enter();
  133. nu_ecap_isr((void *)&nu_ecap_arr[ECAP9_IDX]);
  134. rt_interrupt_leave();
  135. }
  136. #endif
  137. static void nu_ecap_isr(nu_ecap_t psNuEcapBase)
  138. {
  139. int i32ChnId;
  140. ECAP_T *base = psNuEcapBase->base;
  141. /* Get input Capture status */
  142. uint32_t u32Status = ECAP_GET_INT_STATUS(base);
  143. uint32_t u32ChStatus = u32Status & ECAP_CHANNEL_MSK;
  144. /* Check input capture channel flag */
  145. /* Find index of pin is attached in pool. */
  146. while ((i32ChnId = nu_ctz(u32ChStatus)) < ECAP_CHANNEL_NUM) // Count Trailing Zeros ==> Find First One
  147. {
  148. if (u32ChStatus & (ECAP_STATUS_CAPTF0_Msk << i32ChnId))
  149. {
  150. nu_ecap_t psNuEcap = psNuEcapBase + i32ChnId;
  151. /* Clear input capture channel flag */
  152. ECAP_CLR_CAPTURE_FLAG(base, 1 << (ECAP_STATUS_CAPTF0_Pos + i32ChnId));
  153. psNuEcap->input_data_level = NU_ECAP_GET_LEVEL(u32Status, i32ChnId);
  154. psNuEcap->u32CurrentCnt = ECAP_GET_CNT_HOLD_VALUE(base, i32ChnId);
  155. rt_hw_inputcapture_isr(&psNuEcap->parent, psNuEcap->input_data_level);
  156. }
  157. u32ChStatus &= ~(1 << i32ChnId);
  158. }
  159. }
  160. static rt_err_t nu_ecap_get_pulsewidth(struct rt_inputcapture_device *inputcapture, rt_uint32_t *pulsewidth_us)
  161. {
  162. rt_err_t ret = RT_EOK;
  163. float fTempCnt;
  164. nu_ecap_t psNuEcap = (nu_ecap_t) inputcapture;
  165. RT_ASSERT(inputcapture != RT_NULL);
  166. if (psNuEcap->bfirstData)
  167. {
  168. psNuEcap->bfirstData = RT_FALSE;
  169. ret = -RT_ERROR;
  170. return -(ret);
  171. }
  172. if (psNuEcap->u32CurrentCnt > psNuEcap->u32LastCnt)
  173. fTempCnt = psNuEcap->u32CurrentCnt - psNuEcap->u32LastCnt;
  174. else /* Overrun case */
  175. fTempCnt = psNuEcap->u32CurrentCnt + ((0x1000000 - psNuEcap->u32LastCnt) + 1);
  176. *pulsewidth_us = (int)(fTempCnt * psNuEcap->fUsPerTick);
  177. psNuEcap->u32LastCnt = psNuEcap->u32CurrentCnt;
  178. return -(ret);
  179. }
  180. static float get_ecap_tick_time_us(nu_ecap_t psNuEcap)
  181. {
  182. uint8_t u8ClockDivider[8] = { 1, 4, 16, 32, 64, 96, 112, 128};
  183. if (psNuEcap->base == ECAP0 || (psNuEcap->base == ECAP2))
  184. return ((float)1000000 / ((float)CLK_GetPCLK0Freq() / u8ClockDivider[(psNuEcap->base->CTL1 & ECAP_CTL1_CLKSEL_Msk) >> ECAP_CTL1_CLKSEL_Pos]));
  185. else
  186. return ((float)1000000 / ((float)CLK_GetPCLK1Freq() / u8ClockDivider[(psNuEcap->base->CTL1 & ECAP_CTL1_CLKSEL_Msk) >> ECAP_CTL1_CLKSEL_Pos]));
  187. }
  188. static rt_err_t nu_ecap_init(struct rt_inputcapture_device *inputcapture)
  189. {
  190. return RT_EOK;
  191. }
  192. static rt_err_t nu_ecap_open(struct rt_inputcapture_device *inputcapture)
  193. {
  194. rt_err_t ret = RT_EOK;
  195. nu_ecap_t psNuEcap = (nu_ecap_t) inputcapture;
  196. RT_ASSERT(inputcapture != RT_NULL);
  197. psNuEcap->fUsPerTick = get_ecap_tick_time_us(psNuEcap);
  198. /* Enable ECAP Input Channel */
  199. ECAP_ENABLE_INPUT_CHANNEL(psNuEcap->base, 0x1 << (ECAP_CTL0_IC0EN_Pos + psNuEcap->u8Channel));
  200. /* Input Channel interrupt enabled */
  201. ECAP_EnableINT(psNuEcap->base, 0x1 << (ECAP_CTL0_CAPIEN0_Pos + psNuEcap->u8Channel));
  202. /* ECAP_CNT starts up-counting */
  203. ECAP_CNT_START(psNuEcap->base);
  204. return ret;
  205. }
  206. static rt_err_t nu_ecap_close(struct rt_inputcapture_device *inputcapture)
  207. {
  208. rt_err_t ret = RT_EOK;
  209. nu_ecap_t psNuEcap = (nu_ecap_t) inputcapture;
  210. RT_ASSERT(inputcapture != RT_NULL);
  211. /* Input Channel interrupt disabled */
  212. ECAP_DisableINT(psNuEcap->base, 0x1 << (ECAP_CTL0_CAPIEN0_Pos + psNuEcap->u8Channel));
  213. /* Disable ECAP Input Channel */
  214. ECAP_DISABLE_INPUT_CHANNEL(psNuEcap->base, 0x1 << (ECAP_CTL0_IC0EN_Pos + psNuEcap->u8Channel));
  215. /* Clear input capture channel flag */
  216. ECAP_CLR_CAPTURE_FLAG(psNuEcap->base, 0x1 << (ECAP_STATUS_CAPTF0_Pos + psNuEcap->u8Channel));
  217. return ret;
  218. }
  219. static void nu_ecap_channel_init(ECAP_T *base)
  220. {
  221. /* Enable ECAP */
  222. ECAP_Open(base, ECAP_DISABLE_COMPARE);
  223. ECAP_SEL_TIMER_CLK_DIV(base, ECAP_CLK_DIV);
  224. /* Select Reload function */
  225. ECAP_SET_CNT_CLEAR_EVENT(base, ECAP_CTL1_OVRLDEN_Msk);
  226. /* Enable ECAP source IC */
  227. ECAP_SEL_INPUT_SRC(base, ECAP_IC0, ECAP_CAP_INPUT_SRC_FROM_IC);
  228. ECAP_SEL_INPUT_SRC(base, ECAP_IC1, ECAP_CAP_INPUT_SRC_FROM_IC);
  229. ECAP_SEL_INPUT_SRC(base, ECAP_IC2, ECAP_CAP_INPUT_SRC_FROM_IC);
  230. /* Select IC detect rising edge */
  231. ECAP_SEL_CAPTURE_EDGE(base, ECAP_IC0, ECAP_RISING_FALLING_EDGE);
  232. ECAP_SEL_CAPTURE_EDGE(base, ECAP_IC1, ECAP_RISING_FALLING_EDGE);
  233. ECAP_SEL_CAPTURE_EDGE(base, ECAP_IC2, ECAP_RISING_FALLING_EDGE);
  234. }
  235. /* Init and register ecap capture */
  236. static int rt_hw_ecap_init(void)
  237. {
  238. int i;
  239. rt_err_t ret = RT_EOK;
  240. for (i = (ECAP_START + 1); i < ECAP_CNT; i++)
  241. {
  242. nu_ecap_t psNuEcap = &nu_ecap_arr[i];
  243. psNuEcap->u8Channel = i % ECAP_CHANNEL_NUM;
  244. psNuEcap->bfirstData = RT_TRUE;
  245. psNuEcap->u32CurrentCnt = 0;
  246. psNuEcap->u32LastCnt = 0;
  247. psNuEcap->parent.ops = &nu_ecap_ops;
  248. if ((psNuEcap->u8Channel % ECAP_CHANNEL_NUM) == 0)
  249. {
  250. uint32_t u32RegLockBackup = SYS_IsRegLocked();
  251. SYS_UnlockReg();
  252. /* register ecap module */
  253. CLK_EnableModuleClock(psNuEcap->modid);
  254. SYS_ResetModule(psNuEcap->rstidx);
  255. if (u32RegLockBackup)
  256. SYS_LockReg();
  257. nu_ecap_channel_init(psNuEcap->base);
  258. }
  259. /* register inputcapture device */
  260. ret = rt_device_inputcapture_register(&psNuEcap->parent, psNuEcap->name, psNuEcap);
  261. RT_ASSERT(ret == RT_EOK);
  262. }
  263. return 0;
  264. }
  265. INIT_DEVICE_EXPORT(rt_hw_ecap_init);
  266. #endif //#if defined(BSP_USING_ECAP)