Skip to content

Commit

Permalink
[stm32] Use register map query for RCC module
Browse files Browse the repository at this point in the history
  • Loading branch information
salkinium committed Jan 7, 2025
1 parent a1dc260 commit d646fa7
Show file tree
Hide file tree
Showing 3 changed files with 340 additions and 946 deletions.
202 changes: 100 additions & 102 deletions src/modm/platform/clock/stm32/module.lb
Original file line number Diff line number Diff line change
Expand Up @@ -22,131 +22,129 @@ 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")
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["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.findall(r"(LL_RCC_HSI_DIV_?(\d+))")
p["hsi_div4"] = 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 ("", [])
p["msi_range_selection"] = regs.search(r"RCC_.+?_MSIRGSEL")

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"] = []
print(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"])

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") \
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"])

p["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"))
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")
env.template("rcc.hpp.in")

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 = {}
Expand Down
Loading

0 comments on commit d646fa7

Please sign in to comment.