summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVegard Storheil Eriksen <zyp@jvnv.net>2021-09-16 23:50:26 +0200
committerVegard Storheil Eriksen <zyp@jvnv.net>2021-09-16 23:50:26 +0200
commitd5fbedc24fdd41e7c30b2f9239f666f33893e065 (patch)
treed41c8b118a2c2e5822ee47e130550134458dc02e
parentc7666a7cd83d590a067d8cbbe4a7e4eb93d155d6 (diff)
gpio: Generate instances from platform spec.
-rw-r--r--.gitignore1
-rw-r--r--SConscript1
-rw-r--r--gpio/SConscript25
-rw-r--r--gpio/gpio.h250
-rw-r--r--gpio/stm32_gpio.h253
-rw-r--r--platforms/stm32/f0.yaml21
-rw-r--r--platforms/stm32/f1.yaml16
-rw-r--r--platforms/stm32/f3.yaml19
-rw-r--r--platforms/stm32/f4.yaml28
-rw-r--r--platforms/stm32/l0.yaml18
-rw-r--r--platforms/stm32/wb.yaml5
-rw-r--r--templates/periph_instances.h.j24
12 files changed, 391 insertions, 250 deletions
diff --git a/.gitignore b/.gitignore
index 5277dce..6686751 100644
--- a/.gitignore
+++ b/.gitignore
@@ -13,6 +13,7 @@ interrupt/default_handlers.cpp
interrupt/vectors_*.cpp
rcc/rcc.h
rcc/rcc_enums.h
+gpio/gpio.h
timer/timer.h
usb/usb.h
uart/uart.h
diff --git a/SConscript b/SConscript
index 87b5a1c..be66bfe 100644
--- a/SConscript
+++ b/SConscript
@@ -10,6 +10,7 @@ env.Append(
env.SConscript('dma/SConscript'),
env.SConscript('interrupt/SConscript'),
env.SConscript('rcc/SConscript'),
+ env.SConscript('gpio/SConscript'),
env.SConscript('timer/SConscript'),
env.SConscript('uart/SConscript'),
env.SConscript('usb/SConscript'),
diff --git a/gpio/SConscript b/gpio/SConscript
new file mode 100644
index 0000000..ea352cc
--- /dev/null
+++ b/gpio/SConscript
@@ -0,0 +1,25 @@
+Import('env')
+
+headers = []
+instances = []
+sources = []
+aliases = {}
+type_aliases = {}
+
+periph = env['PLATFORM_SPEC'].get('periph', {})
+
+if 'stm32_gpio' in periph:
+ headers.append('stm32_gpio.h')
+ for name, data in periph['stm32_gpio'].items():
+ instances.append({
+ 'type': 'STM32_GPIO_%s_t' % data['type'],
+ 'name': name,
+ 'args': [data['offset']],
+ })
+
+ type_aliases['Pin'] = 'STM32_GPIO_%s_t::Pin' % data['type']
+ type_aliases['PinArray'] = 'STM32_GPIO_%s_t::PinArray' % data['type']
+
+env.Jinja2('gpio.h', '../templates/periph_instances.h.j2', headers = headers, instances = instances, aliases = aliases, type_aliases = type_aliases)
+
+Return('sources')
diff --git a/gpio/gpio.h b/gpio/gpio.h
deleted file mode 100644
index 3b9c1f4..0000000
--- a/gpio/gpio.h
+++ /dev/null
@@ -1,250 +0,0 @@
-#ifndef GPIO_H
-#define GPIO_H
-
-#include <stdint.h>
-
-struct GPIO_reg_t {
- #if defined(STM32F1)
- volatile uint32_t CRL;
- volatile uint32_t CRH;
- volatile uint32_t IDR;
- volatile uint32_t ODR;
- volatile uint32_t BSRR;
- volatile uint32_t BRR;
- volatile uint32_t LCKR;
- #else
- volatile uint32_t MODER;
- volatile uint32_t OTYPER;
- volatile uint32_t OSPEEDR;
- volatile uint32_t PUPDR;
- volatile uint32_t IDR;
- volatile uint32_t ODR;
- volatile uint32_t BSRR;
- volatile uint32_t LCKR;
- volatile uint32_t AFRL;
- volatile uint32_t AFRH;
- #endif
-};
-
-class GPIO_t {
- public:
- GPIO_reg_t& reg;
-
- class Pin {
- private:
- const GPIO_t& g;
- int n;
-
- public:
- constexpr Pin(const GPIO_t& gpio, int pin) : g(gpio), n(pin) {}
-
- enum Mode {
- #if defined(STM32F1)
- Input = 0x4,
- InputPull = 0x8,
- Output = 0x3,
- AF = 0xb,
- Analog = 0x0,
- #else
- Input,
- Output,
- AF,
- Analog,
- #endif
- };
-
- enum Type {
- PushPull,
- OpenDrain,
- };
-
- enum Pull {
- PullNone,
- PullUp,
- PullDown,
- };
-
- enum Speed {
- Low,
- Medium,
- Fast,
- High,
- };
-
- void set_mode(Mode m) {
- #if defined(STM32F1)
- if(n < 8) {
- g.reg.CRL = (g.reg.CRL & ~(0xf << (n * 4))) | m << (n * 4);
- } else {
- g.reg.CRH = (g.reg.CRH & ~(0xf << (n * 4 - 32))) | m << (n * 4 - 32);
- }
- #else
- g.reg.MODER = (g.reg.MODER & ~(3 << (n * 2))) | m << (n * 2);
- #endif
- }
-
- void set_type(Type t) {
- #if defined(STM32F1)
- // TODO: Unified configure() method?
- #else
- if(t) {
- g.reg.OTYPER |= 1 << n;
- } else {
- g.reg.OTYPER &= ~(1 << n);
- }
- #endif
- }
-
- void set_pull(Pull p) {
- #if defined(STM32F1)
- // TODO: Unified configure() method?
- #else
- g.reg.PUPDR = (g.reg.PUPDR & ~(3 << (n * 2))) | p << (n * 2);
- #endif
- }
-
- void set_af(int af) {
- #if defined(STM32F1)
- // TODO: Unified configure() method?
- #else
- if(n < 8) {
- g.reg.AFRL = (g.reg.AFRL & ~(0xf << (n * 4))) | af << (n * 4);
- } else {
- g.reg.AFRH = (g.reg.AFRH & ~(0xf << (n * 4 - 32))) | af << (n * 4 - 32);
- }
- #endif
- }
-
- void set_speed(Speed s) {
- #if defined(STM32F1)
- // TODO: Unified configure() method?
- #else
- g.reg.OSPEEDR = (g.reg.OSPEEDR & ~(3 << (n * 2))) | s << (n * 2);
- #endif
- }
-
- void on() {
- g.reg.BSRR = 1 << n;
- }
-
- void off() {
- g.reg.BSRR = 1 << 16 << n;
- }
-
- void set(bool value) {
- if(value) {
- on();
- } else {
- off();
- }
- }
-
- bool get() {
- return g.reg.IDR & (1 << n);
- }
-
- void toggle() {
- set(!(g.reg.ODR & (1 << n)));
- }
- };
-
- class PinArray {
- private:
- const GPIO_t& g;
- int f;
- int l;
-
- constexpr uint32_t mask1() {
- return ((2 << l) - 1) ^ ((1 << f) - 1);
- }
-
- constexpr uint32_t mask2() {
- return ((4 << (l * 2)) - 1) ^ ((1 << (f * 2)) - 1);
- }
-
- public:
- constexpr PinArray(const GPIO_t& gpio, int first, int last) : g(gpio), f(first), l(last) {}
-
- #if ! defined(STM32F1)
- void set_mode(Pin::Mode m) {
- g.reg.MODER = (g.reg.MODER & ~mask2()) | ((0x55555555 * m) & mask2());
- }
-
- void set_type(Pin::Type t) {
- g.reg.OTYPER = (g.reg.OTYPER & ~mask2()) | ((0x55555555 * t) & mask2());
- }
-
- void set_pull(Pin::Pull p) {
- g.reg.PUPDR = (g.reg.PUPDR & ~mask2()) | ((0x55555555 * p) & mask2());
- }
- #endif
-
- void set(uint16_t value) {
- value <<= f;
- g.reg.BSRR = ((~value & mask1()) << 16) | (value & mask1());
- }
-
- uint16_t get() {
- return (g.reg.IDR & mask1()) >> f;
- }
- };
-
- constexpr GPIO_t(uint32_t reg_addr) : reg(*(GPIO_reg_t*)reg_addr) {}
-
- constexpr Pin operator[](int pin) {
- return Pin(*this, pin);
- }
-
- constexpr PinArray array(int first, int last) {
- return PinArray(*this, first, last);
- }
-};
-
-typedef GPIO_t::Pin Pin;
-typedef GPIO_t::PinArray PinArray;
-
-#if defined(STM32F0)
-static GPIO_t GPIOA(0x48000000);
-static GPIO_t GPIOB(0x48000400);
-static GPIO_t GPIOC(0x48000800);
-static GPIO_t GPIOD(0x48000c00);
-static GPIO_t GPIOE(0x48001000);
-static GPIO_t GPIOF(0x48001400);
-#elif defined(STM32F1)
-static GPIO_t GPIOA(0x40010800);
-static GPIO_t GPIOB(0x40010c00);
-static GPIO_t GPIOC(0x40011000);
-static GPIO_t GPIOD(0x40011400);
-static GPIO_t GPIOE(0x40011800);
-#elif defined(STM32F3)
-static GPIO_t GPIOA(0x48000000);
-static GPIO_t GPIOB(0x48000400);
-static GPIO_t GPIOC(0x48000800);
-static GPIO_t GPIOD(0x48000c00);
-static GPIO_t GPIOE(0x48001000);
-static GPIO_t GPIOF(0x48001400);
-#elif defined(STM32F4)
-static GPIO_t GPIOA(0x40020000);
-static GPIO_t GPIOB(0x40020400);
-static GPIO_t GPIOC(0x40020800);
-static GPIO_t GPIOD(0x40020c00);
-static GPIO_t GPIOE(0x40021000);
-static GPIO_t GPIOF(0x40021400);
-static GPIO_t GPIOG(0x40021800);
-static GPIO_t GPIOH(0x40021c00);
-static GPIO_t GPIOI(0x40022000);
-#elif defined(STM32L0)
-static GPIO_t GPIOA(0x50000000);
-static GPIO_t GPIOB(0x50000400);
-static GPIO_t GPIOC(0x50000800);
-static GPIO_t GPIOD(0x50000c00);
-static GPIO_t GPIOH(0x50001c00);
-#elif defined(STM32WB)
-static GPIO_t GPIOA(0x48000000);
-static GPIO_t GPIOB(0x48000400);
-static GPIO_t GPIOC(0x48000800);
-static GPIO_t GPIOD(0x48000c00);
-static GPIO_t GPIOE(0x48001000);
-#endif
-
-#endif
diff --git a/gpio/stm32_gpio.h b/gpio/stm32_gpio.h
new file mode 100644
index 0000000..6a428d4
--- /dev/null
+++ b/gpio/stm32_gpio.h
@@ -0,0 +1,253 @@
+#pragma once
+
+#include <mmio/mmio.h>
+
+struct STM32_GPIO_reg_v1_t {
+ volatile uint32_t CRL;
+ volatile uint32_t CRH;
+ volatile uint32_t IDR;
+ volatile uint32_t ODR;
+ volatile uint32_t BSRR;
+ volatile uint32_t BRR;
+ volatile uint32_t LCKR;
+};
+
+struct STM32_GPIO_reg_v2_t {
+ volatile uint32_t MODER;
+ volatile uint32_t OTYPER;
+ volatile uint32_t OSPEEDR;
+ volatile uint32_t PUPDR;
+ volatile uint32_t IDR;
+ volatile uint32_t ODR;
+ volatile uint32_t BSRR;
+ volatile uint32_t LCKR;
+ volatile uint32_t AFRL;
+ volatile uint32_t AFRH;
+};
+
+class STM32_GPIO_v1_t : public mmio_ptr<STM32_GPIO_reg_v1_t> {
+ public:
+ using mmio_ptr<STM32_GPIO_reg_v1_t>::ptr;
+
+ class Pin {
+ private:
+ const STM32_GPIO_v1_t& g;
+ int n;
+
+ public:
+ constexpr Pin(const STM32_GPIO_v1_t& gpio, int pin) : g(gpio), n(pin) {}
+
+ enum Mode {
+ Input = 0x4,
+ InputPull = 0x8,
+ Output = 0x3,
+ AF = 0xb,
+ Analog = 0x0,
+ };
+
+ void set_mode(Mode m) {
+ if(n < 8) {
+ g->CRL = (g->CRL & ~(0xf << (n * 4))) | m << (n * 4);
+ } else {
+ g->CRH = (g->CRH & ~(0xf << (n * 4 - 32))) | m << (n * 4 - 32);
+ }
+ }
+
+ void on() {
+ g->BSRR = 1 << n;
+ }
+
+ void off() {
+ g->BSRR = 1 << 16 << n;
+ }
+
+ void set(bool value) {
+ if(value) {
+ on();
+ } else {
+ off();
+ }
+ }
+
+ bool get() {
+ return g->IDR & (1 << n);
+ }
+
+ void toggle() {
+ set(!(g->ODR & (1 << n)));
+ }
+ };
+
+ class PinArray {
+ private:
+ const STM32_GPIO_v1_t& g;
+ int f;
+ int l;
+
+ constexpr uint32_t mask1() {
+ return ((2 << l) - 1) ^ ((1 << f) - 1);
+ }
+
+ constexpr uint32_t mask2() {
+ return ((4 << (l * 2)) - 1) ^ ((1 << (f * 2)) - 1);
+ }
+
+ public:
+ constexpr PinArray(const STM32_GPIO_v1_t& gpio, int first, int last) : g(gpio), f(first), l(last) {}
+
+ void set(uint16_t value) {
+ value <<= f;
+ g->BSRR = ((~value & mask1()) << 16) | (value & mask1());
+ }
+
+ uint16_t get() {
+ return (g->IDR & mask1()) >> f;
+ }
+ };
+
+ constexpr Pin operator[](int pin) const {
+ return Pin(*this, pin);
+ }
+
+ constexpr PinArray array(int first, int last) const {
+ return PinArray(*this, first, last);
+ }
+};
+
+class STM32_GPIO_v2_t : public mmio_ptr<STM32_GPIO_reg_v2_t> {
+ public:
+ using mmio_ptr<STM32_GPIO_reg_v2_t>::ptr;
+
+ class Pin {
+ private:
+ const STM32_GPIO_v2_t& g;
+ int n;
+
+ public:
+ constexpr Pin(const STM32_GPIO_v2_t& gpio, int pin) : g(gpio), n(pin) {}
+
+ enum Mode {
+ Input,
+ Output,
+ AF,
+ Analog,
+ };
+
+ enum Type {
+ PushPull,
+ OpenDrain,
+ };
+
+ enum Pull {
+ PullNone,
+ PullUp,
+ PullDown,
+ };
+
+ enum Speed {
+ Low,
+ Medium,
+ Fast,
+ High,
+ };
+
+ void set_mode(Mode m) {
+ g->MODER = (g->MODER & ~(3 << (n * 2))) | m << (n * 2);
+ }
+
+ void set_type(Type t) {
+ if(t) {
+ g->OTYPER |= 1 << n;
+ } else {
+ g->OTYPER &= ~(1 << n);
+ }
+ }
+
+ void set_pull(Pull p) {
+ g->PUPDR = (g->PUPDR & ~(3 << (n * 2))) | p << (n * 2);
+ }
+
+ void set_af(int af) {
+ if(n < 8) {
+ g->AFRL = (g->AFRL & ~(0xf << (n * 4))) | af << (n * 4);
+ } else {
+ g->AFRH = (g->AFRH & ~(0xf << (n * 4 - 32))) | af << (n * 4 - 32);
+ }
+ }
+
+ void set_speed(Speed s) {
+ g->OSPEEDR = (g->OSPEEDR & ~(3 << (n * 2))) | s << (n * 2);
+ }
+
+ void on() {
+ g->BSRR = 1 << n;
+ }
+
+ void off() {
+ g->BSRR = 1 << 16 << n;
+ }
+
+ void set(bool value) {
+ if(value) {
+ on();
+ } else {
+ off();
+ }
+ }
+
+ bool get() {
+ return g->IDR & (1 << n);
+ }
+
+ void toggle() {
+ set(!(g->ODR & (1 << n)));
+ }
+ };
+
+ class PinArray {
+ private:
+ const STM32_GPIO_v2_t& g;
+ int f;
+ int l;
+
+ constexpr uint32_t mask1() {
+ return ((2 << l) - 1) ^ ((1 << f) - 1);
+ }
+
+ constexpr uint32_t mask2() {
+ return ((4 << (l * 2)) - 1) ^ ((1 << (f * 2)) - 1);
+ }
+
+ public:
+ constexpr PinArray(const STM32_GPIO_v2_t& gpio, int first, int last) : g(gpio), f(first), l(last) {}
+
+ void set_mode(Pin::Mode m) {
+ g->MODER = (g->MODER & ~mask2()) | ((0x55555555 * m) & mask2());
+ }
+
+ void set_type(Pin::Type t) {
+ g->OTYPER = (g->OTYPER & ~mask2()) | ((0x55555555 * t) & mask2());
+ }
+
+ void set_pull(Pin::Pull p) {
+ g->PUPDR = (g->PUPDR & ~mask2()) | ((0x55555555 * p) & mask2());
+ }
+
+ void set(uint16_t value) {
+ value <<= f;
+ g->BSRR = ((~value & mask1()) << 16) | (value & mask1());
+ }
+
+ uint16_t get() {
+ return (g->IDR & mask1()) >> f;
+ }
+ };
+
+ constexpr Pin operator[](int pin) const {
+ return Pin(*this, pin);
+ }
+
+ constexpr PinArray array(int first, int last) const {
+ return PinArray(*this, first, last);
+ }
+};
diff --git a/platforms/stm32/f0.yaml b/platforms/stm32/f0.yaml
new file mode 100644
index 0000000..6e8899a
--- /dev/null
+++ b/platforms/stm32/f0.yaml
@@ -0,0 +1,21 @@
+# This is incomplete, just preserving register addresses!
+- periph:
+ stm32_gpio:
+ GPIOA:
+ offset: 0x48000000
+ type: v2
+ GPIOB:
+ offset: 0x48000400
+ type: v2
+ GPIOC:
+ offset: 0x48000800
+ type: v2
+ GPIOD:
+ offset: 0x48000c00
+ type: v2
+ GPIOE:
+ offset: 0x48001000
+ type: v2
+ GPIOF:
+ offset: 0x48001400
+ type: v2
diff --git a/platforms/stm32/f1.yaml b/platforms/stm32/f1.yaml
index ed97844..a71a319 100644
--- a/platforms/stm32/f1.yaml
+++ b/platforms/stm32/f1.yaml
@@ -1,5 +1,21 @@
# This is incomplete, just preserving register addresses!
- periph:
+ stm32_gpio:
+ GPIOA:
+ offset: 0x40010800
+ type: v1
+ GPIOB:
+ offset: 0x40010c00
+ type: v1
+ GPIOC:
+ offset: 0x40011000
+ type: v1
+ GPIOD:
+ offset: 0x40011400
+ type: v1
+ GPIOE:
+ offset: 0x40011800
+ type: v1
stm32_timer:
TIM1:
offset: 0x40012c00
diff --git a/platforms/stm32/f3.yaml b/platforms/stm32/f3.yaml
index ed97844..4cbb3b8 100644
--- a/platforms/stm32/f3.yaml
+++ b/platforms/stm32/f3.yaml
@@ -1,5 +1,24 @@
# This is incomplete, just preserving register addresses!
- periph:
+ stm32_gpio:
+ GPIOA:
+ offset: 0x48000000
+ type: v2
+ GPIOB:
+ offset: 0x48000400
+ type: v2
+ GPIOC:
+ offset: 0x48000800
+ type: v2
+ GPIOD:
+ offset: 0x48000c00
+ type: v2
+ GPIOE:
+ offset: 0x48001000
+ type: v2
+ GPIOF:
+ offset: 0x48001400
+ type: v2
stm32_timer:
TIM1:
offset: 0x40012c00
diff --git a/platforms/stm32/f4.yaml b/platforms/stm32/f4.yaml
index d362fa4..429e31b 100644
--- a/platforms/stm32/f4.yaml
+++ b/platforms/stm32/f4.yaml
@@ -29,6 +29,34 @@
size: 64k
periph:
+ stm32_gpio:
+ GPIOA:
+ offset: 0x40020000
+ type: v2
+ GPIOB:
+ offset: 0x40020400
+ type: v2
+ GPIOC:
+ offset: 0x40020800
+ type: v2
+ GPIOD:
+ offset: 0x40020c00
+ type: v2
+ GPIOE:
+ offset: 0x40021000
+ type: v2
+ GPIOF:
+ offset: 0x40021400
+ type: v2
+ GPIOG:
+ offset: 0x40021800
+ type: v2
+ GPIOH:
+ offset: 0x40021c00
+ type: v2
+ GPIOI:
+ offset: 0x40022000
+ type: v2
stm32_timer:
TIM1:
diff --git a/platforms/stm32/l0.yaml b/platforms/stm32/l0.yaml
new file mode 100644
index 0000000..75c4330
--- /dev/null
+++ b/platforms/stm32/l0.yaml
@@ -0,0 +1,18 @@
+# This is incomplete, just preserving register addresses!
+- periph:
+ stm32_gpio:
+ GPIOA:
+ offset: 0x50000000
+ type: v2
+ GPIOB:
+ offset: 0x50000400
+ type: v2
+ GPIOC:
+ offset: 0x50000800
+ type: v2
+ GPIOD:
+ offset: 0x50000c00
+ type: v2
+ GPIOH:
+ offset: 0x50001c00
+ type: v2
diff --git a/platforms/stm32/wb.yaml b/platforms/stm32/wb.yaml
index cb1d5fb..152ea28 100644
--- a/platforms/stm32/wb.yaml
+++ b/platforms/stm32/wb.yaml
@@ -31,14 +31,19 @@
stm32_gpio:
GPIOA:
offset: 0x48000000
+ type: v2
GPIOB:
offset: 0x48000400
+ type: v2
GPIOC:
offset: 0x48000800
+ type: v2
GPIOD:
offset: 0x48000c00
+ type: v2
GPIOE:
offset: 0x48001000
+ type: v2
stm32_timer:
TIM1:
diff --git a/templates/periph_instances.h.j2 b/templates/periph_instances.h.j2
index ddbff34..0761f5d 100644
--- a/templates/periph_instances.h.j2
+++ b/templates/periph_instances.h.j2
@@ -17,3 +17,7 @@ constexpr {{ instance.type }} {{ instance.name }}{
{% for alias, ref in (aliases.items() if aliases else {}) %}
constexpr auto {{ alias }} = {{ ref }};
{% endfor %}
+
+{% for alias, ref in (type_aliases.items() if type_aliases else {}) %}
+using {{ alias }} = {{ ref }};
+{% endfor %}