From 2703d4cd2095b10c95bed2afb870332de75d0849 Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Thu, 27 Feb 2020 22:14:25 +0100 Subject: [PATCH] drivers: pwm: mcux_ftm: configure pwm in ticks, not frequency/percent Configure the PWM period and pulse width in timer ticks instead of calculating the frequency and duty cycle for use in the higher level MCUX API. This improves the resolution of the PWM output signal considerably. Signed-off-by: Henrik Brix Andersen --- drivers/pwm/pwm_mcux_ftm.c | 54 ++++++++++++-------------------------- 1 file changed, 17 insertions(+), 37 deletions(-) diff --git a/drivers/pwm/pwm_mcux_ftm.c b/drivers/pwm/pwm_mcux_ftm.c index ccc1b5f22e7..ae96cea12c5 100644 --- a/drivers/pwm/pwm_mcux_ftm.c +++ b/drivers/pwm/pwm_mcux_ftm.c @@ -30,7 +30,7 @@ struct mcux_ftm_config { struct mcux_ftm_data { u32_t clock_freq; u32_t period_cycles; - ftm_chnl_pwm_signal_param_t channel[MAX_CHANNELS]; + ftm_chnl_pwm_config_param_t channel[MAX_CHANNELS]; }; static int mcux_ftm_pin_set(struct device *dev, u32_t pwm, @@ -39,7 +39,7 @@ static int mcux_ftm_pin_set(struct device *dev, u32_t pwm, { const struct mcux_ftm_config *config = dev->config->config_info; struct mcux_ftm_data *data = dev->driver_data; - u8_t duty_cycle; + status_t status; if ((period_cycles == 0U) || (pulse_cycles > period_cycles)) { LOG_ERR("Invalid combination: period_cycles=%d, " @@ -52,8 +52,7 @@ static int mcux_ftm_pin_set(struct device *dev, u32_t pwm, return -ENOTSUP; } - duty_cycle = pulse_cycles * 100U / period_cycles; - data->channel[pwm].dutyCyclePercent = duty_cycle; + data->channel[pwm].dutyValue = pulse_cycles; if ((flags & PWM_POLARITY_INVERTED) == 0) { data->channel[pwm].level = kFTM_HighTrue; @@ -61,13 +60,10 @@ static int mcux_ftm_pin_set(struct device *dev, u32_t pwm, data->channel[pwm].level = kFTM_LowTrue; } - LOG_DBG("pulse_cycles=%d, period_cycles=%d, duty_cycle=%d, flags=%d", - pulse_cycles, period_cycles, duty_cycle, flags); + LOG_DBG("pulse_cycles=%d, period_cycles=%d, flags=%d", + pulse_cycles, period_cycles, flags); if (period_cycles != data->period_cycles) { - u32_t pwm_freq; - status_t status; - if (data->period_cycles != 0) { /* Only warn when not changing from zero */ LOG_WRN("Changing period cycles from %d to %d" @@ -78,38 +74,22 @@ static int mcux_ftm_pin_set(struct device *dev, u32_t pwm, data->period_cycles = period_cycles; - pwm_freq = (data->clock_freq >> config->prescale) / - period_cycles; - - LOG_DBG("pwm_freq=%d, clock_freq=%d", pwm_freq, - data->clock_freq); - - if (pwm_freq == 0U) { - LOG_ERR("Could not set up pwm_freq=%d", pwm_freq); - return -EINVAL; - } - FTM_StopTimer(config->base); + FTM_SetTimerPeriod(config->base, period_cycles); - status = FTM_SetupPwm(config->base, data->channel, - config->channel_count, config->mode, - pwm_freq, data->clock_freq); - - if (status != kStatus_Success) { - LOG_ERR("Could not set up pwm"); - return -ENOTSUP; - } FTM_SetSoftwareTrigger(config->base, true); FTM_StartTimer(config->base, config->ftm_clock_source); - } else { - FTM_UpdatePwmDutycycle(config->base, pwm, config->mode, - duty_cycle); - FTM_UpdateChnlEdgeLevelSelect(config->base, pwm, - data->channel[pwm].level); - FTM_SetSoftwareTrigger(config->base, true); } + status = FTM_SetupPwmMode(config->base, data->channel, + config->channel_count, config->mode); + if (status != kStatus_Success) { + LOG_ERR("Could not set up pwm"); + return -ENOTSUP; + } + FTM_SetSoftwareTrigger(config->base, true); + return 0; } @@ -128,7 +108,7 @@ static int mcux_ftm_init(struct device *dev) { const struct mcux_ftm_config *config = dev->config->config_info; struct mcux_ftm_data *data = dev->driver_data; - ftm_chnl_pwm_signal_param_t *channel = data->channel; + ftm_chnl_pwm_config_param_t *channel = data->channel; struct device *clock_dev; ftm_config_t ftm_config; int i; @@ -153,8 +133,8 @@ static int mcux_ftm_init(struct device *dev) for (i = 0; i < config->channel_count; i++) { channel->chnlNumber = i; channel->level = kFTM_NoPwmSignal; - channel->dutyCyclePercent = 0; - channel->firstEdgeDelayPercent = 0; + channel->dutyValue = 0; + channel->firstEdgeValue = 0; channel++; }