import os from os.path import sep from itertools import groupby from xml.etree.ElementTree import Element, tostring from xml.dom.minidom import parseString import ntpath import re from ArmPackManager import Cache from tools.targets import TARGET_MAP from tools.export.exporters import Exporter, TargetNotSupportedException cache_d = False 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""" def __init__(self, target, use_generic_cpu=False): cache = Cache(True, False) if cache_d: cache.cache_descriptors() t = TARGET_MAP[target] self.core = t.core try: cpu_name = t.device_name target_info = cache.index[cpu_name] # Target does not have device name or pdsc file except: try: # Try to find the core as a generic CMSIS target cpu_name = self.cpu_cmsis() target_info = cache.index[cpu_name] except: raise TargetNotSupportedException("Target not in CMSIS packs") self.url = target_info['pdsc_file'] self.pack_url, self.pack_id = ntpath.split(self.url) self.dname = cpu_name self.dfpu = target_info['processor']['fpu'] self.dvendor = target_info['vendor'] self.dendian = target_info['processor'].get('endianness','Little-endian') self.debug_interface = self.find_debug() self.debug_svd = target_info.get('debug', '') self.compile_header = target_info['compile']['header'] def find_debug(self): debug_map ={ 'STMicroelectronics':'ST-Link', 'Silicon Labs':'J-LINK', 'Nuvoton':'NULink' } reg = "([\w\s]+):?\d*?" m = re.search(reg, self.dvendor) vendor_match = m.group(1) if m else None return debug_map.get(vendor_match, "CMSIS-DAP") def cpu_cmsis(self): #Cortex-M4F => ARMCM4_FP, Cortex-M0+ => ARMCM0P cpu = self.core cpu = cpu.replace("Cortex-","ARMC") cpu = cpu.replace("+","P") cpu = cpu.replace("F","_FP") return cpu 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')