diff options
Diffstat (limited to 'include/kern/gpio/gpio_manager.h')
-rw-r--r-- | include/kern/gpio/gpio_manager.h | 187 |
1 files changed, 187 insertions, 0 deletions
diff --git a/include/kern/gpio/gpio_manager.h b/include/kern/gpio/gpio_manager.h new file mode 100644 index 0000000..922a423 --- /dev/null +++ b/include/kern/gpio/gpio_manager.h @@ -0,0 +1,187 @@ +#ifndef KERN_GPIO_GPIO_MANAGE_H_ +#define KERN_GPIO_GPIO_MANAGE_H_ + +#include "kern/common.h" +#include "arch/stm32l4xxx/peripherals/gpio.h" + +#define GPIO_ERROR_IN_USE 1 +#define GPIO_ERROR_INVALID_PIN_FOR_ALTERNATE_FUNCTION 2 +#define GPIO_ERROR_INVALID_PIN 3 + +typedef enum { +/* Creates vaules GPIO_PIN_<port><num> i.e. GPIO_PIN_A0 */ +#define PORT(p, pn) \ + GPIO_PIN_P ## p ## pn, +#include "arch/stm32l4xxx/peripherals/tables/stm32l432xx/gpio/port_table.inc" +#undef PORT + + N_GPIO_PINS +} gpio_pin_t; + +/* Alternate functions. */ +typedef enum { +#define AFN(fn, ...) \ + GPIO_ALTERNATE_FUNCTION_ ## fn, +#include "arch/stm32l4xxx/peripherals/tables/stm32l432xx/gpio/afn_table.inc" +#undef AFN + GPIO_ALTERNATE_FUNCTION_EVENTOUT, +} gpio_alternate_function_t; + +#define gpio_pin_for_alternate_function(af) ((af) / 16) +#define gpio_pin_out_of_range(pin) \ + ((pin) < 0 || (pin) >= N_GPIO_PINS) + +typedef enum { + GPIO_PORT_A, + GPIO_PORT_B, + GPIO_PORT_C, + GPIO_PORT_D, + GPIO_PORT_E, + GPIO_PORT_F, + GPIO_PORT_G, + GPIO_PORT_H, + GPIO_PORT_I, + + N_GPIO_PORTS, +} gpio_port_t; + +typedef enum { + GPIO_MODE_INPUT, + GPIO_MODE_OUTPUT, + GPIO_MODE_ALTERNATE, + GPIO_MODE_ANALOG +} gpio_mode_t; + +/* + * Enum defining the pin speeds that are possible. + */ +typedef enum { + SPEED_2MHZ = 0, + SPEED_10MHZ = 1, + SPEED_50MHZ = 3, +} gpio_speed_t; + +typedef enum { + GPIO_OUTPUT_TYPE_PUSH_PULL, + GPIO_OUTPUT_TYPE_OPEN_DRAIN +} gpio_output_type_t; + +typedef enum { + GPIO_OUTPUT_SPEED_LOW, + GPIO_OUTPUT_SPEED_MEDIUM, + GPIO_OUTPUT_SPEED_HIGH, + GPIO_OUTPUT_SPEED_VERY_HIGH, +} gpio_output_speed_t; + +typedef enum { + GPIO_PULL_DIR_NONE, + GPIO_PULL_DIR_UP, + GPIO_PULL_DIR_DOWN, +} gpio_pull_dir_t; + +/* Returns the appropriate gpio_port for the provided pin. */ +inline static gpio_port_t get_port_for_pin(gpio_pin_t pin) +{ + switch (pin) { +#define PORT(p, pn) \ + case GPIO_PIN_P ## p ## pn: return GPIO_PORT_ ## p; +#include "arch/stm32l4xxx/peripherals/tables/stm32l432xx/gpio/port_table.inc" +#undef PORT + case N_GPIO_PINS: return N_GPIO_PORTS; + } + + /* Should be unreachable. */ +} + +#define DEFAULT_GPIO_OPTS_OUTPUT \ + (gpio_pin_opts_t) { \ + .mode = GPIO_MODE_OUTPUT, \ + .pull_dir = GPIO_PULL_DIR_DOWN, \ + .output_opts.speed = GPIO_OUTPUT_SPEED_MEDIUM, \ + .output_opts.type = GPIO_OUTPUT_TYPE_PUSH_PULL, \ + } + +#define DEFAULT_GPIO_OPTS_INPUT \ + (gpio_pin_opts_t) { \ + .mode = GPIO_MODE_OUTPUT, \ + .pull_dir = GPIO_PULL_DIR_DOWN, \ + } + +typedef struct { + gpio_mode_t mode; + gpio_pull_dir_t pull_dir; + + union { + struct { + } input_opts; + + struct { + gpio_output_speed_t speed; + gpio_output_type_t type; + } output_opts; + + struct { + uint8_t function; + } alternate_opts; + + struct { + } analog_opts; + }; +} gpio_pin_opts_t; + +/* Differentiates at compile-time from the a gpio_pin_t enum value and a pin + * that's been reserved. */ +typedef struct { + gpio_pin_t v_; +} gpio_reserved_pin_t; + +/* Returns a pointer to the GPIO pin bus and offset. This is useful for when + * raw access to the values are needed. I.e. time critical applications. */ +void get_gpio_pin_port_off( + gpio_pin_t pin, gpio_port_config_t** out_cfg, int* out_off); + +/* Sets the given GPIO pin to high. */ +void set_gpio_pin_high(gpio_reserved_pin_t pin); + +/* Sets the given GPIO pin to low. */ +void set_gpio_pin_low(gpio_reserved_pin_t pin); + +/** returns true if a GPIO pin is in use. */ +bool gpio_pin_in_use(gpio_pin_t pin); + +/* + * Reserve the provided GPIO pin using the opts provided. + * + * sets error_out to GPIO_ERROR_IN_USE if the GPIO pin could not be reserved + * because it already has been reserved. + * + * The function will automatically enable the correct GPIO port bus. + */ +gpio_reserved_pin_t reserve_gpio_pin( + gpio_pin_t pin, gpio_pin_opts_t* opts, int* error_out); + +/* Enables and returns the pin reserved for the alternate function. + * + * If the `hint` parameter is defined (non -1) the manager will try + * to reserve that pin for the alternate function and fail if it can't. + * + * If `hint` is -1 then the first available pin for that alternate function + * will be reserved and returned. + * + * + */ +gpio_reserved_pin_t gpio_enable_alternate_function( + gpio_alternate_function_t fn, + gpio_pin_t hint, + int* error_out); + +/* + * Releases the GPIO pin so it can be reserved again in the future. + * + * The pin is reset during this process and if there are no more reserved pins + * on the corresponding port this function will disable the port. (last one out + * gets the lights.). + */ +void release_gpio_pin(gpio_reserved_pin_t gpio_pin); + +#endif /* KERN_GPIO_GPIO_MANAGE_H_ */ |