Skip to content

Commit 971c48f

Browse files
scripts: Enabled argparse for kinetis_gen_dts.py
Enabled argument parsing for kinetis_gen_dts.py, to simplify usage. Signed-off-by: Daniel DeGrasse <[email protected]>
1 parent 787f9bc commit 971c48f

File tree

2 files changed

+159
-31
lines changed

2 files changed

+159
-31
lines changed

mcux/scripts/kinetis_signal2dts.py renamed to mcux/scripts/kinetis_cfg_utils.py

Lines changed: 76 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,14 @@ def get_name(self):
6969
Get mux option name
7070
"""
7171
return self._name
72+
73+
def get_mux_name(self):
74+
"""
75+
Get name of the mux option, without pin name
76+
"""
77+
if self._channel:
78+
return f"{self._periph}_{self._signal}, {self._channel}"
79+
return f"{self._periph}_{self._signal}"
7280

7381
def get_port(self):
7482
"""
@@ -143,7 +151,7 @@ def __init__(self, pin):
143151
logging.debug('Could not match pin name %s', pin.attrib['name'])
144152
self._name = ''
145153
return
146-
self._name = pin_regex.group(0)
154+
self._name = pin.attrib['name']
147155
self._port = pin_regex.group(1)
148156
self._pin = pin_regex.group(2)
149157
self._properties = self._get_pin_properties(pin.find('functional_properties'))
@@ -152,13 +160,7 @@ def __init__(self, pin):
152160
mux_opt = MUXOption(connections)
153161
# Only append mux options with a valid name
154162
if mux_opt.get_name() != '':
155-
# Use a string of the peripheral name and signal here, since that
156-
# is what the MEX file uses as a key to find this mux option
157-
key = f"{mux_opt.get_periph()}_{mux_opt.get_signal()}"
158-
if mux_opt.get_channel() is not None:
159-
# Special case, use channel for key
160-
key = f"{mux_opt.get_periph()}_{mux_opt.get_channel()}"
161-
self._mux_options[key] = mux_opt
163+
self._mux_options[mux_opt.get_mux_name()] = mux_opt
162164

