diff options
author | Kevin O'Connor <kevin@koconnor.net> | 2019-07-28 23:15:54 -0400 |
---|---|---|
committer | KevinOConnor <kevin@koconnor.net> | 2019-08-05 11:25:40 -0400 |
commit | 8b9cc62359057a686929cc713ffe2931e2203946 (patch) | |
tree | ab2e5469d7919cc6ed652e2928f0eaf9a24420c3 /src/stm32/gpio.c | |
parent | ec3d865b517affd77678e5b1a45ef4691619726d (diff) | |
download | kutter-8b9cc62359057a686929cc713ffe2931e2203946.tar.gz kutter-8b9cc62359057a686929cc713ffe2931e2203946.tar.xz kutter-8b9cc62359057a686929cc713ffe2931e2203946.zip |
stm32: Rename stm32f4/ directory to stm32/
Now that the code in stm32f4/ can handle both stm32f1 and stm32f4
chips, rename the directory to just "stm32".
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
Diffstat (limited to 'src/stm32/gpio.c')
-rw-r--r-- | src/stm32/gpio.c | 130 |
1 files changed, 130 insertions, 0 deletions
diff --git a/src/stm32/gpio.c b/src/stm32/gpio.c new file mode 100644 index 00000000..9fbbdaec --- /dev/null +++ b/src/stm32/gpio.c @@ -0,0 +1,130 @@ +// GPIO functions on stm32f4 +// +// Copyright (C) 2019 Kevin O'Connor <kevin@koconnor.net> +// +// This file may be distributed under the terms of the GNU GPLv3 license. + +#include <string.h> // ffs +#include "board/irq.h" // irq_save +#include "command.h" // DECL_ENUMERATION_RANGE +#include "gpio.h" // gpio_out_setup +#include "internal.h" // gpio_peripheral +#include "sched.h" // sched_shutdown + +DECL_ENUMERATION_RANGE("pin", "PA0", GPIO('A', 0), 32); +DECL_ENUMERATION_RANGE("pin", "PB0", GPIO('B', 0), 32); +DECL_ENUMERATION_RANGE("pin", "PC0", GPIO('C', 0), 32); +DECL_ENUMERATION_RANGE("pin", "PD0", GPIO('D', 0), 32); +DECL_ENUMERATION_RANGE("pin", "PE0", GPIO('E', 0), 32); +#ifdef GPIOH +DECL_ENUMERATION_RANGE("pin", "PF0", GPIO('F', 0), 32); +DECL_ENUMERATION_RANGE("pin", "PG0", GPIO('G', 0), 32); +DECL_ENUMERATION_RANGE("pin", "PH0", GPIO('H', 0), 32); +#endif +#ifdef GPIOI +DECL_ENUMERATION_RANGE("pin", "PI0", GPIO('I', 0), 32); +#endif + +GPIO_TypeDef * const digital_regs[] = { + GPIOA, GPIOB, GPIOC, GPIOD, GPIOE, +#ifdef GPIOH + GPIOF, GPIOG, GPIOH, +#endif +#ifdef GPIOI + GPIOI, +#endif +}; + +// Convert a register and bit location back to an integer pin identifier +static int +regs_to_pin(GPIO_TypeDef *regs, uint32_t bit) +{ + int i; + for (i=0; i<ARRAY_SIZE(digital_regs); i++) + if (digital_regs[i] == regs) + return GPIO('A' + i, ffs(bit)-1); + return 0; +} + +struct gpio_out +gpio_out_setup(uint32_t pin, uint32_t val) +{ + if (GPIO2PORT(pin) >= ARRAY_SIZE(digital_regs)) + goto fail; + GPIO_TypeDef *regs = digital_regs[GPIO2PORT(pin)]; + struct gpio_out g = { .regs=regs, .bit=GPIO2BIT(pin) }; + gpio_out_reset(g, val); + return g; +fail: + shutdown("Not an output pin"); +} + +void +gpio_out_reset(struct gpio_out g, uint32_t val) +{ + GPIO_TypeDef *regs = g.regs; + int pin = regs_to_pin(regs, g.bit); + irqstatus_t flag = irq_save(); + if (val) + regs->BSRR = g.bit; + else + regs->BSRR = g.bit << 16; + gpio_peripheral(pin, GPIO_OUTPUT, 0); + irq_restore(flag); +} + +void +gpio_out_toggle_noirq(struct gpio_out g) +{ + GPIO_TypeDef *regs = g.regs; + regs->ODR ^= g.bit; +} + +void +gpio_out_toggle(struct gpio_out g) +{ + irqstatus_t flag = irq_save(); + gpio_out_toggle_noirq(g); + irq_restore(flag); +} + +void +gpio_out_write(struct gpio_out g, uint32_t val) +{ + GPIO_TypeDef *regs = g.regs; + if (val) + regs->BSRR = g.bit; + else + regs->BSRR = g.bit << 16; +} + + +struct gpio_in +gpio_in_setup(uint32_t pin, int32_t pull_up) +{ + if (GPIO2PORT(pin) >= ARRAY_SIZE(digital_regs)) + goto fail; + GPIO_TypeDef *regs = digital_regs[GPIO2PORT(pin)]; + struct gpio_in g = { .regs=regs, .bit=GPIO2BIT(pin) }; + gpio_in_reset(g, pull_up); + return g; +fail: + shutdown("Not a valid input pin"); +} + +void +gpio_in_reset(struct gpio_in g, int32_t pull_up) +{ + GPIO_TypeDef *regs = g.regs; + int pin = regs_to_pin(regs, g.bit); + irqstatus_t flag = irq_save(); + gpio_peripheral(pin, GPIO_INPUT, pull_up); + irq_restore(flag); +} + +uint8_t +gpio_in_read(struct gpio_in g) +{ + GPIO_TypeDef *regs = g.regs; + return !!(regs->IDR & g.bit); +} |