1919import tempfile
2020from types import ListType
2121from 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
2424from time import time
25+ from intelhex import IntelHex
2526
2627from tools .utils import mkdir , run_cmd , run_cmd_ext , NotSupportedException ,\
27- ToolException , InvalidReleaseTargetException
28+ ToolException , InvalidReleaseTargetException , intelhex_offset
2829from tools .paths import MBED_CMSIS_PATH , MBED_TARGETS_PATH , MBED_LIBRARIES ,\
2930 MBED_HEADER , MBED_DRIVERS , MBED_PLATFORM , MBED_HAL , MBED_CONFIG_FILE ,\
3031 MBED_LIBRARIES_DRIVERS , MBED_LIBRARIES_PLATFORM , MBED_LIBRARIES_HAL ,\
@@ -274,6 +275,29 @@ def get_mbed_official_release(version):
274275
275276 return mbed_official_release
276277
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+
277301
278302def prepare_toolchain (src_paths , target , toolchain_name ,
279303 macros = None , clean = False , jobs = 1 ,
@@ -307,14 +331,16 @@ def prepare_toolchain(src_paths, target, toolchain_name,
307331 # If the configuration object was not yet created, create it now
308332 config = config or Config (target , src_paths , app_config = app_config )
309333 target = config .target
310-
311- # Toolchain instance
312334 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 ]
316336 except KeyError :
317337 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 )
318344
319345 toolchain .config = config
320346 toolchain .jobs = jobs
@@ -323,6 +349,41 @@ def prepare_toolchain(src_paths, target, toolchain_name,
323349
324350 return toolchain
325351
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+
326387def scan_resources (src_paths , toolchain , dependencies_paths = None ,
327388 inc_dirs = None , base_path = None ):
328389 """ Scan resources using initialized toolcain
@@ -453,7 +514,15 @@ def build_project(src_paths, build_path, target, toolchain_name,
453514 resources .objects .extend (objects )
454515
455516 # 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 )
457526
458527 memap_instance = getattr (toolchain , 'memap_instance' , None )
459528 memap_table = ''
0 commit comments