diff --git a/arch/arm/src/stm32/Make.defs b/arch/arm/src/stm32/Make.defs
index 402a3253308b490ea7ccaae51552066aad12afed..d877516ab80b7167168c1564479a10ca9d4ef6ad 100644
--- a/arch/arm/src/stm32/Make.defs
+++ b/arch/arm/src/stm32/Make.defs
@@ -83,6 +83,10 @@ ifeq ($(CONFIG_DAC),y)
 CHIP_CSRCS	+= stm32_dac.c
 endif
 
+ifeq ($(CONFIG_PWM),y)
+CHIP_CSRCS	+= stm32_pwm.c
+endif
+
 ifeq ($(CONFIG_DEBUG),y)
 CHIP_CSRCS	+= stm32_dumpgpio.c
 endif
diff --git a/arch/arm/src/stm32/stm32_adc.c b/arch/arm/src/stm32/stm32_adc.c
index b8eac533a497c32685ab0daa03a401e6c6e0b374..64384295264cf2319318d9e3dc002e6014555c71 100644
--- a/arch/arm/src/stm32/stm32_adc.c
+++ b/arch/arm/src/stm32/stm32_adc.c
@@ -83,7 +83,131 @@
 
 #if defined(CONFIG_STM32_ADC1) || defined(CONFIG_STM32_ADC2) || defined(CONFIG_STM32_ADC3)
 
-/* ADC interrupts */
+/* Timer configuration:  If a timer trigger is specified, then get information
+ * about the timer.
+ */
+
+#if defined(CONFIG_STM32_TIM1_ADC1)
+#    define ADC1_HAVE_TIMER           1
+#    define ADC1_EXTSEL_VALUE         ADC_CR2_EXTSEL_T1CC1
+#    define ADC1_TIMER_BASE           STM32_TIM1_BASE
+#    define ADC1_TIMER_PCLK_FREQUENCY STM32_PCLK2_FREQUENCY
+#elif defined(CONFIG_STM32_TIM2_ADC1)
+#    define ADC1_HAVE_TIMER           1
+#    define ADC1_EXTSEL_VALUE         ADC_CR2_EXTSEL_T2CC2
+#    define ADC1_TIMER_BASE           STM32_TIM2_BASE
+#    define ADC1_TIMER_PCLK_FREQUENCY STM32_PCLK1_FREQUENCY
+#elif defined(CONFIG_STM32_TIM3_ADC1)
+#    define ADC1_HAVE_TIMER           1
+#    define ADC1_EXTSEL_VALUE         ADC_CR2_EXTSEL_T3CC1
+#    define ADC1_TIMER_BASE           STM32_TIM3_BASE
+#    define ADC1_TIMER_PCLK_FREQUENCY STM32_PCLK1_FREQUENCY
+#elif defined(CONFIG_STM32_TIM4_ADC1)
+#    define ADC1_HAVE_TIMER           1
+#    define ADC1_EXTSEL_VALUE         ADC_CR2_EXTSEL_T4CC4
+#    define ADC1_TIMER_BASE           STM32_TIM4_BASE
+#    define ADC1_TIMER_PCLK_FREQUENCY STM32_PCLK1_FREQUENCY
+#elif defined(CONFIG_STM32_TIM5_ADC1)
+#    define ADC1_HAVE_TIMER           1
+#    define ADC1_EXTSEL_VALUE         ADC_CR2_EXTSEL_T5CC1
+#    define ADC1_TIMER_BASE           STM32_TIM5_BASE
+#    define ADC1_TIMER_PCLK_FREQUENCY STM32_PCLK1_FREQUENCY
+#elif defined(CONFIG_STM32_TIM8_ADC1)
+#    define ADC1_HAVE_TIMER           1
+#    define ADC1_EXTSEL_VALUE         ??? which ????
+#    define ADC1_TIMER_BASE           STM32_TIM8_BASE
+#    define ADC1_TIMER_PCLK_FREQUENCY STM32_PCLK2_FREQUENCY
+#else
+#    undef  ADC1_HAVE_TIMER
+#endif
+
+#if defined(ADC1_HAVE_TIMER) && !defined(CONFIG_STM32_ADC1_SAMPLE_FREQUENCY)
+#  error "CONFIG_STM32_ADC1_SAMPLE_FREQUENCY not defined"
+#endif
+
+#if defined(CONFIG_STM32_TIM1_ADC2)
+#    define ADC2_HAVE_TIMER           1
+#    define ADC2_EXTSEL_VALUE         ADC_CR2_EXTSEL_T1CC1
+#    define ADC2_TIMER_BASE           STM32_TIM1_BASE
+#    define ADC2_TIMER_PCLK_FREQUENCY STM32_PCLK2_FREQUENCY
+#elif defined(CONFIG_STM32_TIM2_ADC2)
+#    define ADC2_HAVE_TIMER           1
+#    define ADC2_EXTSEL_VALUE         ADC_CR2_EXTSEL_T2CC2
+#    define ADC2_TIMER_BASE           STM32_TIM2_BASE
+#    define ADC2_TIMER_PCLK_FREQUENCY STM32_PCLK1_FREQUENCY
+#elif defined(CONFIG_STM32_TIM3_ADC2)
+#    define ADC2_HAVE_TIMER           1
+#    define ADC2_EXTSEL_VALUE         ADC_CR2_EXTSEL_T3CC1
+#    define ADC2_TIMER_BASE           STM32_TIM3_BASE
+#    define ADC2_TIMER_PCLK_FREQUENCY STM32_PCLK1_FREQUENCY
+#elif defined(CONFIG_STM32_TIM4_ADC2)
+#    define ADC2_HAVE_TIMER           1
+#    define ADC2_EXTSEL_VALUE         ADC_CR2_EXTSEL_T4CC4
+#    define ADC2_TIMER_BASE           STM32_TIM4_BASE
+#    define ADC2_TIMER_PCLK_FREQUENCY STM32_PCLK1_FREQUENCY
+#elif defined(CONFIG_STM32_TIM5_ADC2)
+#    define ADC2_HAVE_TIMER           1
+#    define ADC2_EXTSEL_VALUE         ADC_CR2_EXTSEL_T5CC1
+#    define ADC2_TIMER_BASE           STM32_TIM5_BASE
+#    define ADC2_TIMER_PCLK_FREQUENCY STM32_PCLK1_FREQUENCY
+#elif defined(CONFIG_STM32_TIM8_ADC2)
+#    define ADC2_HAVE_TIMER           1
+#    define ADC2_EXTSEL_VALUE         ADC_CR2_EXTSEL_T8CC1
+#    define ADC2_TIMER_BASE           STM32_TIM8_BASE
+#    define ADC2_TIMER_PCLK_FREQUENCY STM32_PCLK2_FREQUENCY
+#else
+#    undef  ADC2_HAVE_TIMER
+#endif
+
+#if defined(ADC2_HAVE_TIMER) && !defined(CONFIG_STM32_ADC2_SAMPLE_FREQUENCY)
+#  error "CONFIG_STM32_ADC2_SAMPLE_FREQUENCY not defined"
+#endif
+
+#if defined(CONFIG_STM32_TIM1_ADC3)
+#    define ADC3_HAVE_TIMER           1
+#    define ADC3_EXTSEL_VALUE         ADC_CR2_EXTSEL_T1CC1
+#    define ADC3_TIMER_BASE           STM32_TIM1_BASE
+#    define ADC3_TIMER_PCLK_FREQUENCY STM32_PCLK2_FREQUENCY
+#elif defined(CONFIG_STM32_TIM2_ADC3)
+#    define ADC3_HAVE_TIMER           1
+#    define ADC3_EXTSEL_VALUE         ADC_CR2_EXTSEL_T2CC2
+#    define ADC3_TIMER_BASE           STM32_TIM2_BASE
+#    define ADC3_TIMER_PCLK_FREQUENCY STM32_PCLK1_FREQUENCY
+#elif defined(CONFIG_STM32_TIM3_ADC3)
+#    define ADC3_HAVE_TIMER           1
+#    define ADC3_EXTSEL_VALUE         ADC_CR2_EXTSEL_T3CC1
+#    define ADC3_TIMER_BASE           STM32_TIM3_BASE
+#    define ADC3_TIMER_PCLK_FREQUENCY STM32_PCLK1_FREQUENCY
+#elif defined(CONFIG_STM32_TIM4_ADC3)
+#    define ADC3_HAVE_TIMER           1
+#    define ADC3_EXTSEL_VALUE         ADC_CR2_EXTSEL_T4CC4
+#    define ADC3_TIMER_BASE           STM32_TIM4_BASE
+#    define ADC3_TIMER_PCLK_FREQUENCY STM32_PCLK1_FREQUENCY
+#elif defined(CONFIG_STM32_TIM5_ADC3)
+#    define ADC3_HAVE_TIMER           1
+#    define ADC3_EXTSEL_VALUE         ADC_CR2_EXTSEL_T5CC1
+#    define ADC3_TIMER_BASE           STM32_TIM5_BASE
+#    define ADC3_TIMER_PCLK_FREQUENCY STM32_PCLK1_FREQUENCY
+#elif defined(CONFIG_STM32_TIM8_ADC3)
+#    define ADC3_HAVE_TIMER           1
+#    define ADC3_EXTSEL_VALUE         ADC_CR2_EXTSEL_T8CC1
+#    define ADC3_TIMER_BASE           STM32_TIM8_BASE
+#    define ADC3_TIMER_PCLK_FREQUENCY STM32_PCLK2_FREQUENCY
+#else
+#    undef  ADC3_HAVE_TIMER
+#endif
+
+#if defined(ADC3_HAVE_TIMER) && !defined(CONFIG_STM32_ADC3_SAMPLE_FREQUENCY)
+#  error "CONFIG_STM32_ADC3_SAMPLE_FREQUENCY not defined"
+#endif
+
+#if defined(ADC1_HAVE_TIMER) || defined(ADC2_HAVE_TIMER) || defined(ADC3_HAVE_TIMER)
+#  define ADC_HAVE_TIMER 1
+#else
+#  undef ADC_HAVE_TIMER
+#endif
+
+/* ADC interrupts ***********************************************************/
 
 #ifdef CONFIG_STM32_STM32F10XX
 #  define ADC_SR_ALLINTS (ADC_SR_AWD | ADC_SR_EOC | ADC_SR_JEOC)
@@ -97,7 +221,24 @@
 #  define ADC_CR1_ALLINTS (ADC_CR1_AWDIE | ADC_CR1_EOCIE | ADC_CR1_JEOCIE | ADC_CR1_OVRIE)
 #endif
 
-/* The maximum number of samples */
+/* Timer Setup **************************************************************/
+/* Calculate timer divider values based upon ADCn_TIMER_PCLK_FREQUENCY and
+ * CONFIG_STM32_ADCn_SAMPLE_FREQUENCY.
+ */
+
+#ifdef ADC1_HAVE_TIMER
+#  warning "Missing Logic"
+#endif
+
+#ifdef ADC2_HAVE_TIMER
+#  warning "Missing Logic"
+#endif
+
+#ifdef ADC3_HAVE_TIMER
+#  warning "Missing Logic"
+#endif
+
+/* The maximum number of channels that can be sampled */
 
 #define ADC_MAX_SAMPLES 16
 
@@ -115,6 +256,11 @@ struct stm32_dev_s
   uint8_t  current;   /* Current ADC channel being converted */
   xcpt_t   isr;       /* Interrupt handler for this ADC block */
   uint32_t base;      /* Base address of registers unique to this ADC block */
