summaryrefslogtreecommitdiff
path: root/nuttx
diff options
context:
space:
mode:
authorpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2012-01-16 15:43:01 +0000
committerpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2012-01-16 15:43:01 +0000
commit44d017bbaf9aff6d3f7b5dfd2042a71a6414380c (patch)
tree9331162b22b699068d1bdfe8a637c1b7993e5962 /nuttx
parent61f7bc640f2f2ef42df04ca47d2806401cf97469 (diff)
downloadpx4-nuttx-44d017bbaf9aff6d3f7b5dfd2042a71a6414380c.tar.gz
px4-nuttx-44d017bbaf9aff6d3f7b5dfd2042a71a6414380c.tar.bz2
px4-nuttx-44d017bbaf9aff6d3f7b5dfd2042a71a6414380c.zip
Increase range of pulse count in PWM driver
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@4302 42af7a65-404d-4744-a932-0658087f49c3
Diffstat (limited to 'nuttx')
-rw-r--r--nuttx/ChangeLog3
-rw-r--r--nuttx/Documentation/NuttXCommercial.html2
-rw-r--r--nuttx/arch/arm/src/stm32/chip/stm32_tim.h2
-rw-r--r--nuttx/arch/arm/src/stm32/stm32_pwm.c132
-rwxr-xr-xnuttx/configs/stm3240g-eval/nsh/defconfig4
5 files changed, 101 insertions, 42 deletions
diff --git a/nuttx/ChangeLog b/nuttx/ChangeLog
index 3252793fc..c74f78a12 100644
--- a/nuttx/ChangeLog
+++ b/nuttx/ChangeLog
@@ -2367,3 +2367,6 @@
point numbers (Contributed by Mikhail Bychek)
6.15 2012-xx-xx Gregory Nutt <gnutt@nuttx.org>
+
+ * arch/arm/src/stm32/stm32_pwm.c: Pulse count was limited to 128; now is
+ (essentially) unlimited.
diff --git a/nuttx/Documentation/NuttXCommercial.html b/nuttx/Documentation/NuttXCommercial.html
index 92ac4190d..ea60fda2e 100644
--- a/nuttx/Documentation/NuttXCommercial.html
+++ b/nuttx/Documentation/NuttXCommercial.html
@@ -53,7 +53,7 @@
<li><a href="http://www.2g-eng.com" target="top">2G Engineering</a></li>
<li><a href="http://isotel.eu/Home/" target="top">ISOTEL Research</a></li>
<li><a href="http://www.dspworks.in/" target="top">DSPWorks</a></li>
- <li><a href="http://www.nx-engineering.com/products.html" target="top">NXWidgets</a></li>
+ <li><a href="http://www.nx-engineering.com/products/" target="top">NXWidgets</a></li>
</tr>
<tr>
<td colspan="2" align="center" valign="top">
diff --git a/nuttx/arch/arm/src/stm32/chip/stm32_tim.h b/nuttx/arch/arm/src/stm32/chip/stm32_tim.h
index 104eba3de..8822589c0 100644
--- a/nuttx/arch/arm/src/stm32/chip/stm32_tim.h
+++ b/nuttx/arch/arm/src/stm32/chip/stm32_tim.h
@@ -667,6 +667,8 @@
#define ATIM_RCR_REP_SHIFT (0) /* Bits 7-0: Repetition Counter Value */
#define ATIM_RCR_REP_MASK (0xff << ATIM_RCR_REP_SHIFT)
+#define ATIM_RCR_REP_MAX 128
+
/* Break and dead-time register */
#define ATIM_BDTR_DTG_SHIFT (0) /* Bits 7:0 [7:0]: Dead-Time Generator set-up */
diff --git a/nuttx/arch/arm/src/stm32/stm32_pwm.c b/nuttx/arch/arm/src/stm32/stm32_pwm.c
index c9b97db28..68d935aa2 100644
--- a/nuttx/arch/arm/src/stm32/stm32_pwm.c
+++ b/nuttx/arch/arm/src/stm32/stm32_pwm.c
@@ -101,10 +101,6 @@
#define TIMTYPE_TIM13 TIMTYPE_COUNTUP16
#define TIMTYPE_TIM14 TIMTYPE_COUNTUP16
-/* The maximum repetition count is 128 */
-
-#define PWM_MAX_COUNT 128
-
/* Debug ********************************************************************/
/* Non-standard debug that may be enabled just for testing PWM */
@@ -145,7 +141,8 @@ struct stm32_pwmtimer_s
uint8_t timtype; /* See the TIMTYPE_* definitions */
#ifdef CONFIG_PWM_PULSECOUNT
uint8_t irq; /* Timer update IRQ */
- bool endseq; /* True: Next interrupt is the end */
+ uint8_t rcr; /* Previous pulse count */
+ uint32_t count; /* Remaining pluse count */
#endif
uint32_t base; /* The base address of the timer */
uint32_t pincfg; /* Output pin configuration */
@@ -183,6 +180,7 @@ static int pwm_tim1interrupt(int irq, void *context);
#if defined(CONFIG_STM32_TIM8_PWM)
static int pwm_tim8interrupt(int irq, void *context);
#endif
+static uint8_t pwm_pulsecount(uint32_t count);
#endif
/* PWM driver methods */
@@ -555,14 +553,12 @@ static int pwm_timer(FAR struct stm32_pwmtimer_s *priv,
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);
+#endif
DEBUGASSERT(info->frequency > 0 && info->duty > 0 &&
info->duty < uitoub16(100));
-#endif
/* Disable all interrupts and DMA requests, clear all pending status */
@@ -698,7 +694,8 @@ static int pwm_timer(FAR struct stm32_pwmtimer_s *priv,
#ifdef CONFIG_PWM_PULSECOUNT
if (info->count > 0)
{
- pwm_putreg(priv, STM32_ATIM_RCR_OFFSET, info->count - 1);
+ uint16_t count = (uint16_t)pwm_pulsecount(info->count) - 1;
+ pwm_putreg(priv, STM32_ATIM_RCR_OFFSET, count);
}
/* Otherwise, just clear the repitition counter */
@@ -896,7 +893,14 @@ 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);
- priv->endseq = false;
+
+ /* 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 */
@@ -948,28 +952,22 @@ static int pwm_interrupt(struct stm32_pwmtimer_s *priv)
pwm_putreg(priv, STM32_ATIM_SR_OFFSET, regval & ~ATIM_SR_UIF);
- /* 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.
+ /* Calculate the new count by subtracting the number of pulses
+ * since the last interrupt.
*/
- if (!priv->endseq)
- {
- /* The next interrupt will be the one we care about. */
-
- priv->endseq = true;
- }
- else
+ if (priv->count <= priv->rcr)
{
- /* OK.. This is the real thing. Disable further interrupts and stop
- * the timer
+ /* We are finished. Turn off the mast output to stop the output as
+ * quickly as possible.
*/
+ regval = pwm_getreg(priv, STM32_ATIM_BDTR_OFFSET);
+ regval &= ~ATIM_BDTR_MOE;
+ pwm_putreg(priv, STM32_ATIM_BDTR_OFFSET, regval);
+
+ /* Disable first interrtups, stop and reset the timer */
+
(void)pwm_stop((FAR struct pwm_lowerhalf_s *)priv);
/* Then perform the callback into the upper half driver */
@@ -977,9 +975,29 @@ static int pwm_interrupt(struct stm32_pwmtimer_s *priv)
pwm_expired(priv->handle);
priv->handle = NULL;
- priv->endseq = false;
+ priv->count = 0;
+ priv->rcr = 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.
+ */
+
+ priv->count -= priv->rcr;
+
+ /* Calculate and set the next RCR value */
+
+ priv->rcr = pwm_pulsecount(priv->count);
+ pwm_putreg(priv, STM32_ATIM_RCR_OFFSET, (uint16_t)priv->rcr - 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);
+
return OK;
}
#endif
@@ -1013,6 +1031,53 @@ static int pwm_tim8interrupt(int irq, void *context)
#endif
/****************************************************************************
+ * Name: pwm_pulsecount
+ *
+ * Description:
+ * Pick an optimal pulse count to program the RCR.
+ *
+ * Input parameters:
+ * count - The total count remaining
+ *
+ * Returned Value:
+ * The recommended pulse count
+ *
+ ****************************************************************************/
+
+#if defined(CONFIG_PWM_PULSECOUNT) && (defined(CONFIG_STM32_TIM1_PWM) || defined(CONFIG_STM32_TIM8_PWM))
+static uint8_t pwm_pulsecount(uint32_t count)
+{
+ /* The the remaining pulse count is less than or equal to the maximum, the
+ * just return the count.
+ */
+
+ if (count <= ATIM_RCR_REP_MAX)
+ {
+ return count;
+ }
+
+ /* Otherwise, we have to be careful. We do not want a small number of
+ * counts at the end because we might have trouble responding fast enough.
+ * If the remaining count is less than 150% of the maximum, then return
+ * half of the maximum. In this case the final sequence will be between 64
+ * and 128.
+ */
+
+ else if (count < (3 * ATIM_RCR_REP_MAX / 2))
+ {
+ return (ATIM_RCR_REP_MAX + 1) >> 1;
+ }
+
+ /* Otherwise, return the maximum. The final count will be 64 or more */
+
+ else
+ {
+ return ATIM_RCR_REP_MAX;
+ }
+}
+#endif
+
+/****************************************************************************
* Name: pwm_setup
*
* Description:
@@ -1123,17 +1188,6 @@ static int pwm_start(FAR struct pwm_lowerhalf_s *dev,
priv->timid, info->count);
return -EPERM;
}
-
- /* The maximum repetition count supported by the advanced timers
- * is PWM_MAX_COUNT.
- */
-
- if (info->count > PWM_MAX_COUNT)
- {
- pwmdbg("ERROR: TIM%d count=%d exceeds maximum repeition count: %d\n",
- priv->timid, info->count, PWM_MAX_COUNT);
- return -EDOM;
- }
}
/* Save the handle */
diff --git a/nuttx/configs/stm3240g-eval/nsh/defconfig b/nuttx/configs/stm3240g-eval/nsh/defconfig
index f2eb8a3b6..22bd97110 100755
--- a/nuttx/configs/stm3240g-eval/nsh/defconfig
+++ b/nuttx/configs/stm3240g-eval/nsh/defconfig
@@ -350,9 +350,9 @@ CONFIG_STM32_ADC3_SAMPLE_FREQUENCY=100
#
# The STM3240G-Eval has no real on-board PWM devices, but the board can be configured to output
# a pulse train using several options (see board.h). Here the default setup is for TIM8, CH4.
-# Don't forget to enable CONFIG_STM32_TIM8.
+# Don't forget to enable CONFIG_PWM and CONFIG_STM32_TIM8.
#
-CONFIG_PWM=y
+CONFIG_PWM=n
CONFIG_PWM_PULSECOUNT=y
CONFIG_STM32_TIM8_PWM=y
CONFIG_STM32_TIM8_CHANNEL=4