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 <hebad@vestas.com>
This commit is contained in:
Henrik Brix Andersen 2020-02-27 22:14:25 +01:00 committed by Maureen Helm
commit 2703d4cd20

View file

@ -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++;
}