diff --git a/.gitmodules b/.gitmodules index 72de297697..5cdf30e0e9 100644 --- a/.gitmodules +++ b/.gitmodules @@ -49,3 +49,6 @@ [submodule "ext/nlohmann/json"] path = ext/nlohmann/json url = https://github.com/modm-ext/json-partial.git +[submodule "ext/st/cube-hal"] + path = ext/st/cube-hal + url = https://github.com/modm-ext/stm32-cube-hal-drivers.git diff --git a/ext/st/module.lb b/ext/st/cmsis.lb similarity index 71% rename from ext/st/module.lb rename to ext/st/cmsis.lb index 53cd92b173..85291ca556 100644 --- a/ext/st/module.lb +++ b/ext/st/cmsis.lb @@ -2,7 +2,7 @@ # -*- coding: utf-8 -*- # # Copyright (c) 2016, Fabian Greif -# Copyright (c) 2017, 2024, Niklas Hauser +# Copyright (c) 2017, 2024, 2025, Niklas Hauser # # This file is part of the modm project. # @@ -14,6 +14,8 @@ import re from pathlib import Path from collections import defaultdict +import subprocess + def getDefineForDevice(device_id, familyDefines): """ @@ -61,45 +63,67 @@ def getDefineForDevice(device_id, familyDefines): return None + +class RegisterMap: + def __init__(self, defines, logger): + self._defs = defines + self._log = logger + self.result = None + + def _result(self, query, value, ll): + self.result = value + self._log(f"{query} -{ll}-> {self.result}") + return self.result + + def findall(self, query, default=None): + if matches := re.findall(f"#define (?:{query}) ", self._defs): + return self._result(query, matches, "fn") + return self._result(query, default or [], "fd") + + def search(self, query, default=None): + if (match := re.search(f"#define (?:{query}) ", self._defs)) is not None: + if not (groups := match.groups()): + return self._result(query, match.group(0)[8:-1], "s0") + if len(groups) == 1: + return self._result(query, groups[0], "s1") + return self._result(query, groups, "sn") + return self._result(query, default, "sd") + + def _ops(self, re_pers, re_regs, re_bits, bit_fmt): + reg_bits = defaultdict(list) + matches = re.findall(f"#define (({re_pers})_({re_regs})_(?:{re_bits})) ", self._defs) + for whole, per, reg in matches: + reg_bits[f"{per}->{reg}"].append(whole) + statements = [f"{reg}{bit_fmt(' | '.join(bits))};" for reg, bits in reg_bits.items()] + return self._result((re_pers, re_regs, re_bits), "\n".join(statements), "r") + + def set(self, pers, regs, bits): + return self._ops(pers, regs, bits, lambda bits: f" |= {bits}") + + def clear(self, pers, regs, bits): + return self._ops(pers, regs, bits, lambda bits: f" &= ~({bits})") + + bprops = {} -def common_rcc_map(env): +def common_register_map(env): """ - Finds all CMSIS bit fields related to enabling and resetting peripherals - in the RCC of the format `RCC_(REGISTER)_(PERIPHERAL)_(TYPE)` where: + Finds all register and bit names in the CMSIS header file. - - REGISTER: a variation of `(BUS)(ID?)(ENR|RSTR)`, e.g. `AHB1ENR` - - PERIPHERAL: typical peripheral name, e.g. `GPIOA` - - TYPE: either `EN` or `RST`. - - :returns: a 2D-dictionary: `map[PERIPHERAL][TYPE] = REGISTER` + :returns: a RegisterMap object that allows regex-ing for register names. """ - headers = env.query("headers") - core_header = repopath("ext/arm/cmsis/CMSIS/Core/Include", headers["core_header"]) - - content = "" - for header_path in [core_header, localpath(bprops["folder"], headers["device_header"])]: - content += Path(header_path).read_text(encoding="utf-8", errors="replace") - - # find mpu and fpu features - features = re.findall(r"#define +__([MF]PU)_PRESENT +([01])", content) - core_features = {f[0]:bool(int(f[1])) for f in features} - # find all peripherals - mperipherals = re.findall(r"#define +(.*?) +\(\((.*?_Type(?:Def)?)", content) - # We only care about the absolute peripheral addresses - peripherals = [(p[0],p[1]) for p in mperipherals] - # filter out MPU and/or FPU if required - peripherals = filter(lambda p: p[0] not in core_features or core_features[p[0]], peripherals) - peripherals = sorted(peripherals, key=lambda p: p[0]) - # print("\n".join([s+" -> "+hex(a) for (s,k,a) in peripherals])) - - # Find all RCC enable and reset definitions - match = re.findall(r"RCC_([A-Z0-9]*?)_([A-Z0-9]+?)(EN|RST) ", content) - rcc_map = defaultdict(dict) - for (reg, per, typ) in match: - rcc_map[per][typ] = reg - - bprops["peripherals"] = peripherals - return rcc_map + cmsis = env.query(":cmsis:device:headers") + include_paths = [repopath("ext/arm/cmsis/CMSIS/Core/Include"), localpath(bprops["folder"])] + headers = [Path(localpath(bprops["folder"], cmsis["device_header"]))] + headers += env.query(":cmsis:ll:__headers", []) + + cmd = "arm-none-eabi-gcc" + cmd += " -dM -E -mcpu=" + cmsis["core_header"][:-2].replace("core_c", "cortex-") + cmd += " -D " + cmsis["define"] + for p in include_paths: cmd += f" -I {p}" + for h in headers: cmd += f" {h}" + output = subprocess.run(cmd, shell=True, capture_output=True) + + return RegisterMap(output.stdout.decode("utf-8"), env.log.debug) def common_header_file(env): @@ -127,7 +151,7 @@ def common_header_file(env): define = None content = Path(localpath(folder, family_header)).read_text(encoding="utf-8", errors="replace") - match = re.findall(r"if defined\((?PSTM32[CFGHLU][\w\d]+)\)", content) + match = re.findall(r"if defined\((STM32[A-Z][\w\d]+)\)", content) define = getDefineForDevice(device.identifier, match) if define is None or match is None: raise ValidateException("No device define found for '{}'!".format(device.partname)) @@ -198,17 +222,17 @@ def prepare(module, options): return False module.add_query( - EnvironmentQuery(name="rcc-map", factory=common_rcc_map)) + EnvironmentQuery(name="headers", factory=common_header_file)) module.add_query( EnvironmentQuery(name="peripherals", factory=common_peripherals)) module.add_query( - EnvironmentQuery(name="headers", factory=common_header_file)) + EnvironmentQuery(name="registers", factory=common_register_map)) module.depends(":cmsis:core") return True def validate(env): - env.query("rcc-map") + env.query("headers") env.query("peripherals") def build(env): diff --git a/ext/st/cube-hal b/ext/st/cube-hal new file mode 160000 index 0000000000..12ab4b0749 --- /dev/null +++ b/ext/st/cube-hal @@ -0,0 +1 @@ +Subproject commit 12ab4b0749ef968422eb3a0c0bd8081501b35829 diff --git a/ext/st/ll.lb b/ext/st/ll.lb new file mode 100644 index 0000000000..6a39ca3715 --- /dev/null +++ b/ext/st/ll.lb @@ -0,0 +1,59 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# +# Copyright (c) 2025, 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/. +# ----------------------------------------------------------------------------- + +import re +from pathlib import Path + +class Header(Module): + def __init__(self, header): + self.name = header.stem.split("_ll_")[1] + self.header = header + + def init(self, module): + module.name = self.name + module.description = self.name.replace("_", " ").upper() + + def prepare(self, module, options): + return True + + def build(self, env): + env.outbasepath = "modm/ext/st/ll" + env.copy(self.header, f"{self.name}.h") + + +def init(module): + module.name = ":cmsis:ll" + module.description = "STM32 Low-Level (LL) Library" + + +def prepare(module, options): + target = options[":target"].identifier + if target.platform != "stm32": + return False + + folder = f"stm32{target.family}xx" + headers = [] + for header in Path(localpath(f"cube-hal/{folder}/Inc")).glob("*_ll_*.h"): + module.add_submodule(header := Header(header)) + headers.append(header) + + module.add_query( + EnvironmentQuery(name="__headers", factory=lambda env: + [header.header for header in headers + if env.has_module(f":cmsis:ll:{header.name}")])) + + module.depends(":cmsis:device") + return True + + +def build(env): + pass diff --git a/src/modm/platform/clock/stm32/module.lb b/src/modm/platform/clock/stm32/module.lb index c426d22ac7..8a51d21907 100644 --- a/src/modm/platform/clock/stm32/module.lb +++ b/src/modm/platform/clock/stm32/module.lb @@ -12,6 +12,7 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. # ----------------------------------------------------------------------------- +from collections import defaultdict def init(module): module.name = ":platform:rcc" @@ -21,129 +22,110 @@ def prepare(module, options): if not options[":target"].has_driver("rcc:stm32*"): return False - module.depends(":cmsis:device", ":utils", ":platform:clock", ":architecture:delay") - # FIXME: Move Peripherals enum somewhere better - module.depends(":platform:gpio") + module.depends(":cmsis:device", ":utils", ":platform:clock", + ":architecture:delay", ":platform:gpio", ":cmsis:ll:rcc") return True def build(env): device = env[":target"] - driver = device.get_driver("rcc") - - properties = {} - properties["target"] = target = device.identifier - properties["partname"] = device.partname - properties["core"] = core = device.get_driver("core")["type"] - - if target["family"] in ["c0"]: - properties["hsi_frequency"] = 48_000_000 - properties["lsi_frequency"] = 32_000 - properties["boot_frequency"] = 12_000_000 - elif target["family"] in ["f0", "f1", "f3"]: - properties["hsi_frequency"] = 8_000_000 - properties["lsi_frequency"] = 40_000 - properties["boot_frequency"] = properties["hsi_frequency"] - elif target["family"] in ["h7"]: - properties["hsi_frequency"] = 64_000_000 - properties["lsi_frequency"] = 32_000 - properties["boot_frequency"] = properties["hsi_frequency"] - elif target["family"] in ["l0", "l1"]: - properties["hsi_frequency"] = 16_000_000 - properties["lsi_frequency"] = 37_000 - properties["msi_frequency"] = 2_097_000 - properties["boot_frequency"] = properties["msi_frequency"] - elif target["family"] in ["l5"]: - properties["hsi_frequency"] = 16_000_000 - properties["lsi_frequency"] = 32_000 - properties["msi_frequency"] = 4_000_000 - properties["boot_frequency"] = properties["msi_frequency"] + target = device.identifier + regs = env.query(":cmsis:device:registers") + + # These definitions must exist on all devices + boot_frequency = "HSI_VALUE" + if target.family in ["c0"]: + boot_frequency = "12'000'000" + elif target.family in ["l0", "l1"]: + boot_frequency = "2'097'000" + elif target.family in ["l5"]: + boot_frequency = "4'000'000" + + # We're using two regex here, since some headers have both PLLSOURCE *and* PLL1SOURCE + pll_source = regs.findall(r"(LL_RCC_PLLSOURCE_(.+?))") or regs.findall(r"(LL_RCC_PLL1SOURCE_(.+?))") + assert pll_source, "Cannot find PllSource enums" + + cfgr_sws_pos = regs.search("RCC_.*?_SWS_Pos") + assert (sys_source := regs.findall(r"(LL_RCC_SYS_CLKSOURCE_(.{1,9}))")), "Cannot find SystemClockSource enums" + assert (rtc_source := regs.findall(r"(LL_RCC_RTC_CLKSOURCE_(.+?))")), "Cannot find RealTimeClockSource enums" + assert (ahb_prescaler := regs.findall(r"(LL_RCC_SYSCLK_DIV_(\d+?))")), "Cannot find AhbPrescaler enums" + + apb_prescaler = defaultdict(list) + for reg, bus, div in regs.findall(r"(LL_RCC_APB(\d)?_DIV_(\d+?))"): + apb_prescaler[bus].append((reg, div)) + assert apb_prescaler, "Cannot find any ApbPrescaler enums" + + mco_source = defaultdict(lambda: ([], [])) + for reg, mco, name in regs.findall(r"(LL_RCC_MCO(\d?)SOURCE_(.+?))"): + mco_source[mco][0].append((reg, name)) + for reg, mco, div in regs.findall(r"(LL_RCC_MCO(\d?)_DIV_(\d+?))"): + mco_source[mco][1].append((reg, div)) + assert mco_source, "Cannot find any ClockOutputSource enums" + + # These may not exist on all devices + can_source = regs.findall(r"(LL_RCC_FDCAN_CLKSOURCE_(.+?))") + pll_mul = regs.findall(r"(LL_RCC_PLL_MUL_(\d+_?\d?))") + pll_input_range = regs.findall(r"(LL_RCC_PLLINPUTRANGE_(\d+_\d+))") + usbprescaler = regs.search(r"RCC_CFGR_USBPRE") + lse_drive = regs.findall(r"(LL_RCC_LSEDRIVE_(.+?))") + hsi48 = regs.search(r"RCC_.*?_HSI48ON") + hsi14 = regs.search(r"RCC_.*?_HSI14ON") + msi_range_selection = regs.search(r"RCC_.+?_MSIRGSEL") + epod_booster = regs.findall(r"(LL_RCC_PLL1MBOOST_DIV_(\d+))") + + if (hsi_div4 := regs.search(r"RCC_.*?_HSIDIVEN")): + # Normalize the HSIDIVEN to be Div4 on the STM32L0 family + hsi_div = [("0", "1"), (hsi_div4, "4")] else: - properties["hsi_frequency"] = 16_000_000 - properties["lsi_frequency"] = 32_000 - properties["boot_frequency"] = properties["hsi_frequency"] - - # TODO: Move this data into the device files - properties["usbprescaler"] = device.has_driver("usb") and target.family in ["f0", "f1", "f3"] - properties["pllprediv"] = \ - (target["family"] in ["f0", "f3"] or (target["family"] == "f1" and target["name"] in ["00", "05", "07"])) - properties["pllprediv2"] = False # FIXME: not sure what value this should have - properties["pll_hse_prediv2"] = target["family"] == "f1" and target["name"] in ["01", "02", "03"] - properties["hsi48"] = \ - (target["family"] in ["g4", "h5", "h7", "l5", "u0", "u5"]) or \ - (target["family"] == "f0" and target["name"] in ["42", "48", "71", "72", "78", "91", "98"]) or \ - (target["family"] == "g0" and target["name"] in ["b1", "c1"]) or \ - (target["family"] == "l0" and target["name"][1] == "2") or \ - (target["family"] == "l4" and target["name"][0] not in ["7", "8"]) - if target["family"] in ["g4", "l0", "l4", "l5", "u0"]: - properties["hsi48_cr"] = "CRRCR" - elif target["family"] in ["g0", "h5", "h7", "u5"]: - properties["hsi48_cr"] = "CR" - elif target["family"] in ["f0"]: - properties["hsi48_cr"] = "CR2" - properties["pll_p"] = ((target["family"] == "l4" and target["name"] not in ["12", "22"]) or target["family"] == "g4") - properties["overdrive"] = (target["family"] == "f7") or \ - ((target["family"] == "f4") and target["name"] in ["27", "29", "37", "39", "46", "69", "79"]) - properties["vos0_overdrive"] = (target["family"] == "h7") and \ - target["name"] in ["42", "43", "45", "47", "50", "53", "55", "57"] - properties["has_r1mode"] = (target["family"] == "g4") or \ - (target["family"] == "l4" and target["name"][0] in ["p", "q", "r", "s"]) - properties["pllsai_p_usb"] = (target["family"] == "f7") or \ - ((target["family"] == "f4") and target["name"] in ["46", "69", "79"]) - - if target.family in ["h7"]: - if target.name in ["a3", "b0", "b3"]: - properties["cfgr_prescaler"] = "CDCFGR1" - else: - properties["cfgr_prescaler"] = "D1CFGR" - elif target.family in ["u5"]: - properties["cfgr_prescaler"] = "CFGR2" - else: - properties["cfgr_prescaler"] = "CFGR" - - if target.family in ["h7"]: - if target.name in ["a3", "b0", "b3"]: - properties["cfgr2"] = "CDCFGR2" - else: - properties["cfgr2"] = "D2CFGR" - elif target.family in ["u5"]: - properties["cfgr2"] = "CFGR2" - else: - properties["cfgr2"] = "CFGR" - - if target.family in ["h7"]: - if target.name in ["a3", "b0", "b3"]: - properties["ccipr1"] = "CDCCIP1R" - else: - properties["ccipr1"] = "D2CCIP1R" - elif target.family in ["l5", "u5"]: - properties["ccipr1"] = "CCIPR1" - else: - properties["ccipr1"] = "CCIPR" - - properties["d1"] = ("CD" if target.name in ["a3", "b0", "b3"] else "D1") \ + hsi_div = regs.findall(r"(LL_RCC_HSI_DIV_?(\d+))") + + # There is sadly no easy way to find the MSI range values, so we have to hardcode them + msi_range = regs.findall(r"(LL_RCC_MSIK?RANGE_)\d+") or ("", []) + if len(msi_range) == 7: + msi_range = (msi_range[0], ("kHz65_536", "kHz131_072", "kHz262_144", "kHz524_288", "MHz1_048", "MHz2_097", "MHz4_194")) + elif len(msi_range) == 12: + msi_range = (msi_range[0], ("kHz100", "kHz200", "kHz400", "kHz800", "MHz1", "MHz2", + "MHz4", "MHz8", "MHz16", "MHz24", "MHz32", "MHz48")) + elif len(msi_range) == 16: + msi_range = (msi_range[0], ("MHz48", "MHz24", "MHz16", "MHz12", "MHz4", "MHz2", "MHz1_5", "MHz1", "MHz3_072", + "MHz1_536", "MHz1_024", "kHz768", "kHz400", "kHz200", "kHz133", "kHz100")) + msi_clocks = (["K", "S"] if "K" in msi_range[0] else [""]) if msi_range else [] + + clk48_source = [] + if regs.search(r"RCC_.+?_(?:CL?K48M?SEL|ICLKSEL)"): + clk48_source = regs.findall(r"(LL_RCC_(?:USB|CL?K48)_CLKSOURCE_(.+?))") + + # ------------------------------------------------------------------------- + # TODO: Replace this data with register queries + pllprediv = \ + (target.family in ["f0", "f3"] or (target.family == "f1" and target.name in ["00", "05", "07"])) + pllprediv2 = False # FIXME: not sure what value this should have + pll_hse_prediv2 = target.family == "f1" and target.name in ["01", "02", "03"] + pll_p = ((target.family == "l4" and target.name not in ["12", "22"]) or target.family == "g4") + overdrive = (target.family == "f7") or \ + ((target.family == "f4") and target.name in ["27", "29", "37", "39", "46", "69", "79"]) + vos0_overdrive = (target.family == "h7") and \ + target.name in ["42", "43", "45", "47", "50", "53", "55", "57"] + has_r1mode = (target.family == "g4") or \ + (target.family == "l4" and target.name[0] in ["p", "q", "r", "s"]) + pllsai_p_usb = (target.family == "f7") or \ + ((target.family == "f4") and target.name in ["46", "69", "79"]) + + d2 = ("CD" if target.name in ["a3", "b0", "b3"] else "D2") \ if target.family == "h7" else "" - properties["d2"] = ("CD" if target.name in ["a3", "b0", "b3"] else "D2") \ - if target.family == "h7" else "" - properties["cfgr3"] = ("SRDCFGR" if target.name in ["a0", "a3", "b0", "b3"] else "D3CFGR") - properties["d3"] = ("SRD" if target.name in ["a0", "a3", "b0", "b3"] else "D3") - properties["bdcr"] = "CSR1" if target.family in ["c0"] else "CSR" if target.family in ["l0", "l1"] else "BDCR" - properties["pll_ids"] = ["1", "2", "3"] if target.family in ["h7", "u5"] else [] if target.family in ["c0"] else [""] - properties["has_smps"] = target["family"] == "h7" and (target["name"] in ["25", "35", "45", "47", "55", "57"] or \ - (target["name"] in ["30", "a3", "b0", "b3"] and target["variant"] == "q")) + d3 = ("SRD" if target.name in ["a0", "a3", "b0", "b3"] else "D3") + pll_ids = ["1", "2", "3"] if target.family in ["h7", "u5"] else [] if target.family in ["c0"] else [""] + has_smps = target.family == "h7" and (target.name in ["25", "35", "45", "47", "55", "57"] or \ + (target.name in ["30", "a3", "b0", "b3"] and target["variant"] == "q")) + # ------------------------------------------------------------------------- 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 - env.substitutions = properties - env.outbasepath = "modm/src/modm/platform/clock" - - env.template("rcc.cpp.in") - env.template("rcc.hpp.in") - all_peripherals = env.query(":cmsis:device:peripherals") - rcc_map = env.query(":cmsis:device:rcc-map") + rcc_map = defaultdict(dict) + for (reg, per, typ) in regs.findall(r"RCC_(A[HP]B\d?(?:ENR|RSTR)\d?)_(.*?)(EN|RST)"): + rcc_map[per][typ] = reg rcc_enable = {} rcc_reset = {} @@ -210,8 +192,9 @@ def build(env): if "RST" in mode: rcc_reset[per.capitalize()] = (nper, mode["RST"]) - env.substitutions.update({ - "rcc_enable": rcc_enable, - "rcc_reset": rcc_reset, - }) + + env.outbasepath = "modm/src/modm/platform/clock" + env.substitutions = locals() + env.template("rcc.cpp.in") + env.template("rcc.hpp.in") env.template("rcc_impl.hpp.in") diff --git a/src/modm/platform/clock/stm32/rcc.cpp.in b/src/modm/platform/clock/stm32/rcc.cpp.in index e3c471f357..fb5aba480e 100644 --- a/src/modm/platform/clock/stm32/rcc.cpp.in +++ b/src/modm/platform/clock/stm32/rcc.cpp.in @@ -27,135 +27,6 @@ constinit uint16_t modm_fastdata delay_fcpu_MHz(computeDelayMhz(Rcc::BootFrequen constinit uint16_t modm_fastdata delay_ns_per_loop(computeDelayNsPerLoop(Rcc::BootFrequency)); // ---------------------------------------------------------------------------- -%% if target.family == "f0" -bool -Rcc::enableInternalClockMHz14(uint32_t waitCycles) -{ - bool retval; - RCC->CR2 |= RCC_CR2_HSI14ON; - while (not (retval = (RCC->CR2 & RCC_CR2_HSI14RDY)) and --waitCycles) - ; - return retval; -} -%% endif - -%% if hsi48 -bool -Rcc::enableInternalClockMHz48(uint32_t waitCycles) -{ - bool retval; - RCC->{{hsi48_cr}} |= RCC_{{hsi48_cr}}_HSI48ON; - while (not (retval = (RCC->{{hsi48_cr}} & RCC_{{hsi48_cr}}_HSI48RDY)) and --waitCycles) - ; - return retval; -} -%% endif - -bool -Rcc::enableInternalClock(uint32_t waitCycles) -{ - bool retval; - RCC->CR |= RCC_CR_HSION; - while (not (retval = (RCC->CR & RCC_CR_HSIRDY)) and --waitCycles) - ; - return retval; -} - -%% if target.family in ["l0", "l1", "l4", "l5"] -bool -Rcc::enableMultiSpeedInternalClock(MsiFrequency msi_frequency, uint32_t waitCycles) -{ - bool retval; -%% if target.family in ["l0", "l1"] - RCC->ICSCR = (RCC->ICSCR & ~RCC_ICSCR_MSIRANGE) | static_cast(msi_frequency); - RCC->CR |= RCC_CR_MSION; - while (not (retval = (RCC->CR & RCC_CR_MSIRDY)) and --waitCycles) -%% else - RCC->CR = (RCC->CR & ~RCC_CR_MSIRANGE) | static_cast(msi_frequency) | RCC_CR_MSIRGSEL | RCC_CR_MSION; - while (not (retval = (RCC->CR & RCC_CR_MSIRDY)) and --waitCycles) -%% endif - ; - return retval; -} -%% endif - -%% if target.family in ["u5"] -// MSIxRANGE can be modified when MSIx is OFF (MSISON = 0) or when MSIx is -// ready (MSIxRDY = 1). MSIxRANGE must NOT be modified when MSIx is ON -// and NOT ready (MSIxON = 1 and MSIxRDY = 0) -%% for msi in ["S", "K"] -bool -Rcc::enableMultiSpeedInternalClock{{msi}}(MsiFrequency msi_frequency, uint32_t waitCycles) -{ - bool retval; - uint32_t waitCycles_ = waitCycles; - while ((not (retval = (((RCC->CR & RCC_CR_MSI{{msi}}ON) == 0) || ((RCC->CR & RCC_CR_MSI{{msi}}RDY) == RCC_CR_MSI{{msi}}RDY)))) || --waitCycles_) - ; - if (!retval) - return false; - RCC->ICSCR1 = (RCC->ICSCR1 & ~RCC_ICSCR1_MSI{{msi}}RANGE_Msk) | RCC_ICSCR1_MSIRGSEL | (static_cast(msi_frequency) << RCC_ICSCR1_MSI{{msi}}RANGE_Pos); - RCC->CR |= RCC_CR_MSI{{msi}}ON; - waitCycles_ = waitCycles; - while (not (retval = (RCC->CR & RCC_CR_MSI{{msi}}RDY)) and --waitCycles) - ; - return retval; -} - -%% endfor -%% endif - -bool -Rcc::enableExternalClock(uint32_t waitCycles) -{ - bool retval; - RCC->CR |= RCC_CR_HSEBYP | RCC_CR_HSEON; - while (not (retval = (RCC->CR & RCC_CR_HSERDY)) and --waitCycles) - ; - return retval; -} - -bool -Rcc::enableExternalCrystal(uint32_t waitCycles) -{ - bool retval; - RCC->CR = (RCC->CR & ~RCC_CR_HSEBYP) | RCC_CR_HSEON; - while (not (retval = (RCC->CR & RCC_CR_HSERDY)) and --waitCycles) - ; - return retval; -} - - -%% set lsi_cr="CSR2" if target.family in ["c0"] else "BDCR" if target.family in ["u5"] else "CSR" -bool -Rcc::enableLowSpeedInternalClock(uint32_t waitCycles) -{ - bool retval; - RCC->{{lsi_cr}} |= RCC_{{lsi_cr}}_LSION; - while (not (retval = (RCC->{{lsi_cr}} & RCC_{{lsi_cr}}_LSIRDY)) and --waitCycles) - ; - return retval; -} - -bool -Rcc::enableLowSpeedExternalClock(uint32_t waitCycles) -{ - bool retval; - RCC->{{bdcr}} |= RCC_{{bdcr}}_LSEBYP | RCC_{{bdcr}}_LSEON; - while (not (retval = (RCC->{{bdcr}} & RCC_{{bdcr}}_LSERDY)) and --waitCycles) - ; - return retval; -} - -bool -Rcc::enableLowSpeedExternalCrystal(uint32_t waitCycles) -{ - bool retval; - RCC->{{bdcr}} = (RCC->{{bdcr}} & ~RCC_{{bdcr}}_LSEBYP) | RCC_{{bdcr}}_LSEON; - while (not (retval = (RCC->{{bdcr}} & RCC_{{bdcr}}_LSERDY)) and --waitCycles) - ; - return retval; -} - %% for id in pll_ids bool Rcc::enablePll{{id}}(PllSource source, const PllFactors& pllFactors, uint32_t waitCycles) @@ -563,33 +434,6 @@ Rcc::configurePowerSource(PowerSource source, uint32_t waitCycles) } %% endif -%% if target["family"] == "l0" -bool -Rcc::setHsiPredivider4Enabled(bool divideBy4, uint32_t waitCycles) -{ - const uint32_t enableFlag = divideBy4 ? RCC_CR_HSIDIVEN : 0; - RCC->CR = (RCC->CR & ~RCC_CR_HSIDIVEN) | enableFlag; - while (isHsiPredivider4Active() != divideBy4) - if (waitCycles-- == 0) return false; - - return true; -} -%% endif - -%% set sysclksrcf_cfgr="CFGR1" if target.family in ["u5"] else "CFGR" -bool -Rcc::enableSystemClock(SystemClockSource src, uint32_t waitCycles) -{ - RCC->{{sysclksrcf_cfgr}} = (RCC->{{sysclksrcf_cfgr}} & ~RCC_{{sysclksrcf_cfgr}}_SW) | uint32_t(src); - - // Wait till the main PLL is used as system clock source - src = SystemClockSource(uint32_t(src) << RCC_{{sysclksrcf_cfgr}}_SWS_Pos); - while ((RCC->{{sysclksrcf_cfgr}} & RCC_{{sysclksrcf_cfgr}}_SWS) != uint32_t(src)) - if (not --waitCycles) return false; - - return true; -} - %% if target.family in ["g4", "l5"] bool Rcc::setCanPrescaler(CanPrescaler prescaler) diff --git a/src/modm/platform/clock/stm32/rcc.hpp.in b/src/modm/platform/clock/stm32/rcc.hpp.in index ff30e3893b..5286eb62bb 100644 --- a/src/modm/platform/clock/stm32/rcc.hpp.in +++ b/src/modm/platform/clock/stm32/rcc.hpp.in @@ -1,7 +1,7 @@ /* * Copyright (c) 2012, 2016, Sascha Schade * Copyright (c) 2012, 2017, Fabian Greif - * Copyright (c) 2012, 2014-2017, Niklas Hauser + * Copyright (c) 2012, 2014-2017, 2025, Niklas Hauser * Copyright (c) 2013-2014, Kevin Läufer * Copyright (c) 2018, 2021-2022, Christopher Durand * @@ -21,6 +21,7 @@ #include #include #include +#include namespace modm::platform { @@ -33,503 +34,171 @@ namespace modm::platform * sources & outputs, set PLL parameters and AHB & APB prescalers. * Don't forget to set the flash latencies. * - * @author Niklas Hauser * @ingroup modm_platform_rcc */ class Rcc { public: - static constexpr uint32_t LsiFrequency = {{ lsi_frequency | modm.digsep }}; - static constexpr uint32_t HsiFrequency = {{ hsi_frequency | modm.digsep }}; - static constexpr uint32_t BootFrequency = {{ boot_frequency | modm.digsep }}; - -%% if target.family == "c0" - enum class - HsiSysDivider : uint32_t - { - Div1 = 0, - Div2 = RCC_CR_HSIDIV_0, - Div4 = RCC_CR_HSIDIV_1, - Div8 = RCC_CR_HSIDIV_1 | RCC_CR_HSIDIV_0, - Div16 = RCC_CR_HSIDIV_2, - Div64 = RCC_CR_HSIDIV_2 | RCC_CR_HSIDIV_1, - Div128 = RCC_CR_HSIDIV_2 | RCC_CR_HSIDIV_1 | RCC_CR_HSIDIV_0, - }; - -%% else - enum class - PllSource : uint32_t - { -%% if target.family == "h7" - /// High speed internal clock (4-64 MHz) - Hsi = RCC_PLLCKSELR_PLLSRC_HSI, - InternalClock = Hsi, - /// Low speed internal clock (4MHz) - Cse = RCC_PLLCKSELR_PLLSRC_CSI, - /// High speed external clock - Hse = RCC_PLLCKSELR_PLLSRC_HSE, -%% elif target.family in ["f2", "f4", "f7", "l4", "g0", "g4"] - /// High speed internal clock (16 MHz) - Hsi = RCC_PLLCFGR_PLLSRC_HSI, - InternalClock = Hsi, - /// High speed external clock - Hse = RCC_PLLCFGR_PLLSRC_HSE, -%% elif target.family in ["f0", "f3"] - /// High speed internal clock (8 MHz) - // On STM32F0 and STM32F3 some devices have a fixed /2 pre-divider, some have a configurable - // pre-divider and some have both, selectable via pll source mux - %% if (target.family == "f0" and (target.name in ["42", "48", "70", "71", "72", "78", "91", "98"] or (target.name in ["30"] and target.size in ["c"]))) or (target.family == "f3" and target.name in ["02", "03", "98"] and target.size in ["d", "e"]) - Hsi = RCC_CFGR_PLLSRC_HSI_PREDIV, - InternalClock = Hsi, - %% endif - %% if (target.family == "f0") or (target.family == "f3" and target.name in ["18", "28", "58", "73", "78"]) or (target.family == "f3" and target.size in ["8", "c"]) - HsiDiv2 = RCC_CFGR_PLLSRC_HSI_DIV2, - %% endif - /// High speed external clock - Hse = RCC_CFGR_PLLSRC_HSE_PREDIV, -%% elif target.family in ["f1", "l1"] - /// High speed internal clock (8 MHz) - Hsi = 0, - InternalClock = Hsi, - /// High speed external clock - Hse = RCC_CFGR_PLLSRC, -%% elif target.family == "l0" - /// High speed internal clock (16 MHz) - Hsi = 0, - Hsi16 = Hsi, - InternalClock = Hsi16, - /// High speed external clock - Hse = RCC_CFGR_PLLSRC, -%% elif target.family == "l5" - /// High speed internal clock (16 MHz) - Hsi = RCC_PLLCFGR_PLLSRC_1, - Hsi16 = Hsi, - InternalClock = Hsi16, - /// High speed external clock - Hse = RCC_PLLCFGR_PLLSRC_1 | RCC_PLLCFGR_PLLSRC_0, - /// Multi speed internal clock - Msi = RCC_PLLCFGR_PLLSRC_0, - MultiSpeedInternalClock = Msi, -%% elif target.family in ["u5"] - None = 0b00, - MsiS = 0b01, - Hsi16 = 0b10, - Hse = 0b11, -%% endif -%% if hsi48 and target.family in ["f0"] - /// High speed internal clock (48 MHz) - Hsi48 = RCC_CFGR_PLLSRC_HSI48_PREDIV, - InternalClockMHz48 = Hsi48, -%% endif -%% if target.family in ["l4"] - Msi = RCC_PLLCFGR_PLLSRC_MSI, - MultiSpeedInternalClock = Msi, -%% endif - ExternalClock = Hse, - ExternalCrystal = Hse, - }; -%% endif - -%% if target.family in ["l0", "l1"] - enum class - PllMultiplier : uint32_t - { - Mul3 = RCC_CFGR_PLLMUL3, - Mul4 = RCC_CFGR_PLLMUL4, - Mul6 = RCC_CFGR_PLLMUL6, - Mul8 = RCC_CFGR_PLLMUL8, - Mul12 = RCC_CFGR_PLLMUL12, - Mul16 = RCC_CFGR_PLLMUL16, - Mul24 = RCC_CFGR_PLLMUL24, - Mul32 = RCC_CFGR_PLLMUL32, - Mul48 = RCC_CFGR_PLLMUL48, - }; -%% endif + static constexpr uint32_t LsiFrequency = LSI_VALUE; + static constexpr uint32_t HsiFrequency = HSI_VALUE; + static constexpr uint32_t BootFrequency = {{ boot_frequency }}; enum class SystemClockSource : uint32_t { -%% if target.family == "c0" - Hsi = RCC_CFGR_SWS_HSI, - Hse = RCC_CFGR_SWS_HSE, - Lsi = RCC_CFGR_SWS_LSI, - Lse = RCC_CFGR_SWS_LSE, -%% elif target.family == "l5" - Msi = 0, - Hsi = RCC_CFGR_SW_0, - Hsi16 = Hsi, - Hse = RCC_CFGR_SW_1, - Pll = RCC_CFGR_SW_1 | RCC_CFGR_SW_0, -%% elif target.family in ["u5"] - Msi = 0b00, - Hsi16 = 0b01, - Hse = 0b10, - Pll = 0b11, -%% else - Hsi = RCC_CFGR_SW_HSI, -%% if target.family == "l0" - Hsi16 = Hsi, -%% endif - Hse = RCC_CFGR_SW_HSE, -%% if hsi48 and target.family in ["f0"] - Hsi48 = RCC_CFGR_SW_HSI48, - InternalClockMHz48 = Hsi48, -%% endif -%% if target.family in ["l0", "l4"] - Msi = RCC_CFGR_SW_MSI, - MultiSpeedInternalClock = Msi, -%% endif - - InternalClock = Hsi, - ExternalClock = Hse, - ExternalCrystal = Hse, -%% if target.family == "h7" - Pll1P = RCC_CFGR_SW_PLL1, -%% else - Pll = RCC_CFGR_SW_PLL, -%% endif -%% endif +%% for val, name in sys_source | sort + {{name | capitalize }} = {{val}}, +%% endfor }; + static bool + enableSystemClock(SystemClockSource src, uint32_t waitCycles = 2048) + { + LL_RCC_SetSysClkSource(uint32_t(src)); + const uint32_t sws = uint32_t(src) << {{cfgr_sws_pos}}; + while (LL_RCC_GetSysClkSource() != sws and --waitCycles) ; + return waitCycles; + } enum class RealTimeClockSource : uint32_t { - Lsi = RCC_{{bdcr}}_RTCSEL_1, - Lse = RCC_{{bdcr}}_RTCSEL_0, - Hse = RCC_{{bdcr}}_RTCSEL_0 | RCC_{{bdcr}}_RTCSEL_1, - - ExternalClock = Hse, - ExternalCrystal = Hse, - LowSpeedInternalClock = Lsi, - LowSpeedExternalClock = Lse, - LowSpeedExternalCrystal = Lse +%% for val, name in rtc_source | sort + {{name | capitalize}} = {{val}}, +%% endfor }; + static inline void + enableRealTimeClock(RealTimeClockSource src) + { + LL_RCC_SetRTCClockSource(uint32_t(src)); + } enum class WatchdogClockSource : uint32_t { - LowSpeedInternalClock = 0 + Lsi = 0 }; - - enum class - AhbPrescaler : uint32_t + static inline void + enableWatchdogClock(WatchdogClockSource src = WatchdogClockSource::Lsi) { -%% if target.family in ["c0", "l5", "u5"] - Div1 = 0b0000 << RCC_{{cfgr_prescaler}}_HPRE_Pos, - Div2 = 0b1000 << RCC_{{cfgr_prescaler}}_HPRE_Pos, - Div4 = 0b1001 << RCC_{{cfgr_prescaler}}_HPRE_Pos, - Div8 = 0b1010 << RCC_{{cfgr_prescaler}}_HPRE_Pos, - Div16 = 0b1011 << RCC_{{cfgr_prescaler}}_HPRE_Pos, - Div64 = 0b1100 << RCC_{{cfgr_prescaler}}_HPRE_Pos, - Div128 = 0b1101 << RCC_{{cfgr_prescaler}}_HPRE_Pos, - Div256 = 0b1110 << RCC_{{cfgr_prescaler}}_HPRE_Pos, - Div512 = 0b1111 << RCC_{{cfgr_prescaler}}_HPRE_Pos -%% else - Div1 = RCC_{{cfgr_prescaler}}_HPRE_DIV1, - Div2 = RCC_{{cfgr_prescaler}}_HPRE_DIV2, - Div4 = RCC_{{cfgr_prescaler}}_HPRE_DIV4, - Div8 = RCC_{{cfgr_prescaler}}_HPRE_DIV8, - Div16 = RCC_{{cfgr_prescaler}}_HPRE_DIV16, - Div64 = RCC_{{cfgr_prescaler}}_HPRE_DIV64, - Div128 = RCC_{{cfgr_prescaler}}_HPRE_DIV128, - Div256 = RCC_{{cfgr_prescaler}}_HPRE_DIV256, - Div512 = RCC_{{cfgr_prescaler}}_HPRE_DIV512 -%% endif - }; + (void) src; + } -%% if target.family in ["c0"] - enum class - ApbPrescaler : uint32_t - { - Div1 = RCC_CFGR_PPRE_0, - Div2 = RCC_CFGR_PPRE_2, - Div4 = RCC_CFGR_PPRE_2 | RCC_CFGR_PPRE_0, - Div8 = RCC_CFGR_PPRE_2 | RCC_CFGR_PPRE_1, - Div16 = RCC_CFGR_PPRE_2 | RCC_CFGR_PPRE_1 | RCC_CFGR_PPRE_0 - }; -%% elif target.family in ["f0", "g0"] - enum class - ApbPrescaler : uint32_t - { - Div1 = RCC_CFGR_PPRE_DIV1, - Div2 = RCC_CFGR_PPRE_DIV2, - Div4 = RCC_CFGR_PPRE_DIV4, - Div8 = RCC_CFGR_PPRE_DIV8, - Div16 = RCC_CFGR_PPRE_DIV16 - }; -%% else enum class - Apb1Prescaler : uint32_t + AhbPrescaler : uint32_t { -%% if target.family in ["l5", "u5"] - Div1 = 0b000 << RCC_{{cfgr_prescaler}}_{{d2}}PPRE1_Pos, - Div2 = 0b100 << RCC_{{cfgr_prescaler}}_{{d2}}PPRE1_Pos, - Div4 = 0b101 << RCC_{{cfgr_prescaler}}_{{d2}}PPRE1_Pos, - Div8 = 0b110 << RCC_{{cfgr_prescaler}}_{{d2}}PPRE1_Pos, - Div16 = 0b111 << RCC_{{cfgr_prescaler}}_{{d2}}PPRE1_Pos -%% else - Div1 = RCC_{{cfgr2}}_{{d2}}PPRE1_DIV1, - Div2 = RCC_{{cfgr2}}_{{d2}}PPRE1_DIV2, - Div4 = RCC_{{cfgr2}}_{{d2}}PPRE1_DIV4, - Div8 = RCC_{{cfgr2}}_{{d2}}PPRE1_DIV8, - Div16 = RCC_{{cfgr2}}_{{d2}}PPRE1_DIV16 -%% endif +%% for val, div in ahb_prescaler | sort + Div{{div}} = {{val}}, +%% endfor }; - - enum class - Apb2Prescaler : uint32_t + static inline void + setAhbPrescaler(AhbPrescaler prescaler) { -%% if target.family in ["l5", "u5"] - Div1 = 0b000 << RCC_{{cfgr_prescaler}}_{{d2}}PPRE2_Pos, - Div2 = 0b100 << RCC_{{cfgr_prescaler}}_{{d2}}PPRE2_Pos, - Div4 = 0b101 << RCC_{{cfgr_prescaler}}_{{d2}}PPRE2_Pos, - Div8 = 0b110 << RCC_{{cfgr_prescaler}}_{{d2}}PPRE2_Pos, - Div16 = 0b111 << RCC_{{cfgr_prescaler}}_{{d2}}PPRE2_Pos -%% else - Div1 = RCC_{{cfgr2}}_{{d2}}PPRE2_DIV1, - Div2 = RCC_{{cfgr2}}_{{d2}}PPRE2_DIV2, - Div4 = RCC_{{cfgr2}}_{{d2}}PPRE2_DIV4, - Div8 = RCC_{{cfgr2}}_{{d2}}PPRE2_DIV8, - Div16 = RCC_{{cfgr2}}_{{d2}}PPRE2_DIV16 -%% endif - }; -%% endif + LL_RCC_SetAHBPrescaler(uint32_t(prescaler)); + } -%% if target.family == "h7" +%% for bus, vals in apb_prescaler | items | sort enum class - Apb3Prescaler : uint32_t + Apb{{bus}}Prescaler : uint32_t { - Div1 = RCC_{{cfgr_prescaler}}_{{d1}}PPRE_DIV1, - Div2 = RCC_{{cfgr_prescaler}}_{{d1}}PPRE_DIV2, - Div4 = RCC_{{cfgr_prescaler}}_{{d1}}PPRE_DIV4, - Div8 = RCC_{{cfgr_prescaler}}_{{d1}}PPRE_DIV8, - Div16 = RCC_{{cfgr_prescaler}}_{{d1}}PPRE_DIV16 +%% for val, div in vals | sort + Div{{div}} = {{val}}, +%% endfor }; - - enum class - Apb4Prescaler : uint32_t + static inline void + setApb{{bus}}Prescaler(Apb{{bus}}Prescaler prescaler) { - Div1 = RCC_{{cfgr3}}_{{d3}}PPRE_DIV1, - Div2 = RCC_{{cfgr3}}_{{d3}}PPRE_DIV2, - Div4 = RCC_{{cfgr3}}_{{d3}}PPRE_DIV4, - Div8 = RCC_{{cfgr3}}_{{d3}}PPRE_DIV8, - Div16 = RCC_{{cfgr3}}_{{d3}}PPRE_DIV16 - }; + LL_RCC_SetAPB{{bus}}Prescaler(uint32_t(prescaler)); + } +%# +%% endfor +%% for mco, (sources, divs) in mco_source | items | sort enum class - PllInputRange : uint8_t + ClockOutput{{mco}}Source : uint32_t { - MHz1_2 = 0, - MHz2_4 = 1, - MHz4_8 = 2, - MHz8_16 = 3, +%% for val, name in sources | sort + {{name | capitalize}} = {{val}}, +%% endfor }; -%% elif target.family in ["u5"] enum class - Apb3Prescaler : uint32_t + ClockOutput{{mco}}Prescaler : uint32_t { - Div1 = 0b000 << RCC_CFGR3_PPRE3_Pos, - Div2 = 0b100 << RCC_CFGR3_PPRE3_Pos, - Div4 = 0b101 << RCC_CFGR3_PPRE3_Pos, - Div8 = 0b110 << RCC_CFGR3_PPRE3_Pos, - Div16 = 0b111 << RCC_CFGR3_PPRE3_Pos, +%% for val, div in divs | sort + Div{{div}} = {{val}}, +%% endfor }; - - enum class - PllInputRange : uint8_t + static inline void + enableClockOutput{{mco}}(ClockOutput{{mco}}Source src, ClockOutput{{mco}}Prescaler div = ClockOutput{{mco}}Prescaler::Div1) { - MHz4_8 = 0b00, - MHz8_16 = 0b11, - }; -%% endif + LL_RCC_ConfigMCO{{mco if target.family == "c0" else ""}}(uint32_t(src), uint32_t(div)); + } +%# +%% endfor -%% if usbprescaler +%% if hsi_div enum class - UsbPrescaler : uint32_t - { - Div1 = RCC_CFGR_USBPRE, ///< do not divide - Div1_5 = 0, ///< divide by 1.5 - }; -%% endif - -%% if pllsai_p_usb - enum class Clock48Source + HsiSysPrescaler : uint32_t { - PllQ = 0, - %% if target.family == "f4" and target.name in ["69", "79"] - PllSaiP = RCC_DCKCFGR_CK48MSEL - %% else - PllSaiP = RCC_DCKCFGR2_CK48MSEL - %% endif +%% for val, div in hsi_div | sort + Div{{div}} = {{val}}, +%% endfor }; -%% elif target.family in ["g4", "l4", "l5"] - enum class Clock48Source + static inline void + setHsiSysPrescaler(HsiSysPrescaler div) { -%% set sel48="MSEL" if target.family in ["l5"] else "SEL" -%% if target.family == "l4" and target.name[0] in ["7", "8"] - None = 0, +%% if hsi_div4 + if (div == HsiSysPrescaler::Div1) LL_RCC_HSI_DisableDivider(); + else LL_RCC_HSI_EnableDivider(); %% else - Hsi48 = 0, + RCC->CR = (RCC->CR & ~RCC_CR_HSIDIV_Msk) | uint32_t(div); %% endif - PllSai1Q = RCC_{{ccipr1}}_CLK48{{sel48}}_0, - PllQ = RCC_{{ccipr1}}_CLK48{{sel48}}_1, - Msi = RCC_{{ccipr1}}_CLK48{{sel48}}_1 | RCC_{{ccipr1}}_CLK48{{sel48}}_0 - }; -%% elif target.family in ["u5"] - enum class Clock48Source - { - Hsi48 = 0b00 << RCC_CCIPR1_ICLKSEL_Pos, - Pll2Q = 0b01 << RCC_CCIPR1_ICLKSEL_Pos, - Pll1Q = 0b10 << RCC_CCIPR1_ICLKSEL_Pos, - Msik = 0b11 << RCC_CCIPR1_ICLKSEL_Pos, - }; -%% elif hsi48 and target.family in ["l0"] - enum class Clock48Source - { - PllQ = 0, - Hsi48 = RCC_CCIPR_HSI48SEL, - }; + } +%# %% endif -%% if target.family in ["f2", "f4", "f7"] - enum class - ClockOutput1Source : uint32_t - { - InternalClock = 0, - ExternalClock = RCC_CFGR_MCO1_1, - ExternalCrystal = RCC_CFGR_MCO1_1, - Pll = RCC_CFGR_MCO1_1 | RCC_CFGR_MCO1_0, - }; - - %% if not partname.startswith("stm32f412c") +%% if can_source enum class - ClockOutput2Source : uint32_t - { - SystemClock = 0, - ExternalClock = RCC_CFGR_MCO2_1, - ExternalCrystal = RCC_CFGR_MCO2_1, - Pll = RCC_CFGR_MCO2_1 | RCC_CFGR_MCO2_0, - }; - %% endif -%% elif target.family in ["h7"] - enum class - ClockOutput1Source : uint32_t + CanClockSource : uint32_t { - Hsi = 0, - Lse = RCC_CFGR_MCO1_0, - Hse = RCC_CFGR_MCO1_1, - Pll1Q = RCC_CFGR_MCO1_1 | RCC_CFGR_MCO1_0, - Hsi48 = RCC_CFGR_MCO1_2 +%% for val, name in can_source + {{name | capitalize}} = {{val}}, +%% endfor }; - enum class - ClockOutput2Source : uint32_t - { - SystemClock = 0, - Pll2P = RCC_CFGR_MCO2_0, - Hse = RCC_CFGR_MCO2_1, - Pll = RCC_CFGR_MCO2_1 | RCC_CFGR_MCO2_0, - Csi = RCC_CFGR_MCO2_2, - Lsi = RCC_CFGR_MCO2_2 | RCC_CFGR_MCO2_0 - }; -%% elif target.family in ["l0", "l1", "l4", "l5", "g0", "g4", "u5", "c0"] -%% set cfgr_mco="CFGR1" if target.family in ["u5"] else "CFGR" - enum class - ClockOutputSource : uint32_t - { - Disable = 0b0000, - SystemClock = (0b0001 << RCC_{{cfgr_mco}}_MCOSEL_Pos), // SYSCLK - %% if target.family in ["l4", "l5"] - MultiSpeedInternalClock = (0b0010 << RCC_{{cfgr_mco}}_MCOSEL_Pos), // MSI - %% elif target.family in ["u5"] - MultiSpeedInternalClockS = (0b0010 << RCC_{{cfgr_mco}}_MCOSEL_Pos), // MSIS - %% endif - %% if target.family in ["l0", "l1"] - InternalClock = (0b0010 << RCC_{{cfgr_mco}}_MCOSEL_Pos), // HSI16 - MultiSpeedInternalClock = (0b0011 << RCC_{{cfgr_mco}}_MCOSEL_Pos), // MSI - %% else - InternalClock = (0b0011 << RCC_{{cfgr_mco}}_MCOSEL_Pos), // HSI16 - %% endif - ExternalClock = (0b0100 << RCC_{{cfgr_mco}}_MCOSEL_Pos), // HSE - ExternalCrystal = ExternalClock, // HSE - Pll = (0b0101 << RCC_{{cfgr_mco}}_MCOSEL_Pos), // Main PLL - LowSpeedInternalClock = (0b0110 << RCC_{{cfgr_mco}}_MCOSEL_Pos), // LSI - LowSpeedExternalClock = (0b0111 << RCC_{{cfgr_mco}}_MCOSEL_Pos), // LSE - %% if target.family in ["l5"] - Hsi48 = (0b1000 << RCC_{{cfgr_mco}}_MCOSEL_Pos), // HSI48 - %% elif target.family in ["u5"] - Hsi48 = (0b1000 << RCC_{{cfgr_mco}}_MCOSEL_Pos), // HSI48 - MultiSpeedInternalClockK = (0b1001 << RCC_{{cfgr_mco}}_MCOSEL_Pos), // MSIK - %% endif - }; -%% elif target.family in ["f0", "f1", "f3"] - enum class - ClockOutputSource : uint32_t + static inline void + setCanClockSource(CanClockSource source) { - SystemClock = RCC_CFGR_MCO_SYSCLK, - InternalClock = RCC_CFGR_MCO_HSI, - ExternalClock = RCC_CFGR_MCO_HSE, - ExternalCrystal = RCC_CFGR_MCO_HSE, - %% if target.family == "f0" - InternalClockMHz14 = RCC_CFGR_MCO_HSI14, - %% endif - %% if hsi48 - InternalClockMHz48 = RCC_CFGR_MCO_HSI48, - %% endif - %% if target.family == "f1" - Pll = RCC_CFGR_MCO_PLLCLK_DIV2, ///< divided by 2 - %% else - Pll = RCC_CFGR_MCO_PLL, - %% endif - }; + LL_RCC_SetFDCANClockSource(uint32_t(source)); + } +%# %% endif -%% if target.family in ["g4", "l5", "u5", "h7"] +%% if clk48_source enum class - CanClockSource : uint32_t + ClockMHz48Source : uint32_t { - Hse = 0, -%% if target.family == "g4" - PllQ = RCC_{{ccipr1}}_FDCANSEL_0, - Pclk = RCC_{{ccipr1}}_FDCANSEL_1, -%% elif target.family == "l5" - PllQ = RCC_{{ccipr1}}_FDCANSEL_0, - PllSai1P = RCC_{{ccipr1}}_FDCANSEL_1, -%% elif target.family in ["u5"] - Pll1Q = 0b01 << RCC_{{ccipr1}}_FDCANSEL_Pos, - Pll2P = 0b10 << RCC_{{ccipr1}}_FDCANSEL_Pos, -%% elif target.family in ["h7"] - Pll1Q = 0b01 << RCC_{{ccipr1}}_FDCANSEL_Pos, - Pll2Q = 0b10 << RCC_{{ccipr1}}_FDCANSEL_Pos, -%% endif +%% for val, name in clk48_source | sort + {{name | capitalize}} = {{val}}, +%% endfor }; - static void - setCanClockSource(CanClockSource source) + static inline void + setClockMHz48Source(ClockMHz48Source source) { - RCC->{{ccipr1}} = (RCC->{{ccipr1}} & ~RCC_{{ccipr1}}_FDCANSEL_Msk) | uint32_t(source); + LL_RCC_SetUSBClockSource(uint32_t(source)); } +%# +%% endif - /// FDCAN subsystem prescaler common to all FDCAN instances +%% if target.family in ["g4", "l5"] +%# FIXME: Move to CAN driver. What is it even doing here??? enum class CanPrescaler : uint8_t { - Div1 = 0b0000, - Div2 = 0b0001, - Div4 = 0b0010, - Div6 = 0b0011, - Div8 = 0b0100, - Div10 = 0b0101, - Div12 = 0b0110, - Div14 = 0b0111, - Div16 = 0b1000, - Div18 = 0b1001, - Div20 = 0b1010, - Div22 = 0b1011, - Div24 = 0b1100, - Div26 = 0b1101, - Div28 = 0b1110, - Div30 = 0b1111, + Div1 = 0, +%% for value in range(1, 16) + Div{{2*value}} = {{value}}, +%% endfor }; /// Configure CAN subsystem prescaler @@ -541,119 +210,170 @@ public: public: // sources - static bool - enableInternalClock(uint32_t waitCycles = 2048); + static inline bool + enableInternalClock(uint32_t waitCycles = 2048) + { + LL_RCC_HSI_Enable(); + while(not LL_RCC_HSI_IsReady() and --waitCycles) ; + return waitCycles; + } -%% if target.family == "f0" - static bool - enableInternalClockMHz14(uint32_t waitCycles = 2048); +%% if hsi14 + static inline bool + enableInternalClockMHz14(uint32_t waitCycles = 2048) + { + LL_RCC_HSI14_Enable(); + while(not LL_RCC_HSI48_IsReady() and --waitCycles) ; + return waitCycles; + } +%# %% endif %% if hsi48 static bool - enableInternalClockMHz48(uint32_t waitCycles = 2048); + enableInternalClockMHz48(uint32_t waitCycles = 2048) + { + LL_RCC_HSI48_Enable(); + while(not LL_RCC_HSI48_IsReady() and --waitCycles) ; + return waitCycles; + } +%# %% endif -%% if target.family in ["l0", "l1", "l4", "l5", "u5"] +%% if msi_range enum class MsiFrequency : uint32_t { -%% if target.family in ["l0", "l1"] - kHz65 = RCC_ICSCR_MSIRANGE_0, - kHz131 = RCC_ICSCR_MSIRANGE_1, - kHz262 = RCC_ICSCR_MSIRANGE_2, - kHz524 = RCC_ICSCR_MSIRANGE_3, - MHz1 = RCC_ICSCR_MSIRANGE_4, - MHz2 = RCC_ICSCR_MSIRANGE_5, - MHz4 = RCC_ICSCR_MSIRANGE_6, -%% elif target.family in ["l4"] - kHz100 = RCC_CR_MSIRANGE_0, - kHz200 = RCC_CR_MSIRANGE_1, - kHz400 = RCC_CR_MSIRANGE_2, - kHz800 = RCC_CR_MSIRANGE_3, - MHz1 = RCC_CR_MSIRANGE_4, - MHz2 = RCC_CR_MSIRANGE_5, - MHz4 = RCC_CR_MSIRANGE_6, - MHz8 = RCC_CR_MSIRANGE_7, - MHz16 = RCC_CR_MSIRANGE_8, - MHz24 = RCC_CR_MSIRANGE_9, - MHz32 = RCC_CR_MSIRANGE_10, - MHz48 = RCC_CR_MSIRANGE_11, -%% elif target.family in ["l5"] - kHz100 = 0b0000 << RCC_CR_MSIRANGE_Pos, - kHz200 = 0b0001 << RCC_CR_MSIRANGE_Pos, - kHz400 = 0b0010 << RCC_CR_MSIRANGE_Pos, - kHz800 = 0b0011 << RCC_CR_MSIRANGE_Pos, - MHz1 = 0b0100 << RCC_CR_MSIRANGE_Pos, - MHz2 = 0b0101 << RCC_CR_MSIRANGE_Pos, - MHz4 = 0b0110 << RCC_CR_MSIRANGE_Pos, - MHz8 = 0b0111 << RCC_CR_MSIRANGE_Pos, - MHz16 = 0b1000 << RCC_CR_MSIRANGE_Pos, - MHz24 = 0b1001 << RCC_CR_MSIRANGE_Pos, - MHz32 = 0b1010 << RCC_CR_MSIRANGE_Pos, - MHz48 = 0b1011 << RCC_CR_MSIRANGE_Pos, -%% elif target.family in ["u5"] - MHz48 = 0b0000, - MHz24 = 0b0001, - MHz16 = 0b0010, - MHz12 = 0b0011, - MHz4 = 0b0100, - MHz2 = 0b0101, - kHz1330 = 0b0110, - kHz1000 = 0b0111, - kHz3072 = 0b1000, - kHz1536 = 0b1001, - kHz1024 = 0b1010, - kHz768 = 0b1011, - kHz400 = 0b1100, - kHz200 = 0b1101, - kHz133 = 0b1110, - kHz100 = 0b1111, -%% endif +%% for name in msi_range[1] + {{name}} = {{msi_range[0]}}{{loop.index0}}, +%% endfor }; +%# +%% endif -%% if target.family in ["u5"] - static bool - enableMultiSpeedInternalClockS(MsiFrequency msi_frequency = MsiFrequency::MHz4, uint32_t waitCycles = 2048); +%% for msi in msi_clocks static bool - enableMultiSpeedInternalClockK(MsiFrequency msi_frequency = MsiFrequency::MHz4, uint32_t waitCycles = 2048); -%% else - static bool - enableMultiSpeedInternalClock(MsiFrequency msi_frequency = MsiFrequency::MHz4, uint32_t waitCycles = 2048); + enableMultiSpeedInternalClock{{msi}}(MsiFrequency msi_frequency = MsiFrequency::MHz4, uint32_t waitCycles = 2048) + { + LL_RCC_MSI{{msi}}_SetRange(uint32_t(msi_frequency){% if msi == "S" %} << 4{% endif %}); +%% if msi_range_selection + LL_RCC_MSI_EnableRangeSelection(); %% endif + LL_RCC_MSI{{msi}}_Enable(); + while (not LL_RCC_MSI{{msi}}_IsReady() and --waitCycles) ; + return waitCycles; + } +%# +%% endfor + static inline bool + enableExternalClock(uint32_t waitCycles = 2048) + { + LL_RCC_HSE_EnableBypass(); + LL_RCC_HSE_Enable(); + while(not LL_RCC_HSE_IsReady() and --waitCycles) ; + return waitCycles; + } + + static inline bool + enableExternalCrystal(uint32_t waitCycles = 2048) + { + LL_RCC_HSE_DisableBypass(); + LL_RCC_HSE_Enable(); + while(not LL_RCC_HSE_IsReady() and --waitCycles) ; + return waitCycles; + } + + static inline bool + enableLowSpeedInternalClock(uint32_t waitCycles = 2048) + { + LL_RCC_LSI_Enable(); + while(not LL_RCC_LSI_IsReady() and --waitCycles) ; + return waitCycles; + } + + static inline bool + enableLowSpeedExternalClock(uint32_t waitCycles = 2048) + { + LL_RCC_LSE_EnableBypass(); + LL_RCC_LSE_Enable(); + while(not LL_RCC_LSE_IsReady() and --waitCycles) ; + return waitCycles; + } + +%% if lse_drive + enum class + LseDrive : uint32_t + { +%% for val, name in lse_drive | sort + {{name | capitalize }} = {{val}}, +%% endfor + }; %% endif - static bool - enableExternalClock(uint32_t waitCycles = 2048); + static inline bool + enableLowSpeedExternalCrystal({% if lse_drive %}LseDrive drive = LseDrive::Low, {% endif %}uint32_t waitCycles = 2048) + { + LL_RCC_LSE_DisableBypass(); +%% if lse_drive + LL_RCC_LSE_SetDriveCapability(uint32_t(drive)); +%% endif + LL_RCC_LSE_Enable(); + while(not LL_RCC_LSE_IsReady() and --waitCycles) ; + return waitCycles; + } - static bool - enableExternalCrystal(uint32_t waitCycles = 2048); +public: // PLLs + enum class + PllSource : uint32_t + { +%% for val, name in pll_source | sort + {{name | capitalize }} = {{val}}, +%% endfor + }; - static bool - enableLowSpeedInternalClock(uint32_t waitCycles = 2048); +%% if pll_mul + enum class + PllMultiplier : uint32_t + { +%% for val, mul in pll_mul | sort + Mul{{mul}} = {{val}}, +%% endfor + }; +%# +%% endif - static bool - enableLowSpeedExternalClock(uint32_t waitCycles = 2048); +%% if pll_input_range + enum class + PllInputRange : uint8_t + { +%% for val, name in pll_input_range | sort + MHz{{name}} = {{val}}, +%% endfor + }; +%# +%% endif - static bool - enableLowSpeedExternalCrystal(uint32_t waitCycles = 2048); +%% if usbprescaler + enum class + UsbPrescaler : uint32_t + { + Div1 = RCC_CFGR_USBPRE, ///< do not divide + Div1_5 = 0, ///< divide by 1.5 + }; +%# +%% endif -%% if target.family in ["u5"] +%% if epod_booster enum class EpodBoosterPrescaler : uint32_t { - Div1 = 0b0000 << RCC_PLL1CFGR_PLL1MBOOST_Pos, - Div2 = 0b0001 << RCC_PLL1CFGR_PLL1MBOOST_Pos, - Div4 = 0b0010 << RCC_PLL1CFGR_PLL1MBOOST_Pos, - Div6 = 0b0011 << RCC_PLL1CFGR_PLL1MBOOST_Pos, - Div8 = 0b0100 << RCC_PLL1CFGR_PLL1MBOOST_Pos, - Div10 = 0b0101 << RCC_PLL1CFGR_PLL1MBOOST_Pos, - Div12 = 0b0110 << RCC_PLL1CFGR_PLL1MBOOST_Pos, - Div14 = 0b0111 << RCC_PLL1CFGR_PLL1MBOOST_Pos, - Div16 = 0b1000 << RCC_PLL1CFGR_PLL1MBOOST_Pos, +%% for val, name in epod_booster | sort + {{name | capitalize }} = {{val}}, +%% endfor }; %% endif + %% if target.family != "c0" struct PllFactors { @@ -772,61 +492,7 @@ public: disablePllSai(uint32_t waitCycles = 2048); %% endif -%% if target.family == "l0" - static inline bool - isHsiPredivider4Active() - { - return (RCC->CR & RCC_CR_HSIDIVF); - } - - static bool - setHsiPredivider4Enabled(bool divideBy4, uint32_t waitCycles = 2048); -%% endif - // sinks - static bool - enableSystemClock(SystemClockSource src, uint32_t waitCycles = 2048); - - static inline bool - enableRealTimeClock(RealTimeClockSource src) - { - RCC->{{bdcr}} = (RCC->{{bdcr}} & ~RCC_{{bdcr}}_RTCSEL) | RCC_{{bdcr}}_RTCEN | uint32_t(src); - return true; - } - - static inline bool - enableWatchdogClock(WatchdogClockSource /*src*/) - { return true; } - -%% if pllsai_p_usb - static inline void - setClock48Source(Clock48Source source) - { - %% if target.family == "f4" and target.name in ["69", "79"] - RCC->DCKCFGR = (RCC->DCKCFGR & ~RCC_DCKCFGR_CK48MSEL) | uint32_t(source); - %% else - RCC->DCKCFGR2 = (RCC->DCKCFGR2 & ~RCC_DCKCFGR2_CK48MSEL) | uint32_t(source); - %% endif - } -%% elif target.family in ["g4", "l4", "l5"] - static inline void - setClock48Source(Clock48Source source) - { - RCC->{{ccipr1}} = (RCC->{{ccipr1}} & ~RCC_{{ccipr1}}_CLK48{{sel48}}_Msk) | uint32_t(source); - } -%% elif target.family in ["u5"] - static inline void - setClock48Source(Clock48Source source) - { - RCC->CCIPR1 = (RCC->CCIPR1 & ~RCC_CCIPR1_ICLKSEL_Msk) | uint32_t(source); - } -%% elif hsi48 and target.family in ["l0"] - static inline void - setClock48Source(Clock48Source source) - { - RCC->CCIPR = (RCC->CCIPR & ~RCC_CCIPR_HSI48SEL_Msk) | uint32_t(source); - } -%% endif %% if target.family == "h7" enum class @@ -869,137 +535,7 @@ public: } %% endif -%% if target.family in ["f2", "f4", "f7"] - static inline bool - enableClockOutput1(ClockOutput1Source src, uint8_t div) - { - uint32_t tmp = RCC->CFGR & ~(RCC_CFGR_MCO1 | RCC_CFGR_MCO1PRE); - if (div > 1) tmp |= (div + 2) << 24; - RCC->CFGR = tmp | uint32_t(src); - return true; - } - - %% if not partname.startswith("stm32f412c") - static inline bool - enableClockOutput2(ClockOutput2Source src, uint8_t div) - { - uint32_t tmp = RCC->CFGR & ~(RCC_CFGR_MCO2 | RCC_CFGR_MCO2PRE); - if (div > 1) tmp |= (div + 2) << 27; - RCC->CFGR = tmp | uint32_t(src); - return true; - } - %% endif -%% elif target.family in ["h7"] - static inline bool - enableClockOutput1(ClockOutput1Source src, uint8_t div) - { - uint32_t tmp = RCC->CFGR & ~(RCC_CFGR_MCO1 | RCC_CFGR_MCO1PRE); - if (div > 1) tmp |= (div << 18); - RCC->CFGR = tmp | uint32_t(src); - return true; - } - - static inline bool - enableClockOutput2(ClockOutput2Source src, uint8_t div) - { - uint32_t tmp = RCC->CFGR & ~(RCC_CFGR_MCO2 | RCC_CFGR_MCO2PRE); - if (div > 1) tmp |= (div << 25); - RCC->CFGR = tmp | uint32_t(src); - return true; - } -%% elif target.family in ["l0", "l1", "l4", "l5", "g0", "g4", "u5", "c0"] - enum class - ClockOutputPrescaler : uint32_t - { - Div1 = 0, - Div2 = (1 << RCC_{{cfgr_mco}}_MCOPRE_Pos), - Div4 = (2 << RCC_{{cfgr_mco}}_MCOPRE_Pos), - Div8 = (3 << RCC_{{cfgr_mco}}_MCOPRE_Pos), - Div16 = (4 << RCC_{{cfgr_mco}}_MCOPRE_Pos), -%% if target.family in ["c0", "g0"] - Div32 = (5 << RCC_{{cfgr_mco}}_MCOPRE_Pos), - Div64 = (6 << RCC_{{cfgr_mco}}_MCOPRE_Pos), - Div128 = (7 << RCC_{{cfgr_mco}}_MCOPRE_Pos), -%% endif - }; - - static inline bool - enableClockOutput(ClockOutputSource src, ClockOutputPrescaler div = ClockOutputPrescaler::Div1) - { - RCC->{{cfgr_mco}} = (RCC->{{cfgr_mco}} & ~(RCC_{{cfgr_mco}}_MCOPRE)) | uint32_t(src) | uint32_t(div); - return true; - } -%% else - static inline bool - enableClockOutput(ClockOutputSource src) - { - RCC->CFGR = (RCC->CFGR & ~(RCC_CFGR_MCO)) | uint32_t(src); - return true; - } -%% endif - public: -%% if target.family in ["c0"] - static inline bool - setHsiSysDivider(HsiSysDivider hsisysdivider) - { - RCC->CR = (RCC->CR & ~RCC_CR_HSIDIV_Msk) | uint32_t(hsisysdivider); - return true; - } - -%% endif - static inline bool - setAhbPrescaler(AhbPrescaler prescaler) - { - RCC->{{cfgr_prescaler}} = (RCC->{{cfgr_prescaler}} & ~RCC_{{cfgr_prescaler}}_HPRE) | uint32_t(prescaler); - return true; - } - -%% if target.family in ["c0", "f0", "g0"] - static inline bool - setApbPrescaler(ApbPrescaler prescaler) - { - RCC->CFGR = (RCC->CFGR & ~RCC_CFGR_PPRE) | uint32_t(prescaler); - return true; - } -%% else - static inline bool - setApb1Prescaler(Apb1Prescaler prescaler) - { - RCC->{{cfgr2}} = (RCC->{{cfgr2}} & ~RCC_{{cfgr2}}_{{d2}}PPRE1) | uint32_t(prescaler); - return true; - } - - static inline bool - setApb2Prescaler(Apb2Prescaler prescaler) - { - RCC->{{cfgr2}} = (RCC->{{cfgr2}} & ~RCC_{{cfgr2}}_{{d2}}PPRE2) | uint32_t(prescaler); - return true; - } -%% endif - -%% if target.family == "h7" - static inline bool - setApb3Prescaler(Apb3Prescaler prescaler) - { - RCC->{{cfgr_prescaler}} = (RCC->{{cfgr_prescaler}} & ~RCC_{{cfgr_prescaler}}_{{d1}}PPRE) | uint32_t(prescaler); - return true; - } - static inline bool - setApb4Prescaler(Apb4Prescaler prescaler) - { - RCC->{{cfgr3}} = (RCC->{{cfgr3}} & ~RCC_{{cfgr3}}_{{d3}}PPRE) | uint32_t(prescaler); - return true; - } -%% endif -%% if target.family in ["u5"] - static inline bool - setApb3Prescaler(Apb3Prescaler prescaler) - { - RCC->CFGR3 = (RCC->CFGR3 & ~RCC_CFGR3_PPRE3) | uint32_t(prescaler); - return true; - } -%% endif %% if overdrive static bool @@ -1133,7 +669,7 @@ private: computeFlashLatency(uint32_t Core_Hz, uint16_t Core_mV); }; -} // namespace modm::platform +} // namespace modm::platform #include "rcc_impl.hpp" diff --git a/src/modm/platform/clock/stm32/rcc_impl.hpp.in b/src/modm/platform/clock/stm32/rcc_impl.hpp.in index e1ce1aff37..53c38d7730 100644 --- a/src/modm/platform/clock/stm32/rcc_impl.hpp.in +++ b/src/modm/platform/clock/stm32/rcc_impl.hpp.in @@ -15,7 +15,7 @@ namespace modm::platform constexpr Rcc::flash_latency Rcc::computeFlashLatency(uint32_t Core_Hz, uint16_t Core_mV) { - %% for mV, table_Hz in table.items() | sort + %% for mV, table_Hz in flash_latencies.items() | sort constexpr uint32_t flash_latency_{{ mV }}[] = { %% for hz in table_Hz @@ -24,11 +24,11 @@ Rcc::computeFlashLatency(uint32_t Core_Hz, uint16_t Core_mV) }; %% endfor - const uint32_t *lut(flash_latency_{{ (table|sort)[0] }}); - uint8_t lut_size(sizeof(flash_latency_{{ (table|sort)[0] }}) / sizeof(uint32_t)); - %% if table|length > 1 + const uint32_t *lut(flash_latency_{{ (flash_latencies|sort)[0] }}); + uint8_t lut_size(sizeof(flash_latency_{{ (flash_latencies|sort)[0] }}) / sizeof(uint32_t)); + %% if flash_latencies|length >= 2 // find the right table for the voltage - %% for mV in (table|sort)[1:]|reverse + %% for mV in (flash_latencies|sort)[1:]|reverse {% if not loop.first %}else {% endif %}if ({{ mV }} <= Core_mV) { lut = flash_latency_{{ mV }}; lut_size = sizeof(flash_latency_{{ mV }}) / sizeof(uint32_t); diff --git a/src/modm/platform/core/stm32/module.lb b/src/modm/platform/core/stm32/module.lb index de7c732d45..9f53cfc2ea 100644 --- a/src/modm/platform/core/stm32/module.lb +++ b/src/modm/platform/core/stm32/module.lb @@ -39,7 +39,7 @@ def prepare(module, options): default="sram") ) - module.depends(":platform:cortex-m") + module.depends(":platform:cortex-m", ":cmsis:device") return True @@ -47,7 +47,8 @@ def build(env): target = env[":target"].identifier env.substitutions = { "target": target, - "vector_table_location": env.get(":platform:core:vector_table_location", "rom") + "vector_table_location": env.get(":platform:core:vector_table_location", "rom"), + "regs": env.query(":cmsis:device:registers"), } env.outbasepath = "modm/src/modm/platform/core" # startup helper code diff --git a/src/modm/platform/core/stm32/startup_platform.c.in b/src/modm/platform/core/stm32/startup_platform.c.in index 85085967d8..08fa527005 100644 --- a/src/modm/platform/core/stm32/startup_platform.c.in +++ b/src/modm/platform/core/stm32/startup_platform.c.in @@ -1,7 +1,7 @@ /* * Copyright (c) 2016, Sascha Schade * Copyright (c) 2016-2017, Fabian Greif - * Copyright (c) 2016-2017, 2019, 2024, Niklas Hauser + * Copyright (c) 2016-2017, 2019, 2024, 2025, Niklas Hauser * Copyright (c) 2021, Raphael Lehmann * Copyright (c) 2021, Christopher Durand * @@ -28,75 +28,30 @@ void __modm_initialize_platform(void) { +%% if regs.set("RCC", "APB\d?ENR\d?", "SYSCFG.*?EN|AFIOEN") // Enable SYSCFG -%% if target.family in ["c0", "g0"] - RCC->APBENR2 |= RCC_APBENR2_SYSCFGEN; __DSB(); -%% elif target.family == "f0" - RCC->APB2ENR |= RCC_APB2ENR_SYSCFGCOMPEN; __DSB(); -%% elif target.family == "f1" - RCC->APB2ENR |= RCC_APB2ENR_AFIOEN; __DSB(); -%% elif target.family == "h7" - RCC->APB4ENR |= RCC_APB4ENR_SYSCFGEN; __DSB(); -%% elif target.family == "u5" - RCC->APB3ENR |= RCC_APB3ENR_SYSCFGEN; __DSB(); -%% else - RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN; __DSB(); + {{regs.result}} %% endif - +%% if regs.set("RCC", "A[HP]B\d?ENR\d?", "(?:PWR|BKP)EN") // Enable power to backup domain -%% if target.family == "f1" - RCC->APB1ENR |= RCC_APB1ENR_PWREN | RCC_APB1ENR_BKPEN; __DSB(); -%% elif target.family in ["f0", "f2", "f3", "f4", "f7", "l0", "l1"] - RCC->APB1ENR |= RCC_APB1ENR_PWREN; __DSB(); -%% elif target.family in ["c0", "g0", "u0"] - RCC->APBENR1 |= RCC_APBENR1_PWREN; __DSB(); -%% elif target.family in ["g4", "l4", "l5"] - RCC->APB1ENR1 |= RCC_APB1ENR1_PWREN; __DSB(); -%% elif target.family == "u5" - RCC->AHB3ENR |= RCC_AHB3ENR_PWREN; __DSB(); + {{regs.result}} __DSB(); %% endif - -%% if target.family in ["f0", "f1", "f2", "f3", "f4", "l0", "l1"] - PWR->CR |= PWR_CR_DBP; -%% elif target.family in ["f7", "g0", "g4", "h7", "l4", "l5", "u0", "wb", "wl"] - PWR->CR1 |= PWR_CR1_DBP; -%% elif target.family == "h5" - PWR->DBPCR |= PWR_DBPCR_DBP; -%% elif target.family in ["u5", "wba"] - PWR->DBPR |= PWR_DBPR_DBP; +%% if regs.set("PWR", ".*?", "DBP") + // Enable access to backup domain + {{regs.result}} %% endif - -%% if target.family == "f4" - // Only the more powerful F4 targets have CCM or Backup SRAM -#ifdef RCC_AHB1ENR_CCMDATARAMEN - // Enable Core Coupled Memory (CCM) and backup SRAM (BKPSRAM) - RCC->AHB1ENR |= RCC_AHB1ENR_CCMDATARAMEN | RCC_AHB1ENR_BKPSRAMEN; -#endif -%% elif target.family == "f7" +%% if regs.set("RCC", "A[HP]B\d?ENR\d?", "(?:BKPS?|DTCM|CCMDATA)RAM\d?EN") + // Enable internal memories + {{regs.result}} +%% endif +%% if regs.set("PWR|RCC", "CR2|SVMCR", ".*?SV") + // Enable VDDIO voltages + {{regs.result}} +%% endif +%% if regs.search("RCC_DCKCFGR2_.*?") // Reset from DFU settings to reset values. RCC->DCKCFGR2 = 0; - // Enable Data Tighly Coupled Memory (DTCM) and backup SRAM (BKPSRAM) - RCC->AHB1ENR |= RCC_AHB1ENR_DTCMRAMEN | RCC_AHB1ENR_BKPSRAMEN; -%% elif target.family == "h7" - // Enable all SRAMs - %% if target.name[0].isnumeric() - RCC->AHB2ENR |= RCC_AHB2ENR_SRAM1EN | RCC_AHB2ENR_SRAM2EN; - %% else - RCC->AHB2ENR |= RCC_AHB2ENR_AHBSRAM1EN | RCC_AHB2ENR_AHBSRAM2EN; - %% endif - RCC->AHB4ENR |= RCC_AHB4ENR_BKPRAMEN; -%% elif target.family in ["g4", "l4", "l5"] -#ifdef PWR_CR2_IOSV - // Enable VDDIO2 - PWR->CR2 |= PWR_CR2_IOSV; -#endif -%% elif target.family == "u5" - // Enable power for VDDIO2 and USB - PWR->SVMCR |= PWR_SVMCR_ASV | PWR_SVMCR_IO2SV | PWR_SVMCR_USV; - // Enable Backup SRAM (BKPSRAM) - RCC->AHB1ENR |= RCC_AHB1ENR_BKPSRAMEN; %% endif - %% if vector_table_location == "ram" __DSB(); // Remap SRAM to 0x0 for vector table relocation without VTOR register