123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236 |
- /**************************************************************************//**
- *
- * @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved.
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2020-5-5 YCHuang12 First version
- *
- * Note: 2 channels of a tpwm have the same output.
- ******************************************************************************/
- #include <rtconfig.h>
- #if (defined(BSP_USING_TPWM) && defined(RT_USING_PWM))
- #define LOG_TAG "drv.tpwm"
- #define DBG_ENABLE
- #define DBG_SECTION_NAME LOG_TAG
- #define DBG_LEVEL DBG_INFO
- #define TPWM_CHANNEL_NUM 2
- #include <rtdbg.h>
- #include <stdint.h>
- #include <rtdevice.h>
- #include <rthw.h>
- #include "NuMicro.h"
- /* Private define ---------------------------------------------------------------*/
- #define NU_TPWM_DEVICE(tpwm) (nu_tpwm_t *)(tpwm)
- /* Private typedef --------------------------------------------------------------*/
- typedef struct nu_tpwm
- {
- struct rt_device_pwm tpwm_dev;
- char *name;
- TIMER_T *tpwm_base;
- rt_uint32_t channel_mask; //TPWM_CH0 | TPWM_CH1
- } nu_tpwm_t;
- /* Private functions ------------------------------------------------------------*/
- static rt_err_t nu_tpwm_enable(struct rt_device_pwm *tpwm_dev, struct rt_pwm_configuration *tpwm_config, rt_bool_t enable);
- static rt_err_t nu_tpwm_set(struct rt_device_pwm *tpwm_dev, struct rt_pwm_configuration *tpwm_config);
- static rt_err_t nu_tpwm_get(struct rt_device_pwm *tpwm_dev, struct rt_pwm_configuration *tpwm_config);
- static rt_err_t nu_tpwm_control(struct rt_device_pwm *tpwm_dev, int cmd, void *arg);
- /* Private variables ------------------------------------------------------------*/
- #ifdef BSP_USING_TPWM0
- static nu_tpwm_t nu_tpwm0;
- #endif
- #ifdef BSP_USING_TPWM1
- static nu_tpwm_t nu_tpwm1;
- #endif
- #ifdef BSP_USING_TPWM2
- static nu_tpwm_t nu_tpwm2;
- #endif
- #ifdef BSP_USING_TPWM3
- static nu_tpwm_t nu_tpwm3;
- #endif
- static struct rt_pwm_ops nu_tpwm_ops =
- {
- nu_tpwm_control
- };
- /* Functions define ------------------------------------------------------------*/
- static rt_err_t nu_tpwm_enable(struct rt_device_pwm *tpwm_dev, struct rt_pwm_configuration *tpwm_config, rt_bool_t enable)
- {
- rt_err_t result = RT_EOK;
- rt_uint32_t tpwm_channel = tpwm_config->channel;
- nu_tpwm_t *nu_tpwm = NU_TPWM_DEVICE(tpwm_dev->parent.user_data);
- if (enable == RT_TRUE)
- {
- if (nu_tpwm->channel_mask == 0)
- {
- TPWM_START_COUNTER(nu_tpwm->tpwm_base);
- }
- nu_tpwm->channel_mask |= (1 << tpwm_channel);
- TPWM_ENABLE_OUTPUT(nu_tpwm->tpwm_base, nu_tpwm->channel_mask);
- }
- else
- {
- nu_tpwm->channel_mask &= ~(1 << tpwm_channel);
- TPWM_ENABLE_OUTPUT(nu_tpwm->tpwm_base, nu_tpwm->channel_mask);
- if (nu_tpwm->channel_mask == 0)
- {
- TPWM_STOP_COUNTER(nu_tpwm->tpwm_base);
- }
- }
- return result;
- }
- static rt_err_t nu_tpwm_set(struct rt_device_pwm *tpwm_dev, struct rt_pwm_configuration *tpwm_config)
- {
- if (tpwm_config->period <= 0)
- return -(RT_ERROR);
- rt_uint32_t tpwm_freq, tpwm_dutycycle ;
- rt_uint32_t tpwm_period = tpwm_config->period;
- rt_uint32_t tpwm_pulse = tpwm_config->pulse;
- nu_tpwm_t *nu_tpwm = NU_TPWM_DEVICE(tpwm_dev->parent.user_data);
- rt_uint32_t pre_tpwm_prescaler = TPWM_GET_PRESCALER(nu_tpwm->tpwm_base);
- tpwm_freq = 1000000000 / tpwm_period;
- tpwm_dutycycle = (tpwm_pulse * 100) / tpwm_period;
- TPWM_ConfigOutputFreqAndDuty(nu_tpwm->tpwm_base, tpwm_freq, tpwm_dutycycle) ;
- return RT_EOK;
- }
- static rt_err_t nu_tpwm_get(struct rt_device_pwm *tpwm_dev, struct rt_pwm_configuration *tpwm_config)
- {
- rt_uint32_t tpwm_real_period, tpwm_real_duty, time_tick, u32TPWMClockFreq ;
- nu_tpwm_t *nu_tpwm = NU_TPWM_DEVICE(tpwm_dev->parent.user_data);
- rt_uint32_t tpwm_prescale = TPWM_GET_PRESCALER(nu_tpwm->tpwm_base);
- rt_uint32_t tpwm_period = TPWM_GET_PERIOD(nu_tpwm->tpwm_base);
- rt_uint32_t tpwm_pulse = TPWM_GET_CMPDAT(nu_tpwm->tpwm_base);
- u32TPWMClockFreq = TIMER_GetModuleClock(nu_tpwm->tpwm_base);
- time_tick = 1000000000000 / u32TPWMClockFreq;
- tpwm_real_period = (((tpwm_prescale + 1) * (tpwm_period + 1)) * time_tick) / 1000;
- tpwm_real_duty = (((tpwm_prescale + 1) * tpwm_pulse * time_tick)) / 1000;
- tpwm_config->period = tpwm_real_period;
- tpwm_config->pulse = tpwm_real_duty;
- LOG_I("%s %d %d %d\n", nu_tpwm->name, tpwm_config->channel, tpwm_config->period, tpwm_config->pulse);
- return RT_EOK;
- }
- static rt_err_t nu_tpwm_control(struct rt_device_pwm *tpwm_dev, int cmd, void *arg)
- {
- struct rt_pwm_configuration *tpwm_config = (struct rt_pwm_configuration *)arg;
- RT_ASSERT(tpwm_dev != RT_NULL);
- RT_ASSERT(tpwm_config != RT_NULL);
- nu_tpwm_t *nu_tpwm = NU_TPWM_DEVICE(tpwm_dev->parent.user_data);
- RT_ASSERT(nu_tpwm != RT_NULL);
- RT_ASSERT(nu_tpwm->tpwm_base != RT_NULL);
- if ((tpwm_config->channel + 1) > TPWM_CHANNEL_NUM)
- return -(RT_ERROR);
- switch (cmd)
- {
- case PWM_CMD_ENABLE:
- return nu_tpwm_enable(tpwm_dev, tpwm_config, RT_TRUE);
- case PWM_CMD_DISABLE:
- return nu_tpwm_enable(tpwm_dev, tpwm_config, RT_FALSE);
- case PWM_CMD_SET:
- return nu_tpwm_set(tpwm_dev, tpwm_config);
- case PWM_CMD_GET:
- return nu_tpwm_get(tpwm_dev, tpwm_config);
- default:
- break;
- }
- return -(RT_EINVAL);
- }
- int rt_hw_tpwm_init(void)
- {
- rt_err_t ret = RT_EOK;
- #ifdef BSP_USING_TPWM0
- nu_tpwm0.tpwm_base = TIMER0;
- nu_tpwm0.name = "tpwm0";
- nu_tpwm0.channel_mask = 0;
- ret = rt_device_pwm_register(&nu_tpwm0.tpwm_dev, nu_tpwm0.name, &nu_tpwm_ops, &nu_tpwm0);
- if (ret != RT_EOK)
- {
- rt_kprintf("tpwm0 register failed\n");
- }
- SYS_ResetModule(TMR0_RST);
- CLK_EnableModuleClock(TMR0_MODULE);
- TPWM_ENABLE_PWM_MODE(TIMER0);
- #endif
- #ifdef BSP_USING_TPWM1
- nu_tpwm1.tpwm_base = TIMER1;
- nu_tpwm1.name = "tpwm1";
- nu_tpwm1.channel_mask = 0;
- ret = rt_device_pwm_register(&nu_tpwm1.tpwm_dev, nu_tpwm1.name, &nu_tpwm_ops, &nu_tpwm1);
- if (ret != RT_EOK)
- {
- rt_kprintf("tpwm1 register failed\n");
- }
- SYS_ResetModule(TMR1_RST);
- CLK_EnableModuleClock(TMR1_MODULE);
- TPWM_ENABLE_PWM_MODE(TIMER1);
- #endif
- #ifdef BSP_USING_TPWM2
- nu_tpwm2.tpwm_base = TIMER2;
- nu_tpwm2.name = "tpwm2";
- nu_tpwm2.channel_mask = 0;
- ret = rt_device_pwm_register(&nu_tpwm2.tpwm_dev, nu_tpwm2.name, &nu_tpwm_ops, &nu_tpwm2);
- if (ret != RT_EOK)
- {
- rt_kprintf("tpwm2 register failed\n");
- }
- SYS_ResetModule(TMR2_RST);
- CLK_EnableModuleClock(TMR2_MODULE);
- TPWM_ENABLE_PWM_MODE(TIMER2);
- #endif
- #ifdef BSP_USING_TPWM3
- nu_tpwm3.tpwm_base = TIMER3;
- nu_tpwm3.name = "tpwm3";
- nu_tpwm3.channel_mask = 0;
- ret = rt_device_pwm_register(&nu_tpwm3.tpwm_dev, nu_tpwm3.name, &nu_tpwm_ops, &nu_tpwm3);
- if (ret != RT_EOK)
- {
- rt_kprintf("tpwm3 register failed\n");
- }
- SYS_ResetModule(TMR3_RST);
- CLK_EnableModuleClock(TMR3_MODULE);
- TPWM_ENABLE_PWM_MODE(TIMER3);
- #endif
- return ret;
- }
- INIT_DEVICE_EXPORT(rt_hw_tpwm_init);
- #endif //#if (defined(BSP_USING_TPWM) && defined(RT_USING_PWM))
|