Anders Blomdell / mbed-sdk-tools
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 re
00006 import json
00007 
00008 from tools.arm_pack_manager import Cache
00009 from tools.targets import TARGET_MAP
00010 from tools.export.exporters import Exporter, TargetNotSupportedException
00011 from tools.utils import split_path
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.pdsc_url, self.pdsc_id, _ = split_path(self.url )
00041         self.pack_url, self.pack_id, _ = split_path(target_info['pack_file'])
00042         self.dname  = target_info["_cpu_name"]
00043         self.core  = target_info["_core"]
00044         self.dfpu  = target_info['processor']['fpu']
00045         self.debug, self.dvendor  = self.vendor_debug (target_info['vendor'])
00046         self.dendian  = target_info['processor'].get('endianness','Little-endian')
00047         self.debug_svd  = target_info.get('debug', '')
00048         self.compile_header  = target_info['compile']['header']
00049         self.target_info  = target_info
00050 
00051     @staticmethod
00052     def check_supported(target):
00053         t = TARGET_MAP[target]
00054         try:
00055             cpu_name = t.device_name
00056             target_info = DeviceCMSIS.CACHE.index[cpu_name]
00057         # Target does not have device name or pdsc file
00058         except:
00059             try:
00060                 # Try to find the core as a generic CMSIS target
00061                 cpu_name = DeviceCMSIS.cpu_cmsis(t.core)
00062                 target_info = DeviceCMSIS.CACHE.index[cpu_name]
00063             except:
00064                 return False
00065         target_info["_cpu_name"] = cpu_name
00066         target_info["_core"] = t.core
00067         return target_info
00068 
00069     def vendor_debug (self, vendor):
00070         """Reads the vendor from a PDSC <dvendor> tag.
00071         This tag contains some additional numeric information that is meaningless
00072         for our purposes, so we use a regex to filter.
00073 
00074         Positional arguments:
00075         Vendor - information in <dvendor> tag scraped from ArmPackManager
00076 
00077         Returns a tuple of (debugger, vendor)
00078         """
00079         reg = "([\w\s]+):?\d*?"
00080         m = re.search(reg, vendor)
00081         vendor_match = m.group(1) if m else None
00082         debug_map ={
00083             'STMicroelectronics':'ST-Link',
00084             'Silicon Labs':'J-LINK',
00085             'Nuvoton':'NULink'
00086         }
00087         return debug_map.get(vendor_match, "CMSIS-DAP"), vendor_match
00088 
00089     @staticmethod
00090     def cpu_cmsis (cpu):
00091         """
00092         Transforms information from targets.json to the way the generic cores are named
00093         in CMSIS PDSC files.
00094         Ex:
00095         Cortex-M4F => ARMCM4_FP, Cortex-M0+ => ARMCM0P
00096         Returns formatted CPU
00097         """
00098         cpu = cpu.replace("Cortex-","ARMC")
00099         cpu = cpu.replace("+","P")
00100         cpu = cpu.replace("F","_FP")
00101         cpu = cpu.replace("-NS", "")
00102         return cpu
00103 
00104 
00105 class CMSIS(Exporter):
00106     NAME = 'cmsis'
00107     TOOLCHAIN = 'ARM'
00108 
00109     @classmethod
00110     def is_target_supported(cls, target_name):
00111         target = TARGET_MAP[target_name]
00112         return cls.TOOLCHAIN in target.supported_toolchains
00113 
00114     def make_key(self, src):
00115         """turn a source file into its group name"""
00116         key = src.name.split(sep)[0]
00117         if key == ".":
00118             key = os.path.basename(os.path.realpath(self.export_dir))
00119         return key
00120 
00121     def group_project_files(self, sources, root_element):
00122         """Recursively group the source files by their encompassing directory"""
00123 
00124         data = sorted(sources, key=self.make_key)
00125         for group, files in groupby(data, self.make_key):
00126             new_srcs = []
00127             for f in list(files):
00128                 spl = f.name.split(sep)
00129                 if len(spl) <= 2:
00130                     file_element = Element('file',
00131                                            attrib={
00132                                                'category':f.type,
00133                                                'name': f.loc})
00134                     root_element.append(file_element)
00135                 else:
00136                     f.name = os.path.join(*spl[1:])
00137                     new_srcs.append(f)
00138             if new_srcs:
00139                 group_element = Element('group',attrib={'name':group})
00140                 root_element.append(self.group_project_files(new_srcs,
00141                                                         group_element))
00142         return root_element
00143 
00144     def generate(self):
00145         srcs = self.resources.headers + self.resources.s_sources + \
00146                self.resources.c_sources + self.resources.cpp_sources + \
00147                self.resources.objects + self.libraries + \
00148                [self.resources.linker_script]
00149         srcs = [fileCMSIS(src, src) for src in srcs if src]
00150         ctx = {
00151             'name': self.project_name,
00152             'project_files': tostring(self.group_project_files(srcs, Element('files'))),
00153             'device': DeviceCMSIS(self.target),
00154             'date': ''
00155         }
00156         self.gen_file('cmsis/cpdsc.tmpl', ctx, 'project.cpdsc')
00157 
00158 
00159     @staticmethod
00160     def clean(_):
00161         os.remove('project.cpdsc')