From 1d0f90dcdf149ed0427eebbe51db0ee20c22413d Mon Sep 17 00:00:00 2001 From: Marian Buschsieweke <marian.buschsieweke@ovgu.de> Date: Mon, 18 Jun 2018 09:10:25 +0200 Subject: [PATCH] cpu/lpc2387: Various fixes for GPIO driver - Fixed documentation - Use bitwise operation instead of multiplication and addition in `GPIO_PIN()` - Allow GPIOs to be configured as input via `gpio_init()` - Fixed bugs in `gpio_init_mux`: - `0x01 << ((pin & 31) * 2)` was used before to generate the bitmask, but this would shift by 62 to the left. Correct is `0x01 << ((pin & 15) * 2)` (See [datasheet](https://www.nxp.com/docs/en/user-guide/UM10211.pdf) at pages 156ff) - Only one of the two bits was cleared previously - Changed strategy to access GPIO pins: - Previous strategy: - Set all bits in FIOMASK except the one for the pin to control to disable access to them - Set/clear/read all pins in the target GPIO port (but access to all but the target pin is ignored because of the applied FIOMASK) - New strategy: - Set/clear/read only the target pin - Advantages: - Only one access to a GPIO register instead of two - Proven approach: Access to GPIOs on lpc2387 is mostly done by accessing the GPIO registers directy (e.g. see the sht11 driver). Those accesses never touch the FIOMASK register - No unwanted side effects: Disabling all but one pin in a GPIO port without undoing that seems not to be a good idea --- cpu/lpc2387/include/periph_cpu.h | 24 +++++++++++++++------- cpu/lpc2387/periph/gpio.c | 34 +++++++++++++++----------------- 2 files changed, 33 insertions(+), 25 deletions(-) diff --git a/cpu/lpc2387/include/periph_cpu.h b/cpu/lpc2387/include/periph_cpu.h index 841b63bbf3..d5a99d5a4c 100644 --- a/cpu/lpc2387/include/periph_cpu.h +++ b/cpu/lpc2387/include/periph_cpu.h @@ -39,12 +39,22 @@ extern "C" { * @brief Fast GPIO register definition struct */ typedef struct { - __IO uint32_t DIR; /**< he */ - uint32_t _reserved[3]; /**< really */ - __IO uint32_t MASK; /**< wants */ - __IO uint32_t PIN; /**< to */ - __IO uint32_t SET; /**< know */ - __IO uint32_t CLR; /**< everything */ + /** @brief Direction: Output if corresponding bit is set, otherwise input */ + __IO uint32_t DIR; + /** @brief 12 bytes of reseved memory we don't need to access */ + uint32_t _reserved[3]; + /** @brief Set bits to ignore corresponding bits when accessing `PIN`, `SET` + * or `CLR` register of this port + */ + __IO uint32_t MASK; + /** @brief The current state of each pin of this port is accessible here + * (regardless of direction): If bit is set input is high + */ + __IO uint32_t PIN; + /** @brief Output pins are set to high by setting the corresponding bit */ + __IO uint32_t SET; + /** @brief Output pins are set to low by setting the corresponding bit */ + __IO uint32_t CLR; } FIO_PORT_t; #define FIO_PORTS ((FIO_PORT_t*)FIO_BASE_ADDR) @@ -54,7 +64,7 @@ typedef struct { int gpio_init_mux(unsigned pin, unsigned mux); void gpio_init_states(void); -#define GPIO_PIN(port, pin) (port*32 + pin) +#define GPIO_PIN(port, pin) (port<<5 | pin) #ifndef DOXYGEN #define HAVE_GPIO_FLANK_T diff --git a/cpu/lpc2387/periph/gpio.c b/cpu/lpc2387/periph/gpio.c index a36e28fc5e..3891c50b7f 100644 --- a/cpu/lpc2387/periph/gpio.c +++ b/cpu/lpc2387/periph/gpio.c @@ -67,18 +67,19 @@ int gpio_init(gpio_t pin, gpio_mode_t mode) { unsigned _pin = pin & 31; unsigned port = pin >> 5; - - if (mode != GPIO_OUT) { - return -1; - } - FIO_PORT_t *_port = &FIO_PORTS[port]; - /* set mask */ - _port->MASK = ~(0x1<<_pin); - /* set direction */ - _port->DIR = ~0; + switch (mode){ + case GPIO_OUT: + _port->DIR |= 1<<_pin; + break; + case GPIO_IN: + _port->DIR &= ~(1<<_pin); + break; + default: + return -1; + } gpio_init_mux(pin, 0); @@ -88,13 +89,13 @@ int gpio_init(gpio_t pin, gpio_mode_t mode) int gpio_init_mux(unsigned pin, unsigned mux) { (void) mux; - unsigned _pin = pin & 31; - PINSEL[pin>>4] &= ~(0x1 << (_pin*2)); + unsigned pos = (pin & 0xf) << 1; + PINSEL[pin>>4] &= ~(0x3 << pos); return 0; } int gpio_init_int(gpio_t pin, gpio_mode_t mode, gpio_flank_t flank, - gpio_cb_t cb, void *arg) + gpio_cb_t cb, void *arg) { (void)mode; @@ -222,8 +223,7 @@ int gpio_read(gpio_t pin) unsigned _pin = pin & 31; unsigned port = pin >> 5; FIO_PORT_t *_port = &FIO_PORTS[port]; - _port->MASK = ~(1<<_pin); - return _port->PIN != 0; + return (_port->PIN & (1 << _pin)) != 0; } void gpio_set(gpio_t pin) @@ -231,8 +231,7 @@ void gpio_set(gpio_t pin) unsigned _pin = pin & 31; unsigned port = pin >> 5; FIO_PORT_t *_port = &FIO_PORTS[port]; - _port->MASK = ~(1<<_pin); - _port->SET = ~0; + _port->SET = 1 << _pin; } void gpio_clear(gpio_t pin) @@ -240,8 +239,7 @@ void gpio_clear(gpio_t pin) unsigned _pin = pin & 31; unsigned port = pin >> 5; FIO_PORT_t *_port = &FIO_PORTS[port]; - _port->MASK = ~(1<<_pin); - _port->CLR = ~0; + _port->CLR = 1 << _pin; } void gpio_toggle(gpio_t dev) -- GitLab