summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2012-01-11 18:44:12 +0000
committerpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2012-01-11 18:44:12 +0000
commit61059ae472f03c43613bb05c3789636aa5061e2f (patch)
treeb56578519143faf7a8e8a9ae20ebe31073732736
parent856fd40ce792b3607d46fa316ca7ce6a60ecdd4f (diff)
downloadnuttx-61059ae472f03c43613bb05c3789636aa5061e2f.tar.gz
nuttx-61059ae472f03c43613bb05c3789636aa5061e2f.tar.bz2
nuttx-61059ae472f03c43613bb05c3789636aa5061e2f.zip
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
-rw-r--r--nuttx/arch/arm/src/stm32/stm32_pwm.c68
-rw-r--r--nuttx/drivers/pwm.c5
2 files changed, 60 insertions, 13 deletions
diff --git a/nuttx/arch/arm/src/stm32/stm32_pwm.c b/nuttx/arch/arm/src/stm32/stm32_pwm.c
index dea64c7d9..c9b97db28 100644
--- a/nuttx/arch/arm/src/stm32/stm32_pwm.c
+++ b/nuttx/arch/arm/src/stm32/stm32_pwm.c
@@ -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);
diff --git a/nuttx/drivers/pwm.c b/nuttx/drivers/pwm.c
index 6a613f3b5..adfe0e2e8 100644
--- a/nuttx/drivers/pwm.c
+++ b/nuttx/drivers/pwm.c
@@ -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)