Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/test-kg.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ jobs:

- name: Clone STMicro Sources
run: |
make ext/arm/cmsis/ ext/stmicro/cubehal/ ext/stmicro/header/
make clone-sources-stmicro

- name: Generate Database for ${{ matrix.family_group.name }}
run: |
Expand Down
5 changes: 5 additions & 0 deletions .github/workflows/update-archives.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ jobs:
update-pdfs:
runs-on: ubuntu-latest
steps:
- name: Free up Disk Space
run: |
df -h
sudo rm -rf /usr/lib/jvm /usr/share/dotnet /usr/local/lib/android /opt/microsoft /opt/google
df -h

- name: Check out Repository
uses: actions/checkout@v4
Expand Down
66 changes: 23 additions & 43 deletions src/modm_data/cubehal/dmamux_requests.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@
from ..kg import DeviceIdentifier

_CUBE_PATH = ext_path("stmicro/cubehal")
_DMAMUX_PATTERN = re.compile(r"^\s*#define\s+(?P<name>(LL_DMAMUX_REQ_\w+))\s+(?P<id>(0x[0-9A-Fa-f]+))U")
_DMAMUX_LL_PATTERN = re.compile(r"^\s*#define\s+(?P<name>(LL_DMAMUX?_REQ_\w+))\s+(?P<id>(0x[0-9A-Fa-f]+))U")
_REQUEST_PATTERN = re.compile(r"^\s*#define\s+(?P<name>(DMA_REQUEST_\w+))\s+(?P<id>([0-9]+))U")
_BDMA_REQUEST_PATTERN = re.compile(r"^\s*#define\s+(?P<name>(BDMA_REQUEST_\w+))\s+(?P<id>([0-9]+))U")
_DMAMUX_PATTERN = re.compile(r"^\s*#define\s+(?P<name>(DMAM?U?X?_REQU?E?S?T?_\w+))\s+(?P<id>(LL_DMAMUX?_REQ_\w+))\s*")


def read_request_map(did: DeviceIdentifier) -> dict[str, int]:
Expand All @@ -27,7 +28,7 @@ def read_request_map(did: DeviceIdentifier) -> dict[str, int]:
elif did.family in ["g0", "u0", "wb", "wl"]:
request_map = _read_requests_from_ll_dmamux(dma_header, dmamux_header)
elif did.family == "l4" and did.name[0] in ["p", "q", "r", "s"]:
request_map = _read_requests_l4(did)
request_map = _read_requests_l4(dma_header, dmamux_header, did)
else:
raise RuntimeError("No DMAMUX request data available for {}".format(did))
_fix_request_data(request_map, "DMA")
Expand Down Expand Up @@ -126,62 +127,41 @@ def _read_requests(hal_dma_file, request_pattern):

# For G0, WB and WL
def _read_requests_from_ll_dmamux(hal_dma_file, ll_dmamux_file):
dmamux_map = _read_map(ll_dmamux_file, _DMAMUX_PATTERN)
request_pattern = re.compile(
r"^\s*#define\s+(?P<name>(DMAM?U?X?_REQU?E?S?T?_\w+))\s+(?P<id>(LL_DMAMUX?_REQ_\w+))\s*"
)
requests_map = _read_map(hal_dma_file, request_pattern)
dmamux_map = _read_map(ll_dmamux_file, _DMAMUX_LL_PATTERN)
requests_map = _read_map(hal_dma_file, _DMAMUX_PATTERN)
out_map = {}
for r in requests_map.keys():
out_map[r.replace("DMA_REQUEST_", "", 1).replace("DMAMUX_REQ_", "", 1)] = int(dmamux_map[requests_map[r]], 16)
return out_map


# For L4+
def _read_requests_l4(did):
read_for_p5_q5 = did.name in ["p5", "q5"]
def _read_requests_l4(hal_dma_file, ll_dmamux_file, did):
dmamux_pattern = re.compile(r"^\s*#define\s+(?P<name>(LL_DMAMUX_REQ_\w+))\s+(?P<id>\(? ?\d+)U")
dmamux_map = _read_map(ll_dmamux_file, dmamux_pattern, ignore_duplicates=True)
del dmamux_map["LL_DMAMUX_REQ_ADC2_SHIFT"]
if is_p5_q5 := did.name in ["p5", "q5"]:
dmamux_map = {k: ((int(v[1:]) + 1) if "(" in v else v) for k, v in dmamux_map.items()}
else:
dmamux_map = {k: v.replace("(", "") for k, v in dmamux_map.items() if k != "LL_DMAMUX_REQ_ADC2"}

requests_map = _read_map(hal_dma_file, _DMAMUX_PATTERN)
if not is_p5_q5:
del requests_map["DMA_REQUEST_ADC2"]

