1# Copyright 2022, Niklas Hauser
2# SPDX-License-Identifier: MPL-2.0
3
4import re
5import json
6from pathlib import Path
7from collections import defaultdict
8
9from ...utils import root_path, cache_path
10from ...owl.stmicro import did_from_string
11from ...owl import DeviceIdentifier
12from ...cubemx import cubemx_device_list
13
14
15_SVD_FILES = None
16_SVD_MAP_FILE = cache_path("svd_files.json")
17
18
19def svd_file_devices() -> dict[Path, list[DeviceIdentifier]]:
20 global _SVD_FILES, _SVD_MAP_FILE
21 if _SVD_FILES is None:
22 if not _SVD_MAP_FILE.exists():
23 rm_files, hd_files, cm_files = {}, {}, {}
24 for file in cache_path("stmicro-svd/").glob("*.svd"):
25 match = re.search(r"<description>(.*?)</description>", file.read_text())
26 devices = [did_from_string(n) for n in match.group(1).split(",")]
27 if file.stem.startswith("rm_"):
28 rm_files[file] = devices
29 else:
30 hd_files[file] = devices
31
32 files = list(root_path("ext/cmsis/svd/data/STMicro/").glob("*.svd"))
33 def _sortkey(file):
34 name = re.sub(r"x+$", "", file.stem)
35 return (-len(name),
36 name.count("x"),
37 name.index("x") if "x" in name else 0,
38 name)
39 files.sort(key=_sortkey)
40
41 def _match(file, devices):
42 pattern = re.sub(r"x+$", "", file.stem)
43 pattern = pattern.replace("x", ".").replace("_CM", ".*?@m")
44 pattern = pattern.replace("...A", ".....A")
45 return [d for d in devices if re.match(pattern, d.string, flags=re.IGNORECASE)]
46
47 mdevices = set(cubemx_device_list())
48 for file in files:
49 devices = _match(file, mdevices)
50 mdevices -= set(devices)
51 cm_files[file] = devices
52
53 filefmt = {"cm": {str(p):[str(d) for d in v] for p,v in cm_files.items()},
54 "hd": {str(p):[str(d) for d in v] for p,v in hd_files.items()},
55 "rm": {str(p):[str(d) for d in v] for p,v in rm_files.items()}}
56 with _SVD_MAP_FILE.open('w', encoding='utf-8') as fh:
57 json.dump(filefmt, fh, indent=4)
58 else:
59 with _SVD_MAP_FILE.open('r', encoding='utf-8') as fh:
60 cache = json.load(fh)
61 rm_files = {Path(p):[did_from_string(d) for d in v] for p,v in cache["rm"].items()}
62 hd_files = {Path(p):[did_from_string(d) for d in v] for p,v in cache["hd"].items()}
63 cm_files = {Path(p):[did_from_string(d) for d in v] for p,v in cache["cm"].items()}
64
65 _SVD_FILES = (hd_files, cm_files, rm_files)
66
67 return _SVD_FILES
68
69
70def svd_device_files() -> dict[DeviceIdentifier, list[Path]]:
71 device_files = defaultdict(dict)
72
73 def _remap(files, key):
74 for file, devices in files.items():
75 for device in devices:
76 device_files[device][key] = file
77
78 hd_files, cm_files, rm_files = svd_file_devices()
79 _remap(hd_files, "hd")
80 _remap(cm_files, "cm")
81 _remap(rm_files, "rm")
82 return device_files