Skip to content

Commit 95f3c67

Browse files
scripts: mcux: update pin script to generate headers
Update pin generation script to create pinctrl headers, and add second script to generate headers versus pinctrl definition files Signed-off-by: Daniel DeGrasse <[email protected]>
1 parent 2a1fad0 commit 95f3c67

File tree

3 files changed

+123
-43
lines changed

3 files changed

+123
-43
lines changed

mcux/scripts/kinetis_cfg_utils.py

Lines changed: 47 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
pinctrl definitions for Zephyr
1111
"""
1212

13-
from bdb import set_trace
1413
import xml.etree.ElementTree as ET
1514
import re
1615
import collections
@@ -70,7 +69,7 @@ def get_name(self):
7069
Get mux option name
7170
"""
7271
return self._name
73-
72+
7473
def get_mux_name(self):
7574
"""
7675
Get name of the mux option, without pin name
@@ -261,9 +260,6 @@ def _get_pin_properties(self, props):
261260
"""
262261
prop_mapping = {}
263262
for prop in props.findall('functional_property'):
264-
if len(prop.findall('state/configuration/assign')) == 0:
265-
# Not configurable property. Skip
266-
continue
267263
prop_id = prop.attrib['id']
268264
if not 'default' in prop.attrib:
269265
# No default property. Skip
@@ -272,7 +268,11 @@ def _get_pin_properties(self, props):
272268
prop_mapping[prop_id]['default'] = prop.attrib['default']
273269
for state in prop.findall('state'):
274270
reg_assign = state.find('configuration/assign')
275-
bit_value = int(reg_assign.attrib['bit_field_value'], 0)
271+
if reg_assign:
272+
bit_value = int(reg_assign.attrib['bit_field_value'], 0)
273+
else:
274+
# Assume writing zero to register will select default
275+
bit_value = 0
276276
prop_mapping[prop_id][state.attrib['id']] = bit_value
277277
return prop_mapping
278278

@@ -322,6 +322,20 @@ def __repr__(self):
322322
Get string representation of the object
323323
"""
324324
return "PinGroup(%s)" % (self._name)
325+
326+
def __eq__(self, obj):
327+
"""
328+
return true if two objects have the same pin group name
329+
"""
330+
return isinstance(obj, PinGroup) and self._name == obj._name
331+
332+
def __lt__(self, obj):
333+
"""
334+
Compare objects based on name
335+
"""
336+
if not isinstance(obj, PinGroup):
337+
return True
338+
return self._name < obj._name
325339

326340
def get_pin_props(self):
327341
"""
@@ -459,22 +473,19 @@ def _write_pins(self, which_port, pins, file):
459473
label = pin_data.get_name()
460474
port = pin_data.get_port()
461475
pin = pin_data.get_pin()
462-
463-
# Port values range from 'A'-'E'. Store with 4 bits
464-
# Shift port value so it will not conflict with pin configuration
465-
pin_val = (((ord(port) - ord('A')) & 0xF) << 28)
466-
# Shift pin value to where it will be stored in the pin setting reg
467-
# Pin values range from 0-31, give 6 bits for future expansion
468-
# Shift pin value so it will not conflict with pin configuration
469-
pin_val |= ((int(pin) & 0x3F) << 22)
470-
# Put pin mux value in at the correct offset for the pin config register
471-
pin_val |= ((pin_data.get_mux() & 0x7) << 8)
476+
mux = pin_data.get_mux()
472477

473478
if label in seen_nodes:
474479
continue
475480
seen_nodes.append(label)
476481

477-
file.write(f"#define {label} 0x{pin_val:x} /* PT{port}{pin} */\n")
482+
file.write(f"#define {label} KINETIS_MUX('{port}',{pin},{mux}) /* PT{port}{pin} */\n")
483+
484+
def get_part_num(self):
485+
"""
486+
Return the part number this class is instantiated for
487+
"""
488+
return self._part_num
478489

