diff --git a/tools/config/__init__.py b/tools/config/__init__.py index d3aa10c3b01..3f265f05afe 100644 --- a/tools/config/__init__.py +++ b/tools/config/__init__.py @@ -362,7 +362,8 @@ class Config(object): "artifact_name": str} } - __unused_overrides = set(["target.bootloader_img", "target.restrict_size"]) + __unused_overrides = set(["target.bootloader_img", "target.restrict_size", + "target.mbed_app_start", "target.mbed_app_size"]) # Allowed features in configurations __allowed_features = [ @@ -485,7 +486,9 @@ def has_regions(self): target_overrides = self.app_config_data['target_overrides'].get( self.target.name, {}) return ('target.bootloader_img' in target_overrides or - 'target.restrict_size' in target_overrides) + 'target.restrict_size' in target_overrides or + 'target.mbed_app_start' in target_overrides or + 'target.mbed_app_size' in target_overrides) else: return False @@ -495,15 +498,37 @@ def regions(self): if not self.target.bootloader_supported: raise ConfigException("Bootloader not supported on this target.") cmsis_part = Cache(False, False).index[self.target.device_name] - start = 0 target_overrides = self.app_config_data['target_overrides'].get( self.target.name, {}) + if (('target.bootloader_img' in target_overrides or + 'target.restrict_size' in target_overrides) and + ('target.mbed_app_start' in target_overrides or + 'target.mbed_app_size' in target_overrides)): + raise ConfigException( + "target.bootloader_img and target.restirct_size are " + "incompatible with target.mbed_app_start and " + "target.mbed_app_size") try: rom_size = int(cmsis_part['memory']['IROM1']['size'], 0) rom_start = int(cmsis_part['memory']['IROM1']['start'], 0) except KeyError: raise ConfigException("Not enough information in CMSIS packs to " "build a bootloader project") + if ('target.bootloader_img' in target_overrides or + 'target.restrict_size' in target_overrides): + return self._generate_booloader_build(target_overrides, + rom_size, rom_size) + elif ('target.mbed_app_start' in target_overrides or + 'target.mbed_app_size' in target_overrides): + return self._generate_linker_overrides(target_overrides, + rom_start, rom_size) + else: + raise ConfigException( + "Bootloader build requested but no bootlader configuration") + + @staticmethod + def _generate_booloader_build(target_overrides, rom_start, rom_size): + start = 0 if 'target.bootloader_img' in target_overrides: filename = target_overrides['target.bootloader_img'] if not exists(filename): @@ -534,6 +559,22 @@ def report(self): return {'app_config': self.app_config_location, 'library_configs': map(relpath, self.processed_configs.keys())} + @staticmethod + def _generate_linker_overrides(target_overrides, rom_start, rom_size): + if 'target.mbed_app_start' in target_overrides: + start = int(target_overrides['target.mbed_app_start'], 0) + else: + start = rom_start + if 'target.mbed_app_size' in target_overrides: + size = int(target_overrides['target.mbed_app_size'], 0) + else: + size = (rom_size + rom_start) - start + if start < rom_start: + raise ConfigException("Application starts before ROM") + if size + start > rom_size + rom_start: + raise ConfigException("Application ends after ROM") + yield Region("application", start, size, True, None) + def _process_config_and_overrides(self, data, params, unit_name, unit_kind): """Process "config_parameters" and "target_config_overrides" into a given dictionary diff --git a/tools/test/toolchains/api.py b/tools/test/toolchains/api.py index 01a684fae8a..b836cbda9ef 100644 --- a/tools/test/toolchains/api.py +++ b/tools/test/toolchains/api.py @@ -42,6 +42,7 @@ def test_toolchain_profile_c(profile, source_file): toolchain = tc_class(TARGET_MAP["K64F"], build_profile=profile) toolchain.inc_md5 = "" toolchain.build_dir = "" + toolchain.config = MagicMock(app_config_locaiton=None) compile_command = toolchain.compile_command(to_compile, to_compile + ".o", []) for parameter in profile['c'] + profile['common']: @@ -67,6 +68,7 @@ def test_toolchain_profile_cpp(profile, source_file): toolchain = tc_class(TARGET_MAP["K64F"], build_profile=profile) toolchain.inc_md5 = "" toolchain.build_dir = "" + toolchain.config = MagicMock(app_config_locaiton=None) compile_command = toolchain.compile_command(to_compile, to_compile + ".o", []) for parameter in profile['cxx'] + profile['common']: diff --git a/tools/toolchains/__init__.py b/tools/toolchains/__init__.py index d63dc5f2ec3..98be3cabec5 100644 --- a/tools/toolchains/__init__.py +++ b/tools/toolchains/__init__.py @@ -909,7 +909,9 @@ def compile_command(self, source, object, includes): deps = self.parse_dependencies(dep_path) if (exists(dep_path)) else [] except IOError, IndexError: deps = [] - if len(deps) == 0 or self.need_update(object, deps): + config_file = ([self.config.app_config_location] + if self.config.app_config_location else []) + if len(deps) == 0 or self.need_update(object, deps + config_file): if ext == '.cpp' or self.COMPILE_C_AS_CPP: return self.compile_cpp(source, object, includes) else: @@ -1008,7 +1010,10 @@ def link_program(self, r, tmp_path, name): map = join(tmp_path, name + '.map') r.objects = sorted(set(r.objects)) - if self.need_update(elf, r.objects + r.libraries + [r.linker_script]): + config_file = ([self.config.app_config_location] + if self.config.app_config_location else []) + if self.need_update(elf, r.objects + r.libraries + [r.linker_script] + + config_file): needed_update = True self.progress("link", name) self.link(elf, r.objects, r.libraries, r.lib_dirs, r.linker_script)