From e53e110a3b8d71355ded8e6af5a6622c07da76b0 Mon Sep 17 00:00:00 2001 From: Silvano Seva Date: Sat, 25 May 2024 16:09:18 +0200 Subject: [PATCH] Reorganized and extended the gpio peripheral API --- openrtx/include/peripherals/gpio.h | 239 ++++++++++++++++++++++------- 1 file changed, 184 insertions(+), 55 deletions(-) diff --git a/openrtx/include/peripherals/gpio.h b/openrtx/include/peripherals/gpio.h index 36340144..7a984c4c 100644 --- a/openrtx/include/peripherals/gpio.h +++ b/openrtx/include/peripherals/gpio.h @@ -1,5 +1,5 @@ /*************************************************************************** - * Copyright (C) 2020 - 2023 by Silvano Seva IU2KWO * + * Copyright (C) 2020 - 2024 by Silvano Seva IU2KWO * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * @@ -19,96 +19,225 @@ #define GPIO_H #include +#include +#include #ifdef __cplusplus extern "C" { #endif /** - * GPIO functional modes. - * For more details see microcontroller's reference manual. + * This file provides the common interface for gpio management. Two interfaces + * are available: + * + * 1) gpioDev interface, designed to be common to all the architectures and + * devices but, due to this, slow. + * 2) gpio interface, available only for MCUs, dependent on the underlying + * architecture and device and faster than gpioDev. + * + * MCU gpio interface consists of the following functions, which have to be + * defined in gpio-native.h: + * + * void gpio_setMode(void *port, const uint8_t pin, const uint16_t mode); + * void gpio_setPin(void *port, const uint8_t pin); + * void gpio_clearPin(void *port, const uint8_t pin); + * uint8_t gpio_readPin(const void *port, const uint8_t pin); + * + * Usage and parameters are identical to their gpioDev counterparts. + */ + +/** + * gpio functional modes. + * For more details see the documentation of the gpio peripheral. */ enum Mode { - INPUT = 0, ///Floating Input - INPUT_PULL_UP = 1, ///Pullup Input - INPUT_PULL_DOWN = 2, ///Pulldown Input - INPUT_ANALOG = 3, ///Analog Input - OUTPUT = 4, ///Push Pull Output - OPEN_DRAIN = 5, ///Open Drain Output - ALTERNATE = 6, ///Alternate function - ALTERNATE_OD = 7, ///Alternate Open Drain + INPUT = 0, ///< Input, floating + INPUT_PULL_UP = 1, ///< Input, with pull-up + INPUT_PULL_DOWN = 2, ///< Input, with pull-down + ANALOG = 3, ///< Analog + OUTPUT = 4, ///< Output, push pull + OPEN_DRAIN = 5, ///< Output, open drain + OPEN_DRAIN_PU = 6, ///< Output, open drain with pull-up + ALTERNATE = 7, ///< Alternate function + ALTERNATE_OD = 8, ///< Alternate function, open drain + ALTERNATE_OD_PU = 9 ///< Alternate function, open drain with pull-up }; /** - * Maximum GPIO switching speed. - * For more details see microcontroller's reference manual and datasheet. + * Helper macro to set gpio alternate function number. */ -enum Speed +#define ALTERNATE_FUNC(x) (x << 8) + +struct gpioDev; + +/** + * Gpio device driver API. + */ +struct gpioApi { - LOW = 0x0, /// 2MHz for STM32 - MEDIUM = 0x1, /// 25MHz for STM32 - FAST = 0x2, /// 50MHz for STM32 - HIGH = 0x3 /// 100MHz for STM32 + /** + * Configure gpio pin functional mode. + * + * @param port: device handling the gpio port. + * @param pin: gpio pin number. + * @param mode: bit 7:0 set gpio functional mode, bit 15:8 manage gpio alternate + * function mapping. + * @return zero on success, a negative error code otherwise. + */ + int (*mode)(const struct gpioDev *dev, const uint8_t pin, const uint16_t mode); + + /** + * Set gpio pin to logic high level. + * NOTE: this function does not guarantee that the operation is performed atomically. + * + * @param port: device handling the gpio port. + * @param pin: gpio pin number. + */ + void (*set)(const struct gpioDev *dev, const uint8_t pin); + + /** + * Set gpio pin to logic low level. + * NOTE: this function does not guarantee that the operation is performed atomically. + * + * @param port: device handling the gpio port. + * @param pin: gpio pin number. + */ + void (*clear)(const struct gpioDev *dev, const uint8_t pin); + + /** + * Read gpio pin's logic level. + * + * @param port: device handling the gpio port. + * @param pin: gpio pin number. + * @return true if pin is at high logic level, 0 if pin is at low logic level. + */ + bool (*read)(const struct gpioDev *dev, const uint8_t pin); }; /** - * Configure GPIO pin functional mode. - * @param port: GPIO port, it has to be equal to GPIOA_BASE, GPIOB_BASE, ... - * @param pin: GPIO pin number, between 0 and 15. - * @param mode: GPIO functional mode to be set. + * Gpio device descriptor. */ -void gpio_setMode(void *port, uint8_t pin, enum Mode mode); +struct gpioDev +{ + const struct gpioApi *api; ///< Pointer to device driver API + const void *priv; ///< Pointer to device data +}; /** - * Map alternate function to GPIO pin. The pin has to be configured in alternate - * mode by calling 'gpio_setMode'. - * @param port: GPIO port, it has to be equal to GPIOA_BASE, GPIOB_BASE, ... - * @param pin: GPIO pin number, between 0 and 15. - * @param afNum: alternate function number, retrieved from mapping table in - * microcontroller's datasheet. + * Gpio pin descriptor, general form. */ -void gpio_setAlternateFunction(void *port, uint8_t pin, uint8_t afNum); +struct gpioPin +{ + const struct gpioDev *port; ///< Pointer to the gpio device + const uint8_t pin; ///< Gpio pin number +}; /** - * Configure GPIO pin maximum output speed. - * @param port: GPIO port, it has to be equal to GPIOA_BASE, GPIOB_BASE, ... - * @param pin: GPIO pin number, between 0 and 15. - * @param spd: GPIO output speed to be set. + * Gpio pin descriptor, for native MCU gpios. */ -void gpio_setOutputSpeed(void *port, uint8_t pin, enum Speed spd); +struct gpio +{ + const void *port; ///< Pointer to gpio port + const uint8_t pin; ///< Gpio pin number +}; /** - * Set GPIO pin to high logic level. - * NOTE: this operation is performed atomically. - * @param port: GPIO port, it has to be equal to GPIOA_BASE, GPIOB_BASE, ... - * @param pin: GPIO pin number, between 0 and 15. + * Configure gpio pin functional mode. + * + * @param port: device handling the gpio port. + * @param pin: gpio pin number. + * @param mode: bit 7:0 set gpio functional mode, bit 15:8 manage gpio alternate + * function mapping. + * @return zero on success, a negative error code otherwise. */ -void gpio_setPin(void *port, uint8_t pin); +static inline int gpioDev_setMode(const struct gpioDev *port, const uint8_t pin, + const uint16_t mode) +{ + return port->api->mode(port, pin, mode); +} /** - * Set GPIO pin to low logic level. - * NOTE: this operation is performed atomically. - * @param port: GPIO port, it has to be equal to GPIOA_BASE, GPIOB_BASE, ... - * @param pin: GPIO pin number, between 0 and 15. + * Set gpio pin to logic high level. + * NOTE: this function does not guarantee that the operation is performed atomically. + * + * @param port: device handling the gpio port. + * @param pin: gpio pin number. */ -void gpio_clearPin(void *port, uint8_t pin); +static inline void gpioDev_set(const struct gpioDev *port, const uint8_t pin) +{ + port->api->set(port, pin); +} /** - * Toggle logic level of a GPIO pin, with respect to its state before calling - * this function. - * @param port: GPIO port, it has to be equal to GPIOA_BASE, GPIOB_BASE, ... - * @param pin: GPIO pin number, between 0 and 15. + * Set gpio pin to logic low level. + * NOTE: this function does not guarantee that the operation is performed atomically. + * + * @param port: device handling the gpio port. + * @param pin: gpio pin number. */ -void gpio_togglePin(void *port, uint8_t pin); +static inline void gpioDev_clear(const struct gpioDev *port, const uint8_t pin) +{ + port->api->clear(port, pin); +} /** - * Read GPIO pin's logic level. - * @param port: GPIO port, it has to be equal to GPIOA_BASE, GPIOB_BASE, ... - * @param pin: GPIO pin number, between 0 and 15. - * @return 1 if pin is at high logic level, 0 if pin is at low logic level. + * Read gpio pin's logic level. + * + * @param port: device handling the gpio port. + * @param pin: gpio pin number. + * @return true if pin is at high logic level, 0 if pin is at low logic level. */ -uint8_t gpio_readPin(const void *port, uint8_t pin); +static inline bool gpioDev_read(const struct gpioDev *port, const uint8_t pin) +{ + return port->api->read(port, pin); +} + +/** + * Configure gpio pin functional mode. + * + * @param gpio: pointer to GPIO pin descriptor. + * @param mode: bit 7:0 set gpio functional mode, bit 15:8 manage gpio alternate + * function mapping. + * @return zero on success, a negative error code otherwise. + */ +static inline int gpioPin_setMode(const struct gpioPin *gpio, const uint16_t mode) +{ + return gpio->port->api->mode(gpio->port, gpio->pin, mode); +} + +/** + * Set gpio pin to logic high level. + * NOTE: this function does not guarantee that the operation is performed atomically. + * + * @param gpio: pointer to GPIO pin descriptor. + */ +static inline void gpioPin_set(const struct gpioPin *gpio) +{ + gpio->port->api->set(gpio->port, gpio->pin); +} + +/** + * Set gpio pin to logic low level. + * NOTE: this function does not guarantee that the operation is performed atomically. + * + * @param gpio: pointer to GPIO pin descriptor. + */ +static inline void gpioPin_clear(const struct gpioPin *gpio) +{ + gpio->port->api->clear(gpio->port, gpio->pin); +} + +/** + * Read gpio pin's logic level. + * + * @param gpio: pointer to GPIO pin descriptor. + * @return true if pin is at high logic level, 0 if pin is at low logic level. + */ +static inline bool gpioPin_read(const struct gpioPin *gpio) +{ + return gpio->port->api->read(gpio->port, gpio->pin); +} #ifdef __cplusplus }