Skip to content

Commit e0a4f8a

Browse files
committed
[stm32] Use register map query for RCC module
1 parent a1dc260 commit e0a4f8a

File tree

4 files changed

+338
-979
lines changed

4 files changed

+338
-979
lines changed

src/modm/platform/clock/stm32/module.lb

Lines changed: 93 additions & 114 deletions
Original file line numberDiff line numberDiff line change
@@ -22,131 +22,109 @@ def prepare(module, options):
2222
if not options[":target"].has_driver("rcc:stm32*"):
2323
return False
2424

25-
module.depends(":cmsis:device", ":utils", ":platform:clock", ":architecture:delay")
26-
# FIXME: Move Peripherals enum somewhere better
27-
module.depends(":platform:gpio")
25+
module.depends(":cmsis:device", ":utils", ":platform:clock",
26+
":architecture:delay", ":platform:gpio", ":cmsis:ll:rcc")
2827
return True
2928

3029
def build(env):
3130
device = env[":target"]
32-
driver = device.get_driver("rcc")
31+
target = device.identifier
3332
regs = env.query(":cmsis:device:registers")
3433

35-
properties = {}
36-
properties["target"] = target = device.identifier
37-
properties["partname"] = device.partname
38-
properties["core"] = core = device.get_driver("core")["type"]
39-
40-
if target["family"] in ["c0"]:
41-
properties["hsi_frequency"] = 48_000_000
42-
properties["lsi_frequency"] = 32_000
43-
properties["boot_frequency"] = 12_000_000
44-
elif target["family"] in ["f0", "f1", "f3"]:
45-
properties["hsi_frequency"] = 8_000_000
46-
properties["lsi_frequency"] = 40_000
47-
properties["boot_frequency"] = properties["hsi_frequency"]
48-
elif target["family"] in ["h7"]:
49-
properties["hsi_frequency"] = 64_000_000
50-
properties["lsi_frequency"] = 32_000
51-
properties["boot_frequency"] = properties["hsi_frequency"]
52-
elif target["family"] in ["l0", "l1"]:
53-
properties["hsi_frequency"] = 16_000_000
54-
properties["lsi_frequency"] = 37_000
55-
properties["msi_frequency"] = 2_097_000
56-
properties["boot_frequency"] = properties["msi_frequency"]
57-
elif target["family"] in ["l5"]:
58-
properties["hsi_frequency"] = 16_000_000
59-
properties["lsi_frequency"] = 32_000
60-
properties["msi_frequency"] = 4_000_000
61-
properties["boot_frequency"] = properties["msi_frequency"]
34+
# These definitions must exist on all devices
35+
boot_frequency = "HSI_VALUE"
36+
if target.family in ["c0"]:
37+
boot_frequency = "12'000'000"
38+
elif target.family in ["l0", "l1"]:
39+
boot_frequency = "2'097'000"
40+
elif target.family in ["l5"]:
41+
boot_frequency = "4'000'000"
42+
43+
# We're using two regex here, since some headers have both PLLSOURCE *and* PLL1SOURCE
44+
pll_source = regs.findall(r"(LL_RCC_PLLSOURCE_(.+?))") or regs.findall(r"(LL_RCC_PLL1SOURCE_(.+?))")
45+
assert pll_source, "Cannot find PllSource enums"
46+
47+
cfgr_sws_pos = regs.search("RCC_.*?_SWS_Pos")
48+
assert (sys_source := regs.findall(r"(LL_RCC_SYS_CLKSOURCE_(.{1,9}))")), "Cannot find SystemClockSource enums"
49+
assert (rtc_source := regs.findall(r"(LL_RCC_RTC_CLKSOURCE_(.+?))")), "Cannot find RealTimeClockSource enums"
50+
assert (ahb_prescaler := regs.findall(r"(LL_RCC_SYSCLK_DIV_(\d+?))")), "Cannot find AhbPrescaler enums"
51+
52+
apb_prescaler = defaultdict(list)
53+
for reg, bus, div in regs.findall(r"(LL_RCC_APB(\d)?_DIV_(\d+?))"):
54+
apb_prescaler[bus].append((reg, div))
55+
assert apb_prescaler, "Cannot find any ApbPrescaler enums"
56+
57+
mco_source = defaultdict(lambda: ([], []))
58+
for reg, mco, name in regs.findall(r"(LL_RCC_MCO(\d?)SOURCE_(.+?))"):
59+
mco_source[mco][0].append((reg, name))
60+
for reg, mco, div in regs.findall(r"(LL_RCC_MCO(\d?)_DIV_(\d+?))"):
61+
mco_source[mco][1].append((reg, div))
62+
assert mco_source, "Cannot find any ClockOutputSource enums"
63+
64+
# These may not exist on all devices
65+
can_source = regs.findall(r"(LL_RCC_FDCAN_CLKSOURCE_(.+?))")
66+
pll_mul = regs.findall(r"(LL_RCC_PLL_MUL_(\d+_?\d?))")
67+
pll_input_range = regs.findall(r"(LL_RCC_PLLINPUTRANGE_(\d+_\d+))")
68+
usbprescaler = regs.search(r"RCC_CFGR_USBPRE")
69+
lse_drive = regs.findall(r"(LL_RCC_LSEDRIVE_(.+?))")
70+
hsi48 = regs.search(r"RCC_.*?_HSI48ON")
71+
hsi14 = regs.search(r"RCC_.*?_HSI14ON")
72+
msi_range_selection = regs.search(r"RCC_.+?_MSIRGSEL")
73+
epod_booster = regs.findall(r"(LL_RCC_PLL1MBOOST_DIV_(\d+))")
74+
75+
if (hsi_div4 := regs.search(r"RCC_.*?_HSIDIVEN")):
76+
# Normalize the HSIDIVEN to be Div4 on the STM32L0 family
77+
hsi_div = [("0", "1"), (hsi_div4, "4")]
6278
else:
63-
properties["hsi_frequency"] = 16_000_000
64-
properties["lsi_frequency"] = 32_000
65-
properties["boot_frequency"] = properties["hsi_frequency"]
66-
67-
# TODO: Move this data into the device files
68-
properties["usbprescaler"] = device.has_driver("usb") and target.family in ["f0", "f1", "f3"]
69-
properties["pllprediv"] = \
70-
(target["family"] in ["f0", "f3"] or (target["family"] == "f1" and target["name"] in ["00", "05", "07"]))
71-
properties["pllprediv2"] = False # FIXME: not sure what value this should have
72-
properties["pll_hse_prediv2"] = target["family"] == "f1" and target["name"] in ["01", "02", "03"]
73-
properties["hsi48"] = \
74-
(target["family"] in ["g4", "h5", "h7", "l5", "u0", "u5"]) or \
75-
(target["family"] == "f0" and target["name"] in ["42", "48", "71", "72", "78", "91", "98"]) or \
76-
(target["family"] == "g0" and target["name"] in ["b1", "c1"]) or \
77-
(target["family"] == "l0" and target["name"][1] == "2") or \
78-
(target["family"] == "l4" and target["name"][0] not in ["7", "8"])
79-
if target["family"] in ["g4", "l0", "l4", "l5", "u0"]:
80-
properties["hsi48_cr"] = "CRRCR"
81-
elif target["family"] in ["g0", "h5", "h7", "u5"]:
82-
properties["hsi48_cr"] = "CR"
83-
elif target["family"] in ["f0"]:
84-
properties["hsi48_cr"] = "CR2"
85-
properties["pll_p"] = ((target["family"] == "l4" and target["name"] not in ["12", "22"]) or target["family"] == "g4")
86-
properties["overdrive"] = (target["family"] == "f7") or \
87-
((target["family"] == "f4") and target["name"] in ["27", "29", "37", "39", "46", "69", "79"])
88-
properties["vos0_overdrive"] = (target["family"] == "h7") and \
89-
target["name"] in ["42", "43", "45", "47", "50", "53", "55", "57"]
90-
properties["has_r1mode"] = (target["family"] == "g4") or \
91-
(target["family"] == "l4" and target["name"][0] in ["p", "q", "r", "s"])
92-
properties["pllsai_p_usb"] = (target["family"] == "f7") or \
93-
((target["family"] == "f4") and target["name"] in ["46", "69", "79"])
94-
95-
if target.family in ["h7"]:
96-
if target.name in ["a3", "b0", "b3"]:
97-
properties["cfgr_prescaler"] = "CDCFGR1"
98-
else:
99-
properties["cfgr_prescaler"] = "D1CFGR"
100-
elif target.family in ["u5"]:
101-
properties["cfgr_prescaler"] = "CFGR2"
102-
else:
103-
properties["cfgr_prescaler"] = "CFGR"
104-
105-
if target.family in ["h7"]:
106-
if target.name in ["a3", "b0", "b3"]:
107-
properties["cfgr2"] = "CDCFGR2"
108-
else:
109-
properties["cfgr2"] = "D2CFGR"
110-
elif target.family in ["u5"]:
111-
properties["cfgr2"] = "CFGR2"
112-
else:
113-
properties["cfgr2"] = "CFGR"
114-
115-
if target.family in ["h7"]:
116-
if target.name in ["a3", "b0", "b3"]:
117-
properties["ccipr1"] = "CDCCIP1R"
118-
else:
119-
properties["ccipr1"] = "D2CCIP1R"
120-
elif target.family in ["l5", "u5"]:
121-
properties["ccipr1"] = "CCIPR1"
122-
else:
123-
properties["ccipr1"] = "CCIPR"
124-
125-
properties["d1"] = ("CD" if target.name in ["a3", "b0", "b3"] else "D1") \
79+
hsi_div = regs.findall(r"(LL_RCC_HSI_DIV_?(\d+))")
80+
81+
# There is sadly no easy way to find the MSI range values, so we have to hardcode them
82+
msi_range = regs.findall(r"(LL_RCC_MSIK?RANGE_)\d+") or ("", [])
83+
if len(msi_range) == 7:
84+
msi_range = (msi_range[0], ("kHz65_536", "kHz131_072", "kHz262_144", "kHz524_288", "MHz1_048", "MHz2_097", "MHz4_194"))
85+
elif len(msi_range) == 12:
86+
msi_range = (msi_range[0], ("kHz100", "kHz200", "kHz400", "kHz800", "MHz1", "MHz2",
87+
"MHz4", "MHz8", "MHz16", "MHz24", "MHz32", "MHz48"))
88+
elif len(msi_range) == 16:
89+
msi_range = (msi_range[0], ("MHz48", "MHz24", "MHz16", "MHz12", "MHz4", "MHz2", "MHz1_5", "MHz1", "MHz3_072",
90+
"MHz1_536", "MHz1_024", "kHz768", "kHz400", "kHz200", "kHz133", "kHz100"))
91+
msi_clocks = (["K", "S"] if "K" in msi_range[0] else [""]) if msi_range else []
92+
93+
clk48_source = []
94+
if regs.search(r"RCC_.+?_(?:CL?K48M?SEL|ICLKSEL)"):
95+
clk48_source = regs.findall(r"(LL_RCC_(?:USB|CL?K48)_CLKSOURCE_(.+?))")
96+
97+
# -------------------------------------------------------------------------
98+
# TODO: Replace this data with register queries
99+
pllprediv = \
100+
(target.family in ["f0", "f3"] or (target.family == "f1" and target.name in ["00", "05", "07"]))
101+
pllprediv2 = False # FIXME: not sure what value this should have
102+
pll_hse_prediv2 = target.family == "f1" and target.name in ["01", "02", "03"]
103+
pll_p = ((target.family == "l4" and target.name not in ["12", "22"]) or target.family == "g4")
104+
overdrive = (target.family == "f7") or \
105+
((target.family == "f4") and target.name in ["27", "29", "37", "39", "46", "69", "79"])
106+
vos0_overdrive = (target.family == "h7") and \
107+
target.name in ["42", "43", "45", "47", "50", "53", "55", "57"]
108+
has_r1mode = (target.family == "g4") or \
109+
(target.family == "l4" and target.name[0] in ["p", "q", "r", "s"])
110+
pllsai_p_usb = (target.family == "f7") or \
111+
((target.family == "f4") and target.name in ["46", "69", "79"])
112+
113+
d2 = ("CD" if target.name in ["a3", "b0", "b3"] else "D2") \
126114
if target.family == "h7" else ""
127-
properties["d2"] = ("CD" if target.name in ["a3", "b0", "b3"] else "D2") \
128-
if target.family == "h7" else ""
129-
properties["cfgr3"] = ("SRDCFGR" if target.name in ["a0", "a3", "b0", "b3"] else "D3CFGR")
130-
properties["d3"] = ("SRD" if target.name in ["a0", "a3", "b0", "b3"] else "D3")
131-
properties["bdcr"] = "CSR1" if target.family in ["c0"] else "CSR" if target.family in ["l0", "l1"] else "BDCR"
132-
properties["pll_ids"] = ["1", "2", "3"] if target.family in ["h7", "u5"] else [] if target.family in ["c0"] else [""]
133-
properties["has_smps"] = target["family"] == "h7" and (target["name"] in ["25", "35", "45", "47", "55", "57"] or \
134-
(target["name"] in ["30", "a3", "b0", "b3"] and target["variant"] == "q"))
115+
d3 = ("SRD" if target.name in ["a0", "a3", "b0", "b3"] else "D3")
116+
pll_ids = ["1", "2", "3"] if target.family in ["h7", "u5"] else [] if target.family in ["c0"] else [""]
117+
has_smps = target.family == "h7" and (target.name in ["25", "35", "45", "47", "55", "57"] or \
118+
(target.name in ["30", "a3", "b0", "b3"] and target["variant"] == "q"))
119+
# -------------------------------------------------------------------------
135120

