From 886a99e736d09dcc778a316eb5b74f951536d009 Mon Sep 17 00:00:00 2001 From: Peter van der Perk Date: Mon, 31 Mar 2025 16:39:46 +0200 Subject: [PATCH] kinetis-tpm: Implement pulse_cycles directly instead of duty cycle When using low PWM frequency i.e 50Hz the resolution of pulse_cycles got lost from converting pulse_cycles to duty cycle % and then back to pulse_cycles again. Furthermore TPM_UpdateChnlEdgeLevelSelect call would restart the pwm constantly on a mcux_tpm_set_cycles call now only call TPM_UpdateChnlEdgeLevelSelect when changing the polarity Signed-off-by: Peter van der Perk --- drivers/pwm/pwm_mcux_tpm.c | 47 ++++++++++++++++++++++---------------- 1 file changed, 27 insertions(+), 20 deletions(-) diff --git a/drivers/pwm/pwm_mcux_tpm.c b/drivers/pwm/pwm_mcux_tpm.c index 1d0971aa20e..c647d673858 100644 --- a/drivers/pwm/pwm_mcux_tpm.c +++ b/drivers/pwm/pwm_mcux_tpm.c @@ -55,29 +55,22 @@ static int mcux_tpm_set_cycles(const struct device *dev, uint32_t channel, { const struct mcux_tpm_config *config = dev->config; struct mcux_tpm_data *data = dev->data; - uint8_t duty_cycle; - - if (period_cycles == 0U) { - LOG_ERR("Channel can not be set to inactive level"); - return -ENOTSUP; - } if (channel >= config->channel_count) { LOG_ERR("Invalid channel"); return -ENOTSUP; } - duty_cycle = pulse_cycles * 100U / period_cycles; - data->channel[channel].dutyCyclePercent = duty_cycle; - - if ((flags & PWM_POLARITY_INVERTED) == 0) { - data->channel[channel].level = kTPM_HighTrue; - } else { - data->channel[channel].level = kTPM_LowTrue; + if (period_cycles == 0 || period_cycles == TPM_MAX_COUNTER_VALUE(base)) { + return -ENOTSUP; } - LOG_DBG("pulse_cycles=%d, period_cycles=%d, duty_cycle=%d, flags=%d", - pulse_cycles, period_cycles, duty_cycle, flags); + if ((TPM_MAX_COUNTER_VALUE(base) == 0xFFFFU) && + (pulse_cycles > TPM_MAX_COUNTER_VALUE(base))) { + return -ENOTSUP; + } + + LOG_DBG("pulse_cycles=%d, period_cycles=%d, flags=%d", pulse_cycles, period_cycles, flags); if (period_cycles != data->period_cycles) { uint32_t pwm_freq; @@ -106,6 +99,9 @@ static int mcux_tpm_set_cycles(const struct device *dev, uint32_t channel, TPM_StopTimer(config->base); + /* Set counter back to zero */ + config->base->CNT = 0; + status = TPM_SetupPwm(config->base, data->channel, config->channel_count, config->mode, pwm_freq, data->clock_freq); @@ -115,13 +111,24 @@ static int mcux_tpm_set_cycles(const struct device *dev, uint32_t channel, return -ENOTSUP; } TPM_StartTimer(config->base, config->tpm_clock_source); - } else { - TPM_UpdateChnlEdgeLevelSelect(config->base, channel, - data->channel[channel].level); - TPM_UpdatePwmDutycycle(config->base, channel, config->mode, - duty_cycle); } + if ((flags & PWM_POLARITY_INVERTED) == 0 && + data->channel[channel].level != kTPM_HighTrue) { + data->channel[channel].level = kTPM_HighTrue; + TPM_UpdateChnlEdgeLevelSelect(config->base, channel, kTPM_HighTrue); + } else if ((flags & PWM_POLARITY_INVERTED) != 0 && + data->channel[channel].level != kTPM_LowTrue) { + data->channel[channel].level = kTPM_LowTrue; + TPM_UpdateChnlEdgeLevelSelect(config->base, channel, kTPM_LowTrue); + } + + if (pulse_cycles == period_cycles) { + pulse_cycles = period_cycles + 1U; + } + + config->base->CONTROLS[channel].CnV = pulse_cycles; + return 0; }