drv_pwm.c 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. /*
  2. * Copyright (C) 2018 Shanghai Eastsoft Microelectronics Co., Ltd.
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2019-03-11 wangyq the first version
  9. */
  10. #include <rthw.h>
  11. #include <rtthread.h>
  12. #include <rtdevice.h>
  13. #include <board.h>
  14. #include <ald_cmu.h>
  15. #include <ald_timer.h>
  16. #include <ald_gpio.h>
  17. static void pwm_set_freq(timer_handle_t *timer_initstruct, uint32_t ns)
  18. {
  19. uint64_t _arr = (uint64_t)cmu_get_pclk1_clock() * ns / 1000000000 /
  20. (timer_initstruct->init.prescaler + 1) - 1;
  21. WRITE_REG(timer_initstruct->perh->AR, (uint32_t)_arr);
  22. timer_initstruct->init.period = (uint32_t)_arr;
  23. }
  24. static void pwm_set_duty(timer_handle_t *timer_initstruct, timer_channel_t ch, uint32_t ns)
  25. {
  26. uint64_t tmp = (uint64_t)cmu_get_pclk1_clock() * ns / 1000000000 /
  27. (timer_initstruct->init.prescaler + 1) - 1;
  28. if (ch == TIMER_CHANNEL_1)
  29. WRITE_REG(timer_initstruct->perh->CCVAL1, (uint32_t)tmp);
  30. else if (ch == TIMER_CHANNEL_2)
  31. WRITE_REG(timer_initstruct->perh->CCVAL2, (uint32_t)tmp);
  32. else if (ch == TIMER_CHANNEL_3)
  33. WRITE_REG(timer_initstruct->perh->CCVAL3, (uint32_t)tmp);
  34. else if (ch == TIMER_CHANNEL_4)
  35. WRITE_REG(timer_initstruct->perh->CCVAL4, (uint32_t)tmp);
  36. else
  37. {
  38. ;/* do nothing */
  39. }
  40. }
  41. static rt_err_t es32f0_pwm_control(struct rt_device_pwm *device, int cmd, void *arg)
  42. {
  43. rt_err_t ret = RT_EOK;
  44. uint32_t _ccep;
  45. timer_channel_t pwm_channel;
  46. timer_oc_init_t tim_ocinit;
  47. timer_handle_t *timer_initstruct = (timer_handle_t *)device->parent.user_data;
  48. struct rt_pwm_configuration *cfg = (struct rt_pwm_configuration *)arg;
  49. RT_ASSERT(timer_initstruct != RT_NULL);
  50. tim_ocinit.oc_mode = TIMER_OC_MODE_PWM1;
  51. tim_ocinit.oc_polarity = TIMER_OC_POLARITY_HIGH;
  52. tim_ocinit.oc_fast_en = DISABLE;
  53. tim_ocinit.ocn_polarity = TIMER_OCN_POLARITY_HIGH;
  54. tim_ocinit.ocn_idle = TIMER_OCN_IDLE_RESET;
  55. tim_ocinit.oc_idle = TIMER_OC_IDLE_RESET;
  56. /* select pwm output channel */
  57. if (1 == cfg->channel)
  58. {
  59. pwm_channel = TIMER_CHANNEL_1;
  60. }
  61. else if (2 == cfg->channel)
  62. {
  63. pwm_channel = TIMER_CHANNEL_2;
  64. }
  65. else if (3 == cfg->channel)
  66. {
  67. if (timer_initstruct->perh == GP16C2T0 || timer_initstruct->perh == GP16C2T1)
  68. return RT_EINVAL;
  69. pwm_channel = TIMER_CHANNEL_3;
  70. }
  71. else if (4 == cfg->channel)
  72. {
  73. if (timer_initstruct->perh == GP16C2T0 || timer_initstruct->perh == GP16C2T1)
  74. return RT_EINVAL;
  75. pwm_channel = TIMER_CHANNEL_4;
  76. }
  77. else
  78. {
  79. return RT_EINVAL;
  80. }
  81. switch (cmd)
  82. {
  83. case PWM_CMD_ENABLE:
  84. timer_pwm_start(timer_initstruct, pwm_channel);
  85. break;
  86. case PWM_CMD_DISABLE:
  87. timer_pwm_stop(timer_initstruct, pwm_channel);
  88. break;
  89. case PWM_CMD_SET:
  90. _ccep = timer_initstruct->perh->CCEP;
  91. /* count registers max 0xFFFF, auto adjust prescaler */
  92. do
  93. {
  94. pwm_set_freq(timer_initstruct, cfg->period);
  95. timer_initstruct->init.prescaler ++;
  96. }
  97. while (timer_initstruct->init.period > 0xFFFF);
  98. /* update prescaler */
  99. WRITE_REG(timer_initstruct->perh->PRES, --timer_initstruct->init.prescaler);
  100. timer_oc_config_channel(timer_initstruct, &tim_ocinit, pwm_channel);
  101. pwm_set_duty(timer_initstruct, pwm_channel, cfg->pulse);
  102. timer_initstruct->perh->CCEP = _ccep;
  103. break;
  104. case PWM_CMD_GET:
  105. cfg->pulse = timer_read_capture_value(timer_initstruct, pwm_channel) * 100 /
  106. READ_REG(timer_initstruct->perh->AR);
  107. break;
  108. default:
  109. break;
  110. }
  111. return ret;
  112. }
  113. const static struct rt_pwm_ops es32f0_pwm_ops =
  114. {
  115. es32f0_pwm_control
  116. };
  117. int rt_hw_pwm_init(void)
  118. {
  119. rt_err_t ret = RT_EOK;
  120. gpio_init_t gpio_initstructure;
  121. gpio_initstructure.mode = GPIO_MODE_OUTPUT;
  122. gpio_initstructure.odos = GPIO_PUSH_PULL;
  123. gpio_initstructure.pupd = GPIO_PUSH_UP;
  124. gpio_initstructure.odrv = GPIO_OUT_DRIVE_NORMAL;
  125. gpio_initstructure.flt = GPIO_FILTER_DISABLE;
  126. gpio_initstructure.type = GPIO_TYPE_TTL;
  127. #ifdef BSP_USING_PWM0 /* 4 channels */
  128. static struct rt_device_pwm pwm_dev0;
  129. static timer_handle_t timer_initstruct0;
  130. timer_initstruct0.perh = AD16C4T0;
  131. timer_pwm_init(&timer_initstruct0);
  132. /* gpio initialization */
  133. gpio_initstructure.func = GPIO_FUNC_2;
  134. gpio_init(GPIOA, GPIO_PIN_8, &gpio_initstructure);
  135. gpio_init(GPIOA, GPIO_PIN_9, &gpio_initstructure);
  136. gpio_init(GPIOA, GPIO_PIN_10, &gpio_initstructure);
  137. gpio_init(GPIOA, GPIO_PIN_11, &gpio_initstructure);
  138. ret = rt_device_pwm_register(&pwm_dev0, "pwm0", &es32f0_pwm_ops,
  139. &timer_initstruct0);
  140. #endif
  141. #ifdef BSP_USING_PWM1 /* 4 channels */
  142. static struct rt_device_pwm pwm_dev1;
  143. static timer_handle_t timer_initstruct1;
  144. timer_initstruct1.perh = GP16C4T0;
  145. timer_pwm_init(&timer_initstruct1);
  146. /* gpio initialization */
  147. gpio_initstructure.func = GPIO_FUNC_2;
  148. gpio_init(GPIOB, GPIO_PIN_6, &gpio_initstructure);
  149. gpio_init(GPIOB, GPIO_PIN_7, &gpio_initstructure);
  150. gpio_init(GPIOB, GPIO_PIN_8, &gpio_initstructure);
  151. gpio_init(GPIOB, GPIO_PIN_9, &gpio_initstructure);
  152. ret = rt_device_pwm_register(&pwm_dev1, "pwm1", &es32f0_pwm_ops,
  153. &timer_initstruct1);
  154. #endif
  155. #ifdef BSP_USING_PWM2 /* 2 channels */
  156. static struct rt_device_pwm pwm_dev2;
  157. static timer_handle_t timer_initstruct2;
  158. timer_initstruct2.perh = GP16C2T0;
  159. timer_pwm_init(&timer_initstruct2);
  160. /* gpio initialization */
  161. gpio_initstructure.func = GPIO_FUNC_2;
  162. gpio_init(GPIOA, GPIO_PIN_0, &gpio_initstructure);
  163. gpio_init(GPIOA, GPIO_PIN_1, &gpio_initstructure);
  164. ret = rt_device_pwm_register(&pwm_dev2, "pwm2", &es32f0_pwm_ops,
  165. &timer_initstruct2);
  166. #endif
  167. #ifdef BSP_USING_PWM3 /* 2 channels */
  168. static struct rt_device_pwm pwm_dev3;
  169. static timer_handle_t timer_initstruct3;
  170. timer_initstruct3.perh = GP16C2T1;
  171. timer_pwm_init(&timer_initstruct3);
  172. /* gpio initialization */
  173. gpio_initstructure.func = GPIO_FUNC_3;
  174. gpio_init(GPIOC, GPIO_PIN_6, &gpio_initstructure);
  175. gpio_init(GPIOC, GPIO_PIN_7, &gpio_initstructure);
  176. ret = rt_device_pwm_register(&pwm_dev3, "pwm3", &es32f0_pwm_ops,
  177. &timer_initstruct3);
  178. #endif
  179. return ret;
  180. }
  181. INIT_DEVICE_EXPORT(rt_hw_pwm_init);