From 1016b40c88971f0ca063b408a7a4a30c52d5b985 Mon Sep 17 00:00:00 2001 From: "Konstantin Kirik (snegovick)" Date: Tue, 6 Jan 2026 02:31:50 +0300 Subject: Add sketchy implementation of GPIO driver for stm32f769 --- os/drivers/gpio/gpio.h | 72 ++++++++++++ os/drivers/gpio/stm32f769_gpio.c | 231 +++++++++++++++++++++++++++++++++++++++ os/drivers/gpio/stm32f769_gpio.h | 15 +++ 3 files changed, 318 insertions(+) create mode 100644 os/drivers/gpio/gpio.h create mode 100644 os/drivers/gpio/stm32f769_gpio.c create mode 100644 os/drivers/gpio/stm32f769_gpio.h (limited to 'os') diff --git a/os/drivers/gpio/gpio.h b/os/drivers/gpio/gpio.h new file mode 100644 index 00000000..df041a6c --- /dev/null +++ b/os/drivers/gpio/gpio.h @@ -0,0 +1,72 @@ +#ifndef __GPIO_H__ +#define __GPIO_H__ + +#include + +#define GPIO_INPUT (1U << 16) +#define GPIO_OUTPUT (1U << 17) +#define GPIO_DISCONNECTED 0 + +#define GPIO_OUTPUT_INIT_LOW (1U << 18) +#define GPIO_OUTPUT_INIT_HIGH (1U << 19) +#define GPIO_OUTPUT_INIT_LOGICAL (1U << 20) + +#define GPIO_OUTPUT_LOW (GPIO_OUTPUT | GPIO_OUTPUT_INIT_LOW) +#define GPIO_OUTPUT_HIGH (GPIO_OUTPUT | GPIO_OUTPUT_INIT_HIGH) +#define GPIO_OUTPUT_INACTIVE (GPIO_OUTPUT | \ + GPIO_OUTPUT_INIT_LOW | \ + GPIO_OUTPUT_INIT_LOGICAL) +#define GPIO_OUTPUT_ACTIVE (GPIO_OUTPUT | \ + GPIO_OUTPUT_INIT_HIGH | \ + GPIO_OUTPUT_INIT_LOGICAL) + +#define GPIO_INT_DISABLE (1U << 21) +#define GPIO_INT_ENABLE (1U << 22) +#define GPIO_INT_LEVELS_LOGICAL (1U << 23) +#define GPIO_INT_EDGE (1U << 24) +#define GPIO_INT_LOW_0 (1U << 25) +#define GPIO_INT_HIGH_1 (1U << 26) + +#define GPIO_INT_MASK (GPIO_INT_DISABLE | \ + GPIO_INT_ENABLE | \ + GPIO_INT_LEVELS_LOGICAL | \ + GPIO_INT_EDGE | \ + GPIO_INT_LOW_0 | \ + GPIO_INT_HIGH_1) +#define GPIO_INT_EDGE_RISING (GPIO_INT_ENABLE | \ + GPIO_INT_EDGE | \ + GPIO_INT_HIGH_1) +#define GPIO_INT_EDGE_FALLING (GPIO_INT_ENABLE | \ + GPIO_INT_EDGE | \ + GPIO_INT_LOW_0) +#define GPIO_INT_EDGE_BOTH (GPIO_INT_ENABLE | \ + GPIO_INT_EDGE | \ + GPIO_INT_LOW_0 | \ + GPIO_INT_HIGH_1) +#define GPIO_INT_LEVEL_LOW (GPIO_INT_ENABLE | \ + GPIO_INT_LOW_0) +#define GPIO_INT_LEVEL_HIGH (GPIO_INT_ENABLE | \ + GPIO_INT_HIGH_1) +#define GPIO_INT_EDGE_TO_INACTIVE (GPIO_INT_ENABLE | \ + GPIO_INT_LEVELS_LOGICAL | \ + GPIO_INT_EDGE | \ + GPIO_INT_LOW_0) +#define GPIO_INT_EDGE_TO_ACTIVE (GPIO_INT_ENABLE | \ + GPIO_INT_LEVELS_LOGICAL | \ + GPIO_INT_EDGE | \ + GPIO_INT_HIGH_1) +#define GPIO_INT_LEVEL_INACTIVE (GPIO_INT_ENABLE | \ + GPIO_INT_LEVELS_LOGICAL | \ + GPIO_INT_LOW_0) +#define GPIO_INT_LEVEL_ACTIVE (GPIO_INT_ENABLE | \ + GPIO_INT_LEVELS_LOGICAL | \ + GPIO_INT_HIGH_1) +#define GPIO_DIR_MASK (GPIO_INPUT | GPIO_OUTPUT) + +#define GPIO_OPEN_DRAIN (1 << 27) +#define GPIO_OPEN_SOURCE (1 << 28) +#define GPIO_PULL_UP (1 << 29) +#define GPIO_PULL_DOWN (1 << 30) +#define GPIO_INT_WAKEUP (1 << 31) + +#endif/*__GPIO_H__*/ diff --git a/os/drivers/gpio/stm32f769_gpio.c b/os/drivers/gpio/stm32f769_gpio.c new file mode 100644 index 00000000..250615b2 --- /dev/null +++ b/os/drivers/gpio/stm32f769_gpio.c @@ -0,0 +1,231 @@ +#include "gpio.h" +#include +/* #include "memory_map.h" */ +/* #include "soc_gpio.h" */ +/* #include "soc.h" */ +/* #include "clocks.h" */ +/* #include "clock_control.h" */ + +int stm32f769_gpio_configure_analog(struct device *dev, uint32_t pin, uint32_t flags) +{ +// const struct gpio_stm32f769_config *config = port->config; + uint32_t port_idx = STM32F769_PORT_GET(pin); + GPIO_TypeDef *p = NULL; + if (dev == NULL) { + p = stm32f769_get_port(port_idx); + } else { + p = dev->devptr; + } + + uint32_t moder = sys_read32(p->MODER); + uint32_t ospeedr = sys_read32(p->OSPEEDR); + uint32_t pupdr = sys_read32(p->PUPDR); + uint32_t otyper = sys_read32(p->OTYPER); + + moder |= ((0x3) << (pin * 2)); + sys_write32(moder, p->MODER); + + // Low speed + ospeedr &= ~((0x3) << (pin * 2)); + sys_write32(ospeedr, p->OSPEEDR); + + if ((flags & GPIO_OPEN_DRAIN) != 0U) { + otyper |= (1 << pin); + } else { + otyper &= ~(1 << pin); + } + sys_write32(otyper, p->OTYPER); + + if ((flags & GPIO_PULL_UP) != 0U) { + pupdr &= ~(0x3 << (pin * 2)); + pupdr |= (0x1 << (pin * 2)); + } else if ((flags & GPIO_PULL_DOWN) != 0U) { + pupdr &= ~(0x3 << (pin * 2)); + pupdr |= (0x2 << (pin * 2)); + } else { + pupdr &= ~(0x3 << (pin * 2)); + } + + sys_write32(pupdr, p->PUPDR); + + return 0; +} + +int stm32f769_gpio_configure_af(struct device *dev, uint32_t pin, uint32_t flags) +{ +// const struct gpio_stm32f769_config *config = port->config; + uint32_t port_idx = STM32F769_PORT_GET(pin); + GPIO_TypeDef *p = NULL; + if (dev == NULL) { + p = stm32f769_get_port(port_idx); + } else { + p = dev->devptr; + } + + uint32_t moder = sys_read32(p->MODER); + uint32_t ospeedr = sys_read32(p->OSPEEDR); + uint32_t pupdr = sys_read32(p->PUPDR); + uint32_t otyper = sys_read32(p->OTYPER); + + moder &= ~((0x3) << (pin * 2)); + moder |= ((0x2) << (pin * 2)); + sys_write32(moder, p->MODER); + + // Low speed + ospeedr &= ~((0x3) << (pin * 2)); + sys_write32(ospeedr, p->OSPEEDR); + + if ((flags & GPIO_OPEN_DRAIN) != 0U) { + otyper |= (1 << pin); + } else { + otyper &= ~(1 << pin); + } + sys_write32(otyper, p->OTYPER); + + if ((flags & GPIO_PULL_UP) != 0U) { + pupdr &= ~(0x3 << (pin * 2)); + pupdr |= (0x1 << (pin * 2)); + } else if ((flags & GPIO_PULL_DOWN) != 0U) { + pupdr &= ~(0x3 << (pin * 2)); + pupdr |= (0x2 << (pin * 2)); + } else { + pupdr &= ~(0x3 << (pin * 2)); + } + + sys_write32(pupdr, p->PUPDR); + + return 0; +} + +int stm32f769_gpio_configure(struct device *dev, uint32_t pin, uint32_t flags) +{ +// const struct gpio_stm32f769_config *config = port->config; + uint32_t port_idx = STM32F769_PORT_GET(pin); + GPIO_TypeDef *p = NULL; + if (dev == NULL) { + p = stm32f769_get_port(port_idx); + } else { + p = dev->devptr; + } + + uint32_t moder = sys_read32(p->MODER); + uint32_t ospeedr = sys_read32(p->OSPEEDR); + uint32_t pupdr = sys_read32(p->PUPDR); + uint32_t otyper = sys_read32(p->OTYPER); + + if ((flags & GPIO_OUTPUT) != 0U) { + // GPIO mode + moder &= ~((0x3) << (pin * 2)); + moder |= (0x01 << (pin * 2)); + sys_write32(moder, p->MODER); + + // Low speed + ospeedr &= ~((0x3) << (pin * 2)); + sys_write32(ospeedr, p->OSPEEDR); + + if ((flags & GPIO_OUTPUT_INIT_HIGH) != 0U) { + sys_write32(BIT(pin), p->BSRR); + } else if ((flags & GPIO_OUTPUT_INIT_LOW) != 0U) { + sys_write32(BIT(pin + 16), p->BSRR); + } + } else if ((flags & GPIO_INPUT) != 0U) { + // GPIO mode + moder &= ~((0x3) << (pin * 2)); + sys_write32(moder, p->MODER); + + // Low speed + ospeedr &= ~((0x3) << (pin * 2)); + sys_write32(ospeedr, p->OSPEEDR); + } else { // set mode ANALOG + // GPIO mode + moder |= ((0x3) << (pin * 2)); + sys_write32(moder, p->MODER); + + // Low speed + ospeedr &= ~((0x3) << (pin * 2)); + sys_write32(ospeedr, p->OSPEEDR); + } + + if ((flags & GPIO_OPEN_DRAIN) != 0U) { + otyper |= (1 << pin); + } else { + otyper &= ~(1 << pin); + } + sys_write32(otyper, p->OTYPER); + + if ((flags & GPIO_PULL_UP) != 0U) { + pupdr &= ~(0x3 << (pin * 2)); + pupdr |= (0x1 << (pin * 2)); + } else if ((flags & GPIO_PULL_DOWN) != 0U) { + pupdr &= ~(0x3 << (pin * 2)); + pupdr |= (0x2 << (pin * 2)); + } else { + pupdr &= ~(0x3 << (pin * 2)); + } + + sys_write32(pupdr, p->PUPDR); + + return 0; +} + +int stm32f769_gpio_init(struct device *dev) +{ + uint32_t clkid = 0; + switch (dev->devptr) { + case GPIOA: + clkid = STM32F769_CLOCK_GPIOA; + break; + case GPIOB: + clkid = STM32F769_CLOCK_GPIOB; + break; + case GPIOC: + clkid = STM32F769_CLOCK_GPIOC; + break; + case GPIOD: + clkid = STM32F769_CLOCK_GPIOD; + break; + case GPIOE: + clkid = STM32F769_CLOCK_GPIOE; + break; + case GPIOF: + clkid = STM32F769_CLOCK_GPIOF; + break; + case GPIOG: + clkid = STM32F769_CLOCK_GPIOG; + break; + case GPIOH: + clkid = STM32F769_CLOCK_GPIOH; + break; + case GPIOI: + clkid = STM32F769_CLOCK_GPIOI; + break; + case GPIOJ: + clkid = STM32F769_CLOCK_GPIOJ; + break; + case GPIOK: + clkid = STM32F769_CLOCK_GPIOK; + break; + } + + stm32f769_clock_control_on(clkid); + + return 0; +} + +int stm32f769_gpio_read(struct device *dev, uint32_t pin) { + GPIO_TypeDef *p = dev->devptr; + uint32_t state = sys_read32(p->IDR); + if (state & BIT(pin)) { + return 1; + } + return 0; +} + +void stm32f769_gpio_write(struct device *dev, uint32_t pin, int val) { + GPIO_TypeDef *p = dev->devptr; + if (val == 0) { + sys_write32(BIT(pin + 16), p->BSRR); + } else { + sys_write32(BIT(pin), p->BSRR); + } +} diff --git a/os/drivers/gpio/stm32f769_gpio.h b/os/drivers/gpio/stm32f769_gpio.h new file mode 100644 index 00000000..832963ac --- /dev/null +++ b/os/drivers/gpio/stm32f769_gpio.h @@ -0,0 +1,15 @@ +#ifndef __STM32F769_GPIO_H__ +#define __STM32F769_GPIO_H__ + +#include + +GPIO_TypeDef *stm32f769_get_port(unsigned int port_idx); +uint16_t stm32f769_get_port_clkid(unsigned int port_idx); +int stm32f769_gpio_configure(struct device *dev, uint32_t pin, uint32_t flags); +int stm32f769_gpio_configure_analog(struct device *dev, uint32_t pin, uint32_t flags); +int stm32f769_gpio_configure_af(struct device *dev, uint32_t pin, uint32_t flags); +int stm32f769_gpio_init(struct device *dev); +int stm32f769_gpio_read(struct device *dev, uint32_t pin); +void stm32f769_gpio_write(struct device *dev, uint32_t pin, int val); + +#endif/*__STM32F769_GPIO_H__*/ -- cgit v1.2.3