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