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:
patacongo
2012-01-11 18:44:12 +00:00
parent 67631ddea7
commit 397edddc5b
2 changed files with 60 additions and 13 deletions
+56 -12
View File
@@ -145,8 +145,7 @@ struct stm32_pwmtimer_s
uint8_t timtype; /* See the TIMTYPE_* definitions */ uint8_t timtype; /* See the TIMTYPE_* definitions */
#ifdef CONFIG_PWM_PULSECOUNT #ifdef CONFIG_PWM_PULSECOUNT
uint8_t irq; /* Timer update IRQ */ uint8_t irq; /* Timer update IRQ */
#else bool endseq; /* True: Next interrupt is the end */
uint8_t unused;
#endif #endif
uint32_t base; /* The base address of the timer */ uint32_t base; /* The base address of the timer */
uint32_t pincfg; /* Output pin configuration */ 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); 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", pwmvdbg("TIM%d channel: %d frequency: %d duty: %08x\n",
priv->timid, priv->channel, info->frequency, info->duty); 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 */ /* 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 #ifdef CONFIG_PWM_PULSECOUNT
if (info->count > 0) 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); pwm_putreg(priv, STM32_GTIM_DIER_OFFSET, ATIM_DIER_UIE);
priv->endseq = false;
/* Enable the timer */ /* 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)) #if defined(CONFIG_PWM_PULSECOUNT) && (defined(CONFIG_STM32_TIM1_PWM) || defined(CONFIG_STM32_TIM8_PWM))
static int pwm_interrupt(struct stm32_pwmtimer_s *priv) static int pwm_interrupt(struct stm32_pwmtimer_s *priv)
{ {
uint16_t regval;
/* Verify that this is an update interrupt. Nothing else is expected. */ /* Verify that this is an update interrupt. Nothing else is expected. */
pwmllvdbg("Update interrupt: %04x\n", pwm_getreg(priv, STM32_GTIM_SR_OFFSET)); regval = pwm_getreg(priv, STM32_ATIM_SR_OFFSET);
DEBUGASSERT((pwm_getreg(priv, STM32_GTIM_SR_OFFSET) & ATIM_SR_UIF) != 0); 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; return OK;
} }
#endif #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 */ /* Configure the PWM output pin, but do not start the timer yet */
stm32_configgpio(priv->pincfg); stm32_configgpio(priv->pincfg);
pwm_dumpgpio(priv->pincfg, "PWM setup"); // REMOVE ME pwm_dumpgpio(priv->pincfg, "PWM setup");
return OK; 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 */ /* Start the time */
return pwm_timer(priv, info); return pwm_timer(priv, info);
+4 -1
View File
@@ -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. * 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; upper->started = true;
/* Invoke the bottom half method to start the pulse train */ /* 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 */ /* Looks like we won't be waiting after all */
pwmvdbg("start failed: %d\n", ret);
upper->started = false; upper->started = false;
upper->waiting = 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; 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 */ /* Make sure that the PWM is started */
if (upper->started) if (upper->started)