Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of mbed-sdk-tools by
export/cmsis/__init__.py@32:8ea194f6145b, 2017-01-04 (annotated)
- Committer:
- The Other Jimmy
- Date:
- Wed Jan 04 11:58:24 2017 -0600
- Revision:
- 32:8ea194f6145b
Update tools to follow mbed-os tools release 5.3.1
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
The Other Jimmy |
32:8ea194f6145b | 1 | import os |
The Other Jimmy |
32:8ea194f6145b | 2 | from os.path import sep, join, exists |
The Other Jimmy |
32:8ea194f6145b | 3 | from itertools import groupby |
The Other Jimmy |
32:8ea194f6145b | 4 | from xml.etree.ElementTree import Element, tostring |
The Other Jimmy |
32:8ea194f6145b | 5 | import ntpath |
The Other Jimmy |
32:8ea194f6145b | 6 | import re |
The Other Jimmy |
32:8ea194f6145b | 7 | import json |
The Other Jimmy |
32:8ea194f6145b | 8 | |
The Other Jimmy |
32:8ea194f6145b | 9 | from tools.arm_pack_manager import Cache |
The Other Jimmy |
32:8ea194f6145b | 10 | from tools.targets import TARGET_MAP |
The Other Jimmy |
32:8ea194f6145b | 11 | from tools.export.exporters import Exporter, TargetNotSupportedException |
The Other Jimmy |
32:8ea194f6145b | 12 | |
The Other Jimmy |
32:8ea194f6145b | 13 | class fileCMSIS(): |
The Other Jimmy |
32:8ea194f6145b | 14 | """CMSIS file class. |
The Other Jimmy |
32:8ea194f6145b | 15 | |
The Other Jimmy |
32:8ea194f6145b | 16 | Encapsulates information necessary for files in cpdsc project file""" |
The Other Jimmy |
32:8ea194f6145b | 17 | file_types = {'.cpp': 'sourceCpp', '.c': 'sourceC', '.s': 'sourceAsm', |
The Other Jimmy |
32:8ea194f6145b | 18 | '.obj': 'object', '.o': 'object', '.lib': 'library', |
The Other Jimmy |
32:8ea194f6145b | 19 | '.ar': 'linkerScript', '.h': 'header', '.sct': 'linkerScript'} |
The Other Jimmy |
32:8ea194f6145b | 20 | |
The Other Jimmy |
32:8ea194f6145b | 21 | def __init__(self, loc, name): |
The Other Jimmy |
32:8ea194f6145b | 22 | #print loc |
The Other Jimmy |
32:8ea194f6145b | 23 | _, ext = os.path.splitext(loc) |
The Other Jimmy |
32:8ea194f6145b | 24 | self.type = self.file_types[ext.lower()] |
The Other Jimmy |
32:8ea194f6145b | 25 | self.loc = loc |
The Other Jimmy |
32:8ea194f6145b | 26 | self.name = name |
The Other Jimmy |
32:8ea194f6145b | 27 | |
The Other Jimmy |
32:8ea194f6145b | 28 | |
The Other Jimmy |
32:8ea194f6145b | 29 | class DeviceCMSIS(): |
The Other Jimmy |
32:8ea194f6145b | 30 | """CMSIS Device class |
The Other Jimmy |
32:8ea194f6145b | 31 | |
The Other Jimmy |
32:8ea194f6145b | 32 | Encapsulates target information retrieved by arm-pack-manager""" |
The Other Jimmy |
32:8ea194f6145b | 33 | |
The Other Jimmy |
32:8ea194f6145b | 34 | CACHE = Cache(True, False) |
The Other Jimmy |
32:8ea194f6145b | 35 | def __init__(self, target): |
The Other Jimmy |
32:8ea194f6145b | 36 | target_info = self.check_supported(target) |
The Other Jimmy |
32:8ea194f6145b | 37 | if not target_info: |
The Other Jimmy |
32:8ea194f6145b | 38 | raise TargetNotSupportedException("Target not supported in CMSIS pack") |
The Other Jimmy |
32:8ea194f6145b | 39 | self.url = target_info['pdsc_file'] |
The Other Jimmy |
32:8ea194f6145b | 40 | self.pack_url, self.pack_id = ntpath.split(self.url) |
The Other Jimmy |
32:8ea194f6145b | 41 | self.dname = target_info["_cpu_name"] |
The Other Jimmy |
32:8ea194f6145b | 42 | self.core = target_info["_core"] |
The Other Jimmy |
32:8ea194f6145b | 43 | self.dfpu = target_info['processor']['fpu'] |
The Other Jimmy |
32:8ea194f6145b | 44 | self.debug, self.dvendor = self.vendor_debug(target_info['vendor']) |
The Other Jimmy |
32:8ea194f6145b | 45 | self.dendian = target_info['processor'].get('endianness','Little-endian') |
The Other Jimmy |
32:8ea194f6145b | 46 | self.debug_svd = target_info.get('debug', '') |
The Other Jimmy |
32:8ea194f6145b | 47 | self.compile_header = target_info['compile']['header'] |
The Other Jimmy |
32:8ea194f6145b | 48 | self.target_info = target_info |
The Other Jimmy |
32:8ea194f6145b | 49 | |
The Other Jimmy |
32:8ea194f6145b | 50 | @staticmethod |
The Other Jimmy |
32:8ea194f6145b | 51 | def check_supported(target): |
The Other Jimmy |
32:8ea194f6145b | 52 | t = TARGET_MAP[target] |
The Other Jimmy |
32:8ea194f6145b | 53 | try: |
The Other Jimmy |
32:8ea194f6145b | 54 | cpu_name = t.device_name |
The Other Jimmy |
32:8ea194f6145b | 55 | target_info = DeviceCMSIS.CACHE.index[cpu_name] |
The Other Jimmy |
32:8ea194f6145b | 56 | # Target does not have device name or pdsc file |
The Other Jimmy |
32:8ea194f6145b | 57 | except: |
The Other Jimmy |
32:8ea194f6145b | 58 | try: |
The Other Jimmy |
32:8ea194f6145b | 59 | # Try to find the core as a generic CMSIS target |
The Other Jimmy |
32:8ea194f6145b | 60 | cpu_name = DeviceCMSIS.cpu_cmsis(t.core) |
The Other Jimmy |
32:8ea194f6145b | 61 | target_info = DeviceCMSIS.CACHE.index[cpu_name] |
The Other Jimmy |
32:8ea194f6145b | 62 | except: |
The Other Jimmy |
32:8ea194f6145b | 63 | return False |
The Other Jimmy |
32:8ea194f6145b | 64 | target_info["_cpu_name"] = cpu_name |
The Other Jimmy |
32:8ea194f6145b | 65 | target_info["_core"] = t.core |
The Other Jimmy |
32:8ea194f6145b | 66 | return target_info |
The Other Jimmy |
32:8ea194f6145b | 67 | |
The Other Jimmy |
32:8ea194f6145b | 68 | def vendor_debug(self, vendor): |
The Other Jimmy |
32:8ea194f6145b | 69 | """Reads the vendor from a PDSC <dvendor> tag. |
The Other Jimmy |
32:8ea194f6145b | 70 | This tag contains some additional numeric information that is meaningless |
The Other Jimmy |
32:8ea194f6145b | 71 | for our purposes, so we use a regex to filter. |
The Other Jimmy |
32:8ea194f6145b | 72 | |
The Other Jimmy |
32:8ea194f6145b | 73 | Positional arguments: |
The Other Jimmy |
32:8ea194f6145b | 74 | Vendor - information in <dvendor> tag scraped from ArmPackManager |
The Other Jimmy |
32:8ea194f6145b | 75 | |
The Other Jimmy |
32:8ea194f6145b | 76 | Returns a tuple of (debugger, vendor) |
The Other Jimmy |
32:8ea194f6145b | 77 | """ |
The Other Jimmy |
32:8ea194f6145b | 78 | reg = "([\w\s]+):?\d*?" |
The Other Jimmy |
32:8ea194f6145b | 79 | m = re.search(reg, vendor) |
The Other Jimmy |
32:8ea194f6145b | 80 | vendor_match = m.group(1) if m else None |
The Other Jimmy |
32:8ea194f6145b | 81 | debug_map ={ |
The Other Jimmy |
32:8ea194f6145b | 82 | 'STMicroelectronics':'ST-Link', |
The Other Jimmy |
32:8ea194f6145b | 83 | 'Silicon Labs':'J-LINK', |
The Other Jimmy |
32:8ea194f6145b | 84 | 'Nuvoton':'NULink' |
The Other Jimmy |
32:8ea194f6145b | 85 | } |
The Other Jimmy |
32:8ea194f6145b | 86 | return debug_map.get(vendor_match, "CMSIS-DAP"), vendor_match |
The Other Jimmy |
32:8ea194f6145b | 87 | |
The Other Jimmy |
32:8ea194f6145b | 88 | @staticmethod |
The Other Jimmy |
32:8ea194f6145b | 89 | def cpu_cmsis(cpu): |
The Other Jimmy |
32:8ea194f6145b | 90 | """ |
The Other Jimmy |
32:8ea194f6145b | 91 | Transforms information from targets.json to the way the generic cores are named |
The Other Jimmy |
32:8ea194f6145b | 92 | in CMSIS PDSC files. |
The Other Jimmy |
32:8ea194f6145b | 93 | Ex: |
The Other Jimmy |
32:8ea194f6145b | 94 | Cortex-M4F => ARMCM4_FP, Cortex-M0+ => ARMCM0P |
The Other Jimmy |
32:8ea194f6145b | 95 | Returns formatted CPU |
The Other Jimmy |
32:8ea194f6145b | 96 | """ |
The Other Jimmy |
32:8ea194f6145b | 97 | cpu = cpu.replace("Cortex-","ARMC") |
The Other Jimmy |
32:8ea194f6145b | 98 | cpu = cpu.replace("+","P") |
The Other Jimmy |
32:8ea194f6145b | 99 | cpu = cpu.replace("F","_FP") |
The Other Jimmy |
32:8ea194f6145b | 100 | return cpu |
The Other Jimmy |
32:8ea194f6145b | 101 | |
The Other Jimmy |
32:8ea194f6145b | 102 | |
The Other Jimmy |
32:8ea194f6145b | 103 | class CMSIS(Exporter): |
The Other Jimmy |
32:8ea194f6145b | 104 | NAME = 'cmsis' |
The Other Jimmy |
32:8ea194f6145b | 105 | TOOLCHAIN = 'ARM' |
The Other Jimmy |
32:8ea194f6145b | 106 | TARGETS = [target for target, obj in TARGET_MAP.iteritems() |
The Other Jimmy |
32:8ea194f6145b | 107 | if "ARM" in obj.supported_toolchains] |
The Other Jimmy |
32:8ea194f6145b | 108 | |
The Other Jimmy |
32:8ea194f6145b | 109 | def make_key(self, src): |
The Other Jimmy |
32:8ea194f6145b | 110 | """turn a source file into its group name""" |
The Other Jimmy |
32:8ea194f6145b | 111 | key = src.name.split(sep)[0] |
The Other Jimmy |
32:8ea194f6145b | 112 | if key == ".": |
The Other Jimmy |
32:8ea194f6145b | 113 | key = os.path.basename(os.path.realpath(self.export_dir)) |
The Other Jimmy |
32:8ea194f6145b | 114 | return key |
The Other Jimmy |
32:8ea194f6145b | 115 | |
The Other Jimmy |
32:8ea194f6145b | 116 | def group_project_files(self, sources, root_element): |
The Other Jimmy |
32:8ea194f6145b | 117 | """Recursively group the source files by their encompassing directory""" |
The Other Jimmy |
32:8ea194f6145b | 118 | |
The Other Jimmy |
32:8ea194f6145b | 119 | data = sorted(sources, key=self.make_key) |
The Other Jimmy |
32:8ea194f6145b | 120 | for group, files in groupby(data, self.make_key): |
The Other Jimmy |
32:8ea194f6145b | 121 | new_srcs = [] |
The Other Jimmy |
32:8ea194f6145b | 122 | for f in list(files): |
The Other Jimmy |
32:8ea194f6145b | 123 | spl = f.name.split(sep) |
The Other Jimmy |
32:8ea194f6145b | 124 | if len(spl)==2: |
The Other Jimmy |
32:8ea194f6145b | 125 | file_element = Element('file', |
The Other Jimmy |
32:8ea194f6145b | 126 | attrib={ |
The Other Jimmy |
32:8ea194f6145b | 127 | 'category':f.type, |
The Other Jimmy |
32:8ea194f6145b | 128 | 'name': f.loc}) |
The Other Jimmy |
32:8ea194f6145b | 129 | root_element.append(file_element) |
The Other Jimmy |
32:8ea194f6145b | 130 | else: |
The Other Jimmy |
32:8ea194f6145b | 131 | f.name = os.path.join(*spl[1:]) |
The Other Jimmy |
32:8ea194f6145b | 132 | new_srcs.append(f) |
The Other Jimmy |
32:8ea194f6145b | 133 | if new_srcs: |
The Other Jimmy |
32:8ea194f6145b | 134 | group_element = Element('group',attrib={'name':group}) |
The Other Jimmy |
32:8ea194f6145b | 135 | root_element.append(self.group_project_files(new_srcs, |
The Other Jimmy |
32:8ea194f6145b | 136 | group_element)) |
The Other Jimmy |
32:8ea194f6145b | 137 | return root_element |
The Other Jimmy |
32:8ea194f6145b | 138 | |
The Other Jimmy |
32:8ea194f6145b | 139 | def generate(self): |
The Other Jimmy |
32:8ea194f6145b | 140 | srcs = self.resources.headers + self.resources.s_sources + \ |
The Other Jimmy |
32:8ea194f6145b | 141 | self.resources.c_sources + self.resources.cpp_sources + \ |
The Other Jimmy |
32:8ea194f6145b | 142 | self.resources.objects + self.resources.libraries + \ |
The Other Jimmy |
32:8ea194f6145b | 143 | [self.resources.linker_script] |
The Other Jimmy |
32:8ea194f6145b | 144 | srcs = [fileCMSIS(src, src) for src in srcs if src] |
The Other Jimmy |
32:8ea194f6145b | 145 | ctx = { |
The Other Jimmy |
32:8ea194f6145b | 146 | 'name': self.project_name, |
The Other Jimmy |
32:8ea194f6145b | 147 | 'project_files': tostring(self.group_project_files(srcs, Element('files'))), |
The Other Jimmy |
32:8ea194f6145b | 148 | 'device': DeviceCMSIS(self.target), |
The Other Jimmy |
32:8ea194f6145b | 149 | 'date': '' |
The Other Jimmy |
32:8ea194f6145b | 150 | } |
The Other Jimmy |
32:8ea194f6145b | 151 | # TODO: find how to keep prettyxml from adding xml version to this blob |
The Other Jimmy |
32:8ea194f6145b | 152 | #dom = parseString(ctx['project_files']) |
The Other Jimmy |
32:8ea194f6145b | 153 | #ctx['project_files'] = dom.toprettyxml(indent="\t") |
The Other Jimmy |
32:8ea194f6145b | 154 | |
The Other Jimmy |
32:8ea194f6145b | 155 | self.gen_file('cmsis/cpdsc.tmpl', ctx, 'project.cpdsc') |