Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
arm.py
00001 """ 00002 mbed SDK 00003 Copyright (c) 2011-2013 ARM Limited 00004 00005 Licensed under the Apache License, Version 2.0 (the "License"); 00006 you may not use this file except in compliance with the License. 00007 You may obtain a copy of the License at 00008 00009 http://www.apache.org/licenses/LICENSE-2.0 00010 00011 Unless required by applicable law or agreed to in writing, software 00012 distributed under the License is distributed on an "AS IS" BASIS, 00013 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00014 See the License for the specific language governing permissions and 00015 limitations under the License. 00016 """ 00017 from __future__ import print_function, absolute_import 00018 from builtins import str 00019 00020 import re 00021 from copy import copy 00022 from os.path import join, dirname, splitext, basename, exists, relpath, isfile 00023 from os import makedirs, write, curdir, remove 00024 from tempfile import mkstemp 00025 from shutil import rmtree 00026 00027 from tools.toolchains import mbedToolchain, TOOLCHAIN_PATHS 00028 from tools.hooks import hook_tool 00029 from tools.utils import mkdir, NotSupportedException 00030 00031 class ARM(mbedToolchain): 00032 LINKER_EXT = '.sct' 00033 LIBRARY_EXT = '.ar' 00034 00035 STD_LIB_NAME = "%s.ar" 00036 DIAGNOSTIC_PATTERN = re.compile('"(?P<file>[^"]+)", line (?P<line>\d+)( \(column (?P<column>\d+)\)|): (?P<severity>Warning|Error|Fatal error): (?P<message>.+)') 00037 INDEX_PATTERN = re.compile('(?P<col>\s*)\^') 00038 DEP_PATTERN = re.compile('\S+:\s(?P<file>.+)\n') 00039 SHEBANG = "#! armcc -E" 00040 SUPPORTED_CORES = ["Cortex-M0", "Cortex-M0+", "Cortex-M3", "Cortex-M4", 00041 "Cortex-M4F", "Cortex-M7", "Cortex-M7F", "Cortex-M7FD", "Cortex-A9"] 00042 00043 @staticmethod 00044 def check_executable(): 00045 """Returns True if the executable (armcc) location specified by the 00046 user exists OR the executable can be found on the PATH. 00047 Returns False otherwise.""" 00048 return mbedToolchain.generic_check_executable("ARM", 'armcc', 2, 'bin') 00049 00050 def __init__(self, target, notify=None, macros=None, 00051 build_profile=None, build_dir=None): 00052 mbedToolchain.__init__( 00053 self, target, notify, macros, build_dir=build_dir, 00054 build_profile=build_profile) 00055 if target.core not in self.SUPPORTED_CORES: 00056 raise NotSupportedException( 00057 "this compiler does not support the core %s" % target.core) 00058 00059 if getattr(target, "default_lib", "std") == "small": 00060 if "-DMBED_RTOS_SINGLE_THREAD" not in self.flags['common']: 00061 self.flags['common'].append("-DMBED_RTOS_SINGLE_THREAD") 00062 if "--library_type=microlib" not in self.flags['ld']: 00063 self.flags['ld'].append("--library_type=microlib") 00064 00065 if target.core == "Cortex-M0+": 00066 cpu = "Cortex-M0" 00067 elif target.core == "Cortex-M4F": 00068 cpu = "Cortex-M4.fp" 00069 elif target.core == "Cortex-M7FD": 00070 cpu = "Cortex-M7.fp.dp" 00071 elif target.core == "Cortex-M7F": 00072 cpu = "Cortex-M7.fp.sp" 00073 else: 00074 cpu = target.core 00075 00076 ARM_BIN = join(TOOLCHAIN_PATHS['ARM'], "bin") 00077 ARM_INC = join(TOOLCHAIN_PATHS['ARM'], "include") 00078 00079 main_cc = join(ARM_BIN, "armcc") 00080 00081 self.flags['common'] += ["--cpu=%s" % cpu] 00082 00083 self.asm = [main_cc] + self.flags['common'] + self.flags['asm'] 00084 self.cc = [main_cc] + self.flags['common'] + self.flags['c'] 00085 self.cppc = [main_cc] + self.flags['common'] + self.flags['c'] + self.flags['cxx'] 00086 00087 self.ld = [join(ARM_BIN, "armlink")] + self.flags['ld'] 00088 00089 self.ar = join(ARM_BIN, "armar") 00090 self.elf2bin = join(ARM_BIN, "fromelf") 00091 00092 self.SHEBANG += " --cpu=%s" % cpu 00093 00094 def _get_toolchain_labels(self): 00095 if getattr(self.target, "default_lib", "std") == "small": 00096 return ["ARM", "ARM_MICRO"] 00097 else: 00098 return ["ARM", "ARM_STD"] 00099 00100 def parse_dependencies(self, dep_path): 00101 dependencies = [] 00102 for line in open(dep_path).readlines(): 00103 match = ARM.DEP_PATTERN.match(line) 00104 if match is not None: 00105 #we need to append chroot, because when the .d files are generated the compiler is chrooted 00106 dependencies.append((self.CHROOT if self.CHROOT else '') + match.group('file')) 00107 return dependencies 00108 00109 def parse_output(self, output): 00110 msg = None 00111 for line in output.splitlines(): 00112 match = ARM.DIAGNOSTIC_PATTERN.match(line) 00113 if match is not None: 00114 if msg is not None: 00115 self.notify.cc_info(msg) 00116 msg = None 00117 msg = { 00118 'severity': match.group('severity').lower(), 00119 'file': match.group('file'), 00120 'line': match.group('line'), 00121 'col': match.group('column') if match.group('column') else 0, 00122 'message': match.group('message'), 00123 'text': '', 00124 'target_name': self.target.name, 00125 'toolchain_name': self.name 00126 } 00127 elif msg is not None: 00128 # Determine the warning/error column by calculating the ^ position 00129 match = ARM.INDEX_PATTERN.match(line) 00130 if match is not None: 00131 msg['col'] = len(match.group('col')) 00132 self.notify.cc_info(msg) 00133 msg = None 00134 else: 00135 msg['text'] += line+"\n" 00136 00137 if msg is not None: 00138 self.notify.cc_info(msg) 00139 00140 def get_dep_option(self, object): 00141 base, _ = splitext(object) 00142 dep_path = base + '.d' 00143 return ["--depend", dep_path] 00144 00145 def get_config_option(self, config_header): 00146 return ['--preinclude=' + config_header] 00147 00148 def get_compile_options(self, defines, includes, for_asm=False): 00149 opts = ['-D%s' % d for d in defines] 00150 if for_asm: 00151 return opts 00152 if self.RESPONSE_FILES: 00153 opts += ['--via', self.get_inc_file(includes)] 00154 else: 00155 opts += ["-I%s" % i for i in includes] 00156 00157 config_header = self.get_config_header() 00158 if config_header is not None: 00159 opts = opts + self.get_config_option(config_header) 00160 return opts 00161 00162 @hook_tool 00163 def assemble(self, source, object, includes): 00164 # Preprocess first, then assemble 00165 dir = join(dirname(object), '.temp') 00166 mkdir(dir) 00167 tempfile = join(dir, basename(object) + '.E.s') 00168 00169 # Build preprocess assemble command 00170 cmd_pre = copy(self.asm) 00171 cmd_pre.extend(self.get_compile_options( 00172 self.get_symbols(True), includes, True)) 00173 cmd_pre.extend(["-E", "-o", tempfile, source]) 00174 00175 # Build main assemble command 00176 cmd = self.asm + ["-o", object, tempfile] 00177 00178 # Call cmdline hook 00179 cmd_pre = self.hook.get_cmdline_assembler(cmd_pre) 00180 cmd = self.hook.get_cmdline_assembler(cmd) 00181 00182 # Return command array, don't execute 00183 return [cmd_pre, cmd] 00184 00185 @hook_tool 00186 def compile(self, cc, source, object, includes): 00187 # Build compile command 00188 cmd = cc + self.get_compile_options(self.get_symbols(), includes) 00189 00190 cmd.extend(self.get_dep_option(object)) 00191 00192 cmd.extend(["-o", object, source]) 00193 00194 # Call cmdline hook 00195 cmd = self.hook.get_cmdline_compiler(cmd) 00196 00197 return [cmd] 00198 00199 def compile_c(self, source, object, includes): 00200 return self.compile(self.cc, source, object, includes) 00201 00202 def compile_cpp(self, source, object, includes): 00203 return self.compile(self.cppc, source, object, includes) 00204 00205 def correct_scatter_shebang(self, scatter_file, base_path=curdir): 00206 """Correct the shebang at the top of a scatter file. 00207 00208 Positional arguments: 00209 scatter_file -- the scatter file to correct 00210 00211 Return: 00212 The location of the correct scatter file 00213 00214 Side Effects: 00215 This method MAY write a new scatter file to disk 00216 """ 00217 with open(scatter_file, "r") as input: 00218 lines = input.readlines() 00219 if (lines[0].startswith(self.SHEBANG) or 00220 not lines[0].startswith("#!")): 00221 return scatter_file 00222 else: 00223 new_scatter = join(self.build_dir, ".link_script.sct") 00224 self.SHEBANG += " -I %s" % relpath(dirname(scatter_file), 00225 base_path) 00226 if self.need_update(new_scatter, [scatter_file]): 00227 with open(new_scatter, "w") as out: 00228 out.write(self.SHEBANG) 00229 out.write("\n") 00230 out.write("".join(lines[1:])) 00231 00232 return new_scatter 00233 00234 @hook_tool 00235 def link(self, output, objects, libraries, lib_dirs, scatter_file): 00236 base, _ = splitext(output) 00237 map_file = base + ".map" 00238 args = ["-o", output, "--info=totals", "--map", "--list=%s" % map_file] 00239 args.extend(objects) 00240 args.extend(libraries) 00241 if lib_dirs: 00242 args.extend(["--userlibpath", ",".join(lib_dirs)]) 00243 if scatter_file: 00244 new_scatter = self.correct_scatter_shebang(scatter_file) 00245 args.extend(["--scatter", new_scatter]) 00246 00247 cmd_pre = self.ld + args 00248 cmd = self.hook.get_cmdline_linker(cmd_pre) 00249 00250 if self.RESPONSE_FILES: 00251 cmd_linker = cmd[0] 00252 link_files = self.get_link_file(cmd[1:]) 00253 cmd = [cmd_linker, '--via', link_files] 00254 00255 self.notify.cc_verbose("Link: %s" % ' '.join(cmd)) 00256 self.default_cmd(cmd) 00257 00258 @hook_tool 00259 def archive(self, objects, lib_path): 00260 if self.RESPONSE_FILES: 00261 param = ['--via', self.get_arch_file(objects)] 00262 else: 00263 param = objects 00264 self.default_cmd([self.ar, '-r', lib_path] + param) 00265 00266 @hook_tool 00267 def binary(self, resources, elf, bin): 00268 _, fmt = splitext(bin) 00269 # On .hex format, combine multiple .hex files (for multiple load regions) into one 00270 bin_arg = {".bin": "--bin", ".hex": "--i32combined"}[fmt] 00271 cmd = [self.elf2bin, bin_arg, '-o', bin, elf] 00272 cmd = self.hook.get_cmdline_binary(cmd) 00273 00274 # remove target binary file/path 00275 if exists(bin): 00276 if isfile(bin): 00277 remove(bin) 00278 else: 00279 rmtree(bin) 00280 00281 self.notify.cc_verbose("FromELF: %s" % ' '.join(cmd)) 00282 self.default_cmd(cmd) 00283 00284 @staticmethod 00285 def name_mangle(name): 00286 return "_Z%i%sv" % (len(name), name) 00287 00288 @staticmethod 00289 def make_ld_define(name, value): 00290 return "--predefine=\"-D%s=0x%x\"" % (name, value) 00291 00292 @staticmethod 00293 def redirect_symbol(source, sync, build_dir): 00294 if not exists(build_dir): 00295 makedirs(build_dir) 00296 handle, filename = mkstemp(prefix=".redirect-symbol.", dir=build_dir) 00297 write(handle, "RESOLVE %s AS %s\n" % (source, sync)) 00298 return "--edit=%s" % filename 00299 00300 00301 class ARM_STD(ARM): 00302 def __init__(self, target, notify=None, macros=None, 00303 build_profile=None, build_dir=None): 00304 ARM.__init__(self, target, notify, macros, build_dir=build_dir, 00305 build_profile=build_profile) 00306 if not set(("ARM", "uARM")).intersection(set(target.supported_toolchains)): 00307 raise NotSupportedException("ARM/uARM compiler support is required for ARM build") 00308 00309 00310 class ARM_MICRO(ARM): 00311 PATCHED_LIBRARY = False 00312 def __init__(self, target, notify=None, macros=None, 00313 silent=False, extra_verbose=False, build_profile=None, 00314 build_dir=None): 00315 target.default_lib = "small" 00316 ARM.__init__(self, target, notify, macros, build_dir=build_dir, 00317 build_profile=build_profile) 00318 if not set(("ARM", "uARM")).intersection(set(target.supported_toolchains)): 00319 raise NotSupportedException("ARM/uARM compiler support is required for ARM build") 00320 00321 class ARMC6(ARM_STD): 00322 SHEBANG = "#! armclang -E --target=arm-arm-none-eabi -x c" 00323 SUPPORTED_CORES = ["Cortex-M0", "Cortex-M0+", "Cortex-M3", "Cortex-M4", 00324 "Cortex-M4F", "Cortex-M7", "Cortex-M7F", "Cortex-M7FD", 00325 "Cortex-M23", "Cortex-M23-NS", "Cortex-M33", 00326 "CortexM33-NS", "Cortex-A9"] 00327 @staticmethod 00328 def check_executable(): 00329 return mbedToolchain.generic_check_executable("ARMC6", "armclang", 1) 00330 00331 def __init__(self, target, *args, **kwargs): 00332 mbedToolchain.__init__(self, target, *args, **kwargs) 00333 if target.core not in self.SUPPORTED_CORES: 00334 raise NotSupportedException( 00335 "this compiler does not support the core %s" % target.core) 00336 00337 if not set(("ARM", "ARMC6")).intersection(set(target.supported_toolchains)): 00338 raise NotSupportedException("ARM/ARMC6 compiler support is required for ARMC6 build") 00339 00340 if target.core.lower().endswith("fd"): 00341 self.flags['common'].append("-mcpu=%s" % target.core.lower()[:-2]) 00342 self.flags['ld'].append("--cpu=%s" % target.core.lower()[:-2]) 00343 self.SHEBANG += " -mcpu=%s" % target.core.lower()[:-2] 00344 elif target.core.lower().endswith("f"): 00345 self.flags['common'].append("-mcpu=%s" % target.core.lower()[:-1]) 00346 self.flags['ld'].append("--cpu=%s" % target.core.lower()[:-1]) 00347 self.SHEBANG += " -mcpu=%s" % target.core.lower()[:-1] 00348 elif target.core.lower().endswith("ns"): 00349 self.flags['common'].append("-mcpu=%s" % target.core.lower()[:-3]) 00350 self.flags['ld'].append("--cpu=%s" % target.core.lower()[:-3]) 00351 self.SHEBANG += " -mcpu=%s" % target.core.lower()[:-3] 00352 else: 00353 self.flags['common'].append("-mcpu=%s" % target.core.lower()) 00354 self.flags['ld'].append("--cpu=%s" % target.core.lower()) 00355 self.SHEBANG += " -mcpu=%s" % target.core.lower() 00356 00357 if target.core == "Cortex-M4F": 00358 self.flags['common'].append("-mfpu=fpv4-sp-d16") 00359 self.flags['common'].append("-mfloat-abi=hard") 00360 elif target.core == "Cortex-M7F": 00361 self.flags['common'].append("-mfpu=fpv5-sp-d16") 00362 self.flags['common'].append("-mfloat-abi=softfp") 00363 elif target.core == "Cortex-M7FD": 00364 self.flags['common'].append("-mfpu=fpv5-d16") 00365 self.flags['common'].append("-mfloat-abi=softfp") 00366 elif target.core.startswith("Cortex-M23"): 00367 self.flags['common'].append("-march=armv8-m.base") 00368 elif target.core.startswith("Cortex-M33"): 00369 self.flags['common'].append("-march=armv8-m.main") 00370 00371 if target.core == "Cortex-M23" or target.core == "Cortex-M33": 00372 self.flags['common'].append("-mcmse") 00373 00374 # Create Secure library 00375 if ((target.core == "Cortex-M23" or self.target.core == "Cortex-M33") and 00376 kwargs.get('build_dir', False)): 00377 build_dir = kwargs['build_dir'] 00378 secure_file = join(build_dir, "cmse_lib.o") 00379 self.flags["ld"] += ["--import_cmse_lib_out=%s" % secure_file] 00380 # Add linking time preprocessor macro __DOMAIN_NS 00381 if target.core == "Cortex-M23-NS" or self.target.core == "Cortex-M33-NS": 00382 define_string = self.make_ld_define("__DOMAIN_NS", 1) 00383 self.flags["ld"].append(define_string) 00384 00385 asm_cpu = { 00386 "Cortex-M0+": "Cortex-M0", 00387 "Cortex-M4F": "Cortex-M4.fp", 00388 "Cortex-M7F": "Cortex-M7.fp.sp", 00389 "Cortex-M7FD": "Cortex-M7.fp.dp", 00390 "Cortex-M23-NS": "Cortex-M23", 00391 "Cortex-M33-NS": "Cortex-M33" }.get(target.core, target.core) 00392 00393 self.flags['asm'].append("--cpu=%s" % asm_cpu) 00394 00395 self.cc = ([join(TOOLCHAIN_PATHS["ARMC6"], "armclang")] + 00396 self.flags['common'] + self.flags['c']) 00397 self.cppc = ([join(TOOLCHAIN_PATHS["ARMC6"], "armclang")] + 00398 self.flags['common'] + self.flags['cxx']) 00399 self.asm = [join(TOOLCHAIN_PATHS["ARMC6"], "armasm")] + self.flags['asm'] 00400 self.ld = [join(TOOLCHAIN_PATHS["ARMC6"], "armlink")] + self.flags['ld'] 00401 self.ar = [join(TOOLCHAIN_PATHS["ARMC6"], "armar")] 00402 self.elf2bin = join(TOOLCHAIN_PATHS["ARMC6"], "fromelf") 00403 00404 def _get_toolchain_labels(self): 00405 return ["ARM", "ARM_STD", "ARMC6"] 00406 00407 def parse_dependencies(self, dep_path): 00408 return mbedToolchain.parse_dependencies(self, dep_path) 00409 00410 def is_not_supported_error(self, output): 00411 return "#error [NOT_SUPPORTED]" in output 00412 00413 def parse_output(self, output): 00414 pass 00415 00416 def get_config_option(self, config_header): 00417 return ["-include", config_header] 00418 00419 def get_compile_options(self, defines, includes, for_asm=False): 00420 opts = ['-D%s' % d for d in defines] 00421 opts.extend(["-I%s" % i for i in includes]) 00422 if for_asm: 00423 return ["--cpreproc", 00424 "--cpreproc_opts=%s" % ",".join(self.flags['common'] + opts)] 00425 else: 00426 config_header = self.get_config_header() 00427 if config_header: 00428 opts.extend(self.get_config_option(config_header)) 00429 return opts 00430 00431 @hook_tool 00432 def assemble(self, source, object, includes): 00433 cmd_pre = copy(self.asm) 00434 cmd_pre.extend(self.get_compile_options( 00435 self.get_symbols(True), includes, for_asm=True)) 00436 cmd_pre.extend(["-o", object, source]) 00437 return [self.hook.get_cmdline_assembler(cmd_pre)] 00438 00439 @hook_tool 00440 def compile(self, cc, source, object, includes): 00441 cmd = copy(cc) 00442 cmd.extend(self.get_compile_options(self.get_symbols(), includes)) 00443 cmd.extend(["-o", object, source]) 00444 cmd = self.hook.get_cmdline_compiler(cmd) 00445 return [cmd]
Generated on Tue Jul 12 2022 12:43:28 by
