From 00301ca88f168077d2e40d2eb5474b15a8559011 Mon Sep 17 00:00:00 2001 From: Niklas Hauser Date: Fri, 1 May 2020 17:16:33 +0200 Subject: [PATCH 1/2] [modm-devices] Remove use of device.properties --- docs/src/how-modm-works.md | 2 +- src/modm/platform/adc/stm32f3/module.lb | 12 ++----- src/modm/platform/can/lpc/module.lb | 11 +++--- src/modm/platform/can/stm32/module.lb | 32 +++++------------ src/modm/platform/clock/lpc/module.lb | 2 +- src/modm/platform/comp/stm32/module.lb | 6 ++-- src/modm/platform/dma/stm32/module.lb | 3 +- src/modm/platform/gpio/lpc/module.lb | 2 +- .../platform/i2c/at90_tiny_mega/module.lb | 9 ----- .../platform/i2c/stm32-extended/module.lb | 13 +++---- src/modm/platform/i2c/stm32/module.lb | 12 +++---- src/modm/platform/i2c/xmega/module.lb | 2 +- src/modm/platform/random/stm32/module.lb | 7 +--- .../platform/spi/at90_tiny_mega/module.lb | 34 +++++++------------ .../spi/at90_tiny_mega_uart/module.lb | 15 +++----- src/modm/platform/spi/lpc/module.lb | 2 +- src/modm/platform/spi/stm32_uart/module.lb | 29 +++++----------- src/modm/platform/spi/xmega/module.lb | 2 +- src/modm/platform/timer/lpc/module.lb | 17 ++-------- src/modm/platform/timer/xmega/module.lb | 33 ------------------ .../platform/uart/at90_tiny_mega/module.lb | 27 +++------------ src/modm/platform/uart/lpc/module.lb | 2 +- src/modm/platform/uart/xmega/module.lb | 2 +- 23 files changed, 67 insertions(+), 209 deletions(-) delete mode 100644 src/modm/platform/timer/xmega/module.lb diff --git a/docs/src/how-modm-works.md b/docs/src/how-modm-works.md index dfbcf841fb..13461d72c7 100644 --- a/docs/src/how-modm-works.md +++ b/docs/src/how-modm-works.md @@ -56,7 +56,7 @@ def prepare(module, options): def build(env): device = env[":target"] - env.substitutions = device.properties + env.substitutions = device.get_driver("uart") env.outbasepath = "src/modm/platform/uart" for instance in device.get_driver("uart:stm32*")["instance"]: env.template("uart.hpp.in", "uart_{}.hpp".format(instance)) diff --git a/src/modm/platform/adc/stm32f3/module.lb b/src/modm/platform/adc/stm32f3/module.lb index c2843e47fa..73bd57467b 100644 --- a/src/modm/platform/adc/stm32f3/module.lb +++ b/src/modm/platform/adc/stm32f3/module.lb @@ -27,7 +27,7 @@ class Instance(Module): device = env[":target"] driver = device.get_driver("adc") - properties = device.properties + properties = {} properties["target"] = target = device.identifier instance_id = int(self.instance) properties["id"] = instance_id @@ -151,12 +151,4 @@ def prepare(module, options): return True def build(env): - device = env[":target"] - driver = device.get_driver("adc") - - properties = device.properties - properties["target"] = device.identifier - properties["driver"] = driver - - env.substitutions = properties - env.outbasepath = "modm/src/modm/platform/adc" + pass diff --git a/src/modm/platform/can/lpc/module.lb b/src/modm/platform/can/lpc/module.lb index c2e52dad64..d9cd9f00b1 100644 --- a/src/modm/platform/can/lpc/module.lb +++ b/src/modm/platform/can/lpc/module.lb @@ -38,13 +38,10 @@ def prepare(module, options): def build(env): device = env[":target"] - driver = device.get_driver("can") - - properties = device.properties - properties["target"] = target = device.identifier - properties["driver"] = driver - - env.substitutions = properties + env.substitutions = { + "target": device.identifier, + "driver": device.get_driver("can"), + } env.outbasepath = "modm/src/modm/platform/can" env.template("c_can.cpp.in") diff --git a/src/modm/platform/can/stm32/module.lb b/src/modm/platform/can/stm32/module.lb index 6c07ffdcf8..6874166cdb 100644 --- a/src/modm/platform/can/stm32/module.lb +++ b/src/modm/platform/can/stm32/module.lb @@ -76,16 +76,17 @@ can_map = { }, } -def get_substitutions(instance, device, env): - target = device.identifier - driver = device.get_driver("can") +def get_substitutions(env, instance): + target = env["target"].identifier + driver = env["target"].get_driver("can") instances = map(lambda i: int(i), driver["instance"]) if "instance" in driver else (0,) - cm = can_map[target["family"]] + cm = can_map[target.family] is_single = (cm[instance].type == CanType.Single) or (cm[instance].associated_instance not in instances) other = cm[instance].associated_instance subs = { + "target": target, "id": "" if instance == 0 else str(instance), "own_instance": cm[instance].register, "other_instance": cm[other].register if other in cm else None, @@ -109,15 +110,7 @@ class Instance(Module): return True def build(self, env): - device = env[":target"] - driver = device.get_driver("can") - - properties = device.properties - properties["target"] = target = device.identifier - properties["driver"] = driver - properties.update(get_substitutions(self.instance, device, env)) - - env.substitutions = properties + env.substitutions = get_substitutions(env, self.instance) env.outbasepath = "modm/src/modm/platform/can" env.template("can.hpp.in", "can_{}.hpp".format(self.instance)) @@ -159,22 +152,13 @@ def prepare(module, options): return True def build(env): - device = env[":target"] - driver = device.get_driver("can") - - properties = device.properties - properties["target"] = device.identifier - properties["driver"] = driver - - if "instance" not in driver: - properties.update(get_substitutions(0, device, env)) - - env.substitutions = properties + env.substitutions = {"target": env[":target"].identifier} env.outbasepath = "modm/src/modm/platform/can" env.template("can_filter.hpp.in") env.template("can_filter.cpp.in") if "instance" not in driver: + env.substitutions = get_substitutions(env, 0) env.template("can.hpp.in") env.template("can.cpp.in") diff --git a/src/modm/platform/clock/lpc/module.lb b/src/modm/platform/clock/lpc/module.lb index c8000f9d13..c40df2f4de 100644 --- a/src/modm/platform/clock/lpc/module.lb +++ b/src/modm/platform/clock/lpc/module.lb @@ -25,7 +25,7 @@ def build(env): device = env[":target"] driver = device.get_driver("clock") - properties = device.properties + properties = {} properties["target"] = target = device.identifier properties["driver"] = driver diff --git a/src/modm/platform/comp/stm32/module.lb b/src/modm/platform/comp/stm32/module.lb index 87aee6f45d..e1253a0ace 100644 --- a/src/modm/platform/comp/stm32/module.lb +++ b/src/modm/platform/comp/stm32/module.lb @@ -26,7 +26,7 @@ class Instance(Module): device = env[":target"] driver = device.get_driver("comp") - properties = device.properties + properties = {} properties["target"] = device.identifier instance_id = int(self.instance) properties["id"] = instance_id @@ -50,8 +50,6 @@ class Instance(Module): properties["blanking_source"]["b010"] = "Tim2Oc3" properties["blanking_source"]["b011"] = "Tim3Oc3" - - env.substitutions = properties env.outbasepath = "modm/src/modm/platform/comp" @@ -109,7 +107,7 @@ def build(env): device = env[":target"] driver = device.get_driver("comp") - properties = device.properties + properties = {} properties["target"] = device.identifier properties["driver"] = driver properties["csr"] = "COMP_CSR_" if device.identifier["family"] in ["l4", "g4"] else "COMP_CSR_COMPx" diff --git a/src/modm/platform/dma/stm32/module.lb b/src/modm/platform/dma/stm32/module.lb index 20d50a2d39..655d37d6c6 100644 --- a/src/modm/platform/dma/stm32/module.lb +++ b/src/modm/platform/dma/stm32/module.lb @@ -34,7 +34,7 @@ def prepare(module, options): def build(env): device = env[":target"] - properties = device.properties + properties = {} properties["target"] = device.identifier dma = device.get_driver("dma") properties["dma"] = dma @@ -60,7 +60,6 @@ def build(env): env.substitutions = properties env.outbasepath = "modm/src/modm/platform/dma" - env.template("dma_base.hpp.in") env.template("dma_hal.hpp.in") env.template("dma_hal_impl.hpp.in") diff --git a/src/modm/platform/gpio/lpc/module.lb b/src/modm/platform/gpio/lpc/module.lb index 6fae601442..ec11d66a1b 100644 --- a/src/modm/platform/gpio/lpc/module.lb +++ b/src/modm/platform/gpio/lpc/module.lb @@ -25,7 +25,7 @@ def build(env): device = env[":target"] driver = device.get_driver("gpio") - properties = device.properties + properties = {} properties["target"] = target = device.identifier properties["driver"] = driver diff --git a/src/modm/platform/i2c/at90_tiny_mega/module.lb b/src/modm/platform/i2c/at90_tiny_mega/module.lb index 30179ffe4e..80adff4bb0 100644 --- a/src/modm/platform/i2c/at90_tiny_mega/module.lb +++ b/src/modm/platform/i2c/at90_tiny_mega/module.lb @@ -32,16 +32,7 @@ def prepare(module, options): return True def build(env): - device = env[":target"] - driver = device.get_driver("i2c") - - properties = device.properties - properties["target"] = device.identifier - properties["driver"] = driver - - env.substitutions = properties env.outbasepath = "modm/src/modm/platform/i2c" - env.template("i2c.hpp.in") env.template("i2c_master.hpp.in") env.template("i2c_master.cpp.in") diff --git a/src/modm/platform/i2c/stm32-extended/module.lb b/src/modm/platform/i2c/stm32-extended/module.lb index 4d37b4fc04..a361b5325c 100644 --- a/src/modm/platform/i2c/stm32-extended/module.lb +++ b/src/modm/platform/i2c/stm32-extended/module.lb @@ -31,15 +31,10 @@ class Instance(Module): return True def build(self, env): - device = env[":target"] - driver = device.get_driver("i2c") - - properties = device.properties - properties["target"] = target = device.identifier - properties["id"] = self.instance - properties["shared_interrupt"] = "0" in target.family - - env.substitutions = properties + env.substitutions = { + "shared_interrupt": "0" in env[":target"].identifier.family, + "id": self.instance, + } env.outbasepath = "modm/src/modm/platform/i2c" env.template("i2c_master.cpp.in", "i2c_master_{}.cpp".format(self.instance)) diff --git a/src/modm/platform/i2c/stm32/module.lb b/src/modm/platform/i2c/stm32/module.lb index d3bcd81941..c72c032dfc 100644 --- a/src/modm/platform/i2c/stm32/module.lb +++ b/src/modm/platform/i2c/stm32/module.lb @@ -32,14 +32,10 @@ class Instance(Module): return True def build(self, env): - device = env[":target"] - driver = device.get_driver("i2c") - - properties = device.properties - properties["target"] = target = device.identifier - properties["id"] = self.instance - - env.substitutions = properties + env.substitutions = { + "target": env[":target"].identifier, + "id": self.instance + } env.outbasepath = "modm/src/modm/platform/i2c" env.template("i2c_master.cpp.in", "i2c_master_{}.cpp".format(self.instance)) diff --git a/src/modm/platform/i2c/xmega/module.lb b/src/modm/platform/i2c/xmega/module.lb index 87a39601e1..4cea0db5b2 100644 --- a/src/modm/platform/i2c/xmega/module.lb +++ b/src/modm/platform/i2c/xmega/module.lb @@ -14,7 +14,7 @@ def get_properties(env): device = env[":target"] driver = device.get_driver("i2c:xmega") - properties = device.properties + properties = {} properties["target"] = device.identifier properties["driver"] = driver return properties diff --git a/src/modm/platform/random/stm32/module.lb b/src/modm/platform/random/stm32/module.lb index 6555b906bb..2e7230808a 100644 --- a/src/modm/platform/random/stm32/module.lb +++ b/src/modm/platform/random/stm32/module.lb @@ -22,12 +22,7 @@ def prepare(module, options): return True def build(env): - device = env[":target"] - - properties = device.properties - properties["target"] = device.identifier - - env.substitutions = properties + env.substitutions = {"target": env[":target"].identifier} env.outbasepath = "modm/src/modm/platform/random" env.template("random_number_generator.hpp.in") diff --git a/src/modm/platform/spi/at90_tiny_mega/module.lb b/src/modm/platform/spi/at90_tiny_mega/module.lb index 46fa67ee62..d54602bbe6 100644 --- a/src/modm/platform/spi/at90_tiny_mega/module.lb +++ b/src/modm/platform/spi/at90_tiny_mega/module.lb @@ -11,15 +11,6 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. # ----------------------------------------------------------------------------- -def get_properties(env): - device = env[":target"] - driver = device.get_driver("spi:avr") - properties = device.properties - properties["target"] = device.identifier - properties["partname"] = device.partname - properties["driver"] = driver - return properties - def load_options(module): module.add_option( BooleanOption( @@ -42,10 +33,11 @@ class Instance(Module): return True def build(self, env): - properties = get_properties(env) - properties["id"] = self.instance - - env.substitutions = properties + env.substitutions = { + "target": env[":target"].identifier, + "partname": env[":target"].partname, + "id": self.instance, + } env.outbasepath = "modm/src/modm/platform/spi" env.template("spi.hpp.in", "spi{}.hpp".format(self.instance)) @@ -77,16 +69,14 @@ def prepare(module, options): return True def build(env): - properties = get_properties(env) - driver = properties["driver"] - - if "instance" not in driver: - properties["id"] = "" - - env.substitutions = properties - env.outbasepath = "modm/src/modm/platform/spi" - + driver = env[":target"].get_driver("spi") if "instance" not in driver: + env.substitutions = { + "target": env[":target"].identifier, + "partname": env[":target"].partname, + "id": "", + } + env.outbasepath = "modm/src/modm/platform/spi" env.template("spi_master.hpp.in") env.template("spi_master.cpp.in") env.template("spi.hpp.in") diff --git a/src/modm/platform/spi/at90_tiny_mega_uart/module.lb b/src/modm/platform/spi/at90_tiny_mega_uart/module.lb index 24b0e88fcb..c575856547 100644 --- a/src/modm/platform/spi/at90_tiny_mega_uart/module.lb +++ b/src/modm/platform/spi/at90_tiny_mega_uart/module.lb @@ -13,11 +13,7 @@ def get_properties(env): device = env[":target"] - driver = device.get_driver("spi:avr_uart") - properties = device.properties - properties["target"] = device.identifier - properties["driver"] = driver - return properties + return {"target": device.identifier} class Instance(Module): @@ -52,10 +48,8 @@ class Instance(Module): return True def build(self, env): - properties = get_properties(env) - properties["id"] = self.instance - - target = properties["target"] + target = env[":target"].identifier + properties = {"target": target, "id": self.instance} properties["extended"] = False if target["name"] in ["48", "88", "168", "328"] and target["type"] == "p": @@ -102,5 +96,4 @@ def prepare(module, options): return True def build(env): - env.substitutions = get_properties(env) - env.outbasepath = "modm/src/modm/platform/spi_uart" + pass diff --git a/src/modm/platform/spi/lpc/module.lb b/src/modm/platform/spi/lpc/module.lb index 4fff669c2c..0a8f22d915 100644 --- a/src/modm/platform/spi/lpc/module.lb +++ b/src/modm/platform/spi/lpc/module.lb @@ -25,7 +25,7 @@ def build(env): device = env[":target"] driver = device.get_driver("spi") - properties = device.properties + properties = {} properties["target"] = target = device.identifier properties["driver"] = driver diff --git a/src/modm/platform/spi/stm32_uart/module.lb b/src/modm/platform/spi/stm32_uart/module.lb index 50d078b0df..dc4bd18361 100644 --- a/src/modm/platform/spi/stm32_uart/module.lb +++ b/src/modm/platform/spi/stm32_uart/module.lb @@ -10,14 +10,6 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. # ----------------------------------------------------------------------------- -def get_properties(env): - device = env[":target"] - driver = device.get_driver("usart:stm32") - properties = device.properties - properties["target"] = device.identifier - properties["driver"] = driver - return properties - class Instance(Module): def __init__(self, instance, is_extended = False): self.instance = instance @@ -32,16 +24,17 @@ class Instance(Module): return True def build(self, env): - properties = get_properties(env) - properties["id"] = self.instance - properties["extended"] = self.is_extended - - env.substitutions = properties + env.substitutions = { + "target": env[":target"].identifier, + "id": self.instance, + "extended": self.is_extended, + } env.outbasepath = "modm/src/modm/platform/spi" env.template("uart_spi_master.hpp.in", "uart_spi_master_{}.hpp".format(self.instance)) env.template("uart_spi_master.cpp.in", "uart_spi_master_{}.cpp".format(self.instance)) + def init(module): module.name = ":platform:uart.spi" module.description = "USART in SPI Mode" @@ -57,13 +50,9 @@ def prepare(module, options): ":platform:gpio", ":platform:uart") - if device.get_driver("usart:stm32-extended"): - for instance in device.get_driver("usart:stm32-extended")["instance"]: - module.add_submodule(Instance(int(instance), True)) - - if device.get_driver("usart:stm32"): - for instance in device.get_driver("usart:stm32")["instance"]: - module.add_submodule(Instance(int(instance))) + for driver in device.get_all_drivers("usart"): + for instance in listify(driver["instance"]): + module.add_submodule(Instance(int(instance), "extended" in driver["type"])) return True diff --git a/src/modm/platform/spi/xmega/module.lb b/src/modm/platform/spi/xmega/module.lb index d4de282bc3..84bb7d2deb 100644 --- a/src/modm/platform/spi/xmega/module.lb +++ b/src/modm/platform/spi/xmega/module.lb @@ -26,7 +26,7 @@ def build(env): device = env[":target"] driver = device.get_driver("spi") - properties = device.properties + properties = {} properties["target"] = device.identifier properties["driver"] = driver diff --git a/src/modm/platform/timer/lpc/module.lb b/src/modm/platform/timer/lpc/module.lb index cc2c4fb86c..0696c64447 100644 --- a/src/modm/platform/timer/lpc/module.lb +++ b/src/modm/platform/timer/lpc/module.lb @@ -11,15 +11,6 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. # ----------------------------------------------------------------------------- -def get_properties(env): - device = env[":target"] - driver = device.get_driver("timer") - properties = device.properties - properties["target"] = device.identifier - properties["driver"] = driver - return properties - - class Instance(Module): def __init__(self, instance): self.instance = instance @@ -33,10 +24,8 @@ class Instance(Module): return True def build(self, env): - properties = get_properties(env) - properties["id"] = self.instance - - env.substitutions = properties + env.substitutions = {"target": env["target"].identifier, + "id": self.instance} env.outbasepath = "modm/src/modm/platform/timer" env.template("timer.hpp.in", "timer_{}.hpp".format(self.instance)) @@ -58,7 +47,7 @@ def prepare(module, options): return True def build(env): - env.substitutions = get_properties(env) + env.substitutions = {"target": env["target"].identifier} env.outbasepath = "modm/src/modm/platform/timer" env.copy("timer_registers.hpp") diff --git a/src/modm/platform/timer/xmega/module.lb b/src/modm/platform/timer/xmega/module.lb deleted file mode 100644 index 53732ebb0c..0000000000 --- a/src/modm/platform/timer/xmega/module.lb +++ /dev/null @@ -1,33 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -# -# Copyright (c) 2016-2017, Niklas Hauser -# Copyright (c) 2017, Fabian Greif -# -# This file is part of the modm project. -# -# This Source Code Form is subject to the terms of the Mozilla Public -# License, v. 2.0. If a copy of the MPL was not distributed with this -# file, You can obtain one at http://mozilla.org/MPL/2.0/. -# ----------------------------------------------------------------------------- - -def init(module): - module.name = ":platform:timer" - -def prepare(module, options): - if not options[":target"].has_driver("timer:xmega"): - return False - - module.depends(":platform:core") - return True - -def build(env): - device = env[":target"] - driver = device.get_driver("timer") - - properties = device.properties - properties["target"] = target = device.identifier - properties["driver"] = driver - - env.substitutions = properties - env.outbasepath = "modm/src/modm/platform/timer" diff --git a/src/modm/platform/uart/at90_tiny_mega/module.lb b/src/modm/platform/uart/at90_tiny_mega/module.lb index 8d3a393cbf..96cfef07dd 100644 --- a/src/modm/platform/uart/at90_tiny_mega/module.lb +++ b/src/modm/platform/uart/at90_tiny_mega/module.lb @@ -11,14 +11,6 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. # ----------------------------------------------------------------------------- -def get_properties(env): - device = env[":target"] - driver = device.get_driver("usart:avr") - properties = device.properties - properties["target"] = device.identifier - properties["driver"] = driver - return properties - def load_options(module): module.add_option( BooleanOption( @@ -52,16 +44,13 @@ class Instance(Module): return True def build(self, env): - properties = get_properties(env) - target = properties["target"] - - if target["family"] == "tiny" and target["name"] in ["828", "2313", "4313"]: + target = env[":target"].identifier + if target.family == "tiny" and target.name in ["828", "2313", "4313"]: instance = "" else: instance = self.instance - properties["id"] = instance - env.substitutions = properties + env.substitutions = {"id": instance} env.outbasepath = "modm/src/modm/platform/uart" env.template("uart.hpp.in", "uart{}.hpp".format(instance)) @@ -95,18 +84,12 @@ def prepare(module, options): return True def build(env): - properties = get_properties(env) - driver = properties["driver"] - - if "instance" not in driver: - properties["id"] = "" - - env.substitutions = properties env.outbasepath = "modm/src/modm/platform/uart" - env.template("uart_defines.h") + driver = env[":target"].get_driver("usart:avr") if "instance" not in driver: + env.substitutions = {"id": ""} env.template("uart.hpp.in") env.template("uart_tx.cpp.in") env.template("uart_rx.cpp.in") diff --git a/src/modm/platform/uart/lpc/module.lb b/src/modm/platform/uart/lpc/module.lb index 4a81b74b84..e0a5da8d73 100644 --- a/src/modm/platform/uart/lpc/module.lb +++ b/src/modm/platform/uart/lpc/module.lb @@ -14,7 +14,7 @@ def get_properties(env): device = env[":target"] driver = device.get_driver("uart") - properties = device.properties + properties = {} properties["target"] = device.identifier properties["driver"] = driver return properties diff --git a/src/modm/platform/uart/xmega/module.lb b/src/modm/platform/uart/xmega/module.lb index 93bee55b6d..ef0d191771 100644 --- a/src/modm/platform/uart/xmega/module.lb +++ b/src/modm/platform/uart/xmega/module.lb @@ -14,7 +14,7 @@ def get_properties(env): device = env[":target"] driver = device.get_driver("uart") - properties = device.properties + properties = {} properties["target"] = device.identifier properties["driver"] = driver return properties From 1b92f66a95c92cf3231ab65595e060e9eec4fc3c Mon Sep 17 00:00:00 2001 From: Niklas Hauser Date: Sun, 21 Feb 2021 03:52:43 +0100 Subject: [PATCH 2/2] [modm-devices] Refactor data access --- README.md | 2 +- examples/nucleo_f767zi/ethernet/main.cpp | 7 +- ext/modm-devices | 2 +- ext/st/stm32 | 2 +- repo.lb | 8 + src/modm/board/disco_f746ng/board.hpp | 12 +- src/modm/driver/gpio/gpio_sampler.lb | 22 +- src/modm/platform/adc/stm32/module.lb | 47 ++- src/modm/platform/adc/stm32f0/module.lb | 11 +- src/modm/platform/adc/stm32f3/module.lb | 4 +- src/modm/platform/can/stm32/module.lb | 19 +- src/modm/platform/clock/stm32/module.lb | 29 +- src/modm/platform/comp/stm32/base.hpp.in | 10 +- src/modm/platform/comp/stm32/comp.hpp.in | 6 +- src/modm/platform/comp/stm32/module.lb | 12 +- src/modm/platform/core/cortex/module.lb | 4 +- src/modm/platform/core/stm32/module.lb | 6 +- .../{gpio => core}/stm32/peripherals.hpp.in | 10 +- .../platform/gpio/at90_tiny_mega/base.hpp.in | 13 +- .../platform/gpio/at90_tiny_mega/module.lb | 2 +- src/modm/platform/gpio/sam/module.lb | 7 +- src/modm/platform/gpio/stm32/base.hpp.in | 14 +- .../gpio/stm32/connector_specialized.hpp.in | 8 +- src/modm/platform/gpio/stm32/module.lb | 333 +++++------------- src/modm/platform/gpio/stm32/pin.hpp.in | 89 +++-- src/modm/platform/gpio/stm32/pin_f1.hpp.in | 235 ------------ src/modm/platform/gpio/stm32/port.hpp.in | 35 +- src/modm/platform/gpio/stm32/set.hpp.in | 98 +++--- .../platform/gpio/stm32/software_port.hpp.in | 9 +- src/modm/platform/gpio/stm32/unused.hpp.in | 6 +- .../platform/i2c/stm32-extended/module.lb | 4 +- src/modm/platform/i2c/stm32/module.lb | 4 +- .../platform/spi/at90_tiny_mega/module.lb | 16 +- .../spi/at90_tiny_mega_uart/module.lb | 4 +- src/modm/platform/spi/stm32/module.lb | 8 +- src/modm/platform/spi/stm32_uart/module.lb | 6 +- src/modm/platform/timer/stm32/module.lb | 42 +-- .../platform/uart/at90_tiny_mega/module.lb | 11 +- src/modm/platform/uart/sam/module.lb | 21 +- src/modm/platform/uart/stm32/module.lb | 48 ++- src/modm/platform/usb/stm32/module.lb | 5 +- test/modm/platform/gpio/module.lb | 4 +- tools/build_script_generator/common.py | 2 +- 43 files changed, 405 insertions(+), 832 deletions(-) rename src/modm/platform/{gpio => core}/stm32/peripherals.hpp.in (71%) delete mode 100644 src/modm/platform/gpio/stm32/pin_f1.hpp.in diff --git a/README.md b/README.md index c57acccc64..3bac206b5d 100644 --- a/README.md +++ b/README.md @@ -71,7 +71,7 @@ git clone --recurse-submodules https://github.com/modm-io/modm.git ## Targets modm can generate code for 506 -AVR, 163 SAM and 2010 +AVR, 163 SAM and 2110 STM32 devices, however, there are different levels of support and testing.
diff --git a/examples/nucleo_f767zi/ethernet/main.cpp b/examples/nucleo_f767zi/ethernet/main.cpp index 628bd2d34e..0ae88c3b2d 100755 --- a/examples/nucleo_f767zi/ethernet/main.cpp +++ b/examples/nucleo_f767zi/ethernet/main.cpp @@ -188,11 +188,12 @@ main() Leds::setOutput(); MODM_LOG_INFO << "\n\nReboot: Ethernet Example" << modm::endl; - Ethernet::Port::connect(); usb_hs::Device::connect< - usb_hs::Ck::Ulpick, usb_hs::Stp::Ulpistp, - usb_hs::Dir::Ulpidir, usb_hs::Nxt::Ulpinxt, - usb_hs::D0::Ulpid0, usb_hs::D1::Ulpid1, - usb_hs::D2::Ulpid2, usb_hs::D3::Ulpid3, - usb_hs::D4::Ulpid4, usb_hs::D5::Ulpid5, - usb_hs::D6::Ulpid6, usb_hs::D7::Ulpid7>(); + usb_hs::Ck::UlpiCk, usb_hs::Stp::UlpiStp, + usb_hs::Dir::UlpiDir, usb_hs::Nxt::UlpiNxt, + usb_hs::D0::UlpiD0, usb_hs::D1::UlpiD1, + usb_hs::D2::UlpiD2, usb_hs::D3::UlpiD3, + usb_hs::D4::UlpiD4, usb_hs::D5::UlpiD5, + usb_hs::D6::UlpiD6, usb_hs::D7::UlpiD7>(); usb_hs::Overcurrent::setInput(); // Deactivate VBUS Sensing B diff --git a/src/modm/driver/gpio/gpio_sampler.lb b/src/modm/driver/gpio/gpio_sampler.lb index 6710e3e785..23a106fc34 100644 --- a/src/modm/driver/gpio/gpio_sampler.lb +++ b/src/modm/driver/gpio/gpio_sampler.lb @@ -19,36 +19,22 @@ def prepare(module, options): if options[":target"].identifier["platform"] != "stm32": return False - core = options[":target"].get_driver("core:cortex-m*") + core = options[":target"].driver("core").type # Cortex-M0 doesn't have the DWT->CYCCNT and Cortex-M7 support is broken - if not core or "m0" in core["type"] or "m7" in core["type"]: + if "m0" in core or "m7" in core: return False module.depends( ":platform:gpio", ":platform:core", ":architecture:interrupt") + return True def build(env): - exti_vectors = [v["name"] for v in env[":target"].get_driver("core")["vector"] if "EXTI" in v["name"]] - # These are all exti possible vectors: 0, 0_1, 1, 15_10, 2, 2_3, 2_TSC, 3, 4, 4_15, 9_5 - extimap = { - "0": [0], "1": [1], "2": [2], "3": [3], "4": [4], - "0_1": [0,1], - "2_TSC": [2], - "2_3": [2,3], - "4_15": [4,5,6,7,8,9,10,11,12,13,14,15], - "9_5": [5,6,7,8,9], - "15_10": [10,11,12,13,14,15], - } - extis = OrderedDict() - for v in sorted(exti_vectors): - extis[v] = extimap[v[4:]] - env.substitutions = { - "extis": extis, + "extis": env[":target"].core.shared_irqs("EXTI"), "vectors_location": env.get(":platform:core:vector_table_location", "rom") } env.outbasepath = "modm/src/modm/driver" diff --git a/src/modm/platform/adc/stm32/module.lb b/src/modm/platform/adc/stm32/module.lb index 6600dfeea0..d18ece929a 100644 --- a/src/modm/platform/adc/stm32/module.lb +++ b/src/modm/platform/adc/stm32/module.lb @@ -68,27 +68,6 @@ def prepare(module, options): device = options[":target"] if not device.has_driver("adc:stm32"): return False - global props - props = {} - driver = device.get_driver("adc") - props["target"] = target = device.identifier - props["driver"] = driver - props["instances"] = [] - - if target["family"] in ["f2", "f4", "f7"]: - props["shared_irqs"] = {"ADC": listify(device.get_driver("adc")["instance"])} - props["shared_irq_ids"] = props["shared_irqs"]["ADC"] - else: - shared_irqs = [v["name"] for v in device.get_driver("core")["vector"]] - shared_irqs = [v for v in shared_irqs if v.startswith("ADC") and "_" in v] - props["shared_irqs"] = {} - props["shared_irq_ids"] = [] - for irq in shared_irqs: - parts = irq[3:].split("_") - shared_irqs_ids = (int(parts[0]), int(parts[1]) ) - props["shared_irqs"][irq] = shared_irqs_ids - props["shared_irq_ids"].extend(shared_irqs_ids) - module.depends( ":architecture:adc", @@ -99,21 +78,35 @@ def prepare(module, options): ":math:algorithm", ":utils") - for instance in listify(device.get_driver("adc").get("instance", [])): - module.add_submodule(Instance(int(instance))) + for instance in device.driver("adc").instances(): + module.add_submodule(Instance(instance.number)) return True -def build(env): +def validate(env): device = env[":target"] - driver = device.get_driver("adc") - global props + props = {} + props["target"] = target = device.identifier + props["instances"] = [] + + shared_irqs = device.core.shared_irqs("ADC") + if shared_irqs.values(): + props["shared_irqs"] = shared_irqs + props["shared_irq_ids"] = list(shared_irqs.values())[0] + else: + irq_name = next(device.core.vectors(lambda v: v.startswith("ADC")), "ADC") + instances = [i.number for i in device.driver("adc").instances()] + props["shared_irqs"] = {irq_name: instances} + props["shared_irq_ids"] = instances +def build(env): + device = env[":target"] + global props env.substitutions = props env.outbasepath = "modm/src/modm/platform/adc" - if device.get_driver("adc").get("instance", None) is None: + if not device.driver("adc").instances(): Instance(None).build(env) if any(i in props["shared_irq_ids"] for i in props["instances"]): diff --git a/src/modm/platform/adc/stm32f0/module.lb b/src/modm/platform/adc/stm32f0/module.lb index dc763098df..ef32994b98 100644 --- a/src/modm/platform/adc/stm32f0/module.lb +++ b/src/modm/platform/adc/stm32f0/module.lb @@ -18,8 +18,7 @@ def init(module): def prepare(module, options): device = options[":target"] - if not (device.has_driver("adc:stm32-f0") or - device.has_driver("adc:stm32-g0")): + if not device.has_driver("adc:stm32-[fg]0"): return False module.depends( ":architecture:delay", @@ -33,11 +32,10 @@ def prepare(module, options): def build(env): device = env[":target"] - driver = device.get_driver("adc") properties = {} properties["target"] = target = device.identifier - properties["id"] = driver.get("instance", [""])[0] + properties["id"] = device.driver("adc").instances([""])[0] channels = {i:"In{}".format(i) for i in reversed(range(0,19))} if target.family in ["g0"]: @@ -52,10 +50,7 @@ def build(env): else: channels[18] = "Battery" properties["channels"] = channels - - irq = next(v["name"] for v in device.get_driver("core")["vector"] - if v["name"].startswith("ADC1")) - properties["irq"] = irq + properties["irq"] = next(device.core.vectors(lambda v: v.startswith("ADC1"))) env.substitutions = properties env.outbasepath = "modm/src/modm/platform/adc" diff --git a/src/modm/platform/adc/stm32f3/module.lb b/src/modm/platform/adc/stm32f3/module.lb index 73bd57467b..0c47c3ce06 100644 --- a/src/modm/platform/adc/stm32f3/module.lb +++ b/src/modm/platform/adc/stm32f3/module.lb @@ -145,8 +145,8 @@ def prepare(module, options): ":platform:gpio", ":platform:rcc") - for instance in listify(device.get_driver("adc")["instance"]): - module.add_submodule(Instance(int(instance))) + for instance in device.driver("adc").instances(): + module.add_submodule(Instance(instance.number)) return True diff --git a/src/modm/platform/can/stm32/module.lb b/src/modm/platform/can/stm32/module.lb index 6874166cdb..4f50069f08 100644 --- a/src/modm/platform/can/stm32/module.lb +++ b/src/modm/platform/can/stm32/module.lb @@ -77,9 +77,12 @@ can_map = { } def get_substitutions(env, instance): - target = env["target"].identifier - driver = env["target"].get_driver("can") - instances = map(lambda i: int(i), driver["instance"]) if "instance" in driver else (0,) + device = env[":target"] + target = device.identifier + + driver = device.get_driver("can") + instances = (i.number for i in device.driver("can").instances()) + instances = instances if instances else [0] cm = can_map[target.family] is_single = (cm[instance].type == CanType.Single) or (cm[instance].associated_instance not in instances) @@ -140,12 +143,12 @@ def prepare(module, options): ":platform:rcc", ":utils") - driver = device.get_driver("can") + instances = device.driver("can").instances() # If there is only one instance of the peripheral it is not numbered and # merged into the generic can module. - if "instance" in driver: - for instance in listify(driver["instance"]): - module.add_submodule(Instance(int(instance))) + if instances: + for instance in instances: + module.add_submodule(Instance(instance.number)) else: load_options(module) @@ -158,7 +161,7 @@ def build(env): env.template("can_filter.hpp.in") env.template("can_filter.cpp.in") - if "instance" not in driver: + if not env[":target"].driver("can").instances(): env.substitutions = get_substitutions(env, 0) env.template("can.hpp.in") env.template("can.cpp.in") diff --git a/src/modm/platform/clock/stm32/module.lb b/src/modm/platform/clock/stm32/module.lb index cf0de906f6..25fb892437 100644 --- a/src/modm/platform/clock/stm32/module.lb +++ b/src/modm/platform/clock/stm32/module.lb @@ -21,9 +21,7 @@ def prepare(module, options): if not options[":target"].has_driver("rcc:stm32*"): return False - module.depends(":cmsis:device", ":utils", ":platform:clock") - # FIXME: Move Peripherals enum somewhere better - module.depends(":platform:gpio") + module.depends(":cmsis:device", ":utils", ":platform:clock", ":platform:core") return True def build(env): @@ -67,31 +65,18 @@ def build(env): properties["pllsai_p_usb"] = (target["family"] == "f7") or \ ((target["family"] == "f4") and target["name"] in ["46", "69", "79"]) - flash_latencies = {} - for vcore in device.get_driver("flash")["latency"]: - flash_latencies[int(vcore["vcore-min"])] = sorted([int(f["hclk-max"]) for f in vcore["wait-state"]]) - - properties["table"] = flash_latencies + properties["table"] = device.flash.wait_states env.substitutions = properties env.outbasepath = "modm/src/modm/platform/clock" env.template("rcc.cpp.in") env.template("rcc.hpp.in") - all_peripherals = set() - all_drivers = [d for d in device._properties["driver"] if d["name"] not in ["gpio", "core"]] - translate = lambda s: s.replace("_", "").capitalize() - for d in all_drivers: - dname = translate(d["name"]) - if "instance" in d: - all_peripherals.update(dname + translate(i) for i in d["instance"]) - else: - all_peripherals.add(dname) - all_peripherals = sorted(list(all_peripherals)) - rcc_map = env.query(":cmsis:device:rcc-map") rcc_enable = {} rcc_reset = {} + all_peripherals = uniquify(map(env.filter("modm.fmt.driver"), env[":target"].peripherals)) + all_peripherals_lut = {p.lower():p for p in all_peripherals} for per, mode in rcc_map.items(): nper = per @@ -110,14 +95,14 @@ def build(env): if "Eth" in all_peripherals and per == "ETHMAC": per = "Eth" # Fix USBOTG OTG - if "Usbotgfs" in all_peripherals and per.startswith("OTG"): + if "UsbOtgFs" in all_peripherals and per.startswith("OTG"): if per == "OTGH": per = "OTGHS"; per = "USB"+per # print(per, mode) - if per.capitalize() not in all_peripherals: + if per.lower() not in all_peripherals_lut: continue if "EN" in mode: - rcc_enable[per.capitalize()] = (nper, mode["EN"]) + rcc_enable[all_peripherals_lut[per.lower()]] = (nper, mode["EN"]) if "RST" in mode: rcc_reset[nper] = mode["RST"] diff --git a/src/modm/platform/comp/stm32/base.hpp.in b/src/modm/platform/comp/stm32/base.hpp.in index 46443a8940..383cd99ac8 100644 --- a/src/modm/platform/comp/stm32/base.hpp.in +++ b/src/modm/platform/comp/stm32/base.hpp.in @@ -19,17 +19,17 @@ namespace modm::platform /// @ingroup modm_platform_comp class CompBase { - {% if driver.type not in ["stm32-tsmc90_g4_rockfish_cube"] -%} + {% if type not in ["stm32-tsmc90_g4_rockfish_cube"] -%} public: enum class Mode { - {% if driver.type in ["stm32-v1.3"] -%} + {% if type in ["stm32-v1.3"] -%} UltraLowPower = 0b00 << 2, LowPower = 0b01 << 2, MediumSpeed = 0b10 << 2, HighSpeed = 0b11 << 2, - {% elif driver.type in ["stm32-tsmc90_cube"] -%} + {% elif type in ["stm32-tsmc90_cube"] -%} HighSpeed = 0b00 << 2, MediumSpeed = 0b01 << 2, //MediumSpeed2 = 0b10 << 2, @@ -50,7 +50,7 @@ namespace modm::platform protected: static constexpr uint32_t PolarityMask = 0b1 << 15; - {% if driver.type in ["stm32-v1.3", "stm32-tsmc90_cube"] -%} + {% if type in ["stm32-v1.3", "stm32-tsmc90_cube"] -%} public: enum class Hysteresis @@ -62,7 +62,7 @@ namespace modm::platform }; protected: static constexpr uint32_t HysteresisMask = 0b11 << 16; - {% elif "g4" in driver.type -%} + {% elif "g4" in type -%} public: enum class Hysteresis diff --git a/src/modm/platform/comp/stm32/comp.hpp.in b/src/modm/platform/comp/stm32/comp.hpp.in index 638f838bf1..b1bde6055e 100644 --- a/src/modm/platform/comp/stm32/comp.hpp.in +++ b/src/modm/platform/comp/stm32/comp.hpp.in @@ -234,7 +234,7 @@ namespace modm::platform Output out = Output::NoSelection, {% endif -%} Hysteresis hyst = Hysteresis::NoHysteresis, - {% if driver.type not in ["stm32-tsmc90_g4_rockfish_cube"] -%} + {% if type not in ["stm32-tsmc90_g4_rockfish_cube"] -%} Mode mode = Mode::HighSpeed, {% endif -%} Polarity pol = Polarity::NonInverted, @@ -248,7 +248,7 @@ namespace modm::platform setOutputSelection(out); {% endif -%} setHysteresis(hyst); - {% if driver.type not in ["stm32-tsmc90_g4_rockfish_cube"] -%} + {% if type not in ["stm32-tsmc90_g4_rockfish_cube"] -%} setMode(mode); {% endif -%} setPolarity(pol); @@ -308,7 +308,7 @@ namespace modm::platform } {% endif -%} - {% if driver.type not in ["stm32-tsmc90_g4_rockfish_cube"] -%} + {% if type not in ["stm32-tsmc90_g4_rockfish_cube"] -%} /** * \brief Sets the mode that determins speed/power consumption. * diff --git a/src/modm/platform/comp/stm32/module.lb b/src/modm/platform/comp/stm32/module.lb index e1253a0ace..15d0d587c4 100644 --- a/src/modm/platform/comp/stm32/module.lb +++ b/src/modm/platform/comp/stm32/module.lb @@ -24,13 +24,12 @@ class Instance(Module): def build(self, env): device = env[":target"] - driver = device.get_driver("comp") properties = {} properties["target"] = device.identifier instance_id = int(self.instance) properties["id"] = instance_id - properties["driver"] = driver + properties["type"] = device.driver("comp").type properties["csr"] = "COMP_CSR_" if device.identifier["family"] in ["l4", "g4"] else "COMP_CSR_COMPx" properties["blanking_source"] = dict() if device.identifier["family"] in ["g4"]: @@ -81,7 +80,7 @@ def prepare(module, options): "stm32-v3.4" "stm32-v3.6" """ - if not device.get_driver("comp")["type"] in ["stm32-v1.3", "stm32-tsmc90_cube", "stm32-tsmc90_g4_rockfish_cube"]: + if not device.driver("comp").type in ["stm32-v1.3", "stm32-tsmc90_cube", "stm32-tsmc90_g4_rockfish_cube"]: return False # Only some STM32F3 and STM32L4 @@ -98,18 +97,17 @@ def prepare(module, options): module.depends(":cmsis:device") - for instance in listify(device.get_driver("comp")["instance"]): - module.add_submodule(Instance(int(instance))) + for instance in device.driver("comp").instances(): + module.add_submodule(Instance(instance.number)) return True def build(env): device = env[":target"] - driver = device.get_driver("comp") properties = {} properties["target"] = device.identifier - properties["driver"] = driver + properties["type"] = device.driver("comp").type properties["csr"] = "COMP_CSR_" if device.identifier["family"] in ["l4", "g4"] else "COMP_CSR_COMPx" env.substitutions = properties diff --git a/src/modm/platform/core/cortex/module.lb b/src/modm/platform/core/cortex/module.lb index 8139b55583..c19474814f 100644 --- a/src/modm/platform/core/cortex/module.lb +++ b/src/modm/platform/core/cortex/module.lb @@ -11,6 +11,8 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. # ----------------------------------------------------------------------------- +import copy + def common_vector_table_location(env): return env.get(":platform:cortex-m:vector_table_location", "rom") @@ -72,7 +74,7 @@ def common_memories(env): :returns: dictionary of memory properties """ device = env[":target"] - memories = listify(device.get_driver("core")["memory"]) + memories = copy.deepcopy(listify(device.get_driver("core")["memory"])) # Convert from string to int and add offsets flash_offset = env.get(":platform:cortex-m:linkerscript.flash_offset", 0) diff --git a/src/modm/platform/core/stm32/module.lb b/src/modm/platform/core/stm32/module.lb index 125234452e..679ac609bf 100644 --- a/src/modm/platform/core/stm32/module.lb +++ b/src/modm/platform/core/stm32/module.lb @@ -32,10 +32,14 @@ def build(env): # startup helper code env.template("startup_platform.c.in") + # Generate a list of all on-device peripherals + peripherals = uniquify(map(env.filter("modm.fmt.driver"), env[":target"].peripherals)) + env.substitutions = {"peripherals": peripherals} + env.template("peripherals.hpp.in") + def post_build(env): properties = env.query("::cortex-m:linkerscript") - target = env[":target"].identifier properties["with_crashcatcher"] = env.has_module(":crashcatcher") if "backup" in properties["regions"]: diff --git a/src/modm/platform/gpio/stm32/peripherals.hpp.in b/src/modm/platform/core/stm32/peripherals.hpp.in similarity index 71% rename from src/modm/platform/gpio/stm32/peripherals.hpp.in rename to src/modm/platform/core/stm32/peripherals.hpp.in index df8a0a20f8..54c487ad30 100644 --- a/src/modm/platform/gpio/stm32/peripherals.hpp.in +++ b/src/modm/platform/core/stm32/peripherals.hpp.in @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Niklas Hauser + * Copyright (c) 2019-2020, Niklas Hauser * * This file is part of the modm project. * @@ -9,22 +9,20 @@ */ // ---------------------------------------------------------------------------- -#ifndef MODM_STM32_PERIPHERALS_HPP -#define MODM_STM32_PERIPHERALS_HPP +#pragma once namespace modm::platform { +/// @ingroup modm_platform_core enum class Peripheral { BitBang, -%% for per in all_peripherals +%% for per in peripherals {{ per }}, %% endfor Syscfg = Sys, }; } - -#endif // MODM_STM32_PERIPHERALS_HPP diff --git a/src/modm/platform/gpio/at90_tiny_mega/base.hpp.in b/src/modm/platform/gpio/at90_tiny_mega/base.hpp.in index 48541ade10..9932af2345 100644 --- a/src/modm/platform/gpio/at90_tiny_mega/base.hpp.in +++ b/src/modm/platform/gpio/at90_tiny_mega/base.hpp.in @@ -15,10 +15,7 @@ #include "define.h" #include -namespace modm -{ - -namespace platform +namespace modm::platform { /// @ingroup modm_platform_gpio @@ -95,7 +92,7 @@ protected: template< class Pin > class GpioOpenDrain : public Pin { - static Gpio::InputType inputType; + static inline Gpio::InputType inputType{Gpio::InputType::Floating}; static_assert(Pin::direction == modm::Gpio::Direction::InOut, "Pin must inherit from modm::GpioIO"); public: using Output = GpioOpenDrain; @@ -143,12 +140,6 @@ public: } }; -} // namespace platform - } // namespace modm -template< class Pin > -modm::platform::Gpio::InputType -modm::platform::GpioOpenDrain::inputType(modm::platform::Gpio::InputType::Floating); - #endif // MODM_AVR_GPIO_BASE_HPP diff --git a/src/modm/platform/gpio/at90_tiny_mega/module.lb b/src/modm/platform/gpio/at90_tiny_mega/module.lb index 3eae2a69e9..d8dbba9ca1 100644 --- a/src/modm/platform/gpio/at90_tiny_mega/module.lb +++ b/src/modm/platform/gpio/at90_tiny_mega/module.lb @@ -101,7 +101,7 @@ def validate(env): for d in all_drivers: dname = d["name"].capitalize() if "instance" in d: - all_peripherals.extend([dname + i.capitalize() for i in d["instance"]]) + all_peripherals.extend([dname + i["name"].capitalize() for i in d["instance"]]) else: all_peripherals.append(dname) bprops["all_peripherals"] = sorted(list(set(all_peripherals))) diff --git a/src/modm/platform/gpio/sam/module.lb b/src/modm/platform/gpio/sam/module.lb index 35d5650f0f..089e031773 100644 --- a/src/modm/platform/gpio/sam/module.lb +++ b/src/modm/platform/gpio/sam/module.lb @@ -38,9 +38,10 @@ def build(env): bprops = env.substitutions device = env[":target"] driver = device.get_driver("gpio") + gpios = copy.deepcopy(driver["gpio"]) peripherals = OrderedDict() - for gpio in driver["gpio"]: + for gpio in gpios: signals = [] for signal in gpio["signal"]: signal.update({ @@ -70,14 +71,14 @@ def build(env): gpio["signal"] = signals bprops["peripherals"] = OrderedDict(sorted(peripherals.items())) - bprops["functions"] = sorted(list(set(s["function"] for gpio in driver["gpio"] for s in gpio["signal"]))) + bprops["functions"] = sorted(list(set(s["function"] for gpio in gpios for s in gpio["signal"]))) bprops["target"] = device.identifier env.substitutions = bprops env.outbasepath = "modm/src/modm/platform/gpio" - bprops["gpios"] = driver["gpio"] + bprops["gpios"] = gpios env.template("config.hpp.in") env.copy("connector.hpp") env.copy("pin.hpp") diff --git a/src/modm/platform/gpio/stm32/base.hpp.in b/src/modm/platform/gpio/stm32/base.hpp.in index 86208b73e0..81b26420fd 100644 --- a/src/modm/platform/gpio/stm32/base.hpp.in +++ b/src/modm/platform/gpio/stm32/base.hpp.in @@ -26,7 +26,7 @@ struct Gpio enum class InputType { -%% if target["family"] in ["f1"] +%% if target.family in ["f1"] Floating = 0x4, ///< floating on input PullUp = 0x9, ///< pull-up on input PullDown = 0x8, ///< pull-down on input @@ -41,7 +41,7 @@ struct Gpio OutputType { PushPull = 0x0, ///< push-pull on output -%% if target["family"] in ["f1"] +%% if target.family in ["f1"] OpenDrain = 0x4, ///< open-drain on output %% else OpenDrain = 0x1, ///< open-drain on output @@ -51,14 +51,14 @@ struct Gpio enum class OutputSpeed { -%% if target["family"] in ["f1"] +%% if target.family in ["f1"] Low = 0x2, Medium = 0x1, High = 0x3, MHz2 = Low, MHz10 = Medium, MHz50 = High, -%% elif target["family"] in ["f0", "f3"] +%% elif target.family in ["f0", "f3"] Low = 0, Medium = 0x1, High = 0x3, @@ -99,15 +99,15 @@ struct Gpio Signal { BitBang, -%% for signal in all_signals - {{ signal }}, +%% for signal in signal_names + {{ signal | modm.fmt }}, %% endfor }; /// @endcond protected: /// @cond -%% if target["family"] not in ["f1"] +%% if target.family not in ["f1"] /// I/O Direction Mode values for this specific pin. enum class Mode diff --git a/src/modm/platform/gpio/stm32/connector_specialized.hpp.in b/src/modm/platform/gpio/stm32/connector_specialized.hpp.in index 72f2e9295a..845f5ef907 100644 --- a/src/modm/platform/gpio/stm32/connector_specialized.hpp.in +++ b/src/modm/platform/gpio/stm32/connector_specialized.hpp.in @@ -34,9 +34,9 @@ static constexpr uint8_t lmb(uint32_t value) } // namespace detail // specializations -%% for remap in driver.remap +%% for remap in signal_remap %% set reg = "MAPR" if (remap["position"] | int) < 32 else "MAPR2" - %% set per = remap | formatPeripheral + %% set per = remap | modm.fmt.driver template< template class... Signals > struct GpioConnector { @@ -51,14 +51,14 @@ struct GpioConnector { using namespace detail_gpio_connector; static constexpr uint32_t id = detail::GpioSignalConnect::id; - static_assert((id == uint32_t(-1)) || {% for group in remap.group %}(lmb(id) == {{group.id}}UL){% if not loop.last %} || {% else %},{% endif %}{% endfor %} + static_assert((id == uint32_t(-1)) || {% for group in remap.group %}(lmb(id) == {{group.id}}ul){% if not loop.last %} || {% else %},{% endif %}{% endfor %} "This pin set contains conflicting remap groups!\nAvailable groups for {{per}} are:\n" %% for line in group_map | printSignalMap(per) "{{line}}\n" %% endfor ); if (id != uint32_t(-1)) { - AFIO->{{reg}} = (AFIO->{{reg}} & ~({{ remap["mask"] }}UL << {{ (remap["position"] | int) % 32 }})) | (lmb(id) << {{ (remap["position"] | int) % 32 }}); + AFIO->{{reg}} = (AFIO->{{reg}} & ~({{ remap.mask }}ul << {{ (remap.position | int) % 32 }})) | (lmb(id) << {{ (remap.position | int) % 32 }}); } detail::GpioSignalConnect::connect(); } diff --git a/src/modm/platform/gpio/stm32/module.lb b/src/modm/platform/gpio/stm32/module.lb index 2e4814dcbe..2235c00b5d 100644 --- a/src/modm/platform/gpio/stm32/module.lb +++ b/src/modm/platform/gpio/stm32/module.lb @@ -12,57 +12,102 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. # ----------------------------------------------------------------------------- -import copy -from collections import defaultdict, OrderedDict +def init(module): + module.name = ":platform:gpio" + module.description = "General Purpose I/O (GPIO)" + +def prepare(module, options): + device = options[":target"] + if not device.has_driver("gpio:stm32*"): + return False + + ports = list(map(str.upper, device.gpio.ports)) + module.add_set_option( + EnumerationOption( + name="enable_ports", + description="Enable clock for these GPIO ports during startup", + enumeration=ports), + default=ports) -def port_ranges(gpios): - ports = {p: (32, 0) for p in set(p["port"] for p in gpios)} - for gpio in gpios: - pin = int(gpio["pin"]) - pmin, pmax = ports[gpio["port"]] - ports[gpio["port"]] = (min(pin, pmin), max(pin, pmax)) + module.depends( + ":architecture:gpio", + ":cmsis:device", + ":math:utils", + ":platform:rcc") + return True + +def build(env): + device = env[":target"] + env.substitutions = { + "target": device.identifier, + "signal_remap": device.gpio.signals_remap, + "ranges": device.gpio.ranges, + "ports": list(map(str.upper, device.gpio.ports)), + "signal_names": uniquify(s["name"] for s in device.gpio.signals_all), + "pf": "1" if device.identifier.family in ["l4", "g0", "g4"] else "", + } + env.outbasepath = "modm/src/modm/platform/gpio" + + for (port, pin) in device.gpio.pins: + has_remap = (port+str(pin)) in device.gpio.package_remap + subs = { + "port": port.upper(), "pin": pin, + "exti_irqn": device.core.instance_irq_map("EXTI")[pin][0], + "signals": device.gpio.signals_by_name(port, pin), + "has_remap": has_remap, + } + if has_remap: + reg, mask = get_remap_command(device.identifier.family, port+str(pin)) + subs.update({ + "remap_reg": reg, + "remap_mask": mask, + "remap_value": device.gpio.package_remap[port+str(pin)] + }) + header_name = "gpio_{}{}.hpp".format(port.upper(), pin) + env.template("pin.hpp.in", header_name, substitutions=subs, filters={ + "to_adc_channel": lambda name: "".join(filter(str.isdigit, name))}) - ports = [{"name": k.upper(), "start": v[0], "width": v[1] - v[0] + 1} for k,v in ports.items()] - ports.sort(key=lambda p: p["name"]) - return ports + env.template("port.hpp.in") + env.template("software_port.hpp.in") + env.template("set.hpp.in") + if "f1" in device.gpio.type: + env.template("connector_specialized.hpp.in", + substitutions={"group_map": device.gpio.signals_group}, + filters={"printSignalMap": print_remap_group_table}) + env.template("base.hpp.in") + env.template("unused.hpp.in") + if len(env["enable_ports"]): + env.template("enable.cpp.in") -def translate(s): - return s.replace("_", "").capitalize() + env.copy("../common/inverted.hpp", "inverted.hpp") + env.copy("../common/connector.hpp", "connector.hpp") + env.template("../common/connector_detail.hpp.in", "connector_detail.hpp") -def get_driver(s): - name = "None" - if "driver" in s: name = translate(s["driver"]); - if "instance" in s: name += translate(s["instance"]); - return name -def get_name(s): - return translate(s["name"]) +# ----------------------------------------------------------------------------- +def format_str(s): + return "".join(p.capitalize() for p in str(s).split("_")) -def extract_signals(signals): - afs = {} - for s in signals: - driver = get_driver(s) - name = get_name(s) - key = driver + name - afs[key] = {"driver": driver, "name": name, "af": s["af"]} - return afs +def format_driver(s): + return format_str(s.get("driver", "")) + format_str(s.get("instance", "")) def print_remap_group_table(signal_map, peripheral): + from collections import defaultdict per_signal_map = defaultdict(lambda : defaultdict(list)) afs = [] for key, signals in signal_map.items(): for signal in signals: - if get_driver(signal) == peripheral: - for af in signal["af"]: - per_signal_map[key][af].append(get_name(signal)) - afs.extend(signal["af"]) - afs = sorted(list(set(afs))) + if format_driver(signal) == peripheral: + for af in signal["group"]: + per_signal_map[key][str(af)].append(format_str(signal["name"])) + afs.extend(map(str, signal["group"])) + afs = uniquify(afs) array = [[peripheral] + afs] lengths = [len(s) for s in array[0]] - for gpio in sorted(per_signal_map, key=lambda p: (p[0], int(p[1:]))): - blub = [gpio.upper()] + [[] for _ in afs] - for af, names in per_signal_map[gpio].items(): + for (port, pin) in sorted(per_signal_map): + blub = [port.upper()+str(pin)] + [[] for _ in afs] + for af, names in per_signal_map[(port, pin)].items(): for name in names: blub[array[0].index(af)].append(name) blub = [",".join(b) if isinstance(b, list) else b for b in blub] @@ -80,47 +125,6 @@ def print_remap_group_table(signal_map, peripheral): return lines - -def validate_alternate_functions(driver, env): - """ - For the STM32F1/L1 series - ------------------------- - These chips can only remap functions in groups, some of them with overlapping - pins. A unique map must exist for (Signal.driver + Signal.instance + ordered_set(Pins)) -> Remap - So the combination of Signal driver plus instance and an ordered set of Pins must not map to - different Remap Groups, otherwise our HAL assumptions are broken. - """ - success = True - - if "f1" in driver["type"]: - for remap in driver["remap"]: - af_map = defaultdict(list) - for group in remap["group"]: - for signal in group["signal"]: - af_map[signal["port"] + signal["pin"]].append((group["id"], signal["name"])) - for pin, afs in af_map.items(): - per = remap["driver"] - if "instance" in remap: per += remap["instance"]; - gafs = sorted(list(set([a[0] for a in afs]))) - nafs = sorted(list(set([a[1] for a in afs]))) - if len(afs) > 1: - env.log.debug("P%s: Duplicate groups %s for signal '%s': %s" % (pin.upper(), gafs, per, nafs)) - success = False - else: - for gpio in driver["gpio"]: - if "signal" not in gpio: continue; - af_map = defaultdict(list) - for signal in gpio["signal"]: - if "af" not in signal: continue; - af_map[get_driver(signal)].append((signal["af"], signal["name"])) - for per, afs in af_map.items(): - nafs = sorted(list(set([a[0] for a in afs]))) - if len(nafs) > 1: - env.log.debug("P%s: Duplicate AFs %s for signal '%s': %s" % (gpio["port"].upper() + gpio["pin"], nafs, per, [a[1] for a in afs if a[0] in nafs])) - success = False - if not success: - env.log.debug("Gpio signal validation failed!") - def get_remap_command(family, key): reg = 'SYSCFG->CFGR1' mask = { @@ -136,178 +140,3 @@ def get_remap_command(family, key): if mask is None: raise ValidateException("Unknown Remap for GPIO: 'P{}'".format(key.upper())) return (reg, mask) - -bprops = {} - -# ----------------------------------------------------------------------------- -def init(module): - module.name = ":platform:gpio" - module.description = "General Purpose I/O (GPIO)" - -def prepare(module, options): - device = options[":target"] - if not device.has_driver("gpio:stm32*"): - return False - - bprops["ranges"] = port_ranges(device.get_driver("gpio")["gpio"]) - bprops["ports"] = OrderedDict([(k, i) for i, k in enumerate([p["name"] for p in bprops["ranges"]])]) - - module.add_set_option( - EnumerationOption( - name="enable_ports", - description="Enable clock for these GPIO ports during startup", - enumeration=list(bprops["ports"].keys())), - default=list(bprops["ports"].keys())) - - module.depends( - ":architecture:gpio", - ":cmsis:device", - ":math:utils", - ":platform:rcc") - return True - -def validate(env): - device = env[":target"] - driver = device.get_driver("gpio") - # Not an issue anymore, but kept here for future issues - # validate_alternate_functions(driver, env) - - signal_map = defaultdict(list) - if "f1" in driver["type"]: - # map all remaps onto pins - for remap in driver["remap"]: - # smap = defaultdict(list) - for group in remap["group"]: - for signal in group["signal"]: - key = signal["port"] + signal["pin"] - for sig in signal_map[key]: - if (get_driver(sig) == get_driver(remap) and - get_name(sig) == get_name(signal)): - sig["af"].append(group["id"]) - break - else: - sig = copy.deepcopy(signal) - sig["driver"] = remap["driver"] - sig["af"] = [group["id"]] - if "instance" in remap: - sig["instance"] = remap["instance"] - signal_map[key].append(sig) - bprops["group_map"] = signal_map - - # These are all exti possible vectors: 0, 0_1, 1, 15_10, 2, 2_3, 2_TSC, 3, 4, 4_15, 9_5 - all_exti = { - "0": [0], "1": [1], "2": [2], "3": [3], "4": [4], - "0_1": [0,1], - "2_TSC": [2], - "2_3": [2,3], - "4_15": [4,5,6,7,8,9,10,11,12,13,14,15], - "9_5": [5,6,7,8,9], - "15_10": [10,11,12,13,14,15], - } - extimap = {} - for vec in [v["name"][4:] for v in device.get_driver("core")["vector"] if "EXTI" in v["name"]]: - if vec not in all_exti: - raise ValidateException("Unknown EXTI vector: '{}'".format(vec)) - for num in all_exti[vec]: - if str(num) in extimap: - raise ValidateException("Pin '{}' already in EXTI map!".format(str(num))) - extimap[str(num)] = vec - - # Compute the set of remapped pins - remapped_gpios = {} - for p in driver["package"][0]["pin"]: - variant = p.get("variant", "") - if "remap" in variant: # also matches "remap-default" - name = p["name"][1:4].strip().lower() - if len(name) > 2 and not name[2].isdigit(): - name = name[:2] - remapped_gpios[name] = (variant == "remap") # "remap-default" -> False - - all_signals = {} - for gpio in driver["gpio"]: - key = gpio["port"] + gpio["pin"] - raw_signals = gpio["signal"] if "signal" in gpio else [] - for signal in raw_signals: - if "af" in signal: - signal["af"] = [signal["af"]] - else: - signal["af"] = [] - if key in signal_map: - raw_signals.extend(signal_map[key]) - gpio["signal"] = raw_signals - extracted_signals = extract_signals(raw_signals) - all_signals.update(extracted_signals) - signal_names = sorted(list(set(s["name"] for s in extracted_signals.values()))) - extracted_signals = OrderedDict([(name, sorted([s for s in extracted_signals.values() if s["name"] == name], key=lambda si:si["name"])) for name in signal_names]) - has_remap = key in remapped_gpios - bprops[key] = { - "gpio": gpio, - "exti_irqn": extimap[gpio["pin"]], - "signals": extracted_signals, - "has_remap": has_remap, - } - if has_remap: - reg, mask = get_remap_command(device.identifier.family, key) - bprops[key].update({ - "remap_reg": reg, - "remap_mask": mask, - "remap_value": remapped_gpios[key] - }) - - all_peripherals = [s["driver"] for s in all_signals.values()] - # Signals are not enough, since there are peripherals that don't have signals. - # Example: STM32F401RE < 64pins: SPI4 cannot be connected to any pins. - # FIXME: Allow accessing device file more freely - all_drivers = [d for d in device._properties["driver"] if d["name"] not in ["gpio", "core"]] - for d in all_drivers: - dname = translate(d["name"]) - if "instance" in d: - all_peripherals.extend([dname + translate(i) for i in d["instance"]]) - else: - all_peripherals.append(dname) - if "remap" in driver: - all_peripherals.extend([get_driver(r) for r in driver["remap"]]) - bprops["all_peripherals"] = sorted(list(set(all_peripherals))) - bprops["all_signals"] = sorted(list(set(s["name"] for s in all_signals.values()))) - bprops["pf"] = "1" if device.identifier["family"] in ["l4", "g0", "g4"] else "" - - # Check the max number of ADC instances - max_adc_instance = max(map(int, device.get_driver("adc").get("instance", [1]))) - if (max_adc_instance > (3 if device.identifier["family"] == "f1" else 5 if device.identifier["family"] == "g4" else 4)): - raise ValidateException("Too many ADC instances: '{}'".format(max_adc_instance)) - -def build(env): - device = env[":target"] - driver = device.get_driver("gpio") - properties = device.properties - properties["target"] = device.identifier - properties["driver"] = driver - properties.update(bprops) - - env.substitutions = properties - env.outbasepath = "modm/src/modm/platform/gpio" - gpio_source = "pin_f1.hpp.in" if "f1" in driver["type"] else "pin.hpp.in" - - for gpio in driver["gpio"]: - po, pi = gpio["port"], gpio["pin"] - properties.update(bprops[po + pi]) - header_name = "gpio_{}{}.hpp".format(po.upper(), pi) - env.template(gpio_source, header_name, filters={ "to_adc_channel" : lambda name : "".join(filter(str.isdigit, name)) }) - - env.template("port.hpp.in") - env.template("software_port.hpp.in") - env.template("set.hpp.in") - if "f1" in driver["type"]: - env.template("connector_specialized.hpp.in", filters={"formatPeripheral": get_driver, "printSignalMap": print_remap_group_table}) - env.template("base.hpp.in") - env.template("unused.hpp.in") - if len(env["enable_ports"]): - env.template("enable.cpp.in") - - env.copy("../common/inverted.hpp", "inverted.hpp") - env.copy("../common/connector.hpp", "connector.hpp") - env.template("../common/connector_detail.hpp.in", "connector_detail.hpp") - - # FIXME: Move to modm:platform:core! - env.outbasepath = "modm/src/modm/platform/core" - env.template("peripherals.hpp.in") diff --git a/src/modm/platform/gpio/stm32/pin.hpp.in b/src/modm/platform/gpio/stm32/pin.hpp.in index 68335efc6d..f174d44246 100644 --- a/src/modm/platform/gpio/stm32/pin.hpp.in +++ b/src/modm/platform/gpio/stm32/pin.hpp.in @@ -9,9 +9,8 @@ */ // ---------------------------------------------------------------------------- -%% set port = gpio["port"] | upper %% set reg = "GPIO" ~ port -%% set pin = gpio["pin"] +%% set cr = "CRL" if pin < 8 else "CRH" #ifndef MODM_STM32_GPIO_PIN_{{ port ~ pin }}_HPP #define MODM_STM32_GPIO_PIN_{{ port ~ pin }}_HPP @@ -47,29 +46,36 @@ public: static constexpr bool isInverted = false; static constexpr Port port = Port::{{port}}; ///< Port name static constexpr uint8_t pin = {{pin}}; ///< Pin number - static constexpr IRQn_Type ExternalInterruptIRQ = EXTI{{ exti_irqn }}_IRQn; + static constexpr IRQn_Type ExternalInterruptIRQ = {{ exti_irqn }}_IRQn; protected: + /// Port Number. + static constexpr uint8_t port_nr = uint8_t(port); /// Bitmask for registers that contain a 1bit value for every pin. static constexpr uint16_t mask = 0x1 << pin; +%% if target.family in ["f1"] + static constexpr uint8_t cr_pin = pin % 8; + /// Bitmask for the configuration register with a 4bit mask. + static constexpr uint32_t mask4 = 0xf << (cr_pin * 4); +%% else /// Bitmask for registers that contain a 2bit value for every pin. static constexpr uint32_t mask2 = 0x3 << (pin * 2); - /// Port Number. - static constexpr uint8_t port_nr = uint8_t(port); /// Alternate Function register id. 0 for pin 0-7. 1 for pin 8-15. static constexpr uint8_t af_id = pin / 8; /// Alternate Function offset. static constexpr uint8_t af_offset = (pin * 4) % 32; /// Alternate Function register mask. static constexpr uint32_t af_mask = 0xf << af_offset; +%% endif public: /// @cond +%% if target.family not in ["f1"] inline static void setAlternateFunction(uint8_t af) { {{reg}}->AFR[af_id] = ({{reg}}->AFR[af_id] & ~af_mask) | ((af & 0xf) << af_offset); {{reg}}->MODER = ({{reg}}->MODER & ~mask2) | (i(Mode::AlternateFunction) << (pin * 2)); } - +%% endif /// Enable Analog Mode which is needed to use this pin as an ADC input. inline static void setAnalogInput() { PinSet::setAnalogInput(); } /// @endcond @@ -124,7 +130,9 @@ public: constexpr uint8_t bit_pos = (pin & 0b0011) << 2; constexpr uint16_t syscfg_mask = (0b1111) << bit_pos; constexpr uint16_t syscfg_value = (port_nr & (0b1111)) << bit_pos; -%% if target.family in ["g0"] +%% if target.family in ["f1"] + AFIO->EXTICR[index] = (AFIO->EXTICR[index] & ~syscfg_mask) | syscfg_value; +%% elif target.family in ["g0"] EXTI->EXTICR[index] = (EXTI->EXTICR[index] & ~syscfg_mask) | syscfg_value; %% else SYSCFG->EXTICR[index] = (SYSCFG->EXTICR[index] & ~syscfg_mask) | syscfg_value; @@ -168,6 +176,14 @@ public: // GpioIO // start documentation inherited inline static Direction getDirection() { +%% if target.family in ["f1"] + uint32_t mode = ({{reg}}->{{cr}} & mask4); + if ((mode == 0) or (mode > (uint32_t(0b1001) << (cr_pin * 4)))) + return Direction::Special; + if (mode > 0) + return Direction::Out; + return Direction::In; +%% else uint32_t mode = ({{reg}}->MODER & mask2); if (mode == (i(Mode::Input) << pin * 2)) { return Direction::In; @@ -176,16 +192,18 @@ public: return Direction::Out; } return Direction::Special; +%% endif } // end documentation inherited inline static void lock() { PinSet::lock(); } inline static void disconnect() { setInput(InputType::Floating); +%% if target.family not in ["f1"] {{reg}}->AFR[af_id] &= ~af_mask; - %% if target["family"] in ["l4"] and target["name"] in ["71", "75", "76", "85", "86"] + %% if target.family in ["l4"] and target.name in ["71", "75", "76", "85", "86"] {{reg}}->ASCR &= ~mask; %% endif - +%% endif } public: @@ -193,9 +211,9 @@ public: /// @{ /// Connect to any software peripheral using BitBang = GpioSignal; - %% for name, group in signals.items() - /// Connect to {% for sig in group %}{{ sig.driver }}{{ "" if loop.last else " or "}}{% endfor %} - using {{ name }} = GpioSignal; + %% for sname, sgroup in signals.items() | sort + /// Connect to {% for sig in sgroup %}{{ sig | modm.fmt.driver }}{{ "" if loop.last else " or "}}{% endfor %} + using {{ sname | modm.fmt }} = GpioSignal; %% endfor /// @} #endif @@ -206,14 +224,14 @@ public: (peripheral == Peripheral::BitBang), "Gpio{{ port ~ pin }}::BitBang only connects to software drivers!"); }; - %% for signal_name, signal_group in signals.items() + %% for sname, sgroup in signals.items() | sort template< Peripheral peripheral > - struct {{ signal_name }} { static void connect(); + struct {{ sname | modm.fmt }} { static void connect(); static_assert( - %% for signal in signal_group - (peripheral == Peripheral::{{ signal.driver }}){% if loop.last %},{% else %} ||{% endif %} + %% for signal in sgroup + (peripheral == Peripheral::{{ signal | modm.fmt.driver }}){% if loop.last %},{% else %} or{% endif %} %% endfor - "Gpio{{ port ~ pin }}::{{ signal_name }} only connects to {% for signal in signal_group %}{{signal.driver}}{% if not loop.last %} or {% endif %}{% endfor %}!"); + "Gpio{{ port ~ pin }}::{{ sname | modm.fmt }} only connects to {% for signal in sgroup %}{{signal | modm.fmt.driver}}{% if not loop.last %} or {% endif %}{% endfor %}!"); }; %% endfor /// @endcond @@ -233,30 +251,45 @@ struct Gpio{{ port ~ pin }}::BitBang static constexpr int af = -1; inline static void connect() {} }; -%% for signal_group in signals.values() - %% for signal in signal_group +%% for sname, sgroup in signals.items() | sort + %% for signal in sgroup template<> -struct Gpio{{ port ~ pin }}::{{ signal.name }} +struct Gpio{{ port ~ pin }}::{{ sname | modm.fmt }} { using Gpio = Gpio{{ port ~ pin }}; - static constexpr Gpio::Signal Signal = Gpio::Signal::{{ signal.name }}; - static constexpr int af = {{ signal.af[0] if signal.af | length else -1 }}; + static constexpr Gpio::Signal Signal = Gpio::Signal::{{ sname | modm.fmt }}; + %% if "group" in signal + static constexpr uint32_t Groups = {% for gid in signal.group %}(1ul << {{ gid }}){% if not loop.last %} | {% endif %}{% endfor %}; + %% else + static constexpr uint32_t Groups{-1ul}; + %% endif + static constexpr int af = {{ signal.af if "af" in signal else -1 }}; inline static void connect() { - %% if signal.af | length - setAlternateFunction({{ signal.af[0] }}); - %% elif ( signal.driver.startswith("Adc") or signal.driver.startswith("Dac") - or signal.driver.startswith("Comp") ) + %% if target.family in ["f1"] + %% if signal.is_analog + setAnalogInput(); + %% else + uint32_t cr = {{reg}}->{{cr}}; + if (cr & (0b0011UL << (cr_pin * 4))) { + {{reg}}->{{cr}} = cr | (0b1000UL << (cr_pin * 4)); + } + %% endif + %% else + %% if "af" in signal + setAlternateFunction({{ signal.af }}); + %% elif signal.is_analog disconnect(); setAnalogInput(); + %% endif %% endif } }; - %% if signal.driver.startswith("Adc") and signal.name.startswith("In") + %% if "analog_channel" in signal template<> constexpr int8_t -Gpio{{ port ~ pin }}::AdcChannel = {{ signal.name | to_adc_channel }}; +Gpio{{ port ~ pin }}::AdcChannel = {{ signal.analog_channel }}; %% endif %% if signal.driver.startswith("Dac") and signal.name.startswith("Out") diff --git a/src/modm/platform/gpio/stm32/pin_f1.hpp.in b/src/modm/platform/gpio/stm32/pin_f1.hpp.in deleted file mode 100644 index 469e5d7661..0000000000 --- a/src/modm/platform/gpio/stm32/pin_f1.hpp.in +++ /dev/null @@ -1,235 +0,0 @@ -/* - * Copyright (c) 2017-2018, Niklas Hauser - * - * This file is part of the modm project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ -// ---------------------------------------------------------------------------- - -%% set port = gpio["port"] | upper -%% set reg = "GPIO" ~ port -%% set pin = gpio["pin"] | int -%% set cr = "CRL" if pin < 8 else "CRH" - -#ifndef MODM_STM32_GPIO_PIN_{{ port ~ pin }}_HPP -#define MODM_STM32_GPIO_PIN_{{ port ~ pin }}_HPP - -#include "../device.hpp" -#include "base.hpp" -#include "set.hpp" - - -namespace modm -{ - -namespace platform -{ - -/// @cond -class Gpio{{ port ~ pin }}; -using GpioOutput{{ port ~ pin }} = Gpio{{ port ~ pin }}; -using GpioInput{{ port ~ pin }} = Gpio{{ port ~ pin }}; -/// @endcond - -/// IO class for Pin {{port ~ pin}} -/// @ingroup modm_platform_gpio -struct Gpio{{ port ~ pin }} : public Gpio, ::modm::GpioIO -{ - template - friend class GpioSet; - using PinSet = GpioSet; - friend class Adc1; friend class Adc2; friend class Adc3; -public: - using Output = Gpio{{ port ~ pin }}; - using Input = Gpio{{ port ~ pin }}; - using IO = Gpio{{ port ~ pin }}; - using Type = Gpio{{ port ~ pin }}; - static constexpr bool isInverted = false; - static constexpr Port port = Port::{{port}}; ///< Port name - static constexpr uint8_t pin = {{pin}}; ///< Pin Number - static constexpr IRQn_Type ExternalInterruptIRQ = EXTI{{ exti_irqn }}_IRQn; - -protected: - /// Bitmask for registers that contain a 1bit value for every pin. - static constexpr uint16_t mask = 0x1 << pin; - static constexpr uint8_t cr_pin = {{ pin }} % 8; - /// Bitmask for the configuration register with a 4bit mask. - static constexpr uint32_t mask4 = 0xf << (cr_pin * 4); - /// Port Number. - static constexpr uint8_t port_nr = static_cast(port); - -public: - /// @cond - /// Enable Analog Mode which is needed to use this pin as an ADC input. - inline static void setAnalogInput() { PinSet::setAnalogInput(); } - /// @endcond - -public: - // GpioOutput - // start documentation inherited - inline static void setOutput() { PinSet::setOutput(); } - inline static void setOutput(bool status) { PinSet::setOutput(status); } - inline static void set() { PinSet::set(); } - inline static void set(bool status) { PinSet::set(status); } - inline static void reset() { PinSet::reset(); } - inline static void toggle() { - if (isSet()) reset(); - else set(); - } - inline static bool isSet() { return ({{reg}}->ODR & mask); } - // stop documentation inherited - inline static void configure(OutputType type, OutputSpeed speed = OutputSpeed::MHz50) { PinSet::configure(type, speed); } - inline static void setOutput(OutputType type, OutputSpeed speed = OutputSpeed::MHz50) { PinSet::setOutput(type, speed); } - // GpioInput - // start documentation inherited - inline static void setInput() { PinSet::setInput(); } - inline static bool read() { return ({{reg}}->IDR & mask); } - // end documentation inherited - inline static void configure(InputType type) { PinSet::configure(type); } - inline static void setInput(InputType type) { PinSet::setInput(type); } - // External Interrupts - // Warning: This will disable any previously enabled interrupt which is - // routed to the same interupt line, e.g. PA3 will disable PB3. - // This is a hardware limitation by the STM32 EXTI. - inline static void enableExternalInterrupt() - { - // PA[x], x = 0 .. 3 maps to EXTICR[0] - // PA[x], x = 4 .. 7 maps to EXTICR[1] - // PA[x], x = 8 .. 11 maps to EXTICR[2] - // PA[x], x = 12 .. 15 maps to EXTICR[3] - // => bit3 and bit2 (mask 0b1100) specify the register - // => bit1 and bit0 (mask 0b0011) specify the bit position - constexpr uint8_t index = (pin & 0b1100) >> 2; - constexpr uint8_t bit_pos = (pin & 0b0011) << 2; - constexpr uint16_t syscfg_mask = (0b1111) << bit_pos; - constexpr uint16_t syscfg_value = (port_nr & (0b1111)) << bit_pos; - AFIO->EXTICR[index] = (AFIO->EXTICR[index] & ~syscfg_mask) | syscfg_value; - EXTI->IMR |= mask; - } - inline static void disableExternalInterrupt() { EXTI->IMR &= ~mask; } - inline static void enableExternalInterruptVector(const uint32_t priority) - { - NVIC_SetPriority(ExternalInterruptIRQ, priority); - NVIC_EnableIRQ(ExternalInterruptIRQ); - } - inline static void disableExternalInterruptVector() { NVIC_DisableIRQ(ExternalInterruptIRQ); } - inline static void - setInputTrigger(const InputTrigger trigger) - { - switch (trigger) - { - case InputTrigger::RisingEdge: - EXTI->RTSR |= mask; - EXTI->FTSR &= ~mask; - break; - case InputTrigger::FallingEdge: - EXTI->RTSR &= ~mask; - EXTI->FTSR |= mask; - break; - case InputTrigger::BothEdges: - EXTI->RTSR |= mask; - EXTI->FTSR |= mask; - break; - } - } - inline static bool getExternalInterruptFlag() { return (EXTI->PR & mask); } - inline static void acknowledgeExternalInterruptFlag() { EXTI->PR = mask; } - // GpioIO - // start documentation inherited - inline static Direction getDirection() { - uint32_t mode = ({{reg}}->{{cr}} & mask4); - if ((mode == 0) or (mode > (uint32_t(0b1001) << (cr_pin * 4)))) - return Direction::Special; - if (mode > 0) - return Direction::Out; - return Direction::In; - } - // end documentation inherited - inline static void lock() { PinSet::lock(); } - inline static void disconnect() { setInput(); }; - -public: -#ifdef __DOXYGEN__ - /// @{ - /// Connect to any software peripheral - using BitBang = GpioSignal; - %% for name, group in signals.items() - /// Connect to {% for sig in group %}{{ sig.driver }}{{ "" if loop.last else " or "}}{% endfor %} - using {{ name }} = GpioSignal; - %% endfor - /// @} -#endif - /// @cond - template< Peripheral peripheral > - struct BitBang { static void connect(); - static_assert( - (peripheral == Peripheral::BitBang), - "Gpio{{ port ~ pin }}::BitBang only connects to software drivers!"); - }; - %% for signal_name, signal_group in signals.items() - template< Peripheral peripheral > - struct {{ signal_name }} { static void connect(); - static_assert( - %% for signal in signal_group - (peripheral == Peripheral::{{ signal.driver }}){% if loop.last %},{% else %} ||{% endif %} - %% endfor - "Gpio{{ port ~ pin }}::{{ signal_name }} only connects to {% for signal in signal_group %}{{signal.driver}}{% if not loop.last %} or {% endif %}{% endfor %}!"); - }; - %% endfor - /// @endcond -private: - template< Peripheral peripheral > - static constexpr int8_t AdcChannel = -1; -}; - -/// @cond -template<> -struct Gpio{{ port ~ pin }}::BitBang -{ - using Gpio = Gpio{{ port ~ pin }}; - static constexpr Gpio::Signal Signal = Gpio::Signal::BitBang; - inline static void connect() {} -}; -%% for _, signal_group in signals.items() - %% for signal in signal_group -template<> -struct Gpio{{ port ~ pin }}::{{ signal.name }} -{ - %% if signal.af | length - static constexpr uint32_t Groups = {% for af in signal.af %}(1UL << {{ af }}){% if not loop.last %} | {% endif %}{% endfor %}; - %% else - static constexpr uint32_t Groups = uint32_t(-1); - %% endif - using Gpio = Gpio{{ port ~ pin }}; - static constexpr Gpio::Signal Signal = Gpio::Signal::{{ signal.name }}; - inline static void - connect() - { - %% if signal.driver.startswith("Adc") - setAnalogInput(); - %% else - uint32_t cr = {{reg}}->{{cr}}; - if (cr & (0b0011UL << (cr_pin * 4))) { - {{reg}}->{{cr}} = cr | (0b1000UL << (cr_pin * 4)); - } - %% endif - } -}; - %% if signal.driver.startswith("Adc") and signal.name.startswith("In") -template<> -constexpr int8_t -Gpio{{ port ~ pin }}::AdcChannel = {{ signal.name | to_adc_channel }}; - %% endif - %% endfor - -%% endfor -/// @endcond - -} // namespace platform - -} // namespace modm - -#endif // MODM_STM32_GPIO_{{ port ~ pin }}_HPP diff --git a/src/modm/platform/gpio/stm32/port.hpp.in b/src/modm/platform/gpio/stm32/port.hpp.in index 5254494334..848db241b8 100644 --- a/src/modm/platform/gpio/stm32/port.hpp.in +++ b/src/modm/platform/gpio/stm32/port.hpp.in @@ -17,10 +17,7 @@ #include #include -namespace modm -{ - -namespace platform +namespace modm::platform { /// @cond @@ -57,8 +54,8 @@ public: static PortType isSet() { uint16_t r{0}; -%% for port, id in ports.items() - if constexpr (mask({{id}})) r = (GPIO{{port}}->ODR & mask({{id}})) ^ inverted({{id}}); +%% for port in ports + if constexpr (mask({{loop.index0}})) r = (GPIO{{port}}->ODR & mask({{loop.index0}})) ^ inverted({{loop.index0}}); %% endfor if constexpr (getDataOrder() == modm::GpioPort::DataOrder::Reversed) return bitReverse(r) >> StartPinReversed; @@ -68,8 +65,8 @@ public: static PortType read() { uint16_t r{0}; -%% for port, id in ports.items() - if constexpr (mask({{id}})) r = (GPIO{{port}}->IDR & mask({{id}})) ^ inverted({{id}}); +%% for port in ports + if constexpr (mask({{loop.index0}})) r = (GPIO{{port}}->IDR & mask({{loop.index0}})) ^ inverted({{loop.index0}}); %% endfor if constexpr (getDataOrder() == modm::GpioPort::DataOrder::Reversed) return bitReverse(r) >> StartPinReversed; @@ -82,9 +79,9 @@ public: if constexpr (getDataOrder() == modm::GpioPort::DataOrder::Reversed) p = bitReverse(uint16_t(uint16_t(data) << StartPinReversed)); else p = uint16_t(data) << StartPin; -%% for port, id in ports.items() - if constexpr (mask({{id}})) { p ^= inverted({{id}}); - GPIO{{port}}->BSRR = ((~p & mask({{id}})) << 16) | (p & mask({{id}})); +%% for port in ports + if constexpr (mask({{loop.index0}})) { p ^= inverted({{loop.index0}}); + GPIO{{port}}->BSRR = ((~p & mask({{loop.index0}})) << 16) | (p & mask({{loop.index0}})); } %% endfor } @@ -94,10 +91,10 @@ public: // ------ Port Width Information ------ %% for port in ranges template<> -struct GpioPortInfo +struct GpioPortInfo { - static constexpr int8_t Width = {{port["width"]}}; - static constexpr int8_t StartPin = {{port["start"]}}; + static constexpr int8_t Width = {{port.width}}; + static constexpr int8_t StartPin = {{port.start}}; static constexpr int8_t EndPin = StartPin + Width; template< uint8_t QueryStartPin, int8_t QueryWidth > @@ -107,12 +104,12 @@ struct GpioPortInfo static constexpr bool isReversed = QueryWidth < 0; static constexpr int8_t width = isNormal ? QueryWidth : -QueryWidth; static_assert(isReversed or width <= Width, - "GpioPort Width out of bounds! Maximum is {{port["width"]}}."); + "GpioPort Width out of bounds! Maximum is {{port.width}}."); static_assert(isReversed or (QueryStartPin + QueryWidth <= EndPin), - "GpioPort StartPin + Width out of bounds! Maximum is {{port["start"] + port["width"] - 1}}."); + "GpioPort StartPin + Width out of bounds! Maximum is {{port.start + port.width - 1}}."); static_assert(isNormal or (StartPin <= QueryStartPin + QueryWidth + 1), - "GpioPort StartPin - Width out of bounds! Minimum is {{port["start"]}}."); + "GpioPort StartPin - Width out of bounds! Minimum is {{port.start}}."); }; }; %% endfor @@ -143,8 +140,6 @@ struct GpioSetShim : public GpioSet< %% endfor /// @endcond -} // namespace platform - -} // namespace modm +} // namespace modm::platform #endif // MODM_STM32_GPIO_PORT_HPP diff --git a/src/modm/platform/gpio/stm32/set.hpp.in b/src/modm/platform/gpio/stm32/set.hpp.in index 9b643af7ee..21d81d535e 100644 --- a/src/modm/platform/gpio/stm32/set.hpp.in +++ b/src/modm/platform/gpio/stm32/set.hpp.in @@ -45,7 +45,7 @@ protected: if (masks[id] & (1 << ii)) r |= (uint32_t(value) << (ii * 2)); return r; } -%% if target["family"] in ["f1"] +%% if target.family in ["f1"] static constexpr uint64_t mask4(uint8_t id, uint8_t value = 0b1111) { uint64_t r{0}; for (int ii=0; ii<16; ii++) @@ -70,11 +70,11 @@ public: public: static void setOutput() { -%% if target["family"] in ["f1"] +%% if target.family in ["f1"] configure(OutputType::PushPull); %% else - %% for port, id in ports.items() - if constexpr (mask({{id}})) GPIO{{port}}->MODER = (GPIO{{port}}->MODER & ~mask2({{id}})) | mask2({{id}}, i(Mode::Output)); + %% for port in ports + if constexpr (mask({{loop.index0}})) GPIO{{port}}->MODER = (GPIO{{port}}->MODER & ~mask2({{loop.index0}})) | mask2({{loop.index0}}, i(Mode::Output)); %% endfor %% endif } @@ -88,23 +88,23 @@ public: static void setOutput(OutputType type, OutputSpeed speed = OutputSpeed::MHz50) { configure(type, speed); -%% if target["family"] not in ["f1"] +%% if target.family not in ["f1"] setOutput(); %% endif } static void configure(OutputType type, OutputSpeed speed = OutputSpeed::MHz50) { -%% if target["family"] in ["f1"] - %% for port, id in ports.items() - if constexpr (crl({{id}})) GPIO{{port}}->CRL = (GPIO{{port}}->CRL & ~crl({{id}})) | ((i(type) | i(speed)) * crl({{id}}, 0b0001)); - if constexpr (crh({{id}})) GPIO{{port}}->CRH = (GPIO{{port}}->CRH & ~crh({{id}})) | ((i(type) | i(speed)) * crh({{id}}, 0b0001)); +%% if target.family in ["f1"] + %% for port in ports + if constexpr (crl({{loop.index0}})) GPIO{{port}}->CRL = (GPIO{{port}}->CRL & ~crl({{loop.index0}})) | ((i(type) | i(speed)) * crl({{loop.index0}}, 0b0001)); + if constexpr (crh({{loop.index0}})) GPIO{{port}}->CRH = (GPIO{{port}}->CRH & ~crh({{loop.index0}})) | ((i(type) | i(speed)) * crh({{loop.index0}}, 0b0001)); %% endfor %% else - %% for port, id in ports.items() - if constexpr (mask({{id}})) { - GPIO{{port}}->OSPEEDR = (GPIO{{port}}->OSPEEDR & ~mask2({{id}})) | (i(speed) * mask2({{id}}, 0b01)); - GPIO{{port}}->OTYPER = (GPIO{{port}}->OTYPER & ~mask({{id}})) | (i(type) ? mask({{id}}) : 0); + %% for port in ports + if constexpr (mask({{loop.index0}})) { + GPIO{{port}}->OSPEEDR = (GPIO{{port}}->OSPEEDR & ~mask2({{loop.index0}})) | (i(speed) * mask2({{loop.index0}}, 0b01)); + GPIO{{port}}->OTYPER = (GPIO{{port}}->OTYPER & ~mask({{loop.index0}})) | (i(type) ? mask({{loop.index0}}) : 0); } %% endfor %% endif @@ -112,14 +112,14 @@ public: static void setInput() { -%% if target["family"] in ["f1"] +%% if target.family in ["f1"] configure(InputType::Floating); %% else - %% for port, id in ports.items() - if constexpr (mask({{id}})) { - GPIO{{port}}->MODER &= ~mask2({{id}}); - GPIO{{port}}->OTYPER &= ~mask({{id}}); - GPIO{{port}}->OSPEEDR &= ~mask2({{id}}); + %% for port in ports + if constexpr (mask({{loop.index0}})) { + GPIO{{port}}->MODER &= ~mask2({{loop.index0}}); + GPIO{{port}}->OTYPER &= ~mask({{loop.index0}}); + GPIO{{port}}->OSPEEDR &= ~mask2({{loop.index0}}); } %% endfor %% endif @@ -128,23 +128,23 @@ public: static void setInput(InputType type) { configure(type); -%% if target["family"] not in ["f1"] +%% if target.family not in ["f1"] setInput(); %% endif } static void setAnalogInput() { -%% if target["family"] in ["f1"] - %% for port, id in ports.items() - if constexpr (crl({{id}})) GPIO{{port}}->CRL &= ~crl({{id}}); - if constexpr (crh({{id}})) GPIO{{port}}->CRH &= ~crh({{id}}); +%% if target.family in ["f1"] + %% for port in ports + if constexpr (crl({{loop.index0}})) GPIO{{port}}->CRL &= ~crl({{loop.index0}}); + if constexpr (crh({{loop.index0}})) GPIO{{port}}->CRH &= ~crh({{loop.index0}}); %% endfor %% else - %% for port, id in ports.items() - if constexpr (mask({{id}})) GPIO{{port}}->MODER |= mask2({{id}}, i(Mode::Analog)); - %% if target["family"] in ["l4"] and target["name"] in ["71", "75", "76", "85", "86"] - if constexpr (mask({{id}})) GPIO{{port}}->ASCR |= mask({{id}}); + %% for port in ports + if constexpr (mask({{loop.index0}})) GPIO{{port}}->MODER |= mask2({{loop.index0}}, i(Mode::Analog)); + %% if target.family in ["l4"] and target["name"] in ["71", "75", "76", "85", "86"] + if constexpr (mask({{loop.index0}})) GPIO{{port}}->ASCR |= mask({{loop.index0}}); %% endif %% endfor %% endif @@ -152,16 +152,16 @@ public: static void configure(InputType type) { -%% if target["family"] in ["f1"] - %% for port, id in ports.items() - if constexpr (crl({{id}})) GPIO{{port}}->CRL = (GPIO{{port}}->CRL & ~crl({{id}})) | ((i(type) & 0xc) * crl({{id}}, 0b0001)); - if constexpr (crh({{id}})) GPIO{{port}}->CRH = (GPIO{{port}}->CRH & ~crh({{id}})) | ((i(type) & 0xc) * crh({{id}}, 0b0001)); - if constexpr (mask({{id}})) GPIO{{port}}->BSRR = mask({{id}}) << ((type == InputType::PullUp) ? 0 : 16); +%% if target.family in ["f1"] + %% for port in ports + if constexpr (crl({{loop.index0}})) GPIO{{port}}->CRL = (GPIO{{port}}->CRL & ~crl({{loop.index0}})) | ((i(type) & 0xc) * crl({{loop.index0}}, 0b0001)); + if constexpr (crh({{loop.index0}})) GPIO{{port}}->CRH = (GPIO{{port}}->CRH & ~crh({{loop.index0}})) | ((i(type) & 0xc) * crh({{loop.index0}}, 0b0001)); + if constexpr (mask({{loop.index0}})) GPIO{{port}}->BSRR = mask({{loop.index0}}) << ((type == InputType::PullUp) ? 0 : 16); %% endfor %% else - %% for port, id in ports.items() - if constexpr (mask({{id}})) { - GPIO{{port}}->PUPDR = (GPIO{{port}}->PUPDR & ~mask2({{id}})) | (i(type) * mask2({{id}}, 0b01)); + %% for port in ports + if constexpr (mask({{loop.index0}})) { + GPIO{{port}}->PUPDR = (GPIO{{port}}->PUPDR & ~mask2({{loop.index0}})) | (i(type) * mask2({{loop.index0}}, 0b01)); } %% endfor %% endif @@ -169,8 +169,8 @@ public: static void set() { -%% for port, id in ports.items() - if constexpr (mask({{id}})) GPIO{{port}}->BSRR = (inverted({{id}}) << 16) | (mask({{id}}) & ~inverted({{id}})); +%% for port in ports + if constexpr (mask({{loop.index0}})) GPIO{{port}}->BSRR = (inverted({{loop.index0}}) << 16) | (mask({{loop.index0}}) & ~inverted({{loop.index0}})); %% endfor } @@ -182,17 +182,17 @@ public: static void reset() { -%% for port, id in ports.items() - if constexpr (mask({{id}})) GPIO{{port}}->BSRR = ((uint32_t(mask({{id}})) & ~inverted({{id}})) << 16) | inverted({{id}}); +%% for port in ports + if constexpr (mask({{loop.index0}})) GPIO{{port}}->BSRR = ((uint32_t(mask({{loop.index0}})) & ~inverted({{loop.index0}})) << 16) | inverted({{loop.index0}}); %% endfor } static void toggle() { -%% for port, id in ports.items() - if constexpr (mask({{id}})) { - uint32_t are_set = (GPIO{{port}}->ODR & mask({{id}})); - uint32_t are_reset = mask({{id}}) ^ are_set; +%% for port in ports + if constexpr (mask({{loop.index0}})) { + uint32_t are_set = (GPIO{{port}}->ODR & mask({{loop.index0}})); + uint32_t are_reset = mask({{loop.index0}}) ^ are_set; GPIO{{port}}->BSRR = (are_set << 16) | are_reset; } %% endfor @@ -200,11 +200,11 @@ public: static void lock() { -%% for port, id in ports.items() - if constexpr (mask({{id}})) { - GPIO{{port}}->LCKR = 0x10000 | mask({{id}}); - GPIO{{port}}->LCKR = 0x00000 | mask({{id}}); - GPIO{{port}}->LCKR = 0x10000 | mask({{id}}); +%% for port in ports + if constexpr (mask({{loop.index0}})) { + GPIO{{port}}->LCKR = 0x10000 | mask({{loop.index0}}); + GPIO{{port}}->LCKR = 0x00000 | mask({{loop.index0}}); + GPIO{{port}}->LCKR = 0x10000 | mask({{loop.index0}}); (void) GPIO{{port}}->LCKR; } %% endfor diff --git a/src/modm/platform/gpio/stm32/software_port.hpp.in b/src/modm/platform/gpio/stm32/software_port.hpp.in index 093e774063..4e3e8832ec 100644 --- a/src/modm/platform/gpio/stm32/software_port.hpp.in +++ b/src/modm/platform/gpio/stm32/software_port.hpp.in @@ -66,7 +66,8 @@ public: static PortType isSet() { PortType r{0}; -%% for port, id in ports.items() +%% for port in ports + %% set id = loop.index0 if constexpr (mask({{id}})) { const uint16_t p = (GPIO{{port}}->ODR & mask({{id}})) ^ inverted({{id}}); %% for pos in range(32) @@ -79,7 +80,8 @@ public: static void write(PortType data) { -%% for port, id in ports.items() +%% for port in ports + %% set id = loop.index0 if constexpr (mask({{id}})) { uint32_t p{0}; %% for pos in range(32) if constexpr ({{pos}} < width) if constexpr (constexpr auto pos = shift_mask({{id}}, {{pos}}); pos >= 0) p |= (data & (1ul << {{pos}})) ? (1ul << pos) : (1ul << (pos + 16)); @@ -93,7 +95,8 @@ public: static PortType read() { PortType r{0}; -%% for port, id in ports.items() +%% for port in ports + %% set id = loop.index0 if constexpr (mask({{id}})) { const uint16_t p = (GPIO{{port}}->IDR & mask({{id}})) ^ inverted({{id}}); %% for pos in range(32) diff --git a/src/modm/platform/gpio/stm32/unused.hpp.in b/src/modm/platform/gpio/stm32/unused.hpp.in index c37b665c16..eea23970ca 100644 --- a/src/modm/platform/gpio/stm32/unused.hpp.in +++ b/src/modm/platform/gpio/stm32/unused.hpp.in @@ -111,12 +111,12 @@ public: public: /// @cond -%% for name in all_signals +%% for name in signal_names template< Peripheral _ > - struct {{ name }} + struct {{ name | modm.fmt }} { using Gpio = GpioUnused; - static constexpr Gpio::Signal Signal = Gpio::Signal::{{ name }}; + static constexpr Gpio::Signal Signal = Gpio::Signal::{{ name | modm.fmt }}; static void connect() {} }; %% endfor diff --git a/src/modm/platform/i2c/stm32-extended/module.lb b/src/modm/platform/i2c/stm32-extended/module.lb index a361b5325c..3de8ae191f 100644 --- a/src/modm/platform/i2c/stm32-extended/module.lb +++ b/src/modm/platform/i2c/stm32-extended/module.lb @@ -59,8 +59,8 @@ def prepare(module, options): ":container", ":platform:gpio") - for instance in listify(device.get_driver("i2c")["instance"]): - module.add_submodule(Instance(int(instance))) + for instance in device.driver("i2c").instances(): + module.add_submodule(Instance(instance.number)) return True diff --git a/src/modm/platform/i2c/stm32/module.lb b/src/modm/platform/i2c/stm32/module.lb index c72c032dfc..67441b0fc4 100644 --- a/src/modm/platform/i2c/stm32/module.lb +++ b/src/modm/platform/i2c/stm32/module.lb @@ -61,8 +61,8 @@ def prepare(module, options): ":container", ":platform:gpio") - for instance in listify(device.get_driver("i2c")["instance"]): - module.add_submodule(Instance(int(instance))) + for instance in device.driver("i2c").instances(): + module.add_submodule(Instance(instance.number)) return True diff --git a/src/modm/platform/spi/at90_tiny_mega/module.lb b/src/modm/platform/spi/at90_tiny_mega/module.lb index d54602bbe6..8a9667c1b3 100644 --- a/src/modm/platform/spi/at90_tiny_mega/module.lb +++ b/src/modm/platform/spi/at90_tiny_mega/module.lb @@ -53,10 +53,10 @@ def prepare(module, options): if not device.has_driver("spi:avr"): return False - driver = device.get_driver("spi:avr") - if "instance" in driver: - for instance in listify(driver["instance"]): - module.add_submodule(Instance(int(instance))) + instances = device.driver("spi").instances() + if instances: + for instance in instances: + module.add_submodule(Instance(instance.number)) else: load_options(module) @@ -69,11 +69,11 @@ def prepare(module, options): return True def build(env): - driver = env[":target"].get_driver("spi") - if "instance" not in driver: + device = env[":target"] + if not device.driver("spi").instances(): env.substitutions = { - "target": env[":target"].identifier, - "partname": env[":target"].partname, + "target": device.identifier, + "partname": device.partname, "id": "", } env.outbasepath = "modm/src/modm/platform/spi" diff --git a/src/modm/platform/spi/at90_tiny_mega_uart/module.lb b/src/modm/platform/spi/at90_tiny_mega_uart/module.lb index c575856547..e73ed59a16 100644 --- a/src/modm/platform/spi/at90_tiny_mega_uart/module.lb +++ b/src/modm/platform/spi/at90_tiny_mega_uart/module.lb @@ -90,8 +90,8 @@ def prepare(module, options): ":platform:gpio", ":platform:uart") - for instance in listify(device.get_driver("spi:avr_uart")["instance"]): - module.add_submodule(Instance(int(instance))) + for instance in device.driver("spi").instances(): + module.add_submodule(Instance(instance.number)) return True diff --git a/src/modm/platform/spi/stm32/module.lb b/src/modm/platform/spi/stm32/module.lb index 783b3eb8a3..321d652202 100644 --- a/src/modm/platform/spi/stm32/module.lb +++ b/src/modm/platform/spi/stm32/module.lb @@ -21,7 +21,7 @@ def get_properties(env): class Instance(Module): def __init__(self, driver, instance): - self.instance = int(instance) + self.instance = instance self.driver = driver def init(self, module): @@ -65,9 +65,9 @@ def prepare(module, options): ":platform:gpio", ":platform:rcc") - for driver in device.get_all_drivers("spi:stm32"): - for instance in driver["instance"]: - module.add_submodule(Instance(driver, instance)) + for driver in device.drivers("spi:stm32"): + for instance in driver.instances(): + module.add_submodule(Instance(driver, instance.number)) return True diff --git a/src/modm/platform/spi/stm32_uart/module.lb b/src/modm/platform/spi/stm32_uart/module.lb index dc4bd18361..5b0edbe235 100644 --- a/src/modm/platform/spi/stm32_uart/module.lb +++ b/src/modm/platform/spi/stm32_uart/module.lb @@ -50,9 +50,9 @@ def prepare(module, options): ":platform:gpio", ":platform:uart") - for driver in device.get_all_drivers("usart"): - for instance in listify(driver["instance"]): - module.add_submodule(Instance(int(instance), "extended" in driver["type"])) + for driver in device.drivers("usart"): + for instance in driver.instances(): + module.add_submodule(Instance(instance.number, "extended" in driver.type)) return True diff --git a/src/modm/platform/timer/stm32/module.lb b/src/modm/platform/timer/stm32/module.lb index 5488d51495..ac5085b125 100644 --- a/src/modm/platform/timer/stm32/module.lb +++ b/src/modm/platform/timer/stm32/module.lb @@ -29,18 +29,18 @@ def get_connectors(instance): return [] class Instance(Module): - def __init__(self, driver, instance): - self.driver = driver - self.instance = int(instance) + def __init__(self, device, instance): + self.device = device + self.instance = instance self.vectors = None self.type = "general_purpose" - if self.instance in [1, 8, 20]: + if self.instance.number in [1, 8, 20]: self.type = "advanced" - elif self.instance in [6, 7, 18]: + elif self.instance.number in [6, 7, 18]: self.type = "basic" def init(self, module): - module.name = str(self.instance) + module.name = self.instance.name module.description = "Instance {}".format(self.instance) def prepare(self, module, options): @@ -55,7 +55,8 @@ class Instance(Module): "_CC": ["CaptureCompare1", "CaptureCompare2", "CaptureCompare3", "CaptureCompare4"], } - self.vectors = {irq:[] for irq in props["timer_vectors"][self.instance]} + vectors = list(self.device.core.vectors(lambda v: "TIM"+self.instance.name in v.split("_"))) + self.vectors = {irq:[] for irq in vectors} for irq in self.vectors.keys(): for part, flags in vecmap.items(): if part in irq: @@ -63,7 +64,7 @@ class Instance(Module): if len(self.vectors) == 0: raise ValidateException("No interrupts found for Timer{}! Possible IRQs are {}" - .format(self.instance, props["timer_vectors"])) + .format(self.instance, list(self.device.core.vectors(lambda v: "TIM" in v)))) if self.type != "advanced": if len(self.vectors) != 1: raise ValidateException("Timer{} is only allowed to have one IRQ! Found {}" @@ -72,15 +73,15 @@ class Instance(Module): def build(self, env): global props - props["id"] = self.instance - props["connectors"] = get_connectors(self.instance) + props["id"] = self.instance.number + props["connectors"] = get_connectors(self.instance.number) props["vectors"] = self.vectors props["types"].add(self.type) env.substitutions = props env.outbasepath = "modm/src/modm/platform/timer" - env.template("{}.hpp.in".format(self.type), "timer_{}.hpp".format(self.instance)) - env.template("{}.cpp.in".format(self.type), "timer_{}.cpp".format(self.instance)) + env.template("{}.hpp.in".format(self.type), "timer_{}.hpp".format(self.instance.name)) + env.template("{}.cpp.in".format(self.type), "timer_{}.cpp".format(self.instance.name)) def init(module): @@ -98,27 +99,18 @@ def prepare(module, options): ":platform:gpio", ":platform:rcc") - timers = device.get_all_drivers("tim") + timers = device.drivers("tim") instances = [] for driver in timers: - for instance in driver["instance"]: - module.add_submodule(Instance(driver, instance)) - instances.append(int(instance)) + for instance in driver.instances(): + module.add_submodule(Instance(device, instance)) + instances.append(instance.number) global props device = options[":target"] props["target"] = device.identifier props["types"] = set() - props["timer_vectors"] = tim_vectors = defaultdict(list) - vectors = [v["name"] for v in device.get_driver("core")["vector"] if "TIM" in v["name"]] - for instance in instances: - timstr = "TIM{}".format(instance) - for vector in vectors: - if (vector == timstr or ("_"+timstr+"_") in vector or - vector.startswith(timstr+"_") or vector.endswith("_"+timstr)): - tim_vectors[instance].append(vector) - return True def build(env): diff --git a/src/modm/platform/uart/at90_tiny_mega/module.lb b/src/modm/platform/uart/at90_tiny_mega/module.lb index 96cfef07dd..6d67eacd33 100644 --- a/src/modm/platform/uart/at90_tiny_mega/module.lb +++ b/src/modm/platform/uart/at90_tiny_mega/module.lb @@ -74,10 +74,10 @@ def prepare(module, options): ":math:algorithm", ":platform:gpio") - driver = device.get_driver("usart:avr") - if "instance" in driver: - for instance in listify(driver["instance"]): - module.add_submodule(Instance(int(instance))) + instances = device.driver("usart").instances() + if instances: + for instance in instances: + module.add_submodule(Instance(instance.number)) else: load_options(module) @@ -87,8 +87,7 @@ def build(env): env.outbasepath = "modm/src/modm/platform/uart" env.template("uart_defines.h") - driver = env[":target"].get_driver("usart:avr") - if "instance" not in driver: + if not env[":target"].driver("usart").instances(): env.substitutions = {"id": ""} env.template("uart.hpp.in") env.template("uart_tx.cpp.in") diff --git a/src/modm/platform/uart/sam/module.lb b/src/modm/platform/uart/sam/module.lb index 40126849d4..07d1b12442 100644 --- a/src/modm/platform/uart/sam/module.lb +++ b/src/modm/platform/uart/sam/module.lb @@ -15,12 +15,11 @@ props = {} class Instance(Module): - def __init__(self, driver, instance): - self.driver = driver - self.instance = int(instance) + def __init__(self, instance): + self.instance = instance def init(self, module): - module.name = str(self.instance) + module.name = self.instance.name module.description = "Instance {}".format(self.instance) def prepare(self, module, options): @@ -29,11 +28,10 @@ class Instance(Module): def build(self, env): device = env[":target"].identifier global props - props["id"] = self.instance - props["driver"] = self.driver - props["features"] = self.driver["feature"] if "feature" in self.driver else [] + props["id"] = self.instance.number + props["driver"] = self.instance.driver props["uart_name"] = 'Uart' - props["sercom_name"] = self.driver["name"].capitalize() + props["sercom_name"] = self.instance.driver.name.capitalize() env.substitutions = props env.outbasepath = "modm/src/modm/platform/uart" @@ -72,11 +70,10 @@ def prepare(module, options): props["tcbgt"] = ("feature" in drivers[0]) and ("tcbgt" in drivers[0]["feature"]) props["instances"] = [] - for driver in drivers: - for instance in driver["instance"]: - module.add_submodule(Instance(driver, instance)) - props["target"] = device.identifier + + for instance in device.driver("sercom").instances(): + module.add_submodule(Instance(instance)) return True def build(env): diff --git a/src/modm/platform/uart/stm32/module.lb b/src/modm/platform/uart/stm32/module.lb index fe2ee2aeec..052fd4e003 100644 --- a/src/modm/platform/uart/stm32/module.lb +++ b/src/modm/platform/uart/stm32/module.lb @@ -14,12 +14,11 @@ props = {} class Instance(Module): - def __init__(self, driver, instance): - self.driver = driver - self.instance = int(instance) + def __init__(self, instance): + self.instance = instance def init(self, module): - module.name = str(self.instance) + module.name = self.instance.name module.description = "Instance {}".format(self.instance) def prepare(self, module, options): @@ -48,10 +47,10 @@ class Instance(Module): def build(self, env): device = env[":target"].identifier global props - props["id"] = self.instance - props["driver"] = self.driver - props["features"] = self.driver["feature"] if "feature" in self.driver else [] - props["uart_name"] = self.driver["name"].capitalize() + props["driver"] = self.instance.driver + props["id"] = self.instance.number + props["features"] = self.instance.features() + props["uart_name"] = self.instance.driver.name.capitalize() env.substitutions = props env.outbasepath = "modm/src/modm/platform/uart" @@ -61,7 +60,7 @@ class Instance(Module): env.template("uart.hpp.in", "uart_{}.hpp".format(self.instance)) env.template("uart.cpp.in", "uart_{}.cpp".format(self.instance)) - props["instances"].append(self.instance) + props["instances"].append(self.instance.number) def init(module): @@ -84,26 +83,23 @@ def prepare(module, options): ":platform:rcc") global props - drivers = (device.get_all_drivers("uart") + device.get_all_drivers("usart")) - props["extended_driver"] = ("extended" in drivers[0]["type"]) - props["over8_sampling"] = ("feature" in drivers[0]) and ("over8" in drivers[0]["feature"]) - props["tcbgt"] = ("feature" in drivers[0]) and ("tcbgt" in drivers[0]["feature"]) + drivers = device.drivers("usart", "uart") + props["extended_driver"] = ("extended" in drivers[0].type) + props["shared_features"] = features = drivers[0].features() + props["over8_sampling"] = "over8" in features + props["tcbgt"] = "tcbgt" in features + props["half_duplex"] = "half-duplex" in features + props["7_bit"] = "7-bit" in features + props["target"] = device.identifier props["instances"] = [] - for driver in drivers: - for instance in driver["instance"]: - module.add_submodule(Instance(driver, instance)) - - shared_irqs = [v["name"] for v in device.get_driver("core")["vector"]] - shared_irqs = [v for v in shared_irqs if v.startswith("USART") and "_" in v] - if len(shared_irqs): - props["shared_irq"] = name = shared_irqs[0] - parts = name[5:].split("_") - props["shared_irq_ids"] = range(int(parts[0]), int(parts[1]) + 1) - else: - props["shared_irq_ids"] = [] + shared_irqs = device.core.shared_irqs("USART") + props["shared_irq"] = next(iter(shared_irqs.keys()), None) + props["shared_irq_ids"] = shared_irqs.get(props["shared_irq"], []) - props["target"] = device.identifier + for driver in drivers: + for instance in driver.instances(): + module.add_submodule(Instance(instance)) return True diff --git a/src/modm/platform/usb/stm32/module.lb b/src/modm/platform/usb/stm32/module.lb index 5cecd2517a..0752052d52 100644 --- a/src/modm/platform/usb/stm32/module.lb +++ b/src/modm/platform/usb/stm32/module.lb @@ -34,8 +34,7 @@ def common_usb_irqs(env): :returns: a dictionary of USB interrupt properties """ - usb_vectors = {v["name"] for v in env[":target"].get_driver("core")["vector"] - if any(v["name"].startswith(n) for n in ["USB", "OTG"])} + usb_vectors = set(env[":target"].core.vectors(lambda v: any(v.startswith(n) for n in ["USB", "OTG"]))) is_remap = any("_RMP" in v for v in usb_vectors) port_irqs = defaultdict(list) @@ -60,7 +59,7 @@ def generate_instance(env, port, otg=False): irq_data = env.query(":platform:usb:irqs") env.substitutions = { "port": port, - "peripheral": "Usbotg{}".format(port) if otg else "Usb", + "peripheral": "UsbOtg{}".format(port.capitalize()) if otg else "Usb", "is_otg": otg, "is_remap": irq_data["is_remap"], "irqs": irq_data["port_irqs"][port], diff --git a/test/modm/platform/gpio/module.lb b/test/modm/platform/gpio/module.lb index 823beebc61..ad2cf47928 100644 --- a/test/modm/platform/gpio/module.lb +++ b/test/modm/platform/gpio/module.lb @@ -109,10 +109,10 @@ def build(env): driver = device.get_driver("gpio") gpios = [g for g in driver["gpio"] if (g["port"].upper(), int(g["pin"])) in test_io] - peripherals = sorted([get_driver(s) for g in gpios for s in (g["signal"] if "signal" in g else [])]) + peripherals = sorted([env.filter("modm.fmt.driver")(s) for g in gpios for s in g.get("signal", [])]) connections = OrderedDict() for k in peripherals: - rconns = [(g["port"].upper(), int(g["pin"]), get_name(s), get_af(s)) for g in gpios for s in (g["signal"] if "signal" in g else []) if get_driver(s) == k] + rconns = [(g["port"].upper(), int(g["pin"]), get_name(s), get_af(s)) for g in gpios for s in g.get("signal", []) if get_driver(s) == k] # we need to remove duplicate GPIOs from this list # since we cannot set the same GPIO to multiple different AFs! conns = [] diff --git a/tools/build_script_generator/common.py b/tools/build_script_generator/common.py index 9dcddee52d..de7b441bcc 100644 --- a/tools/build_script_generator/common.py +++ b/tools/build_script_generator/common.py @@ -122,7 +122,7 @@ def common_memories(env): if "memory" in core_driver: memories.extend([ { - k:(int(v) if v.isdigit() else (int(v, 16) if v.startswith("0x") else v)) + k:(int(v) if str(v).isdigit() else (int(v, 16) if v.startswith("0x") else v)) for k, v in memory.items() } for memory in core_driver["memory"]