out_map = {}
p5_q5_if = "#if defined (STM32L4P5xx) || defined (STM32L4Q5xx)"
if_pattern = re.compile(r"^\s*#\s*if\s+")
else_pattern = re.compile(r"^\s*#\s*else")
endif_pattern = re.compile(r"^\s*#\s*endif")
in_p5_q5_section = False
ignore = False
with open(_get_hal_dma_header_path(did), "r") as header_file:
if_counter = 0
for line in header_file.readlines():
if p5_q5_if in line:
in_p5_q5_section = True
ignore = not read_for_p5_q5
elif in_p5_q5_section:
if if_pattern.match(line):
if_counter += 1
elif endif_pattern.match(line):
if if_counter == 0:
in_p5_q5_section = False
ignore = False
else:
if_counter -= 1
elif else_pattern.match(line) and if_counter == 0:
ignore = read_for_p5_q5
if not ignore:
m = _REQUEST_PATTERN.match(line)
if m:
name = m.group("name").replace("DMA_REQUEST_", "", 1)
if name in out_map:
raise RuntimeError(f"Duplicate entry {name}")
out_map[name] = int(m.group("id"))
for r in requests_map.keys():
out_map[r.replace("DMA_REQUEST_", "", 1).replace("DMAMUX_REQ_", "", 1)] = int(dmamux_map[requests_map[r]])
return out_map


def _read_map(filename, pattern):
def _read_map(filename, pattern, ignore_duplicates=False):
out_map = {}
with open(filename, "r") as header_file:
for line in header_file.readlines():
m = pattern.match(line)
if m:
name = m.group("name")
if name in out_map:
raise RuntimeError(f"Duplicate entry {name}")
if name in out_map and not ignore_duplicates:
raise RuntimeError("Duplicate entry {}".format(name))
out_map[name] = m.group("id")
return out_map
140 changes: 88 additions & 52 deletions src/modm_data/cubemx/device_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,13 @@
from ..cubehal import read_request_map as dmamux_request_map
from ..cubehal import read_bdma_request_map as dmamux_bdma_request_map
from . import peripherals
from ..header2svd.stmicro import Header

LOGGER = logging.getLogger(__file__)


_MCU_PATH = ext_path("stmicro/cubemx/mcu")
_EXT_PATH = ext_path("stmicro/")
_MCU_PATH = _EXT_PATH / "cubemx/mcu"
_FAMILY_FILE = None


Expand Down Expand Up @@ -84,66 +86,95 @@ def devices_from_partname(partname: str) -> list[dict[str]]:
LOGGER.info(f"Parsing '{did.string}'")

# information about the core and architecture
cores = [c.text.lower().replace("arm ", "") for c in device_file.query("//Core")]
cores = [c.text.lower().replace("arm ", "").replace("+", "plus") for c in device_file.query("//Core")]
if len(cores) > 1:
did.naming_schema += "@{core}"
devices = [_properties_from_id(comboDeviceName, device_file, did.copy(), c) for c in cores]
devices = [_properties_from_id(partname, comboDeviceName, device_file, did.copy(), c) for c in cores]
return [d for d in devices if d is not None]


def _properties_from_id(comboDeviceName, device_file, did, core):
if core.endswith("m4") or core.endswith("m7") or core.endswith("m33"):
core += "f"
if did.family in ["h7"] or (did.family in ["f7"] and (did.name[0] in ("6", "7"))):
core += "d"
def _properties_from_id(partname, comboDeviceName, device_file, did, core):
if "@" in did.naming_schema:
did.set("core", core[7:9])
p = {"id": did, "core": core}
p = {"id": did, "die": device_file.query("//Die/text()")[0]}

dfp_folder = "STM32{}xx_DFP".format(did.family.upper())
if did.string[5:8] in ["h7r", "h7s"]:
dfp_folder = "STM32H7RSxx_DFP"
elif did.string[5:8] == "wb0":
dfp_folder = "STM32WB0x_DFP"
elif did.string[5:8] == "wba":
dfp_folder = "STM32WBAxx_DFP"
elif did.string[5:8] == "wl3":
dfp_folder = "STM32WL3x_DFP"

# Find OpenCMSIS pack file
dfp_file = XmlReader(os.path.join(_EXT_PATH, dfp_folder, f"Keil.{dfp_folder}.pdsc"))

# Find the correct DFP start node
dfp_node = dfp_file.query(f'//variant[starts-with(@Dvariant,"{partname}")]')
if not dfp_node:
dfp_node = dfp_file.query(f'//device[starts-with(@Dname,"{partname}")]')
if not dfp_node:
dfp_node = dfp_file.query(f'//device[starts-with(@Dname,"{partname[:11]}")]')

