1""" 2Utility script to generate offset definitions for a peripheral from an SVD file. 3 4Usage: 5 6 python gen_offsets.py \ 7 --svd <svd_file> \ 8 --output <output_file> \ 9 --peripheral <peripheral_name> \ 10 --guard <header_guard> \ 11 [--prefix <prefix>] 12 13Copyright (c) 2024 Nordic Semiconductor ASA 14SPDX-License-Identifier: Apache-2.0 15""" 16 17import argparse 18from datetime import datetime 19from pathlib import Path 20import sys 21import xml.etree.ElementTree as ET 22 23 24HEADER = """/* 25 * Copyright (c) {} Nordic Semiconductor ASA 26 * SPDX-License-Identifier: Apache-2.0 27 */ 28 29/* autogenerated using Nordic HAL utils/gen_offsets.py script */ 30""" 31 32 33def parse_offsets(offsets, tree, base_name, base_offset): 34 if base_name: 35 base_name += "_" 36 37 entries = tree.findall("cluster") + tree.findall("register") 38 for entry in entries: 39 is_cluster = entry.tag == "cluster" 40 name = base_name + entry.find("name").text 41 offset = base_offset + int(entry.find("addressOffset").text, 0) 42 43 if "[%s]" not in name: 44 if is_cluster: 45 parse_offsets(offsets, entry, name, offset) 46 else: 47 offsets.append((name, offset)) 48 else: 49 name = name.replace("[%s]", "_{}") 50 dim = int(entry.find("dim").text, 0) 51 dim_inc = int(entry.find("dimIncrement").text, 0) 52 for i in range(dim): 53 if is_cluster: 54 parse_offsets(offsets, entry, name.format(i), offset + i * dim_inc) 55 else: 56 offsets.append((name.format(i), offset + i * dim_inc)) 57 58 59def gen_offsets(svd, output, peripheral, guard, prefix): 60 root = ET.parse(svd).getroot() 61 registers = root.find(f".//peripheral[name='{peripheral}']/registers") 62 if not registers: 63 sys.exit(f"No registers found for {peripheral}") 64 65 offsets = [] 66 parse_offsets(offsets, registers, "", 0) 67 68 with open(output, "w") as f: 69 f.write(HEADER.format(datetime.now().year)) 70 f.write(f"\n#ifndef {guard}\n") 71 f.write(f"#define {guard}\n\n") 72 73 width = max(len(offset[0]) for offset in offsets) 74 for offset in offsets: 75 f.write(f"#define {prefix}{offset[0].ljust(width)} 0x{offset[1]:03X}U\n") 76 77 f.write(f"\n#endif /* {guard} */\n") 78 79 80if __name__ == "__main__": 81 parser = argparse.ArgumentParser(allow_abbrev=False) 82 parser.add_argument("--svd", type=Path, required=True, help="SVD file") 83 parser.add_argument("--output", type=Path, required=True, help="Output file") 84 parser.add_argument("--peripheral", type=str, required=True, help="Peripheral") 85 parser.add_argument("--guard", type=str, required=True, help="Header guard") 86 parser.add_argument("--prefix", type=str, default="", help="Prefix register names") 87 args = parser.parse_args() 88 89 gen_offsets(args.svd, args.output, args.peripheral, args.guard, args.prefix) 90