163165
def __repr__(self):
164166
"""
@@ -285,34 +287,30 @@ def __init__(self, function, signal_map):
285287
"""
286288
self._name = function.attrib.get('name')
287289
pins = function.find('mex:pins', NAMESPACES)
288-
signal_regex = re.compile(r'PT[A-Z]\d+')
289290
# Build dictionary mapping pin properties to pins. This allows us to
290291
# group pins based on shared configuration
291292
self._pin_groups = collections.defaultdict(lambda: [])
292293
for pin in pins:
293294
# find signal defintion for this pin
294-
signal_name = signal_regex.search(pin.attrib.get('pin_signal'))
295-
if signal_name is None or (not signal_name.group(0) in signal_map):
296-
# No definition for this pin mapping
297-
logging.warning('Signal %s not matched', pin.attrib.get('pin_signal'))
295+
signal_name = pin.attrib.get('pin_signal')
296+
signal = signal_map[signal_name]
297+
if not signal:
298+
logging.warning('Signal name %s not present in mapping', signal_name)
299+
# No way to find mux option
298300
continue
299-
signal = signal_map[signal_name.group(0)]
300-
# Get mux option for this pin
301-
key = f"{pin.attrib.get('peripheral')}_{pin.attrib.get('signal')}"
302-
channel = re.search(r'(\d+)', pin.attrib.get('signal'))
303-
# Special case, use channel for key
304-
if channel:
305-
key = f"{pin.attrib.get('peripheral')}_{channel.group(1)}"
306-
mux = signal.get_mux_connection(key)
301+
# Get mux option for this signal
302+
mux_option = f"{pin.attrib.get('peripheral')}_{pin.attrib.get('signal')}"
303+
mux = signal.get_mux_connection(mux_option)
307304
if mux is None:
305+
logging.warning('Signal name %s has no mux', mux_option)
308306
# Do not add pinmux option to group
309307
continue
310308
# Get pin defaults for this pin
311309
defaults = signal.get_pin_defaults()
312310
# Get pin overrides
313311
features = pin.find('mex:pin_features', NAMESPACES)
312+
pin_overrides = {}
314313
if features is not None:
315-
pin_overrides = {}
316314
for feature in pin.find('mex:pin_features', NAMESPACES):
317315
pin_overrides[feature.attrib.get('name')] = feature.attrib.get('value')
318316
pin_props = self._props_to_dts(pin_overrides, defaults)
@@ -499,7 +497,6 @@ def write_pinctrl_defs(self, outputfile):
499497
f" * for {self._part_num}/signal_configuration.xml\n"
500498
" *\n"
501499
f" * {self._copyright}\n"
502-
" * SPDX-License-Identifier: Apache-2.0\n"
503500
" */\n"
504501
"\n")
505502
with open(outputfile, "w", encoding="utf8") as file:
@@ -540,12 +537,12 @@ def write_pinctrl_groups(self, mexfile, outputfile):
540537
f" * for {self._part_num}/signal_configuration.xml\n"
541538
" *\n"
542539
f" * {self._copyright}\n"
543-
" * SPDX-License-Identifier: Apache-2.0\n"
544540
" */\n"
545541
"\n")
546542
pin_groups = self._parse_mex_cfg(mexfile)
547543
with open(outputfile, "w", encoding="utf8") as file:
548544
file.write(file_header)
545+
file.write(f"\n#include <nxp/kinetis/{get_package_name(mexfile)}-pinctrl.dtsi>\n\n")
549546
file.write("&pinctrl {\n")
550547
# Write pin groups back out to disk
551548
for group in pin_groups.values():
@@ -554,21 +551,73 @@ def write_pinctrl_groups(self, mexfile, outputfile):
554551
# Do not write to disk
555552
continue
556553
logging.info("Writing pin group %s to disk", group.get_name())
557-
file.write(f"\t{group.get_name().lower()}:{group.get_name().lower()}: {{\n")
554+
file.write(f"\t{group.get_name().lower()}: {group.get_name().lower()} {{\n")
558555
idx = 0
559556
for pin_prop in sorted(pin_props):
560557
group_str = f"\t\tgroup{idx} {{\n"
561558
# Write all pin names
562-
group_str += "\t\t\tpins = <"
559+
group_str += "\t\t\tpinmux = <"
563560
for pin in group.get_pins(pin_prop):
564561
group_str += f"&{pin.get_name()}\n\t\t\t\t"
565562
# Strip out last 3 tabs and close pin name list
566563
group_str = re.sub(r'\n\t\t\t\t$', '>;\n', group_str)
567564
idx += 1
568565
# Write all pin props
569566
for prop in pin_prop:
570-
group_str += f"\t\t\t{prop}\n"
567+
group_str += f"\t\t\t{prop};\n"
571568
group_str += "\t\t};\n"
572569
file.write(group_str)
573570
file.write("\t};\n\n")
574571
file.write("};\n")
572+
573+
"""
574+
Utility functions used to get details about board/processor from MEX file
575+
"""
576+
577+
def get_board_name(mexfile):
578+
"""
579+
Extracts board name from a mex file
580+
@param mexfile: mex file to parse for board name
581+
"""
582+
try:
583+
config_tree = ET.parse(mexfile)
584+
return config_tree.getroot().find('mex:common/mex:board',
585+
NAMESPACES).text
586+
except ET.ParseError:
587+
print(f"Malformed XML tree {mexfile}")
588+
return None
589+
except IOError:
590+
print(f"File {mexfile} could not be opened")
591+
return None
592+
593+
def get_processor_name(mexfile):
594+
"""
595+
Extracts processor name from a mex file
596+
@param mexfile: mex file to parse for processor name
597+
"""
598+
try:
599+
config_tree = ET.parse(mexfile)
600+
return config_tree.getroot().find('mex:common/mex:processor',
601+
NAMESPACES).text
602+
except ET.ParseError:
603+
print(f"Malformed XML tree {mexfile}")
604+
return None
605+
except IOError:
606+
print(f"File {mexfile} could not be opened")
607+
return None
608+
609+
def get_package_name(mexfile):
610+
"""
611+
Extracts package name from a mex file
612+
@param mexfile: mex file to parse for package name
613+
"""
614+
try:
615+
config_tree = ET.parse(mexfile)
616+
return config_tree.getroot().find('mex:common/mex:package',
617+
NAMESPACES).text
618+
except ET.ParseError:
619+
print(f"Malformed XML tree {mexfile}")
620+
return None
621+
except IOError:
622+
print(f"File {mexfile} could not be opened")
623+
return None

mcux/scripts/kinetis_gen_dts.py

Lines changed: 83 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,91 @@
44
#
55
# SPDX-License-Identifier: Apache-2.0
66

