summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKonstantin Kirik (snegovick) <snegovick@uprojects.org>2026-01-06 02:31:50 +0300
committerKonstantin Kirik (snegovick) <snegovick@uprojects.org>2026-01-06 02:31:50 +0300
commit1016b40c88971f0ca063b408a7a4a30c52d5b985 (patch)
tree75169b0c79403f91148954bd013dcea2aef80b5d
parentb82b61d492b0deea29da9bef88b81413c00f6256 (diff)
Add sketchy implementation of GPIO driver for stm32f769
-rw-r--r--os/drivers/gpio/gpio.h72
-rw-r--r--os/drivers/gpio/stm32f769_gpio.c231
-rw-r--r--os/drivers/gpio/stm32f769_gpio.h15
3 files changed, 318 insertions, 0 deletions
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 <stdint.h>
+
+#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 <arch/sys_io.h>
+/* #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 <stdint.h>
+
+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__*/