Reorganized and extended the gpio peripheral API

pull/273/head
Silvano Seva 2024-05-25 16:09:18 +02:00
rodzic 695210d689
commit e53e110a3b
1 zmienionych plików z 184 dodań i 55 usunięć

Wyświetl plik

@ -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 <stdint.h>
#include <stdbool.h>
#include <gpio-native.h>
#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
}