Rtos API example

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers arm.py Source File

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