From 141f8c9ff6f71989364fbd894dd8077eb1d4a4af Mon Sep 17 00:00:00 2001
From: Hauke Petersen <hauke.petersen@fu-berlin.de>
Date: Sat, 20 Feb 2016 16:46:53 +0100
Subject: [PATCH] cpu/stm32f1: adapted GPIO driver

---
 cpu/stm32f1/include/periph_cpu.h | 27 +++++++++++++++++++++++++
 cpu/stm32f1/periph/gpio.c        | 34 +++++++++++++-------------------
 cpu/stm32f1/periph/i2c.c         |  4 ++--
 cpu/stm32f1/periph/spi.c         |  2 +-
 cpu/stm32f1/periph/uart.c        |  2 +-
 5 files changed, 45 insertions(+), 24 deletions(-)

diff --git a/cpu/stm32f1/include/periph_cpu.h b/cpu/stm32f1/include/periph_cpu.h
index 4cbf4d79f9..459faaff21 100644
--- a/cpu/stm32f1/include/periph_cpu.h
+++ b/cpu/stm32f1/include/periph_cpu.h
@@ -58,6 +58,33 @@ typedef uint32_t gpio_t;
  */
 #define TIMER_MAXVAL        (0xffff)
 
+/**
+ * @brief   Generate GPIO mode bitfields
+ *
+ * We use 4 bit to determine the pin functions:
+ * - bit 2+3: in/out
+ * - bit 1: PU enable
+ * - bit 2: OD enable
+ */
+#define GPIO_MODE(mode, cnf)    (mode | (cnf << 2))
+
+/**
+ * @brief   Override GPIO mode options
+ *
+ * We use 4 bit to encode CNF and MODE.
+ * @{
+ */
+#define HAVE_GPIO_MODE_T
+typedef enum {
+    GPIO_IN    = GPIO_MODE(0, 1),   /**< input w/o pull R */
+    GPIO_IN_PD = GPIO_MODE(0, 2),   /**< input with pull-down */
+    GPIO_IN_PU = GPIO_MODE(0, 2),   /**< input with pull-up */
+    GPIO_OUT   = GPIO_MODE(3, 0),   /**< push-pull output */
+    GPIO_OD    = GPIO_MODE(3, 1),   /**< open-drain w/o pull R */
+    GPIO_OD_PU = (0xff)             /**< not supported by HW */
+} gpio_mode_t;
+/** @} */
+
 /**
  * @brief   Override values for pull register configuration
  * @{
diff --git a/cpu/stm32f1/periph/gpio.c b/cpu/stm32f1/periph/gpio.c
index 209402e73c..ebd8020d32 100644
--- a/cpu/stm32f1/periph/gpio.c
+++ b/cpu/stm32f1/periph/gpio.c
@@ -68,38 +68,32 @@ static inline int _pin_num(gpio_t pin)
 }
 
 
-int gpio_init(gpio_t pin, gpio_dir_t dir, gpio_pp_t pullup)
+int gpio_init(gpio_t pin, gpio_mode_t mode)
 {
     GPIO_TypeDef *port = _port(pin);
     int pin_num = _pin_num(pin);
 
+    /* open-drain output with pull-up is not supported */
+    if (mode == GPIO_OD_PU) {
+        return -1;
+    }
 
     /* enable the clock for the selected port */
     RCC->APB2ENR |= (RCC_APB2ENR_IOPAEN << _port_num(pin));
-    /* clear configuration */
+
+    /* set pin mode */
     port->CR[pin_num >> 3] &= ~(0xf << ((pin_num & 0x7) * 4));
