mbed-os

Dependents:   cobaLCDJoyMotor_Thread odometry_omni_3roda_v3 odometry_omni_3roda_v1 odometry_omni_3roda_v2 ... more

Committer:
be_bryan
Date:
Mon Dec 11 17:54:04 2017 +0000
Revision:
0:b74591d5ab33
motor ++

Who changed what in which revision?

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