if not dfp_node:
LOGGER.error(f"No DFP device entry found for {did.string}: {partname}")
return None

def dfp_findall(key, attribs=None):
values = []
node = dfp_node[0]
while node.tag != "devices":
values += node.findall(key)
node = node.getparent()
if core := did.get("core"):
values = [v for v in values if core.upper() in v.get("Pname", core.upper())]
if attribs is not None:
values = {a: v.get(a) for v in values for a in attribs if v.get(a)}
return values

# Find the correct CMSIS header
dfp_compile = dfp_findall("compile")[0].get("define")
p["cmsis_header"] = cmsis_header = dfp_folder[:-4].lower()
# https://github.com/Open-CMSIS-Pack/STM32H7xx_DFP/pull/7
if did.string == "stm32h730ibt6q":
dfp_compile = "STM32H730xxQ"
stm_header = Header(did, cmsis_header, dfp_compile)
if not stm_header.is_valid:
LOGGER.error("CMSIS Header invalid for %s", did.string)
return None
p["define"] = stm_header.define

# Find out about the CPU
p["core"] = core
processor = dfp_findall("processor", ["DcoreVersion", "Dclock", "Dfpu"])
if (fpu := processor.get("Dfpu")) in ("1", "SP_FPU"):
p["fpu"] = "fpv4-sp-d16" if "m4" in core else "fpv5-sp-d16"
elif fpu == "DP_FPU":
p["fpu"] = "fpv5-d16"
if rev := processor.get("DcoreVersion"):
p["revision"] = rev.lower()

# Maximum operating frequency
if max_frequency := device_file.query("//Frequency"):
max_frequency = float(max_frequency[0].text)
else:
max_frequency = stm32_data.getMaxFrequencyForDevice(did)
# H7 dual-core devices run the M4 core at half the frequency as the M7 core
if did.get("core", "") == "m4":
max_frequency /= 2.0
p["max_frequency"] = int(max_frequency * 1e6)

# flash and ram sizes
# The <ram> and <flash> can occur multiple times.
# they are "ordered" in the same way as the `(S-I-Z-E)` ids in the device combo name
# we must first find out which index the current did.size has inside `(S-I-Z-E)`
sizeIndexFlash = 0
sizeIndexRam = 0

match = re.search(r"\(.(-.)*\)", comboDeviceName)
if match:
sizeArray = match.group(0)[1:-1].lower().split("-")
sizeIndexFlash = sizeArray.index(did.size)
sizeIndexRam = sizeIndexFlash

rams = sorted([int(r.text) for r in device_file.query("//Ram")])
if sizeIndexRam >= len(rams):
sizeIndexRam = len(rams) - 1

flashs = sorted([int(f.text) for f in device_file.query("//Flash")])
if sizeIndexFlash >= len(flashs):
sizeIndexFlash = len(flashs) - 1

p["ram"] = rams[sizeIndexRam] * 1024
p["flash"] = flashs[sizeIndexFlash] * 1024

memories = []
for mem_name, mem_start, mem_size in stm32_data.getMemoryForDevice(did, p["flash"], p["ram"]):
access = "rwx"
if did.family == "f4" and mem_name == "ccm":
access = "rw"
if "flash" in mem_name:
access = "rx"
memories.append({"name": mem_name, "access": access, "size": mem_size, "start": mem_start})

p["memories"] = memories
if max_frequency := processor.get("Dclock"):
max_frequency = int(max_frequency)
elif max_frequency := device_file.query("//Frequency"):
LOGGER.warning(f"Fallback to //Frequency for max frequency for {did.string}!")
max_frequency = int(float(max_frequency[0].text) * 1e6)
p["max_frequency"] = max_frequency

# Find all internal memories
memories = {
m.get("name", m.get("id")).lower(): {
"access": m.get("access", "rwx"),
"start": int(m.get("start"), 0),
"size": int(m.get("size"), 0),
"alias": m.get("alias", "").lower(),
}
for m in (dfp_findall("memory") + dfp_findall("algorithm"))
}
p["memories"] = stm32_data.fixMemoryForDevice(did, memories, stm_header)

# packaging
package = device_file.query("//@Package")[0]
Expand Down Expand Up @@ -216,6 +247,11 @@ def clean_up_version(version):
module = ("TIM",) + module[1:]
elif module[0] == "MDF" and module[1].startswith("ADF"):
module = ("ADF",) + module[1:]
elif module[0] == "USB_DRD_FS":
module = (
"USB",
"USB",
) + module[2:]

modules.append(tuple([m.lower() for m in module]))

Expand Down
Loading
Loading