drv_pwm.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. /*
  2. * Copyright (c) 2006-2018, Synwit Technology Co.,Ltd.
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2018-12-10 Zohar_Lee first version
  9. * 2020-07-10 lik format file
  10. */
  11. #include "drv_pwm.h"
  12. #ifdef RT_USING_PWM
  13. #ifdef BSP_USING_PWM
  14. //#define DRV_DEBUG
  15. #define LOG_TAG "drv.pwm"
  16. #include <drv_log.h>
  17. #define MIN_PERIOD 2
  18. #define MIN_PULSE 1
  19. static struct swm_pwm_cfg pwm_cfg[] =
  20. {
  21. #ifdef BSP_USING_PWM0
  22. PWM0_CFG,
  23. #endif
  24. #ifdef BSP_USING_PWM1
  25. PWM1_CFG,
  26. #endif
  27. #ifdef BSP_USING_PWM2
  28. PWM2_CFG,
  29. #endif
  30. #ifdef BSP_USING_PWM3
  31. PWM3_CFG,
  32. #endif
  33. #ifdef BSP_USING_PWM4
  34. PWM4_CFG,
  35. #endif
  36. #ifdef BSP_USING_PWM5
  37. PWM5_CFG,
  38. #endif
  39. };
  40. static struct swm_pwm pwm_drv[sizeof(pwm_cfg) / sizeof(pwm_cfg[0])] = {0};
  41. static rt_err_t swm_pwm_control(struct rt_device_pwm *pwm_device, int cmd, void *arg);
  42. static struct rt_pwm_ops pwm_ops =
  43. {
  44. swm_pwm_control};
  45. static rt_err_t swm_pwm_enable(struct rt_device_pwm *pwm_device, struct rt_pwm_configuration *configuration, rt_bool_t enable)
  46. {
  47. struct swm_pwm_cfg *cfg = RT_NULL;
  48. RT_ASSERT(pwm_device != RT_NULL);
  49. cfg = pwm_device->parent.user_data;
  50. if (!enable)
  51. {
  52. if (PWM_CH_A == configuration->channel)
  53. {
  54. PWM_Stop(cfg->PWMx, 1, 0);
  55. }
  56. if (PWM_CH_B == configuration->channel)
  57. {
  58. PWM_Stop(cfg->PWMx, 0, 1);
  59. }
  60. }
  61. else
  62. {
  63. if (PWM_CH_A == configuration->channel)
  64. {
  65. PWM_Start(cfg->PWMx, 1, 0);
  66. }
  67. if (PWM_CH_B == configuration->channel)
  68. {
  69. PWM_Start(cfg->PWMx, 0, 1);
  70. }
  71. }
  72. return RT_EOK;
  73. }
  74. static rt_err_t swm_pwm_get(struct rt_device_pwm *pwm_device, struct rt_pwm_configuration *configuration)
  75. {
  76. rt_uint64_t tim_clock;
  77. tim_clock = SystemCoreClock / 8;
  78. struct swm_pwm_cfg *cfg = RT_NULL;
  79. RT_ASSERT(pwm_device != RT_NULL);
  80. cfg = pwm_device->parent.user_data;
  81. /* Convert nanosecond to frequency and duty cycle. 1s = 1 * 1000 * 1000 * 1000 ns */
  82. tim_clock /= 1000000UL;
  83. configuration->period = PWM_GetCycle(cfg->PWMx, configuration->channel) * 1000UL / tim_clock;
  84. configuration->pulse = PWM_GetHDuty(cfg->PWMx, configuration->channel) * 1000UL / tim_clock;
  85. return RT_EOK;
  86. }
  87. static rt_err_t swm_pwm_set(struct rt_device_pwm *pwm_device, struct rt_pwm_configuration *configuration)
  88. {
  89. rt_uint32_t period, pulse;
  90. rt_uint64_t tim_clock;
  91. tim_clock = SystemCoreClock / 8;
  92. struct swm_pwm_cfg *cfg = RT_NULL;
  93. RT_ASSERT(pwm_device != RT_NULL);
  94. cfg = pwm_device->parent.user_data;
  95. /* Convert nanosecond to frequency and duty cycle. 1s = 1 * 1000 * 1000 * 1000 ns */
  96. /* when SystemCoreClock = 120MHz, configuration->period max 4.369ms */
  97. /* when SystemCoreClock = 20MHz, configuration->period max 26.214ms */
  98. tim_clock /= 1000000UL;
  99. period = (unsigned long long)configuration->period * tim_clock / 1000ULL;
  100. pulse = (unsigned long long)configuration->pulse * tim_clock / 1000ULL;
  101. if (period < MIN_PERIOD)
  102. {
  103. period = MIN_PERIOD;
  104. }
  105. if (pulse < MIN_PULSE)
  106. {
  107. pulse = MIN_PULSE;
  108. }
  109. PWM_SetCycle(cfg->PWMx, configuration->channel, period);
  110. PWM_SetHDuty(cfg->PWMx, configuration->channel, pulse);
  111. return RT_EOK;
  112. }
  113. static rt_err_t swm_pwm_control(struct rt_device_pwm *pwm_device, int cmd, void *arg)
  114. {
  115. RT_ASSERT(pwm_device != RT_NULL);
  116. struct rt_pwm_configuration *configuration = (struct rt_pwm_configuration *)arg;
  117. switch (cmd)
  118. {
  119. case PWM_CMD_ENABLE:
  120. return swm_pwm_enable(pwm_device, configuration, RT_TRUE);
  121. case PWM_CMD_DISABLE:
  122. return swm_pwm_enable(pwm_device, configuration, RT_FALSE);
  123. case PWM_CMD_SET:
  124. return swm_pwm_set(pwm_device, configuration);
  125. case PWM_CMD_GET:
  126. return swm_pwm_get(pwm_device, configuration);
  127. default:
  128. return RT_EINVAL;
  129. }
  130. }
  131. int rt_hw_pwm_init(void)
  132. {
  133. int i = 0;
  134. int result = RT_EOK;
  135. for (i = 0; i < sizeof(pwm_cfg) / sizeof(pwm_cfg[0]); i++)
  136. {
  137. pwm_drv[i].cfg = &pwm_cfg[i];
  138. if (pwm_drv[i].cfg->PWMx == PWM0)
  139. {
  140. #ifdef BSP_USING_PWM0A
  141. PORT_Init(PORTC, PIN2, FUNMUX0_PWM0A_OUT, 0);
  142. #endif
  143. #ifdef BSP_USING_PWM0B
  144. PORT_Init(PORTC, PIN4, FUNMUX0_PWM0B_OUT, 0);
  145. #endif
  146. }
  147. else if (pwm_drv[i].cfg->PWMx == PWM1)
  148. {
  149. #ifdef BSP_USING_PWM1A
  150. PORT_Init(PORTC, PIN3, FUNMUX1_PWM1A_OUT, 0);
  151. #endif
  152. #ifdef BSP_USING_PWM1B
  153. PORT_Init(PORTC, PIN5, FUNMUX1_PWM1B_OUT, 0);
  154. #endif
  155. }
  156. else if (pwm_drv[i].cfg->PWMx == PWM2)
  157. {
  158. #ifdef BSP_USING_PWM2A
  159. PORT_Init(PORTN, PIN4, FUNMUX0_PWM2A_OUT, 0);
  160. #endif
  161. #ifdef BSP_USING_PWM2B
  162. PORT_Init(PORTN, PIN6, FUNMUX0_PWM2B_OUT, 0);
  163. #endif
  164. }
  165. else if (pwm_drv[i].cfg->PWMx == PWM3)
  166. {
  167. #ifdef BSP_USING_PWM3A
  168. PORT_Init(PORTN, PIN3, FUNMUX1_PWM3A_OUT, 0);
  169. #endif
  170. #ifdef BSP_USING_PWM3B
  171. PORT_Init(PORTN, PIN5, FUNMUX1_PWM3B_OUT, 0);
  172. #endif
  173. }
  174. else if (pwm_drv[i].cfg->PWMx == PWM4)
  175. {
  176. #ifdef BSP_USING_PWM4A
  177. PORT_Init(PORTN, PIN8, FUNMUX0_PWM4A_OUT, 0);
  178. #endif
  179. #ifdef BSP_USING_PWM4B
  180. PORT_Init(PORTN, PIN10, FUNMUX0_PWM4B_OUT, 0);
  181. #endif
  182. }
  183. else if (pwm_drv[i].cfg->PWMx == PWM5)
  184. {
  185. #ifdef BSP_USING_PWM5A
  186. PORT_Init(PORTN, PIN7, FUNMUX1_PWM5A_OUT, 0);
  187. #endif
  188. #ifdef BSP_USING_PWM5B
  189. PORT_Init(PORTN, PIN9, FUNMUX1_PWM5B_OUT, 0);
  190. #endif
  191. }
  192. PWM_Init(pwm_drv[i].cfg->PWMx, &(pwm_drv[i].cfg->pwm_initstruct));
  193. if (rt_device_pwm_register(&pwm_drv[i].pwm_device, pwm_drv[i].cfg->name, &pwm_ops, pwm_drv[i].cfg) == RT_EOK)
  194. {
  195. LOG_D("%s register success", pwm_drv[i].cfg->name);
  196. }
  197. else
  198. {
  199. LOG_E("%s register failed", pwm_drv[i].cfg->name);
  200. result = -RT_ERROR;
  201. }
  202. }
  203. return result;
  204. }
  205. INIT_DEVICE_EXPORT(rt_hw_pwm_init);
  206. #endif /* BSP_USING_PWM */
  207. #endif /* RT_USING_PWM */