drv_hwtimer.c 7.1 KB

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