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 # Suppress this warning if it's suppressed in dtc 47 warn_reg_unit_address_mismatch= 48 "-Wno-simple_bus_reg" not in args.dtc_flags, 49 default_prop_types=True, 50 infer_binding_for_paths=["/zephyr,user"], 51 werror=args.edtlib_Werror, 52 vendor_prefixes=vendor_prefixes) 53 except edtlib.EDTError as e: 54 sys.exit(f"devicetree error: {e}") 55 56 # Save merged DTS source, as a debugging aid 57 with open(args.dts_out, "w", encoding="utf-8") as f: 58 print(edt.dts_source, file=f) 59 60 write_pickled_edt(edt, args.edt_pickle_out) 61 62 63def parse_args() -> argparse.Namespace: 64 # Returns parsed command-line arguments 65 66 parser = argparse.ArgumentParser(allow_abbrev=False) 67 parser.add_argument("--dts", required=True, help="DTS file") 68 parser.add_argument("--dtc-flags", 69 help="'dtc' devicetree compiler flags, some of which " 70 "might be respected here") 71 parser.add_argument("--bindings-dirs", nargs='+', required=True, 72 help="directory with bindings in YAML format, " 73 "we allow multiple") 74 parser.add_argument("--dts-out", required=True, 75 help="path to write merged DTS source code to (e.g. " 76 "as a debugging aid)") 77 parser.add_argument("--edt-pickle-out", 78 help="path to write pickled edtlib.EDT object to", required=True) 79 parser.add_argument("--vendor-prefixes", action='append', default=[], 80 help="vendor-prefixes.txt path; used for validation; " 81 "may be given multiple times") 82 parser.add_argument("--edtlib-Werror", action="store_true", 83 help="if set, edtlib-specific warnings become errors. " 84 "(this does not apply to warnings shared " 85 "with dtc.)") 86 87 return parser.parse_args() 88 89 90def write_pickled_edt(edt: edtlib.EDT, out_file: str) -> None: 91 # Writes the edt object in pickle format to out_file. 92 93 with open(out_file, 'wb') as f: 94 # Pickle protocol version 4 is the default as of Python 3.8 95 # and was introduced in 3.4, so it is both available and 96 # recommended on all versions of Python that Zephyr supports 97 # (at time of writing, Python 3.6 was Zephyr's minimum 98 # version, and 3.10 the most recent CPython release). 99 # 100 # Using a common protocol version here will hopefully avoid 101 # reproducibility issues in different Python installations. 102 pickle.dump(edt, f, protocol=4) 103 104 105def err(s: str) -> NoReturn: 106 raise Exception(s) 107 108 109if __name__ == "__main__": 110 main() 111