19
19
import tempfile
20
20
from types import ListType
21
21
from shutil import rmtree
22
- from os .path import join , exists , dirname , basename , abspath , normpath
23
- from os import linesep , remove
22
+ from os .path import join , exists , dirname , basename , abspath , normpath , splitext
23
+ from os import linesep , remove , makedirs
24
24
from time import time
25
+ from intelhex import IntelHex
25
26
26
27
from tools .utils import mkdir , run_cmd , run_cmd_ext , NotSupportedException ,\
27
- ToolException , InvalidReleaseTargetException
28
+ ToolException , InvalidReleaseTargetException , intelhex_offset
28
29
from tools .paths import MBED_CMSIS_PATH , MBED_TARGETS_PATH , MBED_LIBRARIES ,\
29
30
MBED_HEADER , MBED_DRIVERS , MBED_PLATFORM , MBED_HAL , MBED_CONFIG_FILE ,\
30
31
MBED_LIBRARIES_DRIVERS , MBED_LIBRARIES_PLATFORM , MBED_LIBRARIES_HAL ,\
@@ -274,6 +275,29 @@ def get_mbed_official_release(version):
274
275
275
276
return mbed_official_release
276
277
278
+ def add_regions_to_profile (profile , config , toolchain_class ):
279
+ """Add regions to the build profile, if there are any.
280
+
281
+ Positional Arguments:
282
+ profile - the profile to update
283
+ config - the configuration object that owns the region
284
+ toolchain_class - the class of the toolchain being used
285
+ """
286
+ regions = list (config .regions )
287
+ for region in regions :
288
+ for define in [(region .name .upper () + "_ADDR" , region .start ),
289
+ (region .name .upper () + "_SIZE" , region .size )]:
290
+ profile ["common" ].append ("-D%s=0x%x" % define )
291
+ active_region = [r for r in regions if r .active ][0 ]
292
+ for define in [("MBED_APP_START" , active_region .start ),
293
+ ("MBED_APP_SIZE" , active_region .size )]:
294
+ profile ["ld" ].append (toolchain_class .make_ld_define (* define ))
295
+
296
+ print ("Using regions in this build:" )
297
+ for region in regions :
298
+ print (" Region %s size 0x%x, offset 0x%x"
299
+ % (region .name , region .size , region .start ))
300
+
277
301
278
302
def prepare_toolchain (src_paths , target , toolchain_name ,
279
303
macros = None , clean = False , jobs = 1 ,
@@ -307,14 +331,16 @@ def prepare_toolchain(src_paths, target, toolchain_name,
307
331
# If the configuration object was not yet created, create it now
308
332
config = config or Config (target , src_paths , app_config = app_config )
309
333
target = config .target
310
-
311
- # Toolchain instance
312
334
try :
313
- toolchain = TOOLCHAIN_CLASSES [toolchain_name ](
314
- target , notify , macros , silent ,
315
- extra_verbose = extra_verbose , build_profile = build_profile )
335
+ cur_tc = TOOLCHAIN_CLASSES [toolchain_name ]
316
336
except KeyError :
317
337
raise KeyError ("Toolchain %s not supported" % toolchain_name )
338
+ if config .has_regions :
339
+ add_regions_to_profile (build_profile , config , cur_tc )
340
+
341
+ # Toolchain instance
342
+ toolchain = cur_tc (target , notify , macros , silent ,
343
+ extra_verbose = extra_verbose , build_profile = build_profile )
318
344
319
345
toolchain .config = config
320
346
toolchain .jobs = jobs
@@ -323,6 +349,41 @@ def prepare_toolchain(src_paths, target, toolchain_name,
323
349
324
350
return toolchain
325
351
352
+ def merge_region_list (region_list , destination , padding = b'\xFF ' ):
353
+ """Merege the region_list into a single image
354
+
355
+ Positional Arguments:
356
+ region_list - list of regions, which should contain filenames
357
+ destination - file name to write all regions to
358
+ padding - bytes to fill gapps with
359
+ """
360
+ merged = IntelHex ()
361
+
362
+ print ("Merging Regions:" )
363
+
364
+ for region in region_list :
365
+ if region .active and not region .filename :
366
+ raise ToolException ("Active region has no contents: No file found." )
367
+ if region .filename :
368
+ print (" Filling region %s with %s" % (region .name , region .filename ))
369
+ part = intelhex_offset (region .filename , offset = region .start )
370
+ part_size = (part .maxaddr () - part .minaddr ()) + 1
371
+ if part_size > region .size :
372
+ raise ToolException ("Contents of region %s does not fit"
373
+ % region .name )
374
+ merged .merge (part )
375
+ pad_size = region .size - part_size
376
+ if pad_size > 0 and region != region_list [- 1 ]:
377
+ print (" Padding region %s with 0x%x bytes" % (region .name , pad_size ))
378
+ merged .puts (merged .maxaddr () + 1 , padding * pad_size )
379
+
380
+ if not exists (dirname (destination )):
381
+ makedirs (dirname (destination ))
382
+ print ("Space used after regions merged: 0x%x" %
383
+ (merged .maxaddr () - merged .minaddr () + 1 ))
384
+ with open (destination , "wb+" ) as output :
385
+ merged .tofile (output , format = 'bin' )
386
+
326
387
def scan_resources (src_paths , toolchain , dependencies_paths = None ,
327
388
inc_dirs = None , base_path = None ):
328
389
""" Scan resources using initialized toolcain
@@ -453,7 +514,15 @@ def build_project(src_paths, build_path, target, toolchain_name,
453
514
resources .objects .extend (objects )
454
515
455
516
# Link Program
456
- res , _ = toolchain .link_program (resources , build_path , name )
517
+ if toolchain .config .has_regions :
518
+ res , _ = toolchain .link_program (resources , build_path , name + "_application" )
519
+ region_list = list (toolchain .config .regions )
520
+ region_list = [r ._replace (filename = res ) if r .active else r
521
+ for r in region_list ]
522
+ res = join (build_path , name ) + ".bin"
523
+ merge_region_list (region_list , res )
524
+ else :
525
+ res , _ = toolchain .link_program (resources , build_path , name )
457
526
458
527
memap_instance = getattr (toolchain , 'memap_instance' , None )
459
528
memap_table = ''
0 commit comments