drv_pwm.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  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. };
  51. #ifdef SOC_SERIES_R9A07G0
  52. #define FSP_PRIV_CLOCK FSP_PRIV_CLOCK_PCLKGPTL
  53. #else
  54. #define FSP_PRIV_CLOCK FSP_PRIV_CLOCK_PCLKD
  55. #endif
  56. /* Convert the raw PWM period counts into ns */
  57. static rt_uint32_t _convert_counts_ns(uint32_t source_div, uint32_t raw)
  58. {
  59. uint32_t pclkd_freq_hz = R_FSP_SystemClockHzGet(FSP_PRIV_CLOCK) >> source_div;
  60. uint32_t ns = (uint32_t)(((uint64_t)raw * 1000000000ULL) / pclkd_freq_hz);
  61. return ns;
  62. }
  63. /* Convert ns into raw PWM period counts */
  64. static rt_uint32_t _convert_ns_counts(uint32_t source_div, uint32_t raw)
  65. {
  66. uint32_t pclkd_freq_hz = R_FSP_SystemClockHzGet(FSP_PRIV_CLOCK) >> source_div;
  67. uint32_t counts = (uint32_t)(((uint64_t)raw * (uint64_t)pclkd_freq_hz) / 1000000000ULL);
  68. return counts;
  69. }
  70. /* PWM_CMD_ENABLE or PWM_CMD_DISABLE */
  71. static rt_err_t drv_pwm_enable(struct ra_pwm *device,
  72. struct rt_pwm_configuration *configuration,
  73. rt_bool_t enable)
  74. {
  75. fsp_err_t err = FSP_SUCCESS;
  76. if (enable)
  77. {
  78. err = R_GPT_Start(device->g_ctrl);
  79. }
  80. else
  81. {
  82. err = R_GPT_Stop(device->g_ctrl);
  83. }
  84. return (err == FSP_SUCCESS) ? RT_EOK : -RT_ERROR;
  85. }
  86. /* PWM_CMD_GET */
  87. static rt_err_t drv_pwm_get(struct ra_pwm *device,
  88. struct rt_pwm_configuration *configuration)
  89. {
  90. timer_info_t info;
  91. if (R_GPT_InfoGet(device->g_ctrl, &info) != FSP_SUCCESS)
  92. return -RT_ERROR;
  93. configuration->pulse =
  94. _convert_counts_ns(device->g_cfg->source_div, device->g_cfg->duty_cycle_counts);
  95. configuration->period =
  96. _convert_counts_ns(device->g_cfg->source_div, info.period_counts);
  97. configuration->channel = device->g_cfg->channel;
  98. return RT_EOK;
  99. }
  100. /* PWM_CMD_SET */
  101. static rt_err_t drv_pwm_set(struct ra_pwm *device,
  102. struct rt_pwm_configuration *conf)
  103. {
  104. uint32_t counts;
  105. fsp_err_t fsp_erra;
  106. fsp_err_t fsp_errb;
  107. rt_err_t rt_err;
  108. uint32_t pulse;
  109. uint32_t period;
  110. struct rt_pwm_configuration orig_conf;
  111. rt_err = drv_pwm_get(device, &orig_conf);
  112. if (rt_err != RT_EOK)
  113. {
  114. return rt_err;
  115. }
  116. /* Pulse cannot last longer than period. */
  117. period = conf->period;
  118. pulse = (period >= conf->pulse) ? conf->pulse : period;
  119. /* Not to set period again if it's not changed. */
  120. if (period != orig_conf.period)
  121. {
  122. counts = _convert_ns_counts(device->g_cfg->source_div, period);
  123. fsp_erra = R_GPT_PeriodSet(device->g_ctrl, counts);
  124. if (fsp_erra != FSP_SUCCESS)
  125. {
  126. return -RT_ERROR;
  127. }
  128. }
  129. /* Two pins of a channel will not be separated. */
  130. counts = _convert_ns_counts(device->g_cfg->source_div, pulse);
  131. fsp_erra = R_GPT_DutyCycleSet(device->g_ctrl, counts, GPT_IO_PIN_GTIOCA);
  132. fsp_errb = R_GPT_DutyCycleSet(device->g_ctrl, counts, GPT_IO_PIN_GTIOCB);
  133. if (fsp_erra != FSP_SUCCESS || fsp_errb != FSP_SUCCESS)
  134. {
  135. return -RT_ERROR;
  136. }
  137. return RT_EOK;
  138. }
  139. /**
  140. * Implement of control method in struct rt_pwm_ops.
  141. */
  142. static rt_err_t drv_pwm_control(struct rt_device_pwm *device, int cmd, void *arg)
  143. {
  144. struct rt_pwm_configuration *configuration = (struct rt_pwm_configuration *)arg;
  145. struct ra_pwm *pwm_device = (struct ra_pwm *)device->parent.user_data;
  146. /**
  147. * There's actually only one GPT timer with 10 channels. In this case, the
  148. * timer is separated into 10 PWM devices, so each device has only one
  149. * channel.
  150. */
  151. if (configuration->channel != 0)
  152. {
  153. return -RT_EINVAL;
  154. }
  155. switch (cmd)
  156. {
  157. case PWM_CMD_ENABLE:
  158. return drv_pwm_enable(pwm_device, configuration, RT_TRUE);
  159. case PWM_CMD_DISABLE:
  160. return drv_pwm_enable(pwm_device, configuration, RT_FALSE);
  161. case PWM_CMD_GET:
  162. return drv_pwm_get(pwm_device, configuration);
  163. case PWM_CMD_SET:
  164. return drv_pwm_set(pwm_device, configuration);
  165. default:
  166. return -RT_EINVAL;
  167. }
  168. return RT_EOK;
  169. }
  170. /**
  171. * This is to register the PWM device
  172. *
  173. * Note that the PWM driver only supports one fixed pin.
  174. */
  175. int rt_hw_pwm_init(void)
  176. {
  177. rt_err_t ret = RT_EOK;
  178. rt_err_t rt_err = RT_EOK;
  179. fsp_err_t fsp_err = FSP_SUCCESS;
  180. for (int i = 0; i < BSP_PWMS_NUM; i++)
  181. {
  182. fsp_err = R_GPT_Open(ra6m4_pwm_obj[i].g_ctrl,
  183. ra6m4_pwm_obj[i].g_cfg);
  184. rt_err = rt_device_pwm_register(&ra6m4_pwm_obj[i].pwm_device,
  185. ra6m4_pwm_obj[i].name,
  186. &drv_ops,
  187. &ra6m4_pwm_obj[i]);
  188. if (fsp_err != FSP_SUCCESS || rt_err != RT_EOK)
  189. {
  190. ret = -RT_ERROR;
  191. }
  192. }
  193. return ret;
  194. }
  195. INIT_BOARD_EXPORT(rt_hw_pwm_init);
  196. #endif /* BSP_USING_PWM */