136121
flash_latencies = {}
137122
for vcore in device.get_driver("flash")["latency"]:
138123
flash_latencies[int(vcore["vcore-min"])] = sorted([int(f["hclk-max"]) for f in vcore["wait-state"]])
139124

140-
properties["table"] = flash_latencies
141-
env.substitutions = properties
142-
env.outbasepath = "modm/src/modm/platform/clock"
143-
144-
env.template("rcc.cpp.in")
145-
env.template("rcc.hpp.in")
146-
147125
all_peripherals = env.query(":cmsis:device:peripherals")
148126
rcc_map = defaultdict(dict)
149-
for (reg, per, typ) in regs.findall(r"RCC_([A-Z0-9]*?)_([A-Z0-9]+?)(EN|RST)"):
127+
for (reg, per, typ) in regs.findall(r"RCC_(A[HP]B\d?(?:ENR|RSTR)\d?)_(.*?)(EN|RST)"):
150128
rcc_map[per][typ] = reg
151129
rcc_enable = {}
152130
rcc_reset = {}
@@ -214,8 +192,9 @@ def build(env):
214192
if "RST" in mode:
215193
rcc_reset[per.capitalize()] = (nper, mode["RST"])
216194

217-
env.substitutions.update({
218-
"rcc_enable": rcc_enable,
219-
"rcc_reset": rcc_reset,
220-
})
195+
196+
env.outbasepath = "modm/src/modm/platform/clock"
197+
env.substitutions = locals()
198+
env.template("rcc.cpp.in")
199+
env.template("rcc.hpp.in")
221200
env.template("rcc_impl.hpp.in")

0 commit comments

Comments
 (0)