aboutsummaryrefslogtreecommitdiff
path: root/02-usart/src/kern/gpio/gpio_manager.c
diff options
context:
space:
mode:
authorJosh Rahm <joshuarahm@gmail.com>2020-11-24 13:46:41 -0700
committerJosh Rahm <joshuarahm@gmail.com>2020-11-24 13:46:41 -0700
commit93b063fedfcf7409a67df035170ea5670cad22e1 (patch)
treea23321a7465d966b1ccf196ca00e65a70c9f9110 /02-usart/src/kern/gpio/gpio_manager.c
parentb040195d31df6ad759f16ea3456471897f55daa1 (diff)
downloadstm32l4-93b063fedfcf7409a67df035170ea5670cad22e1.tar.gz
stm32l4-93b063fedfcf7409a67df035170ea5670cad22e1.tar.bz2
stm32l4-93b063fedfcf7409a67df035170ea5670cad22e1.zip
Moved action to top level.
Removed old iterations of the project and moved the files from 02-usart to the root directory since that's the sole place where the action is and that subproject has outgrown its initial title.
Diffstat (limited to '02-usart/src/kern/gpio/gpio_manager.c')
-rw-r--r--02-usart/src/kern/gpio/gpio_manager.c402
1 files changed, 0 insertions, 402 deletions
diff --git a/02-usart/src/kern/gpio/gpio_manager.c b/02-usart/src/kern/gpio/gpio_manager.c
deleted file mode 100644
index 82dd0ba..0000000
--- a/02-usart/src/kern/gpio/gpio_manager.c
+++ /dev/null
@@ -1,402 +0,0 @@
-#include "kern/gpio/gpio_manager.h"
-
-#include "arch/stm32l4xxx/peripherals/irq.h"
-#include "arch/stm32l4xxx/peripherals/rcc.h"
-
-/* A list of whether the pins are in use or not as a bitmask. */
-uint32_t pins_inuse[N_GPIO_PINS / 32 + (N_GPIO_PINS % 32 != 0)];
-
-struct gpio_afn_and_pin {
- int8_t afn_number;
- gpio_pin_t gpio_pin;
-};
-
-/*
- * Returns which (pin, afn) pairs provide the given alternate function.
- * The out array needs to have 5 positions.
- *
- * This function will use afn_number = -1 as the terminal.
- *
- * Note that EVENTOUT is a special case because all pins have an event out
- * at afn=15 and should be assumed by other logic and thus is not handled
- * by this function.
- */
-static void get_ports_and_pins_for_alternate_function(
- gpio_alternate_function_t afn, struct gpio_afn_and_pin* out)
-{
- switch (afn) {
-#define AFN1(fn, ...) \
- static_assert(false, "Unable to parse afn_table at " #fn);
-#define AFN3(fn, ...) \
- static_assert(false, "Unable to parse afn_table at " #fn);
-#define AFN5(fn, ...) \
- static_assert(false, "Unable to parse afn_table at " #fn);
-#define AFN7(fn, ...) \
- static_assert(false, "Unable to parse afn_table at " #fn);
-
-#define AFN2(fn, afn, pin) \
- out[0].afn_number = afn; \
- out[0].gpio_pin = GPIO_PIN_ ## pin
-
-#define AFN4(fn, afn0, pin0, afn1, pin1) \
- AFN2(fn, afn0, pin0); \
- out[1].afn_number = afn1; \
- out[1].gpio_pin = GPIO_PIN_ ## pin1
-
-#define AFN6(fn, afn0, pin0, afn1, pin1, afn2, pin2) \
- AFN4(fn, afn0, pin0, afn1, pin1); \
- out[2].afn_number = afn2; \
- out[2].gpio_pin = GPIO_PIN_ ## pin2
-
-#define AFN8(fn, afn0, pin0, afn1, pin1, afn2, pin2, afn3, pin3) \
- AFN6(fn, afn0, pin0, afn1, pin1, afn2, pin2); \
- out[2].afn_number = afn3; \
- out[2].gpio_pin = GPIO_PIN_ ## pin3
-
-#define GET_MACRO(_1, _2, _3, _4, _5, _6, _7, _8, NAME, ...) NAME
-#define GET_N(_1, _2, _3, _4, _5, _6, _7, _8, NAME, ...) NAME
-#define AFN(fn, ...) \
- case GPIO_ALTERNATE_FUNCTION_ ## fn: \
- GET_MACRO(__VA_ARGS__, AFN8, AFN7, AFN6, AFN5, AFN4, AFN3, AFN2, AFN1)\
- (fn, __VA_ARGS__); \
- out[GET_N(__VA_ARGS__, 4, 4, 3, 3, 2, 2, 1, 1)] = \
- (struct gpio_afn_and_pin){-1, -1}; \
- break;
-
-#include "arch/stm32l4xxx/peripherals/tables/stm32l432xx/gpio/afn_table.inc"
- case GPIO_ALTERNATE_FUNCTION_EVENTOUT:
- return;
- }
-}
-
-static inline int offset_for_gpio_pin(gpio_pin_t pin)
-{
- switch (pin) {
-#define PORT(p, pn) \
- case GPIO_PIN_P ## p ## pn: return pn;
-#include "arch/stm32l4xxx/peripherals/tables/stm32l432xx/gpio/port_table.inc"
-#undef PORT
- case N_GPIO_PINS: return -1;
- }
-
- /* Should be unreachable. */
- return -1;
-}
-
-inline bool gpio_pin_in_use(gpio_pin_t pin)
-{
- return !!(pins_inuse[pin / 32] & (1 << (pin % 32)));
-}
-
-#define A(...)
-#define B(...)
-#define C(...)
-#define D(...)
-#define E(...)
-#define F(...)
-#define G(...)
-#define H(...)
-#define I(...)
-#define SELECT_MACRO(PORT) PORT
-#define PORT(port, pin) \
- SELECT_MACRO(port)(GPIO_PIN_P ## port ## pin, pin)
-static int gc_port_a()
-{
- return 0
-#undef A
-#define A(abspin, relpin) \
- | (gpio_pin_in_use(abspin) << (relpin))
-#include "arch/stm32l4xxx/peripherals/tables/stm32l432xx/gpio/port_table.inc"
- ;
-#undef A
-#define A(...)
-}
-
-static int gc_port_b()
-{
- return 0
-#undef B
-#define B(abspin, relpin) \
- | (gpio_pin_in_use(abspin) << (relpin))
-#include "arch/stm32l4xxx/peripherals/tables/stm32l432xx/gpio/port_table.inc"
- ;
-#undef B
-#define B(...)
-}
-
-static int gc_port_c()
-{
- return 0
-#undef C
-#define C(abspin, relpin) \
- | (gpio_pin_in_use(abspin) << (relpin))
-#include "arch/stm32l4xxx/peripherals/tables/stm32l432xx/gpio/port_table.inc"
- ;
-#undef C
-#define C(...)
-}
-
-static int gc_port_d()
-{
- return 0
-#undef D
-#define D(abspin, relpin) \
- | (gpio_pin_in_use(abspin) << (relpin))
-#include "arch/stm32l4xxx/peripherals/tables/stm32l432xx/gpio/port_table.inc"
- ;
-#undef D
-#define D(...)
-}
-
-static int gc_port_e()
-{
- return 0
-#undef E
-#define E(abspin, relpin) \
- | (gpio_pin_in_use(abspin) << (relpin))
-#include "arch/stm32l4xxx/peripherals/tables/stm32l432xx/gpio/port_table.inc"
- ;
-#undef E
-#define E(...)
-}
-
-static int gc_port_f()
-{
- return 0
-#undef F
-#define F(abspin, relpin) \
- | (gpio_pin_in_use(abspin) << (relpin))
-#include "arch/stm32l4xxx/peripherals/tables/stm32l432xx/gpio/port_table.inc"
- ;
-#undef F
-#define F(...)
-}
-
-static int gc_port_g()
-{
- return 0
-#undef G
-#define G(abspin, relpin) \
- | (gpio_pin_in_use(abspin) << (relpin))
-#include "arch/stm32l4xxx/peripherals/tables/stm32l432xx/gpio/port_table.inc"
- ;
-#undef G
-#define G(...)
-}
-
-static int gc_port_h()
-{
- return 0
-#undef H
-#define H(abspin, relpin) \
- | (gpio_pin_in_use(abspin) << (relpin))
-#include "arch/stm32l4xxx/peripherals/tables/stm32l432xx/gpio/port_table.inc"
- ;
-#undef H
-#define H(...)
-}
-
-static int gc_port_i()
-{
- return 0
-#undef I
-#define I(abspin, relpin) \
- | (gpio_pin_in_use(abspin) << (relpin))
-#include "arch/stm32l4xxx/peripherals/tables/stm32l432xx/gpio/port_table.inc"
- ;
-#undef I
-#define I(...)
-}
-
-
-static inline bool gpio_pin_try_reserve(gpio_pin_t pin)
-{
- int in_use = __sync_fetch_and_or(
- &pins_inuse[pin / 32], 1 << (pin % 32));
- return !(in_use & (1 << (pin % 32)));
-}
-
-inline static gpio_port_config_t* get_gpio_port_config(gpio_port_t port)
-{
- switch(port) {
- case GPIO_PORT_A: return (gpio_port_config_t*) GPIOA_BASE;
- case GPIO_PORT_B: return (gpio_port_config_t*) GPIOB_BASE;
- case GPIO_PORT_C: return (gpio_port_config_t*) GPIOC_BASE;
- case GPIO_PORT_H: return (gpio_port_config_t*) GPIOH_BASE;
- default: return NULL;
- }
-}
-
-inline static gpio_port_config_t* get_gpio_port_config_for_pin(gpio_pin_t pin)
-{
- gpio_port_t port = get_port_for_pin(pin);
- return get_gpio_port_config(port);
-}
-
-gpio_reserved_pin_t reserve_gpio_pin(
- gpio_pin_t pin, gpio_pin_opts_t* opts, int* error_out)
-{
- *error_out = 0;
- if (!gpio_pin_try_reserve(pin)) {
- *error_out = GPIO_ERROR_IN_USE;
- return (gpio_reserved_pin_t) { .v_ = -1 };
- }
-
- gpio_port_t port = get_port_for_pin(pin);
- regset(RCC.ahb2en_r, rcc_gpioen(port), 1);
-
- gpio_port_config_t* port_config = get_gpio_port_config(port);
-
-
- int off = offset_for_gpio_pin(pin);
-
- regset(port_config->mode_r, gpio_mode_n(off), opts->mode);
- regset(port_config->pupd_r, gpio_pupd_n(off), opts->pull_dir);
-
- switch(opts->mode) {
- case GPIO_MODE_INPUT:
- break;
-
- case GPIO_MODE_OUTPUT:
- regset(port_config->ospeed_r, gpio_ospeed_n(off), opts->output_opts.speed);
- regset(port_config->otype_r, gpio_otype_n(off), opts->output_opts.type);
- break;
-
- case GPIO_MODE_ALTERNATE:
- if (off < 8) {
- regset(
- port_config->af_rl,
- gpio_afsel_n(off),
- opts->alternate_opts.function);
- } else {
- regset(
- port_config->af_rh,
- gpio_afsel_n(off - 8),
- opts->alternate_opts.function);
- }
- break;
-
- case GPIO_MODE_ANALOG:
- regset(port_config->asc_r, gpio_asc_n(off), 1);
- break;
- }
-
- return (gpio_reserved_pin_t) { .v_ = pin };
-}
-
-gpio_reserved_pin_t gpio_enable_alternate_function(
- gpio_alternate_function_t fn,
- gpio_pin_t hint,
- int* error_out)
-{
- int i = 0;
- gpio_pin_opts_t opts;
- struct gpio_afn_and_pin afn_and_pin[5];
-
- if (gpio_pin_out_of_range(hint) && hint != -1) {
- *error_out = GPIO_ERROR_INVALID_PIN;
- return (gpio_reserved_pin_t) { .v_ = -1 };
- }
-
- opts.mode = GPIO_MODE_ALTERNATE;
-
- if (fn == GPIO_ALTERNATE_FUNCTION_EVENTOUT) {
- afn_and_pin[i].afn_number = GPIO_ALTERNATE_FUNCTION_EVENTOUT;
- if (hint == -1) {
- hint = GPIO_PIN_PA0;
- }
- afn_and_pin[i].gpio_pin = hint;
- } else {
- get_ports_and_pins_for_alternate_function(fn, afn_and_pin);
-
- if (hint == -1) {
- hint = afn_and_pin[0].gpio_pin;
- }
-
- for(i = 0;
- i < 5
- && afn_and_pin[i].gpio_pin != hint
- && afn_and_pin[i].gpio_pin != -1;
- ++ i);
-
- if (afn_and_pin[i].gpio_pin == -1 || i == 5) {
- *error_out = GPIO_ERROR_INVALID_PIN_FOR_ALTERNATE_FUNCTION;
- return (gpio_reserved_pin_t) { .v_ = -1 };
- }
- }
-
- opts.alternate_opts.function = afn_and_pin[i].afn_number;
- return reserve_gpio_pin(afn_and_pin[i].gpio_pin, &opts, error_out);
-}
-
-void release_gpio_pin(gpio_reserved_pin_t rpin)
-{
- gpio_pin_t pin = rpin.v_;
- // TODO this should be a critical section.
- gpio_port_t port = get_port_for_pin(pin);
- pins_inuse[pin / 32] &= ~(1 << (pin % 32));
-
- int used;
- switch(port) {
- case GPIO_PORT_A:
- used = gc_port_a();
- break;
- case GPIO_PORT_B:
- used = gc_port_b();
- break;
- case GPIO_PORT_C:
- used = gc_port_c();
- break;
- case GPIO_PORT_D:
- used = gc_port_d();
- break;
- case GPIO_PORT_E:
- used = gc_port_e();
- break;
- case GPIO_PORT_F:
- used = gc_port_f();
- break;
- case GPIO_PORT_G:
- used = gc_port_g();
- break;
- case GPIO_PORT_H:
- used = gc_port_h();
- break;
- case GPIO_PORT_I:
- used = gc_port_i();
- break;
-
- case N_GPIO_PORTS:
- used = 1;
- break;
- }
-
- if (!used) {
- regset(RCC.ahb2en_r, rcc_gpioen(port), 0);
- }
-}
-
-inline void get_gpio_pin_port_off(
- gpio_pin_t pin, gpio_port_config_t** out_cfg, int* out_off)
-{
- *out_cfg = get_gpio_port_config_for_pin(pin);
- *out_off = offset_for_gpio_pin(pin);
-}
-
-void set_gpio_pin_high(gpio_reserved_pin_t pin)
-{
- int off;
- gpio_port_config_t* portcfg;
- get_gpio_pin_port_off(pin.v_, &portcfg, &off);
-
- regset(portcfg->od_r, (1 << off), 1);
-}
-
-void set_gpio_pin_low(gpio_reserved_pin_t pin)
-{
- int off;
- gpio_port_config_t* portcfg;
- get_gpio_pin_port_off(pin.v_, &portcfg, &off);
-
- regset(portcfg->od_r, (1 << off), 0);
-}