+#ifdef ADC_HAVE_TIMER
+  uint32_t tbase;     /* Base address of timer used by this ADC block */
+  uint32_t extsel;    /* EXTSEL value used by this ADC block */
+  uint32_t pclck;     /* The PCLK frequency that drivers this timer */
+#endif
 
   uint8_t  chanlist[ADC_MAX_SAMPLES];
 };
@@ -149,7 +295,12 @@ static int  adc_setup(FAR struct adc_dev_s *dev);
 static void adc_shutdown(FAR struct adc_dev_s *dev);
 static void adc_rxint(FAR struct adc_dev_s *dev, bool enable);
 static int  adc_ioctl(FAR struct adc_dev_s *dev, int cmd, unsigned long arg);
-static void adc_enable(FAR struct adc_dev_s *dev, bool enable);
+static void adc_enable(FAR struct stm32_dev_s *priv, bool enable);
+
+#ifdef ADC_HAVE_TIMER
+static int  adc_timinit(FAR struct stm32_dev_s *priv);
+#endif
+static void adc_startconv(FAR struct stm32_dev_s *priv, bool enable);
 
 /****************************************************************************
  * Private Data
@@ -180,6 +331,11 @@ static struct stm32_dev_s g_adcpriv1 =
 #endif
   .intf        = 1,
   .base        = STM32_ADC1_BASE,
+#ifdef ADC1_HAVE_TIMER
+  .tbase       = ADC1_TIMER_BASE,
+  .extsel      = ADC1_EXTSEL_VALUE,
+  .pclck       = ADC1_TIMER_PCLK_FREQUENCY,
+#endif
 };
 
 static struct adc_dev_s g_adcdev1 =
@@ -203,6 +359,11 @@ static struct stm32_dev_s g_adcpriv2 =
 #endif
   .intf        = 2;
   .base        = STM32_ADC2_BASE,
+#ifdef ADC2_HAVE_TIMER
+  .tbase       = ADC2_TIMER_BASE,
+  .extsel      = ADC2_EXTSEL_VALUE,
+  .pclck       = ADC2_TIMER_PCLK_FREQUENCY,
+#endif
 };
 
 static struct adc_dev_s g_adcdev2 =
@@ -226,6 +387,11 @@ static struct stm32_dev_s g_adcpriv3 =
 #endif
   .intf        = 3;
   .base        = STM32_ADC3_BASE,
+#ifdef ADC3_HAVE_TIMER
+  .tbase       = ADC3_TIMER_BASE,
+  .extsel      = ADC3_EXTSEL_VALUE,
+  .pclck       = ADC3_TIMER_PCLK_FREQUENCY,
+#endif
 };
 
 static struct adc_dev_s g_adcdev3 =
@@ -277,6 +443,116 @@ static void adc_putreg(struct stm32_dev_s *priv, int offset, uint32_t value)
   putreg32(value, priv->base + offset);
 }
 
+/****************************************************************************
+ * Name: tim_getreg
+ *
+ * Description:
+ *   Read the value of an ADC timer register.
+ *
+ * Input Parameters:
+ *   priv - A reference to the ADC block status
+ *   offset - The offset to the register to read
+ *
+ * Returned Value:
+ *   The current contents of the specified register
+ *
+ ****************************************************************************/
+
+#ifdef HAVE_DMA
+static uint32_t tim_getreg(struct stm32_dev_s *priv, int offset)
+{
+  return getreg32(priv->tbase + offset);
+}
+#endif
+
+/****************************************************************************
+ * Name: tim_putreg
+ *
+ * Description:
+ *   Read the value of an ADC timer register.
+ *
+ * Input Parameters:
+ *   priv - A reference to the ADC block status
+ *   offset - The offset to the register to read
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void tim_putreg(struct stm32_dev_s *priv, int offset, uint32_t value)
+{
+  putreg32(value, priv->tbase + offset);
+}
+#endif
+
+/****************************************************************************
+ * Name: adc_timinit
+ *
+ * Description:
+ *   Initialize the timer that drivers the ADC sampling for this channel using
+ *   the pre-calculated timer divider definitions.
+ *
+ * Input Parameters:
+ *   chan - A reference to the DAC channel state data
+ *
+ * Returned Value:
+ *   Zero on success; a negated errno value on failure.
+ *
+ ****************************************************************************/
+
+#ifdef ADC_HAVE_TIMER
+static int adc_timinit(FAR struct stm32_dev_s *priv)
+{
+  /* Configure the time base: Timer period, prescaler, clock division,
+   * counter mode (up).
+   */
+#warning "Missing Logic"
+
+  /* Selection EXTSEL selection: update */
+#warning "Missing Logic"
+  
+  /* Enable the counter */
+#warning "Missing Logic"
+}
+#endif
+
+/****************************************************************************
+ * Name: adc_startconv
+ *
+ * Description:
+ *   Start (or stop) the ADC conversion process
+ *
+ * Input Parameters:
+ *   priv - A reference to the ADC block status
+ *   enable - True: Start conversion
+ *
+ * Returned Value:
+ *
+ ****************************************************************************/
+
+static void adc_startconv(struct stm32_dev_s *priv, bool enable)
+{
+  uint32_t regval;
+
+  avdbg("enable: %d\n", enable);
+
+  regval  = adc_getreg(priv, STM32_ADC_CR2_OFFSET);
+  if (enable)
+    {
+      /* Start conversion of regular channles */
+
+      regval |= ADC_CR2_SWSTART;
+    }
+  else
+    {
+      /* Disable the conversion of regular channels */
+
+      regval &= ~ADC_CR2_SWSTART;
+    }
+  regval  = adc_getreg(priv, STM32_ADC_CR2_OFFSET);
+}
+
 /****************************************************************************
  * Name: adc_rccreset
  *
@@ -363,9 +639,8 @@ static void adc_rccreset(struct stm32_dev_s *priv, bool reset)
  *
  *******************************************************************************/
 
-static void adc_enable(FAR struct adc_dev_s *dev, bool enable)
+static void adc_enable(FAR struct stm32_dev_s *priv, bool enable)
 {
-  FAR struct stm32_dev_s *priv = (FAR struct stm32_dev_s *)dev->ad_priv;
   uint32_t regval;
 
   avdbg("enable: %d\n", enable);
@@ -380,6 +655,10 @@ static void adc_enable(FAR struct adc_dev_s *dev, bool enable)
       regval &= ~ADC_CR2_ADON;
     }
   adc_putreg(priv, STM32_ADC_CR2_OFFSET, regval);
+
+  /* Enable or disable conversions */
+
+//adc_startconv(priv, enable);
 }
 
 /****************************************************************************
@@ -473,38 +752,47 @@ static void adc_reset(FAR struct adc_dev_s *dev)
   regval |= ADC_CR1_AWDEN;
 
   /* AWDIE: Analog watchdog interrupt enable */
-  
+
   regval |= ADC_CR1_AWDIE;
-  
+
   /* EOCIE: Interrupt enable for EOC */
   
   regval |= ADC_CR1_EOCIE;
-  
-  adc_putreg(priv, STM32_ADC_CR1_OFFSET, regval);
 
-#warning "Only one channel is able to be guarded for the watchdog"
-#warning "The channel is configured in the ADC_CR1_AWDCH [4:0]"
-#warning "We have to decide if we need this watchdog "
+  adc_putreg(priv, STM32_ADC_CR1_OFFSET, regval);
 
   /* ADC1 CR2 Configuration */
-  
-  /* Set the ADON bit to wake up the ADC from power down mode */
 
   regval  = adc_getreg(priv, STM32_ADC_CR2_OFFSET);
-  regval |= ADC_CR2_ADON;
-    
+
   /* Clear CONT, ALIGN (Right = 0) and EXTTRIG bits */
 
   regval &= ~ADC_CR2_CONT;
   regval &= ~ADC_CR2_ALIGN;
   regval &= ~ADC_CR2_EXTSEL_MASK;
+
+  /* EXTTRIG: External Trigger Conversion mode for regular channels enable*/
+  
+  //regval |= ADC_CR2_EXTTRIG;
   
-  /* SWSTART: Start conversion of regular channels */
+  /* EXTSEL[2:0]: External event select for regular group
+   * These bits select the external event used to trigger the start
+   * of conversion of a regular group: 
+   *    000: Timer 1 CC1 event
+   *    001: Timer 1 CC2 event
+   *    010: Timer 1 CC3 event
+   *    011: Timer 2 CC2 event
+   *    100: Timer 3 TRGO event
+   *    101: Timer 4 CC4 event
+   *    110: EXTI line11/TIM8_TRGO event (TIM8_TRGO is available only in high-density devices)
+   *    111: SWSTART
+   */
+
+  /* Select trigger when SWSTART is set */
+  //regval |= ADC_CR2_EXTSEL_SWSTART;
 
-#warning "Don't you want to finish setting up the registers before starting the conversion?"
-  regval |= ADC_CR2_SWSTART;
   adc_putreg(priv, STM32_ADC_CR2_OFFSET, regval);
-  
+
   /* Configuration of the channel conversions */
 
   regval = adc_getreg(priv, STM32_ADC_SQR3_OFFSET) & ADC_SQR3_RESERVED;
@@ -513,7 +801,7 @@ static void adc_reset(FAR struct adc_dev_s *dev)
       regval |= (uint32_t)priv->chanlist[i] << offset;
     }
   adc_putreg(priv, STM32_ADC_SQR3_OFFSET, regval);
-  
+
   regval = adc_getreg(priv, STM32_ADC_SQR2_OFFSET) & ADC_SQR2_RESERVED;
   for (i = 6, offset = 0; i < priv->nchannels && i < 12; i++, offset += 5)
     {
@@ -537,15 +825,21 @@ static void adc_reset(FAR struct adc_dev_s *dev)
   /* Set the channel index of the first conversion */
 
   priv->current = 0;
-  irqrestore(flags);
 
-  avdbg("CR1: 0x%08x  CR2: 0x%08x\n",
+  /* Set ADON to wake up the ADC from Power Down state. */
+  
+  adc_enable(priv, true);
+  adc_startconv(priv, true);
+  irqrestore(flags);
+  
+  avdbg("SR: %08x CR1: 0x%08x  CR2: 0x%08x\n",
+        adc_getreg(priv, STM32_ADC_SR_OFFSET),
         adc_getreg(priv, STM32_ADC_CR1_OFFSET),
-        adc_getreg(priv, STM32_ADC_CR2_OFFSET))
+        adc_getreg(priv, STM32_ADC_CR2_OFFSET));
   avdbg("SQR1: 0x%08x  SQR2: 0x%08x SQR3: 0x%08x\n",
         adc_getreg(priv, STM32_ADC_SQR1_OFFSET),
         adc_getreg(priv, STM32_ADC_SQR2_OFFSET),
-        adc_getreg(priv, STM32_ADC_SQR3_OFFSET))
+        adc_getreg(priv, STM32_ADC_SQR3_OFFSET));
 }
 
 /****************************************************************************
@@ -632,9 +926,9 @@ static void adc_rxint(FAR struct adc_dev_s *dev, bool enable)
   regval = adc_getreg(priv, STM32_ADC_CR1_OFFSET);
   if (enable)
     {
-      /* Enable the end-of-conversion ADC interrupt */
+      /* Enable the end-of-conversion ADC and analog watchdog interrupts */
 
