drv_epwm.c 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  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. * 2020-3-16 YH First version
  10. *
  11. ******************************************************************************/
  12. #include <rtconfig.h>
  13. #if defined(BSP_USING_EPWM)
  14. #define LOG_TAG "drv.epwm"
  15. #define DBG_ENABLE
  16. #define DBG_SECTION_NAME "drv.epwm"
  17. #define DBG_LEVEL DBG_INFO
  18. #define DBG_COLOR
  19. #include <rtdbg.h>
  20. #include <stdint.h>
  21. #include <rtdevice.h>
  22. #include <rthw.h>
  23. #include "NuMicro.h"
  24. enum
  25. {
  26. EPWM_START = -1,
  27. #if defined(BSP_USING_EPWM0)
  28. EPWM0_IDX,
  29. #endif
  30. #if defined(BSP_USING_EPWM1)
  31. EPWM1_IDX,
  32. #endif
  33. EPWM_CNT
  34. };
  35. struct nu_epwm
  36. {
  37. struct rt_device_pwm dev;
  38. char *name;
  39. EPWM_T *epwm_base;
  40. };
  41. typedef struct nu_epwm *nu_epwm_t;
  42. static struct nu_epwm nu_epwm_arr [] =
  43. {
  44. #if defined(BSP_USING_EPWM0)
  45. {
  46. .name = "epwm0",
  47. .epwm_base = EPWM0,
  48. },
  49. #endif
  50. #if defined(BSP_USING_EPWM1)
  51. {
  52. .name = "epwm1",
  53. .epwm_base = EPWM1,
  54. },
  55. #endif
  56. {0}
  57. }; /* epwm nu_epwm */
  58. static rt_err_t nu_epwm_control(struct rt_device_pwm *device, int cmd, void *arg);
  59. static struct rt_pwm_ops nu_epwm_ops =
  60. {
  61. .control = nu_epwm_control
  62. };
  63. static rt_err_t nu_epwm_enable(struct rt_device_pwm *device, struct rt_pwm_configuration *configuration, rt_bool_t enable)
  64. {
  65. rt_err_t result = RT_EOK;
  66. EPWM_T *pwm_base = ((nu_epwm_t)device)->epwm_base;
  67. rt_uint32_t pwm_channel = ((struct rt_pwm_configuration *)configuration)->channel;
  68. if (enable == RT_TRUE)
  69. {
  70. EPWM_EnableOutput(pwm_base, 1 << pwm_channel);
  71. EPWM_Start(pwm_base, 1 << pwm_channel);
  72. }
  73. else
  74. {
  75. EPWM_DisableOutput(pwm_base, 1 << pwm_channel);
  76. EPWM_ForceStop(pwm_base, 1 << pwm_channel);
  77. }
  78. return result;
  79. }
  80. static rt_err_t nu_epwm_set(struct rt_device_pwm *device, struct rt_pwm_configuration *configuration)
  81. {
  82. if ((((struct rt_pwm_configuration *)configuration)->period) <= 0)
  83. return -(RT_ERROR);
  84. rt_uint8_t pwm_channel_pair;
  85. rt_uint32_t pwm_freq, pwm_dutycycle ;
  86. EPWM_T *pwm_base = ((nu_epwm_t)device)->epwm_base;
  87. rt_uint8_t pwm_channel = ((struct rt_pwm_configuration *)configuration)->channel;
  88. rt_uint32_t pwm_period = ((struct rt_pwm_configuration *)configuration)->period;
  89. rt_uint32_t pwm_pulse = ((struct rt_pwm_configuration *)configuration)->pulse;
  90. rt_uint32_t pre_pwm_prescaler = EPWM_GET_PRESCALER(pwm_base, pwm_channel);
  91. if ((pwm_channel % 2) == 0)
  92. pwm_channel_pair = pwm_channel + 1;
  93. else
  94. pwm_channel_pair = pwm_channel - 1;
  95. pwm_freq = 1000000000 / pwm_period;
  96. pwm_dutycycle = (pwm_pulse * 100) / pwm_period;
  97. EPWM_ConfigOutputChannel(pwm_base, pwm_channel, pwm_freq, pwm_dutycycle) ;
  98. if ((pre_pwm_prescaler != 0) || (EPWM_GET_CNR(pwm_base, pwm_channel_pair) != 0) || (EPWM_GET_CMR(pwm_base, pwm_channel_pair) != 0))
  99. {
  100. if (pre_pwm_prescaler < EPWM_GET_PRESCALER(pwm_base, pwm_channel))
  101. {
  102. EPWM_SET_CNR(pwm_base, pwm_channel_pair, ((EPWM_GET_CNR(pwm_base, pwm_channel_pair) + 1) * (pre_pwm_prescaler + 1)) / (EPWM_GET_PRESCALER(pwm_base, pwm_channel) + 1));
  103. EPWM_SET_CMR(pwm_base, pwm_channel_pair, (EPWM_GET_CMR(pwm_base, pwm_channel_pair) * (pre_pwm_prescaler + 1)) / (EPWM_GET_PRESCALER(pwm_base, pwm_channel) + 1));
  104. }
  105. else if (pre_pwm_prescaler > EPWM_GET_PRESCALER(pwm_base, pwm_channel))
  106. {
  107. EPWM_SET_CNR(pwm_base, pwm_channel, ((EPWM_GET_CNR(pwm_base, pwm_channel) + 1) * (EPWM_GET_PRESCALER(pwm_base, pwm_channel) + 1)) / (pre_pwm_prescaler + 1));
  108. EPWM_SET_CMR(pwm_base, pwm_channel, (EPWM_GET_CMR(pwm_base, pwm_channel) * (EPWM_GET_PRESCALER(pwm_base, pwm_channel) + 1)) / (pre_pwm_prescaler + 1));
  109. }
  110. }
  111. return RT_EOK;
  112. }
  113. static rt_uint32_t nu_epwm_clksr(struct rt_device_pwm *device)
  114. {
  115. rt_uint32_t u32Src, u32EPWMClockSrc;
  116. EPWM_T *pwm_base = ((nu_epwm_t)device)->epwm_base;
  117. if (pwm_base == EPWM0)
  118. {
  119. u32Src = CLK->CLKSEL2 & CLK_CLKSEL2_EPWM0SEL_Msk;
  120. }
  121. else /* (epwm == EPWM1) */
  122. {
  123. u32Src = CLK->CLKSEL2 & CLK_CLKSEL2_EPWM1SEL_Msk;
  124. }
  125. if (u32Src == 0U)
  126. {
  127. /* clock source is from PLL clock */
  128. u32EPWMClockSrc = CLK_GetPLLClockFreq();
  129. }
  130. else
  131. {
  132. /* clock source is from PCLK */
  133. SystemCoreClockUpdate();
  134. if (pwm_base == EPWM0)
  135. {
  136. u32EPWMClockSrc = CLK_GetPCLK0Freq();
  137. }
  138. else /* (epwm == EPWM1) */
  139. {
  140. u32EPWMClockSrc = CLK_GetPCLK1Freq();
  141. }
  142. }
  143. return u32EPWMClockSrc;
  144. }
  145. static rt_err_t nu_epwm_get(struct rt_device_pwm *device, struct rt_pwm_configuration *configuration)
  146. {
  147. rt_uint32_t pwm_real_period, pwm_real_duty, time_tick, u32EPWMClockSrc ;
  148. EPWM_T *pwm_base = ((nu_epwm_t)device)->epwm_base;
  149. rt_uint32_t pwm_channel = ((struct rt_pwm_configuration *)configuration)->channel;
  150. rt_uint32_t pwm_prescale = EPWM_GET_PRESCALER(pwm_base, pwm_channel);
  151. rt_uint32_t pwm_period = EPWM_GET_CNR(pwm_base, pwm_channel);
  152. rt_uint32_t pwm_pulse = EPWM_GET_CMR(pwm_base, pwm_channel);
  153. u32EPWMClockSrc = nu_epwm_clksr(device);
  154. time_tick = 1000000000000 / u32EPWMClockSrc;
  155. pwm_real_period = (((pwm_prescale + 1) * (pwm_period + 1)) * time_tick) / 1000;
  156. pwm_real_duty = (((pwm_prescale + 1) * pwm_pulse * time_tick)) / 1000;
  157. ((struct rt_pwm_configuration *)configuration)->period = pwm_real_period;
  158. ((struct rt_pwm_configuration *)configuration)->pulse = pwm_real_duty;
  159. LOG_I("%s %d %d %d\n", ((nu_epwm_t)device)->name, configuration->channel, configuration->period, configuration->pulse);
  160. return RT_EOK;
  161. }
  162. static rt_err_t nu_epwm_control(struct rt_device_pwm *device, int cmd, void *arg)
  163. {
  164. struct rt_pwm_configuration *configuration = (struct rt_pwm_configuration *)arg;
  165. RT_ASSERT(device != RT_NULL);
  166. RT_ASSERT(configuration != RT_NULL);
  167. if (((((struct rt_pwm_configuration *)configuration)->channel) + 1) > EPWM_CHANNEL_NUM)
  168. return -(RT_ERROR);
  169. switch (cmd)
  170. {
  171. case PWM_CMD_ENABLE:
  172. return nu_epwm_enable(device, configuration, RT_TRUE);
  173. case PWM_CMD_DISABLE:
  174. return nu_epwm_enable(device, configuration, RT_FALSE);
  175. case PWM_CMD_SET:
  176. return nu_epwm_set(device, configuration);
  177. case PWM_CMD_GET:
  178. return nu_epwm_get(device, configuration);
  179. }
  180. return -(RT_EINVAL);
  181. }
  182. int rt_hw_epwm_init(void)
  183. {
  184. rt_err_t ret;
  185. int i;
  186. for (i = (EPWM_START + 1); i < EPWM_CNT; i++)
  187. {
  188. ret = rt_device_pwm_register(&nu_epwm_arr[i].dev, nu_epwm_arr[i].name, &nu_epwm_ops, RT_NULL);
  189. RT_ASSERT(ret == RT_EOK);
  190. }
  191. return 0;
  192. }
  193. INIT_DEVICE_EXPORT(rt_hw_epwm_init);
  194. #endif