BA / Mbed OS BaBoRo1
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         return cpu
00102 
00103 
00104 class CMSIS(Exporter ):
00105     NAME = 'cmsis'
00106     TOOLCHAIN = 'ARM'
00107 
00108     @classmethod
00109     def is_target_supported(cls, target_name):
00110         target = TARGET_MAP[target_name]
00111         return cls.TOOLCHAIN in target.supported_toolchains
00112 
00113     def make_key(self, src):
00114         """turn a source file into its group name"""
00115         key = src.name.split(sep)[0]
00116         if key == ".":
00117             key = os.path.basename(os.path.realpath(self.export_dir))
00118         return key
00119 
00120     def group_project_files(self, sources, root_element):
00121         """Recursively group the source files by their encompassing directory"""
00122 
00123         data = sorted(sources, key=self.make_key)
00124         for group, files in groupby(data, self.make_key):
00125             new_srcs = []
00126             for f in list(files):
00127                 spl = f.name.split(sep)
00128                 if len(spl) <= 2:
00129                     file_element = Element('file',
00130                                            attrib={
00131                                                'category':f.type,
00132                                                'name': f.loc})
00133                     root_element.append(file_element)
00134                 else:
00135                     f.name = os.path.join(*spl[1:])
00136                     new_srcs.append(f)
00137             if new_srcs:
00138                 group_element = Element('group',attrib={'name':group})
00139                 root_element.append(self.group_project_files(new_srcs,
00140                                                         group_element))
00141         return root_element
00142 
00143     def generate(self):
00144         srcs = self.resources.headers + self.resources.s_sources + \
00145                self.resources.c_sources + self.resources.cpp_sources + \
00146                self.resources.objects + self.resources.libraries + \
00147                [self.resources.linker_script]
00148         srcs = [fileCMSIS(src, src) for src in srcs if src]
00149         ctx = {
00150             'name': self.project_name,
00151             'project_files': tostring(self.group_project_files(srcs, Element('files'))),
00152             'device': DeviceCMSIS(self.target),
00153             'date': ''
00154         }
00155         self.gen_file('cmsis/cpdsc.tmpl', ctx, 'project.cpdsc')
00156 
00157 
00158     @staticmethod
00159     def clean(_):
00160         os.remove('project.cpdsc')