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 target.core == "Cortex-M0+": 00060 cpu = "Cortex-M0" 00061 elif target.core == "Cortex-M4F": 00062 cpu = "Cortex-M4.fp" 00063 elif target.core == "Cortex-M7FD": 00064 cpu = "Cortex-M7.fp.dp" 00065 elif target.core == "Cortex-M7F": 00066 cpu = "Cortex-M7.fp.sp" 00067 else: 00068 cpu = target.core 00069 00070 ARM_BIN = join(TOOLCHAIN_PATHS['ARM'], "bin") 00071 ARM_INC = join(TOOLCHAIN_PATHS['ARM'], "include") 00072 00073 main_cc = join(ARM_BIN, "armcc") 00074 00075 self.flags['common'] += ["--cpu=%s" % cpu] 00076 00077 self.asm = [main_cc] + self.flags['common'] + self.flags['asm'] 00078 self.cc = [main_cc] + self.flags['common'] + self.flags['c'] 00079 self.cppc = [main_cc] + self.flags['common'] + self.flags['c'] + self.flags['cxx'] 00080 00081 self.ld = [join(ARM_BIN, "armlink")] + self.flags['ld'] 00082 00083 self.ar = join(ARM_BIN, "armar") 00084 self.elf2bin = join(ARM_BIN, "fromelf") 00085 00086 self.SHEBANG += " --cpu=%s" % cpu 00087 00088 def parse_dependencies(self, dep_path): 00089 dependencies = [] 00090 for line in open(dep_path).readlines(): 00091 match = ARM.DEP_PATTERN.match(line) 00092 if match is not None: 00093 #we need to append chroot, because when the .d files are generated the compiler is chrooted 00094 dependencies.append((self.CHROOT if self.CHROOT else '') + match.group('file')) 00095 return dependencies 00096 00097 def parse_output(self, output): 00098 msg = None 00099 for line in output.splitlines(): 00100 match = ARM.DIAGNOSTIC_PATTERN.match(line) 00101 if match is not None: 00102 if msg is not None: 00103 self.notify.cc_info(msg) 00104 msg = None 00105 msg = { 00106 'severity': match.group('severity').lower(), 00107 'file': match.group('file'), 00108 'line': match.group('line'), 00109 'col': match.group('column') if match.group('column') else 0, 00110 'message': match.group('message'), 00111 'text': '', 00112 'target_name': self.target.name, 00113 'toolchain_name': self.name 00114 } 00115 elif msg is not None: 00116 # Determine the warning/error column by calculating the ^ position 00117 match = ARM.INDEX_PATTERN.match(line) 00118 if match is not None: 00119 msg['col'] = len(match.group('col')) 00120 self.notify.cc_info(msg) 00121 msg = None 00122 else: 00123 msg['text'] += line+"\n" 00124 00125 if msg is not None: 00126 self.notify.cc_info(msg) 00127 00128 def get_dep_option(self, object): 00129 base, _ = splitext(object) 00130 dep_path = base + '.d' 00131 return ["--depend", dep_path] 00132 00133 def get_config_option(self, config_header): 00134 return ['--preinclude=' + config_header] 00135 00136 def get_compile_options(self, defines, includes, for_asm=False): 00137 opts = ['-D%s' % d for d in defines] 00138 if for_asm: 00139 return opts 00140 if self.RESPONSE_FILES: 00141 opts += ['--via', self.get_inc_file(includes)] 00142 else: 00143 opts += ["-I%s" % i for i in includes] 00144 00145 config_header = self.get_config_header() 00146 if config_header is not None: 00147 opts = opts + self.get_config_option(config_header) 00148 return opts 00149 00150 @hook_tool 00151 def assemble(self, source, object, includes): 00152 # Preprocess first, then assemble 00153 dir = join(dirname(object), '.temp') 00154 mkdir(dir) 00155 tempfile = join(dir, basename(object) + '.E.s') 00156 00157 # Build preprocess assemble command 00158 cmd_pre = copy(self.asm) 00159 cmd_pre.extend(self.get_compile_options( 00160 self.get_symbols(True), includes, True)) 00161 cmd_pre.extend(["-E", "-o", tempfile, source]) 00162 00163 # Build main assemble command 00164 cmd = self.asm + ["-o", object, tempfile] 00165 00166 # Call cmdline hook 00167 cmd_pre = self.hook.get_cmdline_assembler(cmd_pre) 00168 cmd = self.hook.get_cmdline_assembler(cmd) 00169 00170 # Return command array, don't execute 00171 return [cmd_pre, cmd] 00172 00173 @hook_tool 00174 def compile(self, cc, source, object, includes): 00175 # Build compile command 00176 cmd = cc + self.get_compile_options(self.get_symbols(), includes) 00177 00178 cmd.extend(self.get_dep_option(object)) 00179 00180 cmd.extend(["-o", object, source]) 00181 00182 # Call cmdline hook 00183 cmd = self.hook.get_cmdline_compiler(cmd) 00184 00185 return [cmd] 00186 00187 def compile_c(self, source, object, includes): 00188 return self.compile(self.cc, source, object, includes) 00189 00190 def compile_cpp(self, source, object, includes): 00191 return self.compile(self.cppc, source, object, includes) 00192 00193 def correct_scatter_shebang(self, scatter_file, base_path=curdir): 00194 """Correct the shebang at the top of a scatter file. 00195 00196 Positional arguments: 00197 scatter_file -- the scatter file to correct 00198 00199 Return: 00200 The location of the correct scatter file 00201 00202 Side Effects: 00203 This method MAY write a new scatter file to disk 00204 """ 00205 with open(scatter_file, "r") as input: 00206 lines = input.readlines() 00207 if (lines[0].startswith(self.SHEBANG) or 00208 not lines[0].startswith("#!")): 00209 return scatter_file 00210 else: 00211 new_scatter = join(self.build_dir, ".link_script.sct") 00212 self.SHEBANG += " -I %s" % relpath(dirname(scatter_file), 00213 base_path) 00214 if self.need_update(new_scatter, [scatter_file]): 00215 with open(new_scatter, "w") as out: 00216 out.write(self.SHEBANG) 00217 out.write("\n") 00218 out.write("".join(lines[1:])) 00219 00220 return new_scatter 00221 00222 @hook_tool 00223 def link(self, output, objects, libraries, lib_dirs, scatter_file): 00224 base, _ = splitext(output) 00225 map_file = base + ".map" 00226 args = ["-o", output, "--info=totals", "--map", "--list=%s" % map_file] 00227 args.extend(objects) 00228 args.extend(libraries) 00229 if lib_dirs: 00230 args.extend(["--userlibpath", ",".join(lib_dirs)]) 00231 if scatter_file: 00232 new_scatter = self.correct_scatter_shebang(scatter_file) 00233 args.extend(["--scatter", new_scatter]) 00234 00235 cmd_pre = self.ld + args 00236 cmd = self.hook.get_cmdline_linker(cmd_pre) 00237 00238 if self.RESPONSE_FILES: 00239 cmd_linker = cmd[0] 00240 link_files = self.get_link_file(cmd[1:]) 00241 cmd = [cmd_linker, '--via', link_files] 00242 00243 self.notify.cc_verbose("Link: %s" % ' '.join(cmd)) 00244 self.default_cmd(cmd) 00245 00246 @hook_tool 00247 def archive(self, objects, lib_path): 00248 if self.RESPONSE_FILES: 00249 param = ['--via', self.get_arch_file(objects)] 00250 else: 00251 param = objects 00252 self.default_cmd([self.ar, '-r', lib_path] + param) 00253 00254 @hook_tool 00255 def binary(self, resources, elf, bin): 00256 _, fmt = splitext(bin) 00257 # On .hex format, combine multiple .hex files (for multiple load regions) into one 00258 bin_arg = {".bin": "--bin", ".hex": "--i32combined"}[fmt] 00259 cmd = [self.elf2bin, bin_arg, '-o', bin, elf] 00260 cmd = self.hook.get_cmdline_binary(cmd) 00261 00262 # remove target binary file/path 00263 if exists(bin): 00264 if isfile(bin): 00265 remove(bin) 00266 else: 00267 rmtree(bin) 00268 00269 self.notify.cc_verbose("FromELF: %s" % ' '.join(cmd)) 00270 self.default_cmd(cmd) 00271 00272 @staticmethod 00273 def name_mangle(name): 00274 return "_Z%i%sv" % (len(name), name) 00275 00276 @staticmethod 00277 def make_ld_define(name, value): 00278 return "--predefine=\"-D%s=0x%x\"" % (name, value) 00279 00280 @staticmethod 00281 def redirect_symbol(source, sync, build_dir): 00282 if not exists(build_dir): 00283 makedirs(build_dir) 00284 handle, filename = mkstemp(prefix=".redirect-symbol.", dir=build_dir) 00285 write(handle, "RESOLVE %s AS %s\n" % (source, sync)) 00286 return "--edit=%s" % filename 00287 00288 00289 class ARM_STD(ARM): 00290 def __init__(self, target, notify=None, macros=None, 00291 build_profile=None, build_dir=None): 00292 ARM.__init__(self, target, notify, macros, build_dir=build_dir, 00293 build_profile=build_profile) 00294 if "ARM" not in target.supported_toolchains: 00295 raise NotSupportedException("ARM compiler support is required for ARM build") 00296 00297 00298 class ARM_MICRO(ARM): 00299 PATCHED_LIBRARY = False 00300 def __init__(self, target, notify=None, macros=None, 00301 silent=False, extra_verbose=False, build_profile=None, 00302 build_dir=None): 00303 ARM.__init__(self, target, notify, macros, build_dir=build_dir, 00304 build_profile=build_profile) 00305 if not set(("ARM", "uARM")).intersection(set(target.supported_toolchains)): 00306 raise NotSupportedException("ARM/uARM compiler support is required for ARM build") 00307 00308 class ARMC6(ARM_STD): 00309 SHEBANG = "#! armclang -E --target=arm-arm-none-eabi -x c" 00310 SUPPORTED_CORES = ["Cortex-M0", "Cortex-M0+", "Cortex-M3", "Cortex-M4", 00311 "Cortex-M4F", "Cortex-M7", "Cortex-M7F", "Cortex-M7FD", 00312 "Cortex-M23", "Cortex-M23-NS", "Cortex-M33", 00313 "CortexM33-NS", "Cortex-A9"] 00314 @staticmethod 00315 def check_executable(): 00316 return mbedToolchain.generic_check_executable("ARMC6", "armclang", 1) 00317 00318 def __init__(self, target, *args, **kwargs): 00319 mbedToolchain.__init__(self, target, *args, **kwargs) 00320 if target.core not in self.SUPPORTED_CORES: 00321 raise NotSupportedException( 00322 "this compiler does not support the core %s" % target.core) 00323 00324 if not set(("ARM", "ARMC6")).intersection(set(target.supported_toolchains)): 00325 raise NotSupportedException("ARM/ARMC6 compiler support is required for ARMC6 build") 00326 00327 if target.core.lower().endswith("fd"): 00328 self.flags['common'].append("-mcpu=%s" % target.core.lower()[:-2]) 00329 self.flags['ld'].append("--cpu=%s" % target.core.lower()[:-2]) 00330 self.SHEBANG += " -mcpu=%s" % target.core.lower()[:-2] 00331 elif target.core.lower().endswith("f"): 00332 self.flags['common'].append("-mcpu=%s" % target.core.lower()[:-1]) 00333 self.flags['ld'].append("--cpu=%s" % target.core.lower()[:-1]) 00334 self.SHEBANG += " -mcpu=%s" % target.core.lower()[:-1] 00335 elif target.core.lower().endswith("ns"): 00336 self.flags['common'].append("-mcpu=%s" % target.core.lower()[:-3]) 00337 self.flags['ld'].append("--cpu=%s" % target.core.lower()[:-3]) 00338 self.SHEBANG += " -mcpu=%s" % target.core.lower()[:-3] 00339 else: 00340 self.flags['common'].append("-mcpu=%s" % target.core.lower()) 00341 self.flags['ld'].append("--cpu=%s" % target.core.lower()) 00342 self.SHEBANG += " -mcpu=%s" % target.core.lower() 00343 00344 if target.core == "Cortex-M4F": 00345 self.flags['common'].append("-mfpu=fpv4-sp-d16") 00346 self.flags['common'].append("-mfloat-abi=hard") 00347 elif target.core == "Cortex-M7F": 00348 self.flags['common'].append("-mfpu=fpv5-sp-d16") 00349 self.flags['common'].append("-mfloat-abi=softfp") 00350 elif target.core == "Cortex-M7FD": 00351 self.flags['common'].append("-mfpu=fpv5-d16") 00352 self.flags['common'].append("-mfloat-abi=softfp") 00353 elif target.core.startswith("Cortex-M23"): 00354 self.flags['common'].append("-march=armv8-m.base") 00355 elif target.core.startswith("Cortex-M33"): 00356 self.flags['common'].append("-march=armv8-m.main") 00357 00358 if target.core == "Cortex-M23" or target.core == "Cortex-M33": 00359 self.flags['common'].append("-mcmse") 00360 00361 # Create Secure library 00362 if ((target.core == "Cortex-M23" or self.target.core == "Cortex-M33") and 00363 kwargs.get('build_dir', False)): 00364 build_dir = kwargs['build_dir'] 00365 secure_file = join(build_dir, "cmse_lib.o") 00366 self.flags["ld"] += ["--import_cmse_lib_out=%s" % secure_file] 00367 # Add linking time preprocessor macro __DOMAIN_NS 00368 if target.core == "Cortex-M23-NS" or self.target.core == "Cortex-M33-NS": 00369 define_string = self.make_ld_define("__DOMAIN_NS", 1) 00370 self.flags["ld"].append(define_string) 00371 00372 asm_cpu = { 00373 "Cortex-M0+": "Cortex-M0", 00374 "Cortex-M4F": "Cortex-M4.fp", 00375 "Cortex-M7F": "Cortex-M7.fp.sp", 00376 "Cortex-M7FD": "Cortex-M7.fp.dp", 00377 "Cortex-M23-NS": "Cortex-M23", 00378 "Cortex-M33-NS": "Cortex-M33" }.get(target.core, target.core) 00379 00380 self.flags['asm'].append("--cpu=%s" % asm_cpu) 00381 00382 self.cc = ([join(TOOLCHAIN_PATHS["ARMC6"], "armclang")] + 00383 self.flags['common'] + self.flags['c']) 00384 self.cppc = ([join(TOOLCHAIN_PATHS["ARMC6"], "armclang")] + 00385 self.flags['common'] + self.flags['cxx']) 00386 self.asm = [join(TOOLCHAIN_PATHS["ARMC6"], "armasm")] + self.flags['asm'] 00387 self.ld = [join(TOOLCHAIN_PATHS["ARMC6"], "armlink")] + self.flags['ld'] 00388 self.ar = [join(TOOLCHAIN_PATHS["ARMC6"], "armar")] 00389 self.elf2bin = join(TOOLCHAIN_PATHS["ARMC6"], "fromelf") 00390 00391 def parse_dependencies(self, dep_path): 00392 return mbedToolchain.parse_dependencies(self, dep_path) 00393 00394 def is_not_supported_error(self, output): 00395 return "#error [NOT_SUPPORTED]" in output 00396 00397 def parse_output(self, output): 00398 pass 00399 00400 def get_config_option(self, config_header): 00401 return ["-include", config_header] 00402 00403 def get_compile_options(self, defines, includes, for_asm=False): 00404 opts = ['-D%s' % d for d in defines] 00405 opts.extend(["-I%s" % i for i in includes]) 00406 if for_asm: 00407 return ["--cpreproc", 00408 "--cpreproc_opts=%s" % ",".join(self.flags['common'] + opts)] 00409 else: 00410 config_header = self.get_config_header() 00411 if config_header: 00412 opts.extend(self.get_config_option(config_header)) 00413 return opts 00414 00415 @hook_tool 00416 def assemble(self, source, object, includes): 00417 cmd_pre = copy(self.asm) 00418 cmd_pre.extend(self.get_compile_options( 00419 self.get_symbols(True), includes, for_asm=True)) 00420 cmd_pre.extend(["-o", object, source]) 00421 return [self.hook.get_cmdline_assembler(cmd_pre)] 00422 00423 @hook_tool 00424 def compile(self, cc, source, object, includes): 00425 cmd = copy(cc) 00426 cmd.extend(self.get_compile_options(self.get_symbols(), includes)) 00427 cmd.extend(["-o", object, source]) 00428 cmd = self.hook.get_cmdline_compiler(cmd) 00429 return [cmd]
Generated on Tue Jul 12 2022 18:18:24 by
