From a3986eeba34ae6d776ce3d7baeaa802017a310fc Mon Sep 17 00:00:00 2001 From: Michal Lenc <michallenc@seznam.cz> Date: Wed, 4 Aug 2021 23:05:27 +0200 Subject: [PATCH] arch/arm/src/imxrt/imxrt_flexpwm.c: Set LDOK bits after all channels are set This commit changes the FLexPWM driver for iMXRT MCU so that LDOK bits in Master Control Register are set at once after all channels are configured. Setting LDOK bit enables the driver to load prescaler, modulus and PWM values of corresponging submodule and start PWM output. Setting all bits at once instead of doing it separately can help avoiding the channels to be out of sync with each other. Signed-off-by: Michal Lenc <michallenc@seznam.cz> --- arch/arm/src/imxrt/imxrt_flexpwm.c | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/arch/arm/src/imxrt/imxrt_flexpwm.c b/arch/arm/src/imxrt/imxrt_flexpwm.c index 16885db51e..64913cbdc6 100644 --- a/arch/arm/src/imxrt/imxrt_flexpwm.c +++ b/arch/arm/src/imxrt/imxrt_flexpwm.c @@ -616,10 +616,6 @@ static int pwm_change_freq(FAR struct pwm_lowerhalf_s *dev, putreg16(regval, priv->base + IMXRT_FLEXPWM_SM0VAL5_OFFSET + MODULE_OFFSET * shift); - regval = getreg16(priv->base + IMXRT_FLEXPWM_MCTRL_OFFSET); - regval |= MCTRL_LDOK(1 << shift); - putreg16(regval, priv->base + IMXRT_FLEXPWM_MCTRL_OFFSET); - return OK; } @@ -683,10 +679,6 @@ static int pwm_set_output(FAR struct pwm_lowerhalf_s *dev, uint8_t channel, putreg16(regval, priv->base + IMXRT_FLEXPWM_OUTEN_OFFSET); } - regval = getreg16(priv->base + IMXRT_FLEXPWM_MCTRL_OFFSET); - regval |= MCTRL_LDOK(1 << shift); - putreg16(regval, priv->base + IMXRT_FLEXPWM_MCTRL_OFFSET); - return OK; } @@ -887,6 +879,7 @@ static int pwm_start(FAR struct pwm_lowerhalf_s *dev, { FAR struct imxrt_flexpwm_s *priv = (FAR struct imxrt_flexpwm_s *)dev; int ret = OK; + uint8_t ldok_map = 0; /* Change frequency only if it is needed */ @@ -894,6 +887,7 @@ static int pwm_start(FAR struct pwm_lowerhalf_s *dev, { for (int i = 0; i < PWM_NCHANNELS; i++) { +#ifdef CONFIG_PWM_MULTICHAN /* Break the loop if all following channels are not configured */ if (info->channels[i].channel == -1) @@ -907,6 +901,9 @@ static int pwm_start(FAR struct pwm_lowerhalf_s *dev, { ret = pwm_change_freq(dev, info, i); } +#else + ret = pwm_change_freq(dev, info, i); +#endif } /* Save current frequency */ @@ -933,14 +930,28 @@ static int pwm_start(FAR struct pwm_lowerhalf_s *dev, { ret = pwm_set_output(dev, info->channels[i].channel, info->channels[i].duty); + + /* Remember the channel number in bitmap */ + + ldok_map |= 1 << (info->channels[i].channel - 1); } } #else /* Enable PWM output just for first channel */ ret = pwm_set_output(dev, priv->modules[0].module, info->duty); + + /* Remember the channel number in bitmap */ + + ldok_map = 1 << (priv->modules[0].module - 1); #endif /* CONFIG_PWM_MULTICHAN */ + /* Set Load Okay bits */ + + uint16_t regval = getreg16(priv->base + IMXRT_FLEXPWM_MCTRL_OFFSET); + regval |= MCTRL_LDOK(ldok_map); + putreg16(regval, priv->base + IMXRT_FLEXPWM_MCTRL_OFFSET); + return ret; }