-      regval |= ADC_CR1_EOCIE;
+      regval |= (ADC_CR1_EOCIE | ADC_CR1_AWDIE);
     }
   else
     {
@@ -659,7 +953,7 @@ static void adc_rxint(FAR struct adc_dev_s *dev, bool enable)
 
 static int  adc_ioctl(FAR struct adc_dev_s *dev, int cmd, unsigned long arg)
 {
-  avdbg("intf: %d\n", priv->intf);
+  avdbg("Entry\n");
   return -ENOTTY;
 }
 
@@ -680,7 +974,6 @@ static int adc_interrupt(FAR struct adc_dev_s *dev)
   FAR struct stm32_dev_s *priv = (FAR struct stm32_dev_s *)dev->ad_priv;
   uint32_t adcsr;
   int32_t  value;
-  uint8_t  ch;
 
   avdbg("intf: %d\n", priv->intf);
 
@@ -700,6 +993,10 @@ static int adc_interrupt(FAR struct adc_dev_s *dev)
 
       value  = adc_getreg(priv, STM32_ADC_DR_OFFSET);
       value &= ADC_DR_DATA_MASK;
+#ifdef ADC_DUALMODE
+#error "not yet implemented"
+      value &= ADC_DR_ADC2DATA_MASK;
+#endif
     
       /* Give the ADC data to the ADC dirver.  adc_receive accepts 3 parameters:
        *
@@ -708,18 +1005,21 @@ static int adc_interrupt(FAR struct adc_dev_s *dev)
        * 3) The third is the converted data for the channel.
        */
 
-      adc_receive(dev, priv->current, value);
+      avdbg("Calling adc_receive(priv, ch=%d, value=%d)\n",
+            priv->chanlist[priv->current], value);
 
+      adc_receive(dev, priv->chanlist[priv->current], value);
+  
       /* Set the channel number of the next channel that will complete conversion */
 
       if (++priv->current >= priv->nchannels)
         {
-           /* Restart the conversion sequence from the beginning */
+          /* Restart the conversion sequence from the beginning */
 #warning "Missing logic"
-
-           /* Reset the index to the first channel to be converted */
-
-           priv->current = 0;
+         
+          /* Reset the index to the first channel to be converted */
+        
+          priv->current = 0;
         }
     }
 
@@ -744,7 +1044,7 @@ static int adc12_interrupt(int irq, void *context)
   uint32_t regval;
   uint32_t pending;
 
-  avdbg("irq: %d\n");
+  avdbg("irq: %d\n", irq);
 
   /* Check for pending ADC1 interrupts */
 
@@ -793,7 +1093,7 @@ static int adc3_interrupt(int irq, void *context)
   uint32_t regval;
   uint32_t pending;
 
-  avdbg("irq: %d\n");
+  avdbg("irq: %d\n", irq);
 
   /* Check for pending ADC3 interrupts */
 
@@ -828,7 +1128,7 @@ static int adc123_interrupt(int irq, void *context)
   uint32_t regval;
   uint32_t pending;
 
-  avdbg("irq: %d\n");
+  avdbg("irq: %d\n", irq);
 
   /* Check for pending ADC1 interrupts */
 
diff --git a/arch/arm/src/stm32/stm32_adc.h b/arch/arm/src/stm32/stm32_adc.h
index eb5926f288af2773021f8127444302a24770e2c2..ce778c5d24cf37464619b2181ad811bdfe0df3a3 100644
--- a/arch/arm/src/stm32/stm32_adc.h
+++ b/arch/arm/src/stm32/stm32_adc.h
@@ -47,6 +47,104 @@
 
 #include <nuttx/analog/adc.h>
 
+/************************************************************************************
+ * Pre-processor Definitions
+ ************************************************************************************/
+/* Configuration ********************************************************************/
+/* Timer devices may be used for different purposes.  One special purpose is to
+ * control periodic ADC sampling.  If CONFIG_STM32_TIMn is defined then 
+ * CONFIG_STM32_TIMn_ADC must also be defined to indicate that timer "n" is intended
+ * to be used for that purpose.
+ */
+
+/* For the STM32 F1 line, timers 1-4 may be used.  For STM32 F4 line, timers 1-5 and
+ * 8 may be used.
+ */
+
+#ifndef CONFIG_STM32_TIM1
+#  undef CONFIG_STM32_TIM1_ADC
+#  undef CONFIG_STM32_TIM1_ADC1
+#  undef CONFIG_STM32_TIM1_ADC2
+#  undef CONFIG_STM32_TIM1_ADC3
+#endif
+#ifndef CONFIG_STM32_TIM2
+#  undef CONFIG_STM32_TIM2_ADC
+#  undef CONFIG_STM32_TIM2_ADC1
+#  undef CONFIG_STM32_TIM2_ADC2
+#  undef CONFIG_STM32_TIM2_ADC3
+#endif
+#ifndef CONFIG_STM32_TIM3
+#  undef CONFIG_STM32_TIM3_ADC
+#  undef CONFIG_STM32_TIM3_ADC1
+#  undef CONFIG_STM32_TIM3_ADC2
+#  undef CONFIG_STM32_TIM3_ADC3
+#endif
+#ifndef CONFIG_STM32_TIM4
+#  undef CONFIG_STM32_TIM4_ADC
+#  undef CONFIG_STM32_TIM4_ADC1
+#  undef CONFIG_STM32_TIM4_ADC2
+#  undef CONFIG_STM32_TIM4_ADC3
+#endif
+
+#if defined(CONFIG_STM32_STM32F40XX)
+#  ifndef CONFIG_STM32_TIM5
+#    undef CONFIG_STM32_TIM5_ADC
+#    undef CONFIG_STM32_TIM5_ADC1
+#    undef CONFIG_STM32_TIM5_ADC2
+#    undef CONFIG_STM32_TIM5_ADC3
+#  endif
+#  ifndef CONFIG_STM32_TIM8
+#    undef CONFIG_STM32_TIM8_ADC
+#    undef CONFIG_STM32_TIM8_ADC1
+#    undef CONFIG_STM32_TIM8_ADC2
+#    undef CONFIG_STM32_TIM8_ADC3
+#  endif
+#else
+#  undef CONFIG_STM32_TIM5_ADC
+#  undef CONFIG_STM32_TIM5_ADC1
+#  undef CONFIG_STM32_TIM5_ADC2
+#  undef CONFIG_STM32_TIM5_ADC3
+#  undef CONFIG_STM32_TIM8_ADC
+#  undef CONFIG_STM32_TIM8_ADC1
+#  undef CONFIG_STM32_TIM8_ADC2
+#  undef CONFIG_STM32_TIM8_ADC3
+#endif
+
+/* Timers 6, 7, and 10-14 are not used with the ADC by any supported family */
+
+#undef CONFIG_STM32_TIM6_ADC
+#undef CONFIG_STM32_TIM6_ADC1
+#undef CONFIG_STM32_TIM6_ADC2
+#undef CONFIG_STM32_TIM6_ADC3
+#undef CONFIG_STM32_TIM7_ADC
+#undef CONFIG_STM32_TIM7_ADC1
+#undef CONFIG_STM32_TIM7_ADC2
+#undef CONFIG_STM32_TIM7_ADC3
+#undef CONFIG_STM32_TIM9_ADC
+#undef CONFIG_STM32_TIM9_ADC1
+#undef CONFIG_STM32_TIM9_ADC2
+#undef CONFIG_STM32_TIM9_ADC3
+#undef CONFIG_STM32_TIM10_ADC
+#undef CONFIG_STM32_TIM10_ADC1
+#undef CONFIG_STM32_TIM10_ADC2
+#undef CONFIG_STM32_TIM10_ADC3
+#undef CONFIG_STM32_TIM11_ADC
+#undef CONFIG_STM32_TIM11_ADC1
+#undef CONFIG_STM32_TIM11_ADC2
+#undef CONFIG_STM32_TIM11_ADC3
+#undef CONFIG_STM32_TIM12_ADC
+#undef CONFIG_STM32_TIM12_ADC1
+#undef CONFIG_STM32_TIM12_ADC2
+#undef CONFIG_STM32_TIM12_ADC3
+#undef CONFIG_STM32_TIM13_ADC
+#undef CONFIG_STM32_TIM13_ADC1
+#undef CONFIG_STM32_TIM13_ADC2
+#undef CONFIG_STM32_TIM13_ADC3
+#undef CONFIG_STM32_TIM14_ADC
+#undef CONFIG_STM32_TIM14_ADC1
+#undef CONFIG_STM32_TIM14_ADC2
+#undef CONFIG_STM32_TIM14_ADC3
+
 /************************************************************************************
  * Public Function Prototypes
  ************************************************************************************/
diff --git a/arch/arm/src/stm32/stm32_dac.c b/arch/arm/src/stm32/stm32_dac.c
index 8d152c57f74de447018b16fb6977932cd8c5aeb9..ad767371fdb3ca55f02f49c22b7d018d112325ef 100644
--- a/arch/arm/src/stm32/stm32_dac.c
+++ b/arch/arm/src/stm32/stm32_dac.c
@@ -172,49 +172,49 @@
 
 #ifdef CONFIG_STM32_DAC1_DMA
 #  if CONFIG_STM32_DAC1_TIMER == 6
-#    ifndef CONFIG_STM32_TIM6
-#      error "CONFIG_STM32_TIM6 required for DAC1"
+#    ifndef CONFIG_STM32_TIM6_DAC
+#      error "CONFIG_STM32_TIM6_DAC required for DAC1"
 #    endif
 #    define DAC1_TSEL_VALUE           DAC_CR_TSEL_TIM6
 #    define DAC1_TIMER_BASE           STM32_TIM6_BASE
 #    define DAC1_TIMER_PCLK_FREQUENCY STM32_PCLK1_FREQUENCY
 #  elif CONFIG_STM32_DAC1_TIMER == 3 && defined(CONFIG_STM32_CONNECTIVITYLINE)
-#    ifndef CONFIG_STM32_TIM3
-#      error "CONFIG_STM32_TIM3 required for DAC1"
+#    ifndef CONFIG_STM32_TIM3_DAC
+#      error "CONFIG_STM32_TIM3_DAC required for DAC1"
 #    endif
 #    define DAC1_TSEL_VALUE           DAC_CR_TSEL_TIM3
 #    define DAC1_TIMER_BASE           STM32_TIM3_BASE
 #    define DAC1_TIMER_PCLK_FREQUENCY STM32_PCLK1_FREQUENCY
 #  elif CONFIG_STM32_DAC1_TIMER == 8 && !defined(CONFIG_STM32_CONNECTIVITYLINE)
-#    ifndef CONFIG_STM32_TIM8
-#      error "CONFIG_STM32_TIM8 required for DAC1"
+#    ifndef CONFIG_STM32_TIM8_DAC
+#      error "CONFIG_STM32_TIM8_DAC required for DAC1"
 #    endif
 #    define DAC1_TSEL_VALUE           DAC_CR_TSEL_TIM8
 #    define DAC1_TIMER_BASE           STM32_TIM8_BASE
 #    define DAC1_TIMER_PCLK_FREQUENCY STM32_PCLK2_FREQUENCY
 #  elif CONFIG_STM32_DAC1_TIMER == 7
-#    ifndef CONFIG_STM32_TIM7
-#      error "CONFIG_STM32_TIM7 required for DAC1"
+#    ifndef CONFIG_STM32_TIM7_DAC
+#      error "CONFIG_STM32_TIM7_DAC required for DAC1"
 #    endif
 #    define DAC1_TSEL_VALUE DAC_CR_TSEL_TIM7
 #    define DAC1_TIMER_BASE STM32_TIM7_BASE
 #  elif CONFIG_STM32_DAC1_TIMER == 5
