Rtos API example

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers gcc.py Source File

gcc.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 os.path import join, basename, splitext, dirname, exists
00019 from distutils.spawn import find_executable
00020 
00021 from tools.toolchains import mbedToolchain, TOOLCHAIN_PATHS
00022 from tools.hooks import hook_tool
00023 
00024 class GCC(mbedToolchain):
00025     LINKER_EXT = '.ld'
00026     LIBRARY_EXT = '.a'
00027 
00028     STD_LIB_NAME = "lib%s.a"
00029     DIAGNOSTIC_PATTERN = re.compile('((?P<file>[^:]+):(?P<line>\d+):)(\d+:)? (?P<severity>warning|[eE]rror|fatal error): (?P<message>.+)')
00030     INDEX_PATTERN  = re.compile('(?P<col>\s*)\^')
00031 
00032     def __init__(self, target,  notify=None, macros=None,
00033                  silent=False, extra_verbose=False, build_profile=None,
00034                  build_dir=None):
00035         mbedToolchain.__init__(self, target, notify, macros, silent,
00036                                extra_verbose=extra_verbose,
00037                                build_profile=build_profile, build_dir=build_dir)
00038 
00039         tool_path=TOOLCHAIN_PATHS['GCC_ARM']
00040         # Add flags for current size setting
00041         default_lib = "std"
00042         if hasattr(target, "default_lib"):
00043             default_lib = target.default_lib
00044         elif hasattr(target, "default_build"): # Legacy
00045             default_lib = target.default_build
00046 
00047         if default_lib == "small":
00048             self.flags["common"].append("-DMBED_RTOS_SINGLE_THREAD")
00049             self.flags["ld"].append("--specs=nano.specs")
00050 
00051         if target.core == "Cortex-M0+":
00052             cpu = "cortex-m0plus"
00053         elif target.core == "Cortex-M4F":
00054             cpu = "cortex-m4"
00055         elif target.core == "Cortex-M7F":
00056             cpu = "cortex-m7"
00057         elif target.core == "Cortex-M7FD":
00058             cpu = "cortex-m7"
00059         elif target.core == "Cortex-M23-NS":
00060             cpu = "cortex-m23"
00061         elif target.core == "Cortex-M33-NS":
00062             cpu = "cortex-m33"
00063         else:
00064             cpu = target.core.lower()
00065 
00066         self.cpu = ["-mcpu=%s" % cpu]
00067         if target.core.startswith("Cortex-M"):
00068             self.cpu.append("-mthumb")
00069 
00070         # FPU handling, M7 possibly to have double FPU
00071         if target.core == "Cortex-M4F":
00072             self.cpu.append("-mfpu=fpv4-sp-d16")
00073             self.cpu.append("-mfloat-abi=softfp")
00074         elif target.core == "Cortex-M7F":
00075             self.cpu.append("-mfpu=fpv5-sp-d16")
00076             self.cpu.append("-mfloat-abi=softfp")
00077         elif target.core == "Cortex-M7FD":
00078             self.cpu.append("-mfpu=fpv5-d16")
00079             self.cpu.append("-mfloat-abi=softfp")
00080 
00081         if target.core == "Cortex-A9":
00082             self.cpu.append("-mthumb-interwork")
00083             self.cpu.append("-marm")
00084             self.cpu.append("-march=armv7-a")
00085             self.cpu.append("-mfpu=vfpv3")
00086             self.cpu.append("-mfloat-abi=hard")
00087             self.cpu.append("-mno-unaligned-access")
00088 
00089         if target.core.startswith("Cortex-M23"):
00090             self.cpu.append("-march=armv8-m.base")
00091         elif target.core.startswith("Cortex-M33"):
00092             self.cpu.append("-march=armv8-m.main")
00093 
00094         if target.core == "Cortex-M23" or target.core == "Cortex-M33":
00095             self.cpu.append("-mcmse")
00096 
00097         self.flags["common"] += self.cpu
00098 
00099         main_cc = join(tool_path, "arm-none-eabi-gcc")
00100         main_cppc = join(tool_path, "arm-none-eabi-g++")
00101         self.asm = [main_cc] + self.flags['asm'] + self.flags["common"]
00102         self.cc  = [main_cc]
00103         self.cppc =[main_cppc]
00104         self.cc += self.flags['c'] + self.flags['common']
00105         self.cppc += self.flags['cxx'] + self.flags['common']
00106 
00107         self.flags['ld'] += self.cpu
00108         self.ld = [join(tool_path, "arm-none-eabi-gcc")] + self.flags['ld']
00109         self.sys_libs = ["stdc++", "supc++", "m", "c", "gcc", "nosys"]
00110         self.preproc = [join(tool_path, "arm-none-eabi-cpp"), "-E", "-P"]
00111 
00112         self.ar = join(tool_path, "arm-none-eabi-ar")
00113         self.elf2bin = join(tool_path, "arm-none-eabi-objcopy")
00114 
00115     def is_not_supported_error(self, output):
00116         return "error: #error [NOT_SUPPORTED]" in output
00117 
00118     def parse_output(self, output):
00119         # The warning/error notification is multiline
00120         msg = None
00121         for line in output.splitlines():
00122             match = self.DIAGNOSTIC_PATTERN.search(line)
00123             if match is not None:
00124                 if msg is not None:
00125                     self.cc_info(msg)
00126                     msg = None
00127                 msg = {
00128                     'severity': match.group('severity').lower(),
00129                     'file': match.group('file'),
00130                     'line': match.group('line'),
00131                     'col': 0,
00132                     'message': match.group('message'),
00133                     'text': '',
00134                     'target_name': self.target.name,
00135                     'toolchain_name': self.name
00136                 }
00137             elif msg is not None:
00138                 # Determine the warning/error column by calculating the ^ position
00139                 match = self.INDEX_PATTERN.match(line)
00140                 if match is not None:
00141                     msg['col'] = len(match.group('col'))
00142                     self.cc_info(msg)
00143                     msg = None
00144                 else:
00145                     msg['text'] += line+"\n"
00146 
00147         if msg is not None:
00148             self.cc_info(msg)
00149 
00150     def get_dep_option(self, object):
00151         base, _ = splitext(object)
00152         dep_path = base + '.d'
00153         return ["-MD", "-MF", dep_path]
00154 
00155     def get_config_option(self, config_header):
00156         return ['-include', config_header]
00157 
00158     def get_compile_options(self, defines, includes, for_asm=False):
00159         opts = ['-D%s' % d for d in defines]
00160         if self.RESPONSE_FILES:
00161             opts += ['@%s' % self.get_inc_file(includes)]
00162         else:
00163             opts += ["-I%s" % i for i in includes]
00164 
00165         if not for_asm:
00166             config_header = self.get_config_header()
00167             if config_header is not None:
00168                 opts = opts + self.get_config_option(config_header)
00169         return opts
00170 
00171     @hook_tool
00172     def assemble(self, source, object, includes):
00173         # Build assemble command
00174         cmd = self.asm + self.get_compile_options(self.get_symbols(True), includes) + ["-o", object, source]
00175 
00176         # Call cmdline hook
00177         cmd = self.hook.get_cmdline_assembler(cmd)
00178 
00179         # Return command array, don't execute
00180         return [cmd]
00181 
00182     @hook_tool
00183     def compile(self, cc, source, object, includes):
00184         # Build compile command
00185         cmd = cc + self.get_compile_options(self.get_symbols(), includes)
00186 
00187         cmd.extend(self.get_dep_option(object))
00188 
00189         cmd.extend(["-o", object, source])
00190 
00191         # Call cmdline hook
00192         cmd = self.hook.get_cmdline_compiler(cmd)
00193 
00194         return [cmd]
00195 
00196     def compile_c(self, source, object, includes):
00197         return self.compile(self.cc, source, object, includes)
00198 
00199     def compile_cpp(self, source, object, includes):
00200         return self.compile(self.cppc, source, object, includes)
00201 
00202     @hook_tool
00203     def link(self, output, objects, libraries, lib_dirs, mem_map):
00204         libs = []
00205         for l in libraries:
00206             name, _ = splitext(basename(l))
00207             libs.append("-l%s" % name[3:])
00208         libs.extend(["-l%s" % l for l in self.sys_libs])
00209 
00210         # Preprocess
00211         if mem_map:
00212             preproc_output = join(dirname(output), ".link_script.ld")
00213             cmd = (self.preproc + [mem_map] + self.ld[1:] +
00214                    [ "-o", preproc_output])
00215             self.cc_verbose("Preproc: %s" % ' '.join(cmd))
00216             self.default_cmd(cmd)
00217             mem_map = preproc_output
00218 
00219         # Build linker command
00220         map_file = splitext(output)[0] + ".map"
00221         cmd = self.ld + ["-o", output, "-Wl,-Map=%s" % map_file] + objects + ["-Wl,--start-group"] + libs + ["-Wl,--end-group"]
00222         if mem_map:
00223             cmd.extend(['-T', mem_map])
00224 
00225         for L in lib_dirs:
00226             cmd.extend(['-L', L])
00227         cmd.extend(libs)
00228 
00229         # Call cmdline hook
00230         cmd = self.hook.get_cmdline_linker(cmd)
00231 
00232         if self.RESPONSE_FILES:
00233             # Split link command to linker executable + response file
00234             cmd_linker = cmd[0]
00235             link_files = self.get_link_file(cmd[1:])
00236             cmd = [cmd_linker, "@%s" % link_files]
00237 
00238         # Exec command
00239         self.cc_verbose("Link: %s" % ' '.join(cmd))
00240         self.default_cmd(cmd)
00241 
00242     @hook_tool
00243     def archive(self, objects, lib_path):
00244         if self.RESPONSE_FILES:
00245             param = ["@%s" % self.get_arch_file(objects)]
00246         else:
00247             param = objects
00248 
00249         # Exec command
00250         self.default_cmd([self.ar, 'rcs', lib_path] + param)
00251 
00252     @hook_tool
00253     def binary(self, resources, elf, bin):
00254         # Build binary command
00255         _, fmt = splitext(bin)
00256         bin_arg = {'.bin': 'binary', '.hex': 'ihex'}[fmt]
00257         cmd = [self.elf2bin, "-O", bin_arg, elf, bin]
00258 
00259         # Call cmdline hook
00260         cmd = self.hook.get_cmdline_binary(cmd)
00261 
00262         # Exec command
00263         self.cc_verbose("FromELF: %s" % ' '.join(cmd))
00264         self.default_cmd(cmd)
00265 
00266     @staticmethod
00267     def name_mangle(name):
00268         return "_Z%i%sv" % (len(name), name)
00269 
00270     @staticmethod
00271     def make_ld_define(name, value):
00272         return "-D%s=0x%x" % (name, value)
00273 
00274     @staticmethod
00275     def redirect_symbol(source, sync, build_dir):
00276         return "-Wl,--defsym=%s=%s" % (source, sync)
00277 
00278     @staticmethod
00279     def check_executable():
00280         """Returns True if the executable (arm-none-eabi-gcc) location
00281         specified by the user exists OR the executable can be found on the PATH.
00282         Returns False otherwise."""
00283         if not TOOLCHAIN_PATHS['GCC_ARM'] or not exists(TOOLCHAIN_PATHS['GCC_ARM']):
00284             if find_executable('arm-none-eabi-gcc'):
00285                 TOOLCHAIN_PATHS['GCC_ARM'] = ''
00286                 return True
00287             else:
00288                 return False
00289         else:
00290             exec_name = join(TOOLCHAIN_PATHS['GCC_ARM'], 'arm-none-eabi-gcc')
00291             return exists(exec_name) or exists(exec_name + '.exe')
00292 
00293 class GCC_ARM(GCC):
00294     pass