1#!/usr/bin/env python3 2 3# Copyright (c) 2019 - 2020 Nordic Semiconductor ASA 4# Copyright (c) 2019 Linaro Limited 5# Copyright (c) 2024 SILA Embedded Solutions GmbH 6# SPDX-License-Identifier: Apache-2.0 7 8# This script uses edtlib to generate a pickled edt from a devicetree 9# (.dts) file. Information from binding files in YAML format is used 10# as well. 11# 12# Bindings are files that describe devicetree nodes. Devicetree nodes are 13# usually mapped to bindings via their 'compatible = "..."' property. 14# 15# See Zephyr's Devicetree user guide for details. 16# 17# Note: Do not access private (_-prefixed) identifiers from edtlib here (and 18# also note that edtlib is not meant to expose the dtlib API directly). 19# Instead, think of what API you need, and add it as a public documented API in 20# edtlib. This will keep this script simple. 21 22import argparse 23import os 24import pickle 25import sys 26from typing import NoReturn 27 28sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'python-devicetree', 29 'src')) 30 31import edtlib_logger 32from devicetree import edtlib 33 34 35def main(): 36 args = parse_args() 37 38 edtlib_logger.setup_edtlib_logging() 39 40 vendor_prefixes = {} 41 for prefixes_file in args.vendor_prefixes: 42 vendor_prefixes.update(edtlib.load_vendor_prefixes_txt(prefixes_file)) 43 44 try: 45 edt = edtlib.EDT(args.dts, args.bindings_dirs, 46 workspace_dir=args.workspace_dir, 47 # Suppress this warning if it's suppressed in dtc 48 warn_reg_unit_address_mismatch= 49 "-Wno-simple_bus_reg" not in args.dtc_flags, 50 default_prop_types=True, 51 infer_binding_for_paths=["/zephyr,user", "/cpus"], 52 werror=args.edtlib_Werror, 53 vendor_prefixes=vendor_prefixes) 54 except edtlib.EDTError as e: 55 sys.exit(f"devicetree error: {e}") 56 57 # Save merged DTS source, as a debugging aid 58 with open(args.dts_out, "w", encoding="utf-8") as f: 59 print(edt.dts_source, file=f) 60 61 write_pickled_edt(edt, args.edt_pickle_out) 62 63 64def parse_args() -> argparse.Namespace: 65 # Returns parsed command-line arguments 66 67 parser = argparse.ArgumentParser(allow_abbrev=False) 68 parser.add_argument("--dts", required=True, help="DTS file") 69 parser.add_argument("--dtc-flags", 70 help="'dtc' devicetree compiler flags, some of which " 71 "might be respected here") 72 parser.add_argument("--bindings-dirs", nargs='+', required=True, 73 help="directory with bindings in YAML format, " 74 "we allow multiple") 75 parser.add_argument("--workspace-dir", default=os.getcwd(), 76 help="directory to be used as reference for generated " 77 "relative paths (e.g. WEST_TOPDIR)") 78 parser.add_argument("--dts-out", required=True, 79 help="path to write merged DTS source code to (e.g. " 80 "as a debugging aid)") 81 parser.add_argument("--edt-pickle-out", 82 help="path to write pickled edtlib.EDT object to", required=True) 83 parser.add_argument("--vendor-prefixes", action='append', default=[], 84 help="vendor-prefixes.txt path; used for validation; " 85 "may be given multiple times") 86 parser.add_argument("--edtlib-Werror", action="store_true", 87 help="if set, edtlib-specific warnings become errors. " 88 "(this does not apply to warnings shared " 89 "with dtc.)") 90 91 return parser.parse_args() 92 93 94def write_pickled_edt(edt: edtlib.EDT, out_file: str) -> None: 95 # Writes the edt object in pickle format to out_file. 96 97 with open(out_file, 'wb') as f: 98 # Pickle protocol version 4 is the default as of Python 3.8 99 # and was introduced in 3.4, so it is both available and 100 # recommended on all versions of Python that Zephyr supports 101 # (at time of writing, Python 3.6 was Zephyr's minimum 102 # version, and 3.10 the most recent CPython release). 103 # 104 # Using a common protocol version here will hopefully avoid 105 # reproducibility issues in different Python installations. 106 pickle.dump(edt, f, protocol=4) 107 108 109def err(s: str) -> NoReturn: 110 raise Exception(s) 111 112 113if __name__ == "__main__": 114 main() 115