-#    ifndef CONFIG_STM32_TIM5
-#      error "CONFIG_STM32_TIM5 required for DAC1"
+#    ifndef CONFIG_STM32_TIM5_DAC
+#      error "CONFIG_STM32_TIM5_DAC required for DAC1"
 #    endif
 #    define DAC1_TSEL_VALUE           DAC_CR_TSEL_TIM5
 #    define DAC1_TIMER_BASE           STM32_TIM5_BASE
 #    define DAC1_TIMER_PCLK_FREQUENCY STM32_PCLK1_FREQUENCY
 #  elif CONFIG_STM32_DAC1_TIMER == 2
-#    ifndef CONFIG_STM32_TIM2
-#      error "CONFIG_STM32_TIM2 required for DAC1"
+#    ifndef CONFIG_STM32_TIM2_DAC
+#      error "CONFIG_STM32_TIM2_DAC required for DAC1"
 #    endif
 #    define DAC1_TSEL_VALUE           DAC_CR_TSEL_TIM2
 #    define DAC1_TIMER_BASE           STM32_TIM2_BASE
 #    define DAC1_TIMER_PCLK_FREQUENCY STM32_PCLK1_FREQUENCY
 #  elif CONFIG_STM32_DAC1_TIMER == 4
-#    ifndef CONFIG_STM32_TIM4
-#      error "CONFIG_STM32_TIM4 required for DAC1"
+#    ifndef CONFIG_STM32_TIM4_DAC
+#      error "CONFIG_STM32_TIM4_DAC required for DAC1"
 #    endif
 #    define DAC1_TSEL_VALUE           DAC_CR_TSEL_TIM4
 #    define DAC1_TIMER_BASE           STM32_TIM4_BASE
@@ -228,50 +228,50 @@
 
 #ifdef CONFIG_STM32_DAC2_DMA
 #  if CONFIG_STM32_DAC2_TIMER == 6
-#    ifndef CONFIG_STM32_TIM6
-#      error "CONFIG_STM32_TIM6 required for DAC2"
+#    ifndef CONFIG_STM32_TIM6_DAC
+#      error "CONFIG_STM32_TIM6_DAC required for DAC2"
 #    endif
 #    define DAC2_TSEL_VALUE           DAC_CR_TSEL_TIM6
 #    define DAC2_TIMER_BASE           STM32_TIM6_BASE
 #    define DAC2_TIMER_PCLK_FREQUENCY STM32_PCLK1_FREQUENCY
 #  elif CONFIG_STM32_DAC2_TIMER == 3 && defined(CONFIG_STM32_CONNECTIVITYLINE)
-#    ifndef CONFIG_STM32_TIM3
-#      error "CONFIG_STM32_TIM3 required for DAC2"
+#    ifndef CONFIG_STM32_TIM3_DAC
+#      error "CONFIG_STM32_TIM3_DAC required for DAC2"
 #    endif
 #    define DAC2_TSEL_VALUE           DAC_CR_TSEL_TIM3
 #    define DAC2_TIMER_BASE           STM32_TIM3_BASE
 #    define DAC2_TIMER_PCLK_FREQUENCY STM32_PCLK1_FREQUENCY
 #  elif CONFIG_STM32_DAC2_TIMER == 8 && !defined(CONFIG_STM32_CONNECTIVITYLINE)
-#    ifndef CONFIG_STM32_TIM8
-#      error "CONFIG_STM32_TIM8 required for DAC2"
+#    ifndef CONFIG_STM32_TIM8_DAC
+#      error "CONFIG_STM32_TIM8_DAC required for DAC2"
 #    endif
 #    define DAC2_TSEL_VALUE           DAC_CR_TSEL_TIM8
 #    define DAC2_TIMER_BASE           STM32_TIM8_BASE
 #    define DAC2_TIMER_PCLK_FREQUENCY STM32_PCLK2_FREQUENCY
 #  elif CONFIG_STM32_DAC2_TIMER == 7
-#    ifndef CONFIG_STM32_TIM7
-#      error "CONFIG_STM32_TIM7 required for DAC2"
+#    ifndef CONFIG_STM32_TIM7_DAC
+#      error "CONFIG_STM32_TIM7_DAC required for DAC2"
 #    endif
 #    define DAC2_TSEL_VALUE           DAC_CR_TSEL_TIM7
 #    define DAC2_TIMER_BASE           STM32_TIM7_BASE
 #    define DAC2_TIMER_PCLK_FREQUENCY STM32_PCLK1_FREQUENCY
 #  elif CONFIG_STM32_DAC2_TIMER == 5
-#    ifndef CONFIG_STM32_TIM5
-#      error "CONFIG_STM32_TIM5 required for DAC2"
+#    ifndef CONFIG_STM32_TIM5_DAC
+#      error "CONFIG_STM32_TIM5_DAC required for DAC2"
 #    endif
 #    define DAC2_TSEL_VALUE           DAC_CR_TSEL_TIM5
 #    define DAC2_TIMER_BASE           STM32_TIM5_BASE
 #    define DAC2_TIMER_PCLK_FREQUENCY STM32_PCLK1_FREQUENCY
 #  elif CONFIG_STM32_DAC2_TIMER == 2
-#    ifndef CONFIG_STM32_TIM2
-#      error "CONFIG_STM32_TIM2 required for DAC2"
+#    ifndef CONFIG_STM32_TIM2_DAC
+#      error "CONFIG_STM32_TIM2_DAC required for DAC2"
 #    endif
 #    define DAC2_TSEL_VALUE           DAC_CR_TSEL_TIM2
 #    define DAC2_TIMER_BASE           STM32_TIM2_BASE
 #    define DAC2_TIMER_PCLK_FREQUENCY STM32_PCLK1_FREQUENCY
 #  elif CONFIG_STM32_DAC2_TIMER == 4
-#    ifndef CONFIG_STM32_TIM4
-#      error "CONFIG_STM32_TIM4 required for DAC2"
+#    ifndef CONFIG_STM32_TIM4_DAC
+#      error "CONFIG_STM32_TIM4_DAC required for DAC2"
 #    endif
 #    define DAC2_TSEL_VALUE           DAC_CR_TSEL_TIM4
 #    define DAC2_TIMER_BASE           STM32_TIM4_BASE
diff --git a/arch/arm/src/stm32/stm32_dac.h b/arch/arm/src/stm32/stm32_dac.h
index 41d681ee76297b9a16710066e0b3990eb03c7a80..44404e6fb3244b981d1acb194a36a9e1479904d0 100644
--- a/arch/arm/src/stm32/stm32_dac.h
+++ b/arch/arm/src/stm32/stm32_dac.h
@@ -47,6 +47,59 @@
 
 #include <nuttx/analog/dac.h>
 
+/************************************************************************************
+ * Pre-processor definitions
+ ************************************************************************************/
+/* Configuration ********************************************************************/
+/* Timer devices may be used for different purposes.  One special purpose is to
+ * control periodic DAC outputs.  If CONFIG_STM32_TIMn is defined then 
+ * CONFIG_STM32_TIMn_DAC must also be defined to indicate that timer "n" is intended
+ * to be used for that purpose.
+ */
+
+#ifndef CONFIG_STM32_TIM1
+#  undef CONFIG_STM32_TIM1_DAC
+#endif
+#ifndef CONFIG_STM32_TIM2
+#  undef CONFIG_STM32_TIM2_DAC
+#endif
+#ifndef CONFIG_STM32_TIM3
+#  undef CONFIG_STM32_TIM3_DAC
+#endif
+#ifndef CONFIG_STM32_TIM4
+#  undef CONFIG_STM32_TIM4_DAC
+#endif
+#ifndef CONFIG_STM32_TIM5
+#  undef CONFIG_STM32_TIM5_DAC
+#endif
+#ifndef CONFIG_STM32_TIM6
+#  undef CONFIG_STM32_TIM6_DAC
+#endif
+#ifndef CONFIG_STM32_TIM7
+#  undef CONFIG_STM32_TIM7_DAC
+#endif
+#ifndef CONFIG_STM32_TIM8
+#  undef CONFIG_STM32_TIM8_DAC
+#endif
+#ifndef CONFIG_STM32_TIM9
+#  undef CONFIG_STM32_TIM9_DAC
+#endif
+#ifndef CONFIG_STM32_TIM10
+#  undef CONFIG_STM32_TIM10_DAC
+#endif
+#ifndef CONFIG_STM32_TIM11
+#  undef CONFIG_STM32_TIM11_DAC
+#endif
+#ifndef CONFIG_STM32_TIM12
+#  undef CONFIG_STM32_TIM12_DAC
+#endif
+#ifndef CONFIG_STM32_TIM13
+#  undef CONFIG_STM32_TIM13_DAC
+#endif
+#ifndef CONFIG_STM32_TIM14
+#  undef CONFIG_STM32_TIM14_DAC
+#endif
+
 /************************************************************************************
  * Public Function Prototypes
  ************************************************************************************/
