From f66e1e5638ddc4cb6aafa7fd33ff476a11e613fb Mon Sep 17 00:00:00 2001 From: Niklas Hauser Date: Mon, 6 Jan 2025 21:10:55 +0100 Subject: [PATCH] [stm32] Use register map query for RCC module --- src/modm/platform/clock/stm32/module.lb | 195 ++--- src/modm/platform/clock/stm32/rcc.cpp.in | 156 ---- src/modm/platform/clock/stm32/rcc.hpp.in | 928 ++++++----------------- 3 files changed, 340 insertions(+), 939 deletions(-) diff --git a/src/modm/platform/clock/stm32/module.lb b/src/modm/platform/clock/stm32/module.lb index ba31c176a0..591409b72b 100644 --- a/src/modm/platform/clock/stm32/module.lb +++ b/src/modm/platform/clock/stm32/module.lb @@ -22,9 +22,8 @@ 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): @@ -32,113 +31,119 @@ def build(env): driver = device.get_driver("rcc") regs = env.query(":cmsis:device:registers") - 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"] + p = {"regs": regs} + p["target"] = target = device.identifier + p["partname"] = device.partname + p["core"] = core = device.get_driver("core")["type"] + + # These definitions must exist on all devices + p["boot_frequency"] = "HSI_VALUE" + if target.family in ["c0"]: + p["boot_frequency"] = "12'000'000" + elif target.family in ["l0", "l1"]: + p["boot_frequency"] = "2'097'000" + elif target.family in ["l5"]: + p["boot_frequency"] = "4'000'000" + + # We're using two regex here, since some headers have both PLLSOURCE *and* PLL1SOURCE + p["pll_source"] = regs.findall(r"(LL_RCC_PLLSOURCE_(.+?))") or regs.findall(r"(LL_RCC_PLL1SOURCE_(.+?))") + assert p["pll_source"], "Cannot find PllSource enums" + + p["sys_source"] = regs.findall(r"(LL_RCC_SYS_CLKSOURCE_(.{1,9}))") + assert p["sys_source"], "Cannot find SystemClockSource enums" + p["cfgr_sws_pos"] = regs.search("RCC_.*?_SWS_Pos") + + p["rtc_source"] = regs.findall(r"(LL_RCC_RTC_CLKSOURCE_(.+?))") + assert p["rtc_source"], "Cannot find RealTimeClockSource enums" + + p["ahb_prescaler"] = regs.findall(r"(LL_RCC_SYSCLK_DIV_(\d+?))") + assert p["ahb_prescaler"], "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" + p["apb_prescaler"] = apb_prescaler + + 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" + p["mco_source"] = mco_source + + # These may not exist on all devices + p["can_source"] = regs.findall(r"(LL_RCC_FDCAN_CLKSOURCE_(.+?))") + p["hsi_div"] = regs.findall(r"(LL_RCC_HSI_DIV_?(\d+))") + p["pll_mul"] = regs.findall(r"(LL_RCC_PLL_MUL_(\d+_?\d?))") + p["pll_input_range"] = regs.findall(r"(LL_RCC_PLLINPUTRANGE_(\d+_\d+))") + p["usbprescaler"] = regs.search(r"RCC_CFGR_USBPRE") + p["lse_drive"] = regs.findall(r"(LL_RCC_LSEDRIVE_(.+?))") + p["hsi48"] = regs.search(r"RCC_.*?_HSI48ON") + p["hsi14"] = regs.search(r"RCC_.*?_HSI14ON") + p["hsi_div"] = regs.search(r"RCC_.*?_HSIDIV") + + # 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+") + p["msi_clocks"] = (["K", "S"] if "K" in msi_range[0] else [""]) if msi_range else [] + 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")) + p["msi_range"] = msi_range or ("", []) + + + if regs.search(r"RCC_.+?_(?:CL?K48M?SEL|ICLKSEL)"): + p["clk48_source"] = regs.findall(r"(LL_RCC_(?:USB|CL?K48)_CLKSOURCE_(.+?))") else: - properties["hsi_frequency"] = 16_000_000 - properties["lsi_frequency"] = 32_000 - properties["boot_frequency"] = properties["hsi_frequency"] + p["clk48_source"] = [] # 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"]) + p["pllprediv"] = \ + (target.family in ["f0", "f3"] or (target.family == "f1" and target.name in ["00", "05", "07"])) + p["pllprediv2"] = False # FIXME: not sure what value this should have + p["pll_hse_prediv2"] = target.family == "f1" and target.name in ["01", "02", "03"] + p["pll_p"] = ((target.family == "l4" and target.name not in ["12", "22"]) or target.family == "g4") + p["overdrive"] = (target.family == "f7") or \ + ((target.family == "f4") and target.name in ["27", "29", "37", "39", "46", "69", "79"]) + p["vos0_overdrive"] = (target.family == "h7") and \ + target.name in ["42", "43", "45", "47", "50", "53", "55", "57"] + p["has_r1mode"] = (target.family == "g4") or \ + (target.family == "l4" and target.name[0] in ["p", "q", "r", "s"]) + p["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" + p["ccipr1"] = "CDCCIP1R" 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" + p["ccipr1"] = "D2CCIP1R" elif target.family in ["l5", "u5"]: - properties["ccipr1"] = "CCIPR1" + p["ccipr1"] = "CCIPR1" else: - properties["ccipr1"] = "CCIPR" + p["ccipr1"] = "CCIPR" - properties["d1"] = ("CD" if target.name in ["a3", "b0", "b3"] else "D1") \ - if target.family == "h7" else "" - properties["d2"] = ("CD" if target.name in ["a3", "b0", "b3"] else "D2") \ + p["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")) + p["d3"] = ("SRD" if target.name in ["a0", "a3", "b0", "b3"] else "D3") + p["pll_ids"] = ["1", "2", "3"] if target.family in ["h7", "u5"] else [] if target.family in ["c0"] else [""] + p["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 + p["table"] = flash_latencies + env.substitutions = p env.outbasepath = "modm/src/modm/platform/clock" env.template("rcc.cpp.in") @@ -146,7 +151,7 @@ def build(env): all_peripherals = env.query(":cmsis:device:peripherals") rcc_map = defaultdict(dict) - for (reg, per, typ) in regs.findall(r"RCC_([A-Z0-9]*?)_([A-Z0-9]+?)(EN|RST)"): + 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 = {} 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..46a62a248c 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,612 +34,331 @@ 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 }; + static inline void + enableWatchdogClock(WatchdogClockSource src = WatchdogClockSource::Lsi) + { + (void) src; + } enum class AhbPrescaler : uint32_t { -%% 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 +%% for val, div in ahb_prescaler | sort + Div{{div}} = {{val}}, +%% endfor }; + static inline void + setAhbPrescaler(AhbPrescaler prescaler) + { + LL_RCC_SetAHBPrescaler(uint32_t(prescaler)); + } -%% if target.family in ["c0"] +%% for bus, vals in apb_prescaler | items | sort enum class - ApbPrescaler : uint32_t + Apb{{bus}}Prescaler : 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 +%% for val, div in vals | sort + Div{{div}} = {{val}}, +%% endfor }; -%% elif target.family in ["f0", "g0"] + static inline void + setApb{{bus}}Prescaler(Apb{{bus}}Prescaler prescaler) + { + LL_RCC_SetAPB{{bus}}Prescaler(uint32_t(prescaler)); + } +%# +%% endfor + +%% for mco, (sources, divs) in mco_source | items | sort enum class - ApbPrescaler : uint32_t + ClockOutput{{mco}}Source : 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 +%% for val, name in sources | sort + {{name | capitalize}} = {{val}}, +%% endfor }; -%% else enum class - Apb1Prescaler : uint32_t + ClockOutput{{mco}}Prescaler : 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 divs | sort + Div{{div}} = {{val}}, +%% endfor }; + static inline void + enableClockOutput{{mco}}(ClockOutput{{mco}}Source src, ClockOutput{{mco}}Prescaler div = ClockOutput{{mco}}Prescaler::Div1) + { + LL_RCC_ConfigMCO{{mco if target.family == "c0" else ""}}(uint32_t(src), uint32_t(div)); + } +%# +%% endfor +%% if hsi_div enum class - Apb2Prescaler : uint32_t + HsiSysDivider : uint32_t { -%% 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 +%% for val, div in hsi_div | sort + Div{{div}} = {{val}}, +%% endfor }; + static inline void + setHsiSysDivider(HsiSysDivider div) + { + RCC->CR = (RCC->CR & ~RCC_CR_HSIDIV_Msk) | uint32_t(div); + } +%# %% endif -%% if target.family == "h7" +%% if can_source enum class - Apb3Prescaler : uint32_t + CanClockSource : 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, name in can_source + {{name | capitalize}} = {{val}}, +%% endfor }; - enum class - Apb4Prescaler : uint32_t + static inline void + setCanClockSource(CanClockSource source) { - 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_SetFDCANClockSource(uint32_t(source)); + } +%# +%% endif +%% if clk48_source enum class - PllInputRange : uint8_t + ClockMHz48Source : uint32_t { - MHz1_2 = 0, - MHz2_4 = 1, - MHz4_8 = 2, - MHz8_16 = 3, - }; -%% elif target.family in ["u5"] - enum class - Apb3Prescaler : 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, name in clk48_source | sort + {{name | capitalize}} = {{val}}, +%% endfor }; - enum class - PllInputRange : uint8_t + static inline void + setClockMHz48Source(ClockMHz48Source source) { - MHz4_8 = 0b00, - MHz8_16 = 0b11, - }; + LL_RCC_SetUSBClockSource(uint32_t(source)); + } +%# %% endif -%% if usbprescaler +%% if target.family in ["g4", "l5"] +%# FIXME: Move to CAN driver. What is it even doing here??? enum class - UsbPrescaler : uint32_t + CanPrescaler : uint8_t { - Div1 = RCC_CFGR_USBPRE, ///< do not divide - Div1_5 = 0, ///< divide by 1.5 + Div1 = 0, +%% for value in range(1, 16) + Div{{2*value}} = {{value}}, +%% endfor }; + + /// Configure CAN subsystem prescaler + /// \warning Configure the prescaler before enabling the CAN peripherals + /// \returns true if setting the prescaler was successful + static bool + setCanPrescaler(CanPrescaler prescaler); %% endif -%% if pllsai_p_usb - enum class Clock48Source +public: + // sources + static inline bool + enableInternalClock(uint32_t waitCycles = 2048) { - PllQ = 0, - %% if target.family == "f4" and target.name in ["69", "79"] - PllSaiP = RCC_DCKCFGR_CK48MSEL - %% else - PllSaiP = RCC_DCKCFGR2_CK48MSEL - %% endif - }; -%% elif target.family in ["g4", "l4", "l5"] - enum class Clock48Source + LL_RCC_HSI_Enable(); + while(not LL_RCC_HSI_IsReady() and --waitCycles) ; + return waitCycles; + } + +%% if hsi14 + static inline bool + enableInternalClockMHz14(uint32_t waitCycles = 2048) { -%% set sel48="MSEL" if target.family in ["l5"] else "SEL" -%% if target.family == "l4" and target.name[0] in ["7", "8"] - None = 0, -%% else - Hsi48 = 0, + LL_RCC_HSI14_Enable(); + while(not LL_RCC_HSI48_IsReady() and --waitCycles) ; + return waitCycles; + } +%# %% 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 + +%% if hsi48 + static bool + enableInternalClockMHz48(uint32_t waitCycles = 2048) { - PllQ = 0, - Hsi48 = RCC_CCIPR_HSI48SEL, - }; + LL_RCC_HSI48_Enable(); + while(not LL_RCC_HSI48_IsReady() and --waitCycles) ; + return waitCycles; + } +%# %% endif -%% if target.family in ["f2", "f4", "f7"] +%% if msi_range enum class - ClockOutput1Source : uint32_t + MsiFrequency : uint32_t { - InternalClock = 0, - ExternalClock = RCC_CFGR_MCO1_1, - ExternalCrystal = RCC_CFGR_MCO1_1, - Pll = RCC_CFGR_MCO1_1 | RCC_CFGR_MCO1_0, +%% for name in msi_range[1] + {{name}} = {{msi_range[0]}}{{loop.index0}}, +%% endfor }; +%# +%% endif - %% if not partname.startswith("stm32f412c") - enum class - ClockOutput2Source : uint32_t +%% for msi in msi_clocks + static bool + enableMultiSpeedInternalClock{{msi}}(MsiFrequency msi_frequency = MsiFrequency::MHz4, uint32_t waitCycles = 2048) { - 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 + LL_RCC_MSI{{msi}}_SetRange(uint32_t(msi_frequency){% if msi == "S" %} << 4{% endif %}); +%% if target.family not in ["l0", "l1", "wb"] + 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) { - 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 - }; + LL_RCC_HSE_EnableBypass(); + LL_RCC_HSE_Enable(); + while(not LL_RCC_HSE_IsReady() and --waitCycles) ; + return waitCycles; + } - enum class - ClockOutput2Source : uint32_t + static inline bool + enableExternalCrystal(uint32_t waitCycles = 2048) { - 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 + 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) { - 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 + LL_RCC_LSI_Enable(); + while(not LL_RCC_LSI_IsReady() and --waitCycles) ; + return waitCycles; + } + + static inline bool + enableLowSpeedExternalClock(uint32_t waitCycles = 2048) { - 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 - }; -%% endif + LL_RCC_LSE_EnableBypass(); + LL_RCC_LSE_Enable(); + while(not LL_RCC_LSE_IsReady() and --waitCycles) ; + return waitCycles; + } -%% if target.family in ["g4", "l5", "u5", "h7"] +%% if lse_drive enum class - CanClockSource : uint32_t + LseDrive : 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 lse_drive | sort + {{name | capitalize }} = {{val}}, +%% endfor }; +%% endif - static void - setCanClockSource(CanClockSource source) + static inline bool + enableLowSpeedExternalCrystal({% if lse_drive %}LseDrive drive = LseDrive::Low, {% endif %}uint32_t waitCycles = 2048) { - RCC->{{ccipr1}} = (RCC->{{ccipr1}} & ~RCC_{{ccipr1}}_FDCANSEL_Msk) | uint32_t(source); + 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; } - /// FDCAN subsystem prescaler common to all FDCAN instances +public: // PLLs enum class - CanPrescaler : uint8_t + PllSource : uint32_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, +%% for val, name in pll_source | sort + {{name | capitalize }} = {{val}}, +%% endfor }; - /// Configure CAN subsystem prescaler - /// \warning Configure the prescaler before enabling the CAN peripherals - /// \returns true if setting the prescaler was successful - static bool - setCanPrescaler(CanPrescaler prescaler); -%% endif - -public: - // sources - static bool - enableInternalClock(uint32_t waitCycles = 2048); - -%% if target.family == "f0" - static bool - enableInternalClockMHz14(uint32_t waitCycles = 2048); +%% if pll_mul + enum class + PllMultiplier : uint32_t + { +%% for val, mul in pll_mul | sort + Mul{{mul}} = {{val}}, +%% endfor + }; +%# %% endif -%% if hsi48 - static bool - enableInternalClockMHz48(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 -%% if target.family in ["l0", "l1", "l4", "l5", "u5"] +%% if usbprescaler enum class - MsiFrequency : uint32_t + UsbPrescaler : 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 + Div1 = RCC_CFGR_USBPRE, ///< do not divide + Div1_5 = 0, ///< divide by 1.5 }; - -%% if target.family in ["u5"] - static bool - enableMultiSpeedInternalClockS(MsiFrequency msi_frequency = MsiFrequency::MHz4, uint32_t waitCycles = 2048); - 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); -%% endif +%# %% endif - static bool - enableExternalClock(uint32_t waitCycles = 2048); - - static bool - enableExternalCrystal(uint32_t waitCycles = 2048); - - static bool - enableLowSpeedInternalClock(uint32_t waitCycles = 2048); - - static bool - enableLowSpeedExternalClock(uint32_t waitCycles = 2048); - - static bool - enableLowSpeedExternalCrystal(uint32_t waitCycles = 2048); - -%% if target.family in ["u5"] +%% if regs.search("RCC_PLL1CFGR_PLL1MBOOST") enum class EpodBoosterPrescaler : uint32_t { @@ -772,62 +492,24 @@ public: disablePllSai(uint32_t waitCycles = 2048); %% endif -%% if target.family == "l0" +%% if hsi_div static inline bool isHsiPredivider4Active() { - return (RCC->CR & RCC_CR_HSIDIVF); + return LL_RCC_IsActiveFlag_HSIDIV(); } 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) + setHsiPredivider4(bool enabled, uint32_t waitCycles = 2048) { - 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); + (enabled) ? LL_RCC_HSI_EnableDivider() : LL_RCC_HSI_DisableDivider(); + while (LL_RCC_IsActiveFlag_HSIDIV() != enabled and --waitCycles) ; + return waitCycles; } %% endif + // sinks + %% if target.family == "h7" enum class UsbClockSource : uint32_t @@ -869,137 +551,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 +685,7 @@ private: computeFlashLatency(uint32_t Core_Hz, uint16_t Core_mV); }; -} // namespace modm::platform +} // namespace modm::platform #include "rcc_impl.hpp"