BA
/
BaBoRo1
Embed:
(wiki syntax)
Show/hide line numbers
__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 return apply_supported_whitelist( 00137 cls.TOOLCHAIN, cls.POST_BINARY_WHITELIST, target) and\ 00138 DeviceCMSIS.check_supported(target_name) 00139 00140 #File associations within .uvprojx file 00141 file_types = {'.cpp': 8, '.c': 1, '.s': 2, 00142 '.obj': 3, '.o': 3, '.lib': 4, 00143 '.ar': 4, '.h': 5, '.hpp': 5, '.sct': 4} 00144 00145 def uv_files (self, files): 00146 """An generator containing Uvision specific information about project files 00147 Positional Arguments: 00148 files - the location of source files 00149 00150 .uvprojx XML for project file: 00151 <File> 00152 <FileType>{{file.type}}</FileType> 00153 <FileName>{{file.name}}</FileName> 00154 <FilePath>{{file.loc}}</FilePath> 00155 </File> 00156 """ 00157 for loc in files: 00158 #Encapsulates the information necessary for template entry above 00159 UVFile = namedtuple('UVFile', ['type','loc','name']) 00160 _, ext = os.path.splitext(loc) 00161 if ext.lower() in self.file_types : 00162 type = self.file_types [ext.lower()] 00163 name = ntpath.basename(normpath(loc)) 00164 yield UVFile(type, loc, name) 00165 00166 def format_flags (self): 00167 """Format toolchain flags for Uvision""" 00168 flags = copy.deepcopy(self.flags) 00169 # to be preprocessed with armcc 00170 asm_flag_string = ( 00171 '--cpreproc --cpreproc_opts=-D__ASSERT_MSG,' + 00172 ",".join(filter(lambda f: f.startswith("-D"), flags['asm_flags']))) 00173 flags['asm_flags'] = asm_flag_string 00174 # All non-asm flags are in one template field 00175 c_flags = list(set(flags['c_flags'] + flags['cxx_flags'] +flags['common_flags'])) 00176 ld_flags = list(set(flags['ld_flags'] )) 00177 # These flags are in template to be set by user i n IDE 00178 template = ["--no_vla", "--cpp", "--c99"] 00179 # Flag is invalid if set in template 00180 # Optimizations are also set in the template 00181 invalid_flag = lambda x: x in template or re.match("-O(\d|time)", x) 00182 flags['c_flags'] = [flag.replace('"','\\"') for flag in c_flags if not invalid_flag(flag)] 00183 flags['c_flags'] = " ".join(flags['c_flags']) 00184 flags['ld_flags'] = " ".join(flags['ld_flags']) 00185 return flags 00186 00187 def format_src (self, srcs): 00188 """Make sources into the named tuple for use in the template""" 00189 grouped = self.group_project_files(srcs) 00190 for group, files in grouped.items(): 00191 grouped[group] = sorted(list(self.uv_files (files)), 00192 key=lambda tuple: tuple[2].lower()) 00193 return grouped 00194 00195 @staticmethod 00196 def format_fpu (core): 00197 """Generate a core's FPU string""" 00198 if core.endswith("FD"): 00199 return "FPU3(DFPU)" 00200 elif core.endswith("F"): 00201 return "FPU2" 00202 else: 00203 return "" 00204 00205 def generate (self): 00206 """Generate the .uvproj file""" 00207 cache = Cache(True, False) 00208 00209 srcs = self.resources.headers + self.resources.s_sources + \ 00210 self.resources.c_sources + self.resources.cpp_sources + \ 00211 self.resources.objects + self.resources.libraries 00212 ctx = { 00213 'name': self.project_name, 00214 # project_files => dict of generators - file group to generator of 00215 # UVFile tuples defined above 00216 'project_files': sorted(list(self.format_src (srcs).items()), 00217 key=lambda tuple: tuple[0].lower()), 00218 'include_paths': ';'.join(self.filter_dot(d) for d in 00219 self.resources.inc_dirs).encode('utf-8'), 00220 'device': DeviceUvision(self.target), 00221 } 00222 sct_file = self.resources.linker_script 00223 ctx['linker_script'] = self.toolchain.correct_scatter_shebang( 00224 sct_file, self.resources.file_basepath[sct_file]) 00225 if ctx['linker_script'] != sct_file: 00226 self.generated_files.append(ctx['linker_script']) 00227 core = ctx['device'].core 00228 ctx['cputype'] = core.rstrip("FD") 00229 if core.endswith("FD"): 00230 ctx['fpu_setting'] = 3 00231 elif core.endswith("F"): 00232 ctx['fpu_setting'] = 2 00233 else: 00234 ctx['fpu_setting'] = 1 00235 ctx['fputype'] = self.format_fpu (core) 00236 ctx.update(self.format_flags ()) 00237 self.gen_file('uvision/uvision.tmpl', ctx, self.project_name+".uvprojx") 00238 self.gen_file('uvision/uvision_debug.tmpl', ctx, self.project_name + ".uvoptx") 00239 00240 @staticmethod 00241 def clean (project_name): 00242 os.remove(project_name + ".uvprojx") 00243 os.remove(project_name + ".uvoptx") 00244 # legacy .build directory cleaned if exists 00245 if exists('.build'): 00246 shutil.rmtree('.build') 00247 if exists('BUILD'): 00248 shutil.rmtree('BUILD') 00249 00250 @staticmethod 00251 def build (project_name, log_name='build_log.txt', cleanup=True): 00252 """ Build Uvision project """ 00253 # > UV4 -r -j0 -o [log_name] [project_name].uvprojx 00254 proj_file = project_name + ".uvprojx" 00255 cmd = ['UV4', '-r', '-j0', '-o', log_name, proj_file] 00256 00257 # Build the project 00258 p = Popen(cmd, stdout=PIPE, stderr=PIPE) 00259 out, err = p.communicate() 00260 ret_code = p.returncode 00261 00262 # Print the log file to stdout 00263 with open(log_name, 'r') as f: 00264 print(f.read()) 00265 00266 # Cleanup the exported and built files 00267 if cleanup: 00268 os.remove(log_name) 00269 Uvision.clean(project_name) 00270 00271 # Returns 0 upon success, 1 upon a warning, and neither upon an error 00272 if ret_code != 0 and ret_code != 1: 00273 # Seems like something went wrong. 00274 return -1 00275 else: 00276 return 0
Generated on Tue Jul 12 2022 12:21:33 by
