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