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.
Diff: export/uvision/__init__.py
- Revision:
- 31:8ea194f6145b
- Child:
- 35:da9c89f8be7d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/export/uvision/__init__.py Wed Jan 04 11:58:24 2017 -0600
@@ -0,0 +1,245 @@
+import os
+from os.path import sep, normpath, join, exists
+import ntpath
+import copy
+from collections import namedtuple
+import shutil
+from subprocess import Popen, PIPE
+import re
+
+from tools.arm_pack_manager import Cache
+from tools.targets import TARGET_MAP
+from tools.export.exporters import Exporter
+from tools.export.cmsis import DeviceCMSIS
+
+cache_d = False
+
+
+class DeviceUvision(DeviceCMSIS):
+ """Uvision Device class, inherits CMSIS Device class
+
+ Encapsulates information necessary for uvision project targets"""
+ def __init__(self, target):
+ DeviceCMSIS.__init__(self, target)
+ dev_format = "$$Device:{0}${1}"
+ self.svd = ''
+ if self.debug_svd:
+ self.svd = dev_format.format(self.dname, self.debug_svd)
+ self.reg_file = dev_format.format(self.dname, self.compile_header)
+ self.debug_interface = self.uv_debug()
+ self.flash_dll = self.generate_flash_dll()
+
+ def uv_debug(self):
+ """Return a namedtuple of information about uvision debug settings"""
+ UVDebug = namedtuple('UVDebug',['bin_loc','core_flag', 'key'])
+
+ # CortexMXn => pCMX
+ cpu = self.core.replace("Cortex-", "C")
+ cpu = cpu.replace("+", "")
+ cpu = cpu.replace("F", "")
+ cpu_flag = "p"+cpu
+
+ # Locations found in Keil_v5/TOOLS.INI
+ debuggers = {"st-link": ('STLink\\ST-LINKIII-KEIL_SWO.dll', 'ST-LINKIII-KEIL_SWO'),
+ "j-link":('Segger\\JL2CM3.dll', 'JL2CM3'),
+ "cmsis-dap":('BIN\\CMSIS_AGDI.dll', 'CMSIS_AGDI'),
+ "nulink":('NULink\\Nu_Link.dll','Nu_Link')}
+ res = debuggers[self.debug.lower()]
+ binary = res[0]
+ key = res[1]
+
+ return UVDebug(binary, cpu_flag, key)
+
+ def generate_flash_dll(self):
+ '''Flash DLL string from uvision
+ S = SW/JTAG Clock ID
+ C = CPU index in JTAG chain
+ P = Access Port
+ For the Options for Target -> Debug tab -> settings -> "Flash" tab in the dialog:
+ FD = RAM Start for Flash Functions
+ FC = RAM Size for Flash Functions
+ FN = Number of Flash types
+ FF = Flash File Name (without an extension)
+ FS = Start Address of the Flash Device
+ FL = Size of the Flash Device
+ FP = Full path to the Device algorithm (RTE)
+
+ Necessary to flash some targets. Info gathered from algorithms field of pdsc file.
+ '''
+ fl_count = 0
+ def get_mem_no_x(mem_str):
+ mem_reg = "\dx(\w+)"
+ m = re.search(mem_reg, mem_str)
+ return m.group(1) if m else None
+
+ RAMS = [(get_mem_no_x(info["start"]), get_mem_no_x(info["size"]))
+ for mem, info in self.target_info["memory"].items() if "RAM" in mem]
+ format_str = "UL2CM3(-S0 -C0 -P0 -FD{ramstart}"+" -FC{ramsize} "+"-FN{num_algos} {extra_flags})"
+ ramstart = ''
+ #Default according to Keil developer
+ ramsize = '1000'
+ if len(RAMS)>=1:
+ ramstart = RAMS[0][0]
+ extra_flags = []
+ for name, info in self.target_info["algorithm"].items():
+ if not name or not info:
+ continue
+ if int(info["default"])==0:
+ continue
+ name_reg = "\w*/([\w_]+)\.flm"
+ m = re.search(name_reg, name.lower())
+ fl_name = m.group(1) if m else None
+ name_flag = "-FF" + str(fl_count) + fl_name
+
+ start, size = get_mem_no_x(info["start"]), get_mem_no_x(info["size"])
+ rom_start_flag = "-FS"+str(fl_count)+str(start)
+ rom_size_flag = "-FL" + str(fl_count) + str(size)
+
+ if info["ramstart"] is not None and info["ramsize"] is not None:
+ ramstart = get_mem_no_x(info["ramstart"])
+ ramsize = get_mem_no_x(info["ramsize"])
+
+ path_flag = "-FP" + str(fl_count) + "($$Device:"+self.dname+"$"+name+")"
+
+ extra_flags.extend([name_flag, rom_start_flag, rom_size_flag, path_flag])
+ fl_count += 1
+
+ extra = " ".join(extra_flags)
+ return format_str.format(ramstart=ramstart,
+ ramsize=ramsize,
+ extra_flags=extra, num_algos=fl_count)
+
+
+class Uvision(Exporter):
+ """Keil Uvision class
+
+ This class encapsulates information to be contained in a Uvision
+ project file (.uvprojx).
+ The needed information can be viewed in uvision.tmpl
+ """
+ NAME = 'uvision5'
+ TOOLCHAIN = 'ARM'
+ TARGETS = []
+ for target, obj in TARGET_MAP.iteritems():
+ if not ("ARM" in obj.supported_toolchains and hasattr(obj, "device_name")):
+ continue
+ if not DeviceCMSIS.check_supported(target):
+ continue
+ TARGETS.append(target)
+ #File associations within .uvprojx file
+ file_types = {'.cpp': 8, '.c': 1, '.s': 2,
+ '.obj': 3, '.o': 3, '.lib': 4,
+ '.ar': 4, '.h': 5, '.hpp': 5, '.sct': 4}
+
+ def uv_files(self, files):
+ """An generator containing Uvision specific information about project files
+ Positional Arguments:
+ files - the location of source files
+
+ .uvprojx XML for project file:
+ <File>
+ <FileType>{{file.type}}</FileType>
+ <FileName>{{file.name}}</FileName>
+ <FilePath>{{file.loc}}</FilePath>
+ </File>
+ """
+ for loc in files:
+ #Encapsulates the information necessary for template entry above
+ UVFile = namedtuple('UVFile', ['type','loc','name'])
+ _, ext = os.path.splitext(loc)
+ if ext.lower() in self.file_types:
+ type = self.file_types[ext.lower()]
+ name = ntpath.basename(normpath(loc))
+ yield UVFile(type, loc, name)
+
+ def format_flags(self):
+ """Format toolchain flags for Uvision"""
+ flags = copy.deepcopy(self.flags)
+ asm_flag_string = '--cpreproc --cpreproc_opts=-D__ASSERT_MSG,' + \
+ ",".join(flags['asm_flags'])
+ # asm flags only, common are not valid within uvision project,
+ # they are armcc specific
+ flags['asm_flags'] = asm_flag_string
+ # cxx flags included, as uvision have them all in one tab
+ flags['c_flags'] = list(set(['-D__ASSERT_MSG']
+ + flags['common_flags']
+ + flags['c_flags']
+ + flags['cxx_flags']))
+ # not compatible with c99 flag set in the template
+ try: flags['c_flags'].remove("--c99")
+ except ValueError: pass
+ # cpp is not required as it's implicit for cpp files
+ try: flags['c_flags'].remove("--cpp")
+ except ValueError: pass
+ # we want no-vla for only cxx, but it's also applied for C in IDE,
+ # thus we remove it
+ try: flags['c_flags'].remove("--no_vla")
+ except ValueError: pass
+ flags['c_flags'] =" ".join(flags['c_flags'])
+ return flags
+
+ def format_src(self, srcs):
+ """Make sources into the named tuple for use in the template"""
+ grouped = self.group_project_files(srcs)
+ for group, files in grouped.items():
+ grouped[group] = self.uv_files(files)
+ return grouped
+
+ def generate(self):
+ """Generate the .uvproj file"""
+ cache = Cache(True, False)
+ if cache_d:
+ cache.cache_descriptors()
+
+ srcs = self.resources.headers + self.resources.s_sources + \
+ self.resources.c_sources + self.resources.cpp_sources + \
+ self.resources.objects + self.resources.libraries
+ ctx = {
+ 'name': self.project_name,
+ # project_files => dict of generators - file group to generator of
+ # UVFile tuples defined above
+ 'project_files': self.format_src(srcs),
+ 'linker_script':self.resources.linker_script,
+ 'include_paths': '; '.join(self.resources.inc_dirs).encode('utf-8'),
+ 'device': DeviceUvision(self.target),
+ }
+ # Turn on FPU optimizations if the core has an FPU
+ ctx['fpu_setting'] = 1 if 'f' not in ctx['device'].core.lower() \
+ or 'd' in ctx['device'].core.lower() else 2
+ ctx.update(self.format_flags())
+ self.gen_file('uvision/uvision.tmpl', ctx, self.project_name+".uvprojx")
+ self.gen_file('uvision/uvision_debug.tmpl', ctx, self.project_name + ".uvoptx")
+
+ @staticmethod
+ def build(project_name, log_name='build_log.txt', cleanup=True):
+ """ Build Uvision project """
+ # > UV4 -r -j0 -o [log_name] [project_name].uvprojx
+ proj_file = project_name + ".uvprojx"
+ cmd = ['UV4', '-r', '-j0', '-o', log_name, proj_file]
+
+ # Build the project
+ p = Popen(cmd, stdout=PIPE, stderr=PIPE)
+ out, err = p.communicate()
+ ret_code = p.returncode
+
+ # Print the log file to stdout
+ with open(log_name, 'r') as f:
+ print f.read()
+
+ # Cleanup the exported and built files
+ if cleanup:
+ os.remove(log_name)
+ os.remove(project_name+".uvprojx")
+ os.remove(project_name+".uvoptx")
+ # legacy .build directory cleaned if exists
+ if exists('.build'):
+ shutil.rmtree('.build')
+ if exists('BUILD'):
+ shutil.rmtree('BUILD')
+
+ # Returns 0 upon success, 1 upon a warning, and neither upon an error
+ if ret_code != 0 and ret_code != 1:
+ # Seems like something went wrong.
+ return -1
+ else:
+ return 0
