diff options
Diffstat (limited to 'src/stm32f0/gpio.c')
-rw-r--r-- | src/stm32f0/gpio.c | 141 |
1 files changed, 141 insertions, 0 deletions
diff --git a/src/stm32f0/gpio.c b/src/stm32f0/gpio.c new file mode 100644 index 00000000..74e2fb9e --- /dev/null +++ b/src/stm32f0/gpio.c @@ -0,0 +1,141 @@ +/* + * GPIO functions on STM32F042 boards. + * + * Copyright (C) 2019 Eug Krashtan <eug.krashtan@gmail.com> + * This file may be distributed under the terms of the GNU GPLv3 license. + * + */ + +#include "board/gpio.h" // gpio_out_setup +#include "stm32f0xx_hal.h" +#include "internal.h" // GPIO +#include "board/irq.h" // irq_save +#include "compiler.h" // ARRAY_SIZE +#include "sched.h" // sched_shutdown +#include "command.h" // shutdown + +DECL_ENUMERATION_RANGE("pin", "PA0", GPIO('A', 0), 11); +DECL_ENUMERATION_RANGE("pin", "PB0", GPIO('B', 0), 9); +DECL_ENUMERATION_RANGE("pin", "PF0", GPIO('F', 0), 2); + +GPIO_TypeDef *const digital_regs[] = { + GPIOA, GPIOB, GPIOC, GPIOF +}; + +// <port:4><pin:4> +uint8_t const avail_pins[] = { + 0x0 + 0x0, //PA0 + 0x0 + 0x1, //PA1 +#if !(CONFIG_SERIAL) + 0x0 + 0x2, //PA2 - USART pins + 0x0 + 0x3, //PA3 +#endif + 0x0 + 0x4, //PA4 + 0x0 + 0x5, //PA5 + 0x0 + 0x6, //PA6 + 0x0 + 0x7, //PA7 +#if !(CONFIG_CANSERIAL) + 0x0 + 0x9, //PA9 - but remapped in CAN mode to PA11,PA12 + 0x0 + 0xa, //PA10 +#endif + 0x10 + 0x1, //PB1 + 0x10 + 0x8, //PB8 + 0x50 + 0x0, //PF0 + 0x50 + 0x1, //PF1 +}; + +/**************************************************************** + * General Purpose Input Output (GPIO) pins + ****************************************************************/ + +static uint8_t +gpio_check_pin(uint8_t pin) +{ + int i; + for(i=0; i<ARRAY_SIZE(avail_pins); i++) { + if (avail_pins[i] == pin) + return i; + } + return 0xFF; +} + +struct gpio_out +gpio_out_setup(uint8_t pin, uint8_t val) +{ + struct gpio_out g = { .pin=pin }; + if (gpio_check_pin(pin) < 0xFF) { + gpio_out_reset(g, val); + } else { + shutdown("Not an output pin"); + } + return g; +} + +void +gpio_out_reset(struct gpio_out g, uint8_t val) +{ + GPIO_InitTypeDef GPIO_InitStruct = {0}; + GPIO_InitStruct.Pin = 1 << (g.pin % 16); + GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; + HAL_GPIO_Init(digital_regs[GPIO2PORT(g.pin)], &GPIO_InitStruct); + HAL_GPIO_WritePin(digital_regs[GPIO2PORT(g.pin)], 1 << (g.pin % 16), val); +} + +void +gpio_out_write(struct gpio_out g, uint8_t val) +{ + HAL_GPIO_WritePin(digital_regs[GPIO2PORT(g.pin)], 1 << (g.pin % 16), val); +} + +struct gpio_in +gpio_in_setup(uint8_t pin, int8_t pull_up) +{ + struct gpio_in g = { .pin=pin }; + if (gpio_check_pin(pin) < 0xFF) { + gpio_in_reset(g, pull_up); + } else { + shutdown("Not an input pin"); + } + return g; +} + +void +gpio_in_reset(struct gpio_in g, int8_t pull_up) +{ + irqstatus_t flag = irq_save(); + GPIO_InitTypeDef GPIO_InitStruct = {0}; + GPIO_InitStruct.Pin = 1 << (g.pin % 16); + GPIO_InitStruct.Mode = GPIO_MODE_INPUT; + GPIO_InitStruct.Pull = (pull_up)?GPIO_PULLUP:GPIO_NOPULL; + HAL_GPIO_Init(digital_regs[GPIO2PORT(g.pin)], &GPIO_InitStruct); + irq_restore(flag); +} + +uint8_t +gpio_in_read(struct gpio_in g) +{ + return HAL_GPIO_ReadPin(digital_regs[GPIO2PORT(g.pin)], 1 << (g.pin % 16)); +} + +void +gpio_out_toggle_noirq(struct gpio_out g) +{ + HAL_GPIO_TogglePin(digital_regs[GPIO2PORT(g.pin)], 1 << (g.pin % 16)); +} + +void +gpio_out_toggle(struct gpio_out g) +{ + irqstatus_t flag = irq_save(); + gpio_out_toggle_noirq(g); + irq_restore(flag); +} + +void gpio_init(void) +{ + /* GPIO Ports Clock Enable */ + __HAL_RCC_GPIOA_CLK_ENABLE(); + __HAL_RCC_GPIOB_CLK_ENABLE(); + __HAL_RCC_GPIOF_CLK_ENABLE(); +} |