479490
def write_pinctrl_defs(self, outputfile):
480491
"""
@@ -494,15 +505,27 @@ def write_pinctrl_defs(self, outputfile):
494505
f" * {self._copyright}\n"
495506
" */\n"
496507
"\n")
508+
509+
# Notes on the below macro:
510+
# Port values range from 'A'-'E', so we store them with 4 bits,
511+
# with port A being 0, B=1,...
512+
# Pin values range from 0-31, so we give 6 bits for future expansion
513+
# Mux values range from 0-8, so we give 3 bits
514+
# shift the port and pin values to the MSBs of the mux value, so they
515+
# don't conflict with pin configuration settings
516+
# Store the mux value at the offset it will actually be written to the
517+
# configuration register
518+
mux_macro = ("#define KINETIS_MUX(port, pin, mux)\t\t\\\n"
519+
"\t(((((port) - 'A') & 0xF) << 28) |\t\\\n"
520+
"\t(((pin) & 0x3F) << 22) |\t\t\\\n"
521+
"\t(((mux) & 0x7) << 8))\n\n")
497522
with open(outputfile, "w", encoding="utf8") as file:
498523
file.write(file_header)
499524
# ifdef guard
500525
file.write(f"#ifndef _ZEPHYR_DTS_BINDING_{self._part_num.upper()}_\n")
501526
file.write(f"#define _ZEPHYR_DTS_BINDING_{self._part_num.upper()}_\n\n")
502527
# Write macro to make port name
503-
file.write("#define MUX(port, pin) (((((port) - 'A') & 0xF) << 28) | (((pin) & 0x3F)) << 22)\n\n")
504-
file.write("#define PIN(mux) (((mux) & 0xFC00000) >> 22\n\n")
505-
file.write("#define PORT(mux) (((mux) & 0xF0000000) >> 28)\n\n")
528+
file.write(mux_macro)
506529
self._write_pins('a', pcr_pins, file)
507530
self._write_pins('b', pcr_pins, file)
508531
self._write_pins('c', pcr_pins, file)
@@ -548,7 +571,7 @@ def write_pinctrl_groups(self, mexfile, outputfile):
548571
file.write(f"\n#include <nxp/kinetis/{get_package_name(mexfile)}-pinctrl.h>\n\n")
549572
file.write("&pinctrl {\n")
550573
# Write pin groups back out to disk
551-
for group in pin_groups.values():
574+
for group in sorted(pin_groups.values()):
552575
pin_props = group.get_pin_props()
553576
if len(pin_props) == 0:
554577
# Do not write to disk
@@ -559,11 +582,11 @@ def write_pinctrl_groups(self, mexfile, outputfile):
559582
for pin_prop in sorted(pin_props):
560583
group_str = f"\t\tgroup{idx} {{\n"
561584
# Write all pin names
562-
group_str += "\t\t\tpinmux = <"
585+
group_str += "\t\t\tpinmux = "
563586
for pin in group.get_pins(pin_prop):
564-
group_str += f"{pin.get_name()}\n\t\t\t\t"
587+
group_str += f"<{pin.get_name()}>,\n\t\t\t\t"
565588
# Strip out last 3 tabs and close pin name list
566-
group_str = re.sub(r'\n\t\t\t\t$', '>;\n', group_str)
589+
group_str = re.sub(r',\n\t\t\t\t$', ';\n', group_str)
567590
idx += 1
568591
# Write all pin props
569592
for prop in pin_prop:

mcux/scripts/kinetis_gen_dts.py

Lines changed: 9 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,10 @@
88
Wrapper around kinetis_signal2dts.py to provide arguments
99
"""
1010

11-
import logging
1211
import datetime
1312
import argparse
1413
import pathlib
1514
import sys
16-
import re
1715

1816
import kinetis_cfg_utils
1917

