Fix the STM32 PWM driver pulse count logic
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@4298 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
parent
67631ddea7
commit
397edddc5b
@ -145,8 +145,7 @@ struct stm32_pwmtimer_s
|
||||
uint8_t timtype; /* See the TIMTYPE_* definitions */
|
||||
#ifdef CONFIG_PWM_PULSECOUNT
|
||||
uint8_t irq; /* Timer update IRQ */
|
||||
#else
|
||||
uint8_t unused;
|
||||
bool endseq; /* True: Next interrupt is the end */
|
||||
#endif
|
||||
uint32_t base; /* The base address of the timer */
|
||||
uint32_t pincfg; /* Output pin configuration */
|
||||
@ -552,9 +551,18 @@ static int pwm_timer(FAR struct stm32_pwmtimer_s *priv,
|
||||
|
||||
DEBUGASSERT(priv != NULL && info != NULL);
|
||||
|
||||
#ifdef CONFIG_PWM_PULSECOUNT
|
||||
pwmvdbg("TIM%d channel: %d frequency: %d duty: %08x count: %d\n",
|
||||
priv->timid, priv->channel, info->frequency,
|
||||
info->duty, info->count);
|
||||
DEBUGASSERT(info->frequency > 0 && info->duty > 0 &&
|
||||
info->duty < uitoub16(100) && info->count < PWM_MAX_COUNT);
|
||||
#else
|
||||
pwmvdbg("TIM%d channel: %d frequency: %d duty: %08x\n",
|
||||
priv->timid, priv->channel, info->frequency, info->duty);
|
||||
DEBUGASSERT(info->frequency > 0 && info->duty > 0 && info->duty < uitoub16(100));
|
||||
DEBUGASSERT(info->frequency > 0 && info->duty > 0 &&
|
||||
info->duty < uitoub16(100));
|
||||
#endif
|
||||
|
||||
/* Disable all interrupts and DMA requests, clear all pending status */
|
||||
|
||||
@ -884,9 +892,11 @@ static int pwm_timer(FAR struct stm32_pwmtimer_s *priv,
|
||||
#ifdef CONFIG_PWM_PULSECOUNT
|
||||
if (info->count > 0)
|
||||
{
|
||||
/* Enable the update interrupt. */
|
||||
/* Clear all pending interrupts and enable the update interrupt. */
|
||||
|
||||
pwm_putreg(priv, STM32_GTIM_SR_OFFSET, 0);
|
||||
pwm_putreg(priv, STM32_GTIM_DIER_OFFSET, ATIM_DIER_UIE);
|
||||
priv->endseq = false;
|
||||
|
||||
/* Enable the timer */
|
||||
|
||||
@ -927,19 +937,49 @@ static int pwm_timer(FAR struct stm32_pwmtimer_s *priv,
|
||||
#if defined(CONFIG_PWM_PULSECOUNT) && (defined(CONFIG_STM32_TIM1_PWM) || defined(CONFIG_STM32_TIM8_PWM))
|
||||
static int pwm_interrupt(struct stm32_pwmtimer_s *priv)
|
||||
{
|
||||
uint16_t regval;
|
||||
|
||||
/* Verify that this is an update interrupt. Nothing else is expected. */
|
||||
|
||||
pwmllvdbg("Update interrupt: %04x\n", pwm_getreg(priv, STM32_GTIM_SR_OFFSET));
|
||||
DEBUGASSERT((pwm_getreg(priv, STM32_GTIM_SR_OFFSET) & ATIM_SR_UIF) != 0);
|
||||
regval = pwm_getreg(priv, STM32_ATIM_SR_OFFSET);
|
||||
DEBUGASSERT((regval & ATIM_SR_UIF) != 0);
|
||||
|
||||
/* Disable further interrupts and stop the timer */
|
||||
/* Clear the UIF interrupt bit */
|
||||
|
||||
(void)pwm_stop((FAR struct pwm_lowerhalf_s *)priv);
|
||||
pwm_putreg(priv, STM32_ATIM_SR_OFFSET, regval & ~ATIM_SR_UIF);
|
||||
|
||||
/* Then perform the callback into the upper half driver */
|
||||
/* Now all of the time critical stuff is done so we can do some debug output */
|
||||
|
||||
pwmllvdbg("Update interrupt SR: %04x RCR: %d endseq: %d\n",
|
||||
regval, pwm_getreg(priv, STM32_ATIM_RCR_OFFSET), priv->endseq);
|
||||
|
||||
/* Ignore the first update interrupt. That apparently happens when the
|
||||
* timer first starts so we always get one immediately. The second is
|
||||
* one that is controlled by RCR.
|
||||
*/
|
||||
|
||||
if (!priv->endseq)
|
||||
{
|
||||
/* The next interrupt will be the one we care about. */
|
||||
|
||||
priv->endseq = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* OK.. This is the real thing. Disable further interrupts and stop
|
||||
* the timer
|
||||
*/
|
||||
|
||||
(void)pwm_stop((FAR struct pwm_lowerhalf_s *)priv);
|
||||
|
||||
/* Then perform the callback into the upper half driver */
|
||||
|
||||
pwm_expired(priv->handle);
|
||||
|
||||
priv->handle = NULL;
|
||||
priv->endseq = false;
|
||||
}
|
||||
|
||||
pwm_expired(priv->handle);
|
||||
priv->handle = NULL;
|
||||
return OK;
|
||||
}
|
||||
#endif
|
||||
@ -1002,7 +1042,7 @@ static int pwm_setup(FAR struct pwm_lowerhalf_s *dev)
|
||||
/* Configure the PWM output pin, but do not start the timer yet */
|
||||
|
||||
stm32_configgpio(priv->pincfg);
|
||||
pwm_dumpgpio(priv->pincfg, "PWM setup"); // REMOVE ME
|
||||
pwm_dumpgpio(priv->pincfg, "PWM setup");
|
||||
return OK;
|
||||
}
|
||||
|
||||
@ -1096,6 +1136,10 @@ static int pwm_start(FAR struct pwm_lowerhalf_s *dev,
|
||||
}
|
||||
}
|
||||
|
||||
/* Save the handle */
|
||||
|
||||
priv->handle = handle;
|
||||
|
||||
/* Start the time */
|
||||
|
||||
return pwm_timer(priv, info);
|
||||
|
@ -322,7 +322,7 @@ static int pwm_start(FAR struct pwm_upperhalf_s *upper, unsigned int oflags)
|
||||
* We do these things before starting the PWM to avoid race conditions.
|
||||
*/
|
||||
|
||||
upper->waiting = (upper->info.count > 0) && ((oflags & O_NONBLOCK) != 0);
|
||||
upper->waiting = (upper->info.count > 0) && ((oflags & O_NONBLOCK) == 0);
|
||||
upper->started = true;
|
||||
|
||||
/* Invoke the bottom half method to start the pulse train */
|
||||
@ -354,6 +354,7 @@ static int pwm_start(FAR struct pwm_upperhalf_s *upper, unsigned int oflags)
|
||||
{
|
||||
/* Looks like we won't be waiting after all */
|
||||
|
||||
pwmvdbg("start failed: %d\n", ret);
|
||||
upper->started = false;
|
||||
upper->waiting = false;
|
||||
}
|
||||
@ -649,6 +650,8 @@ void pwm_expired(FAR void *handle)
|
||||
{
|
||||
FAR struct pwm_upperhalf_s *upper = (FAR struct pwm_upperhalf_s *)handle;
|
||||
|
||||
pwmllvdbg("started: %d waiting: %d\n", upper->started, upper->waiting);
|
||||
|
||||
/* Make sure that the PWM is started */
|
||||
|
||||
if (upper->started)
|
||||
|
Loading…
Reference in New Issue
Block a user