drv_pwm.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. /*
  2. * Copyright (c) 2006-2023, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2023-10-20 ChuShicheng first version
  9. */
  10. #include "drv_pwm.h"
  11. #include "board.h"
  12. #include "hardware/pwm.h"
  13. #ifdef BSP_USING_PWM
  14. #define DBG_LEVEL DBG_LOG
  15. #include <rtdbg.h>
  16. #define LOG_TAG "DRV.PWM"
  17. struct pico_pwm
  18. {
  19. struct rt_device_pwm pwm_device;
  20. rt_uint8_t slice_num;
  21. rt_uint8_t pin_a;
  22. rt_uint8_t pin_b;
  23. rt_uint8_t a_all_flag; /* 1: Two pins simultaneously output PWM A channel */
  24. rt_uint8_t b_all_flag; /* 1: Two pins simultaneously output PWM B channel */
  25. char *name;
  26. };
  27. static struct pico_pwm pico_pwm_obj[] =
  28. {
  29. #ifdef BSP_USING_PWM0
  30. {
  31. .name = "pwm0",
  32. .slice_num = 0,
  33. .pin_a = BSP_PWM0_A_PIN,
  34. .pin_b = BSP_PWM0_B_PIN,
  35. #ifdef BSP_PWM0_A_ALL
  36. .a_all_flag = 1,
  37. #endif /* BSP_PWM0_A_ALL */
  38. #ifdef BSP_PWM0_B_ALL
  39. .b_all_flag = 1,
  40. #endif /* BSP_PWM0_B_ALL */
  41. },
  42. #endif /* BSP_USING_PWM0 */
  43. #ifdef BSP_USING_PWM1
  44. {
  45. .name = "pwm1",
  46. .slice_num = 1,
  47. .pin_a = BSP_PWM1_A_PIN,
  48. .pin_b = BSP_PWM1_B_PIN,
  49. #ifdef BSP_PWM1_A_ALL
  50. .a_all_flag = 1,
  51. #endif /* BSP_PWM1_A_ALL */
  52. #ifdef BSP_PWM1_B_ALL
  53. .b_all_flag = 1,
  54. #endif /* BSP_PWM1_B_ALL */
  55. },
  56. #endif /* BSP_USING_PWM1 */
  57. #ifdef BSP_USING_PWM2
  58. {
  59. .name = "pwm2",
  60. .slice_num = 2,
  61. .pin_a = BSP_PWM2_A_PIN,
  62. .pin_b = BSP_PWM2_B_PIN,
  63. #ifdef BSP_PWM2_A_ALL
  64. .a_all_flag = 1,
  65. #endif /* BSP_PWM2_A_ALL */
  66. #ifdef BSP_PWM2_B_ALL
  67. .b_all_flag = 1,
  68. #endif /* BSP_PWM2_B_ALL */
  69. },
  70. #endif /* BSP_USING_PWM2 */
  71. #ifdef BSP_USING_PWM3
  72. {
  73. .name = "pwm3",
  74. .slice_num = 3,
  75. .pin_a = BSP_PWM3_A_PIN,
  76. .pin_b = BSP_PWM3_B_PIN,
  77. #ifdef BSP_PWM3_A_ALL
  78. .a_all_flag = 1,
  79. #endif /* BSP_PWM3_A_ALL */
  80. #ifdef BSP_PWM3_B_ALL
  81. .b_all_flag = 1,
  82. #endif /* BSP_PWM3_B_ALL */
  83. },
  84. #endif /* BSP_USING_PWM3 */
  85. #ifdef BSP_USING_PWM4
  86. {
  87. .name = "pwm4",
  88. .slice_num = 4,
  89. .pin_a = BSP_PWM4_A_PIN,
  90. .pin_b = BSP_PWM4_B_PIN,
  91. #ifdef BSP_PWM4_A_ALL
  92. .a_all_flag = 1,
  93. #endif /* BSP_PWM4_A_ALL */
  94. #ifdef BSP_PWM4_B_ALL
  95. .b_all_flag = 1,
  96. #endif /* BSP_PWM4_B_ALL */
  97. },
  98. #endif /* BSP_USING_PWM4 */
  99. #ifdef BSP_USING_PWM5
  100. {
  101. .name = "pwm5",
  102. .slice_num = 5,
  103. .pin_a = BSP_PWM5_A_PIN,
  104. .pin_b = BSP_PWM5_B_PIN,
  105. #ifdef BSP_PWM5_A_ALL
  106. .a_all_flag = 1,
  107. #endif /* BSP_PWM5_A_ALL */
  108. #ifdef BSP_PWM5_B_ALL
  109. .b_all_flag = 1,
  110. #endif /* BSP_PWM5_B_ALL */
  111. },
  112. #endif /* BSP_USING_PWM5 */
  113. #ifdef BSP_USING_PWM6
  114. {
  115. .name = "pwm6",
  116. .slice_num = 6,
  117. .pin_a = BSP_PWM6_A_PIN,
  118. .pin_b = BSP_PWM6_B_PIN,
  119. #ifdef BSP_PWM6_A_ALL
  120. .a_all_flag = 1,
  121. #endif /* BSP_PWM6_A_ALL */
  122. #ifdef BSP_PWM6_B_ALL
  123. .b_all_flag = 1,
  124. #endif /* BSP_PWM6_B_ALL */
  125. },
  126. #endif /* BSP_USING_PWM6 */
  127. #ifdef BSP_USING_PWM7
  128. {
  129. .name = "pwm7",
  130. .slice_num = 7,
  131. .pin_a = BSP_PWM7_A_PIN,
  132. .pin_b = BSP_PWM7_B_PIN,
  133. },
  134. #endif /* BSP_USING_PWM7 */
  135. };
  136. static rt_err_t _pwm_set(rt_uint8_t slice_num, struct rt_pwm_configuration *configuration)
  137. {
  138. uint32_t period_hz = 1000000000 / configuration->period;
  139. uint32_t pulse = 1000000000 / configuration->pulse;
  140. pwm_config config = pwm_get_default_config();
  141. pwm_config_set_clkdiv(&config, 1.33f);
  142. pwm_init(slice_num, &config, true);
  143. pwm_set_wrap(slice_num, 100000000 / period_hz);
  144. pwm_set_chan_level(slice_num, configuration->channel, 100000000 / pulse);
  145. return RT_EOK;
  146. }
  147. static rt_err_t _pwm_get(rt_uint8_t slice_num, struct rt_pwm_configuration *configuration)
  148. {
  149. uint32_t period_hz = pwm_hw->slice[slice_num].top;
  150. configuration->period = period_hz * 10;
  151. configuration->pulse = pwm_hw->slice[slice_num].cc * 10;
  152. return RT_EOK;
  153. }
  154. static rt_err_t _pwm_control(struct rt_device_pwm *device, int cmd, void *arg)
  155. {
  156. struct pico_pwm *_pwm = rt_container_of(device, struct pico_pwm, pwm_device);
  157. struct rt_pwm_configuration *configuration = (struct rt_pwm_configuration *)arg;
  158. switch (cmd)
  159. {
  160. case PWM_CMD_ENABLE:
  161. pwm_set_enabled (_pwm->slice_num, RT_TRUE);
  162. return RT_EOK;
  163. case PWM_CMD_DISABLE:
  164. pwm_set_enabled (_pwm->slice_num, RT_FALSE);
  165. return RT_EOK;
  166. case PWM_CMD_SET:
  167. return _pwm_set(_pwm->slice_num, configuration);
  168. case PWM_CMD_GET:
  169. return _pwm_get(_pwm->slice_num, configuration);
  170. default:
  171. return -RT_EINVAL;
  172. }
  173. }
  174. static struct rt_pwm_ops _pwm_ops =
  175. {
  176. _pwm_control
  177. };
  178. int rt_hw_pwm_init(void)
  179. {
  180. int result = RT_EOK;
  181. for (int i = 0; i < sizeof(pico_pwm_obj) / sizeof(pico_pwm_obj[0]); i++)
  182. {
  183. if(pico_pwm_obj[i].a_all_flag)
  184. {
  185. gpio_set_function(pico_pwm_obj[i].slice_num * 2, GPIO_FUNC_PWM);
  186. gpio_set_function(pico_pwm_obj[i].slice_num * 2 + 16, GPIO_FUNC_PWM);
  187. }
  188. else
  189. {
  190. gpio_set_function(pico_pwm_obj[i].pin_a, GPIO_FUNC_PWM);
  191. }
  192. if(pico_pwm_obj[i].b_all_flag)
  193. {
  194. gpio_set_function(pico_pwm_obj[i].slice_num * 2 + 1, GPIO_FUNC_PWM);
  195. gpio_set_function(pico_pwm_obj[i].slice_num * 2 + 17, GPIO_FUNC_PWM);
  196. }
  197. else
  198. {
  199. gpio_set_function(pico_pwm_obj[i].pin_b, GPIO_FUNC_PWM);
  200. }
  201. result = rt_device_pwm_register(&pico_pwm_obj[i].pwm_device, pico_pwm_obj[i].name, &_pwm_ops, 0);
  202. if(result != RT_EOK)
  203. {
  204. LOG_E("%s register fail.", pico_pwm_obj[i].name);
  205. }
  206. }
  207. return result;
  208. }
  209. INIT_DEVICE_EXPORT(rt_hw_pwm_init);
  210. #endif /* BSP_USING_PWM */