drv_tpwm.c 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  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. * 2022-3-15 Wayne 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 <rtdevice.h>
  22. #include "NuMicro.h"
  23. /* Private define ---------------------------------------------------------------*/
  24. #define NU_TPWM_DEVICE(tpwm) (nu_tpwm_t)(tpwm)
  25. enum
  26. {
  27. TPWM_START = -1,
  28. #if defined(BSP_USING_TPWM0)
  29. TPWM0_IDX,
  30. #endif
  31. #if defined(BSP_USING_TPWM1)
  32. TPWM1_IDX,
  33. #endif
  34. #if defined(BSP_USING_TPWM2)
  35. TPWM2_IDX,
  36. #endif
  37. #if defined(BSP_USING_TPWM3)
  38. TPWM3_IDX,
  39. #endif
  40. TPWM_CNT
  41. };
  42. /* Private typedef --------------------------------------------------------------*/
  43. struct nu_tpwm
  44. {
  45. struct rt_device_pwm tpwm_dev;
  46. char *name;
  47. TIMER_T *base;
  48. uint32_t rstidx;
  49. uint32_t modid;
  50. rt_uint32_t channel_mask; //TPWM_CH0 | TPWM_CH1
  51. } ;
  52. typedef struct nu_tpwm *nu_tpwm_t;
  53. /* Private functions ------------------------------------------------------------*/
  54. static rt_err_t nu_tpwm_enable(struct rt_device_pwm *tpwm_dev, struct rt_pwm_configuration *tpwm_config, rt_bool_t enable);
  55. static rt_err_t nu_tpwm_set(struct rt_device_pwm *tpwm_dev, struct rt_pwm_configuration *tpwm_config);
  56. static rt_err_t nu_tpwm_get(struct rt_device_pwm *tpwm_dev, struct rt_pwm_configuration *tpwm_config);
  57. static rt_err_t nu_tpwm_control(struct rt_device_pwm *tpwm_dev, int cmd, void *arg);
  58. /* Private variables ------------------------------------------------------------*/
  59. static struct nu_tpwm nu_tpwm_arr [] =
  60. {
  61. #if defined(BSP_USING_TPWM0)
  62. { .name = "tpwm0", .base = TIMER0, .rstidx = TMR0_RST, .modid = TMR0_MODULE },
  63. #endif
  64. #if defined(BSP_USING_TPWM1)
  65. { .name = "tpwm1", .base = TIMER1, .rstidx = TMR1_RST, .modid = TMR1_MODULE },
  66. #endif
  67. #if defined(BSP_USING_TPWM2)
  68. { .name = "tpwm2", .base = TIMER2, .rstidx = TMR2_RST, .modid = TMR2_MODULE },
  69. #endif
  70. #if defined(BSP_USING_TPWM3)
  71. { .name = "tpwm3", .base = TIMER3, .rstidx = TMR3_RST, .modid = TMR3_MODULE },
  72. #endif
  73. };
  74. static struct rt_pwm_ops nu_tpwm_ops =
  75. {
  76. nu_tpwm_control
  77. };
  78. /* Functions define ------------------------------------------------------------*/
  79. static rt_err_t nu_tpwm_enable(struct rt_device_pwm *tpwm_dev, struct rt_pwm_configuration *tpwm_config, rt_bool_t enable)
  80. {
  81. rt_err_t result = RT_EOK;
  82. rt_uint32_t tpwm_channel = tpwm_config->channel;
  83. nu_tpwm_t psNuTPWM = NU_TPWM_DEVICE(tpwm_dev->parent.user_data);
  84. if (enable == RT_TRUE)
  85. {
  86. if (psNuTPWM->channel_mask == 0)
  87. {
  88. TPWM_START_COUNTER(psNuTPWM->base);
  89. }
  90. psNuTPWM->channel_mask |= (1 << tpwm_channel);
  91. TPWM_ENABLE_OUTPUT(psNuTPWM->base, psNuTPWM->channel_mask);
  92. }
  93. else
  94. {
  95. psNuTPWM->channel_mask &= ~(1 << tpwm_channel);
  96. TPWM_ENABLE_OUTPUT(psNuTPWM->base, psNuTPWM->channel_mask);
  97. if (psNuTPWM->channel_mask == 0)
  98. {
  99. TPWM_STOP_COUNTER(psNuTPWM->base);
  100. }
  101. }
  102. return result;
  103. }
  104. static rt_err_t nu_tpwm_set(struct rt_device_pwm *tpwm_dev, struct rt_pwm_configuration *tpwm_config)
  105. {
  106. if (tpwm_config->period <= 0)
  107. return -(RT_ERROR);
  108. rt_uint32_t tpwm_freq, tpwm_dutycycle ;
  109. rt_uint32_t tpwm_period = tpwm_config->period;
  110. rt_uint32_t tpwm_pulse = tpwm_config->pulse;
  111. nu_tpwm_t psNuTPWM = NU_TPWM_DEVICE(tpwm_dev->parent.user_data);
  112. rt_uint32_t pre_tpwm_prescaler = TPWM_GET_PRESCALER(psNuTPWM->base);
  113. tpwm_freq = 1000000000 / tpwm_period;
  114. tpwm_dutycycle = (tpwm_pulse * 100) / tpwm_period;
  115. TPWM_ConfigOutputFreqAndDuty(psNuTPWM->base, tpwm_freq, tpwm_dutycycle) ;
  116. return RT_EOK;
  117. }
  118. static rt_err_t nu_tpwm_get(struct rt_device_pwm *tpwm_dev, struct rt_pwm_configuration *tpwm_config)
  119. {
  120. rt_uint32_t tpwm_real_period, tpwm_real_duty, time_tick, u32TPWMClockFreq ;
  121. nu_tpwm_t psNuTPWM = NU_TPWM_DEVICE(tpwm_dev->parent.user_data);
  122. rt_uint32_t tpwm_prescale = TPWM_GET_PRESCALER(psNuTPWM->base);
  123. rt_uint32_t tpwm_period = TPWM_GET_PERIOD(psNuTPWM->base);
  124. rt_uint32_t tpwm_pulse = TPWM_GET_CMPDAT(psNuTPWM->base);
  125. u32TPWMClockFreq = TIMER_GetModuleClock(psNuTPWM->base);
  126. time_tick = (uint64_t)1000000000000 / u32TPWMClockFreq;
  127. LOG_I("%s reg--> %d %d %d %d %d\n", psNuTPWM->name, tpwm_prescale, tpwm_period, tpwm_pulse, u32TPWMClockFreq, time_tick);
  128. tpwm_real_period = (((tpwm_prescale + 1) * (tpwm_period + 1)) * time_tick) / 1000;
  129. tpwm_real_duty = (((tpwm_prescale + 1) * tpwm_pulse * time_tick)) / 1000;
  130. tpwm_config->period = tpwm_real_period;
  131. tpwm_config->pulse = tpwm_real_duty;
  132. LOG_I("%s %d %d %d\n", psNuTPWM->name, tpwm_config->channel, tpwm_config->period, tpwm_config->pulse);
  133. return RT_EOK;
  134. }
  135. static rt_err_t nu_tpwm_control(struct rt_device_pwm *tpwm_dev, int cmd, void *arg)
  136. {
  137. struct rt_pwm_configuration *tpwm_config = (struct rt_pwm_configuration *)arg;
  138. RT_ASSERT(tpwm_dev != RT_NULL);
  139. RT_ASSERT(tpwm_config != RT_NULL);
  140. nu_tpwm_t psNuTPWM = NU_TPWM_DEVICE(tpwm_dev->parent.user_data);
  141. RT_ASSERT(psNuTPWM != RT_NULL);
  142. RT_ASSERT(psNuTPWM->base != RT_NULL);
  143. if ((tpwm_config->channel + 1) > TPWM_CHANNEL_NUM)
  144. return -(RT_ERROR);
  145. switch (cmd)
  146. {
  147. case PWM_CMD_ENABLE:
  148. return nu_tpwm_enable(tpwm_dev, tpwm_config, RT_TRUE);
  149. case PWM_CMD_DISABLE:
  150. return nu_tpwm_enable(tpwm_dev, tpwm_config, RT_FALSE);
  151. case PWM_CMD_SET:
  152. return nu_tpwm_set(tpwm_dev, tpwm_config);
  153. case PWM_CMD_GET:
  154. return nu_tpwm_get(tpwm_dev, tpwm_config);
  155. default:
  156. break;
  157. }
  158. return -(RT_EINVAL);
  159. }
  160. int rt_hw_tpwm_init(void)
  161. {
  162. int i;
  163. rt_err_t ret = RT_EOK;
  164. for (i = (TPWM_START + 1); i < TPWM_CNT; i++)
  165. {
  166. nu_tpwm_arr[i].channel_mask = 0;
  167. CLK_EnableModuleClock(nu_tpwm_arr[i].modid);
  168. SYS_ResetModule(nu_tpwm_arr[i].rstidx);
  169. TPWM_ENABLE_PWM_MODE(nu_tpwm_arr[i].base);
  170. /* Register RT PWM device. */
  171. ret = rt_device_pwm_register(&nu_tpwm_arr[i].tpwm_dev, nu_tpwm_arr[i].name, &nu_tpwm_ops, &nu_tpwm_arr[i]);
  172. RT_ASSERT(ret == RT_EOK);
  173. }
  174. return 0;
  175. }
  176. INIT_DEVICE_EXPORT(rt_hw_tpwm_init);
  177. #endif //#if (defined(BSP_USING_TPWM) && defined(RT_USING_PWM))