Just update duty if frequency is not changed and PSM started. This removeis glitch or blinking when only duty is frequently changed.

This commit is contained in:
Pierre-noel Bouteville 2016-06-05 15:35:43 -06:00 committed by Gregory Nutt
parent af43ce4f46
commit 0bd444ae47

View File

@ -166,8 +166,8 @@ enum stm32_chanmode_e
struct stm32_pwmchan_s
{
uint8_t channel; /* Timer output channel: {1,..4} */
uint32_t pincfg; /* Output pin configuration */
uint8_t channel; /* Timer output channel: {1,..4} */
uint32_t pincfg; /* Output pin configuration */
enum stm32_chanmode_e mode;
};
@ -176,21 +176,23 @@ struct stm32_pwmchan_s
struct stm32_pwmtimer_s
{
FAR const struct pwm_ops_s *ops; /* PWM operations */
uint8_t timid; /* Timer ID {1,...,17} */
struct stm32_pwmchan_s channels[PWM_NCHANNELS];
uint8_t timtype; /* See the TIMTYPE_* definitions */
enum stm32_timmode_e mode;
uint8_t timid; /* Timer ID {1,...,17} */
struct stm32_pwmchan_s channels[PWM_NCHANNELS];
uint8_t timtype; /* See the TIMTYPE_* definitions */
enum stm32_timmode_e mode;
#ifdef CONFIG_PWM_PULSECOUNT
uint8_t irq; /* Timer update IRQ */
uint8_t prev; /* The previous value of the RCR (pre-loaded) */
uint8_t curr; /* The current value of the RCR (pre-loaded) */
uint32_t count; /* Remaining pluse count */
uint8_t irq; /* Timer update IRQ */
uint8_t prev; /* The previous value of the RCR (pre-loaded) */
uint8_t curr; /* The current value of the RCR (pre-loaded) */
uint32_t count; /* Remaining pluse count */
#else
int frequency; /* Current frequency setting */
#endif
uint32_t base; /* The base address of the timer */
uint32_t pclk; /* The frequency of the peripheral clock
uint32_t base; /* The base address of the timer */
uint32_t pclk; /* The frequency of the peripheral clock
* that drives the timer module. */
#ifdef CONFIG_PWM_PULSECOUNT
FAR void *handle; /* Handle used for upper-half callback */
FAR void *handle; /* Handle used for upper-half callback */
#endif
};
@ -1634,6 +1636,89 @@ static int pwm_timer(FAR struct stm32_pwmtimer_s *priv,
return OK;
}
#ifndef CONFIG_PWM_PULSECOUNT
/****************************************************************************
* Name: pwm_update_duty
*
* Description:
* Try to change only channel duty.
*
* Input parameters:
* priv - A reference to the lower half PWM driver state structure
* channel - Channel to by updated
* duty - New duty.
*
* Returned Value:
* Zero on success; a negated errno value on failure
*
****************************************************************************/
static int pwm_update_duty(FAR struct stm32_pwmtimer_s *priv, uint8_t channel,
ub16_t duty)
{
/* Register offset */
int ccr_offset;
/* Calculated values */
uint32_t reload;
uint32_t ccr;
DEBUGASSERT(priv != NULL);
pwmvdbg("TIM%d channel: %d duty: %08x\n",
priv->timid, channel, duty);
#ifndef CONFIG_PWM_MULTICHAN
DEBUGASSERT(channel == priv->channels[0].channel);
DEBUGASSERT(chan->duty >= 0 && chan->duty < uitoub16(100));
#endif
/* Get the reload values */
reload = pwm_getreg(priv, STM32_GTIM_ARR_OFFSET);
/* Duty cycle:
*
* duty cycle = ccr / reload (fractional value)
*/
ccr = b16toi(duty * reload + b16HALF);
pwmvdbg("ccr: %d\n", ccr);
switch (channel)
{
case 1: /* Register offset for Channel 1 */
ccr_offset = STM32_GTIM_CCR1_OFFSET;
break;
case 2: /* Register offset for Channel 2 */
ccr_offset = STM32_GTIM_CCR2_OFFSET;
break;
case 3: /* Register offset for Channel 3 */
ccr_offset = STM32_GTIM_CCR3_OFFSET;
break;
case 4: /* Register offset for Channel 4 */
ccr_offset = STM32_GTIM_CCR4_OFFSET;
break;
default:
pwmdbg("No such channel: %d\n", channel);
return -EINVAL;
}
/* Set the duty cycle by writing to the CCR register for this channel */
pwm_putreg(priv, ccr_offset, (uint16_t)ccr);
return OK;
}
#endif
/****************************************************************************
* Name: pwm_interrupt
*
@ -2082,8 +2167,43 @@ static int pwm_start(FAR struct pwm_lowerhalf_s *dev,
static int pwm_start(FAR struct pwm_lowerhalf_s *dev,
FAR const struct pwm_info_s *info)
{
int ret = OK;
FAR struct stm32_pwmtimer_s *priv = (FAR struct stm32_pwmtimer_s *)dev;
return pwm_timer(priv, info);
#ifndef CONFIG_PWM_PULSECOUNT
/* if frequency has not changed we just update duty */
if ( info->frequency == priv->frequency )
{
#ifdef CONFIG_PWM_MULTICHAN
int i;
for (i = 0; ret == OK && i < CONFIG_PWM_NCHANNELS; i++)
{
ret = pwm_update_duty(priv,info->channels[i].channel,
info->channels[i].duty);
}
#else
ret = pwm_update_duty(priv,priv->channels[0].channel,info->duty);
#endif
}
else
#endif
{
ret = pwm_timer(priv, info);
#ifndef CONFIG_PWM_PULSECOUNT
/* Save current frequency */
if ( ret == OK )
{
priv->frequency = info->frequency;
}
#endif
}
return ret;
}
#endif
@ -2122,6 +2242,10 @@ static int pwm_stop(FAR struct pwm_lowerhalf_s *dev)
flags = enter_critical_section();
/* Stopped so frequency is zero */
priv->frequency = 0;
/* Disable further interrupts and stop the timer */
pwm_putreg(priv, STM32_GTIM_DIER_OFFSET, 0);