Greg Steiert / pegasus_dev

Dependents:   blinky_max32630fthr

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers __init__.py Source File

__init__.py

00001 import os
00002 from os.path import sep, join, exists
00003 from itertools import groupby
00004 from xml.etree.ElementTree import Element, tostring
00005 import ntpath
00006 import re
00007 import json
00008 
00009 from tools.arm_pack_manager import Cache
00010 from tools.targets import TARGET_MAP
00011 from tools.export.exporters import Exporter, TargetNotSupportedException
00012 
00013 class fileCMSIS ():
00014     """CMSIS file class.
00015 
00016     Encapsulates information necessary for files in cpdsc project file"""
00017     file_types = {'.cpp': 'sourceCpp', '.c': 'sourceC', '.s': 'sourceAsm',
00018                   '.obj': 'object', '.o': 'object', '.lib': 'library',
00019                   '.ar': 'linkerScript', '.h': 'header', '.sct': 'linkerScript'}
00020 
00021     def __init__(self, loc, name):
00022         #print loc
00023         _, ext = os.path.splitext(loc)
00024         self.type  = self.file_types [ext.lower()]
00025         self.loc  = loc
00026         self.name  = name
00027 
00028 
00029 class DeviceCMSIS ():
00030     """CMSIS Device class
00031 
00032     Encapsulates target information retrieved by arm-pack-manager"""
00033 
00034     CACHE = Cache(True, False)
00035     def __init__(self, target):
00036         target_info = self.check_supported (target)
00037         if not target_info:
00038             raise TargetNotSupportedException("Target not supported in CMSIS pack")
00039         self.url  = target_info['pdsc_file']
00040         self.pack_url, self.pack_id  = ntpath.split(self.url )
00041         self.dname  = target_info["_cpu_name"]
00042         self.core  = target_info["_core"]
00043         self.dfpu  = target_info['processor']['fpu']
00044         self.debug, self.dvendor  = self.vendor_debug (target_info['vendor'])
00045         self.dendian  = target_info['processor'].get('endianness','Little-endian')
00046         self.debug_svd  = target_info.get('debug', '')
00047         self.compile_header  = target_info['compile']['header']
00048         self.target_info  = target_info
00049 
00050     @staticmethod
00051     def check_supported(target):
00052         t = TARGET_MAP[target]
00053         try:
00054             cpu_name = t.device_name
00055             target_info = DeviceCMSIS.CACHE.index[cpu_name]
00056         # Target does not have device name or pdsc file
00057         except:
00058             try:
00059                 # Try to find the core as a generic CMSIS target
00060                 cpu_name = DeviceCMSIS.cpu_cmsis(t.core)
00061                 target_info = DeviceCMSIS.index[cpu_name]
00062             except:
00063                 return False
00064         target_info["_cpu_name"] = cpu_name
00065         target_info["_core"] = t.core
00066         return target_info
00067 
00068     def vendor_debug (self, vendor):
00069         """Reads the vendor from a PDSC <dvendor> tag.
00070         This tag contains some additional numeric information that is meaningless
00071         for our purposes, so we use a regex to filter.
00072 
00073         Positional arguments:
00074         Vendor - information in <dvendor> tag scraped from ArmPackManager
00075 
00076         Returns a tuple of (debugger, vendor)
00077         """
00078         reg = "([\w\s]+):?\d*?"
00079         m = re.search(reg, vendor)
00080         vendor_match = m.group(1) if m else None
00081         debug_map ={
00082             'STMicroelectronics':'ST-Link',
00083             'Silicon Labs':'J-LINK',
00084             'Nuvoton':'NULink'
00085         }
00086         return debug_map.get(vendor_match, "CMSIS-DAP"), vendor_match
00087 
00088     @staticmethod
00089     def cpu_cmsis (cpu):
00090         """
00091         Transforms information from targets.json to the way the generic cores are named
00092         in CMSIS PDSC files.
00093         Ex:
00094         Cortex-M4F => ARMCM4_FP, Cortex-M0+ => ARMCM0P
00095         Returns formatted CPU
00096         """
00097         cpu = cpu.replace("Cortex-","ARMC")
00098         cpu = cpu.replace("+","P")
00099         cpu = cpu.replace("F","_FP")
00100         return cpu
00101 
00102 
00103 class CMSIS(Exporter ):
00104     NAME = 'cmsis'
00105     TOOLCHAIN = 'ARM'
00106     TARGETS = [target for target, obj in TARGET_MAP.iteritems()
00107                if "ARM" in obj.supported_toolchains]
00108 
00109     def make_key(self, src):
00110         """turn a source file into its group name"""
00111         key = src.name.split(sep)[0]
00112         if key == ".":
00113             key = os.path.basename(os.path.realpath(self.export_dir))
00114         return key
00115 
00116     def group_project_files(self, sources, root_element):
00117         """Recursively group the source files by their encompassing directory"""
00118 
00119         data = sorted(sources, key=self.make_key)
00120         for group, files in groupby(data, self.make_key):
00121             new_srcs = []
00122             for f in list(files):
00123                 spl = f.name.split(sep)
00124                 if len(spl)==2:
00125                     file_element = Element('file',
00126                                            attrib={
00127                                                'category':f.type,
00128                                                'name': f.loc})
00129                     root_element.append(file_element)
00130                 else:
00131                     f.name = os.path.join(*spl[1:])
00132                     new_srcs.append(f)
00133             if new_srcs:
00134                 group_element = Element('group',attrib={'name':group})
00135                 root_element.append(self.group_project_files(new_srcs,
00136                                                         group_element))
00137         return root_element
00138 
00139     def generate(self):
00140         srcs = self.resources.headers + self.resources.s_sources + \
00141                self.resources.c_sources + self.resources.cpp_sources + \
00142                self.resources.objects + self.resources.libraries + \
00143                [self.resources.linker_script]
00144         srcs = [fileCMSIS(src, src) for src in srcs if src]
00145         ctx = {
00146             'name': self.project_name,
00147             'project_files': tostring(self.group_project_files(srcs, Element('files'))),
00148             'device': DeviceCMSIS(self.target),
00149             'date': ''
00150         }
00151         # TODO: find how to keep prettyxml from adding xml version to this blob
00152         #dom = parseString(ctx['project_files'])
00153         #ctx['project_files'] = dom.toprettyxml(indent="\t")
00154 
00155         self.gen_file('cmsis/cpdsc.tmpl', ctx, 'project.cpdsc')