drv_hwtimer.c 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. /*
  2. * Copyright (c) 2006-2023, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2018-04-17 WangBing the first version.
  9. * 2019-04-22 tyustli add imxrt series support
  10. * 2019-07-15 Magicoe The first version for LPC55S6x
  11. *
  12. */
  13. #include <rtthread.h>
  14. #ifdef BSP_USING_HWTIMER
  15. #define LOG_TAG "drv.hwtimer"
  16. #include <drv_log.h>
  17. #include <rtdevice.h>
  18. #include "drv_hwtimer.h"
  19. #include "fsl_ctimer.h"
  20. enum
  21. {
  22. #ifdef BSP_USING_CTIMER0
  23. TIM1_INDEX,
  24. #endif
  25. #ifdef BSP_USING_CTIMER3
  26. TIM2_INDEX,
  27. #endif
  28. #ifdef BSP_USING_CTIMER4
  29. TIM3_INDEX,
  30. #endif
  31. };
  32. struct lpc_hwtimer
  33. {
  34. rt_hwtimer_t time_device;
  35. CTIMER_Type* tim_handle;
  36. enum IRQn tim_irqn;
  37. char* name;
  38. };
  39. static struct lpc_hwtimer lpc_hwtimer_obj[] =
  40. {
  41. #ifdef BSP_USING_CTIMER0
  42. TIM1_CONFIG,
  43. #endif
  44. #ifdef BSP_USING_CTIMER3
  45. TIM3_CONFIG,
  46. #endif
  47. #ifdef BSP_USING_CTIMER4
  48. TIM4_CONFIG,
  49. #endif
  50. };
  51. static void NVIC_Configuration(void)
  52. {
  53. #ifdef BSP_USING_CTIMER0
  54. EnableIRQ(CTIMER0_IRQn);
  55. #endif
  56. #ifdef BSP_USING_CTIMER3
  57. EnableIRQ(CTIMER3_IRQn);
  58. #endif
  59. #ifdef BSP_USING_CTIMER4
  60. EnableIRQ(CTIMER4_IRQn);
  61. #endif
  62. }
  63. static rt_err_t lpc_ctimer_control(rt_hwtimer_t *timer, rt_uint32_t cmd, void *args)
  64. {
  65. rt_err_t err = RT_EOK;
  66. CTIMER_Type *hwtimer_dev;
  67. hwtimer_dev = (CTIMER_Type *)timer->parent.user_data;
  68. RT_ASSERT(timer != RT_NULL);
  69. switch (cmd)
  70. {
  71. case HWTIMER_CTRL_FREQ_SET:
  72. {
  73. uint32_t clk;
  74. uint32_t pre;
  75. if(hwtimer_dev == CTIMER0) clk = CLOCK_GetCTimerClkFreq(0U);
  76. if(hwtimer_dev == CTIMER3) clk = CLOCK_GetCTimerClkFreq(3U);
  77. if(hwtimer_dev == CTIMER4) clk = CLOCK_GetCTimerClkFreq(4U);
  78. pre = clk / *((uint32_t *)args) - 1;
  79. hwtimer_dev->PR = pre;
  80. }
  81. break;
  82. default:
  83. err = -RT_ENOSYS;
  84. break;
  85. }
  86. return err;
  87. }
  88. static rt_uint32_t lpc_ctimer_count_get(rt_hwtimer_t *timer)
  89. {
  90. rt_uint32_t CurrentTimer_Count;
  91. CTIMER_Type *hwtimer_dev;
  92. hwtimer_dev = (CTIMER_Type *)timer->parent.user_data;
  93. RT_ASSERT(timer != RT_NULL);
  94. CurrentTimer_Count = hwtimer_dev->TC;
  95. return CurrentTimer_Count;
  96. }
  97. static void lpc_ctimer_init(rt_hwtimer_t *timer, rt_uint32_t state)
  98. {
  99. CTIMER_Type *hwtimer_dev;
  100. ctimer_config_t cfg;
  101. hwtimer_dev = (CTIMER_Type *)timer->parent.user_data;
  102. RT_ASSERT(timer != RT_NULL);
  103. /* Use Main clock for some of the Ctimers */
  104. if(hwtimer_dev == CTIMER0) CLOCK_AttachClk(kMAIN_CLK_to_CTIMER0);
  105. if(hwtimer_dev == CTIMER3) CLOCK_AttachClk(kMAIN_CLK_to_CTIMER3);
  106. if(hwtimer_dev == CTIMER4) CLOCK_AttachClk(kMAIN_CLK_to_CTIMER4);
  107. CTIMER_Deinit(hwtimer_dev);
  108. if (state == 1)
  109. {
  110. NVIC_Configuration();
  111. CTIMER_GetDefaultConfig(&cfg);
  112. CTIMER_Init(hwtimer_dev, &cfg);
  113. }
  114. }
  115. static rt_err_t lpc_ctimer_start(rt_hwtimer_t *timer, rt_uint32_t cnt, rt_hwtimer_mode_t mode)
  116. {
  117. CTIMER_Type *hwtimer_dev;
  118. hwtimer_dev = (CTIMER_Type *)timer->parent.user_data;
  119. /* Match Configuration for Channel 0 */
  120. ctimer_match_config_t matchCfg;
  121. RT_ASSERT(timer != RT_NULL);
  122. /* Configuration*/
  123. matchCfg.enableCounterReset = true;
  124. matchCfg.enableCounterStop = (mode == HWTIMER_MODE_ONESHOT) ? true : false;;
  125. matchCfg.matchValue = cnt;
  126. matchCfg.outControl = kCTIMER_Output_NoAction;
  127. matchCfg.outPinInitState = false;
  128. matchCfg.enableInterrupt = true;
  129. CTIMER_SetupMatch(hwtimer_dev, kCTIMER_Match_1, &matchCfg);
  130. NVIC_Configuration();
  131. CTIMER_StartTimer(hwtimer_dev);
  132. return RT_EOK;
  133. }
  134. static void lpc_ctimer_stop(rt_hwtimer_t *timer)
  135. {
  136. CTIMER_Type *hwtimer_dev;
  137. hwtimer_dev = (CTIMER_Type *)timer->parent.user_data;
  138. RT_ASSERT(timer != RT_NULL);
  139. CTIMER_StopTimer(hwtimer_dev);
  140. }
  141. static const struct rt_hwtimer_ops lpc_hwtimer_ops =
  142. {
  143. .init = lpc_ctimer_init,
  144. .start = lpc_ctimer_start,
  145. .stop = lpc_ctimer_stop,
  146. .count_get = lpc_ctimer_count_get,
  147. .control = lpc_ctimer_control,
  148. };
  149. static const struct rt_hwtimer_info lpc_hwtimer_info =
  150. {
  151. 25000000, /* the maximum count frequency can be set */
  152. 6103, /* the minimum count frequency can be set */
  153. 0xFFFFFFFF,
  154. HWTIMER_CNTMODE_UP,
  155. };
  156. int rt_hw_hwtimer_init(void)
  157. {
  158. int i = 0;
  159. int result = RT_EOK;
  160. for (i = 0; i < sizeof(lpc_hwtimer_obj) / sizeof(lpc_hwtimer_obj[0]); i++)
  161. {
  162. lpc_hwtimer_obj[i].time_device.info = &lpc_hwtimer_info;
  163. lpc_hwtimer_obj[i].time_device.ops = &lpc_hwtimer_ops;
  164. if (rt_device_hwtimer_register(&lpc_hwtimer_obj[i].time_device,
  165. lpc_hwtimer_obj[i].name, lpc_hwtimer_obj[i].tim_handle) == RT_EOK)
  166. {
  167. LOG_D("%s register success", lpc_hwtimer_obj[i].name);
  168. }
  169. else
  170. {
  171. LOG_E("%s register failed", lpc_hwtimer_obj[i].name);
  172. result = -RT_ERROR;
  173. }
  174. }
  175. return result;
  176. }
  177. INIT_DEVICE_EXPORT(rt_hw_hwtimer_init);
  178. #ifdef BSP_USING_CTIMER0
  179. void CTIMER0_IRQHandler(void)
  180. {
  181. uint32_t int_stat;
  182. /* Get Interrupt status flags */
  183. int_stat = CTIMER_GetStatusFlags(CTIMER0);
  184. /* Clear the status flags that were set */
  185. CTIMER_ClearStatusFlags(CTIMER0, int_stat);
  186. rt_device_hwtimer_isr(&lpc_hwtimer_obj[TIM1_INDEX].time_device);
  187. }
  188. #endif /* BSP_USING_HWTIMER0 */
  189. #ifdef BSP_USING_CTIMER3
  190. void CTIMER3_IRQHandler(void)
  191. {
  192. uint32_t int_stat;
  193. /* Get Interrupt status flags */
  194. int_stat = CTIMER_GetStatusFlags(CTIMER3);
  195. /* Clear the status flags that were set */
  196. CTIMER_ClearStatusFlags(CTIMER3, int_stat);
  197. rt_device_hwtimer_isr(&lpc_hwtimer_obj[TIM2_INDEX].time_device);
  198. }
  199. #endif /* BSP_USING_HWTIMER3 */
  200. #ifdef BSP_USING_CTIMER4
  201. void CTIMER4_IRQHandler(void)
  202. {
  203. uint32_t int_stat;
  204. /* Get Interrupt status flags */
  205. int_stat = CTIMER_GetStatusFlags(CTIMER4);
  206. /* Clear the status flags that were set */
  207. CTIMER_ClearStatusFlags(CTIMER4, int_stat);
  208. rt_device_hwtimer_isr(&lpc_hwtimer_obj[TIM3_INDEX].time_device);
  209. }
  210. #endif /* BSP_USING_HWTIMER4 */
  211. #endif /* BSP_USING_HWTIMER */