Clone of official tools

Committer:
theotherjimmy
Date:
Wed Oct 25 14:46:50 2017 -0500
Revision:
41:2a77626a4c21
Parent:
40:7d3fa6b99b2b
Child:
43:2a7da56ebd24
Update to track Mbed OS 5.6.3

Who changed what in which revision?

UserRevisionLine numberNew contents of line
The Other Jimmy 31:8ea194f6145b 1 import os
The Other Jimmy 31:8ea194f6145b 2 from os.path import sep, normpath, join, exists
The Other Jimmy 31:8ea194f6145b 3 import ntpath
The Other Jimmy 31:8ea194f6145b 4 import copy
The Other Jimmy 31:8ea194f6145b 5 from collections import namedtuple
The Other Jimmy 31:8ea194f6145b 6 import shutil
The Other Jimmy 31:8ea194f6145b 7 from subprocess import Popen, PIPE
The Other Jimmy 31:8ea194f6145b 8 import re
The Other Jimmy 31:8ea194f6145b 9
The Other Jimmy 31:8ea194f6145b 10 from tools.arm_pack_manager import Cache
The Other Jimmy 31:8ea194f6145b 11 from tools.targets import TARGET_MAP
theotherjimmy 40:7d3fa6b99b2b 12 from tools.export.exporters import Exporter, apply_supported_whitelist
The Other Jimmy 31:8ea194f6145b 13 from tools.export.cmsis import DeviceCMSIS
The Other Jimmy 31:8ea194f6145b 14
The Other Jimmy 31:8ea194f6145b 15 cache_d = False
The Other Jimmy 31:8ea194f6145b 16
The Other Jimmy 31:8ea194f6145b 17
The Other Jimmy 31:8ea194f6145b 18 class DeviceUvision(DeviceCMSIS):
The Other Jimmy 31:8ea194f6145b 19 """Uvision Device class, inherits CMSIS Device class
The Other Jimmy 31:8ea194f6145b 20
The Other Jimmy 31:8ea194f6145b 21 Encapsulates information necessary for uvision project targets"""
The Other Jimmy 31:8ea194f6145b 22 def __init__(self, target):
The Other Jimmy 31:8ea194f6145b 23 DeviceCMSIS.__init__(self, target)
The Other Jimmy 31:8ea194f6145b 24 dev_format = "$$Device:{0}${1}"
The Other Jimmy 31:8ea194f6145b 25 self.svd = ''
The Other Jimmy 31:8ea194f6145b 26 if self.debug_svd:
The Other Jimmy 31:8ea194f6145b 27 self.svd = dev_format.format(self.dname, self.debug_svd)
The Other Jimmy 31:8ea194f6145b 28 self.reg_file = dev_format.format(self.dname, self.compile_header)
The Other Jimmy 31:8ea194f6145b 29 self.debug_interface = self.uv_debug()
The Other Jimmy 31:8ea194f6145b 30 self.flash_dll = self.generate_flash_dll()
The Other Jimmy 31:8ea194f6145b 31
The Other Jimmy 31:8ea194f6145b 32 def uv_debug(self):
The Other Jimmy 31:8ea194f6145b 33 """Return a namedtuple of information about uvision debug settings"""
The Other Jimmy 31:8ea194f6145b 34 UVDebug = namedtuple('UVDebug',['bin_loc','core_flag', 'key'])
The Other Jimmy 31:8ea194f6145b 35
The Other Jimmy 31:8ea194f6145b 36 # CortexMXn => pCMX
The Other Jimmy 31:8ea194f6145b 37 cpu = self.core.replace("Cortex-", "C")
The Other Jimmy 31:8ea194f6145b 38 cpu = cpu.replace("+", "")
The Other Jimmy 31:8ea194f6145b 39 cpu = cpu.replace("F", "")
The Other Jimmy 31:8ea194f6145b 40 cpu_flag = "p"+cpu
The Other Jimmy 31:8ea194f6145b 41
The Other Jimmy 31:8ea194f6145b 42 # Locations found in Keil_v5/TOOLS.INI
The Other Jimmy 31:8ea194f6145b 43 debuggers = {"st-link": ('STLink\\ST-LINKIII-KEIL_SWO.dll', 'ST-LINKIII-KEIL_SWO'),
The Other Jimmy 31:8ea194f6145b 44 "j-link":('Segger\\JL2CM3.dll', 'JL2CM3'),
The Other Jimmy 31:8ea194f6145b 45 "cmsis-dap":('BIN\\CMSIS_AGDI.dll', 'CMSIS_AGDI'),
The Other Jimmy 31:8ea194f6145b 46 "nulink":('NULink\\Nu_Link.dll','Nu_Link')}
The Other Jimmy 31:8ea194f6145b 47 res = debuggers[self.debug.lower()]
The Other Jimmy 31:8ea194f6145b 48 binary = res[0]
The Other Jimmy 31:8ea194f6145b 49 key = res[1]
The Other Jimmy 31:8ea194f6145b 50
The Other Jimmy 31:8ea194f6145b 51 return UVDebug(binary, cpu_flag, key)
The Other Jimmy 31:8ea194f6145b 52
The Other Jimmy 31:8ea194f6145b 53 def generate_flash_dll(self):
The Other Jimmy 31:8ea194f6145b 54 '''Flash DLL string from uvision
The Other Jimmy 31:8ea194f6145b 55 S = SW/JTAG Clock ID
The Other Jimmy 31:8ea194f6145b 56 C = CPU index in JTAG chain
The Other Jimmy 31:8ea194f6145b 57 P = Access Port
The Other Jimmy 31:8ea194f6145b 58 For the Options for Target -> Debug tab -> settings -> "Flash" tab in the dialog:
The Other Jimmy 31:8ea194f6145b 59 FD = RAM Start for Flash Functions
The Other Jimmy 31:8ea194f6145b 60 FC = RAM Size for Flash Functions
The Other Jimmy 31:8ea194f6145b 61 FN = Number of Flash types
The Other Jimmy 31:8ea194f6145b 62 FF = Flash File Name (without an extension)
The Other Jimmy 31:8ea194f6145b 63 FS = Start Address of the Flash Device
The Other Jimmy 31:8ea194f6145b 64 FL = Size of the Flash Device
The Other Jimmy 31:8ea194f6145b 65 FP = Full path to the Device algorithm (RTE)
The Other Jimmy 31:8ea194f6145b 66
The Other Jimmy 31:8ea194f6145b 67 Necessary to flash some targets. Info gathered from algorithms field of pdsc file.
The Other Jimmy 31:8ea194f6145b 68 '''
The Other Jimmy 31:8ea194f6145b 69 fl_count = 0
The Other Jimmy 31:8ea194f6145b 70 def get_mem_no_x(mem_str):
The Other Jimmy 31:8ea194f6145b 71 mem_reg = "\dx(\w+)"
The Other Jimmy 31:8ea194f6145b 72 m = re.search(mem_reg, mem_str)
The Other Jimmy 31:8ea194f6145b 73 return m.group(1) if m else None
The Other Jimmy 31:8ea194f6145b 74
The Other Jimmy 31:8ea194f6145b 75 RAMS = [(get_mem_no_x(info["start"]), get_mem_no_x(info["size"]))
The Other Jimmy 31:8ea194f6145b 76 for mem, info in self.target_info["memory"].items() if "RAM" in mem]
The Other Jimmy 31:8ea194f6145b 77 format_str = "UL2CM3(-S0 -C0 -P0 -FD{ramstart}"+" -FC{ramsize} "+"-FN{num_algos} {extra_flags})"
The Other Jimmy 31:8ea194f6145b 78 ramstart = ''
The Other Jimmy 31:8ea194f6145b 79 #Default according to Keil developer
The Other Jimmy 31:8ea194f6145b 80 ramsize = '1000'
The Other Jimmy 31:8ea194f6145b 81 if len(RAMS)>=1:
The Other Jimmy 31:8ea194f6145b 82 ramstart = RAMS[0][0]
The Other Jimmy 31:8ea194f6145b 83 extra_flags = []
The Other Jimmy 31:8ea194f6145b 84 for name, info in self.target_info["algorithm"].items():
The Other Jimmy 31:8ea194f6145b 85 if not name or not info:
The Other Jimmy 31:8ea194f6145b 86 continue
The Other Jimmy 31:8ea194f6145b 87 if int(info["default"])==0:
The Other Jimmy 31:8ea194f6145b 88 continue
The Other Jimmy 31:8ea194f6145b 89 name_reg = "\w*/([\w_]+)\.flm"
The Other Jimmy 31:8ea194f6145b 90 m = re.search(name_reg, name.lower())
The Other Jimmy 31:8ea194f6145b 91 fl_name = m.group(1) if m else None
The Other Jimmy 31:8ea194f6145b 92 name_flag = "-FF" + str(fl_count) + fl_name
The Other Jimmy 31:8ea194f6145b 93
The Other Jimmy 31:8ea194f6145b 94 start, size = get_mem_no_x(info["start"]), get_mem_no_x(info["size"])
The Other Jimmy 31:8ea194f6145b 95 rom_start_flag = "-FS"+str(fl_count)+str(start)
The Other Jimmy 31:8ea194f6145b 96 rom_size_flag = "-FL" + str(fl_count) + str(size)
The Other Jimmy 31:8ea194f6145b 97
The Other Jimmy 31:8ea194f6145b 98 if info["ramstart"] is not None and info["ramsize"] is not None:
The Other Jimmy 31:8ea194f6145b 99 ramstart = get_mem_no_x(info["ramstart"])
The Other Jimmy 31:8ea194f6145b 100 ramsize = get_mem_no_x(info["ramsize"])
The Other Jimmy 31:8ea194f6145b 101
The Other Jimmy 31:8ea194f6145b 102 path_flag = "-FP" + str(fl_count) + "($$Device:"+self.dname+"$"+name+")"
The Other Jimmy 31:8ea194f6145b 103
The Other Jimmy 31:8ea194f6145b 104 extra_flags.extend([name_flag, rom_start_flag, rom_size_flag, path_flag])
The Other Jimmy 31:8ea194f6145b 105 fl_count += 1
The Other Jimmy 31:8ea194f6145b 106
The Other Jimmy 31:8ea194f6145b 107 extra = " ".join(extra_flags)
The Other Jimmy 31:8ea194f6145b 108 return format_str.format(ramstart=ramstart,
The Other Jimmy 31:8ea194f6145b 109 ramsize=ramsize,
The Other Jimmy 31:8ea194f6145b 110 extra_flags=extra, num_algos=fl_count)
The Other Jimmy 31:8ea194f6145b 111
The Other Jimmy 31:8ea194f6145b 112
The Other Jimmy 31:8ea194f6145b 113 class Uvision(Exporter):
The Other Jimmy 31:8ea194f6145b 114 """Keil Uvision class
The Other Jimmy 31:8ea194f6145b 115
The Other Jimmy 31:8ea194f6145b 116 This class encapsulates information to be contained in a Uvision
The Other Jimmy 31:8ea194f6145b 117 project file (.uvprojx).
The Other Jimmy 31:8ea194f6145b 118 The needed information can be viewed in uvision.tmpl
The Other Jimmy 31:8ea194f6145b 119 """
The Other Jimmy 31:8ea194f6145b 120 NAME = 'uvision5'
The Other Jimmy 31:8ea194f6145b 121 TOOLCHAIN = 'ARM'
The Other Jimmy 36:96847d42f010 122
The Other Jimmy 36:96847d42f010 123 POST_BINARY_WHITELIST = set([
The Other Jimmy 36:96847d42f010 124 "MCU_NRF51Code.binary_hook",
The Other Jimmy 36:96847d42f010 125 "TEENSY3_1Code.binary_hook",
The Other Jimmy 36:96847d42f010 126 "LPCTargetCode.lpc_patch",
The Other Jimmy 36:96847d42f010 127 "LPC4088Code.binary_hook",
The Other Jimmy 36:96847d42f010 128 "MTSCode.combine_bins_mts_dot",
The Other Jimmy 36:96847d42f010 129 "MTSCode.combine_bins_mts_dragonfly",
The Other Jimmy 36:96847d42f010 130 "NCS36510TargetCode.ncs36510_addfib"
The Other Jimmy 36:96847d42f010 131 ])
theotherjimmy 40:7d3fa6b99b2b 132
theotherjimmy 40:7d3fa6b99b2b 133 @classmethod
theotherjimmy 40:7d3fa6b99b2b 134 def is_target_supported(cls, target_name):
theotherjimmy 40:7d3fa6b99b2b 135 target = TARGET_MAP[target_name]
theotherjimmy 40:7d3fa6b99b2b 136 return apply_supported_whitelist(
theotherjimmy 40:7d3fa6b99b2b 137 cls.TOOLCHAIN, cls.POST_BINARY_WHITELIST, target) and\
theotherjimmy 40:7d3fa6b99b2b 138 DeviceCMSIS.check_supported(target_name)
The Other Jimmy 36:96847d42f010 139
The Other Jimmy 31:8ea194f6145b 140 #File associations within .uvprojx file
The Other Jimmy 31:8ea194f6145b 141 file_types = {'.cpp': 8, '.c': 1, '.s': 2,
The Other Jimmy 31:8ea194f6145b 142 '.obj': 3, '.o': 3, '.lib': 4,
The Other Jimmy 31:8ea194f6145b 143 '.ar': 4, '.h': 5, '.hpp': 5, '.sct': 4}
The Other Jimmy 31:8ea194f6145b 144
The Other Jimmy 31:8ea194f6145b 145 def uv_files(self, files):
The Other Jimmy 31:8ea194f6145b 146 """An generator containing Uvision specific information about project files
The Other Jimmy 31:8ea194f6145b 147 Positional Arguments:
The Other Jimmy 31:8ea194f6145b 148 files - the location of source files
The Other Jimmy 31:8ea194f6145b 149
The Other Jimmy 31:8ea194f6145b 150 .uvprojx XML for project file:
The Other Jimmy 31:8ea194f6145b 151 <File>
The Other Jimmy 31:8ea194f6145b 152 <FileType>{{file.type}}</FileType>
The Other Jimmy 31:8ea194f6145b 153 <FileName>{{file.name}}</FileName>
The Other Jimmy 31:8ea194f6145b 154 <FilePath>{{file.loc}}</FilePath>
The Other Jimmy 31:8ea194f6145b 155 </File>
The Other Jimmy 31:8ea194f6145b 156 """
The Other Jimmy 31:8ea194f6145b 157 for loc in files:
The Other Jimmy 31:8ea194f6145b 158 #Encapsulates the information necessary for template entry above
The Other Jimmy 31:8ea194f6145b 159 UVFile = namedtuple('UVFile', ['type','loc','name'])
The Other Jimmy 31:8ea194f6145b 160 _, ext = os.path.splitext(loc)
The Other Jimmy 31:8ea194f6145b 161 if ext.lower() in self.file_types:
The Other Jimmy 31:8ea194f6145b 162 type = self.file_types[ext.lower()]
The Other Jimmy 31:8ea194f6145b 163 name = ntpath.basename(normpath(loc))
The Other Jimmy 31:8ea194f6145b 164 yield UVFile(type, loc, name)
The Other Jimmy 31:8ea194f6145b 165
The Other Jimmy 31:8ea194f6145b 166 def format_flags(self):
The Other Jimmy 31:8ea194f6145b 167 """Format toolchain flags for Uvision"""
The Other Jimmy 31:8ea194f6145b 168 flags = copy.deepcopy(self.flags)
The Other Jimmy 35:da9c89f8be7d 169 # to be preprocessed with armcc
theotherjimmy 40:7d3fa6b99b2b 170 asm_flag_string = (
theotherjimmy 40:7d3fa6b99b2b 171 '--cpreproc --cpreproc_opts=-D__ASSERT_MSG,' +
theotherjimmy 40:7d3fa6b99b2b 172 ",".join(filter(lambda f: f.startswith("-D"), flags['asm_flags'])))
The Other Jimmy 31:8ea194f6145b 173 flags['asm_flags'] = asm_flag_string
The Other Jimmy 35:da9c89f8be7d 174 # All non-asm flags are in one template field
The Other Jimmy 35:da9c89f8be7d 175 c_flags = list(set(flags['c_flags'] + flags['cxx_flags'] +flags['common_flags']))
theotherjimmy 40:7d3fa6b99b2b 176 ld_flags = list(set(flags['ld_flags'] ))
The Other Jimmy 35:da9c89f8be7d 177 # These flags are in template to be set by user i n IDE
The Other Jimmy 35:da9c89f8be7d 178 template = ["--no_vla", "--cpp", "--c99"]
The Other Jimmy 35:da9c89f8be7d 179 # Flag is invalid if set in template
The Other Jimmy 35:da9c89f8be7d 180 # Optimizations are also set in the template
The Other Jimmy 35:da9c89f8be7d 181 invalid_flag = lambda x: x in template or re.match("-O(\d|time)", x)
The Other Jimmy 36:96847d42f010 182 flags['c_flags'] = [flag.replace('"','\\"') for flag in c_flags if not invalid_flag(flag)]
The Other Jimmy 35:da9c89f8be7d 183 flags['c_flags'] = " ".join(flags['c_flags'])
theotherjimmy 40:7d3fa6b99b2b 184 flags['ld_flags'] = " ".join(flags['ld_flags'])
The Other Jimmy 31:8ea194f6145b 185 return flags
The Other Jimmy 31:8ea194f6145b 186
The Other Jimmy 31:8ea194f6145b 187 def format_src(self, srcs):
The Other Jimmy 31:8ea194f6145b 188 """Make sources into the named tuple for use in the template"""
The Other Jimmy 31:8ea194f6145b 189 grouped = self.group_project_files(srcs)
The Other Jimmy 31:8ea194f6145b 190 for group, files in grouped.items():
The Other Jimmy 35:da9c89f8be7d 191 grouped[group] = sorted(list(self.uv_files(files)),
The Other Jimmy 35:da9c89f8be7d 192 key=lambda (_, __, name): name.lower())
The Other Jimmy 31:8ea194f6145b 193 return grouped
The Other Jimmy 31:8ea194f6145b 194
The Other Jimmy 36:96847d42f010 195 @staticmethod
The Other Jimmy 36:96847d42f010 196 def format_fpu(core):
The Other Jimmy 36:96847d42f010 197 """Generate a core's FPU string"""
The Other Jimmy 36:96847d42f010 198 if core.endswith("FD"):
The Other Jimmy 36:96847d42f010 199 return "FPU3(DFPU)"
The Other Jimmy 36:96847d42f010 200 elif core.endswith("F"):
The Other Jimmy 36:96847d42f010 201 return "FPU2"
The Other Jimmy 36:96847d42f010 202 else:
The Other Jimmy 36:96847d42f010 203 return ""
The Other Jimmy 36:96847d42f010 204
The Other Jimmy 31:8ea194f6145b 205 def generate(self):
The Other Jimmy 31:8ea194f6145b 206 """Generate the .uvproj file"""
The Other Jimmy 31:8ea194f6145b 207 cache = Cache(True, False)
The Other Jimmy 31:8ea194f6145b 208 if cache_d:
The Other Jimmy 31:8ea194f6145b 209 cache.cache_descriptors()
The Other Jimmy 31:8ea194f6145b 210
The Other Jimmy 31:8ea194f6145b 211 srcs = self.resources.headers + self.resources.s_sources + \
The Other Jimmy 31:8ea194f6145b 212 self.resources.c_sources + self.resources.cpp_sources + \
The Other Jimmy 31:8ea194f6145b 213 self.resources.objects + self.resources.libraries
The Other Jimmy 31:8ea194f6145b 214 ctx = {
The Other Jimmy 31:8ea194f6145b 215 'name': self.project_name,
The Other Jimmy 31:8ea194f6145b 216 # project_files => dict of generators - file group to generator of
The Other Jimmy 31:8ea194f6145b 217 # UVFile tuples defined above
The Other Jimmy 35:da9c89f8be7d 218 'project_files': sorted(list(self.format_src(srcs).iteritems()),
The Other Jimmy 35:da9c89f8be7d 219 key=lambda (group, _): group.lower()),
theotherjimmy 40:7d3fa6b99b2b 220 'linker_script':self.toolchain.correct_scatter_shebang(
theotherjimmy 40:7d3fa6b99b2b 221 self.resources.linker_script),
The Other Jimmy 31:8ea194f6145b 222 'include_paths': '; '.join(self.resources.inc_dirs).encode('utf-8'),
The Other Jimmy 31:8ea194f6145b 223 'device': DeviceUvision(self.target),
The Other Jimmy 31:8ea194f6145b 224 }
theotherjimmy 41:2a77626a4c21 225 if ctx['linker_script'] is not self.resources.linker_script:
theotherjimmy 41:2a77626a4c21 226 self.generated_files.append(ctx['linker_script'])
The Other Jimmy 36:96847d42f010 227 core = ctx['device'].core
The Other Jimmy 36:96847d42f010 228 ctx['cputype'] = core.rstrip("FD")
The Other Jimmy 36:96847d42f010 229 if core.endswith("FD"):
The Other Jimmy 36:96847d42f010 230 ctx['fpu_setting'] = 3
The Other Jimmy 36:96847d42f010 231 elif core.endswith("F"):
The Other Jimmy 36:96847d42f010 232 ctx['fpu_setting'] = 2
The Other Jimmy 36:96847d42f010 233 else:
The Other Jimmy 36:96847d42f010 234 ctx['fpu_setting'] = 1
The Other Jimmy 36:96847d42f010 235 ctx['fputype'] = self.format_fpu(core)
The Other Jimmy 31:8ea194f6145b 236 ctx.update(self.format_flags())
The Other Jimmy 31:8ea194f6145b 237 self.gen_file('uvision/uvision.tmpl', ctx, self.project_name+".uvprojx")
The Other Jimmy 31:8ea194f6145b 238 self.gen_file('uvision/uvision_debug.tmpl', ctx, self.project_name + ".uvoptx")
The Other Jimmy 31:8ea194f6145b 239
The Other Jimmy 31:8ea194f6145b 240 @staticmethod
The Other Jimmy 31:8ea194f6145b 241 def build(project_name, log_name='build_log.txt', cleanup=True):
The Other Jimmy 31:8ea194f6145b 242 """ Build Uvision project """
The Other Jimmy 31:8ea194f6145b 243 # > UV4 -r -j0 -o [log_name] [project_name].uvprojx
The Other Jimmy 31:8ea194f6145b 244 proj_file = project_name + ".uvprojx"
The Other Jimmy 31:8ea194f6145b 245 cmd = ['UV4', '-r', '-j0', '-o', log_name, proj_file]
The Other Jimmy 31:8ea194f6145b 246
The Other Jimmy 31:8ea194f6145b 247 # Build the project
The Other Jimmy 31:8ea194f6145b 248 p = Popen(cmd, stdout=PIPE, stderr=PIPE)
The Other Jimmy 31:8ea194f6145b 249 out, err = p.communicate()
The Other Jimmy 31:8ea194f6145b 250 ret_code = p.returncode
The Other Jimmy 31:8ea194f6145b 251
The Other Jimmy 31:8ea194f6145b 252 # Print the log file to stdout
The Other Jimmy 31:8ea194f6145b 253 with open(log_name, 'r') as f:
The Other Jimmy 31:8ea194f6145b 254 print f.read()
The Other Jimmy 31:8ea194f6145b 255
The Other Jimmy 31:8ea194f6145b 256 # Cleanup the exported and built files
The Other Jimmy 31:8ea194f6145b 257 if cleanup:
The Other Jimmy 31:8ea194f6145b 258 os.remove(log_name)
The Other Jimmy 31:8ea194f6145b 259 os.remove(project_name+".uvprojx")
The Other Jimmy 31:8ea194f6145b 260 os.remove(project_name+".uvoptx")
The Other Jimmy 31:8ea194f6145b 261 # legacy .build directory cleaned if exists
The Other Jimmy 31:8ea194f6145b 262 if exists('.build'):
The Other Jimmy 31:8ea194f6145b 263 shutil.rmtree('.build')
The Other Jimmy 31:8ea194f6145b 264 if exists('BUILD'):
The Other Jimmy 31:8ea194f6145b 265 shutil.rmtree('BUILD')
The Other Jimmy 31:8ea194f6145b 266
The Other Jimmy 31:8ea194f6145b 267 # Returns 0 upon success, 1 upon a warning, and neither upon an error
The Other Jimmy 31:8ea194f6145b 268 if ret_code != 0 and ret_code != 1:
The Other Jimmy 31:8ea194f6145b 269 # Seems like something went wrong.
The Other Jimmy 31:8ea194f6145b 270 return -1
The Other Jimmy 31:8ea194f6145b 271 else:
The Other Jimmy 31:8ea194f6145b 272 return 0