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.
__init__.py
00001 from __future__ import print_function, absolute_import 00002 from builtins import str 00003 00004 import os 00005 from os.path import normpath, exists, dirname 00006 import ntpath 00007 import copy 00008 from collections import namedtuple 00009 import shutil 00010 from subprocess import Popen, PIPE 00011 import re 00012 00013 from tools.resources import FileType 00014 from tools.targets import TARGET_MAP 00015 from tools.export.exporters import Exporter 00016 from tools.export.cmsis import DeviceCMSIS 00017 00018 00019 class DeviceUvision (DeviceCMSIS): 00020 """Uvision Device class, inherits CMSIS Device class 00021 00022 Encapsulates information necessary for uvision project targets""" 00023 def __init__(self, target): 00024 DeviceCMSIS.__init__(self, target) 00025 dev_format = "$$Device:{0}${1}" 00026 self.svd = '' 00027 if self.debug_svd: 00028 self.svd = dev_format.format(self.dname, self.debug_svd) 00029 self.reg_file = dev_format.format(self.dname, self.compile_header) 00030 self.debug_interface = self.uv_debug () 00031 self.flash_dll = self.generate_flash_dll () 00032 00033 def uv_debug (self): 00034 """Return a namedtuple of information about uvision debug settings""" 00035 UVDebug = namedtuple('UVDebug', ['bin_loc', 'core_flag', 'key']) 00036 00037 # CortexMXn => pCMX 00038 cpu = self.core.replace("Cortex-", "C") 00039 cpu = cpu.replace("+", "") 00040 cpu = cpu.replace("F", "") 00041 cpu = cpu.replace("-NS", "") 00042 cpu_flag = "p"+cpu 00043 00044 # Locations found in Keil_v5/TOOLS.INI 00045 debuggers = { 00046 "st-link": ('STLink\\ST-LINKIII-KEIL_SWO.dll', 00047 'ST-LINKIII-KEIL_SWO'), 00048 "j-link": ('Segger\\JL2CM3.dll', 'JL2CM3'), 00049 "cmsis-dap": ('BIN\\CMSIS_AGDI.dll', 'CMSIS_AGDI'), 00050 "nulink": ('NULink\\Nu_Link.dll', 'Nu_Link') 00051 } 00052 res = debuggers[self.debug.lower()] 00053 binary = res[0] 00054 key = res[1] 00055 00056 return UVDebug(binary, cpu_flag, key) 00057 00058 def generate_flash_dll (self): 00059 '''Flash DLL string from uvision 00060 S = SW/JTAG Clock ID 00061 C = CPU index in JTAG chain 00062 P = Access Port 00063 For the Options for Target -> Debug -> settings -> "Flash" dialog: 00064 FD = RAM Start for Flash Functions 00065 FC = RAM Size for Flash Functions 00066 FN = Number of Flash types 00067 FF = Flash File Name (without an extension) 00068 FS = Start Address of the Flash Device 00069 FL = Size of the Flash Device 00070 FP = Full path to the Device algorithm (RTE) 00071 00072 Necessary to flash some targets. 00073 ''' 00074 fl_count = 0 00075 00076 def get_mem_no_x(mem_str): 00077 mem_reg = "\dx(\w+)" 00078 m = re.search(mem_reg, mem_str) 00079 return m.group(1) if m else None 00080 00081 RAMS = [ 00082 (get_mem_no_x(info["start"]), get_mem_no_x(info["size"])) 00083 for mem, info in self.target_info["memory"].items() if "RAM" in mem 00084 ] 00085 format_str = ( 00086 "UL2CM3(-S0 -C0 -P0 -FD{ramstart}" 00087 " -FC{ramsize} -FN{num_algos} {extra_flags})" 00088 ) 00089 ramstart = '' 00090 # Default according to Keil developer 00091 ramsize = '1000' 00092 if len(RAMS) >= 1: 00093 ramstart = RAMS[0][0] 00094 extra_flags = [] 00095 for name, info in self.target_info["algorithm"].items(): 00096 if not name or not info: 00097 continue 00098 if int(info["default"]) == 0: 00099 continue 00100 name_reg = "\w*/([\w_]+)\.flm" 00101 m = re.search(name_reg, name.lower()) 00102 fl_name = m.group(1) if m else None 00103 name_flag = "-FF" + str(fl_count) + fl_name 00104 00105 start = get_mem_no_x(info["start"]) 00106 size = get_mem_no_x(info["size"]) 00107 rom_start_flag = "-FS" + str(fl_count) + str(start) 00108 rom_size_flag = "-FL" + str(fl_count) + str(size) 00109 00110 if info["ramstart"] is not None and info["ramsize"] is not None: 00111 ramstart = get_mem_no_x(info["ramstart"]) 00112 ramsize = get_mem_no_x(info["ramsize"]) 00113 00114 path_flag = "-FP{}($$Device:{}${})".format( 00115 str(fl_count), self.dname, name 00116 ) 00117 00118 extra_flags.extend([ 00119 name_flag, rom_start_flag, rom_size_flag, path_flag 00120 ]) 00121 fl_count += 1 00122 00123 extra = " ".join(extra_flags) 00124 return format_str.format(ramstart=ramstart, 00125 ramsize=ramsize, 00126 extra_flags=extra, num_algos=fl_count) 00127 00128 00129 class Uvision (Exporter): 00130 """Keil Uvision class 00131 00132 This class encapsulates information to be contained in a Uvision 00133 project file (.uvprojx). 00134 The needed information can be viewed in uvision.tmpl 00135 """ 00136 00137 POST_BINARY_WHITELIST = set([ 00138 "MCU_NRF51Code.binary_hook", 00139 "TEENSY3_1Code.binary_hook", 00140 "LPCTargetCode.lpc_patch", 00141 "LPC4088Code.binary_hook", 00142 "MTSCode.combine_bins_mts_dot", 00143 "MTSCode.combine_bins_mts_dragonfly", 00144 "NCS36510TargetCode.ncs36510_addfib" 00145 ]) 00146 00147 # File associations within .uvprojx file 00148 file_types = {'.cpp': 8, '.c': 1, '.s': 2, 00149 '.obj': 3, '.o': 3, '.lib': 4, 00150 '.ar': 4, '.h': 5, '.hpp': 5, '.sct': 4} 00151 00152 def uv_files (self, files): 00153 """An generator containing Uvision specific information about project files 00154 Positional Arguments: 00155 files - the location of source files 00156 00157 .uvprojx XML for project file: 00158 <File> 00159 <FileType>{{file.type}}</FileType> 00160 <FileName>{{file.name}}</FileName> 00161 <FilePath>{{file.loc}}</FilePath> 00162 </File> 00163 """ 00164 for loc in files: 00165 # Encapsulates the information necessary for template entry above 00166 UVFile = namedtuple('UVFile', ['type', 'loc', 'name']) 00167 _, ext = os.path.splitext(loc) 00168 if ext.lower() in self.file_types : 00169 type = self.file_types [ext.lower()] 00170 name = ntpath.basename(normpath(loc)) 00171 yield UVFile(type, loc, name) 00172 00173 def format_flags (self): 00174 """Format toolchain flags for Uvision""" 00175 flags = copy.deepcopy(self.flags) 00176 asm_flag_string = ( 00177 '--cpreproc --cpreproc_opts=-D__ASSERT_MSG,' + 00178 ",".join("-D{}".format(s) for s in 00179 self.toolchain.get_symbols(for_asm=True))) 00180 flags['asm_flags'] = asm_flag_string 00181 00182 config_header = self.config_header_ref 00183 config_option = self.toolchain.get_config_option(config_header.name) 00184 c_flags = set( 00185 flags['c_flags'] + flags['cxx_flags'] + flags['common_flags'] 00186 ) 00187 in_template = set( 00188 ["--no_vla", "--cpp", "--c99", "-MMD"] + config_option 00189 ) 00190 00191 def valid_flag(x): 00192 return ( 00193 x not in in_template and 00194 not x.startswith("-O") and 00195 not x.startswith("-std") and 00196 not x.startswith("-D") 00197 ) 00198 00199 def is_define(s): 00200 return s.startswith("-D") and "(" not in s 00201 00202 flags['c_flags'] = " ".join( 00203 f.replace('"', '\\"') for f in c_flags if valid_flag(f) 00204 ) 00205 flags['c_flags'] += " " 00206 flags['c_flags'] += " ".join(config_option) 00207 flags['c_defines'] = " ".join(f[2:].replace('"', '\\"') 00208 for f in c_flags if is_define(f)) 00209 flags['ld_flags'] = " ".join(set(flags['ld_flags'])) 00210 return flags 00211 00212 def format_src (self, srcs): 00213 """Make sources into the named tuple for use in the template""" 00214 grouped = self.group_project_files(srcs) 00215 for group, files in grouped.items(): 00216 grouped[group] = sorted(list(self.uv_files (files)), 00217 key=lambda tuple: tuple[2].lower()) 00218 return grouped 00219 00220 @staticmethod 00221 def format_fpu (core): 00222 """Generate a core's FPU string""" 00223 if core.endswith("FD"): 00224 return "FPU3(DFPU)" 00225 elif core.endswith("F"): 00226 return "FPU2" 00227 else: 00228 return "" 00229 00230 def generate (self): 00231 """Generate the .uvproj file""" 00232 srcs = ( 00233 self.resources.headers + self.resources.s_sources + 00234 self.resources.c_sources + self.resources.cpp_sources + 00235 self.resources.objects + self.libraries 00236 ) 00237 ctx = { 00238 'name': self.project_name, 00239 # project_files => dict of generators - file group to generator of 00240 # UVFile tuples defined above 00241 'project_files': sorted(list(self.format_src (srcs).items()), 00242 key=lambda tuple: tuple[0].lower()), 00243 'include_paths': ';'.join(self.filter_dot(d) for d in 00244 self.resources.inc_dirs).encode('utf-8'), 00245 'device': DeviceUvision(self.target), 00246 } 00247 sct_name, sct_path = self.resources.get_file_refs( 00248 FileType.LD_SCRIPT)[0] 00249 ctx['linker_script'] = self.toolchain.correct_scatter_shebang( 00250 sct_path, dirname(sct_name)) 00251 if ctx['linker_script'] != sct_path: 00252 self.generated_files.append(ctx['linker_script']) 00253 ctx['cputype'] = ctx['device'].core.rstrip("FD").replace("-NS", "") 00254 if ctx['device'].core.endswith("FD"): 00255 ctx['fpu_setting'] = 3 00256 elif ctx['device'].core.endswith("F"): 00257 ctx['fpu_setting'] = 2 00258 else: 00259 ctx['fpu_setting'] = 1 00260 ctx['fputype'] = self.format_fpu (ctx['device'].core) 00261 ctx['armc6'] = int(self.TOOLCHAIN is 'ARMC6') 00262 ctx['toolchain_name'] = self.TOOLCHAIN_NAME 00263 ctx.update(self.format_flags ()) 00264 self.gen_file( 00265 'uvision/uvision.tmpl', ctx, self.project_name + ".uvprojx" 00266 ) 00267 self.gen_file( 00268 'uvision/uvision_debug.tmpl', ctx, self.project_name + ".uvoptx" 00269 ) 00270 00271 @staticmethod 00272 def clean(project_name): 00273 os.remove(project_name + ".uvprojx") 00274 os.remove(project_name + ".uvoptx") 00275 # legacy .build directory cleaned if exists 00276 if exists('.build'): 00277 shutil.rmtree('.build') 00278 if exists('BUILD'): 00279 shutil.rmtree('BUILD') 00280 00281 @staticmethod 00282 def build (project_name, log_name='build_log.txt', cleanup=True): 00283 """ Build Uvision project """ 00284 # > UV4 -r -j0 -o [log_name] [project_name].uvprojx 00285 proj_file = project_name + ".uvprojx" 00286 cmd = ['UV4', '-r', '-j0', '-o', log_name, proj_file] 00287 00288 # Build the project 00289 p = Popen(cmd, stdout=PIPE, stderr=PIPE) 00290 out, err = p.communicate() 00291 ret_code = p.returncode 00292 00293 # Print the log file to stdout 00294 with open(log_name, 'r') as f: 00295 print(f.read()) 00296 00297 # Cleanup the exported and built files 00298 if cleanup: 00299 os.remove(log_name) 00300 Uvision.clean(project_name) 00301 00302 # Returns 0 upon success, 1 upon a warning, and neither upon an error 00303 if ret_code != 0 and ret_code != 1: 00304 # Seems like something went wrong. 00305 return -1 00306 else: 00307 return 0 00308 00309 00310 class UvisionArmc5(Uvision ): 00311 NAME = 'uvision5-armc5' 00312 TOOLCHAIN = 'ARM' 00313 TOOLCHAIN_NAME = '' 00314 00315 @classmethod 00316 def is_target_supported(cls, target_name): 00317 target = TARGET_MAP[target_name] 00318 if not (set(target.supported_toolchains).intersection( 00319 set(["ARM", "uARM"]))): 00320 return False 00321 if not DeviceCMSIS.check_supported(target_name): 00322 return False 00323 if "Cortex-A" in target.core: 00324 return False 00325 if not hasattr(target, "post_binary_hook"): 00326 return True 00327 if target.post_binary_hook['function'] in cls.POST_BINARY_WHITELIST: 00328 return True 00329 else: 00330 return False 00331 00332 00333 class UvisionArmc6(Uvision ): 00334 NAME = 'uvision5-armc6' 00335 TOOLCHAIN = 'ARMC6' 00336 TOOLCHAIN_NAME = '6070000::V6.7::.\ARMCLANG' 00337 00338 @classmethod 00339 def is_target_supported(cls, target_name): 00340 target = TARGET_MAP[target_name] 00341 if not (set(target.supported_toolchains).intersection( 00342 set(["ARMC6"]))): 00343 return False 00344 if not DeviceCMSIS.check_supported(target_name): 00345 return False 00346 if "Cortex-A" in target.core: 00347 return False 00348 if not hasattr(target, "post_binary_hook"): 00349 return True 00350 if target.post_binary_hook['function'] in cls.POST_BINARY_WHITELIST: 00351 return True 00352 else: 00353 return False
Generated on Tue Jul 12 2022 17:12:47 by
