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 sep, normpath, join, exists 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.arm_pack_manager import Cache 00014 from tools.targets import TARGET_MAP 00015 from tools.export.exporters import Exporter, apply_supported_whitelist 00016 from tools.export.cmsis import DeviceCMSIS 00017 00018 class DeviceUvision (DeviceCMSIS ): 00019 """Uvision Device class, inherits CMSIS Device class 00020 00021 Encapsulates information necessary for uvision project targets""" 00022 def __init__(self, target): 00023 DeviceCMSIS.__init__(self, target) 00024 dev_format = "$$Device:{0}${1}" 00025 self.svd = '' 00026 if self.debug_svd: 00027 self.svd = dev_format.format(self.dname, self.debug_svd) 00028 self.reg_file = dev_format.format(self.dname, self.compile_header) 00029 self.debug_interface = self.uv_debug () 00030 self.flash_dll = self.generate_flash_dll () 00031 00032 def uv_debug (self): 00033 """Return a namedtuple of information about uvision debug settings""" 00034 UVDebug = namedtuple('UVDebug',['bin_loc','core_flag', 'key']) 00035 00036 # CortexMXn => pCMX 00037 cpu = self.core.replace("Cortex-", "C") 00038 cpu = cpu.replace("+", "") 00039 cpu = cpu.replace("F", "") 00040 cpu_flag = "p"+cpu 00041 00042 # Locations found in Keil_v5/TOOLS.INI 00043 debuggers = {"st-link": ('STLink\\ST-LINKIII-KEIL_SWO.dll', 'ST-LINKIII-KEIL_SWO'), 00044 "j-link":('Segger\\JL2CM3.dll', 'JL2CM3'), 00045 "cmsis-dap":('BIN\\CMSIS_AGDI.dll', 'CMSIS_AGDI'), 00046 "nulink":('NULink\\Nu_Link.dll','Nu_Link')} 00047 res = debuggers[self.debug.lower()] 00048 binary = res[0] 00049 key = res[1] 00050 00051 return UVDebug(binary, cpu_flag, key) 00052 00053 def generate_flash_dll (self): 00054 '''Flash DLL string from uvision 00055 S = SW/JTAG Clock ID 00056 C = CPU index in JTAG chain 00057 P = Access Port 00058 For the Options for Target -> Debug tab -> settings -> "Flash" tab in the dialog: 00059 FD = RAM Start for Flash Functions 00060 FC = RAM Size for Flash Functions 00061 FN = Number of Flash types 00062 FF = Flash File Name (without an extension) 00063 FS = Start Address of the Flash Device 00064 FL = Size of the Flash Device 00065 FP = Full path to the Device algorithm (RTE) 00066 00067 Necessary to flash some targets. Info gathered from algorithms field of pdsc file. 00068 ''' 00069 fl_count = 0 00070 def get_mem_no_x(mem_str): 00071 mem_reg = "\dx(\w+)" 00072 m = re.search(mem_reg, mem_str) 00073 return m.group(1) if m else None 00074 00075 RAMS = [(get_mem_no_x(info["start"]), get_mem_no_x(info["size"])) 00076 for mem, info in self.target_info["memory"].items() if "RAM" in mem] 00077 format_str = "UL2CM3(-S0 -C0 -P0 -FD{ramstart}"+" -FC{ramsize} "+"-FN{num_algos} {extra_flags})" 00078 ramstart = '' 00079 #Default according to Keil developer 00080 ramsize = '1000' 00081 if len(RAMS)>=1: 00082 ramstart = RAMS[0][0] 00083 extra_flags = [] 00084 for name, info in self.target_info["algorithm"].items(): 00085 if not name or not info: 00086 continue 00087 if int(info["default"])==0: 00088 continue 00089 name_reg = "\w*/([\w_]+)\.flm" 00090 m = re.search(name_reg, name.lower()) 00091 fl_name = m.group(1) if m else None 00092 name_flag = "-FF" + str(fl_count) + fl_name 00093 00094 start, size = get_mem_no_x(info["start"]), get_mem_no_x(info["size"]) 00095 rom_start_flag = "-FS"+str(fl_count)+str(start) 00096 rom_size_flag = "-FL" + str(fl_count) + str(size) 00097 00098 if info["ramstart"] is not None and info["ramsize"] is not None: 00099 ramstart = get_mem_no_x(info["ramstart"]) 00100 ramsize = get_mem_no_x(info["ramsize"]) 00101 00102 path_flag = "-FP" + str(fl_count) + "($$Device:"+self.dname+"$"+name+")" 00103 00104 extra_flags.extend([name_flag, rom_start_flag, rom_size_flag, path_flag]) 00105 fl_count += 1 00106 00107 extra = " ".join(extra_flags) 00108 return format_str.format(ramstart=ramstart, 00109 ramsize=ramsize, 00110 extra_flags=extra, num_algos=fl_count) 00111 00112 00113 class Uvision (Exporter ): 00114 """Keil Uvision class 00115 00116 This class encapsulates information to be contained in a Uvision 00117 project file (.uvprojx). 00118 The needed information can be viewed in uvision.tmpl 00119 """ 00120 NAME = 'uvision5' 00121 TOOLCHAIN = 'ARM' 00122 00123 POST_BINARY_WHITELIST = set([ 00124 "MCU_NRF51Code.binary_hook", 00125 "TEENSY3_1Code.binary_hook", 00126 "LPCTargetCode.lpc_patch", 00127 "LPC4088Code.binary_hook", 00128 "MTSCode.combine_bins_mts_dot", 00129 "MTSCode.combine_bins_mts_dragonfly", 00130 "NCS36510TargetCode.ncs36510_addfib" 00131 ]) 00132 00133 @classmethod 00134 def is_target_supported (cls, target_name): 00135 target = TARGET_MAP[target_name] 00136 if not (set(target.supported_toolchains) and set(["ARM", "uARM"])): 00137 return False 00138 if not DeviceCMSIS.check_supported(target_name): 00139 return False 00140 if not hasattr(target, "post_binary_hook"): 00141 return True 00142 if target.post_binary_hook['function'] in cls.POST_BINARY_WHITELIST: 00143 return True 00144 else: 00145 return False 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 # to be preprocessed with armcc 00177 asm_flag_string = ( 00178 '--cpreproc --cpreproc_opts=-D__ASSERT_MSG,' + 00179 ",".join(filter(lambda f: f.startswith("-D"), flags['asm_flags']))) 00180 flags['asm_flags'] = asm_flag_string 00181 # All non-asm flags are in one template field 00182 c_flags = list(set(flags['c_flags'] + flags['cxx_flags'] +flags['common_flags'])) 00183 ld_flags = list(set(flags['ld_flags'] )) 00184 # These flags are in template to be set by user i n IDE 00185 template = ["--no_vla", "--cpp", "--c99"] 00186 # Flag is invalid if set in template 00187 # Optimizations are also set in the template 00188 invalid_flag = lambda x: x in template or re.match("-O(\d|time)", x) 00189 flags['c_flags'] = [flag.replace('"','\\"') for flag in c_flags if not invalid_flag(flag)] 00190 flags['c_flags'] = " ".join(flags['c_flags']) 00191 flags['ld_flags'] = " ".join(flags['ld_flags']) 00192 return flags 00193 00194 def format_src (self, srcs): 00195 """Make sources into the named tuple for use in the template""" 00196 grouped = self.group_project_files(srcs) 00197 for group, files in grouped.items(): 00198 grouped[group] = sorted(list(self.uv_files (files)), 00199 key=lambda tuple: tuple[2].lower()) 00200 return grouped 00201 00202 @staticmethod 00203 def format_fpu (core): 00204 """Generate a core's FPU string""" 00205 if core.endswith("FD"): 00206 return "FPU3(DFPU)" 00207 elif core.endswith("F"): 00208 return "FPU2" 00209 else: 00210 return "" 00211 00212 def generate (self): 00213 """Generate the .uvproj file""" 00214 cache = Cache(True, False) 00215 00216 srcs = self.resources.headers + self.resources.s_sources + \ 00217 self.resources.c_sources + self.resources.cpp_sources + \ 00218 self.resources.objects + self.resources.libraries 00219 ctx = { 00220 'name': self.project_name, 00221 # project_files => dict of generators - file group to generator of 00222 # UVFile tuples defined above 00223 'project_files': sorted(list(self.format_src (srcs).items()), 00224 key=lambda tuple: tuple[0].lower()), 00225 'include_paths': ';'.join(self.filter_dot(d) for d in 00226 self.resources.inc_dirs).encode('utf-8'), 00227 'device': DeviceUvision(self.target), 00228 } 00229 sct_file = self.resources.linker_script 00230 ctx['linker_script'] = self.toolchain.correct_scatter_shebang( 00231 sct_file, self.resources.file_basepath[sct_file]) 00232 if ctx['linker_script'] != sct_file: 00233 self.generated_files.append(ctx['linker_script']) 00234 core = ctx['device'].core 00235 ctx['cputype'] = core.rstrip("FD") 00236 if core.endswith("FD"): 00237 ctx['fpu_setting'] = 3 00238 elif core.endswith("F"): 00239 ctx['fpu_setting'] = 2 00240 else: 00241 ctx['fpu_setting'] = 1 00242 ctx['fputype'] = self.format_fpu (core) 00243 ctx.update(self.format_flags ()) 00244 self.gen_file('uvision/uvision.tmpl', ctx, self.project_name+".uvprojx") 00245 self.gen_file('uvision/uvision_debug.tmpl', ctx, self.project_name + ".uvoptx") 00246 00247 @staticmethod 00248 def clean (project_name): 00249 os.remove(project_name + ".uvprojx") 00250 os.remove(project_name + ".uvoptx") 00251 # legacy .build directory cleaned if exists 00252 if exists('.build'): 00253 shutil.rmtree('.build') 00254 if exists('BUILD'): 00255 shutil.rmtree('BUILD') 00256 00257 @staticmethod 00258 def build (project_name, log_name='build_log.txt', cleanup=True): 00259 """ Build Uvision project """ 00260 # > UV4 -r -j0 -o [log_name] [project_name].uvprojx 00261 proj_file = project_name + ".uvprojx" 00262 cmd = ['UV4', '-r', '-j0', '-o', log_name, proj_file] 00263 00264 # Build the project 00265 p = Popen(cmd, stdout=PIPE, stderr=PIPE) 00266 out, err = p.communicate() 00267 ret_code = p.returncode 00268 00269 # Print the log file to stdout 00270 with open(log_name, 'r') as f: 00271 print(f.read()) 00272 00273 # Cleanup the exported and built files 00274 if cleanup: 00275 os.remove(log_name) 00276 Uvision.clean(project_name) 00277 00278 # Returns 0 upon success, 1 upon a warning, and neither upon an error 00279 if ret_code != 0 and ret_code != 1: 00280 # Seems like something went wrong. 00281 return -1 00282 else: 00283 return 0
Generated on Tue Jul 12 2022 12:43:27 by
1.7.2