7+
"""
8+
Wrapper around kinetis_signal2dts.py to provide arguments
9+
"""
10+
711
import logging
12+
import datetime
13+
import argparse
14+
import pathlib
15+
import sys
16+
import re
17+
18+
import kinetis_cfg_utils
19+
20+
HELPSTR = """
21+
Processes NXP Kinetis MEX configuration files
22+
Given a mex file, generates the board level pinctrl groups required for
23+
Zephyr. Only supports Kinetis parts.
24+
This tool is intended to be used with the configuration data downloaded
25+
from NXP's website. One way to extract this config data is to use the
26+
MCUXpresso configuration tool to download processor defintions, locate
27+
those defintions on the disk. Alternatively, individual processor config
28+
data packs can be downloaded from the MCUXpresso SDK builder tool. Either way,
29+
the path to the 'processors' directory must be provided as the 'cfg-tool-root'
30+
parameter.
31+
"""
32+
33+
parser = argparse.ArgumentParser(description=HELPSTR,
34+
formatter_class=argparse.RawDescriptionHelpFormatter)
35+
36+
parser.add_argument('mex_file', metavar = 'MEX',
37+
type=str, help='path to source MEX file')
38+
parser.add_argument('--cfg-tool-root', metavar = 'CFG_TOOL', type=str,
39+
help='Path to root of MCUXpresso processors directory')
40+
parser.add_argument('--copyright', action='store_true',
41+
help='Enable default NXP copyright')
42+
parser.add_argument('--board-output', metavar = 'BOARD_OUT', type=str,
43+
help='Output path for board level DTS file')
44+
parser.add_argument('--soc-output', metavar = 'SOC_OUT', type=str,
45+
help='Output path for soc level DTSI file')
46+
parser.add_argument('--signal-file', metavar = 'SIGNAL_XML', type=str,
47+
help='Direct path to source signal_configuration.xml file')
48+
49+
args = parser.parse_args()
50+
51+
board_name = kinetis_cfg_utils.get_board_name(args.mex_file)
52+
processor_name = kinetis_cfg_utils.get_processor_name(args.mex_file)
53+
package_name = kinetis_cfg_utils.get_package_name(args.mex_file)
54+
55+
if not args.board_output:
56+
args.board_output = f"{board_name.lower().replace('-', '_')}-pinctrl.dtsi"
57+
58+
if not args.soc_output:
59+
args.soc_output = f"{package_name}-pinctrl.dtsi"
60+
61+
if args.cfg_tool_root:
62+
# Attempt to locate all the required config files automatically, using
63+
# the processor name given in the mex file
64+
proc_root = pathlib.Path(args.cfg_tool_root) / processor_name / 'ksdk2_0' / package_name
65+
if not proc_root.exists():
66+
print(f"Error: Path {args.cfg_tool_root} provided for config root root is invalid")
67+
sys.exit(255)
68+
# Check for all the files we need
69+
signal_path = proc_root / 'signal_configuration.xml'
70+
# Verify files exist
71+
if not signal_path.exists():
72+
print("CFG tools path appears valid, but required files could not be found")
73+
sys.exit(254)
74+
# Set filenames to arguments for tool
75+
if not args.signal_file:
76+
args.signal_file = str(signal_path)
77+
878

9-
from kinetis_signal2dts import NXPSdkUtil
1079

1180
xml = "signal_configuration.xml"
1281

13-
gen = NXPSdkUtil(xml, log_level = logging.INFO)
14-
gen.write_pinctrl_defs("pinctrl.dtsi")
15-
gen.write_pinctrl_groups("/mnt/windows-share/mex-files/FRDM-K64F.mex", 'board.dtsi')
82+
if args.copyright:
83+
# Add default copyright
84+
copyright_txt = (f"Copyright (c) {datetime.datetime.today().year}, NXP\n"
85+
f" * SPDX-License-Identifier: Apache-2.0")
86+
util = kinetis_cfg_utils.NXPSdkUtil(args.signal_file, copyright_header= copyright_txt)
87+
else:
88+
util = kinetis_cfg_utils.NXPSdkUtil(args.signal_file)
89+
90+
print(f"Generating configuration for {board_name}")
91+
util.write_pinctrl_defs(args.soc_output)
92+
print(f"Wrote pinctrl header defs to {args.soc_output}")
93+
util.write_pinctrl_groups(args.mex_file, args.board_output)
94+
print(f"Wrote pinctrl dts file to {args.board_output}")

0 commit comments

Comments
 (0)