diff --git a/boards/arm/efr32_slwstk6061a/efr32_slwstk6061a.dts b/boards/arm/efr32_slwstk6061a/efr32_slwstk6061a.dts index 78e3d25e904b4..723243fa8d69e 100644 --- a/boards/arm/efr32_slwstk6061a/efr32_slwstk6061a.dts +++ b/boards/arm/efr32_slwstk6061a/efr32_slwstk6061a.dts @@ -29,11 +29,11 @@ leds { compatible = "gpio-leds"; led0: led_0 { - gpios = <&gpiof 4 0>; + gpios = <&gpiof 4 GPIO_ACTIVE_HIGH>; label = "LED 0"; }; led1: led_1 { - gpios = <&gpiof 5 0>; + gpios = <&gpiof 5 GPIO_ACTIVE_HIGH>; label = "LED 1"; }; }; @@ -42,12 +42,12 @@ compatible = "gpio-keys"; button0: button_0 { /* gpio flags need validation */ - gpios = <&gpiof 6 GPIO_INT_ACTIVE_LOW>; + gpios = <&gpiof 6 GPIO_INT_LOW>; label = "User Push Button 0"; }; button1: button_1 { /* gpio flags need validation */ - gpios = <&gpiof 7 GPIO_INT_ACTIVE_LOW>; + gpios = <&gpiof 7 GPIO_INT_LOW>; label = "User Push Button 1"; }; }; diff --git a/boards/arm/sam_e70_xplained/sam_e70_xplained.dts b/boards/arm/sam_e70_xplained/sam_e70_xplained.dts index ea1b2c70a0f21..a38adceb0a5a7 100644 --- a/boards/arm/sam_e70_xplained/sam_e70_xplained.dts +++ b/boards/arm/sam_e70_xplained/sam_e70_xplained.dts @@ -32,7 +32,7 @@ leds { compatible = "gpio-leds"; green_led: led_0 { - gpios = <&portc 8 0>; + gpios = <&portc 8 GPIO_ACTIVE_LOW>; label = "User LED"; }; }; @@ -45,8 +45,7 @@ */ sw0_user_button: button_1 { label = "User Button"; - gpios = <&porta 11 (GPIO_PUD_PULL_UP | - GPIO_INT_ACTIVE_LOW)>; + gpios = <&porta 11 (GPIO_PUD_PULL_UP | GPIO_INT_LOW)>; }; }; }; diff --git a/drivers/gpio/gpio_dw.c b/drivers/gpio/gpio_dw.c index 021f8d23a3218..9f16f893de5da 100644 --- a/drivers/gpio/gpio_dw.c +++ b/drivers/gpio/gpio_dw.c @@ -154,7 +154,7 @@ static inline void dw_interrupt_config(struct device *port, int access_op, struct gpio_dw_runtime *context = port->driver_data; const struct gpio_dw_config *config = port->config->config_info; u32_t base_addr = dw_base_to_block_base(context->base_addr); - u8_t flag_is_set; + bool flag_is_set; ARG_UNUSED(access_op); diff --git a/drivers/gpio/gpio_gecko.c b/drivers/gpio/gpio_gecko.c index 4ec1e44b17ef9..db16ce6d76548 100644 --- a/drivers/gpio/gpio_gecko.c +++ b/drivers/gpio/gpio_gecko.c @@ -57,6 +57,7 @@ struct gpio_gecko_data { sys_slist_t callbacks; /* pin callback routine enable flags, by pin number */ u32_t pin_callback_enables; + u32_t invert; }; static inline void gpio_gecko_add_port(struct gpio_gecko_common_data *data, @@ -73,25 +74,38 @@ static int gpio_gecko_configure(struct device *dev, const struct gpio_gecko_config *config = dev->config->config_info; GPIO_P_TypeDef *gpio_base = config->gpio_base; GPIO_Port_TypeDef gpio_index = config->gpio_index; + struct gpio_gecko_data *data = dev->driver_data; GPIO_Mode_TypeDef mode; unsigned int out = 0U; /* Check for an invalid pin configuration */ - if ((flags & GPIO_INT) && (flags & GPIO_DIR_OUT)) { + if ((flags & GPIO_INT_ENABLE) && (flags & GPIO_OUTPUT_ENABLE)) { return -EINVAL; } /* Interrupt on static level is not supported by the hardware */ - if ((flags & GPIO_INT) && !(flags & GPIO_INT_EDGE)) { + if ((flags & GPIO_INT_ENABLE) && !(flags & GPIO_INT_EDGE)) { return -ENOTSUP; } /* Setting interrupt flags for a complete port is not implemented */ - if ((flags & GPIO_INT) && (access_op == GPIO_ACCESS_BY_PORT)) { + if ((flags & GPIO_INT_ENABLE) && (access_op == GPIO_ACCESS_BY_PORT)) { return -ENOTSUP; } - if ((flags & GPIO_DIR_MASK) == GPIO_DIR_IN) { + if (flags & GPIO_OUTPUT_ENABLE) { + /* Following modes enable both output and input */ + if (flags & GPIO_SINGLE_ENDED) { + if (flags & GPIO_LINE_OPEN_DRAIN) { + mode = gpioModeWiredAnd; + } else { + mode = gpioModeWiredOr; + } + } else { + mode = gpioModePushPull; + } + out = (flags & GPIO_OUTPUT_INIT_HIGH) ? 1U : 0U; + } else if (flags & GPIO_INPUT_ENABLE) { if ((flags & GPIO_PUD_MASK) == GPIO_PUD_PULL_UP) { mode = gpioModeInputPull; out = 1U; /* pull-up*/ @@ -101,8 +115,9 @@ static int gpio_gecko_configure(struct device *dev, } else { mode = gpioModeInput; } - } else { /* GPIO_DIR_OUT */ - mode = gpioModePushPull; + } else { + /* Neither input nor output mode is selected */ + mode = gpioModeDisabled; } /* The flags contain options that require touching registers in the * GPIO module and the corresponding PORT module. @@ -113,6 +128,12 @@ static int gpio_gecko_configure(struct device *dev, if (access_op == GPIO_ACCESS_BY_PIN) { GPIO_PinModeSet(gpio_index, pin, mode, out); + if (flags & GPIO_ACTIVE_LOW) { + data->invert |= BIT(pin); + } else { + data->invert &= ~BIT(pin); + } + } else { /* GPIO_ACCESS_BY_PORT */ gpio_base->MODEL = GECKO_GPIO_MODEL(7, mode) | GECKO_GPIO_MODEL(6, mode) | GECKO_GPIO_MODEL(5, mode) @@ -128,15 +149,14 @@ static int gpio_gecko_configure(struct device *dev, | GECKO_GPIO_MODEH(9, mode) | GECKO_GPIO_MODEH(8, mode); gpio_base->DOUT = (out ? 0xFFFF : 0x0000); + data->invert = (flags & GPIO_ACTIVE_LOW ? 0xFFFF : 0x0000); } if (access_op == GPIO_ACCESS_BY_PIN) { GPIO_IntConfig(gpio_index, pin, - (flags & GPIO_INT_ACTIVE_HIGH) - || (flags & GPIO_INT_DOUBLE_EDGE), - !(flags & GPIO_INT_ACTIVE_HIGH) - || (flags & GPIO_INT_DOUBLE_EDGE), - !!(flags & GPIO_INT)); + flags & GPIO_INT_HIGH, + flags & GPIO_INT_LOW, + flags & GPIO_INT_ENABLE); } return 0; @@ -147,8 +167,12 @@ static int gpio_gecko_write(struct device *dev, { const struct gpio_gecko_config *config = dev->config->config_info; GPIO_P_TypeDef *gpio_base = config->gpio_base; + struct gpio_gecko_data *data = dev->driver_data; if (access_op == GPIO_ACCESS_BY_PIN) { + if (data->invert & BIT(pin)) { + value = !value; + } if (value) { /* Set the data output for the corresponding pin. * Writing zeros to the other bits leaves the data @@ -164,7 +188,7 @@ static int gpio_gecko_write(struct device *dev, } } else { /* GPIO_ACCESS_BY_PORT */ /* Write the data output for all the pins */ - gpio_base->DOUT = value; + gpio_base->DOUT = value ^ data->invert; } return 0; @@ -175,8 +199,10 @@ static int gpio_gecko_read(struct device *dev, { const struct gpio_gecko_config *config = dev->config->config_info; GPIO_P_TypeDef *gpio_base = config->gpio_base; + struct gpio_gecko_data *data = dev->driver_data; *value = gpio_base->DIN; + *value ^= data->invert; if (access_op == GPIO_ACCESS_BY_PIN) { *value = (*value & BIT(pin)) >> pin; diff --git a/drivers/gpio/gpio_qmsi.c b/drivers/gpio/gpio_qmsi.c index 46822c52c4d65..0e335fe40f4ce 100644 --- a/drivers/gpio/gpio_qmsi.c +++ b/drivers/gpio/gpio_qmsi.c @@ -171,7 +171,7 @@ static void gpio_qmsi_callback(void *data, u32_t status) } } -static void qmsi_write_bit(u32_t *target, u8_t bit, u8_t value) +static void qmsi_write_bit(u32_t *target, u8_t bit, bool value) { if (value) { sys_set_bit((uintptr_t) target, bit); diff --git a/drivers/gpio/gpio_qmsi_ss.c b/drivers/gpio/gpio_qmsi_ss.c index 0ce5c5bab1767..68fc8adb28f4e 100644 --- a/drivers/gpio/gpio_qmsi_ss.c +++ b/drivers/gpio/gpio_qmsi_ss.c @@ -143,7 +143,7 @@ static void ss_gpio_qmsi_callback(void *data, uint32_t status) } } -static void ss_qmsi_write_bit(u32_t *target, u8_t bit, u8_t value) +static void ss_qmsi_write_bit(u32_t *target, u8_t bit, bool value) { if (value) { sys_set_bit((uintptr_t) target, bit); diff --git a/drivers/gpio/gpio_sam.c b/drivers/gpio/gpio_sam.c index 0251aad32cf69..a9b0b6b92ecd1 100644 --- a/drivers/gpio/gpio_sam.c +++ b/drivers/gpio/gpio_sam.c @@ -22,24 +22,61 @@ struct gpio_sam_config { }; struct gpio_sam_runtime { + u32_t invert; sys_slist_t cb; }; #define DEV_CFG(dev) \ ((const struct gpio_sam_config *const)(dev)->config->config_info) +#define DEV_DATA(dev) \ + ((struct gpio_sam_runtime *const)(dev)->driver_data) -static int gpio_sam_config_pin(Pio * const pio, u32_t mask, int flags) +static int gpio_sam_config_pin(struct device *dev, Pio * const pio, u32_t mask, + int flags) { + struct gpio_sam_runtime *const dev_data = DEV_DATA(dev); + + if (!(flags & (GPIO_OUTPUT_ENABLE | GPIO_INPUT_ENABLE))) { + /* Neither input nor output mode is selected */ + + /* Disable the interrupt. */ + pio->PIO_IDR = mask; + /* Disable pull-up. */ + pio->PIO_PUDR = mask; + /* Disable pull-down. */ + pio->PIO_PPDDR = mask; + /* Let the PIO control the pin (instead of a peripheral). */ + pio->PIO_PER = mask; + + return 0; + } + /* Setup the pin direcion. */ - if ((flags & GPIO_DIR_MASK) == GPIO_DIR_OUT) { + if (flags & GPIO_OUTPUT_ENABLE) { + if (flags & GPIO_OUTPUT_INIT_HIGH) { + /* Set the pin. */ + pio->PIO_SODR = mask; + } + if (flags & GPIO_OUTPUT_INIT_LOW) { + /* Clear the pin. */ + pio->PIO_CODR = mask; + } pio->PIO_OER = mask; } else { pio->PIO_ODR = mask; } + /* Note: Input is always enabled. */ + + if (flags & GPIO_ACTIVE_LOW) { + dev_data->invert |= mask; + } else { + dev_data->invert &= ~mask; + } + /* Setup interrupt configuration. */ - if (flags & GPIO_INT) { - if (flags & GPIO_INT_DOUBLE_EDGE) { + if (flags & GPIO_INT_ENABLE) { + if ((flags & GPIO_INT_LOW) && (flags & GPIO_INT_HIGH)) { return -ENOTSUP; } @@ -55,7 +92,7 @@ static int gpio_sam_config_pin(Pio * const pio, u32_t mask, int flags) pio->PIO_LSR = mask; } - if (flags & GPIO_INT_ACTIVE_HIGH) { + if (flags & GPIO_INT_HIGH) { /* Set to high-level or rising edge. */ pio->PIO_REHLSR = mask; } else { @@ -116,11 +153,11 @@ static int gpio_sam_config(struct device *dev, int access_op, u32_t pin, switch (access_op) { case GPIO_ACCESS_BY_PIN: - gpio_sam_config_pin(pio, BIT(pin), flags); + gpio_sam_config_pin(dev, pio, BIT(pin), flags); break; case GPIO_ACCESS_BY_PORT: for (i = 0; i < 32; i++) { - result = gpio_sam_config_pin(pio, BIT(i), flags); + result = gpio_sam_config_pin(dev, pio, BIT(i), flags); if (result < 0) { return result; } @@ -137,11 +174,15 @@ static int gpio_sam_write(struct device *dev, int access_op, u32_t pin, u32_t value) { const struct gpio_sam_config * const cfg = DEV_CFG(dev); + struct gpio_sam_runtime *const dev_data = DEV_DATA(dev); Pio *const pio = cfg->regs; u32_t mask = 1 << pin; switch (access_op) { case GPIO_ACCESS_BY_PIN: + if (dev_data->invert & mask) { + value = !value; + } if (value) { /* Set the pin. */ pio->PIO_SODR = mask; @@ -152,7 +193,7 @@ static int gpio_sam_write(struct device *dev, int access_op, u32_t pin, break; case GPIO_ACCESS_BY_PORT: pio->PIO_OWER = pio->PIO_OSR; /* Write those out pin only */ - pio->PIO_ODSR = value; + pio->PIO_ODSR = value ^ dev_data->invert; pio->PIO_OWDR = 0xffffffff; /* Disable write ODSR */ break; default: @@ -166,9 +207,11 @@ static int gpio_sam_read(struct device *dev, int access_op, u32_t pin, u32_t *value) { const struct gpio_sam_config * const cfg = DEV_CFG(dev); + struct gpio_sam_runtime *const dev_data = DEV_DATA(dev); Pio *const pio = cfg->regs; *value = pio->PIO_PDSR; + *value ^= dev_data->invert; switch (access_op) { case GPIO_ACCESS_BY_PIN: diff --git a/include/dt-bindings/gpio/gpio.h b/include/dt-bindings/gpio/gpio.h index c365d449e347b..a6c2be4159181 100644 --- a/include/dt-bindings/gpio/gpio.h +++ b/include/dt-bindings/gpio/gpio.h @@ -6,107 +6,155 @@ #ifndef ZEPHYR_INCLUDE_DT_BINDINGS_GPIO_GPIO_H_ #define ZEPHYR_INCLUDE_DT_BINDINGS_GPIO_GPIO_H_ - -/** - * @name GPIO direction flags - * The `GPIO_DIR_*` flags are used with `gpio_pin_configure` or `gpio_port_configure`, - * to specify whether a GPIO pin will be used for input or output. - * @{ +/** GPIO pin is active (has logical value '1') in low state. */ +#define GPIO_ACTIVE_LOW (1 << 0) +/** GPIO pin is active (has logical value '1') in high state. */ +#define GPIO_ACTIVE_HIGH (0 << 0) + +/** Configures GPIO output in single-ended mode (open drain or open source). */ +#define GPIO_SINGLE_ENDED (1 << 1) +/** Configures GPIO output in push-pull mode */ +#define GPIO_PUSH_PULL (0 << 1) + +/** Indicates single ended open drain mode (wired AND). */ +#define GPIO_LINE_OPEN_DRAIN (1 << 2) +/** Indicates single ended open source mode (wired OR). */ +#define GPIO_LINE_OPEN_SOURCE (0 << 2) + +/** Configures GPIO output in open drain mode (wired AND). + * + * @note 'Open Drain' mode also known as 'Open Collector' is an output + * configuration which behaves like a switch that is either connected to ground + * or disconnected. */ -/** GPIO pin to be input. */ -#define GPIO_DIR_IN (0 << 0) - -/** GPIO pin to be output. */ -#define GPIO_DIR_OUT (1 << 0) - -/** @cond INTERNAL_HIDDEN */ -#define GPIO_DIR_MASK 0x1 -/** @endcond */ -/** @} */ - - -/** - * @name GPIO interrupt flags - * The `GPIO_INT_*` flags are used with `gpio_pin_configure` or `gpio_port_configure`, - * to specify how input GPIO pins will trigger interrupts. - * @{ +#define GPIO_OPEN_DRAIN (GPIO_SINGLE_ENDED | GPIO_LINE_OPEN_DRAIN) +/** Configures GPIO output in open source mode (wired OR). + * + * @note 'Open Source' is a term used by software engineers to describe output + * mode opposite to 'Open Drain'. It has no corresponding hardware schematic + * and is generally not used by hardware engineers. */ -/** GPIO pin to trigger interrupt. */ -#define GPIO_INT (1 << 1) - -/** GPIO pin trigger on level low or falling edge. */ -#define GPIO_INT_ACTIVE_LOW (0 << 2) +#define GPIO_OPEN_SOURCE (GPIO_SINGLE_ENDED | GPIO_LINE_OPEN_SOURCE) -/** GPIO pin trigger on level high or rising edge. */ -#define GPIO_INT_ACTIVE_HIGH (1 << 2) +/** Enables pin as input. */ +#define GPIO_INPUT_ENABLE (1 << 3) +/** Disables pin as input. */ +#define GPIO_INPUT_DISABLE (0 << 3) -/** Enable GPIO pin debounce. */ -#define GPIO_INT_DEBOUNCE (1 << 4) +/** Enables pin as output (no change to the output state). */ +#define GPIO_OUTPUT_ENABLE (1 << 4) +/** Disables pin as output. */ +#define GPIO_OUTPUT_DISABLE (0 << 4) -/** Do Level trigger. */ -#define GPIO_INT_LEVEL (0 << 5) +/** Initializes output to a low state. */ +#define GPIO_OUTPUT_INIT_LOW (1 << 5) -/** Do Edge trigger. */ -#define GPIO_INT_EDGE (1 << 5) +/** Initializes output to a high state. */ +#define GPIO_OUTPUT_INIT_HIGH (1 << 6) -/** Interrupt triggers on both rising and falling edge. - * Must be combined with GPIO_INT_EDGE. - */ -#define GPIO_INT_DOUBLE_EDGE (1 << 6) -/** @} */ +/** Configures GPIO pin as output and initializes it to a low state. */ +#define GPIO_OUTPUT_LOW (GPIO_OUTPUT_ENABLE | GPIO_OUTPUT_INIT_LOW) +/** Configures GPIO pin as output and initializes it to a high state. */ +#define GPIO_OUTPUT_HIGH (GPIO_OUTPUT_ENABLE | GPIO_OUTPUT_INIT_HIGH) +/** Enables GPIO pin debounce. */ +#define GPIO_INPUT_DEBOUNCE (1 << 7) /** - * @name GPIO polarity flags - * The `GPIO_POL_*` flags are used with `gpio_pin_configure` or `gpio_port_configure`, - * to specify the polarity of a GPIO pin. + * @name GPIO interrupt flags. + * The `GPIO_INT_*` flags are used to specify how input GPIO pins will trigger + * interrupts. * @{ */ -/** @cond INTERNAL_HIDDEN */ -#define GPIO_POL_POS 7 -/** @endcond */ +/** Enables GPIO pin interrupt. + * + * This is a component flag that should be combined with other + * `GPIO_INT_*` flags to produce a meaningful configuration. + */ +#define GPIO_INT_ENABLE (1 << 8) -/** GPIO pin polarity is normal. */ -#define GPIO_POL_NORMAL (0 << GPIO_POL_POS) +/** GPIO interrupt is level sensitive. + * + * This is a component flag that should be combined with other + * `GPIO_INT_*` flags to produce a meaningful configuration. + */ +#define GPIO_INT_LEVEL (0 << 9) -/** GPIO pin polarity is inverted. */ -#define GPIO_POL_INV (1 << GPIO_POL_POS) +/** GPIO interrupt is edge sensitive. + * + * This is a component flag that should be combined with other + * `GPIO_INT_*` flags to produce a meaningful configuration. + */ +#define GPIO_INT_EDGE (1 << 9) -/** @cond INTERNAL_HIDDEN */ -#define GPIO_POL_MASK (1 << GPIO_POL_POS) -/** @endcond */ -/** @} */ +/** Trigger detection when input state is (or transitions to) low. + * + * This is a component flag that should be combined with other + * `GPIO_INT_*` flags to produce a meaningful configuration. + */ +#define GPIO_INT_LOW (1 << 10) +/** Trigger detection on input state is (or transitions to) high. + * + * This is a component flag that should be combined with other + * `GPIO_INT_*` flags to produce a meaningful configuration. + */ +#define GPIO_INT_HIGH (1 << 11) + +/** Trigger GPIO pin interrupt on rising edge. */ +#define GPIO_INT_EDGE_RISING (GPIO_INT_ENABLE \ + | GPIO_INT_EDGE \ + | GPIO_INT_HIGH) + +/** Trigger GPIO pin interrupt on falling edge. */ +#define GPIO_INT_EDGE_FALLING (GPIO_INT_ENABLE \ + | GPIO_INT_EDGE \ + | GPIO_INT_LOW) + +/** Trigger GPIO pin interrupt on rising or falling edge. */ +#define GPIO_INT_EDGE_BOTH (GPIO_INT_ENABLE \ + | GPIO_INT_EDGE \ + | GPIO_INT_LOW \ + | GPIO_INT_HIGH) + +/** Trigger GPIO pin interrupt on level low. */ +#define GPIO_INT_LEVEL_LOW (GPIO_INT_ENABLE \ + | GPIO_INT_LEVEL \ + | GPIO_INT_LOW) + +/** Trigger GPIO pin interrupt on level high. */ +#define GPIO_INT_LEVEL_HIGH (GPIO_INT_ENABLE \ + | GPIO_INT_LEVEL \ + | GPIO_INT_HIGH) + +/** @} */ /** - * @name GPIO pull flags - * The `GPIO_PUD_*` flags are used with `gpio_pin_configure` or `gpio_port_configure`, - * to specify the pull-up or pull-down electrical configuration of a GPIO pin. + * @name GPIO pull flags. + * The `GPIO_PUD_*` flags are used to specify the pull-up or pull-down + * electrical configuration of a GPIO pin. * @{ */ /** @cond INTERNAL_HIDDEN */ -#define GPIO_PUD_POS 8 +#define GPIO_PUD_SHIFT 12 +#define GPIO_PUD_MASK (0x3 << GPIO_PUD_SHIFT) /** @endcond */ /** Pin is neither pull-up nor pull-down. */ -#define GPIO_PUD_NORMAL (0 << GPIO_PUD_POS) +#define GPIO_PUD_NORMAL (0 << GPIO_PUD_SHIFT) /** Enable GPIO pin pull-up. */ -#define GPIO_PUD_PULL_UP (1 << GPIO_PUD_POS) +#define GPIO_PUD_PULL_UP (1 << GPIO_PUD_SHIFT) /** Enable GPIO pin pull-down. */ -#define GPIO_PUD_PULL_DOWN (2 << GPIO_PUD_POS) - -/** @cond INTERNAL_HIDDEN */ -#define GPIO_PUD_MASK (3 << GPIO_PUD_POS) -/** @endcond */ +#define GPIO_PUD_PULL_DOWN (2 << GPIO_PUD_SHIFT) /** @} */ /** - * @name GPIO drive strength flags - * The `GPIO_DS_*` flags are used with `gpio_pin_configure` or `gpio_port_configure`, - * to specify the drive strength configuration of a GPIO pin. + * @name GPIO drive strength flags. + * The `GPIO_DS_*` flags are used to specify the drive strength configuration of + * a GPIO pin. * * The drive strength of individual pins can be configured * independently for when the pin output is low and high. @@ -117,10 +165,6 @@ * The `GPIO_DS_*_HIGH` enumerations define the drive strength of a pin * when output is high. * - * The `DISCONNECT` drive strength indicates that the pin is placed in a - * high impedance state and not driven, this option is used to - * configure hardware that supports a open collector drive mode. - * * The interface supports two different drive strengths: * `DFLT` - The lowest drive strength supported by the HW * `ALT` - The highest drive strength supported by the HW @@ -133,48 +177,148 @@ * @{ */ /** @cond INTERNAL_HIDDEN */ -#define GPIO_DS_LOW_POS 12 -#define GPIO_DS_LOW_MASK (0x3 << GPIO_DS_LOW_POS) +#define GPIO_DS_LOW_SHIFT 14 +#define GPIO_DS_LOW_MASK (0x3 << GPIO_DS_LOW_SHIFT) /** @endcond */ -/** Default drive strength standard when GPIO pin output is low. - */ -#define GPIO_DS_DFLT_LOW (0x0 << GPIO_DS_LOW_POS) +/** Use default drive strength when GPIO pin output is low. */ +#define GPIO_DS_DFLT_LOW (0 << GPIO_DS_LOW_SHIFT) -/** Alternative drive strength when GPIO pin output is low. - * For hardware that does not support configurable drive strength - * use the default drive strength. - */ -#define GPIO_DS_ALT_LOW (0x1 << GPIO_DS_LOW_POS) +/** Use low/reduced drive strength when GPIO pin output is low. */ +#define GPIO_DS_LO_LOW (1 << GPIO_DS_LOW_SHIFT) + +/** Use high/increased drive strength when GPIO pin output is low. */ +#define GPIO_DS_HI_LOW (2 << GPIO_DS_LOW_SHIFT) + +/** @cond INTERNAL_HIDDEN */ +#define GPIO_DS_HIGH_SHIFT 16 +#define GPIO_DS_HIGH_MASK (0x3 << GPIO_DS_HIGH_SHIFT) +/** @endcond */ + +/** Use default drive strength when GPIO pin output is high. */ +#define GPIO_DS_DFLT_HIGH (0 << GPIO_DS_HIGH_SHIFT) -/** Disconnect pin when GPIO pin output is low. - * For hardware that does not support disconnect use the default - * drive strength. +/** Use low/reduced drive strength when GPIO pin output is high. */ +#define GPIO_DS_LO_HIGH (1 << GPIO_DS_HIGH_SHIFT) + +/** Use high/increased drive strength when GPIO pin output is high. */ +#define GPIO_DS_HI_HIGH (2 << GPIO_DS_HIGH_SHIFT) +/** @} */ + +/** @name Deprecated Flags. + * + * These flags were defined at a time when the characteristic they + * identified was assumed to be relevant only for interrupts. The + * features are also useful for non-interrupt inputs and in some cases + * for outputs. + * + * @{ */ -#define GPIO_DS_DISCONNECT_LOW (0x3 << GPIO_DS_LOW_POS) /** @cond INTERNAL_HIDDEN */ -#define GPIO_DS_HIGH_POS 14 -#define GPIO_DS_HIGH_MASK (0x3 << GPIO_DS_HIGH_POS) +#define GPIO_DIR_SHIFT 3 +#define GPIO_DIR_MASK (0x3 << GPIO_DIR_SHIFT) /** @endcond */ -/** Default drive strength when GPIO pin output is high. +/** Legacy flag indicating pin is configured as input only. + * + * @deprecated Replace with `GPIO_INPUT_ENABLE` */ -#define GPIO_DS_DFLT_HIGH (0x0 << GPIO_DS_HIGH_POS) +#define GPIO_DIR_IN GPIO_INPUT_ENABLE -/** Alternative drive strength when GPIO pin output is high. - * For hardware that does not support configurable drive strengths - * use the default drive strength. +/** Legacy flag indicating pin is configured as output. + * + * @deprecated Replace with `GPIO_OUTPUT_ENABLE` */ -#define GPIO_DS_ALT_HIGH (0x1 << GPIO_DS_HIGH_POS) +#define GPIO_DIR_OUT GPIO_OUTPUT_ENABLE -/** Disconnect pin when GPIO pin output is high. - * For hardware that does not support disconnect use the default - * drive strength. +/** Legacy alias identifying high drive strength when GPIO output is low. + * + * @deprecated Replace with `GPIO_DS_HI_LOW` */ -#define GPIO_DS_DISCONNECT_HIGH (0x3 << GPIO_DS_HIGH_POS) -/** @} */ +#define GPIO_DS_ALT_LOW GPIO_DS_HI_LOW +/** Legacy flag indicating pin is disconnected when GPIO pin output is low. + * + * @deprecated Replace with `GPIO_OPEN_SOURCE` + */ +#define GPIO_DS_DISCONNECT_LOW (0x3 << GPIO_DS_LOW_SHIFT) +/** Legacy alias identifying high drive strength when GPIO output is high. + * + * @deprecated Replace with `GPIO_DS_HI_HIGH` + */ +#define GPIO_DS_ALT_HIGH GPIO_DS_HI_HIGH + +/** Legacy flag indicating pin is disconnected when GPIO pin output is high. + * + * @deprecated Replace with `GPIO_OPEN_DRAIN` + */ +#define GPIO_DS_DISCONNECT_HIGH (0x3 << GPIO_DS_HIGH_SHIFT) + +/** Legacy flag indicating that interrupts should be enabled on the GPIO. + * + * @deprecated Replace with `GPIO_INT_ENABLE` + */ +#define GPIO_INT GPIO_INT_ENABLE + +/** Legacy flag setting indicating signal or interrupt active level. + * + * This flag was used both to indicate a signal's active level, and to + * indicate the level associated with an interrupt on a signal. As + * active level is also relevant to output signals the two + * interpretations have been separated. The legacy value supports + * testing for interrupt level as this is the most common use in + * existing code. + * + * @deprecated Replace with `GPIO_ACTIVE_LOW` or `GPIO_INT_LOW` + * depending on intent. + */ +#define GPIO_INT_ACTIVE_LOW GPIO_INT_LOW + +/** Legacy flag setting indicating signal or interrupt active level. + * + * This flag was used both to indicate a signal's active level, and to + * indicate the level associated with an interrupt on a signal. As + * active level is also relevant to output signals the two + * interpretations have been separated. The legacy value supports + * testing for interrupt level as this is the most common use in + * existing code. + * + * @deprecated Replace with `GPIO_ACTIVE_HIGH` or `GPIO_INT_HIGH` + * depending on intent. + */ +#define GPIO_INT_ACTIVE_HIGH GPIO_INT_HIGH + +/** Legacy flag indicating interrupt triggers on both rising and falling edge. + * + * @deprecated Replace with `GPIO_INT_EDGE_BOTH`. + */ +#define GPIO_INT_DOUBLE_EDGE (1 << 18) + +/** Legacy flag indicating a desire to debounce the signal. + * + * @deprecated Replace with `GPIO_INPUT_DEBOUNCE` + */ +#define GPIO_INT_DEBOUNCE GPIO_INPUT_DEBOUNCE + +/** @cond INTERNAL_HIDDEN */ +#define GPIO_POL_SHIFT 19 +#define GPIO_POL_MASK (1 << GPIO_POL_SHIFT) +/** @endcond */ + +/** Legacy flag indicating that GPIO pin polarity is normal. + * + * @deprecated Replace with `GPIO_ACTIVE_HIGH`. + */ +#define GPIO_POL_NORMAL (0 << GPIO_POL_SHIFT) + +/** Legacy flag indicating that GPIO pin polarity is inverted. + * + * @deprecated Replace with `GPIO_ACTIVE_LOW`. + */ +#define GPIO_POL_INV (1 << GPIO_POL_SHIFT) + +/** @} */ #endif /* ZEPHYR_INCLUDE_DT_BINDINGS_GPIO_GPIO_H_ */ diff --git a/include/gpio.h b/include/gpio.h index f5ca16967aa95..d2020e9170f23 100644 --- a/include/gpio.h +++ b/include/gpio.h @@ -202,6 +202,12 @@ static inline int gpio_pin_configure(struct device *port, u32_t pin, /** * @brief Write the data value to a single pin. + * + * Write logical data value to a pin, taking into account GPIO_ACTIVE_LOW flag. + * If an output was configured as Active Low, writing value 1 to a pin will set + * it to low output state. Otherwise writing value 1 to a pin will set it to + * high output state. + * * @param port Pointer to the device structure for the driver instance. * @param pin Pin number where the data is written. * @param value Value set on the pin. @@ -216,7 +222,8 @@ static inline int gpio_pin_write(struct device *port, u32_t pin, /** * @brief Read the data value of a single pin. * - * Read the input state of a pin, returning the value 0 or 1. + * Read the logical value of a pin, returning 0 or 1. The function takes into + * account GPIO_ACTIVE_LOW flag. * * @param port Pointer to the device structure for the driver instance. * @param pin Pin number where data is read. diff --git a/samples/basic/blinky/src/main.c b/samples/basic/blinky/src/main.c index 2ca87c2319747..ea72dadbebcfd 100644 --- a/samples/basic/blinky/src/main.c +++ b/samples/basic/blinky/src/main.c @@ -8,8 +8,9 @@ #include #include -#define LED_PORT LED0_GPIO_CONTROLLER -#define LED LED0_GPIO_PIN +#define LED_PORT LED0_GPIO_CONTROLLER +#define LED_PIN LED0_GPIO_PIN +#define LED_FLAGS LED0_GPIO_FLAGS /* 1000 msec = 1 sec */ #define SLEEP_TIME 1000 @@ -21,11 +22,11 @@ void main(void) dev = device_get_binding(LED_PORT); /* Set LED pin as output */ - gpio_pin_configure(dev, LED, GPIO_DIR_OUT); + gpio_pin_configure(dev, LED_PIN, GPIO_DIR_OUT | LED_FLAGS); while (1) { /* Set pin to HIGH/LOW every 1 second */ - gpio_pin_write(dev, LED, cnt % 2); + gpio_pin_write(dev, LED_PIN, cnt % 2); cnt++; k_sleep(SLEEP_TIME); }