drv_pwm.c 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. /*
  2. * Copyright (c) 2006-2025, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2021-10-25 KevinXu first version
  9. */
  10. #include "drv_pwm.h"
  11. #ifdef BSP_USING_PWM
  12. /* Declare the control function first */
  13. static rt_err_t drv_pwm_control(struct rt_device_pwm *, int, void *);
  14. static struct rt_pwm_ops drv_ops =
  15. {
  16. drv_pwm_control
  17. };
  18. static struct ra_pwm ra6m4_pwm_obj[BSP_PWMS_NUM] =
  19. {
  20. #ifdef BSP_USING_PWM0
  21. [BSP_PWM0_INDEX] = PWM_DRV_INITIALIZER(0),
  22. #endif
  23. #ifdef BSP_USING_PWM1
  24. [BSP_PWM1_INDEX] = PWM_DRV_INITIALIZER(1),
  25. #endif
  26. #ifdef BSP_USING_PWM2
  27. [BSP_PWM2_INDEX] = PWM_DRV_INITIALIZER(2),
  28. #endif
  29. #ifdef BSP_USING_PWM3
  30. [BSP_PWM3_INDEX] = PWM_DRV_INITIALIZER(3),
  31. #endif
  32. #ifdef BSP_USING_PWM4
  33. [BSP_PWM4_INDEX] = PWM_DRV_INITIALIZER(4),
  34. #endif
  35. #ifdef BSP_USING_PWM5
  36. [BSP_PWM5_INDEX] = PWM_DRV_INITIALIZER(5),
  37. #endif
  38. #ifdef BSP_USING_PWM6
  39. [BSP_PWM6_INDEX] = PWM_DRV_INITIALIZER(6),
  40. #endif
  41. #ifdef BSP_USING_PWM7
  42. [BSP_PWM7_INDEX] = PWM_DRV_INITIALIZER(7),
  43. #endif
  44. #ifdef BSP_USING_PWM8
  45. [BSP_PWM8_INDEX] = PWM_DRV_INITIALIZER(8),
  46. #endif
  47. #ifdef BSP_USING_PWM9
  48. [BSP_PWM9_INDEX] = PWM_DRV_INITIALIZER(9),
  49. #endif
  50. #ifdef BSP_USING_PWM10
  51. [BSP_PWM10_INDEX] = PWM_DRV_INITIALIZER(10),
  52. #endif
  53. #ifdef BSP_USING_PWM11
  54. [BSP_PWM11_INDEX] = PWM_DRV_INITIALIZER(11),
  55. #endif
  56. #ifdef BSP_USING_PWM12
  57. [BSP_PWM12_INDEX] = PWM_DRV_INITIALIZER(12),
  58. #endif
  59. #ifdef BSP_USING_PWM13
  60. [BSP_PWM13_INDEX] = PWM_DRV_INITIALIZER(13),
  61. #endif
  62. };
  63. #ifdef SOC_SERIES_R9A07G0
  64. #define FSP_PRIV_CLOCK FSP_PRIV_CLOCK_PCLKGPTL
  65. #else
  66. #define FSP_PRIV_CLOCK FSP_PRIV_CLOCK_PCLKD
  67. #endif
  68. /* Convert the raw PWM period counts into ns */
  69. static rt_uint32_t _convert_counts_ns(uint32_t source_div, uint32_t raw)
  70. {
  71. uint32_t pclkd_freq_hz = R_FSP_SystemClockHzGet(FSP_PRIV_CLOCK) >> source_div;
  72. uint32_t ns = (uint32_t)(((uint64_t)raw * 1000000000ULL) / pclkd_freq_hz);
  73. return ns;
  74. }
  75. /* Convert ns into raw PWM period counts */
  76. static rt_uint32_t _convert_ns_counts(uint32_t source_div, uint32_t raw)
  77. {
  78. uint32_t pclkd_freq_hz = R_FSP_SystemClockHzGet(FSP_PRIV_CLOCK) >> source_div;
  79. uint32_t counts = (uint32_t)(((uint64_t)raw * (uint64_t)pclkd_freq_hz) / 1000000000ULL);
  80. return counts;
  81. }
  82. /* PWM_CMD_ENABLE or PWM_CMD_DISABLE */
  83. static rt_err_t drv_pwm_enable(struct ra_pwm *device,
  84. struct rt_pwm_configuration *configuration,
  85. rt_bool_t enable)
  86. {
  87. fsp_err_t err = FSP_SUCCESS;
  88. if (enable)
  89. {
  90. err = R_GPT_Start(device->g_ctrl);
  91. }
  92. else
  93. {
  94. err = R_GPT_Stop(device->g_ctrl);
  95. }
  96. return (err == FSP_SUCCESS) ? RT_EOK : -RT_ERROR;
  97. }
  98. /* PWM_CMD_GET */
  99. static rt_err_t drv_pwm_get(struct ra_pwm *device,
  100. struct rt_pwm_configuration *configuration)
  101. {
  102. timer_info_t info;
  103. if (R_GPT_InfoGet(device->g_ctrl, &info) != FSP_SUCCESS)
  104. return -RT_ERROR;
  105. configuration->pulse =
  106. _convert_counts_ns(device->g_cfg->source_div, device->g_cfg->duty_cycle_counts);
  107. configuration->period =
  108. _convert_counts_ns(device->g_cfg->source_div, info.period_counts);
  109. configuration->channel = device->g_cfg->channel;
  110. return RT_EOK;
  111. }
  112. /* PWM_CMD_SET */
  113. static rt_err_t drv_pwm_set(struct ra_pwm *device,
  114. struct rt_pwm_configuration *conf)
  115. {
  116. uint32_t counts;
  117. fsp_err_t fsp_erra;
  118. fsp_err_t fsp_errb;
  119. rt_err_t rt_err;
  120. uint32_t pulse;
  121. uint32_t period;
  122. struct rt_pwm_configuration orig_conf;
  123. rt_err = drv_pwm_get(device, &orig_conf);
  124. if (rt_err != RT_EOK)
  125. {
  126. return rt_err;
  127. }
  128. /* Pulse cannot last longer than period. */
  129. period = conf->period;
  130. pulse = (period >= conf->pulse) ? conf->pulse : period;
  131. /* Not to set period again if it's not changed. */
  132. if (period != orig_conf.period)
  133. {
  134. counts = _convert_ns_counts(device->g_cfg->source_div, period);
  135. fsp_erra = R_GPT_PeriodSet(device->g_ctrl, counts);
  136. if (fsp_erra != FSP_SUCCESS)
  137. {
  138. return -RT_ERROR;
  139. }
  140. }
  141. /* Two pins of a channel will not be separated. */
  142. counts = _convert_ns_counts(device->g_cfg->source_div, pulse);
  143. fsp_erra = R_GPT_DutyCycleSet(device->g_ctrl, counts, GPT_IO_PIN_GTIOCA);
  144. fsp_errb = R_GPT_DutyCycleSet(device->g_ctrl, counts, GPT_IO_PIN_GTIOCB);
  145. if (fsp_erra != FSP_SUCCESS || fsp_errb != FSP_SUCCESS)
  146. {
  147. return -RT_ERROR;
  148. }
  149. return RT_EOK;
  150. }
  151. /**
  152. * Implement of control method in struct rt_pwm_ops.
  153. */
  154. static rt_err_t drv_pwm_control(struct rt_device_pwm *device, int cmd, void *arg)
  155. {
  156. struct rt_pwm_configuration *configuration = (struct rt_pwm_configuration *)arg;
  157. struct ra_pwm *pwm_device = (struct ra_pwm *)device->parent.user_data;
  158. /**
  159. * There's actually only one GPT timer with 10 channels. In this case, the
  160. * timer is separated into 10 PWM devices, so each device has only one
  161. * channel.
  162. */
  163. if (configuration->channel != 0)
  164. {
  165. return -RT_EINVAL;
  166. }
  167. switch (cmd)
  168. {
  169. case PWM_CMD_ENABLE:
  170. return drv_pwm_enable(pwm_device, configuration, RT_TRUE);
  171. case PWM_CMD_DISABLE:
  172. return drv_pwm_enable(pwm_device, configuration, RT_FALSE);
  173. case PWM_CMD_GET:
  174. return drv_pwm_get(pwm_device, configuration);
  175. case PWM_CMD_SET:
  176. return drv_pwm_set(pwm_device, configuration);
  177. default:
  178. return -RT_EINVAL;
  179. }
  180. return RT_EOK;
  181. }
  182. /**
  183. * This is to register the PWM device
  184. *
  185. * Note that the PWM driver only supports one fixed pin.
  186. */
  187. int rt_hw_pwm_init(void)
  188. {
  189. rt_err_t ret = RT_EOK;
  190. rt_err_t rt_err = RT_EOK;
  191. fsp_err_t fsp_err = FSP_SUCCESS;
  192. for (int i = 0; i < BSP_PWMS_NUM; i++)
  193. {
  194. fsp_err = R_GPT_Open(ra6m4_pwm_obj[i].g_ctrl,
  195. ra6m4_pwm_obj[i].g_cfg);
  196. rt_err = rt_device_pwm_register(&ra6m4_pwm_obj[i].pwm_device,
  197. ra6m4_pwm_obj[i].name,
  198. &drv_ops,
  199. &ra6m4_pwm_obj[i]);
  200. if (fsp_err != FSP_SUCCESS || rt_err != RT_EOK)
  201. {
  202. ret = -RT_ERROR;
  203. }
  204. }
  205. return ret;
  206. }
  207. INIT_BOARD_EXPORT(rt_hw_pwm_init);
  208. #endif /* BSP_USING_PWM */