Skip to content

Tools: Add Uvision6 exporter #7569

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 11 commits into from
Aug 27, 2018
3 changes: 2 additions & 1 deletion tools/export/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@
cdt, vscode, gnuarmeclipse, qtcreator, cmake, nb, cces, codeblocks)

EXPORTERS = {
u'uvision5': uvision.Uvision,
u'uvision6': uvision.UvisionArmc6,
u'uvision5': uvision.UvisionArmc5,
u'make_gcc_arm': makefile.GccArm,
u'make_armc5': makefile.Armc5,
u'make_armc6': makefile.Armc6,
Expand Down
1 change: 1 addition & 0 deletions tools/export/cmsis/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ def cpu_cmsis(cpu):
cpu = cpu.replace("Cortex-","ARMC")
cpu = cpu.replace("+","P")
cpu = cpu.replace("F","_FP")
cpu = cpu.replace("-NS", "")
return cpu


Expand Down
10 changes: 5 additions & 5 deletions tools/export/exporters.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,10 +112,10 @@ def flags(self):
flags['cxx_flags'] += c_defines
config_header = self.config_header_ref
if config_header:
flags['c_flags'] += self.toolchain.get_config_option(
config_header.name)
flags['cxx_flags'] += self.toolchain.get_config_option(
config_option = self.toolchain.get_config_option(
config_header.name)
flags['c_flags'] += config_option
flags['cxx_flags'] += config_option
return flags

@property
Expand Down Expand Up @@ -150,9 +150,9 @@ def config_header_ref(self):
if config_header:
def is_config_header(f):
return f.path == config_header
return filter(
return list(filter(
is_config_header, self.resources.get_file_refs(FileType.HEADER)
)[0]
))[0]
else:
return None

Expand Down
202 changes: 134 additions & 68 deletions tools/export/uvision/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from builtins import str

import os
from os.path import sep, normpath, join, exists, dirname
from os.path import normpath, exists, dirname
import ntpath
import copy
from collections import namedtuple
Expand All @@ -11,11 +11,11 @@
import re

from tools.resources import FileType
from tools.arm_pack_manager import Cache
from tools.targets import TARGET_MAP
from tools.export.exporters import Exporter, apply_supported_whitelist
from tools.export.exporters import Exporter
from tools.export.cmsis import DeviceCMSIS


class DeviceUvision(DeviceCMSIS):
"""Uvision Device class, inherits CMSIS Device class

Expand All @@ -32,19 +32,23 @@ def __init__(self, target):

def uv_debug(self):
"""Return a namedtuple of information about uvision debug settings"""
UVDebug = namedtuple('UVDebug',['bin_loc','core_flag', 'key'])
UVDebug = namedtuple('UVDebug', ['bin_loc', 'core_flag', 'key'])

# CortexMXn => pCMX
cpu = self.core.replace("Cortex-", "C")
cpu = cpu.replace("+", "")
cpu = cpu.replace("F", "")
cpu = cpu.replace("-NS", "")
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')}
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]
Expand All @@ -56,7 +60,7 @@ def generate_flash_dll(self):
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:
For the Options for Target -> Debug -> settings -> "Flash" dialog:
FD = RAM Start for Flash Functions
FC = RAM Size for Flash Functions
FN = Number of Flash types
Expand All @@ -65,44 +69,55 @@ def generate_flash_dll(self):
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.
Necessary to flash some targets.
'''
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})"
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
# Default according to Keil developer
ramsize = '1000'
if len(RAMS)>=1:
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:
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)
start = get_mem_no_x(info["start"])
size = 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+")"
path_flag = "-FP{}($$Device:{}${})".format(
str(fl_count), self.dname, name
)

extra_flags.extend([name_flag, rom_start_flag, rom_size_flag, path_flag])
extra_flags.extend([
name_flag, rom_start_flag, rom_size_flag, path_flag
])
fl_count += 1

extra = " ".join(extra_flags)
Expand All @@ -118,8 +133,6 @@ class Uvision(Exporter):
project file (.uvprojx).
The needed information can be viewed in uvision.tmpl
"""
NAME = 'uvision5'
TOOLCHAIN = 'ARM'

POST_BINARY_WHITELIST = set([
"MCU_NRF51Code.binary_hook",
Expand All @@ -131,24 +144,7 @@ class Uvision(Exporter):
"NCS36510TargetCode.ncs36510_addfib"
])

@classmethod
def is_target_supported(cls, target_name):
target = TARGET_MAP[target_name]
if not (set(target.supported_toolchains).intersection(
set(["ARM", "uARM"]))):
return False
if not DeviceCMSIS.check_supported(target_name):
return False
if "Cortex-A" in target.core:
return False
if not hasattr(target, "post_binary_hook"):
return True
if target.post_binary_hook['function'] in cls.POST_BINARY_WHITELIST:
return True
else:
return False

#File associations within .uvprojx file
# 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}
Expand All @@ -166,8 +162,8 @@ def uv_files(self, files):
</File>
"""
for loc in files:
#Encapsulates the information necessary for template entry above
UVFile = namedtuple('UVFile', ['type','loc','name'])
# 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()]
Expand All @@ -177,22 +173,40 @@ def uv_files(self, files):
def format_flags(self):
"""Format toolchain flags for Uvision"""
flags = copy.deepcopy(self.flags)
# to be preprocessed with armcc
asm_flag_string = (
'--cpreproc --cpreproc_opts=-D__ASSERT_MSG,' +
",".join(filter(lambda f: f.startswith("-D"), flags['asm_flags'])))
",".join("-D{}".format(s) for s in
self.toolchain.get_symbols(for_asm=True)))
flags['asm_flags'] = asm_flag_string
# All non-asm flags are in one template field
c_flags = list(set(flags['c_flags'] + flags['cxx_flags'] +flags['common_flags']))
ld_flags = list(set(flags['ld_flags'] ))
# These flags are in template to be set by user i n IDE
template = ["--no_vla", "--cpp", "--c99"]
# Flag is invalid if set in template
# Optimizations are also set in the template
invalid_flag = lambda x: x in template or re.match("-O(\d|time)", x)
flags['c_flags'] = [flag.replace('"','\\"') for flag in c_flags if not invalid_flag(flag)]
flags['c_flags'] = " ".join(flags['c_flags'])
flags['ld_flags'] = " ".join(flags['ld_flags'])

config_header = self.config_header_ref
config_option = self.toolchain.get_config_option(config_header.name)
c_flags = set(
flags['c_flags'] + flags['cxx_flags'] + flags['common_flags']
)
in_template = set(
["--no_vla", "--cpp", "--c99", "-MMD"] + config_option
)

def valid_flag(x):
return (
x not in in_template and
not x.startswith("-O") and
not x.startswith("-std") and
not x.startswith("-D")
)

def is_define(s):
return s.startswith("-D") and "(" not in s

flags['c_flags'] = " ".join(
f.replace('"', '\\"') for f in c_flags if valid_flag(f)
)
flags['c_flags'] += " "
flags['c_flags'] += " ".join(config_option)
flags['c_defines'] = " ".join(f[2:].replace('"', '\\"')
for f in c_flags if is_define(f))
flags['ld_flags'] = " ".join(set(flags['ld_flags']))
return flags

def format_src(self, srcs):
Expand All @@ -215,11 +229,11 @@ def format_fpu(core):

def generate(self):
"""Generate the .uvproj file"""
cache = Cache(True, False)

srcs = self.resources.headers + self.resources.s_sources + \
self.resources.c_sources + self.resources.cpp_sources + \
self.resources.objects + self.libraries
srcs = (
self.resources.headers + self.resources.s_sources +
self.resources.c_sources + self.resources.cpp_sources +
self.resources.objects + self.libraries
)
ctx = {
'name': self.project_name,
# project_files => dict of generators - file group to generator of
Expand All @@ -230,23 +244,29 @@ def generate(self):
self.resources.inc_dirs).encode('utf-8'),
'device': DeviceUvision(self.target),
}
sct_name, sct_path = self.resources.get_file_refs(FileType.LD_SCRIPT)[0]
sct_name, sct_path = self.resources.get_file_refs(
FileType.LD_SCRIPT)[0]
ctx['linker_script'] = self.toolchain.correct_scatter_shebang(
sct_path, dirname(sct_name))
if ctx['linker_script'] != sct_path:
self.generated_files.append(ctx['linker_script'])
core = ctx['device'].core
ctx['cputype'] = core.rstrip("FD")
if core.endswith("FD"):
ctx['cputype'] = ctx['device'].core.rstrip("FD").replace("-NS", "")
if ctx['device'].core.endswith("FD"):
ctx['fpu_setting'] = 3
elif core.endswith("F"):
elif ctx['device'].core.endswith("F"):
ctx['fpu_setting'] = 2
else:
ctx['fpu_setting'] = 1
ctx['fputype'] = self.format_fpu(core)
ctx['fputype'] = self.format_fpu(ctx['device'].core)
ctx['armc6'] = int(self.TOOLCHAIN is 'ARMC6')
ctx['toolchain_name'] = self.TOOLCHAIN_NAME
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")
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 clean(project_name):
Expand Down Expand Up @@ -285,3 +305,49 @@ def build(project_name, log_name='build_log.txt', cleanup=True):
return -1
else:
return 0


class UvisionArmc5(Uvision):
NAME = 'uvision5-armc5'
TOOLCHAIN = 'ARM'
TOOLCHAIN_NAME = ''

@classmethod
def is_target_supported(cls, target_name):
target = TARGET_MAP[target_name]
if not (set(target.supported_toolchains).intersection(
set(["ARM", "uARM"]))):
return False
if not DeviceCMSIS.check_supported(target_name):
return False
if "Cortex-A" in target.core:
return False
if not hasattr(target, "post_binary_hook"):
return True
if target.post_binary_hook['function'] in cls.POST_BINARY_WHITELIST:
return True
else:
return False


class UvisionArmc6(Uvision):
NAME = 'uvision5-armc6'
TOOLCHAIN = 'ARMC6'
TOOLCHAIN_NAME = '6070000::V6.7::.\ARMCLANG'

@classmethod
def is_target_supported(cls, target_name):
target = TARGET_MAP[target_name]
if not (set(target.supported_toolchains).intersection(
set(["ARMC6"]))):
return False
if not DeviceCMSIS.check_supported(target_name):
return False
if "Cortex-A" in target.core:
return False
if not hasattr(target, "post_binary_hook"):
return True
if target.post_binary_hook['function'] in cls.POST_BINARY_WHITELIST:
return True
else:
return False
Loading