diff --git a/arch/arm/src/stm32/stm32_pwm.c b/arch/arm/src/stm32/stm32_pwm.c
new file mode 100644
index 0000000000000000000000000000000000000000..8646bfcd76c30f4736f677d6c8a9d29de48894b6
--- /dev/null
+++ b/arch/arm/src/stm32/stm32_pwm.c
@@ -0,0 +1,459 @@
+/****************************************************************************
+ * arch/arm/src/stm32/stm32_pwm.c
+ *
+ *   Copyright (C) 2011 Gregory Nutt. All rights reserved.
+ *   Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ *    used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <stdint.h>
+#include <stdio.h>
+#include <assert.h>
+#include <debug.h>
+
+#include <nuttx/pwm.h>
+
+#include "up_internal.h"
+#include "up_arch.h"
+
+#include "chip.h"
+#include "stm32_pwm.h"
+#include "stm32_internal.h"
+
+/* This module then only compiles if there is at least one enabled timer
+ * intended for use with the PWM upper half driver.
+ */
+
+#if defined(CONFIG_STM32_TIM1_PWM)  || defined(CONFIG_STM32_TIM2_PWM)  || \
+    defined(CONFIG_STM32_TIM3_PWM)  || defined(CONFIG_STM32_TIM4_PWM)  || \
+    defined(CONFIG_STM32_TIM5_PWM)  || defined(CONFIG_STM32_TIM6_PWM)  || \
+    defined(CONFIG_STM32_TIM7_PWM)  || defined(CONFIG_STM32_TIM8_PWM)  || \
+    defined(CONFIG_STM32_TIM9_PWM)  || defined(CONFIG_STM32_TIM10_PWM) || \
+    defined(CONFIG_STM32_TIM11_PWM) || defined(CONFIG_STM32_TIM12_PWM) || \
+    defined(CONFIG_STM32_TIM13_PWM) || defined(CONFIG_STM32_TIM14_PWM)
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+/* This structure representst the state of one PWM timer */
+
+struct stm32_pwmtimer_s
+{
+  uint32_t base;  /* The base address of the timer */
+};
+
+/****************************************************************************
+ * Static Function Prototypes
+ ****************************************************************************/
+
+static int pwm_setup(FAR struct pwm_lowerhalf_s *dev);
+static int pwm_shutdown(FAR struct pwm_lowerhalf_s *dev);
+static int pwm_start(FAR struct pwm_lowerhalf_s *dev, FAR const struct pwm_info_s *info);
+static int pwm_stop(FAR struct pwm_lowerhalf_s *dev);
+static int pwm_pulsecount(FAR struct pwm_lowerhalf_s *dev, FAR pwm_count_t *count);
+static int pwm_ioctl(FAR struct pwm_lowerhalf_s *dev, int cmd, unsigned long arg);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+/* This is the list of lower half PWM driver methods used by the upper half driver */
+
+static const struct pwm_ops_s g_pwmops =
+{
+  .setup      = pwm_setup(FAR struct pwm_lowerhalf_s *dev);
+  .shutdown   = pwm_shutdown(FAR struct pwm_lowerhalf_s *dev);
+  .start      = pwm_start(FAR struct pwm_lowerhalf_s *dev, FAR const struct pwm_info_s *info);
+  .stop       = pwm_stop(FAR struct pwm_lowerhalf_s *dev);
+  .pulsecount = pwm_pulsecount(FAR struct pwm_lowerhalf_s *dev, FAR pwm_count_t *count);
+  .ioctl      = pwm_ioctl(FAR struct pwm_lowerhalf_s *dev, int cmd, unsigned long arg);
+};
+
+/* The following represent the state of each possible PWM driver */
+
+#ifdef CONFIG_STM32_TIM1_PWM
+static struct stm32_pwmtimer_s g_pwm1dev =
+{
+  .ops        = *g_pwmops;
+  .base       = STM32_TIM1_BASE;
+};
+#endif
+
+#ifdef CONFIG_STM32_TIM2_PWM
+static struct stm32_pwmtimer_s g_pwm2dev =
+{
+  .ops        = *g_pwmops;
+  .base       = STM32_TIM2_BASE;
+};
+#endif
+
+#ifdef CONFIG_STM32_TIM3_PWM
+static struct stm32_pwmtimer_s g_pwm3dev =
+{
+  .ops        = *g_pwmops;
+  .base       = STM32_TIM3_BASE;
+};
+#endif
+
+#ifdef CONFIG_STM32_TIM4_PWM
+static struct stm32_pwmtimer_s g_pwm4dev =
+{
+  .ops        = *g_pwmops;
+  .base       = STM32_TIM4_BASE;
+};
+#endif
+
+#ifdef CONFIG_STM32_TIM5_PWM
+static struct stm32_pwmtimer_s g_pwm5dev =
+{
+  .ops        = *g_pwmops;
+  .base       = STM32_TIM5_BASE;
+};
+#endif
+
+#ifdef CONFIG_STM32_TIM6_PWM
+static struct stm32_pwmtimer_s g_pwm6dev =
+{
+  .ops        = *g_pwmops;
+  .base       = STM32_TIM6_BASE;
+};
+#endif
+
+#ifdef CONFIG_STM32_TIM7_PWM
+static struct stm32_pwmtimer_s g_pwm7dev =
+{
+  .ops        = *g_pwmops;
+  .base       = STM32_TIM7_BASE;
+};
+#endif
+
+#ifdef CONFIG_STM32_TIM8_PWM
+static struct stm32_pwmtimer_s g_pwm8dev =
+{
+  .ops        = *g_pwmops;
+  .base       = STM32_TIM8_BASE;
+};
+#endif
+
+#ifdef CONFIG_STM32_TIM9_PWM
+static struct stm32_pwmtimer_s g_pwm9dev =
+{
+  .ops        = *g_pwmops;
+  .base       = STM32_TIM9_BASE;
+};
+#endif
+
+#ifdef CONFIG_STM32_TIM10_PWM
+static struct stm32_pwmtimer_s g_pwm10dev =
+{
+  .ops        = *g_pwmops;
+  .base       = STM32_TIM10_BASE;
+};
+#endif
+
+#ifdef CONFIG_STM32_TIM11_PWM
+static struct stm32_pwmtimer_s g_pwm11dev =
+{
+  .ops        = *g_pwmops;
+  .base       = STM32_TIM11_BASE;
+};
+#endif
+
+#ifdef CONFIG_STM32_TIM12_PWM
+static struct stm32_pwmtimer_s g_pwm12dev =
+{
+  .ops        = *g_pwmops;
+  .base       = STM32_TIM12_BASE;
+};
+#endif
+
+#ifdef CONFIG_STM32_TIM13_PWM
+static struct stm32_pwmtimer_s g_pwm13dev =
+{
+  .ops        = *g_pwmops;
+  .base       = STM32_TIM13_BASE;
+};
+#endif
+
+#ifdef CONFIG_STM32_TIM14_PWM
+static struct stm32_pwmtimer_s g_pwm14dev =
+{
+  .ops        = *g_pwmops;
+  .base       = STM32_TIM14_BASE;
+};
+#endif
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: pwm_setup
+ *
+ * Description:
+ *   This method is called when the driver is opened.  The lower half driver
+ *   should configure and initialize the device so that it is ready for use.
+ *   It should not, however, output pulses until the start method is called.
+ *
+ * Input parameters:
+ *   dev - A reference to the lower half PWM driver state structure
+ *
+ * Returned Value:
+ *   Zero on success; a negated errno value on failure
+ *
+ ****************************************************************************/
+
+static int pwm_setup(FAR struct pwm_lowerhalf_s *dev)
+{
+#warning "Missing logic"
+  return -ENOSYS;
+}
+
+/****************************************************************************
+ * Name: pwm_shutdown
+ *
+ * Description:
+ *   This method is called when the driver is closed.  The lower half driver
+ *   stop pulsed output, free any resources, disable the timer hardware, and
+ *   put the system into the lowest possible power usage state
+ *
+ * Input parameters:
+ *   dev - A reference to the lower half PWM driver state structure
+ *
+ * Returned Value:
+ *   Zero on success; a negated errno value on failure
+ *
+ ****************************************************************************/
+
+static int pwm_shutdown(FAR struct pwm_lowerhalf_s *dev)
+{
+#warning "Missing logic"
+  return -ENOSYS;
+}
+
+/****************************************************************************
+ * Name: pwm_start
+ *
+ * Description:
+ *   (Re-)initialize the timer resources and start the pulsed output
+ *
+ * Input parameters:
+ *   dev - A reference to the lower half PWM driver state structure
+ *   info - A reference to the characteristics of the pulsed output
+ *
+ * Returned Value:
+ *   Zero on success; a negated errno value on failure
+ *
+ ****************************************************************************/
+
+static int pwm_start(FAR struct pwm_lowerhalf_s *dev, FAR const struct pwm_info_s *info)
+{
+#warning "Missing logic"
+  return -ENOSYS;
+}
+
+/****************************************************************************
+ * Name: pwm_stop
+ *
+ * Description:
+ *   Stop the pulsed output and reset the timer resources
+ *
+ * Input parameters:
+ *   dev - A reference to the lower half PWM driver state structure
+ *
+ * Returned Value:
+ *   Zero on success; a negated errno value on failure
+ *
+ ****************************************************************************/
+
+static int pwm_stop(FAR struct pwm_lowerhalf_s *dev)
+{
+#warning "Missing logic"
+  return -ENOSYS;
+}
+
+/****************************************************************************
+ * Name: pwm_pulsecount
+ *
+ * Description:
+ *   Get the number of pulses generated
+ *
+ * Input parameters:
+ *   dev - A reference to the lower half PWM driver state structure
+ *   count - A pointer to the location to return the pulse count
+ *
+ * Returned Value:
+ *   Zero on success; a negated errno value on failure
+ *
+ ****************************************************************************/
+
+static int pwm_pulsecount(FAR struct pwm_lowerhalf_s *dev, FAR pwm_count_t *count)
+{
+#warning "Missing logic"
+  return -ENOSYS;
+}
+
+/****************************************************************************
+ * Name:
+ *
+ * Description:
+ *   Lower-half logic may support platform-specific ioctl commands
+ *
+ * Input parameters:
+ *   dev - A reference to the lower half PWM driver state structure
+ *   cmd - The ioctl command
+ *   arg - The argument accompanying the ioctl command
+ *
+ * Returned Value:
+ *   Zero on success; a negated errno value on failure
+ *
+ ****************************************************************************/
+
+static int pwm_ioctl(FAR struct pwm_lowerhalf_s *dev, int cmd, unsigned long arg)
+{
+  /* There are no platform-specific ioctl commands */
+
+  return -ENOTTY;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: stm32_pwminitialize
+ *
+ * Description:
+ *   Initialize one timer for use with the upper_level PWM driver.
+ *
+ * Input Parameters:
+ *   timer - A number identifying the timer use.  The number of valid timer
+ *     IDs varies with the STM32 MCU and MCU family but is somewhere in
+ *     the range of {1,..,14}.
+ *
+ * Returned Value:
+ *   On success, a pointer to the STM32 lower half PWM driver is returned.
+ *   NULL is returned on any failure.
+ *
+ ****************************************************************************/
+
+FAR struct pwm_lowerhalf_s *stm32_pwminitialize(int timer)
+{
+  FAR struct stm32_pwmtimer_s *lower;
+
+  switch (timer)
+    {
+#ifdef CONFIG_STM32_TIM1_PWM
+      case 1:
+        lower = &g_pwm1dev;
+        break;
+#endif
+#ifdef CONFIG_STM32_TIM2_PWM
+      case 2:
+        lower = &g_pwm2dev;
+        break;
+#endif
+#ifdef CONFIG_STM32_TIM3_PWM
+      case 3:
+        lower = &g_pwm3dev;
+        break;
+#endif
+#ifdef CONFIG_STM32_TIM4_PWM
+      case 4:
+        lower = &g_pwm4dev;
+        break;
+#endif
+#ifdef CONFIG_STM32_TIM5_PWM
+      case 5:
+        lower = &g_pwm5dev;
+        break;
+#endif
+#ifdef CONFIG_STM32_TIM6_PWM
+      case 6:
+        lower = &g_pwm6dev;
+        break;
+#endif
+#ifdef CONFIG_STM32_TIM7_PWM
+      case 7:
+        lower = &g_pwm7dev;
+        break;
+#endif
+#ifdef CONFIG_STM32_TIM8_PWM
+      case 8:
+        lower = &g_pwm8dev;
+        break;
+#endif
+#ifdef CONFIG_STM32_TIM9_PWM
+      case 9:
+        lower = &g_pwm9dev;
+        break;
+#endif
+#ifdef CONFIG_STM32_TIM10_PWM
+      case 10:
+        lower = &g_pwm10dev;
+        break;
+#endif
+#ifdef CONFIG_STM32_TIM11_PWM
+      case 11:
+        lower = &g_pwm11dev;
+        break;
+#endif
+#ifdef CONFIG_STM32_TIM12_PWM
+      case 12:
+        lower = &g_pwm12dev;
+        break;
+#endif
+#ifdef CONFIG_STM32_TIM13_PWM
+      case 13:
+        lower = &g_pwm13dev;
+        break;
+#endif
+#ifdef CONFIG_STM32_TIM14_PWM
+      case 14:
+        lower = &g_pwm14dev;
+        break;
+#endif
+      default:
+        return NULL;
+    }
+
+  return (FAR struct pwm_lowerhalf_s *)lower;
+}
+
+#endif /* CONFIG_STM32_TIMn_PWM, n = 1,...,14 */
diff --git a/arch/arm/src/stm32/stm32_pwm.h b/arch/arm/src/stm32/stm32_pwm.h
new file mode 100644
index 0000000000000000000000000000000000000000..6204cda210f7f624b2213b2a2ed89bd4ce14766d
--- /dev/null
+++ b/arch/arm/src/stm32/stm32_pwm.h
@@ -0,0 +1,154 @@
+/************************************************************************************
+ * arch/arm/src/stm32/stm32_pwm.h
+ *
+ *   Copyright (C) 2011 Gregory Nutt. All rights reserved.
+ *   Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ *    used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ************************************************************************************/
+
+#ifndef __ARCH_ARM_SRC_STM32_STM32_TIM_H
+#define __ARCH_ARM_SRC_STM32_STM32_TIM_H
+
+/* The STM32 does not have dedicated PWM hardware.  Rather, pulsed output control
+ * is a capabilitiy of the STM32 timers.  The logic in this file implements the
+ * lower half of the standard, NuttX PWM interface using the STM32 timers.  That
+ * interface is described in include/nuttx/pwm.h.
+ */
+
+/************************************************************************************
+ * Included Files
+ ************************************************************************************/
+
+#include <nuttx/config.h>
+
+#include "chip.h"
+#include "chip/stm32_tim.h"
+
+/************************************************************************************
+ * Pre-processor Definitions
+ ************************************************************************************/
+/* Configuration ********************************************************************/
+/* Timer devices may be used for different purposes.  One special purpose is
+ * to generate modulated outputs for such things as motor control.  If CONFIG_STM32_TIMn
+ * is defined then the CONFIG_STM32_TIMn_PWM must also be defined to indicate that
+ * timer "n" is intended to be used for pulsed output signal generation.
+ */
+
+#ifndef CONFIG_STM32_TIM1
+#  undef CONFIG_STM32_TIM1_PWM
+#endif
+#ifndef CONFIG_STM32_TIM2
+#  undef CONFIG_STM32_TIM2_PWM
+#endif
+#ifndef CONFIG_STM32_TIM3
+#  undef CONFIG_STM32_TIM3_PWM
+#endif
+#ifndef CONFIG_STM32_TIM4
+#  undef CONFIG_STM32_TIM4_PWM
+#endif
+#ifndef CONFIG_STM32_TIM5
+#  undef CONFIG_STM32_TIM5_PWM
+#endif
+#ifndef CONFIG_STM32_TIM6
+#  undef CONFIG_STM32_TIM6_PWM
+#endif
+#ifndef CONFIG_STM32_TIM7
+#  undef CONFIG_STM32_TIM7_PWM
+#endif
+#ifndef CONFIG_STM32_TIM8
+#  undef CONFIG_STM32_TIM8_PWM
+#endif
+#ifndef CONFIG_STM32_TIM9
+#  undef CONFIG_STM32_TIM9_PWM
+#endif
+#ifndef CONFIG_STM32_TIM10
+#  undef CONFIG_STM32_TIM10_PWM
+#endif
+#ifndef CONFIG_STM32_TIM11
+#  undef CONFIG_STM32_TIM11_PWM
+#endif
+#ifndef CONFIG_STM32_TIM12
+#  undef CONFIG_STM32_TIM12_PWM
+#endif
+#ifndef CONFIG_STM32_TIM13
+#  undef CONFIG_STM32_TIM13_PWM
+#endif
+#ifndef CONFIG_STM32_TIM14
+#  undef CONFIG_STM32_TIM14_PWM
+#endif
+
+/************************************************************************************
+ * Public Types
+ ************************************************************************************/
+
+/************************************************************************************
+ * Public Data
+ ************************************************************************************/
+
+#ifndef __ASSEMBLY__
+
+#undef EXTERN
+#if defined(__cplusplus)
+#define EXTERN extern "C"
+extern "C" {
+#else
+#define EXTERN extern
+#endif
+
+/************************************************************************************
+ * Public Functions
+ ************************************************************************************/
+
+/************************************************************************************
+ * Name: stm32_pwminitialize
+ *
+ * Description:
+ *   Initialize one timer for use with the upper_level PWM driver.
+ *
+ * Input Parameters:
+ *   timer - A number identifying the timer use.  The number of valid timer
+ *     IDs varies with the STM32 MCU and MCU family but is somewhere in
+ *     the range of {1,..,14}.
+ *
+ * Returned Value:
+ *   On success, a pointer to the STM32 lower half PWM driver is returned.
+ *   NULL is returned on any failure.
+ *
+ ************************************************************************************/
+
+EXTERN FAR struct pwm_lowerhalf_s *stm32_pwminitialize(int timer);
+
+#undef EXTERN
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* __ASSEMBLY__ */
+#endif /* __ARCH_ARM_SRC_STM32_STM32_TIM_H */
diff --git a/arch/arm/src/stm32/stm32_tim.c b/arch/arm/src/stm32/stm32_tim.c
index 5ce4951789193f37c914754da125247d221dc41b..e25f02df46a4a400aca5ef082267bf435cd93252 100644
--- a/arch/arm/src/stm32/stm32_tim.c
+++ b/arch/arm/src/stm32/stm32_tim.c
@@ -4,6 +4,11 @@
  *   Copyright (C) 2011 Uros Platise. All rights reserved.
  *   Author: Uros Platise <uros.platise@isotel.eu>
  *
+ * With modifications and updates by:
+ *
+ *   Copyright (C) 2011 Gregory Nutt. All rights reserved.
+ *   Author: Gregory Nutt <gnutt@nuttx.org>
+ *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
@@ -33,10 +38,9 @@
  *
  ************************************************************************************/
 
-/** \file
- *  \author Uros Platise
- *  \brief STM32 Basic, General and Advanced Timers
- */
+/************************************************************************************
+ * Included Files
+ ************************************************************************************/
 
 #include <nuttx/config.h>
 #include <nuttx/arch.h>
@@ -59,6 +63,74 @@
 #include "stm32_gpio.h"
 #include "stm32_tim.h"
 
+/************************************************************************************
+ * Private Types
+ ************************************************************************************/
+/* Configuration ********************************************************************/
+/* Timer devices may be used for different purposes.  Such special purposes include:
+ *
+ * - To generate modulated outputs for such things as motor control.  If CONFIG_STM32_TIMn
+ *   is defined then the CONFIG_STM32_TIMn_PWM may also be defined to indicate that
+ *   the timer is intended to be used for pulsed output modulation.
+ *
+ * - To control periodic ADC input sampling.  If CONFIG_STM32_TIMn is defined then 
+ *   CONFIG_STM32_TIMn_ADC may also be defined to indicate that timer "n" is intended
+ *   to be used for that purpose.
+ *
+ * - To control periodic DAC outputs.  If CONFIG_STM32_TIMn is defined then 
+ *   CONFIG_STM32_TIMn_DAC may also be defined to indicate that timer "n" is intended
+ *   to be used for that purpose.
+ *
+ * In any of these cases, the timer will not be used by this timer module.
+ */
+
+#if defined(CONFIG_STM32_TIM1_PWM) || defined (CONFIG_STM32_TIM1_ADC) || defined(CONFIG_STM32_TIM1_DAC)
+#  undef CONFIG_STM32_TIM1
+#endif
+#if defined(CONFIG_STM32_TIM2_PWM || defined (CONFIG_STM32_TIM2_ADC) || defined(CONFIG_STM32_TIM2_DAC)
+#  undef CONFIG_STM32_TIM2
+#endif
+#if defined(CONFIG_STM32_TIM3_PWM || defined (CONFIG_STM32_TIM3_ADC) || defined(CONFIG_STM32_TIM3_DAC)
+#  undef CONFIG_STM32_TIM3
+#endif
+#if defined(CONFIG_STM32_TIM4_PWM || defined (CONFIG_STM32_TIM4_ADC) || defined(CONFIG_STM32_TIM4_DAC)
+#  undef CONFIG_STM32_TIM4
+#endif
+#if defined(CONFIG_STM32_TIM5_PWM || defined (CONFIG_STM32_TIM5_ADC) || defined(CONFIG_STM32_TIM5_DAC)
+#  undef CONFIG_STM32_TIM5
+#endif
+#if defined(CONFIG_STM32_TIM6_PWM || defined (CONFIG_STM32_TIM6_ADC) || defined(CONFIG_STM32_TIM6_DAC)
+#  undef CONFIG_STM32_TIM6
+#endif
+#if defined(CONFIG_STM32_TIM7_PWM || defined (CONFIG_STM32_TIM7_ADC) || defined(CONFIG_STM32_TIM7_DAC)
+#  undef CONFIG_STM32_TIM7
+#endif
+#if defined(CONFIG_STM32_TIM8_PWM || defined (CONFIG_STM32_TIM8_ADC) || defined(CONFIG_STM32_TIM8_DAC)
+#  undef CONFIG_STM32_TIM8
+#endif
+#if defined(CONFIG_STM32_TIM9_PWM || defined (CONFIG_STM32_TIM9_ADC) || defined(CONFIG_STM32_TIM9_DAC)
+#  undef CONFIG_STM32_TIM9
+#endif
+#if defined(CONFIG_STM32_TIM10_PWM || defined (CONFIG_STM32_TIM10_ADC) || defined(CONFIG_STM32_TIM10_DAC)
+#  undef CONFIG_STM32_TIM10
+#endif
+#if defined(CONFIG_STM32_TIM11_PWM || defined (CONFIG_STM32_TIM11_ADC) || defined(CONFIG_STM32_TIM11_DAC)
+#  undef CONFIG_STM32_TIM11
+#endif
+#if defined(CONFIG_STM32_TIM12_PWM || defined (CONFIG_STM32_TIM12_ADC) || defined(CONFIG_STM32_TIM12_DAC)
+#  undef CONFIG_STM32_TIM12
+#endif
+#if defined(CONFIG_STM32_TIM13_PWM || defined (CONFIG_STM32_TIM13_ADC) || defined(CONFIG_STM32_TIM13_DAC)
+#  undef CONFIG_STM32_TIM13
+#endif
+#if defined(CONFIG_STM32_TIM14_PWM || defined (CONFIG_STM32_TIM14_ADC) || defined(CONFIG_STM32_TIM14_DAC)
+#  undef CONFIG_STM32_TIM14
+#endif
+
+/* This module then only compiles if there are enabled timers that are not intended for
+ * some other purpose.
+ */
+
 #if defined(CONFIG_STM32_TIM1) || defined(CONFIG_STM32_TIM2) || defined(CONFIG_STM32_TIM3) || \
     defined(CONFIG_STM32_TIM4) || defined(CONFIG_STM32_TIM5) || defined(CONFIG_STM32_TIM6) || \
     defined(CONFIG_STM32_TIM7) || defined(CONFIG_STM32_TIM8)
diff --git a/arch/arm/src/stm32/stm32_tim.h b/arch/arm/src/stm32/stm32_tim.h
index 1aa18328e281fc2c66b6222456908bb5e4873b79..8f12b187560233157979ebd13121aecc3c77471e 100644
--- a/arch/arm/src/stm32/stm32_tim.h
+++ b/arch/arm/src/stm32/stm32_tim.h
@@ -4,6 +4,11 @@
  *   Copyright (C) 2011 Uros Platise. All rights reserved.
  *   Author: Uros Platise <uros.platise@isotel.eu>
  *
+ * With modifications and updates by:
+ *
+ *   Copyright (C) 2011 Gregory Nutt. All rights reserved.
+ *   Author: Gregory Nutt <gnutt@nuttx.org>
+ *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
@@ -33,14 +38,13 @@
  *
  ************************************************************************************/
 
-/** \file
- *  \author Uros Platise
- *  \brief STM32 Timer Device Driver
- */
-
 #ifndef __ARCH_ARM_SRC_STM32_STM32_TIM_H
 #define __ARCH_ARM_SRC_STM32_STM32_TIM_H
 
+/************************************************************************************
+ * Included Files
+ ************************************************************************************/
+
 #include <nuttx/config.h>
 
 #include "chip.h"
@@ -49,6 +53,22 @@
 /************************************************************************************
  * Pre-processor Definitions
  ************************************************************************************/
+/* Helpers **************************************************************************/
+
+#define STM32_TIM_SETMODE(d,mode)       ((d)->ops->setmode(d,mode))
+#define STM32_TIM_SETCLOCK(d,freq)      ((d)->ops->setclock(d,freq))
+#define STM32_TIM_SETPERIOD(d,period)   ((d)->ops->setperiod(d,period))
+#define STM32_TIM_SETCHANNEL(d,ch,mode) ((d)->ops->setchannel(d,ch,mode))
+#define STM32_TIM_SETCOMPARE(d,ch,comp) ((d)->ops->setcompare(d,ch,comp))
+#define STM32_TIM_GETCAPTURE(d,ch)      ((d)->ops->getcapture(d,ch))
+#define STM32_TIM_SETISR(d,hnd,s)       ((d)->ops->setisr(d,hnd,s))
+#define STM32_TIM_ENABLEINT(d,s)        ((d)->ops->enableint(d,s))
+#define STM32_TIM_DISABLEINT(d,s)       ((d)->ops->disableint(d,s))
+#define STM32_TIM_ACKINT(d,s)           ((d)->ops->ackint(d,s))
+
+/************************************************************************************
+ * Public Types
+ ************************************************************************************/
 
 #ifndef __ASSEMBLY__
 
@@ -60,119 +80,107 @@ extern "C" {
 #define EXTERN extern
 #endif
 
-/************************************************************************************
- * Public Types
- ************************************************************************************/
+/* TIM Device Structure */
 
-/** TIM Device Structure
- */
-struct stm32_tim_dev_s {
-    struct stm32_tim_ops_s *ops;
+struct stm32_tim_dev_s
+{
+  struct stm32_tim_ops_s *ops;
 };
 
+/* TIM Modes of Operation */
 
-/** TIM Modes of Operation
- */
-typedef enum {
-    STM32_TIM_MODE_UNUSED       = -1,
+typedef enum
+{
+  STM32_TIM_MODE_UNUSED       = -1,
     
-    /* One of the following */
-    STM32_TIM_MODE_MASK         = 0x0310,
-    STM32_TIM_MODE_DISABLED     = 0x0000,
-    STM32_TIM_MODE_UP           = 0x0100,
-    STM32_TIM_MODE_DOWN         = 0x0110,
-    STM32_TIM_MODE_UPDOWN       = 0x0200,
-    STM32_TIM_MODE_PULSE        = 0x0300,
+  /* One of the following */
+
+  STM32_TIM_MODE_MASK         = 0x0310,
+  STM32_TIM_MODE_DISABLED     = 0x0000,
+  STM32_TIM_MODE_UP           = 0x0100,
+  STM32_TIM_MODE_DOWN         = 0x0110,
+  STM32_TIM_MODE_UPDOWN       = 0x0200,
+  STM32_TIM_MODE_PULSE        = 0x0300,
     
-    /* One of the following */
-    STM32_TIM_MODE_CK_INT       = 0x0000,
-//  STM32_TIM_MODE_CK_INT_TRIG  = 0x0400,
-//  STM32_TIM_MODE_CK_EXT       = 0x0800,
-//  STM32_TIM_MODE_CK_EXT_TRIG  = 0x0C00,
-
-    /* Clock sources, OR'ed with CK_EXT */
-//  STM32_TIM_MODE_CK_CHINVALID = 0x0000,
-//  STM32_TIM_MODE_CK_CH1       = 0x0001,
-//  STM32_TIM_MODE_CK_CH2       = 0x0002,
-//  STM32_TIM_MODE_CK_CH3       = 0x0003,
-//  STM32_TIM_MODE_CK_CH4       = 0x0004
+  /* One of the following */
+
+  STM32_TIM_MODE_CK_INT       = 0x0000,
+//STM32_TIM_MODE_CK_INT_TRIG  = 0x0400,
+//STM32_TIM_MODE_CK_EXT       = 0x0800,
+//STM32_TIM_MODE_CK_EXT_TRIG  = 0x0C00,
+
+  /* Clock sources, OR'ed with CK_EXT */
+
+//STM32_TIM_MODE_CK_CHINVALID = 0x0000,
+//STM32_TIM_MODE_CK_CH1       = 0x0001,
+//STM32_TIM_MODE_CK_CH2       = 0x0002,
+//STM32_TIM_MODE_CK_CH3       = 0x0003,
+//STM32_TIM_MODE_CK_CH4       = 0x0004
     
-    /* Todo: external trigger block */
+  /* Todo: external trigger block */
     
 } stm32_tim_mode_t;
 
+/* TIM Channel Modes */
 
-/** TIM Channel Modes
- */
-typedef enum {
-    STM32_TIM_CH_DISABLED       = 0x00,
+typedef enum
+{
+  STM32_TIM_CH_DISABLED       = 0x00,
     
-    /* Common configuration */
-    STM32_TIM_CH_POLARITY_POS   = 0x00,
-    STM32_TIM_CH_POLARITY_NEG   = 0x01,
+  /* Common configuration */
+
+  STM32_TIM_CH_POLARITY_POS   = 0x00,
+  STM32_TIM_CH_POLARITY_NEG   = 0x01,
     
-    /* MODES: */
-    STM32_TIM_CH_MODE_MASK      = 0x06,
+  /* MODES: */
+
+  STM32_TIM_CH_MODE_MASK      = 0x06,
     
-    /* Output Compare Modes */
-    STM32_TIM_CH_OUTPWM         = 0x04,     /** Enable standard PWM mode, active high when counter < compare */
-//  STM32_TIM_CH_OUTCOMPARE     = 0x06,
+  /* Output Compare Modes */
+
+  STM32_TIM_CH_OUTPWM         = 0x04,     /** Enable standard PWM mode, active high when counter < compare */
+//STM32_TIM_CH_OUTCOMPARE     = 0x06,
     
-    // TODO other modes ... as PWM capture, ENCODER and Hall Sensor
-//  STM32_TIM_CH_INCAPTURE      = 0x10,
-//  STM32_TIM_CH_INPWM          = 0x20
-//  STM32_TIM_CH_DRIVE_OC   -- open collector mode
+  // TODO other modes ... as PWM capture, ENCODER and Hall Sensor
+//STM32_TIM_CH_INCAPTURE      = 0x10,
+//STM32_TIM_CH_INPWM          = 0x20
+//STM32_TIM_CH_DRIVE_OC   -- open collector mode
     
 } stm32_tim_channel_t;
 
+/* TIM Operations */
 
-/** TIM Operations
- */
-struct stm32_tim_ops_s {
+struct stm32_tim_ops_s
+{
+  /* Basic Timers */
 
-    /* Basic Timers */
-    
-    int	    (*setmode)(FAR struct stm32_tim_dev_s *dev, stm32_tim_mode_t mode);
-    int     (*setclock)(FAR struct stm32_tim_dev_s *dev, uint32_t freq);
-    void    (*setperiod)(FAR struct stm32_tim_dev_s *dev, uint16_t period);
+  int  (*setmode)(FAR struct stm32_tim_dev_s *dev, stm32_tim_mode_t mode);
+  int  (*setclock)(FAR struct stm32_tim_dev_s *dev, uint32_t freq);
+  void (*setperiod)(FAR struct stm32_tim_dev_s *dev, uint16_t period);
     
-    /* General and Advanced Timers Adds */
+  /* General and Advanced Timers Adds */
     
-    int     (*setchannel)(FAR struct stm32_tim_dev_s *dev, uint8_t channel, stm32_tim_channel_t mode);
-    int	    (*setcompare)(FAR struct stm32_tim_dev_s *dev, uint8_t channel, uint16_t compare);
-    int	    (*getcapture)(FAR struct stm32_tim_dev_s *dev, uint8_t channel);
-    
-    int     (*setisr)(FAR struct stm32_tim_dev_s *dev, int (*handler)(int irq, void *context), int source);
-    void    (*enableint)(FAR struct stm32_tim_dev_s *dev, int source);
-    void    (*disableint)(FAR struct stm32_tim_dev_s *dev, int source);
-    void    (*ackint)(FAR struct stm32_tim_dev_s *dev, int source);
+  int  (*setchannel)(FAR struct stm32_tim_dev_s *dev, uint8_t channel, stm32_tim_channel_t mode);
+  int  (*setcompare)(FAR struct stm32_tim_dev_s *dev, uint8_t channel, uint16_t compare);
+  int  (*getcapture)(FAR struct stm32_tim_dev_s *dev, uint8_t channel);
+
+  int  (*setisr)(FAR struct stm32_tim_dev_s *dev, int (*handler)(int irq, void *context), int source);
+  void (*enableint)(FAR struct stm32_tim_dev_s *dev, int source);
+  void (*disableint)(FAR struct stm32_tim_dev_s *dev, int source);
+  void (*ackint)(FAR struct stm32_tim_dev_s *dev, int source);
 };
 
-
-/* Helpers */
-
-#define STM32_TIM_SETMODE(d,mode)       ((d)->ops->setmode(d,mode))
-#define STM32_TIM_SETCLOCK(d,freq)      ((d)->ops->setclock(d,freq))
-#define STM32_TIM_SETPERIOD(d,period)   ((d)->ops->setperiod(d,period))
-#define STM32_TIM_SETCHANNEL(d,ch,mode) ((d)->ops->setchannel(d,ch,mode))
-#define STM32_TIM_SETCOMPARE(d,ch,comp) ((d)->ops->setcompare(d,ch,comp))
-#define STM32_TIM_GETCAPTURE(d,ch)      ((d)->ops->getcapture(d,ch))
-#define STM32_TIM_SETISR(d,hnd,s)       ((d)->ops->setisr(d,hnd,s))
-#define STM32_TIM_ENABLEINT(d,s)        ((d)->ops->enableint(d,s))
-#define STM32_TIM_DISABLEINT(d,s)       ((d)->ops->disableint(d,s))
-#define STM32_TIM_ACKINT(d,s)           ((d)->ops->ackint(d,s))
-
-
 /************************************************************************************
  * Public Functions
  ************************************************************************************/
 
-/** Power-up timer and get its structure */
+/* Power-up timer and get its structure */
+
 EXTERN FAR struct stm32_tim_dev_s * stm32_tim_init(int timer);
 
-/** Power-down timer, mark it as unused */
-EXTERN int stm32_tim_deinit(FAR struct stm32_tim_dev_s * dev);
+/* Power-down timer, mark it as unused */
 
+EXTERN int stm32_tim_deinit(FAR struct stm32_tim_dev_s * dev);
 
 #undef EXTERN
 #if defined(__cplusplus)
diff --git a/configs/stm3210e-eval/README.txt b/configs/stm3210e-eval/README.txt
index 25496db2db1feacd7de2f5ff81771210b159fc79..eb7c49b95cfc67b67300cf82df61ab4e2a4850ad 100755
--- a/configs/stm3210e-eval/README.txt
+++ b/configs/stm3210e-eval/README.txt
@@ -481,7 +481,40 @@ STM3210E-EVAL-specific Configuration Options
 
     CONFIG_STM32_FORCEPOWER
 
-  Alternate pin mappings (should not be used with the STM3210E-EVAL board):
+  Timer devices may be used for different purposes.  One special purpose is
+  to generate modulated outputs for such things as motor control.  If CONFIG_STM32_TIMn
+  is defined (as above) then the following may also be defined to indicate that
+  the timer is intended to be used for pulsed output modulation, ADC conversion,
+  or DAC conversion.
+
+	CONFIG_STM32_TIM1_PWM
+	CONFIG_STM32_TIM2_PWM
+	CONFIG_STM32_TIM3_PWM
+	CONFIG_STM32_TIM4_PWM
+	CONFIG_STM32_TIM5_PWM
+	CONFIG_STM32_TIM6_PWM
+	CONFIG_STM32_TIM7_PWM
+	CONFIG_STM32_TIM8_PWM
+
+	CONFIG_STM32_TIM1_ADC
+	CONFIG_STM32_TIM2_ADC
+	CONFIG_STM32_TIM3_ADC
+	CONFIG_STM32_TIM4_ADC
+	CONFIG_STM32_TIM5_ADC
+	CONFIG_STM32_TIM6_ADC
+	CONFIG_STM32_TIM7_ADC
+	CONFIG_STM32_TIM8_ADC
+
+	CONFIG_STM32_TIM1_DAC
+	CONFIG_STM32_TIM2_DAC
+	CONFIG_STM32_TIM3_DAC
+	CONFIG_STM32_TIM4_DAC
+	CONFIG_STM32_TIM5_DAC
+	CONFIG_STM32_TIM6_DAC
+	CONFIG_STM32_TIM7_DAC
+	CONFIG_STM32_TIM8_DAC
+
+    Alternate pin mappings (should not be used with the STM3210E-EVAL board):
 
 	CONFIG_STM32_TIM1_FULL_REMAP
 	CONFIG_STM32_TIM1_PARTIAL_REMAP
diff --git a/configs/stm3240g-eval/README.txt b/configs/stm3240g-eval/README.txt
index 78b384c3149c002c9f9ee318127b562b32366198..257cb95e0d8c5ef0d69f9c93f8d868355957e2ad 100755
--- a/configs/stm3240g-eval/README.txt
+++ b/configs/stm3240g-eval/README.txt
@@ -360,7 +360,47 @@ STM3240G-EVAL-specific Configuration Options
 
     CONFIG_STM32_FORCEPOWER
 
+  Timer devices may be used for different purposes.  One special purpose is
+  to generate modulated outputs for such things as motor control.  If CONFIG_STM32_TIMn
+  is defined (as above) then the following may also be defined to indicate that
+  the timer is intended to be used for pulsed output modulation, ADC conversion,
+  or DAC conversion.
+
+	CONFIG_STM32_TIM1_PWM
+	CONFIG_STM32_TIM2_PWM
+	CONFIG_STM32_TIM3_PWM
+	CONFIG_STM32_TIM4_PWM
+	CONFIG_STM32_TIM5_PWM
+	CONFIG_STM32_TIM6_PWM
+	CONFIG_STM32_TIM7_PWM
+	CONFIG_STM32_TIM8_PWM
+	CONFIG_STM32_TIM9_PWM
+	CONFIG_STM32_TIM10_PWM
+	CONFIG_STM32_TIM11_PWM
+	CONFIG_STM32_TIM12_PWM
+	CONFIG_STM32_TIM13_PWM
+	CONFIG_STM32_TIM14_PWM
+
+	CONFIG_STM32_TIM1_ADC
+	CONFIG_STM32_TIM2_ADC
+	CONFIG_STM32_TIM3_ADC
+	CONFIG_STM32_TIM4_ADC
+	CONFIG_STM32_TIM5_ADC
+	CONFIG_STM32_TIM6_ADC
+	CONFIG_STM32_TIM7_ADC
+	CONFIG_STM32_TIM8_ADC
+
+	CONFIG_STM32_TIM1_DAC
+	CONFIG_STM32_TIM2_DAC
+	CONFIG_STM32_TIM3_DAC
+	CONFIG_STM32_TIM4_DAC
+	CONFIG_STM32_TIM5_DAC
+	CONFIG_STM32_TIM6_DAC
+	CONFIG_STM32_TIM7_DAC
+	CONFIG_STM32_TIM8_DAC
+
   JTAG Enable settings (by default JTAG-DP and SW-DP are disabled):
+
 	CONFIG_STM32_JTAG_FULL_ENABLE - Enables full SWJ (JTAG-DP + SW-DP)
 	CONFIG_STM32_JTAG_NOJNTRST_ENABLE - Enables full SWJ (JTAG-DP + SW-DP)
 	  but without JNTRST.
diff --git a/include/nuttx/pwm.h b/include/nuttx/pwm.h
new file mode 100644
index 0000000000000000000000000000000000000000..2e954d2fc862273959f272b2755315ed3267ebcf
--- /dev/null
+++ b/include/nuttx/pwm.h
@@ -0,0 +1,253 @@
+/****************************************************************************
+ * include/nuttx/pwm.h
+ *
+ *   Copyright (C) 2011 Gregory Nutt. All rights reserved.
+ *   Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ *    used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+#ifndef __INCLUDE_NUTTX_PWM_H
+#define __INCLUDE_NUTTX_PWM_H
+
+/* For the purposes of this driver, a PWM device is any devices and generates
+ * periodic outputs of controlled frequency and pulse width.  Such is device
+ * might be use, for example, to perform pulse-width modulated output or
+ * frequency/pulse-count modulated output (such as might be needed to control
+ * a stepper motor.
+ *
+ * The PWM driver is split into two parts:
+ *
+ * 1) An "upper half", generic driver that provides the comman PWM interface
+ *    to application level code, and
+ * 2) An "lower half" platform-specific driver that implements the low-level
+ *    timer controls to implement the PWM functionality.
+ */
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+#include <nuttx/compiler.h>
+
+#include <fixedmath.h>
+
+#include <nuttx/ioctl.h>
+
+#ifdef CONFIG_PWM
+
+/****************************************************************************
+ * Pre-Processor Definitions
+ ****************************************************************************/
+/* The PWM module uses a standard character driver framework.  However, since
+ * the PWM driver is a devices control interface and not a data transfer
+ * interface, the majority of the functionality is implemented in driver
+ * ioctl calls.  The PWM ioctal commands are lised below:
+ *
+ * PWMIOC_SETCHARACTERISTICS - Set the characteristics of the next pulsed
+ *   output.  This command will neither start nor stop the pulsed output.
+ *   It will either setup the configuration that will be used when the
+ *   output is started; or it will change the characteristics of the pulsed
+ *   output on the fly if the timer is already started.
+ *
+ *   ioctl argument:  A read-only reference to struct pwm_info_s that provides
+ *   the characteristics of the pulsed output.
+ *
+ * PWMIOC_GETCHARACTERISTICS - Get the currently selected characteristics of
+ *   the pulsed output (independent of whether the output is start or stopped).
+ *
+ *   ioctl argument:  A reference to struct pwm_info_s to recevie the
+ *   characteristics of the pulsed output.
+ *
+ * PWMIOC_START - Start the pulsed output.  The PWMIOC_SETCHARACTERISTICS
+ *   command must have previously been sent.
+ *
+ *   ioctl argument:  None
+ *
+ * PWMIOC_STOP - Stop the pulsed output.
+ *
+ *   ioctl argument:  None
+ *
+ * PWMIOC_GETPULSECOUNT - Return the number of pulses generated.
+ *
+ *   ioctl argument:  A pointer to a pwm_count_t variable that will be used to
+ *     receive the pulse count
+ */
+
+#define PWMIOC_SETCHARACTERISTICS _PWMIOC(1)
+#define PWMIOC_GETCHARACTERISTICS _PWMIOC(2)
+#define PWMIOC_START              _PWMIOC(3)
+#define PWMIOC_STOP               _PWMIOC(4)
+#define PWMIOC_GETPULSECOUNT      _PWMIOC(5)
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+/* This structure describes the characteristics of the pulsed output */
+
+struct pwm_info_s
+{
+  uint32_t frequency; /* Frequency of the pulse train */
+  b16_t    duty;      /* Duty of the pulse train, "1" to "0" duration */
+};
+
+/* This type is used to return pulse counts */
+
+#ifdef CONFIG_HAVE_LONG_LONG
+typedef uint16_t pwm_count_t;
+#else
+struct pwm_count_s
+{
+  uint32_t ms;  /* Most significant 32-bits of the 64-count */
+  uint32_t ls;  /* Least significant 32-bits of the 64-count */
+};
+typedef struct pwm_count_s pwm_count_t;
+#endif
+
+/* This structure is a set a callback functions used to call from the upper-
+ * half, generic PWM driver into lower-half, platform-specific logic that
+ * supports the low-level timer outputs.
+ */
+
+struct pwm_lowerhalf_s;
+struct pwm_ops_s
+{
+  /* This method is called when the driver is opened.  The lower half driver
+   * should configure and initialize the device so that it is ready for use.
+   * It should not, however, output pulses until the start method is called.
+   */
+
+  CODE int (*setup)(FAR struct pwm_lowerhalf_s *dev);
+
+  /* This method is called when the driver is closed.  The lower half driver
+   * stop pulsed output, free any resources, disable the timer hardware, and
+   * put the system into the lowest possible power usage state
+   */
+
+  CODE int (*shutdown)(FAR struct pwm_lowerhalf_s *dev);
+
+  /* (Re-)initialize the timer resources and start the pulsed output */
+
+  CODE int (*start)(FAR struct pwm_lowerhalf_s *dev, FAR const struct pwm_info_s *info);
+
+  /* Stop the pulsed output and reset the timer resources*/
+
+  CODE int (*stop)(FAR struct pwm_lowerhalf_s *dev);
+
+  /* Get the number of pulses generated */
+
+  CODE int (*pulsecount)(FAR struct pwm_lowerhalf_s *dev, FAR pwm_count_t *count);
+
+  /* Lower-half logic may support platform-specific ioctl commands */
+
+  CODE int (*ioctl)(FAR struct pwm_lowerhalf_s *dev, int cmd, unsigned long arg);
+};
+
+/* This structure is the generic form of state structure used by lower half
+ * timer driver.  This state structure is passed to the pwm driver when the
+ * driver is initialized.  Then, on subsequent callbacks into the lower half
+ * timer logic, this structure is provided so that the timer logic can
+ * maintain state information.
+ *
+ * Normally that timer logic will have its own, custom state structure
+ * that is simply cast to struct pwm_lowerhalf_s.  In order to perform such casts,
+ * the initial fields of the custom state structure match the initial fields
+ * of the following generic PWM state structure.
+ */
+
+struct pwm_lowerhalf_s
+{
+  /* The first field of this state structure must be a pointer to the PWM
+   * callback structure:
+   */
+
+  FAR const struct pwm_ops_s *ops;
+
+  /* The custom timer state structure may include additional fields after
+   * the pointer to the PWM callback structgure.
+   */
+};
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+#ifdef __cplusplus
+#define EXTERN extern "C"
+extern "C" {
+#else
+#define EXTERN extern
+#endif
+
+/****************************************************************************
+ * "Upper-Half" ADC Driver Interfaces
+ ****************************************************************************/
+/****************************************************************************
+ * Name: pwm_register
+ *
+ * Description:
+ *   This function binds an instance of a "lower half" timer driver with the
+ *   "upper half" PWM device and registers that device so that can be used
+ *   by application code.
+ *
+ *   When this function is called, the "lower half" driver should be in the
+ *   reset state (as if the shutdown() method had already been called).
+ *
+ * Input parameters:
+ *   path - The full path to the driver to be registers in the NuttX pseudo-
+ *     filesystem.  The recommended convention is to name all PWM drivers
+ *     as "/dev/pwm0", "/dev/pwm1", etc.  where the driver path differs only
+ *     in the "minor" number at the end of the device name.
+ *   dev - A pointer to an instance of lower half timer driver.  This instance
+ *     is bound to the PWM driver and must persists as long as the driver
+ *     persists.
+ *
+ * Returned Value:
+ *   Zero on success; a negated errno value on failure.
+ *
+ ****************************************************************************/
+
+int pwm_register(FAR const char *path, FAR struct pwm_lowerhalf_s *dev);
+
+/****************************************************************************
+ * Platform-Independent "Lower-Half" ADC Driver Interfaces
+ ****************************************************************************/
+
+#undef EXTERN
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CONFIG_PWM */
+#endif /* __INCLUDE_NUTTX_PWM_H */