summaryrefslogtreecommitdiff
path: root/nuttx/arch/arm/src/stm32/stm32_pwm.c
diff options
context:
space:
mode:
authorpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2012-01-16 18:17:58 +0000
committerpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2012-01-16 18:17:58 +0000
commit331c8f43eca498006f83c7a6e3b80ade63982b62 (patch)
tree89d51bbc28dda626e48bd59303f109856e756b46 /nuttx/arch/arm/src/stm32/stm32_pwm.c
parent4dbb08ffcbfc8645114ecb72c8c2e37c86791aef (diff)
downloadpx4-nuttx-331c8f43eca498006f83c7a6e3b80ade63982b62.tar.gz
px4-nuttx-331c8f43eca498006f83c7a6e3b80ade63982b62.tar.bz2
px4-nuttx-331c8f43eca498006f83c7a6e3b80ade63982b62.zip
Fixe the STM32 repetition counter. Setting of the repitition count was out of phase by 1
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@4304 42af7a65-404d-4744-a932-0658087f49c3
Diffstat (limited to 'nuttx/arch/arm/src/stm32/stm32_pwm.c')
-rw-r--r--nuttx/arch/arm/src/stm32/stm32_pwm.c77
1 files changed, 53 insertions, 24 deletions
diff --git a/nuttx/arch/arm/src/stm32/stm32_pwm.c b/nuttx/arch/arm/src/stm32/stm32_pwm.c
index 68d935aa2..54b15529c 100644
--- a/nuttx/arch/arm/src/stm32/stm32_pwm.c
+++ b/nuttx/arch/arm/src/stm32/stm32_pwm.c
@@ -141,7 +141,8 @@ struct stm32_pwmtimer_s
uint8_t timtype; /* See the TIMTYPE_* definitions */
#ifdef CONFIG_PWM_PULSECOUNT
uint8_t irq; /* Timer update IRQ */
- uint8_t rcr; /* Previous pulse count */
+ 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 */
#endif
uint32_t base; /* The base address of the timer */
@@ -694,8 +695,31 @@ static int pwm_timer(FAR struct stm32_pwmtimer_s *priv,
#ifdef CONFIG_PWM_PULSECOUNT
if (info->count > 0)
{
- uint16_t count = (uint16_t)pwm_pulsecount(info->count) - 1;
- pwm_putreg(priv, STM32_ATIM_RCR_OFFSET, count);
+ /* Save the remining count and the number of counts that will have
+ * elapsed on the first interrupt.
+ */
+
+ /* If the first interrupt occurs at the end end of the first
+ * repition count, then the count will be the same as the RCR
+ * value.
+ */
+
+ priv->prev = pwm_pulsecount(info->count);
+ pwm_putreg(priv, STM32_ATIM_RCR_OFFSET, (uint16_t)priv->prev - 1);
+
+ /* Generate an update event to reload the prescaler. This should
+ * preload the RCR into active repetition counter.
+ */
+
+ pwm_putreg(priv, STM32_GTIM_EGR_OFFSET, ATIM_EGR_UG);
+
+ /* Now set the value of the RCR that will be loaded on the next
+ * update event.
+ */
+
+ priv->count = info->count;
+ priv->curr = pwm_pulsecount(info->count - priv->prev);
+ pwm_putreg(priv, STM32_ATIM_RCR_OFFSET, (uint16_t)priv->curr - 1);
}
/* Otherwise, just clear the repitition counter */
@@ -703,14 +727,22 @@ static int pwm_timer(FAR struct stm32_pwmtimer_s *priv,
else
#endif
{
+ /* Set the repeition counter to zero */
+
pwm_putreg(priv, STM32_ATIM_RCR_OFFSET, 0);
+
+ /* Generate an update event to reload the prescaler */
+
+ pwm_putreg(priv, STM32_GTIM_EGR_OFFSET, ATIM_EGR_UG);
}
}
+ else
#endif
+ {
+ /* Generate an update event to reload the prescaler (all timers) */
- /* Generate an update event to reload the prescaler (all timers) */
-
- pwm_putreg(priv, STM32_GTIM_EGR_OFFSET, ATIM_EGR_UG);
+ pwm_putreg(priv, STM32_GTIM_EGR_OFFSET, ATIM_EGR_UG);
+ }
/* Handle channel specific setup */
@@ -894,14 +926,6 @@ static int pwm_timer(FAR struct stm32_pwmtimer_s *priv,
pwm_putreg(priv, STM32_GTIM_SR_OFFSET, 0);
pwm_putreg(priv, STM32_GTIM_DIER_OFFSET, ATIM_DIER_UIE);
- /* Save the remining count and the number of counts that will have
- * elapsed on the first interrupt. Since the first interrupt will
- * occur immediately, that count will be zero.
- */
-
- priv->rcr = 0;
- priv->count =info->count;
-
/* Enable the timer */
cr1 |= GTIM_CR1_CEN;
@@ -956,7 +980,7 @@ static int pwm_interrupt(struct stm32_pwmtimer_s *priv)
* since the last interrupt.
*/
- if (priv->count <= priv->rcr)
+ if (priv->count <= priv->prev)
{
/* We are finished. Turn off the mast output to stop the output as
* quickly as possible.
@@ -976,27 +1000,32 @@ static int pwm_interrupt(struct stm32_pwmtimer_s *priv)
priv->handle = NULL;
priv->count = 0;
- priv->rcr = 0;
+ priv->prev = 0;
+ priv->curr = 0;
}
else
{
/* Decrement the count of pulses remaining using the number of
- * pulses generated since the last interrupt. This will be the
- * same as the current RCR value *except* on the first interrupt.
+ * pulses generated since the last interrupt.
*/
- priv->count -= priv->rcr;
+ priv->count -= priv->prev;
- /* Calculate and set the next RCR value */
+ /* Set up the next RCR. Set 'prev' to the value of the RCR that
+ * was loaded when the update occurred (just before this interrupt)
+ * and set 'curr' to the current value of the RCR register (which
+ * will bet loaded on the next update event).
+ */
- priv->rcr = pwm_pulsecount(priv->count);
- pwm_putreg(priv, STM32_ATIM_RCR_OFFSET, (uint16_t)priv->rcr - 1);
+ priv->prev = priv->curr;
+ priv->curr = pwm_pulsecount(priv->count - priv->prev);
+ pwm_putreg(priv, STM32_ATIM_RCR_OFFSET, (uint16_t)priv->curr - 1);
}
/* Now all of the time critical stuff is done so we can do some debug output */
- pwmllvdbg("Update interrupt SR: %04x RCR: %d count: %d\n",
- regval, priv->rcr, priv->count);
+ pwmllvdbg("Update interrupt SR: %04x prev: %d curr: %d count: %d\n",
+ regval, priv->prev, priv->curr, priv->count);
return OK;
}