drv_hwtimer.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  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-02-21 Yilin Sun Initial revision.
  9. */
  10. #include "drv_hwtimer.h"
  11. #ifdef BSP_USING_HWTIMER
  12. #include "fsl_mrt.h"
  13. typedef struct
  14. {
  15. rt_hwtimer_t timer_device;
  16. mrt_chnl_t channel;
  17. char *name;
  18. } mcx_hwtimer_obj_t;
  19. static inline rt_err_t mcx_hwtimer_mode_set(mcx_hwtimer_obj_t *handle, rt_hwtimer_mode_t mode)
  20. {
  21. mrt_timer_mode_t mrt_mode;
  22. switch (mode)
  23. {
  24. case HWTIMER_MODE_ONESHOT:
  25. mrt_mode = kMRT_OneShotMode;
  26. break;
  27. case HWTIMER_MODE_PERIOD:
  28. mrt_mode = kMRT_RepeatMode;
  29. break;
  30. default:
  31. return -RT_EINVAL;
  32. }
  33. MRT_SetupChannelMode(MRT0, handle->channel, mrt_mode);
  34. return RT_EOK;
  35. }
  36. static void mcx_hwtimer_init(rt_hwtimer_t *timer, rt_uint32_t state)
  37. {
  38. mrt_config_t mrt_config;
  39. MRT_GetDefaultConfig(&mrt_config);
  40. MRT_Init(MRT0, &mrt_config);
  41. }
  42. static rt_err_t mcx_hwtimer_start(rt_hwtimer_t *timer, rt_uint32_t cnt, rt_hwtimer_mode_t mode)
  43. {
  44. rt_err_t ret = RT_EOK;
  45. mcx_hwtimer_obj_t *handle = timer->parent.user_data;
  46. MRT_StopTimer(MRT0, handle->channel);
  47. ret = mcx_hwtimer_mode_set(handle, mode);
  48. if (ret != RT_EOK)
  49. {
  50. return ret;
  51. }
  52. MRT_StartTimer(MRT0, handle->channel, cnt);
  53. MRT_EnableInterrupts(MRT0, handle->channel, kMRT_TimerInterruptEnable);
  54. return ret;
  55. }
  56. static void mcx_hwtimer_stop(rt_hwtimer_t *timer)
  57. {
  58. mcx_hwtimer_obj_t *handle = timer->parent.user_data;
  59. MRT_StopTimer(MRT0, handle->channel);
  60. MRT_DisableInterrupts(MRT0, handle->channel, kMRT_TimerInterruptEnable);
  61. }
  62. static rt_uint32_t mcx_hwtimer_count_get(rt_hwtimer_t *timer)
  63. {
  64. mcx_hwtimer_obj_t *handle = timer->parent.user_data;
  65. return MRT_GetCurrentTimerCount(MRT0, handle->channel);
  66. }
  67. static rt_err_t mcx_hwtimer_control(rt_hwtimer_t *timer, rt_uint32_t cmd, void *args)
  68. {
  69. rt_err_t ret = RT_EOK;
  70. mcx_hwtimer_obj_t *handle = timer->parent.user_data;
  71. switch (cmd)
  72. {
  73. case HWTIMER_CTRL_STOP:
  74. mcx_hwtimer_stop(timer);
  75. break;
  76. case HWTIMER_CTRL_MODE_SET:
  77. ret = mcx_hwtimer_mode_set(handle, *(rt_hwtimer_mode_t *)args);
  78. if (ret != RT_EOK)
  79. {
  80. return ret;
  81. }
  82. break;
  83. default:
  84. return -RT_EINVAL;
  85. }
  86. return RT_EOK;
  87. }
  88. static mcx_hwtimer_obj_t mcx_hwtimer_list[] =
  89. {
  90. { .name = "timer0", .channel = kMRT_Channel_0, },
  91. { .name = "timer1", .channel = kMRT_Channel_1, },
  92. { .name = "timer2", .channel = kMRT_Channel_2, },
  93. { .name = "timer3", .channel = kMRT_Channel_3, },
  94. };
  95. static struct rt_hwtimer_info mcx_hwtimer_info =
  96. {
  97. .cntmode = HWTIMER_CNTMODE_DW,
  98. .maxcnt = 0x00FFFFFF, /* 24bit counter */
  99. .minfreq = 150000000,
  100. .maxfreq = 150000000,
  101. };
  102. static const struct rt_hwtimer_ops mcx_hwtimer_ops =
  103. {
  104. .init = mcx_hwtimer_init,
  105. .control = mcx_hwtimer_control,
  106. .start = mcx_hwtimer_start,
  107. .stop = mcx_hwtimer_stop,
  108. .count_get = mcx_hwtimer_count_get,
  109. };
  110. int rt_hw_hwtimer_init(void)
  111. {
  112. /* MRT frequency is fixed to AHB clock */
  113. uint32_t mrt_freq = CLOCK_GetFreq(kCLOCK_BusClk);
  114. mcx_hwtimer_info.minfreq = mrt_freq;
  115. mcx_hwtimer_info.maxfreq = mrt_freq;
  116. for (uint8_t i = 0; i < ARRAY_SIZE(mcx_hwtimer_list); i++)
  117. {
  118. mcx_hwtimer_list[i].timer_device.info = &mcx_hwtimer_info;
  119. mcx_hwtimer_list[i].timer_device.ops = &mcx_hwtimer_ops;
  120. rt_err_t ret = rt_device_hwtimer_register(&mcx_hwtimer_list[i].timer_device, mcx_hwtimer_list[i].name, &mcx_hwtimer_list[i]);
  121. if (ret != RT_EOK)
  122. {
  123. return ret;
  124. }
  125. }
  126. EnableIRQ(MRT0_IRQn);
  127. return RT_EOK;
  128. }
  129. void MRT0_IRQHandler(void)
  130. {
  131. /* Get channel interrupt flags */
  132. uint32_t mrt_flag = MRT0->IRQ_FLAG;
  133. /* Clear interrupt flags (W1C). */
  134. MRT0->IRQ_FLAG = mrt_flag;
  135. for (uint8_t i = 0; i < 4; i++)
  136. {
  137. if (mrt_flag & (1U << i))
  138. {
  139. rt_device_hwtimer_isr(&mcx_hwtimer_list[i].timer_device);
  140. }
  141. }
  142. }
  143. INIT_DEVICE_EXPORT(rt_hw_hwtimer_init);
  144. #endif /* BSP_USING_HWTIMER */