drv_hwtimer.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. /*
  2. * File : drv_hwtimer.c
  3. * This file is part of RT-Thread RTOS
  4. * COPYRIGHT (C) 2017, RT-Thread Development Team
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License along
  17. * with this program; if not, write to the Free Software Foundation, Inc.,
  18. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  19. *
  20. * Change Logs:
  21. * Date Author Notes
  22. * 2018-04-17 WangBing the first version.
  23. */
  24. #include <rtthread.h>
  25. #include <rtdevice.h>
  26. #include "drv_hwtimer.h"
  27. #include "fsl_common.h"
  28. #include "fsl_gpt.h"
  29. #ifdef RT_USING_HWTIMER
  30. #if defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL
  31. #error "Please don't define 'FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL'!"
  32. #endif
  33. /* Select IPG Clock as PERCLK_CLK clock source */
  34. #define EXAMPLE_GPT_CLOCK_SOURCE_SELECT (0U)
  35. /* Clock divider for PERCLK_CLK clock source */
  36. #define EXAMPLE_GPT_CLOCK_DIVIDER_SELECT (5U)
  37. /* Get source clock for GPT driver (GPT prescaler = 6) */
  38. #define EXAMPLE_GPT_CLK_FREQ (CLOCK_GetFreq(kCLOCK_IpgClk) / (EXAMPLE_GPT_CLOCK_DIVIDER_SELECT + 1U))
  39. static void NVIC_Configuration(void)
  40. {
  41. EnableIRQ(GPT1_IRQn);
  42. }
  43. static rt_err_t rt1052_hwtimer_control(rt_hwtimer_t *timer, rt_uint32_t cmd, void *args)
  44. {
  45. rt_err_t err = RT_EOK;
  46. GPT_Type *hwtimer_dev;
  47. hwtimer_dev = (GPT_Type *)timer->parent.user_data;
  48. RT_ASSERT(timer != RT_NULL);
  49. switch (cmd)
  50. {
  51. case HWTIMER_CTRL_FREQ_SET:
  52. {
  53. uint32_t clk;
  54. uint32_t pre;
  55. clk = EXAMPLE_GPT_CLK_FREQ;
  56. pre = clk / *((uint32_t *)args) - 1;
  57. GPT_SetClockDivider(hwtimer_dev, pre);
  58. }
  59. break;
  60. default:
  61. err = -RT_ENOSYS;
  62. break;
  63. }
  64. return err;
  65. }
  66. static rt_uint32_t rt1052_hwtimer_count_get(rt_hwtimer_t *timer)
  67. {
  68. rt_uint32_t CurrentTimer_Count;
  69. GPT_Type *hwtimer_dev;
  70. hwtimer_dev = (GPT_Type *)timer->parent.user_data;
  71. RT_ASSERT(timer != RT_NULL);
  72. CurrentTimer_Count = GPT_GetCurrentTimerCount(hwtimer_dev);
  73. return CurrentTimer_Count;
  74. }
  75. static void rt1052_hwtimer_init(rt_hwtimer_t *timer, rt_uint32_t state)
  76. {
  77. GPT_Type *hwtimer_dev;
  78. gpt_config_t gptConfig;
  79. hwtimer_dev = (GPT_Type *)timer->parent.user_data;
  80. RT_ASSERT(timer != RT_NULL);
  81. GPT_Deinit(hwtimer_dev);
  82. if (state == 1)
  83. {
  84. /*Clock setting for GPT*/
  85. CLOCK_SetMux(kCLOCK_PerclkMux, EXAMPLE_GPT_CLOCK_SOURCE_SELECT);
  86. CLOCK_SetDiv(kCLOCK_PerclkDiv, EXAMPLE_GPT_CLOCK_DIVIDER_SELECT);
  87. /* Initialize GPT module by default config */
  88. GPT_GetDefaultConfig(&gptConfig);
  89. GPT_Init(hwtimer_dev, &gptConfig);
  90. }
  91. }
  92. static rt_err_t rt1052_hwtimer_start(rt_hwtimer_t *timer, rt_uint32_t cnt, rt_hwtimer_mode_t mode)
  93. {
  94. GPT_Type *hwtimer_dev;
  95. hwtimer_dev = (GPT_Type *)timer->parent.user_data;
  96. RT_ASSERT(timer != RT_NULL);
  97. hwtimer_dev->CR |= (mode == HWTIMER_MODE_PERIOD) ? GPT_CR_FRR_MASK : 0U;
  98. GPT_SetOutputCompareValue(hwtimer_dev, kGPT_OutputCompare_Channel1, cnt);
  99. GPT_EnableInterrupts(hwtimer_dev, kGPT_OutputCompare1InterruptEnable);
  100. NVIC_Configuration();
  101. GPT_StartTimer(hwtimer_dev);
  102. return RT_EOK;
  103. }
  104. static void rt1052_hwtimer_stop(rt_hwtimer_t *timer)
  105. {
  106. GPT_Type *hwtimer_dev;
  107. hwtimer_dev = (GPT_Type *)timer->parent.user_data;
  108. RT_ASSERT(timer != RT_NULL);
  109. GPT_StopTimer(hwtimer_dev);
  110. }
  111. static const struct rt_hwtimer_ops rt1052_hwtimer_ops =
  112. {
  113. rt1052_hwtimer_init,
  114. rt1052_hwtimer_start,
  115. rt1052_hwtimer_stop,
  116. rt1052_hwtimer_count_get,
  117. rt1052_hwtimer_control,
  118. };
  119. static const struct rt_hwtimer_info rt1052_hwtimer_info =
  120. {
  121. 25000000, /* the maximum count frequency can be set */
  122. 6103, /* the minimum count frequency can be set */
  123. 0xFFFFFFFF,
  124. HWTIMER_CNTMODE_UP,
  125. };
  126. static rt_hwtimer_t GPT_timer1;
  127. int rt1052_hw_hwtimer_init(void)
  128. {
  129. int ret = RT_EOK;
  130. GPT_timer1.info = &rt1052_hwtimer_info;
  131. GPT_timer1.ops = &rt1052_hwtimer_ops;
  132. rt_device_hwtimer_register(&GPT_timer1, "_timer", GPT1);
  133. return ret;
  134. }
  135. void GPT1_IRQHandler(void)
  136. {
  137. if (GPT_GetStatusFlags(GPT1, kGPT_OutputCompare1Flag) != 0)
  138. {
  139. GPT_ClearStatusFlags(GPT1, kGPT_OutputCompare1Flag);
  140. rt_device_hwtimer_isr(&GPT_timer1);
  141. }
  142. /* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F, Cortex-M7, Cortex-M7F Store immediate overlapping
  143. exception return operation might vector to incorrect interrupt */
  144. #if defined __CORTEX_M && (__CORTEX_M == 4U || __CORTEX_M == 7U)
  145. __DSB();
  146. #endif
  147. }
  148. INIT_DEVICE_EXPORT(rt1052_hw_hwtimer_init);
  149. #endif /*RT_USING_HWTIMER*/