aboutsummaryrefslogtreecommitdiff
path: root/include/kern/gpio/gpio_manager.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/kern/gpio/gpio_manager.h')
-rw-r--r--include/kern/gpio/gpio_manager.h187
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_ */