drv_tpwm.c 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. /**************************************************************************//**
  2. *
  3. * @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0
  6. *
  7. * Change Logs:
  8. * Date Author Notes
  9. * 2020-5-5 YCHuang12 First version
  10. *
  11. * Note: 2 channels of a tpwm have the same output.
  12. ******************************************************************************/
  13. #include <rtconfig.h>
  14. #if (defined(BSP_USING_TPWM) && defined(RT_USING_PWM))
  15. #define LOG_TAG "drv.tpwm"
  16. #define DBG_ENABLE
  17. #define DBG_SECTION_NAME LOG_TAG
  18. #define DBG_LEVEL DBG_INFO
  19. #define TPWM_CHANNEL_NUM 2
  20. #include <rtdbg.h>
  21. #include <stdint.h>
  22. #include <rtdevice.h>
  23. #include <rthw.h>
  24. #include "NuMicro.h"
  25. /* Private define ---------------------------------------------------------------*/
  26. #define NU_TPWM_DEVICE(tpwm) (nu_tpwm_t *)(tpwm)
  27. /* Private typedef --------------------------------------------------------------*/
  28. typedef struct nu_tpwm
  29. {
  30. struct rt_device_pwm tpwm_dev;
  31. char *name;
  32. TIMER_T *tpwm_base;
  33. rt_uint32_t channel_mask; //TPWM_CH0 | TPWM_CH1
  34. } nu_tpwm_t;
  35. /* Private functions ------------------------------------------------------------*/
  36. static rt_err_t nu_tpwm_enable(struct rt_device_pwm *tpwm_dev, struct rt_pwm_configuration *tpwm_config, rt_bool_t enable);
  37. static rt_err_t nu_tpwm_set(struct rt_device_pwm *tpwm_dev, struct rt_pwm_configuration *tpwm_config);
  38. static rt_err_t nu_tpwm_get(struct rt_device_pwm *tpwm_dev, struct rt_pwm_configuration *tpwm_config);
  39. static rt_err_t nu_tpwm_control(struct rt_device_pwm *tpwm_dev, int cmd, void *arg);
  40. /* Private variables ------------------------------------------------------------*/
  41. #ifdef BSP_USING_TPWM0
  42. static nu_tpwm_t nu_tpwm0;
  43. #endif
  44. #ifdef BSP_USING_TPWM1
  45. static nu_tpwm_t nu_tpwm1;
  46. #endif
  47. #ifdef BSP_USING_TPWM2
  48. static nu_tpwm_t nu_tpwm2;
  49. #endif
  50. #ifdef BSP_USING_TPWM3
  51. static nu_tpwm_t nu_tpwm3;
  52. #endif
  53. static struct rt_pwm_ops nu_tpwm_ops =
  54. {
  55. nu_tpwm_control
  56. };
  57. /* Functions define ------------------------------------------------------------*/
  58. static rt_err_t nu_tpwm_enable(struct rt_device_pwm *tpwm_dev, struct rt_pwm_configuration *tpwm_config, rt_bool_t enable)
  59. {
  60. rt_err_t result = RT_EOK;
  61. rt_uint32_t tpwm_channel = tpwm_config->channel;
  62. nu_tpwm_t *nu_tpwm = NU_TPWM_DEVICE(tpwm_dev->parent.user_data);
  63. if (enable == RT_TRUE)
  64. {
  65. if (nu_tpwm->channel_mask == 0)
  66. {
  67. TPWM_START_COUNTER(nu_tpwm->tpwm_base);
  68. }
  69. nu_tpwm->channel_mask |= (1 << tpwm_channel);
  70. TPWM_ENABLE_OUTPUT(nu_tpwm->tpwm_base, nu_tpwm->channel_mask);
  71. }
  72. else
  73. {
  74. nu_tpwm->channel_mask &= ~(1 << tpwm_channel);
  75. TPWM_ENABLE_OUTPUT(nu_tpwm->tpwm_base, nu_tpwm->channel_mask);
  76. if (nu_tpwm->channel_mask == 0)
  77. {
  78. TPWM_STOP_COUNTER(nu_tpwm->tpwm_base);
  79. }
  80. }
  81. return result;
  82. }
  83. static rt_err_t nu_tpwm_set(struct rt_device_pwm *tpwm_dev, struct rt_pwm_configuration *tpwm_config)
  84. {
  85. if (tpwm_config->period <= 0)
  86. return -(RT_ERROR);
  87. rt_uint32_t tpwm_freq, tpwm_dutycycle ;
  88. rt_uint32_t tpwm_period = tpwm_config->period;
  89. rt_uint32_t tpwm_pulse = tpwm_config->pulse;
  90. nu_tpwm_t *nu_tpwm = NU_TPWM_DEVICE(tpwm_dev->parent.user_data);
  91. rt_uint32_t pre_tpwm_prescaler = TPWM_GET_PRESCALER(nu_tpwm->tpwm_base);
  92. tpwm_freq = 1000000000 / tpwm_period;
  93. tpwm_dutycycle = (tpwm_pulse * 100) / tpwm_period;
  94. TPWM_ConfigOutputFreqAndDuty(nu_tpwm->tpwm_base, tpwm_freq, tpwm_dutycycle) ;
  95. return RT_EOK;
  96. }
  97. static rt_err_t nu_tpwm_get(struct rt_device_pwm *tpwm_dev, struct rt_pwm_configuration *tpwm_config)
  98. {
  99. rt_uint32_t tpwm_real_period, tpwm_real_duty, time_tick, u32TPWMClockFreq ;
  100. nu_tpwm_t *nu_tpwm = NU_TPWM_DEVICE(tpwm_dev->parent.user_data);
  101. rt_uint32_t tpwm_prescale = TPWM_GET_PRESCALER(nu_tpwm->tpwm_base);
  102. rt_uint32_t tpwm_period = TPWM_GET_PERIOD(nu_tpwm->tpwm_base);
  103. rt_uint32_t tpwm_pulse = TPWM_GET_CMPDAT(nu_tpwm->tpwm_base);
  104. u32TPWMClockFreq = TIMER_GetModuleClock(nu_tpwm->tpwm_base);
  105. time_tick = 1000000000000 / u32TPWMClockFreq;
  106. tpwm_real_period = (((tpwm_prescale + 1) * (tpwm_period + 1)) * time_tick) / 1000;
  107. tpwm_real_duty = (((tpwm_prescale + 1) * tpwm_pulse * time_tick)) / 1000;
  108. tpwm_config->period = tpwm_real_period;
  109. tpwm_config->pulse = tpwm_real_duty;
  110. LOG_I("%s %d %d %d\n", nu_tpwm->name, tpwm_config->channel, tpwm_config->period, tpwm_config->pulse);
  111. return RT_EOK;
  112. }
  113. static rt_err_t nu_tpwm_control(struct rt_device_pwm *tpwm_dev, int cmd, void *arg)
  114. {
  115. struct rt_pwm_configuration *tpwm_config = (struct rt_pwm_configuration *)arg;
  116. RT_ASSERT(tpwm_dev != RT_NULL);
  117. RT_ASSERT(tpwm_config != RT_NULL);
  118. nu_tpwm_t *nu_tpwm = NU_TPWM_DEVICE(tpwm_dev->parent.user_data);
  119. RT_ASSERT(nu_tpwm != RT_NULL);
  120. RT_ASSERT(nu_tpwm->tpwm_base != RT_NULL);
  121. if ((tpwm_config->channel + 1) > TPWM_CHANNEL_NUM)
  122. return -(RT_ERROR);
  123. switch (cmd)
  124. {
  125. case PWM_CMD_ENABLE:
  126. return nu_tpwm_enable(tpwm_dev, tpwm_config, RT_TRUE);
  127. case PWM_CMD_DISABLE:
  128. return nu_tpwm_enable(tpwm_dev, tpwm_config, RT_FALSE);
  129. case PWM_CMD_SET:
  130. return nu_tpwm_set(tpwm_dev, tpwm_config);
  131. case PWM_CMD_GET:
  132. return nu_tpwm_get(tpwm_dev, tpwm_config);
  133. default:
  134. break;
  135. }
  136. return -(RT_EINVAL);
  137. }
  138. int rt_hw_tpwm_init(void)
  139. {
  140. rt_err_t ret = RT_EOK;
  141. #ifdef BSP_USING_TPWM0
  142. nu_tpwm0.tpwm_base = TIMER0;
  143. nu_tpwm0.name = "tpwm0";
  144. nu_tpwm0.channel_mask = 0;
  145. ret = rt_device_pwm_register(&nu_tpwm0.tpwm_dev, nu_tpwm0.name, &nu_tpwm_ops, &nu_tpwm0);
  146. if (ret != RT_EOK)
  147. {
  148. rt_kprintf("tpwm0 register failed\n");
  149. }
  150. SYS_ResetModule(TMR0_RST);
  151. CLK_EnableModuleClock(TMR0_MODULE);
  152. TPWM_ENABLE_PWM_MODE(TIMER0);
  153. #endif
  154. #ifdef BSP_USING_TPWM1
  155. nu_tpwm1.tpwm_base = TIMER1;
  156. nu_tpwm1.name = "tpwm1";
  157. nu_tpwm1.channel_mask = 0;
  158. ret = rt_device_pwm_register(&nu_tpwm1.tpwm_dev, nu_tpwm1.name, &nu_tpwm_ops, &nu_tpwm1);
  159. if (ret != RT_EOK)
  160. {
  161. rt_kprintf("tpwm1 register failed\n");
  162. }
  163. SYS_ResetModule(TMR1_RST);
  164. CLK_EnableModuleClock(TMR1_MODULE);
  165. TPWM_ENABLE_PWM_MODE(TIMER1);
  166. #endif
  167. #ifdef BSP_USING_TPWM2
  168. nu_tpwm2.tpwm_base = TIMER2;
  169. nu_tpwm2.name = "tpwm2";
  170. nu_tpwm2.channel_mask = 0;
  171. ret = rt_device_pwm_register(&nu_tpwm2.tpwm_dev, nu_tpwm2.name, &nu_tpwm_ops, &nu_tpwm2);
  172. if (ret != RT_EOK)
  173. {
  174. rt_kprintf("tpwm2 register failed\n");
  175. }
  176. SYS_ResetModule(TMR2_RST);
  177. CLK_EnableModuleClock(TMR2_MODULE);
  178. TPWM_ENABLE_PWM_MODE(TIMER2);
  179. #endif
  180. #ifdef BSP_USING_TPWM3
  181. nu_tpwm3.tpwm_base = TIMER3;
  182. nu_tpwm3.name = "tpwm3";
  183. nu_tpwm3.channel_mask = 0;
  184. ret = rt_device_pwm_register(&nu_tpwm3.tpwm_dev, nu_tpwm3.name, &nu_tpwm_ops, &nu_tpwm3);
  185. if (ret != RT_EOK)
  186. {
  187. rt_kprintf("tpwm3 register failed\n");
  188. }
  189. SYS_ResetModule(TMR3_RST);
  190. CLK_EnableModuleClock(TMR3_MODULE);
  191. TPWM_ENABLE_PWM_MODE(TIMER3);
  192. #endif
  193. return ret;
  194. }
  195. INIT_DEVICE_EXPORT(rt_hw_tpwm_init);
  196. #endif //#if (defined(BSP_USING_TPWM) && defined(RT_USING_PWM))