1919PIN = collections .namedtuple ('PIN' , ['PERIPH' , 'NAME_PART' , 'SIGNAL' , 'PORT' ,
2020 'PIN' , 'CH' , 'MUX_FUNC' ])
2121
22+ NAMESPACES = {'mex' : 'http://mcuxpresso.nxp.com/XSD/mex_configuration_10' }
23+
24+ class MUXOption :
25+ """
26+ Internal class representing a mux option on the SOC
27+ """
28+ def __init__ (self , connection ):
29+ """
30+ Initializes a mux option
31+ @param connection XML connection option from signal_configuration.xml
32+ """
33+ self ._name = connection .attrib .get ('name_part' )
34+ logging .debug ("\t \t %s" , self ._name )
35+ if self ._name is None :
36+ self ._name = ''
37+ return
38+ # Get MUX settings
39+ self ._port = None
40+ for periph in connection .iter ('peripheral_signal_ref' ):
41+ self ._periph = periph .attrib .get ('peripheral' )
42+ for assign in connection .iter ('assign' ):
43+ reg = assign .attrib .get ('register' )
44+ val = assign .attrib .get ('bit_field_value' )
45+ logging .debug ('\t \t \t [ASSIGN] %s %s' , reg , val )
46+ # Only process PCR registers
47+ match = re .match (r'PORT([A-Z])_PCR(\d+)' , reg )
48+ if match :
49+ self ._name += f"_PT{ match .group (1 )} { match .group (2 )} "
50+ self ._port = match .group (1 )
51+ self ._pin = int (match .group (2 ))
52+ self ._mux = int (val , 16 )
53+ if self ._port is None :
54+ # Not a valid port mapping. Clear name
55+ self ._name = ''
56+
57+ def __repr__ (self ):
58+ """
59+ String representation of object
60+ """
61+ return "MUXOption(%s)" % (self ._name )
62+
63+ def get_name (self ):
64+ """
65+ Get mux option name
66+ """
67+ return self ._name
68+
69+ def get_port (self ):
70+ """
71+ Get mux port
72+ """
73+ return self ._port
74+
75+ def get_pin (self ):
76+ """
77+ Get mux pin
78+ """
79+ return self ._pin
80+
81+ def get_mux (self ):
82+ """
83+ Get mux register write value
84+ """
85+ return self ._mux
86+
87+ def get_periph (self ):
88+ """
89+ Get peripheral name
90+ """
91+ return self ._periph
92+
93+ def __hash__ (self ):
94+ """
95+ Override hash method to return pin name as hash
96+ """
97+ return hash (self ._name )
98+
99+ def __eq__ (self , obj ):
100+ """
101+ Like the hash method, we override the eq method to return true if two
102+ objects have the same pin name
103+ """
104+ return isinstance (obj , SignalPin ) and self ._name == obj ._name
105+
106+ def __lt__ (self , obj ):
107+ """
108+ Compare objects based on name
109+ """
110+ if not isinstance (obj , SignalPin ):
111+ return True
112+ return self ._name < obj ._name
113+
114+
115+ class SignalPin :
116+ """
117+ Internal class representing a signal on the SOC
118+ """
119+ def __init__ (self , pin ):
120+ """
121+ Initializes a SignalPin object
122+ @param pin: pin XML object from signal_configuration.xml
123+ """
124+ # Kinetis pin names are formatted as [PT[Port][Pin]]
125+ pin_regex = re .search (r'PT([A-Z])(\d+)' , pin .attrib ['name' ])
126+ if pin_regex is None :
127+ logging .debug ('Could not match pin name %s' , pin .attrib ['name' ])
128+ self ._name = ''
129+ return
130+ self ._name = pin_regex .group (0 )
131+ self ._port = pin_regex .group (1 )
132+ self ._pin = pin_regex .group (2 )
133+ self ._properties = self ._get_pin_properties (pin .find ('functional_properties' ))
134+ self ._mux_options = {}
135+ for connections in pin .findall ('connections' ):
136+ mux_opt = MUXOption (connections )
137+ # Only append mux options with a valid name
138+ if mux_opt .get_name () != '' :
139+ self ._mux_options [mux_opt .get_name ()] = mux_opt
140+
141+ def __repr__ (self ):
142+ """
143+ String representation of object
144+ """
145+ return "SignalPin(%s)" % (self ._name )
146+
147+ def __hash__ (self ):
148+ """
149+ Override hash method to return pin name as hash
150+ """
151+ return hash (self ._name )
152+
153+ def __eq__ (self , obj ):
154+ """
155+ Like the hash method, we override the eq method to return true if two
156+ objects have the same pin name
157+ """
158+ return isinstance (obj , SignalPin ) and self ._name == obj ._name
159+
160+ def __lt__ (self , obj ):
161+ """
162+ Compare objects based on name
163+ """
164+ if not isinstance (obj , SignalPin ):
165+ return True
166+ return self ._name < obj ._name
167+
168+ def get_name (self ):
169+ """
170+ Get name of pin
171+ """
172+ return self ._name
173+
174+ def get_port (self ):
175+ """
176+ Get PORT this signal is defined for
177+ """
178+ return self ._port
179+
180+ def get_pin (self ):
181+ """
182+ Get pin this signal is defined for
183+ """
184+ return self ._pin
185+
186+ def get_mux_connection (self , signal ):
187+ """
188+ Gets an MUXOption object for the relevant signal name
189+ @param signal: Signal name on pin to get mux option for
190+ """
191+ if signal in self ._mux_options :
192+ return self ._mux_options [signal ]
193+ return None
194+
195+ def get_mux_options (self ):
196+ """
197+ Gets all unique settings for IOMUX on the specific pin
198+ """
199+ return set (self ._mux_options .values ())
200+
201+ def get_pin_properties (self ):
202+ """
203+ Gets array of pin property names
204+ """
205+ return self ._properties .keys ()
206+
207+ def get_pin_property_default (self , prop ):
208+ """
209+ Gets name of default pin property
210+ @param prop: name of pin property
211+ """
212+ return self ._properties [prop ]['default' ]
213+
214+ def get_pin_defaults (self ):
215+ """
216+ Gets mapping of all pin property names to default value names
217+ """
218+ pin_defaults = {}
219+ for prop in self .get_pin_properties ():
220+ pin_default = self .get_pin_property_default (prop )
221+ pin_defaults [prop ] = pin_default
222+ return pin_defaults
223+
224+ def get_pin_property_value (self , prop , selection ):
225+ """
226+ Gets bit value for pin property
227+ @param prop: name of pin property
228+ @param selection: name of option selected for property
229+ """
230+ return self ._properties [prop ][selection ]
231+
232+ def _get_pin_properties (self , props ):
233+ """
234+ Builds dictionary with all pin properties
235+ @param props: pin function_properties XML object in signal_configuration.xml
236+ """
237+ prop_mapping = {}
238+ for prop in props .findall ('functional_property' ):
239+ if len (prop .findall ('state/configuration/assign' )) == 0 :
240+ # Not configurable property. Skip
241+ continue
242+ prop_id = prop .attrib ['id' ]
243+ if not 'default' in prop .attrib :
244+ # No default property. Skip
245+ continue
246+ prop_mapping [prop_id ] = {}
247+ prop_mapping [prop_id ]['default' ] = prop .attrib ['default' ]
248+ for state in prop .findall ('state' ):
249+ reg_assign = state .find ('configuration/assign' )
250+ bit_value = int (reg_assign .attrib ['bit_field_value' ], 0 )
251+ prop_mapping [prop_id ][state .attrib ['id' ]] = bit_value
252+ return prop_mapping
253+
254+
22255class NXPSdkUtil :
23256 """
24257 Class for kinetis configuration file parser
@@ -38,15 +271,15 @@ def __init__(self, signal_file, copyright_header = "", log_level = logging.ERROR
38271 self ._logger .setLevel (log_level )
39272 self ._parse_signal_xml (signal_file )
40273 self ._copyright = copyright_header
41- logging .info ("Loaded %d pinmux defs" , len (self ._pins ))
274+ logging .info ("Loaded %d pin defs" , len (self ._pins ))
42275
43276 def _parse_signal_xml (self , signal_fn ):
44277 """
45278 Parses signal XML configuration file. Builds a list of pins, which can
46279 be used to generate soc level DTSI file.
47280 @param signal_fn: signal_configuration.xml file to parse
48281 """
49- self ._pins = []
282+ self ._pins = {}
50283 try :
51284 signal_tree = ET .parse (signal_fn )
52285 except ET .ParseError :
@@ -72,69 +305,10 @@ def _parse_signal_xml(self, signal_fn):
72305
73306 pins_node = signal_root .find ("pins" )
74307 for pin in pins_node :
75- name = pin .attrib .get ("name" )
76-
77- # Kinetis family uses PT[A-Z][0-31]
78- if "PT" in name :
79- logging .debug (name )
80-
81- num_conns = 0
82-
83- for conns in pin .findall ("connections" ):
84- num_conns += 1
85- logging .debug ("\t %s - %s %s" , num_conns , conns .tag , conns .attrib )
86- name_part = conns .attrib .get ("name_part" )
87- # func = conns.attrib.get("package_function")
88-
89- conns_tree = ET .ElementTree (conns )
90- periph = None
91-
92- num_periph_sig = 0
93-
94- for ref in conns_tree .iter ('peripheral_signal_ref' ):
95- num_periph_sig += 1
96- logging .debug ("\t \t %s - %s %s" , num_periph_sig , ref .tag , ref .attrib )
97- signal = ref .attrib .get ("signal" )
98- periph = ref .attrib .get ("peripheral" )
99- channel = ref .attrib .get ("channel" )
100-
101- if num_periph_sig > 1 :
102- logging .error (num_periph_sig )
103-
104- # handle unrouted_pin_function_ref case (disabled pin)
105- if periph is None :
106- continue
107-
108- pin = None
109-
110- for ref in conns_tree .iter ('assign' ):
111- logging .debug ("\t \t \t [ASSIGN] %s %s" , ref .tag , ref .attrib )
112- reg = ref .attrib .get ("register" )
113- reg_match = re .search (r"PORT([A-Z])_PCR(\d+)" , reg )
114-
115- # Only process PCR registers
116- if reg_match :
117- port = reg_match .group (1 ).lower ()
118- if len (reg_match .groups ()) == 2 :
119- pin = reg_match .group (2 ).lower ()
120- else :
121- pin = None
122- else :
123- continue
124-
125- logging .debug (ref .attrib )
126-
127- val = ref .attrib .get ("bit_field_value" )
128-
129- pin_data = PIN (PERIPH = periph ,
130- NAME_PART = name_part ,
131- SIGNAL = signal ,
132- PORT = port ,
133- PIN = int (pin ),
134- CH = channel ,
135- MUX_FUNC = int (val , 16 ))
136- logging .debug (pin_data )
137- self ._pins .append (pin_data )
308+ signal = SignalPin (pin )
309+ # Only add valid signal pins to list
310+ if signal .get_name () != '' :
311+ self ._pins [signal .get_name ()] = signal
138312
139313 def _write_pins (self , which_port , pins , file ):
140314 """
@@ -144,30 +318,30 @@ def _write_pins(self, which_port, pins, file):
144318 @param pins: list of pin mux options to write
145319 @param file: output file to write to
146320 """
147- port_pins = list (filter (lambda p : (p .PORT .lower () == which_port ), pins ))
321+ port_pins = list (filter (lambda p : (p .get_port () .lower () == which_port ), pins ))
148322
149323 if (len (port_pins )) == 0 :
150324 return
151325
152- port_pins .sort (key = lambda p : (p .PIN , p .MUX_FUNC ))
326+ port_pins .sort (key = lambda p : (p .get_pin () , p .get_mux () ))
153327
154328 seen_nodes = []
155329
156330 file .write (f"&port{ which_port } {{\n " )
157331 for pin_data in port_pins :
158- port_name = f"PT{ pin_data .PORT .upper ()} { pin_data .PIN } "
332+ port_name = f"PT{ pin_data .get_port () .upper ()} { pin_data .get_pin () } "
159333 # Special case handle GPIO so that it will be of the form:
160334 # PT[A-E][0-31]: GPIO[A-E]_PT[A-E][0-31]: ...
161335 #
162336 # eg:
163337 # PTA3: GPIOA_PTA3: gpioa_pta3 { .... };
164- if pin_data .PERIPH .startswith ("GPIO" ):
165- node = f"{ pin_data .PERIPH .lower ()} _{ port_name .lower ()} "
338+ if pin_data .get_periph () .startswith ("GPIO" ):
339+ node = f"{ pin_data .get_periph () .lower ()} _{ port_name .lower ()} "
166340 label = f"{ port_name } : { node .upper ()} "
167341 else :
168- label = f" { pin_data .NAME_PART } _ { port_name } "
342+ label = pin_data .get_name ()
169343 node = label .lower ()
170- k_port_pins_prop = f"< { pin_data .PIN } { pin_data .MUX_FUNC } >"
344+ k_port_pins_prop = f"< { pin_data .get_pin () } { pin_data .get_mux () } >"
171345
172346 if node in seen_nodes :
173347 continue
@@ -187,7 +361,11 @@ def write_pinctrl_defs(self, outputfile):
187361 can include this pinctrl dtsi file to access pin control defintions.
188362 @param outputfile: file to write output pinctrl defs to
189363 """
190- pcr_pins = list (filter (lambda p : (p .PERIPH not in ["FB" , "EZPORT" ]), self ._pins ))
364+ # Create list of all pin mux options
365+ pinmux_opts = []
366+ for pin in self ._pins .values ():
367+ pinmux_opts .extend (pin .get_mux_options ())
368+ pcr_pins = list (filter (lambda p : (p .get_periph () not in ["FB" , "EZPORT" ]), pinmux_opts ))
191369 file_header = ("/*\n "
192370 " * NOTE: Autogenerated file by kinetis_signal2dts.py\n "
193371 f" * for { self ._part_num } /signal_configuration.xml\n "
@@ -203,3 +381,4 @@ def write_pinctrl_defs(self, outputfile):
203381 self ._write_pins ('c' , pcr_pins , file )
204382 self ._write_pins ('d' , pcr_pins , file )
205383 self ._write_pins ('e' , pcr_pins , file )
384+
0 commit comments