#ifndef KERN_GPIO_GPIO_MANAGE_H_ #define KERN_GPIO_GPIO_MANAGE_H_ #include "arch/stm32l4xxx/peripherals/gpio.h" #include "kern/common.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_ 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_INPUT, .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); /* * Returns whether the GPIO pin has high or low input. */ bool get_gpio_pin_input_state(gpio_reserved_pin_t pin); #endif /* KERN_GPIO_GPIO_MANAGE_H_ */