1#!/usr/bin/env python3 2# 3# Copyright 2023, NXP 4# 5# SPDX-License-Identifier: Apache-2.0 6 7""" 8Wrapper around support libraries for i.MX RT, LPC, and Kinetis SOCs. 9Allows user to generate pin control board files from MCUXpresso config 10tools (MEX) files 11""" 12# Standard python libraries 13import argparse 14import tempfile 15import zipfile 16import pathlib 17import sys 18import re 19import datetime 20 21# SOC configuration data support libraries 22from imx import imx_cfg_utils 23from kinetis import kinetis_cfg_utils 24from lpc import lpc_cfg_utils 25# Shared MEX utilities 26from shared import mex_utils 27 28 29HELPSTR = """ 30Processes NXP MEX configuration files 31Given a mex file, generates the board level pinctrl groups required for 32Zephyr. This tool is intended to be used with the configuration data packs 33downloaded from NXP's MCUXpresso SDK builder, as well as MEX files created 34by the user using MCUXpresso configuration tools 35""" 36 37 38def parse_args(): 39 """ 40 Parses arguments, and returns object with parsed arguments 41 as properties 42 """ 43 parser = argparse.ArgumentParser(description=HELPSTR, 44 formatter_class=argparse.RawDescriptionHelpFormatter) 45 46 parser.add_argument('mex_file', metavar = 'MEX', 47 type=str, help='path to source MEX file') 48 parser.add_argument('data_pack', metavar = 'DATA_PACK', type=str, 49 help='Path to downloaded data package zip') 50 parser.add_argument('--copyright', action='store_true', 51 help='Enable default NXP copyright') 52 parser.add_argument('--board-output', metavar = 'BOARD_OUT', type=str, 53 help='Output path for board level DTS file') 54 parser.add_argument('--controller', metavar = 'CTRL', type=str, 55 help=("SOC pin controller type." 56 "Currently supports: [IOMUX, IOCON, PORT]")) 57 58 return parser.parse_args() 59 60def processor_to_controller(processor_name): 61 """ 62 Returns pin controller type for processor, or None if 63 processor is unknown 64 """ 65 # Select family of pin controller based on SOC type 66 if "IMXRT1" in processor_name: 67 # Use IMX config tools 68 return 'IOMUX' 69 if "IMXRT6" in processor_name: 70 # LPC config tools 71 return 'IOCON' 72 if "IMXRT5" in processor_name: 73 # LPC config tools 74 return 'IOCON' 75 if "LPC55" in processor_name: 76 # LPC config tools 77 return 'IOCON' 78 if "MK" in processor_name: 79 # Kinetis config tools 80 return 'PORT' 81 # Unknown processor family 82 return "UNKNOWN" 83 84def get_pack_version(pack_dir): 85 """ 86 Gets datapack version 87 @param pack_dir: root directory data pack is in 88 """ 89 # Check version of the config tools archive 90 npi_data = pathlib.Path(pack_dir) / 'npidata.mf' 91 data_version = 0.0 92 with open(npi_data, 'r', encoding='UTF8') as stream: 93 line = stream.readline() 94 while line != '': 95 match = re.search(r'data_version=([\d\.]+)', line) 96 if match: 97 data_version = float(match.group(1)) 98 break 99 line = stream.readline() 100 return data_version 101 102 103def main(): 104 """ 105 Main entry point. Will process arguments, and generate board pin control 106 files. 107 """ 108 args = parse_args() 109 utils = mex_utils.NxpMexUtil(args.mex_file) 110 pins_version = utils.get_pins_version() 111 112 if round(pins_version) != 14: 113 print("Warning: This tool is only verified for MEX files version 14, " 114 "other versions may not work") 115 116 board_name = utils.get_board_name() 117 processor_name = utils.get_processor_name() 118 package_name = utils.get_package_name() 119 120 # Extract the Data pack to a temporary directory 121 temp_dir = tempfile.TemporaryDirectory() 122 zipfile.ZipFile(args.data_pack).extractall(temp_dir.name) 123 proc_root = (pathlib.Path(temp_dir.name) / 'processors'/ 124 processor_name / 'ksdk2_0' / package_name) 125 if not proc_root.exists(): 126 print(f"Error: Data pack does not contain processor data for {processor_name}") 127 sys.exit(255) 128 data_version = get_pack_version(temp_dir.name) 129 130 print(f"Found data pack version {data_version}, pins version {pins_version} " 131 f"for processor {processor_name}") 132 if round(data_version) != 14: 133 print("Warning: This tool is only verified for data pack version 14, " 134 "other versions may not work") 135 136 if not args.board_output: 137 args.board_output = f"{board_name.lower().replace('-', '_')}-pinctrl.dtsi" 138 139 # Initialize SOC specific utility, and generate board pin control 140 if args.copyright: 141 # Add default copyright 142 nxp_copyright = (f"Copyright {datetime.datetime.today().year}, NXP\n" 143 f" * SPDX-License-Identifier: Apache-2.0") 144 else: 145 nxp_copyright = '' 146 147 if args.controller is None: 148 args.controller = processor_to_controller(processor_name) 149 150 # If controller is unknown, this is an unknown SOC and user did not 151 # manually select a controller 152 if args.controller == "UNKNOWN": 153 print(f"Error: processor {processor_name} is not currently supported by this tool") 154 print("You can try specifying your pin controller family manually, " 155 "but this is unsupported!") 156 sys.exit(255) 157 158 # Select correct config tool script for the MEX file 159 if args.controller == 'IOMUX': 160 cfg_util = imx_cfg_utils.NXPSdkUtil(str(proc_root), copyright_header=nxp_copyright) 161 elif args.controller == 'IOCON': 162 cfg_util = lpc_cfg_utils.NXPSdkUtil(str(proc_root), copyright_header=nxp_copyright) 163 elif args.controller == 'PORT': 164 cfg_util = kinetis_cfg_utils.NXPSdkUtil(str(proc_root), copyright_header=nxp_copyright) 165 else: 166 print("Error: unknown controller type") 167 sys.exit(255) 168 print(f"Generating configuration for {board_name}") 169 cfg_util.write_pinctrl_groups(args.mex_file, args.board_output) 170 print(f"Wrote board pinctrl dts file to {args.board_output}") 171 172 173 174if __name__ == "__main__": 175 main() 176