22
22
import shutil
23
23
import inspect
24
24
import sys
25
+ from collections import namedtuple
25
26
from copy import copy
26
- from inspect import getmro
27
- from collections import namedtuple , Mapping
28
27
from future .utils import raise_from
29
28
from tools .resources import FileType
30
29
from tools .targets .LPC import patch
45
44
"Cortex-M4F" : ["M4" , "CORTEX_M" , "RTOS_M4_M7" , "LIKE_CORTEX_M4" , "CORTEX" ],
46
45
"Cortex-M7" : ["M7" , "CORTEX_M" , "RTOS_M4_M7" , "LIKE_CORTEX_M7" , "CORTEX" ],
47
46
"Cortex-M7F" : ["M7" , "CORTEX_M" , "RTOS_M4_M7" , "LIKE_CORTEX_M7" , "CORTEX" ],
48
- "Cortex-M7FD" : ["M7" , "CORTEX_M" , "RTOS_M4_M7" , "LIKE_CORTEX_M7" , "CORTEX" ],
47
+ "Cortex-M7FD" : ["M7" , "CORTEX_M" , "RTOS_M4_M7" , "LIKE_CORTEX_M7" ,
48
+ "CORTEX" ],
49
49
"Cortex-A9" : ["A9" , "CORTEX_A" , "LIKE_CORTEX_A9" , "CORTEX" ],
50
50
"Cortex-M23" : ["M23" , "CORTEX_M" , "LIKE_CORTEX_M23" , "CORTEX" ],
51
- "Cortex-M23-NS" : ["M23" , "M23_NS" , "CORTEX_M" , "LIKE_CORTEX_M23" , "CORTEX" ],
51
+ "Cortex-M23-NS" : ["M23" , "M23_NS" , "CORTEX_M" , "LIKE_CORTEX_M23" ,
52
+ "CORTEX" ],
52
53
"Cortex-M33" : ["M33" , "CORTEX_M" , "LIKE_CORTEX_M33" , "CORTEX" ],
53
- "Cortex-M33-NS" : ["M33" , "M33_NS" , "CORTEX_M" , "LIKE_CORTEX_M33" , "CORTEX" ],
54
+ "Cortex-M33-NS" : ["M33" , "M33_NS" , "CORTEX_M" , "LIKE_CORTEX_M33" ,
55
+ "CORTEX" ],
54
56
"Cortex-M33F" : ["M33" , "CORTEX_M" , "LIKE_CORTEX_M33" , "CORTEX" ],
55
- "Cortex-M33F-NS" : ["M33" , "M33_NS" , "CORTEX_M" , "LIKE_CORTEX_M33" , "CORTEX" ],
57
+ "Cortex-M33F-NS" : ["M33" , "M33_NS" , "CORTEX_M" , "LIKE_CORTEX_M33" ,
58
+ "CORTEX" ],
56
59
"Cortex-M33FE" : ["M33" , "CORTEX_M" , "LIKE_CORTEX_M33" , "CORTEX" ],
57
- "Cortex-M33FE-NS" : ["M33" , "M33_NS" , "CORTEX_M" , "LIKE_CORTEX_M33" , "CORTEX" ]
60
+ "Cortex-M33FE-NS" : ["M33" , "M33_NS" , "CORTEX_M" , "LIKE_CORTEX_M33" ,
61
+ "CORTEX" ]
58
62
}
59
63
60
64
CORE_ARCH = {
78
82
"Cortex-M33FE-NS" : 8 ,
79
83
}
80
84
81
- ################################################################################
85
+ ###############################################################################
82
86
# Generic Target class that reads and interprets the data in targets.json
83
87
88
+
84
89
class HookError (Exception ):
85
90
""" A simple class that represents all the exceptions associated with
86
91
hooking
87
92
"""
88
93
pass
89
94
95
+
90
96
CACHES = {}
97
+
98
+
91
99
def cached (func ):
92
100
"""A simple decorator used for automatically caching data returned by a
93
101
function
@@ -102,9 +110,15 @@ def wrapper(*args, **kwargs):
102
110
103
111
# Cumulative attributes can have values appended to them, so they
104
112
# need to be computed differently than regular attributes
105
- CUMULATIVE_ATTRIBUTES = ['extra_labels' , 'macros' , 'device_has' , 'features' , 'components' ]
106
113
107
- default_build_tools_metadata = {u'version' :0 , u'public' :False }
114
+
115
+ CUMULATIVE_ATTRIBUTES = [
116
+ 'extra_labels' , 'macros' , 'device_has' , 'features' , 'components'
117
+ ]
118
+
119
+
120
+ default_build_tools_metadata = {u'version' : 0 , u'public' : False }
121
+
108
122
109
123
def get_resolution_order (json_data , target_name , order , level = 0 ):
110
124
""" Return the order in which target descriptions are searched for
@@ -128,22 +142,29 @@ def get_resolution_order(json_data, target_name, order, level=0):
128
142
def target (name , json_data ):
129
143
"""Construct a target object"""
130
144
if name .startswith ("_" ):
131
- raise Exception ("Invalid target name '%s' specified, target name should not start with '_'" % name )
132
-
145
+ raise Exception (
146
+ "Invalid target name '%s' specified,"
147
+ " target name should not start with '_'" % name
148
+ )
133
149
try :
134
150
resolution_order = get_resolution_order (json_data , name , [])
135
151
except KeyError as exc :
136
152
raise_from (NotSupportedException (
137
153
"target {} has an incomplete target definition" .format (name )
138
154
), exc )
139
155
resolution_order_names = [tgt for tgt , _ in resolution_order ]
140
-
141
- return Target (name = name ,
142
- json_data = {key : value for key , value in json_data .items ()
143
- if key in resolution_order_names },
144
- resolution_order = resolution_order ,
145
- resolution_order_names = resolution_order_names ,
146
- build_tools_metadata = json_data .get ("__build_tools_metadata__" , default_build_tools_metadata ))
156
+ return Target (
157
+ name = name ,
158
+ json_data = {key : value for key , value in json_data .items ()
159
+ if key in resolution_order_names },
160
+ resolution_order = resolution_order ,
161
+ resolution_order_names = resolution_order_names ,
162
+ build_tools_metadata = json_data .get (
163
+ "__build_tools_metadata__" ,
164
+ default_build_tools_metadata
165
+ )
166
+ )
167
+
147
168
148
169
def generate_py_target (new_targets , name ):
149
170
"""Add one or more new target(s) represented as a Python dictionary
@@ -158,15 +179,21 @@ def generate_py_target(new_targets, name):
158
179
total_data = {}
159
180
total_data .update (new_targets )
160
181
total_data .update (base_targets )
161
-
162
182
return target (name , total_data )
163
183
164
- class Target (namedtuple ("Target" , "name json_data resolution_order resolution_order_names build_tools_metadata" )):
184
+
185
+ class Target (namedtuple (
186
+ "Target" ,
187
+ "name json_data resolution_order "
188
+ "resolution_order_names build_tools_metadata"
189
+ )):
165
190
"""An object to represent a Target (MCU/Board)"""
166
191
167
192
# Default location of the 'targets.json' file
168
193
__targets_json_location_default = os .path .join (
169
- os .path .dirname (os .path .abspath (__file__ )), '..' , '..' , 'targets' , 'targets.json' )
194
+ os .path .dirname (os .path .abspath (__file__ )),
195
+ '..' , '..' , 'targets' , 'targets.json'
196
+ )
170
197
171
198
# Current/new location of the 'targets.json' file
172
199
__targets_json_location = None
@@ -188,8 +215,10 @@ def get_json_target_data():
188
215
for extra_target in Target .__extra_target_json_files :
189
216
for k , v in json_file_to_dict (extra_target ).items ():
190
217
if k in targets :
191
- print ('WARNING: Custom target "%s" cannot replace existing '
192
- 'target.' % k )
218
+ print (
219
+ 'WARNING: Custom target "%s" cannot replace existing '
220
+ 'target.' % k
221
+ )
193
222
else :
194
223
targets [k ] = v
195
224
targets [k ]["_from_file" ] = extra_target
@@ -206,8 +235,10 @@ def add_extra_targets(source_dir):
206
235
@staticmethod
207
236
def set_targets_json_location (location = None ):
208
237
"""Set the location of the targets.json file"""
209
- Target .__targets_json_location = (location or
210
- Target .__targets_json_location_default )
238
+ Target .__targets_json_location = (
239
+ location or
240
+ Target .__targets_json_location_default
241
+ )
211
242
Target .__extra_target_json_files = []
212
243
# Invalidate caches, since the location of the JSON file changed
213
244
CACHES .clear ()
@@ -229,8 +260,10 @@ def __add_paths_to_progen(data):
229
260
if isinstance (val , dict ):
230
261
out [key ] = Target .__add_paths_to_progen (val )
231
262
elif key == "template" :
232
- out [key ] = [os .path .join (os .path .dirname (__file__ ), 'export' , v )
233
- for v in val ]
263
+ out [key ] = [
264
+ os .path .join (os .path .dirname (__file__ ), 'export' , v )
265
+ for v in val
266
+ ]
234
267
else :
235
268
out [key ] = val
236
269
return out
@@ -301,14 +334,13 @@ def __getattr_helper(self, attrname):
301
334
return self .__getattr_cumulative (attrname )
302
335
else :
303
336
tdata = self .json_data
304
- starting_value = None
305
337
for tgt in self .resolution_order :
306
338
data = tdata [tgt [0 ]]
307
339
try :
308
340
return data [attrname ]
309
341
except KeyError :
310
342
pass
311
- else : # Attribute not found
343
+ else : # Attribute not found
312
344
raise AttributeError (
313
345
"Attribute '%s' not found in target '%s'"
314
346
% (attrname , self .name ))
@@ -328,7 +360,6 @@ def get_target(target_name):
328
360
""" Return the target instance starting from the target name """
329
361
return target (target_name , Target .get_json_target_data ())
330
362
331
-
332
363
@property
333
364
def program_cycle_s (self ):
334
365
"""Special override for program_cycle_s as it's default value depends
@@ -398,19 +429,20 @@ def get_post_build_hook(self, toolchain_labels):
398
429
("Static function '%s' " % function_name ) +
399
430
("required by '%s' " % hook_data ["function" ]) +
400
431
("in target '%s' " % self .name ) +
401
- ("not found in class '%s'" % class_name ))
432
+ ("not found in class '%s'" % class_name ))
402
433
# Check if the hook specification also has toolchain restrictions
403
434
toolchain_restrictions = set (hook_data .get ("toolchains" , []))
404
435
if toolchain_restrictions and \
405
436
not set (toolchain_labels ).intersection (toolchain_restrictions ):
406
437
return None
407
438
return getattr (cls , function_name )
408
439
409
- ################################################################################
440
+ ###############################################################################
410
441
# Target specific code goes in this section
411
442
# This code can be invoked from the target description using the
412
443
# "post_binary_hook" key
413
444
445
+
414
446
class LPCTargetCode (object ):
415
447
"""General LPC Target patching code"""
416
448
@staticmethod
@@ -419,6 +451,7 @@ def lpc_patch(t_self, resources, elf, binf):
419
451
t_self .notify .debug ("LPC Patch: %s" % os .path .split (binf )[1 ])
420
452
patch (binf )
421
453
454
+
422
455
class LPC4088Code (object ):
423
456
"""Code specific to the LPC4088"""
424
457
@staticmethod
@@ -450,18 +483,22 @@ def binary_hook(t_self, resources, elf, binf):
450
483
# file to 'binf'
451
484
shutil .rmtree (binf , True )
452
485
os .rename (binf + '.temp' , binf )
453
- t_self .notify .debug ("Generated custom binary file (internal flash + SPIFI)" )
486
+ t_self .notify .debug (
487
+ "Generated custom binary file (internal flash + SPIFI)"
488
+ )
454
489
LPCTargetCode .lpc_patch (t_self , resources , elf , binf )
455
490
491
+
456
492
class TEENSY3_1Code (object ):
457
493
"""Hooks for the TEENSY3.1"""
458
494
@staticmethod
459
495
def binary_hook (t_self , resources , elf , binf ):
460
496
"""Hook that is run after elf is generated"""
461
- # This function is referenced by old versions of targets.json and should
462
- # be kept for backwards compatibility.
497
+ # This function is referenced by old versions of targets.json and
498
+ # should be kept for backwards compatibility.
463
499
pass
464
500
501
+
465
502
class MTSCode (object ):
466
503
"""Generic MTS code"""
467
504
@staticmethod
@@ -506,15 +543,16 @@ def combine_bins_mtb_mts_dragonfly(t_self, resources, elf, binf):
506
543
"""A hook for the MTB MTS Dragonfly"""
507
544
MTSCode ._combine_bins_helper ("MTB_MTS_DRAGONFLY" , binf )
508
545
546
+
509
547
class MCU_NRF51Code (object ):
510
548
"""NRF51 Hooks"""
511
549
@staticmethod
512
550
def binary_hook (t_self , resources , _ , binf ):
513
551
"""Hook that merges the soft device with the bin file"""
514
552
# Scan to find the actual paths of soft device
515
553
sdf = None
516
- for softdevice_and_offset_entry \
517
- in t_self . target . EXPECTED_SOFTDEVICES_WITH_OFFSETS :
554
+ sd_with_offsets = t_self . target . EXPECTED_SOFTDEVICES_WITH_OFFSETS
555
+ for softdevice_and_offset_entry in sd_with_offsets :
518
556
for hexf in resources .get_file_paths (FileType .HEX ):
519
557
if hexf .find (softdevice_and_offset_entry ['name' ]) != - 1 :
520
558
t_self .notify .debug ("SoftDevice file found %s."
@@ -536,8 +574,10 @@ def binary_hook(t_self, resources, _, binf):
536
574
if t_self .target .MERGE_BOOTLOADER is True :
537
575
for hexf in resources .get_file_paths (FileType .HEX ):
538
576
if hexf .find (t_self .target .OVERRIDE_BOOTLOADER_FILENAME ) != - 1 :
539
- t_self .notify .debug ("Bootloader file found %s."
540
- % t_self .target .OVERRIDE_BOOTLOADER_FILENAME )
577
+ t_self .notify .debug (
578
+ "Bootloader file found %s."
579
+ % t_self .target .OVERRIDE_BOOTLOADER_FILENAME
580
+ )
541
581
blf = hexf
542
582
break
543
583
elif hexf .find (softdevice_and_offset_entry ['boot' ]) != - 1 :
@@ -571,20 +611,23 @@ def binary_hook(t_self, resources, _, binf):
571
611
with open (binf .replace (".bin" , ".hex" ), "w" ) as fileout :
572
612
binh .write_hex_file (fileout , write_start_addr = False )
573
613
614
+
574
615
class NCS36510TargetCode :
575
616
@staticmethod
576
617
def ncs36510_addfib (t_self , resources , elf , binf ):
577
618
from tools .targets .NCS import add_fib_at_start
578
619
print ("binf " , binf )
579
620
add_fib_at_start (binf [:- 4 ])
580
621
622
+
581
623
class RTL8195ACode :
582
624
"""RTL8195A Hooks"""
583
625
@staticmethod
584
626
def binary_hook (t_self , resources , elf , binf ):
585
627
from tools .targets .REALTEK_RTL8195AM import rtl8195a_elf2bin
586
628
rtl8195a_elf2bin (t_self , elf , binf )
587
629
630
+
588
631
class PSOC6Code :
589
632
@staticmethod
590
633
def complete (t_self , resources , elf , binf ):
@@ -598,19 +641,27 @@ def complete(t_self, resources, elf, binf):
598
641
else :
599
642
psoc6_complete (t_self , elf , binf )
600
643
644
+
601
645
class LPC55S69Code :
602
646
"""LPC55S69 Hooks"""
603
647
@staticmethod
604
648
def binary_hook (t_self , resources , elf , binf ):
605
649
from tools .targets .LPC55S69 import lpc55s69_complete
606
650
configured_secure_image_filename = t_self .target .secure_image_filename
607
- secure_bin = find_secure_image (t_self .notify , resources , binf , configured_secure_image_filename , FileType .BIN )
651
+ secure_bin = find_secure_image (
652
+ t_self .notify ,
653
+ resources ,
654
+ binf ,
655
+ configured_secure_image_filename ,
656
+ FileType .BIN
657
+ )
608
658
lpc55s69_complete (t_self , binf , secure_bin )
609
659
610
- ################################################################################
611
660
612
- # Instantiate all public targets
661
+ # End Target specific section
662
+ ###############################################################################
613
663
def update_target_data ():
664
+ """Instantiate all public targets"""
614
665
TARGETS [:] = [Target .get_target (tgt ) for tgt , obj
615
666
in Target .get_json_target_data ().items ()
616
667
if obj .get ("public" , True )]
@@ -619,6 +670,7 @@ def update_target_data():
619
670
TARGET_MAP .update (dict ([(tgt .name , tgt ) for tgt in TARGETS ]))
620
671
TARGET_NAMES [:] = TARGET_MAP .keys ()
621
672
673
+
622
674
TARGETS = []
623
675
TARGET_MAP = dict ()
624
676
TARGET_NAMES = []
@@ -628,6 +680,7 @@ def update_target_data():
628
680
# Some targets with different name have the same exporters
629
681
EXPORT_MAP = {}
630
682
683
+
631
684
# Detection APIs
632
685
def get_target_detect_codes ():
633
686
""" Returns dictionary mapping detect_code -> platform_name
@@ -638,6 +691,7 @@ def get_target_detect_codes():
638
691
result [detect_code ] = tgt .name
639
692
return result
640
693
694
+
641
695
def set_targets_json_location (location = None ):
642
696
"""Sets the location of the JSON file that contains the targets"""
643
697
# First instruct Target about the new location
@@ -647,4 +701,3 @@ def set_targets_json_location(location=None):
647
701
# instead. This ensures compatibility with code that does
648
702
# "from tools.targets import TARGET_NAMES"
649
703
update_target_data ()
650
-
0 commit comments