@@ -41,10 +39,6 @@
4139
help='Enable default NXP copyright')
4240
parser.add_argument('--board-output', metavar = 'BOARD_OUT', type=str,
4341
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')
4842

4943
args = parser.parse_args()
5044

@@ -54,41 +48,37 @@
5448

5549
if not args.board_output:
5650
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.h"
51+
elif pathlib.Path(args.board_output).is_dir():
52+
# Append board name to path
53+
if not args.board_output.endswith('/'):
54+
args.board_output += '/'
55+
args.board_output += f"{board_name.lower().replace('-', '_')}-pinctrl.dtsi"
6056

6157
if args.cfg_tool_root:
6258
# Attempt to locate all the required config files automatically, using
6359
# the processor name given in the mex file
6460
proc_root = pathlib.Path(args.cfg_tool_root) / processor_name / 'ksdk2_0' / package_name
6561
if not proc_root.exists():
66-
print(f"Error: Path {args.cfg_tool_root} provided for config root root is invalid")
62+
print(f"Error: Path {args.cfg_tool_root} provided for config root is invalid")
6763
sys.exit(255)
6864
# Check for all the files we need
6965
signal_path = proc_root / 'signal_configuration.xml'
7066
# Verify files exist
7167
if not signal_path.exists():
7268
print("CFG tools path appears valid, but required files could not be found")
7369
sys.exit(254)
74-
# Set filenames to arguments for tool
75-
if not args.signal_file:
76-
args.signal_file = str(signal_path)
77-
70+
signal_file = str(signal_path)
7871

7972

80-
xml = "signal_configuration.xml"
8173

8274
if args.copyright:
8375
# Add default copyright
8476
copyright_txt = (f"Copyright (c) {datetime.datetime.today().year}, NXP\n"
8577
f" * SPDX-License-Identifier: Apache-2.0")
86-
util = kinetis_cfg_utils.NXPSdkUtil(args.signal_file, copyright_header= copyright_txt)
78+
util = kinetis_cfg_utils.NXPSdkUtil(signal_file, copyright_header= copyright_txt)
8779
else:
88-
util = kinetis_cfg_utils.NXPSdkUtil(args.signal_file)
80+
util = kinetis_cfg_utils.NXPSdkUtil(signal_file)
8981

9082
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}")
9383
util.write_pinctrl_groups(args.mex_file, args.board_output)
9484
print(f"Wrote pinctrl dts file to {args.board_output}")
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
#!/usr/bin/env python3
2+
#
3+
# Copyright (c) 2022, NXP
4+
#
5+
# SPDX-License-Identifier: Apache-2.0
6+
7+
"""
8+
Wrapper around kinetis_signal2dts.py to provide arguments
9+
"""
10+
11+
import datetime
12+
import argparse
13+
from errno import EINVAL, ENOTDIR
14+
import pathlib
15+
import sys
16+
17+
import kinetis_cfg_utils
18+
19+
HELPSTR = """
20+
Processes NXP Kinetis signal configuration files and outputs kinetis pinctrl
21+
headers. Only supports Kinetis parts.
22+
This tool is intended to be used with the configuration data downloaded
23+
from NXP's website. One way to extract this config data is to use the
24+
MCUXpresso configuration tool to download processor defintions, locate
25+
those defintions on the disk. Alternatively, individual processor config
26+
data packs can be downloaded from the MCUXpresso SDK builder tool. Either way,
27+
the path to the 'processors' directory must be provided as the 'cfg-tool-root'
28+
parameter.
29+
"""
30+
31+
parser = argparse.ArgumentParser(description=HELPSTR,
32+
formatter_class=argparse.RawDescriptionHelpFormatter)
33+
34+
parser.add_argument('--processor-root', metavar = 'PROC_ROOT', type=str,
35+
help='Path to root of processor directory with package defintions')
36+
parser.add_argument('--copyright', action='store_true',
37+
help='Enable default NXP copyright')
38+
parser.add_argument('--soc-output', metavar = 'SOC_OUT', type=str,
39+
help='Output folder for soc level header files')
40+
41+
args = parser.parse_args()
42+
43+
if not args.soc_output:
44+
args.soc_output = "."
45+
elif not pathlib.Path(args.soc_output).is_dir():
46+
print('SOC output path must be a directory')
47+
sys.exit(ENOTDIR)
48+
49+
# Attempt to locate the signal XML files we will generate from
50+
proc_root = pathlib.Path(args.processor_root) / 'ksdk2_0'
51+
if not proc_root.exists():
52+
print(f"Error: Path {args.processor_root} provided for processor root is invalid")
53+
sys.exit(EINVAL)
54+
# Iterate through all processor package signal.xml files
55+
for directory in proc_root.iterdir():
56+
signal_path = directory / 'signal_configuration.xml'
57+
if signal_path.exists():
58+
if args.copyright:
59+
# Add default copyright
60+
copyright_txt = (f"Copyright (c) {datetime.datetime.today().year}, NXP\n"
61+
f" * SPDX-License-Identifier: Apache-2.0")
62+
util = kinetis_cfg_utils.NXPSdkUtil(str(signal_path), copyright_header= copyright_txt)
63+
else:
64+
util = kinetis_cfg_utils.NXPSdkUtil(str(signal_path))
65+
out_path = f"{args.soc_output}/{util.get_part_num().upper()}-pinctrl.h"
66+
util.write_pinctrl_defs(out_path)
67+
print(f"Wrote pinctrl header defs to {out_path}")

0 commit comments

Comments
 (0)