diff options
author | Josh Rahm <joshuarahm@gmail.com> | 2020-11-23 19:41:05 -0700 |
---|---|---|
committer | Josh Rahm <joshuarahm@gmail.com> | 2020-11-23 19:41:05 -0700 |
commit | 60b1e3055c179312eef809fe1d01f58042b64d5f (patch) | |
tree | c620b5ca1eab2d05c9396637db50d0a110328d29 /02-usart/src | |
parent | 2a6ae24ba769892993ec7a173c564f59feb06495 (diff) | |
download | stm32l4-60b1e3055c179312eef809fe1d01f58042b64d5f.tar.gz stm32l4-60b1e3055c179312eef809fe1d01f58042b64d5f.tar.bz2 stm32l4-60b1e3055c179312eef809fe1d01f58042b64d5f.zip |
Add new GPIO subsystem.
This gpio subsystem keeps track of the GPIO pins which
have been reserved and takes care of the housekeeping
with keeping them running.
This gpio subsystem also knows which alternate functions
belong to which pins, so it can automatically configure
the pins for the alternate functions.
Diffstat (limited to '02-usart/src')
-rw-r--r-- | 02-usart/src/arch/stm32l4xxx/peripherals/clock.c | 1 | ||||
-rw-r--r-- | 02-usart/src/arch/stm32l4xxx/peripherals/gpio.c | 52 | ||||
-rw-r--r-- | 02-usart/src/arch/stm32l4xxx/peripherals/irq.c | 26 | ||||
-rw-r--r-- | 02-usart/src/kern/dma/dma_manager.c | 1 | ||||
-rw-r--r-- | 02-usart/src/kern/gpio/gpio_manager.c | 402 | ||||
-rw-r--r-- | 02-usart/src/kern/gpio/sysled.c | 14 | ||||
-rw-r--r-- | 02-usart/src/kern/main.c | 39 | ||||
-rw-r--r-- | 02-usart/src/kern/spin.c | 49 |
8 files changed, 454 insertions, 130 deletions
diff --git a/02-usart/src/arch/stm32l4xxx/peripherals/clock.c b/02-usart/src/arch/stm32l4xxx/peripherals/clock.c index ba127a9..1029d39 100644 --- a/02-usart/src/arch/stm32l4xxx/peripherals/clock.c +++ b/02-usart/src/arch/stm32l4xxx/peripherals/clock.c @@ -6,7 +6,6 @@ #include "arch/stm32l4xxx/peripherals/flash.h" #include <stdint.h> -#include "kern/spin.h" #define TIMEOUT 10000 diff --git a/02-usart/src/arch/stm32l4xxx/peripherals/gpio.c b/02-usart/src/arch/stm32l4xxx/peripherals/gpio.c deleted file mode 100644 index a1e82c7..0000000 --- a/02-usart/src/arch/stm32l4xxx/peripherals/gpio.c +++ /dev/null @@ -1,52 +0,0 @@ -#include "arch/stm32l4xxx/peripherals/gpio.h" -#include "arch/stm32l4xxx/peripherals/rcc.h" - -/* - * Sets the mode of a pin on a gpio por. - */ -void set_gpio_pin_mode( - __IO gpio_port_t* gpio_port, gpio_pin_t pin, gpio_pin_mode_t mode) -{ - /* Each pin has a 2-bit mode provided at bits pin#*2 and pin#*2+1 */ - gpio_port->mode_r &= ~(0x03 << pin * 2); - gpio_port->mode_r |= mode << pin * 2; -} - -gpio_output_pin_t set_gpio_pin_output( - __IO gpio_port_t* gpio_port, gpio_pin_t pin) -{ - set_gpio_pin_mode(gpio_port, pin, MODE_OUTPUT); - - return (gpio_output_pin_t){.gpio_port = gpio_port, .pin = pin}; -} - -void set_gpio_output_pin(gpio_output_pin_t pin, bool onoff) -{ - if (onoff) { - pin.gpio_port->output_r |= 1 << pin.pin; - } else { - pin.gpio_port->output_r &= ~(1 << pin.pin); - } -} - -void set_gpio_alternate_function( - __IO gpio_port_t* port, gpio_pin_t gpio_pin, alternate_function_t afn) -{ - __IO uint32_t* reg; - if (gpio_pin < 8) { - reg = &(port->af_rl); - } else { - reg = &(port->af_rh); - gpio_pin -= 8; - } - - uint32_t tmp = *reg & (~0x0f << gpio_pin * 4); - *reg = tmp | (afn << gpio_pin * 4); -} - -#define GPIO_PORTS_BASE_ADDR ((uint8_t*)0x48000000) -__IO gpio_port_t* enable_gpio(gpio_port_number_t gpio_port_number) -{ - RCC.ahb2en_r |= 1 << gpio_port_number; /* Enable the GPIO port. */ - return (__IO gpio_port_t*)(GPIO_PORTS_BASE_ADDR + (gpio_port_number * 0x400)); -} diff --git a/02-usart/src/arch/stm32l4xxx/peripherals/irq.c b/02-usart/src/arch/stm32l4xxx/peripherals/irq.c index 8fb3e49..364b9a7 100644 --- a/02-usart/src/arch/stm32l4xxx/peripherals/irq.c +++ b/02-usart/src/arch/stm32l4xxx/peripherals/irq.c @@ -4,6 +4,7 @@ #include "arch.h" #include "kern/delay.h" +#include "kern/gpio/gpio_manager.h" #define IRQ_RESERVED(n) #define IRQ(name, uname_, n) \ @@ -16,10 +17,11 @@ void isr_simple_pin_on() { - __IO gpio_port_t* port_b = enable_gpio(GPIO_PORT_B); - gpio_output_pin_t pin3 = set_gpio_pin_output(port_b, PIN_3); + int ec; + gpio_pin_opts_t opts = DEFAULT_GPIO_OPTS_OUTPUT; + gpio_reserved_pin_t pin3 = reserve_gpio_pin(GPIO_PIN_PB3, &opts, &ec); - pin_on(pin3); + set_gpio_pin_high(pin3); } #define IRQ_RESERVED(n) 0, @@ -47,13 +49,15 @@ const void* vectors[] __attribute__((section(".vectors"))) = { */ void unhandled_isr(uint8_t number) { - __IO gpio_port_t* port_b = enable_gpio(GPIO_PORT_B); - gpio_output_pin_t pin3 = set_gpio_pin_output(port_b, PIN_3); + int ec; + gpio_pin_opts_t opts = DEFAULT_GPIO_OPTS_OUTPUT; + gpio_reserved_pin_t pin3 = reserve_gpio_pin(GPIO_PIN_PB3, &opts, &ec); + for (;;) { for (int i = 0; i < 20; ++ i) { - pin_on(pin3); + set_gpio_pin_high(pin3); delay(1000000); - pin_off(pin3); + set_gpio_pin_low(pin3); delay(1000000); } delay(50000000); @@ -62,15 +66,15 @@ void unhandled_isr(uint8_t number) for (int i = 0; i < 8; ++ i) { if (n & 1) { // LSB is a 1 - pin_on(pin3); + set_gpio_pin_high(pin3); delay(15000000); - pin_off(pin3); + set_gpio_pin_low(pin3); delay(15000000); } else { // LSB is a 0 - pin_on(pin3); + set_gpio_pin_high(pin3); delay(1000000); - pin_off(pin3); + set_gpio_pin_low(pin3); delay(29000000); } diff --git a/02-usart/src/kern/dma/dma_manager.c b/02-usart/src/kern/dma/dma_manager.c index 4336496..00e9f3d 100644 --- a/02-usart/src/kern/dma/dma_manager.c +++ b/02-usart/src/kern/dma/dma_manager.c @@ -75,7 +75,6 @@ static int try_reserve_dma_channel( return !(in_use & (1 << chan.chan)); } - // int in_use = __sync_fetch_and_or(&dma_inuse[dmasel], 1 << chan); void release_dma_channel(dma_channel_t chan) { dma_channel_config_t* config = get_raw_channel_config(chan); diff --git a/02-usart/src/kern/gpio/gpio_manager.c b/02-usart/src/kern/gpio/gpio_manager.c new file mode 100644 index 0000000..82dd0ba --- /dev/null +++ b/02-usart/src/kern/gpio/gpio_manager.c @@ -0,0 +1,402 @@ +#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); +} diff --git a/02-usart/src/kern/gpio/sysled.c b/02-usart/src/kern/gpio/sysled.c new file mode 100644 index 0000000..a728da3 --- /dev/null +++ b/02-usart/src/kern/gpio/sysled.c @@ -0,0 +1,14 @@ +#include "kern/gpio/sysled.h" + +#define SYSLED GPIO_PIN_PB3 + +gpio_reserved_pin_t get_sysled() +{ + if (gpio_pin_in_use(SYSLED)) { + return (gpio_reserved_pin_t) { .v_ = SYSLED }; + } + + int ec; + gpio_pin_opts_t opts = DEFAULT_GPIO_OPTS_OUTPUT; + return reserve_gpio_pin(SYSLED, &opts, &ec); +} diff --git a/02-usart/src/kern/main.c b/02-usart/src/kern/main.c index 0e0c89c..32166bc 100644 --- a/02-usart/src/kern/main.c +++ b/02-usart/src/kern/main.c @@ -10,24 +10,23 @@ #include "arch/stm32l4xxx/peripherals/irq.h" #include "kern/dma/dma_manager.h" +#include "kern/gpio/gpio_manager.h" +#include "kern/gpio/sysled.h" #include "kern/delay.h" #include "kern/mem.h" -#include "kern/spin.h" #include "kern/string.h" /** Overrides the default systick irq handler. */ void on_systick() { static int is_on = 0; - - __IO gpio_port_t* port_b = enable_gpio(GPIO_PORT_B); - gpio_output_pin_t pin3 = set_gpio_pin_output(port_b, PIN_3); + gpio_reserved_pin_t sysled = get_sysled(); if (is_on) { - pin_off(pin3); + set_gpio_pin_low(sysled); } else { - pin_on(pin3); + set_gpio_pin_high(sysled); } is_on = ! is_on; @@ -35,17 +34,26 @@ void on_systick() void setup_usart2(uint32_t baud_rate) { - __IO gpio_port_t* port_a = enable_gpio(GPIO_PORT_A); enable_hsi(&RCC, true); + int ec = 0; + gpio_enable_alternate_function( + GPIO_ALTERNATE_FUNCTION_USART2_TX, GPIO_PIN_PA2, &ec); + + if (ec) { + unhandled_isr(ec & 0xff); + } + + gpio_enable_alternate_function( + GPIO_ALTERNATE_FUNCTION_USART2_RX, GPIO_PIN_PA15, &ec); + + if (ec) { + unhandled_isr(ec & 0xff); + } + set_usart2_clock_src(&RCC, USART_CLK_SRC_HSI16); set_usart2_clock_enabled(&RCC, USART_CLK_SRC_HSI16); - set_gpio_pin_mode(port_a, PIN_2, MODE_ALTERNATE); - set_gpio_pin_mode(port_a, PIN_15, MODE_ALTERNATE); - set_gpio_alternate_function(port_a, PIN_2, AFN_7); - set_gpio_alternate_function(port_a, PIN_15, AFN_3); - /* De-assert reset of USART2 */ regset(RCC.apb1rst1_r, rcc_usart2rst, 0); @@ -96,14 +104,13 @@ int main() // regset(USART2.ic_r, usart_tccf, 1); // dma_mem2p_initiate_transfer(dma_chan, thing, strlen(thing)); - __IO gpio_port_t* port_b = enable_gpio(GPIO_PORT_B); - gpio_output_pin_t pin3 = set_gpio_pin_output(port_b, PIN_3); - pin_on(pin3); + gpio_reserved_pin_t sysled = get_sysled(); + set_gpio_pin_high(sysled); // usart_printf(&USART2, "Start Configuring Countdown!\n"); /* Set the countdown to start from 1,000,0000. */ - SCB.strv_r = 10000000; + SCB.strv_r = 1000000; /* Enable interrupts. */ regset(SCB.stcs_r, scb_tickint, 1); diff --git a/02-usart/src/kern/spin.c b/02-usart/src/kern/spin.c deleted file mode 100644 index 7c4f6eb..0000000 --- a/02-usart/src/kern/spin.c +++ /dev/null @@ -1,49 +0,0 @@ -#include "kern/spin.h" -#include "kern/delay.h" -#include "arch/stm32l4xxx/peripherals/gpio.h" - -#define SHORT_DELAY 200000 -#define LONG_DELAY (SHORT_DELAY * 2) - -static void flash_bit( - uint32_t base, gpio_output_pin_t out_pin, - uint8_t bit /* 0 => 0, non-zero => 1 */) -{ - pin_on(out_pin); - if (bit) { - delay(base * 2); - } else { - delay(base); - } - pin_off(out_pin); - delay(base); -} - -void spin(uint32_t base, uint8_t c) -{ - uint8_t code; - __IO gpio_port_t* port_b = enable_gpio(GPIO_PORT_B); - gpio_output_pin_t pin3 = set_gpio_pin_output(port_b, PIN_3); - - for (;;) { - code = c; - flash_bit(base, pin3, code & 0x80); - code <<= 1; - flash_bit(base, pin3, code & 0x80); - code <<= 1; - flash_bit(base, pin3, code & 0x80); - code <<= 1; - flash_bit(base, pin3, code & 0x80); - - code <<= 1; - flash_bit(base, pin3, code & 0x80); - code <<= 1; - flash_bit(base, pin3, code & 0x80); - code <<= 1; - flash_bit(base, pin3, code & 0x80); - code <<= 1; - flash_bit(base, pin3, code & 0x80); - - delay(base * 4); - } -} |