2016-09-09 19:09:33 +00:00
|
|
|
import os
|
2016-09-12 16:29:40 +00:00
|
|
|
from os.path import sep, join, exists
|
2016-09-09 19:09:33 +00:00
|
|
|
from itertools import groupby
|
|
|
|
from xml.etree.ElementTree import Element, tostring
|
|
|
|
import ntpath
|
|
|
|
import re
|
2016-09-30 19:52:22 +00:00
|
|
|
import json
|
2016-09-09 19:09:33 +00:00
|
|
|
|
2016-09-12 16:29:40 +00:00
|
|
|
from tools.arm_pack_manager import Cache
|
2016-09-09 19:09:33 +00:00
|
|
|
from tools.targets import TARGET_MAP
|
|
|
|
from tools.export.exporters import Exporter, TargetNotSupportedException
|
|
|
|
|
|
|
|
class fileCMSIS():
|
|
|
|
"""CMSIS file class.
|
|
|
|
|
|
|
|
Encapsulates information necessary for files in cpdsc project file"""
|
|
|
|
file_types = {'.cpp': 'sourceCpp', '.c': 'sourceC', '.s': 'sourceAsm',
|
|
|
|
'.obj': 'object', '.o': 'object', '.lib': 'library',
|
|
|
|
'.ar': 'linkerScript', '.h': 'header', '.sct': 'linkerScript'}
|
|
|
|
|
|
|
|
def __init__(self, loc, name):
|
|
|
|
#print loc
|
|
|
|
_, ext = os.path.splitext(loc)
|
|
|
|
self.type = self.file_types[ext.lower()]
|
|
|
|
self.loc = loc
|
|
|
|
self.name = name
|
|
|
|
|
|
|
|
|
|
|
|
class DeviceCMSIS():
|
|
|
|
"""CMSIS Device class
|
|
|
|
|
|
|
|
Encapsulates target information retrieved by arm-pack-manager"""
|
2016-10-31 22:42:36 +00:00
|
|
|
cache = Cache(True, False)
|
2016-09-12 16:29:40 +00:00
|
|
|
def __init__(self, target):
|
2016-10-31 21:00:15 +00:00
|
|
|
target_info = self.check_supported(target)
|
|
|
|
if not target_info:
|
|
|
|
raise TargetNotSupportedException("Target not supported in CMSIS pack")
|
2016-09-09 19:09:33 +00:00
|
|
|
|
2016-10-31 21:00:15 +00:00
|
|
|
self.url = target_info['pdsc_file']
|
|
|
|
self.pack_url, self.pack_id = ntpath.split(self.url)
|
|
|
|
self.dname = target_info["_cpu_name"]
|
|
|
|
self.core = target_info["_core"]
|
|
|
|
self.dfpu = target_info['processor']['fpu']
|
|
|
|
self.debug, self.dvendor = self.vendor_debug(target_info['vendor'])
|
|
|
|
self.dendian = target_info['processor'].get('endianness','Little-endian')
|
|
|
|
self.debug_svd = target_info.get('debug', '')
|
|
|
|
self.compile_header = target_info['compile']['header']
|
|
|
|
self.target_info = target_info
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
def check_supported(target):
|
2016-09-09 19:09:33 +00:00
|
|
|
t = TARGET_MAP[target]
|
|
|
|
try:
|
|
|
|
cpu_name = t.device_name
|
2016-10-31 22:42:36 +00:00
|
|
|
target_info = DeviceCMSIS.cache.index[cpu_name]
|
2016-09-09 19:09:33 +00:00
|
|
|
# Target does not have device name or pdsc file
|
|
|
|
except:
|
|
|
|
try:
|
|
|
|
# Try to find the core as a generic CMSIS target
|
2016-10-31 21:00:15 +00:00
|
|
|
cpu_name = DeviceCMSIS.cpu_cmsis(t.core)
|
2016-10-31 22:42:36 +00:00
|
|
|
target_info = DeviceCMSIS.index[cpu_name]
|
2016-09-09 19:09:33 +00:00
|
|
|
except:
|
2016-10-31 21:00:15 +00:00
|
|
|
return False
|
|
|
|
target_info["_cpu_name"] = cpu_name
|
|
|
|
target_info["_core"] = t.core
|
|
|
|
return target_info
|
2016-09-30 19:52:22 +00:00
|
|
|
|
2016-09-21 19:51:30 +00:00
|
|
|
def vendor_debug(self, vendor):
|
|
|
|
reg = "([\w\s]+):?\d*?"
|
|
|
|
m = re.search(reg, vendor)
|
|
|
|
vendor_match = m.group(1) if m else None
|
2016-09-09 19:09:33 +00:00
|
|
|
debug_map ={
|
|
|
|
'STMicroelectronics':'ST-Link',
|
|
|
|
'Silicon Labs':'J-LINK',
|
|
|
|
'Nuvoton':'NULink'
|
|
|
|
}
|
2016-09-21 19:51:30 +00:00
|
|
|
return debug_map.get(vendor_match, "CMSIS-DAP"), vendor_match
|
2016-09-09 19:09:33 +00:00
|
|
|
|
2016-10-31 21:00:15 +00:00
|
|
|
@staticmethod
|
|
|
|
def cpu_cmsis(cpu):
|
2016-09-09 19:09:33 +00:00
|
|
|
#Cortex-M4F => ARMCM4_FP, Cortex-M0+ => ARMCM0P
|
|
|
|
cpu = cpu.replace("Cortex-","ARMC")
|
|
|
|
cpu = cpu.replace("+","P")
|
|
|
|
cpu = cpu.replace("F","_FP")
|
|
|
|
return cpu
|
|
|
|
|
2016-09-30 19:52:22 +00:00
|
|
|
|
2016-09-09 19:09:33 +00:00
|
|
|
class CMSIS(Exporter):
|
|
|
|
NAME = 'cmsis'
|
|
|
|
TOOLCHAIN = 'ARM'
|
|
|
|
TARGETS = [target for target, obj in TARGET_MAP.iteritems()
|
|
|
|
if "ARM" in obj.supported_toolchains]
|
|
|
|
|
|
|
|
def make_key(self, src):
|
|
|
|
"""turn a source file into its group name"""
|
|
|
|
key = src.name.split(sep)[0]
|
|
|
|
if key == ".":
|
|
|
|
key = os.path.basename(os.path.realpath(self.export_dir))
|
|
|
|
return key
|
|
|
|
|
|
|
|
def group_project_files(self, sources, root_element):
|
|
|
|
"""Recursively group the source files by their encompassing directory"""
|
|
|
|
|
|
|
|
data = sorted(sources, key=self.make_key)
|
|
|
|
for group, files in groupby(data, self.make_key):
|
|
|
|
new_srcs = []
|
|
|
|
for f in list(files):
|
|
|
|
spl = f.name.split(sep)
|
|
|
|
if len(spl)==2:
|
|
|
|
file_element = Element('file',
|
|
|
|
attrib={
|
|
|
|
'category':f.type,
|
|
|
|
'name': f.loc})
|
|
|
|
root_element.append(file_element)
|
|
|
|
else:
|
|
|
|
f.name = os.path.join(*spl[1:])
|
|
|
|
new_srcs.append(f)
|
|
|
|
if new_srcs:
|
|
|
|
group_element = Element('group',attrib={'name':group})
|
|
|
|
root_element.append(self.group_project_files(new_srcs,
|
|
|
|
group_element))
|
|
|
|
return root_element
|
|
|
|
|
|
|
|
def generate(self):
|
|
|
|
|
|
|
|
srcs = self.resources.headers + self.resources.s_sources + \
|
|
|
|
self.resources.c_sources + self.resources.cpp_sources + \
|
|
|
|
self.resources.objects + self.resources.libraries + \
|
|
|
|
[self.resources.linker_script]
|
|
|
|
srcs = [fileCMSIS(src, src) for src in srcs if src]
|
|
|
|
ctx = {
|
|
|
|
'name': self.project_name,
|
|
|
|
'project_files': tostring(self.group_project_files(srcs, Element('files'))),
|
|
|
|
'device': DeviceCMSIS(self.target),
|
|
|
|
'date': ''
|
|
|
|
}
|
|
|
|
# TODO: find how to keep prettyxml from adding xml version to this blob
|
|
|
|
#dom = parseString(ctx['project_files'])
|
|
|
|
#ctx['project_files'] = dom.toprettyxml(indent="\t")
|
|
|
|
|
|
|
|
self.gen_file('cmsis/cpdsc.tmpl', ctx, 'project.cpdsc')
|