diff --git a/cpu/stm32l1/include/periph_cpu.h b/cpu/stm32l1/include/periph_cpu.h index 35068642c374f9502e56d99895668175a735bfa7..18399b038c39104f2bc4faccfc363e0a73fd3114 100644 --- a/cpu/stm32l1/include/periph_cpu.h +++ b/cpu/stm32l1/include/periph_cpu.h @@ -45,6 +45,31 @@ typedef uint32_t gpio_t; */ #define GPIO_PIN(x, y) ((GPIOA_BASE + (x << 10)) | y) +/** + * @brief Generate GPIO mode bitfields + * + * We use 5 bit to encode the mode: + * - bit 0+1: pin mode (input / output) + * - bit 2+3: pull resistor configuration + * - bit 4: output type (0: push-pull, 1: open-drain) + */ +#define GPIO_MODE(io, pr, ot) ((io << 0) | (pr << 2) | (ot << 4)) + +/** + * @brief Override GPIO mode options + * @{ + */ +#define HAVE_GPIO_MODE_T +typedef enum { + GPIO_IN = GPIO_MODE(0, 0, 0), /**< input w/o pull R */ + GPIO_IN_PD = GPIO_MODE(0, 2, 0), /**< input with pull-down */ + GPIO_IN_PU = GPIO_MODE(0, 1, 0), /**< input with pull-up */ + GPIO_OUT = GPIO_MODE(1, 0, 0), /**< push-pull output */ + GPIO_OD = GPIO_MODE(1, 0, 1), /**< open-drain w/o pull R */ + GPIO_OD_PU = GPIO_MODE(1, 1, 1) /**< open-drain with pull-up */ +} gpio_mode_t; +/** @} */ + /** * @brief Available ports on the STM32L1 family */ @@ -106,6 +131,7 @@ typedef struct { I2C_TypeDef *dev; /**< i2c device */ gpio_t scl; /**< scl pin number */ gpio_t sda; /**< sda pin number */ + gpio_mode_t pin_mode; /**< with or without pull resistor */ gpio_af_t af; /**< I2C alternate function value */ uint8_t er_irqn; /**< error IRQ */ uint8_t ev_irqn; /**< event IRQ */ diff --git a/cpu/stm32l1/periph/gpio.c b/cpu/stm32l1/periph/gpio.c index bb80559f9f54e2ee3d9c3a7c3e28c70a0c0246e0..9de5baea76e8a41363e9e0383097d91fdd099c87 100644 --- a/cpu/stm32l1/periph/gpio.c +++ b/cpu/stm32l1/periph/gpio.c @@ -63,32 +63,31 @@ static inline int _pin_num(gpio_t pin) return (pin & 0x0f); } -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); /* enable clock */ RCC->AHBENR |= (RCC_AHBENR_GPIOAEN << _port_num(pin)); - /* configure pull register */ - port->PUPDR &= ~(3 << (2 * pin_num)); - port->PUPDR |= (pullup << (2 * pin_num)); - /* set direction */ - if (dir == GPIO_DIR_OUT) { - port->MODER &= ~(3 << (2 * pin_num)); /* set pin to output mode */ - port->MODER |= (1 << (2 * pin_num)); - port->OTYPER &= ~(1 << pin_num); /* set to push-pull */ - port->OSPEEDR |= (3 << (2 * pin_num)); /* set to high speed */ - port->ODR &= ~(1 << pin_num); /* set pin to low signal */ - } - else { - port->MODER &= ~(3 << (2 * pin_num)); /* configure pin as input */ - } + + /* set mode */ + port->MODER &= ~(0x3 << (2 * pin_num)); + port->MODER |= ((mode & 0x3) << (2 * pin_num)); + /* set pull resistor configuration */ + port->PUPDR &= ~(0x3 << (2 * pin_num)); + port->PUPDR |= (((mode >> 2) & 0x3) << (2 * pin_num)); + /* set output mode */ + port->OTYPER &= ~(1 << pin_num); + port->OTYPER |= (((mode >> 4) & 0x1) << pin_num); + /* finally set pin speed to maximum and reset output */ + port->OSPEEDR |= (3 << (2 * pin_num)); + port->BRR = (1 << pin_num); + return 0; } -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); @@ -100,7 +99,7 @@ int gpio_init_int(gpio_t pin, /* enable the SYSCFG clock */ RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN; /* initialize pin as input */ - gpio_init(pin, GPIO_DIR_IN, pullup); + gpio_init(pin, mode); /* enable global pin interrupt */ if (pin_num < 5) { NVIC_EnableIRQ(EXTI0_IRQn + pin_num); diff --git a/cpu/stm32l1/periph/i2c.c b/cpu/stm32l1/periph/i2c.c index 3fad897d94f84a2e527ea2974f3dc54257894ea7..5d2d4f6d819733eefc18a5bdf2004f5b609c87c2 100644 --- a/cpu/stm32l1/periph/i2c.c +++ b/cpu/stm32l1/periph/i2c.c @@ -97,9 +97,9 @@ int i2c_init_master(i2c_t dev, i2c_speed_t speed) NVIC_EnableIRQ(i2c_config[dev].er_irqn); /* configure pins */ - gpio_init(i2c_config[dev].scl, GPIO_DIR_OUT, GPIO_PULLUP); + gpio_init(i2c_config[dev].scl, i2c_config[dev].pin_mode); gpio_init_af(i2c_config[dev].scl, i2c_config[dev].af); - gpio_init(i2c_config[dev].sda, GPIO_DIR_OUT, GPIO_PULLUP); + gpio_init(i2c_config[dev].sda, i2c_config[dev].pin_mode); gpio_init_af(i2c_config[dev].sda, i2c_config[dev].af); /* configure device */ diff --git a/cpu/stm32l1/periph/uart.c b/cpu/stm32l1/periph/uart.c index 22da881ef7a7a75e744781cbbad130dc50548092..056f261d8f45c5ed360600f1d7063bacff8400aa 100644 --- a/cpu/stm32l1/periph/uart.c +++ b/cpu/stm32l1/periph/uart.c @@ -114,9 +114,9 @@ static int init_base(uart_t uart, uint32_t baudrate) } /* uart_configure RX and TX pins, set pin to use alternative function mode */ - gpio_init(tx_pin, GPIO_DIR_OUT, GPIO_NOPULL); + gpio_init(tx_pin, GPIO_OUT); gpio_init_af(tx_pin, af); - gpio_init(rx_pin, GPIO_DIR_IN, GPIO_NOPULL); + gpio_init(rx_pin, GPIO_IN); gpio_init_af(rx_pin, af); /* uart_configure UART to mode 8N1 with given baudrate */