-    /* set new configuration */
-    if (dir == GPIO_DIR_OUT) {
-        if (pullup != GPIO_NOPULL) {
-            return -1;
-        }
-        /* set to output, push-pull, 50MHz */
-        port->CR[pin_num >> 3] |= (0x3 << ((pin_num & 0x7) * 4));
-        /* clear pin */
-        port->BRR = (1 << pin_num);
-    }
-    else {
-        /* configure pin to input, pull register according to the value of
-         * the pullup parameter */
-        port->CR[pin_num >> 3] |= ((pullup & 0xc)  << ((pin_num & 0x7) * 4));
-        port->ODR &= ~(1 << pin_num);
-        port->ODR |=  ((pullup & 0x1) << pin_num);
+    port->CR[pin_num >> 3] |=  (mode << ((pin_num & 0x7) * 4));
+    /* set initial state of output register */
+    port->BRR = (1 << pin_num);
+    if (mode == GPIO_IN_PU) {
+        port->BSRR = (1 << pin_num);
     }
 
     return 0; /* all OK */
 }
 
-int gpio_init_int(gpio_t pin, gpio_pp_t pullup, gpio_flank_t flank,
+int gpio_init_int(gpio_t pin, gpio_mode_t mode, gpio_flank_t flank,
                   gpio_cb_t cb, void *arg)
 {
     int pin_num = _pin_num(pin);
@@ -107,7 +101,7 @@ int gpio_init_int(gpio_t pin, gpio_pp_t pullup, gpio_flank_t flank,
     /* disable interrupts on the channel we want to edit (just in case) */
     EXTI->IMR &= ~(1 << pin_num);
     /* configure pin as input */
-    gpio_init(pin, GPIO_DIR_IN, pullup);
+    gpio_init(pin, mode);
     /* set callback */
     exti_ctx[pin_num].cb = cb;
     exti_ctx[pin_num].arg = arg;
diff --git a/cpu/stm32f1/periph/i2c.c b/cpu/stm32f1/periph/i2c.c
index 48702e9fe8..7c1aef7236 100644
--- a/cpu/stm32f1/periph/i2c.c
+++ b/cpu/stm32f1/periph/i2c.c
@@ -167,8 +167,8 @@ static void _pin_config(gpio_t scl, gpio_t sda)
 {
     /* toggle pins to reset analog filter -> see datasheet */
     /* set as output */
-    gpio_init(scl, GPIO_DIR_OUT, GPIO_NOPULL);
-    gpio_init(sda, GPIO_DIR_OUT, GPIO_NOPULL);
+    gpio_init(scl, GPIO_OUT);
+    gpio_init(sda, GPIO_OUT);
     /* run through toggling sequence */
     gpio_set(scl);
     gpio_set(sda);
diff --git a/cpu/stm32f1/periph/spi.c b/cpu/stm32f1/periph/spi.c
index 9c8c09240b..8075b9c91a 100644
--- a/cpu/stm32f1/periph/spi.c
+++ b/cpu/stm32f1/periph/spi.c
@@ -161,7 +161,7 @@ int spi_conf_pins(spi_t dev)
     /* configure pins for alternate function input (MISO) or output (MOSI, CLK) */
     gpio_init_af(clk, GPIO_AF_OUT_PP);
     gpio_init_af(mosi, GPIO_AF_OUT_PP);
-    gpio_init(miso, GPIO_DIR_IN, GPIO_NOPULL);
+    gpio_init(miso, GPIO_IN);
     return 0;
 }
 
diff --git a/cpu/stm32f1/periph/uart.c b/cpu/stm32f1/periph/uart.c
index bfe88789b8..0e3cd765f9 100644
--- a/cpu/stm32f1/periph/uart.c
+++ b/cpu/stm32f1/periph/uart.c
@@ -66,7 +66,7 @@ int uart_init(uart_t uart, uint32_t baudrate, uart_rx_cb_t rx_cb, void *arg)
     isr_ctx[uart].arg   = arg;
 
     /* configure RX and TX pin */
-    gpio_init(uart_config[uart].rx_pin, GPIO_DIR_IN, GPIO_NOPULL);
+    gpio_init(uart_config[uart].rx_pin, GPIO_IN);
     gpio_init_af(uart_config[uart].tx_pin, GPIO_AF_OUT_PP);
 
     /* enable the clock */
-- 
GitLab