From 346b51d9fa0c8edf4a121d1c92a705b6c36b37d0 Mon Sep 17 00:00:00 2001
From: Hauke Petersen <hauke.petersen@fu-berlin.de>
Date: Tue, 17 Jan 2017 14:08:13 +0100
Subject: [PATCH] cpu/stm32/pwm: made channel config more flexible

---
 cpu/stm32_common/include/periph_cpu_common.h | 20 +++++++++++++------
 cpu/stm32_common/periph/pwm.c                | 21 ++++++++++++++------
 2 files changed, 29 insertions(+), 12 deletions(-)

diff --git a/cpu/stm32_common/include/periph_cpu_common.h b/cpu/stm32_common/include/periph_cpu_common.h
index 98f1eb2d14..a18d5792a0 100644
--- a/cpu/stm32_common/include/periph_cpu_common.h
+++ b/cpu/stm32_common/include/periph_cpu_common.h
@@ -129,16 +129,24 @@ typedef struct {
     uint8_t irqn;           /**< global IRQ channel */
 } timer_conf_t;
 
+/**
+ * @brief   PWM channel
+ */
+typedef struct {
+    gpio_t pin;             /**< GPIO pin mapped to this channel */
+    uint8_t cc_chan;        /**< capture compare channel used */
+} pwm_chan_t;
+
 /**
  * @brief   PWM configuration
  */
 typedef struct {
-    TIM_TypeDef *dev;       /**< Timer used */
-    uint32_t rcc_mask;      /**< bit in clock enable register */
-    gpio_t pins[4];         /**< pins used, set to GPIO_UNDEF if not used */
-    gpio_af_t af;           /**< alternate function used */
-    uint8_t chan;           /**< number of configured channels */
-    uint8_t bus;            /**< APB bus */
+    TIM_TypeDef *dev;               /**< Timer used */
+    uint32_t rcc_mask;              /**< bit in clock enable register */
+    pwm_chan_t chan[TIMER_CHAN];    /**< channel mapping, set to {GPIO_UNDEF, 0}
+                                     *   if not used */
+    gpio_af_t af;                   /**< alternate function used */
+    uint8_t bus;                    /**< APB bus */
 } pwm_conf_t;
 
 /**
diff --git a/cpu/stm32_common/periph/pwm.c b/cpu/stm32_common/periph/pwm.c
index f7009ddd65..511ecf71ff 100644
--- a/cpu/stm32_common/periph/pwm.c
+++ b/cpu/stm32_common/periph/pwm.c
@@ -58,9 +58,11 @@ uint32_t pwm_init(pwm_t pwm, pwm_mode_t mode, uint32_t freq, uint16_t res)
     }
 
     /* configure the used pins */
-    for (unsigned i = 0; i < pwm_config[pwm].chan; i++) {
-        gpio_init(pwm_config[pwm].pins[i], GPIO_OUT);
-        gpio_init_af(pwm_config[pwm].pins[i], pwm_config[pwm].af);
+    unsigned i = 0;
+    while ((i < TIMER_CHAN) && (pwm_config[pwm].chan[i].pin != GPIO_UNDEF)) {
+        gpio_init(pwm_config[pwm].chan[i].pin, GPIO_OUT);
+        gpio_init_af(pwm_config[pwm].chan[i].pin, pwm_config[pwm].af);
+        i++;
     }
 
     /* configure the PWM frequency and resolution by setting the auto-reload
@@ -100,19 +102,26 @@ uint32_t pwm_init(pwm_t pwm, pwm_mode_t mode, uint32_t freq, uint16_t res)
 uint8_t pwm_channels(pwm_t pwm)
 {
     assert(pwm < PWM_NUMOF);
-    return pwm_config[pwm].chan;
+
+    unsigned i = 0;
+    while ((i < TIMER_CHAN) && (pwm_config[pwm].chan[i].pin != GPIO_UNDEF)) {
+        i++;
+    }
+    return (uint8_t)i;
 }
 
 void pwm_set(pwm_t pwm, uint8_t channel, uint16_t value)
 {
-    assert((pwm < PWM_NUMOF) && (channel < pwm_config[pwm].chan));
+    assert((pwm < PWM_NUMOF) &&
+           (channel < TIMER_CHAN) &&
+           (pwm_config[pwm].chan[channel].pin != GPIO_UNDEF));
 
     /* norm value to maximum possible value */
     if (value > dev(pwm)->ARR) {
         value = (uint16_t)dev(pwm)->ARR;
     }
     /* set new value */
-    dev(pwm)->CCR[channel] = value;
+    dev(pwm)->CCR[pwm_config[pwm].chan[channel].cc_chan] = value;
 }
 
 void pwm_start(pwm_t pwm)
-- 
GitLab