From d5fbedc24fdd41e7c30b2f9239f666f33893e065 Mon Sep 17 00:00:00 2001 From: Vegard Storheil Eriksen Date: Thu, 16 Sep 2021 23:50:26 +0200 Subject: gpio: Generate instances from platform spec. --- .gitignore | 1 + SConscript | 1 + gpio/SConscript | 25 ++++ gpio/gpio.h | 250 --------------------------------------- gpio/stm32_gpio.h | 253 ++++++++++++++++++++++++++++++++++++++++ platforms/stm32/f0.yaml | 21 ++++ platforms/stm32/f1.yaml | 16 +++ platforms/stm32/f3.yaml | 19 +++ platforms/stm32/f4.yaml | 28 +++++ platforms/stm32/l0.yaml | 18 +++ platforms/stm32/wb.yaml | 5 + templates/periph_instances.h.j2 | 4 + 12 files changed, 391 insertions(+), 250 deletions(-) create mode 100644 gpio/SConscript delete mode 100644 gpio/gpio.h create mode 100644 gpio/stm32_gpio.h create mode 100644 platforms/stm32/f0.yaml create mode 100644 platforms/stm32/l0.yaml 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 - -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 + +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 { + public: + using mmio_ptr::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 { + public: + using mmio_ptr::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 %} -- cgit v1.2.3