Development mbed library for MAX32630FTHR

Dependents:   blinky_max32630fthr

Committer:
switches
Date:
Fri Nov 11 20:59:50 2016 +0000
Revision:
0:5c4d7b2438d3
Initial commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
switches 0:5c4d7b2438d3 1 """
switches 0:5c4d7b2438d3 2 mbed SDK
switches 0:5c4d7b2438d3 3 Copyright (c) 2011-2016 ARM Limited
switches 0:5c4d7b2438d3 4
switches 0:5c4d7b2438d3 5 Licensed under the Apache License, Version 2.0 (the "License");
switches 0:5c4d7b2438d3 6 you may not use this file except in compliance with the License.
switches 0:5c4d7b2438d3 7 You may obtain a copy of the License at
switches 0:5c4d7b2438d3 8
switches 0:5c4d7b2438d3 9 http://www.apache.org/licenses/LICENSE-2.0
switches 0:5c4d7b2438d3 10
switches 0:5c4d7b2438d3 11 Unless required by applicable law or agreed to in writing, software
switches 0:5c4d7b2438d3 12 distributed under the License is distributed on an "AS IS" BASIS,
switches 0:5c4d7b2438d3 13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
switches 0:5c4d7b2438d3 14 See the License for the specific language governing permissions and
switches 0:5c4d7b2438d3 15 limitations under the License.
switches 0:5c4d7b2438d3 16 """
switches 0:5c4d7b2438d3 17
switches 0:5c4d7b2438d3 18 import os
switches 0:5c4d7b2438d3 19 import binascii
switches 0:5c4d7b2438d3 20 import struct
switches 0:5c4d7b2438d3 21 import shutil
switches 0:5c4d7b2438d3 22 import inspect
switches 0:5c4d7b2438d3 23 import sys
switches 0:5c4d7b2438d3 24 from collections import namedtuple
switches 0:5c4d7b2438d3 25 from tools.patch import patch
switches 0:5c4d7b2438d3 26 from tools.paths import TOOLS_BOOTLOADERS
switches 0:5c4d7b2438d3 27 from tools.utils import json_file_to_dict
switches 0:5c4d7b2438d3 28
switches 0:5c4d7b2438d3 29 __all__ = ["target", "TARGETS", "TARGET_MAP", "TARGET_NAMES", "CORE_LABELS",
switches 0:5c4d7b2438d3 30 "HookError", "generate_py_target", "Target",
switches 0:5c4d7b2438d3 31 "CUMULATIVE_ATTRIBUTES", "get_resolution_order"]
switches 0:5c4d7b2438d3 32
switches 0:5c4d7b2438d3 33 CORE_LABELS = {
switches 0:5c4d7b2438d3 34 "ARM7TDMI-S": ["ARM7", "LIKE_CORTEX_ARM7"],
switches 0:5c4d7b2438d3 35 "Cortex-M0" : ["M0", "CORTEX_M", "LIKE_CORTEX_M0"],
switches 0:5c4d7b2438d3 36 "Cortex-M0+": ["M0P", "CORTEX_M", "LIKE_CORTEX_M0"],
switches 0:5c4d7b2438d3 37 "Cortex-M1" : ["M1", "CORTEX_M", "LIKE_CORTEX_M1"],
switches 0:5c4d7b2438d3 38 "Cortex-M3" : ["M3", "CORTEX_M", "LIKE_CORTEX_M3"],
switches 0:5c4d7b2438d3 39 "Cortex-M4" : ["M4", "CORTEX_M", "RTOS_M4_M7", "LIKE_CORTEX_M4"],
switches 0:5c4d7b2438d3 40 "Cortex-M4F" : ["M4", "CORTEX_M", "RTOS_M4_M7", "LIKE_CORTEX_M4"],
switches 0:5c4d7b2438d3 41 "Cortex-M7" : ["M7", "CORTEX_M", "RTOS_M4_M7", "LIKE_CORTEX_M7"],
switches 0:5c4d7b2438d3 42 "Cortex-M7F" : ["M7", "CORTEX_M", "RTOS_M4_M7", "LIKE_CORTEX_M7"],
switches 0:5c4d7b2438d3 43 "Cortex-M7FD" : ["M7", "CORTEX_M", "RTOS_M4_M7", "LIKE_CORTEX_M7"],
switches 0:5c4d7b2438d3 44 "Cortex-A9" : ["A9", "CORTEX_A", "LIKE_CORTEX_A9"]
switches 0:5c4d7b2438d3 45 }
switches 0:5c4d7b2438d3 46
switches 0:5c4d7b2438d3 47 ################################################################################
switches 0:5c4d7b2438d3 48 # Generic Target class that reads and interprets the data in targets.json
switches 0:5c4d7b2438d3 49
switches 0:5c4d7b2438d3 50 class HookError(Exception):
switches 0:5c4d7b2438d3 51 """ A simple class that represents all the exceptions associated with
switches 0:5c4d7b2438d3 52 hooking
switches 0:5c4d7b2438d3 53 """
switches 0:5c4d7b2438d3 54 pass
switches 0:5c4d7b2438d3 55
switches 0:5c4d7b2438d3 56 CACHES = {}
switches 0:5c4d7b2438d3 57 def cached(func):
switches 0:5c4d7b2438d3 58 """A simple decorator used for automatically caching data returned by a
switches 0:5c4d7b2438d3 59 function
switches 0:5c4d7b2438d3 60 """
switches 0:5c4d7b2438d3 61 def wrapper(*args, **kwargs):
switches 0:5c4d7b2438d3 62 """The wrapped function itself"""
switches 0:5c4d7b2438d3 63 if not CACHES.has_key((func.__name__, args)):
switches 0:5c4d7b2438d3 64 CACHES[(func.__name__, args)] = func(*args, **kwargs)
switches 0:5c4d7b2438d3 65 return CACHES[(func.__name__, args)]
switches 0:5c4d7b2438d3 66 return wrapper
switches 0:5c4d7b2438d3 67
switches 0:5c4d7b2438d3 68
switches 0:5c4d7b2438d3 69 # Cumulative attributes can have values appended to them, so they
switches 0:5c4d7b2438d3 70 # need to be computed differently than regular attributes
switches 0:5c4d7b2438d3 71 CUMULATIVE_ATTRIBUTES = ['extra_labels', 'macros', 'device_has', 'features']
switches 0:5c4d7b2438d3 72
switches 0:5c4d7b2438d3 73
switches 0:5c4d7b2438d3 74 def get_resolution_order(json_data, target_name, order, level=0):
switches 0:5c4d7b2438d3 75 """ Return the order in which target descriptions are searched for
switches 0:5c4d7b2438d3 76 attributes. This mimics the Python 2.2 method resolution order, which
switches 0:5c4d7b2438d3 77 is what the old targets.py module used. For more details, check
switches 0:5c4d7b2438d3 78 http://makina-corpus.com/blog/metier/2014/python-tutorial-understanding-python-mro-class-search-path
switches 0:5c4d7b2438d3 79 The resolution order contains (name, level) tuples, where "name" is the
switches 0:5c4d7b2438d3 80 name of the class and "level" is the level in the inheritance hierarchy
switches 0:5c4d7b2438d3 81 (the target itself is at level 0, its first parent at level 1, its
switches 0:5c4d7b2438d3 82 parent's parent at level 2 and so on)
switches 0:5c4d7b2438d3 83 """
switches 0:5c4d7b2438d3 84 # the resolution order can't contain duplicate target names
switches 0:5c4d7b2438d3 85 if target_name not in [l[0] for l in order]:
switches 0:5c4d7b2438d3 86 order.append((target_name, level))
switches 0:5c4d7b2438d3 87 parents = json_data[target_name].get("inherits", [])
switches 0:5c4d7b2438d3 88 for par in parents:
switches 0:5c4d7b2438d3 89 order = get_resolution_order(json_data, par, order, level + 1)
switches 0:5c4d7b2438d3 90 return order
switches 0:5c4d7b2438d3 91
switches 0:5c4d7b2438d3 92
switches 0:5c4d7b2438d3 93 def target(name, json_data):
switches 0:5c4d7b2438d3 94 """Construct a target object"""
switches 0:5c4d7b2438d3 95 resolution_order = get_resolution_order(json_data, name, [])
switches 0:5c4d7b2438d3 96 resolution_order_names = [tgt for tgt, _ in resolution_order]
switches 0:5c4d7b2438d3 97 return Target(name=name,
switches 0:5c4d7b2438d3 98 json_data={key: value for key, value in json_data.items()
switches 0:5c4d7b2438d3 99 if key in resolution_order_names},
switches 0:5c4d7b2438d3 100 resolution_order=resolution_order,
switches 0:5c4d7b2438d3 101 resolution_order_names=resolution_order_names)
switches 0:5c4d7b2438d3 102
switches 0:5c4d7b2438d3 103 def generate_py_target(new_targets, name):
switches 0:5c4d7b2438d3 104 """Add one or more new target(s) represented as a Python dictionary
switches 0:5c4d7b2438d3 105 in 'new_targets'. It is an error to add a target with a name that
switches 0:5c4d7b2438d3 106 already exists.
switches 0:5c4d7b2438d3 107 """
switches 0:5c4d7b2438d3 108 base_targets = Target.get_json_target_data()
switches 0:5c4d7b2438d3 109 for new_target in new_targets.keys():
switches 0:5c4d7b2438d3 110 if new_target in base_targets:
switches 0:5c4d7b2438d3 111 raise Exception("Attempt to add target '%s' that already exists"
switches 0:5c4d7b2438d3 112 % new_target)
switches 0:5c4d7b2438d3 113 total_data = {}
switches 0:5c4d7b2438d3 114 total_data.update(new_targets)
switches 0:5c4d7b2438d3 115 total_data.update(base_targets)
switches 0:5c4d7b2438d3 116 return target(name, total_data)
switches 0:5c4d7b2438d3 117
switches 0:5c4d7b2438d3 118 class Target(namedtuple("Target", "name json_data resolution_order resolution_order_names")):
switches 0:5c4d7b2438d3 119 """An object to represent a Target (MCU/Board)"""
switches 0:5c4d7b2438d3 120
switches 0:5c4d7b2438d3 121 # Default location of the 'targets.json' file
switches 0:5c4d7b2438d3 122 __targets_json_location_default = os.path.join(
switches 0:5c4d7b2438d3 123 os.path.dirname(os.path.abspath(__file__)), '..', 'targets', 'targets.json')
switches 0:5c4d7b2438d3 124
switches 0:5c4d7b2438d3 125 # Current/new location of the 'targets.json' file
switches 0:5c4d7b2438d3 126 __targets_json_location = None
switches 0:5c4d7b2438d3 127
switches 0:5c4d7b2438d3 128 @staticmethod
switches 0:5c4d7b2438d3 129 @cached
switches 0:5c4d7b2438d3 130 def get_json_target_data():
switches 0:5c4d7b2438d3 131 """Load the description of JSON target data"""
switches 0:5c4d7b2438d3 132 return json_file_to_dict(Target.__targets_json_location or
switches 0:5c4d7b2438d3 133 Target.__targets_json_location_default)
switches 0:5c4d7b2438d3 134
switches 0:5c4d7b2438d3 135 @staticmethod
switches 0:5c4d7b2438d3 136 def set_targets_json_location(location=None):
switches 0:5c4d7b2438d3 137 """Set the location of the targets.json file"""
switches 0:5c4d7b2438d3 138 Target.__targets_json_location = (location or
switches 0:5c4d7b2438d3 139 Target.__targets_json_location_default)
switches 0:5c4d7b2438d3 140 # Invalidate caches, since the location of the JSON file changed
switches 0:5c4d7b2438d3 141 CACHES.clear()
switches 0:5c4d7b2438d3 142
switches 0:5c4d7b2438d3 143 @staticmethod
switches 0:5c4d7b2438d3 144 @cached
switches 0:5c4d7b2438d3 145 def get_module_data():
switches 0:5c4d7b2438d3 146 """Get the members of this module using Python's "inspect" module"""
switches 0:5c4d7b2438d3 147 return dict([(m[0], m[1]) for m in
switches 0:5c4d7b2438d3 148 inspect.getmembers(sys.modules[__name__])])
switches 0:5c4d7b2438d3 149
switches 0:5c4d7b2438d3 150 @staticmethod
switches 0:5c4d7b2438d3 151 def __add_paths_to_progen(data):
switches 0:5c4d7b2438d3 152 """Modify the exporter specification ("progen") by changing all
switches 0:5c4d7b2438d3 153 "template" keys to full paths
switches 0:5c4d7b2438d3 154 """
switches 0:5c4d7b2438d3 155 out = {}
switches 0:5c4d7b2438d3 156 for key, val in data.items():
switches 0:5c4d7b2438d3 157 if isinstance(val, dict):
switches 0:5c4d7b2438d3 158 out[key] = Target.__add_paths_to_progen(val)
switches 0:5c4d7b2438d3 159 elif key == "template":
switches 0:5c4d7b2438d3 160 out[key] = [os.path.join(os.path.dirname(__file__), 'export', v)
switches 0:5c4d7b2438d3 161 for v in val]
switches 0:5c4d7b2438d3 162 else:
switches 0:5c4d7b2438d3 163 out[key] = val
switches 0:5c4d7b2438d3 164 return out
switches 0:5c4d7b2438d3 165
switches 0:5c4d7b2438d3 166 def __getattr_cumulative(self, attrname):
switches 0:5c4d7b2438d3 167 """Look for the attribute in the class and its parents, as defined by
switches 0:5c4d7b2438d3 168 the resolution order
switches 0:5c4d7b2438d3 169 """
switches 0:5c4d7b2438d3 170 tdata = self.json_data
switches 0:5c4d7b2438d3 171 # For a cumulative attribute, figure out when it was defined the
switches 0:5c4d7b2438d3 172 # last time (in attribute resolution order) then follow the "_add"
switches 0:5c4d7b2438d3 173 # and "_remove" data fields
switches 0:5c4d7b2438d3 174 for idx, tgt in enumerate(self.resolution_order):
switches 0:5c4d7b2438d3 175 # the attribute was defined at this level in the resolution
switches 0:5c4d7b2438d3 176 # order
switches 0:5c4d7b2438d3 177 if attrname in tdata[tgt[0]]:
switches 0:5c4d7b2438d3 178 def_idx = idx
switches 0:5c4d7b2438d3 179 break
switches 0:5c4d7b2438d3 180 else:
switches 0:5c4d7b2438d3 181 raise AttributeError("Attribute '%s' not found in target '%s'"
switches 0:5c4d7b2438d3 182 % (attrname, self.name))
switches 0:5c4d7b2438d3 183 # Get the starting value of the attribute
switches 0:5c4d7b2438d3 184 starting_value = (tdata[self.resolution_order[def_idx][0]][attrname]
switches 0:5c4d7b2438d3 185 or [])[:]
switches 0:5c4d7b2438d3 186 # Traverse the resolution list in high inheritance to low
switches 0:5c4d7b2438d3 187 # inheritance level, left to right order to figure out all the
switches 0:5c4d7b2438d3 188 # other classes that change the definition by adding or removing
switches 0:5c4d7b2438d3 189 # elements
switches 0:5c4d7b2438d3 190 for idx in xrange(self.resolution_order[def_idx][1] - 1, -1, -1):
switches 0:5c4d7b2438d3 191 same_level_targets = [tar[0] for tar in self.resolution_order
switches 0:5c4d7b2438d3 192 if tar[1] == idx]
switches 0:5c4d7b2438d3 193 for tar in same_level_targets:
switches 0:5c4d7b2438d3 194 data = tdata[tar]
switches 0:5c4d7b2438d3 195 # Do we have anything to add ?
switches 0:5c4d7b2438d3 196 if data.has_key(attrname + "_add"):
switches 0:5c4d7b2438d3 197 starting_value.extend(data[attrname + "_add"])
switches 0:5c4d7b2438d3 198 # Do we have anything to remove ?
switches 0:5c4d7b2438d3 199 if data.has_key(attrname + "_remove"):
switches 0:5c4d7b2438d3 200 # Macros can be defined either without a value (MACRO)
switches 0:5c4d7b2438d3 201 # or with a value (MACRO=10). When removing, we specify
switches 0:5c4d7b2438d3 202 # only the name of the macro, without the value. So we
switches 0:5c4d7b2438d3 203 # need to create a mapping between the macro name and
switches 0:5c4d7b2438d3 204 # its value. This will work for extra_labels and other
switches 0:5c4d7b2438d3 205 # type of arrays as well, since they fall into the
switches 0:5c4d7b2438d3 206 # "macros without a value" category (simple definitions
switches 0:5c4d7b2438d3 207 # without a value).
switches 0:5c4d7b2438d3 208 name_def_map = {}
switches 0:5c4d7b2438d3 209 for crtv in starting_value:
switches 0:5c4d7b2438d3 210 if crtv.find('=') != -1:
switches 0:5c4d7b2438d3 211 temp = crtv.split('=')
switches 0:5c4d7b2438d3 212 if len(temp) != 2:
switches 0:5c4d7b2438d3 213 raise ValueError(
switches 0:5c4d7b2438d3 214 "Invalid macro definition '%s'" % crtv)
switches 0:5c4d7b2438d3 215 name_def_map[temp[0]] = crtv
switches 0:5c4d7b2438d3 216 else:
switches 0:5c4d7b2438d3 217 name_def_map[crtv] = crtv
switches 0:5c4d7b2438d3 218 for element in data[attrname + "_remove"]:
switches 0:5c4d7b2438d3 219 if element not in name_def_map:
switches 0:5c4d7b2438d3 220 raise ValueError(
switches 0:5c4d7b2438d3 221 ("Unable to remove '%s' in '%s.%s' since "
switches 0:5c4d7b2438d3 222 % (element, self.name, attrname)) +
switches 0:5c4d7b2438d3 223 "it doesn't exist")
switches 0:5c4d7b2438d3 224 starting_value.remove(name_def_map[element])
switches 0:5c4d7b2438d3 225 return starting_value
switches 0:5c4d7b2438d3 226
switches 0:5c4d7b2438d3 227 def __getattr_helper(self, attrname):
switches 0:5c4d7b2438d3 228 """Compute the value of a given target attribute"""
switches 0:5c4d7b2438d3 229 if attrname in CUMULATIVE_ATTRIBUTES:
switches 0:5c4d7b2438d3 230 return self.__getattr_cumulative(attrname)
switches 0:5c4d7b2438d3 231 else:
switches 0:5c4d7b2438d3 232 tdata = self.json_data
switches 0:5c4d7b2438d3 233 starting_value = None
switches 0:5c4d7b2438d3 234 for tgt in self.resolution_order:
switches 0:5c4d7b2438d3 235 data = tdata[tgt[0]]
switches 0:5c4d7b2438d3 236 if data.has_key(attrname):
switches 0:5c4d7b2438d3 237 starting_value = data[attrname]
switches 0:5c4d7b2438d3 238 break
switches 0:5c4d7b2438d3 239 else: # Attribute not found
switches 0:5c4d7b2438d3 240 raise AttributeError(
switches 0:5c4d7b2438d3 241 "Attribute '%s' not found in target '%s'"
switches 0:5c4d7b2438d3 242 % (attrname, self.name))
switches 0:5c4d7b2438d3 243 # 'progen' needs the full path to the template (the path in JSON is
switches 0:5c4d7b2438d3 244 # relative to tools/export)
switches 0:5c4d7b2438d3 245 if attrname == "progen":
switches 0:5c4d7b2438d3 246 return self.__add_paths_to_progen(starting_value)
switches 0:5c4d7b2438d3 247 else:
switches 0:5c4d7b2438d3 248 return starting_value
switches 0:5c4d7b2438d3 249
switches 0:5c4d7b2438d3 250 def __getattr__(self, attrname):
switches 0:5c4d7b2438d3 251 """ Return the value of an attribute. This function only computes the
switches 0:5c4d7b2438d3 252 attribute's value once, then adds it to the instance attributes (in
switches 0:5c4d7b2438d3 253 __dict__), so the next time it is returned directly
switches 0:5c4d7b2438d3 254 """
switches 0:5c4d7b2438d3 255 result = self.__getattr_helper(attrname)
switches 0:5c4d7b2438d3 256 self.__dict__[attrname] = result
switches 0:5c4d7b2438d3 257 return result
switches 0:5c4d7b2438d3 258
switches 0:5c4d7b2438d3 259 @staticmethod
switches 0:5c4d7b2438d3 260 @cached
switches 0:5c4d7b2438d3 261 def get_target(target_name):
switches 0:5c4d7b2438d3 262 """ Return the target instance starting from the target name """
switches 0:5c4d7b2438d3 263 return target(target_name, Target.get_json_target_data())
switches 0:5c4d7b2438d3 264
switches 0:5c4d7b2438d3 265
switches 0:5c4d7b2438d3 266 @property
switches 0:5c4d7b2438d3 267 def program_cycle_s(self):
switches 0:5c4d7b2438d3 268 """Special override for program_cycle_s as it's default value depends
switches 0:5c4d7b2438d3 269 upon is_disk_virtual
switches 0:5c4d7b2438d3 270 """
switches 0:5c4d7b2438d3 271 try:
switches 0:5c4d7b2438d3 272 return self.__getattr__("program_cycle_s")
switches 0:5c4d7b2438d3 273 except AttributeError:
switches 0:5c4d7b2438d3 274 return 4 if self.is_disk_virtual else 1.5
switches 0:5c4d7b2438d3 275
switches 0:5c4d7b2438d3 276 @property
switches 0:5c4d7b2438d3 277 def labels(self):
switches 0:5c4d7b2438d3 278 """Get all possible labels for this target"""
switches 0:5c4d7b2438d3 279 labels = [self.name] + CORE_LABELS[self.core] + self.extra_labels
switches 0:5c4d7b2438d3 280 # Automatically define UVISOR_UNSUPPORTED if the target doesn't
switches 0:5c4d7b2438d3 281 # specifically define UVISOR_SUPPORTED
switches 0:5c4d7b2438d3 282 if "UVISOR_SUPPORTED" not in labels:
switches 0:5c4d7b2438d3 283 labels.append("UVISOR_UNSUPPORTED")
switches 0:5c4d7b2438d3 284 return labels
switches 0:5c4d7b2438d3 285
switches 0:5c4d7b2438d3 286 def init_hooks(self, hook, toolchain_name):
switches 0:5c4d7b2438d3 287 """Initialize the post-build hooks for a toolchain. For now, this
switches 0:5c4d7b2438d3 288 function only allows "post binary" hooks (hooks that are executed
switches 0:5c4d7b2438d3 289 after the binary image is extracted from the executable file)
switches 0:5c4d7b2438d3 290 """
switches 0:5c4d7b2438d3 291
switches 0:5c4d7b2438d3 292 # If there's no hook, simply return
switches 0:5c4d7b2438d3 293 try:
switches 0:5c4d7b2438d3 294 hook_data = self.post_binary_hook
switches 0:5c4d7b2438d3 295 except AttributeError:
switches 0:5c4d7b2438d3 296 return
switches 0:5c4d7b2438d3 297 # A hook was found. The hook's name is in the format
switches 0:5c4d7b2438d3 298 # "classname.functionname"
switches 0:5c4d7b2438d3 299 temp = hook_data["function"].split(".")
switches 0:5c4d7b2438d3 300 if len(temp) != 2:
switches 0:5c4d7b2438d3 301 raise HookError(
switches 0:5c4d7b2438d3 302 ("Invalid format for hook '%s' in target '%s'"
switches 0:5c4d7b2438d3 303 % (hook_data["function"], self.name)) +
switches 0:5c4d7b2438d3 304 " (must be 'class_name.function_name')")
switches 0:5c4d7b2438d3 305 class_name, function_name = temp[0], temp[1]
switches 0:5c4d7b2438d3 306 # "class_name" must refer to a class in this file, so check if the
switches 0:5c4d7b2438d3 307 # class exists
switches 0:5c4d7b2438d3 308 mdata = self.get_module_data()
switches 0:5c4d7b2438d3 309 if not mdata.has_key(class_name) or \
switches 0:5c4d7b2438d3 310 not inspect.isclass(mdata[class_name]):
switches 0:5c4d7b2438d3 311 raise HookError(
switches 0:5c4d7b2438d3 312 ("Class '%s' required by '%s' in target '%s'"
switches 0:5c4d7b2438d3 313 % (class_name, hook_data["function"], self.name)) +
switches 0:5c4d7b2438d3 314 " not found in targets.py")
switches 0:5c4d7b2438d3 315 # "function_name" must refer to a static function inside class
switches 0:5c4d7b2438d3 316 # "class_name"
switches 0:5c4d7b2438d3 317 cls = mdata[class_name]
switches 0:5c4d7b2438d3 318 if (not hasattr(cls, function_name)) or \
switches 0:5c4d7b2438d3 319 (not inspect.isfunction(getattr(cls, function_name))):
switches 0:5c4d7b2438d3 320 raise HookError(
switches 0:5c4d7b2438d3 321 ("Static function '%s' " % function_name) +
switches 0:5c4d7b2438d3 322 ("required by '%s' " % hook_data["function"]) +
switches 0:5c4d7b2438d3 323 ("in target '%s' " % self.name) +
switches 0:5c4d7b2438d3 324 ("not found in class '%s'" % class_name))
switches 0:5c4d7b2438d3 325 # Check if the hook specification also has target restrictions
switches 0:5c4d7b2438d3 326 toolchain_restrictions = hook_data.get("toolchains", [])
switches 0:5c4d7b2438d3 327 if toolchain_restrictions and \
switches 0:5c4d7b2438d3 328 (toolchain_name not in toolchain_restrictions):
switches 0:5c4d7b2438d3 329 return
switches 0:5c4d7b2438d3 330 # Finally, hook the requested function
switches 0:5c4d7b2438d3 331 hook.hook_add_binary("post", getattr(cls, function_name))
switches 0:5c4d7b2438d3 332
switches 0:5c4d7b2438d3 333 ################################################################################
switches 0:5c4d7b2438d3 334 # Target specific code goes in this section
switches 0:5c4d7b2438d3 335 # This code can be invoked from the target description using the
switches 0:5c4d7b2438d3 336 # "post_binary_hook" key
switches 0:5c4d7b2438d3 337
switches 0:5c4d7b2438d3 338 class LPCTargetCode(object):
switches 0:5c4d7b2438d3 339 """General LPC Target patching code"""
switches 0:5c4d7b2438d3 340 @staticmethod
switches 0:5c4d7b2438d3 341 def lpc_patch(t_self, resources, elf, binf):
switches 0:5c4d7b2438d3 342 """Patch an elf file"""
switches 0:5c4d7b2438d3 343 t_self.debug("LPC Patch: %s" % os.path.split(binf)[1])
switches 0:5c4d7b2438d3 344 patch(binf)
switches 0:5c4d7b2438d3 345
switches 0:5c4d7b2438d3 346 class LPC4088Code(object):
switches 0:5c4d7b2438d3 347 """Code specific to the LPC4088"""
switches 0:5c4d7b2438d3 348 @staticmethod
switches 0:5c4d7b2438d3 349 def binary_hook(t_self, resources, elf, binf):
switches 0:5c4d7b2438d3 350 """Hook to be run after an elf file is built"""
switches 0:5c4d7b2438d3 351 if not os.path.isdir(binf):
switches 0:5c4d7b2438d3 352 # Regular binary file, nothing to do
switches 0:5c4d7b2438d3 353 LPCTargetCode.lpc_patch(t_self, resources, elf, binf)
switches 0:5c4d7b2438d3 354 return
switches 0:5c4d7b2438d3 355 outbin = open(binf + ".temp", "wb")
switches 0:5c4d7b2438d3 356 partf = open(os.path.join(binf, "ER_IROM1"), "rb")
switches 0:5c4d7b2438d3 357 # Pad the fist part (internal flash) with 0xFF to 512k
switches 0:5c4d7b2438d3 358 data = partf.read()
switches 0:5c4d7b2438d3 359 outbin.write(data)
switches 0:5c4d7b2438d3 360 outbin.write('\xFF' * (512*1024 - len(data)))
switches 0:5c4d7b2438d3 361 partf.close()
switches 0:5c4d7b2438d3 362 # Read and append the second part (external flash) in chunks of fixed
switches 0:5c4d7b2438d3 363 # size
switches 0:5c4d7b2438d3 364 chunksize = 128 * 1024
switches 0:5c4d7b2438d3 365 partf = open(os.path.join(binf, "ER_IROM2"), "rb")
switches 0:5c4d7b2438d3 366 while True:
switches 0:5c4d7b2438d3 367 data = partf.read(chunksize)
switches 0:5c4d7b2438d3 368 outbin.write(data)
switches 0:5c4d7b2438d3 369 if len(data) < chunksize:
switches 0:5c4d7b2438d3 370 break
switches 0:5c4d7b2438d3 371 partf.close()
switches 0:5c4d7b2438d3 372 outbin.close()
switches 0:5c4d7b2438d3 373 # Remove the directory with the binary parts and rename the temporary
switches 0:5c4d7b2438d3 374 # file to 'binf'
switches 0:5c4d7b2438d3 375 shutil.rmtree(binf, True)
switches 0:5c4d7b2438d3 376 os.rename(binf + '.temp', binf)
switches 0:5c4d7b2438d3 377 t_self.debug("Generated custom binary file (internal flash + SPIFI)")
switches 0:5c4d7b2438d3 378 LPCTargetCode.lpc_patch(t_self, resources, elf, binf)
switches 0:5c4d7b2438d3 379
switches 0:5c4d7b2438d3 380 class TEENSY3_1Code(object):
switches 0:5c4d7b2438d3 381 """Hooks for the TEENSY3.1"""
switches 0:5c4d7b2438d3 382 @staticmethod
switches 0:5c4d7b2438d3 383 def binary_hook(t_self, resources, elf, binf):
switches 0:5c4d7b2438d3 384 """Hook that is run after elf is generated"""
switches 0:5c4d7b2438d3 385 from intelhex import IntelHex
switches 0:5c4d7b2438d3 386 binh = IntelHex()
switches 0:5c4d7b2438d3 387 binh.loadbin(binf, offset=0)
switches 0:5c4d7b2438d3 388
switches 0:5c4d7b2438d3 389 with open(binf.replace(".bin", ".hex"), "w") as file_desc:
switches 0:5c4d7b2438d3 390 binh.tofile(file_desc, format='hex')
switches 0:5c4d7b2438d3 391
switches 0:5c4d7b2438d3 392 class MTSCode(object):
switches 0:5c4d7b2438d3 393 """Generic MTS code"""
switches 0:5c4d7b2438d3 394 @staticmethod
switches 0:5c4d7b2438d3 395 def _combine_bins_helper(target_name, binf):
switches 0:5c4d7b2438d3 396 """combine bins with the bootloader for a particular target"""
switches 0:5c4d7b2438d3 397 loader = os.path.join(TOOLS_BOOTLOADERS, target_name, "bootloader.bin")
switches 0:5c4d7b2438d3 398 target = binf + ".tmp"
switches 0:5c4d7b2438d3 399 if not os.path.exists(loader):
switches 0:5c4d7b2438d3 400 print "Can't find bootloader binary: " + loader
switches 0:5c4d7b2438d3 401 return
switches 0:5c4d7b2438d3 402 outbin = open(target, 'w+b')
switches 0:5c4d7b2438d3 403 part = open(loader, 'rb')
switches 0:5c4d7b2438d3 404 data = part.read()
switches 0:5c4d7b2438d3 405 outbin.write(data)
switches 0:5c4d7b2438d3 406 outbin.write('\xFF' * (64*1024 - len(data)))
switches 0:5c4d7b2438d3 407 part.close()
switches 0:5c4d7b2438d3 408 part = open(binf, 'rb')
switches 0:5c4d7b2438d3 409 data = part.read()
switches 0:5c4d7b2438d3 410 outbin.write(data)
switches 0:5c4d7b2438d3 411 part.close()
switches 0:5c4d7b2438d3 412 outbin.seek(0, 0)
switches 0:5c4d7b2438d3 413 data = outbin.read()
switches 0:5c4d7b2438d3 414 outbin.seek(0, 1)
switches 0:5c4d7b2438d3 415 crc = struct.pack('<I', binascii.crc32(data) & 0xFFFFFFFF)
switches 0:5c4d7b2438d3 416 outbin.write(crc)
switches 0:5c4d7b2438d3 417 outbin.close()
switches 0:5c4d7b2438d3 418 os.remove(binf)
switches 0:5c4d7b2438d3 419 os.rename(target, binf)
switches 0:5c4d7b2438d3 420
switches 0:5c4d7b2438d3 421 @staticmethod
switches 0:5c4d7b2438d3 422 def combine_bins_mts_dot(t_self, resources, elf, binf):
switches 0:5c4d7b2438d3 423 """A hook for the MTS MDOT"""
switches 0:5c4d7b2438d3 424 MTSCode._combine_bins_helper("MTS_MDOT_F411RE", binf)
switches 0:5c4d7b2438d3 425
switches 0:5c4d7b2438d3 426 @staticmethod
switches 0:5c4d7b2438d3 427 def combine_bins_mts_dragonfly(t_self, resources, elf, binf):
switches 0:5c4d7b2438d3 428 """A hoof for the MTS Dragonfly"""
switches 0:5c4d7b2438d3 429 MTSCode._combine_bins_helper("MTS_DRAGONFLY_F411RE", binf)
switches 0:5c4d7b2438d3 430
switches 0:5c4d7b2438d3 431 class MCU_NRF51Code(object):
switches 0:5c4d7b2438d3 432 """NRF51 Hooks"""
switches 0:5c4d7b2438d3 433 @staticmethod
switches 0:5c4d7b2438d3 434 def binary_hook(t_self, resources, _, binf):
switches 0:5c4d7b2438d3 435 """Hook that merges the soft device with the bin file"""
switches 0:5c4d7b2438d3 436 # Scan to find the actual paths of soft device
switches 0:5c4d7b2438d3 437 sdf = None
switches 0:5c4d7b2438d3 438 for softdevice_and_offset_entry\
switches 0:5c4d7b2438d3 439 in t_self.target.EXPECTED_SOFTDEVICES_WITH_OFFSETS:
switches 0:5c4d7b2438d3 440 for hexf in resources.hex_files:
switches 0:5c4d7b2438d3 441 if hexf.find(softdevice_and_offset_entry['name']) != -1:
switches 0:5c4d7b2438d3 442 t_self.debug("SoftDevice file found %s."
switches 0:5c4d7b2438d3 443 % softdevice_and_offset_entry['name'])
switches 0:5c4d7b2438d3 444 sdf = hexf
switches 0:5c4d7b2438d3 445
switches 0:5c4d7b2438d3 446 if sdf is not None:
switches 0:5c4d7b2438d3 447 break
switches 0:5c4d7b2438d3 448 if sdf is not None:
switches 0:5c4d7b2438d3 449 break
switches 0:5c4d7b2438d3 450
switches 0:5c4d7b2438d3 451 if sdf is None:
switches 0:5c4d7b2438d3 452 t_self.debug("Hex file not found. Aborting.")
switches 0:5c4d7b2438d3 453 return
switches 0:5c4d7b2438d3 454
switches 0:5c4d7b2438d3 455 # Look for bootloader file that matches this soft device or bootloader
switches 0:5c4d7b2438d3 456 # override image
switches 0:5c4d7b2438d3 457 blf = None
switches 0:5c4d7b2438d3 458 if t_self.target.MERGE_BOOTLOADER is True:
switches 0:5c4d7b2438d3 459 for hexf in resources.hex_files:
switches 0:5c4d7b2438d3 460 if hexf.find(t_self.target.OVERRIDE_BOOTLOADER_FILENAME) != -1:
switches 0:5c4d7b2438d3 461 t_self.debug("Bootloader file found %s."
switches 0:5c4d7b2438d3 462 % t_self.target.OVERRIDE_BOOTLOADER_FILENAME)
switches 0:5c4d7b2438d3 463 blf = hexf
switches 0:5c4d7b2438d3 464 break
switches 0:5c4d7b2438d3 465 elif hexf.find(softdevice_and_offset_entry['boot']) != -1:
switches 0:5c4d7b2438d3 466 t_self.debug("Bootloader file found %s."
switches 0:5c4d7b2438d3 467 % softdevice_and_offset_entry['boot'])
switches 0:5c4d7b2438d3 468 blf = hexf
switches 0:5c4d7b2438d3 469 break
switches 0:5c4d7b2438d3 470
switches 0:5c4d7b2438d3 471 # Merge user code with softdevice
switches 0:5c4d7b2438d3 472 from intelhex import IntelHex
switches 0:5c4d7b2438d3 473 binh = IntelHex()
switches 0:5c4d7b2438d3 474 binh.loadbin(binf, offset=softdevice_and_offset_entry['offset'])
switches 0:5c4d7b2438d3 475
switches 0:5c4d7b2438d3 476 if t_self.target.MERGE_SOFT_DEVICE is True:
switches 0:5c4d7b2438d3 477 t_self.debug("Merge SoftDevice file %s"
switches 0:5c4d7b2438d3 478 % softdevice_and_offset_entry['name'])
switches 0:5c4d7b2438d3 479 sdh = IntelHex(sdf)
switches 0:5c4d7b2438d3 480 binh.merge(sdh)
switches 0:5c4d7b2438d3 481
switches 0:5c4d7b2438d3 482 if t_self.target.MERGE_BOOTLOADER is True and blf is not None:
switches 0:5c4d7b2438d3 483 t_self.debug("Merge BootLoader file %s" % blf)
switches 0:5c4d7b2438d3 484 blh = IntelHex(blf)
switches 0:5c4d7b2438d3 485 binh.merge(blh)
switches 0:5c4d7b2438d3 486
switches 0:5c4d7b2438d3 487 with open(binf.replace(".bin", ".hex"), "w") as fileout:
switches 0:5c4d7b2438d3 488 binh.tofile(fileout, format='hex')
switches 0:5c4d7b2438d3 489
switches 0:5c4d7b2438d3 490 class NCS36510TargetCode:
switches 0:5c4d7b2438d3 491 @staticmethod
switches 0:5c4d7b2438d3 492 def ncs36510_addfib(t_self, resources, elf, binf):
switches 0:5c4d7b2438d3 493 from tools.add_fib import add_fib_at_start
switches 0:5c4d7b2438d3 494 print("binf ", binf)
switches 0:5c4d7b2438d3 495 add_fib_at_start(binf[:-4])
switches 0:5c4d7b2438d3 496 ################################################################################
switches 0:5c4d7b2438d3 497
switches 0:5c4d7b2438d3 498 # Instantiate all public targets
switches 0:5c4d7b2438d3 499 TARGETS = [Target.get_target(name) for name, value
switches 0:5c4d7b2438d3 500 in Target.get_json_target_data().items()
switches 0:5c4d7b2438d3 501 if value.get("public", True)]
switches 0:5c4d7b2438d3 502
switches 0:5c4d7b2438d3 503 # Map each target name to its unique instance
switches 0:5c4d7b2438d3 504 TARGET_MAP = dict([(t.name, t) for t in TARGETS])
switches 0:5c4d7b2438d3 505
switches 0:5c4d7b2438d3 506 TARGET_NAMES = TARGET_MAP.keys()
switches 0:5c4d7b2438d3 507
switches 0:5c4d7b2438d3 508 # Some targets with different name have the same exporters
switches 0:5c4d7b2438d3 509 EXPORT_MAP = {}
switches 0:5c4d7b2438d3 510
switches 0:5c4d7b2438d3 511 # Detection APIs
switches 0:5c4d7b2438d3 512 def get_target_detect_codes():
switches 0:5c4d7b2438d3 513 """ Returns dictionary mapping detect_code -> platform_name
switches 0:5c4d7b2438d3 514 """
switches 0:5c4d7b2438d3 515 result = {}
switches 0:5c4d7b2438d3 516 for tgt in TARGETS:
switches 0:5c4d7b2438d3 517 for detect_code in tgt.detect_code:
switches 0:5c4d7b2438d3 518 result[detect_code] = tgt.name
switches 0:5c4d7b2438d3 519 return result
switches 0:5c4d7b2438d3 520
switches 0:5c4d7b2438d3 521 def set_targets_json_location(location=None):
switches 0:5c4d7b2438d3 522 """Sets the location of the JSON file that contains the targets"""
switches 0:5c4d7b2438d3 523 # First instruct Target about the new location
switches 0:5c4d7b2438d3 524 Target.set_targets_json_location(location)
switches 0:5c4d7b2438d3 525 # Then re-initialize TARGETS, TARGET_MAP and TARGET_NAMES. The
switches 0:5c4d7b2438d3 526 # re-initialization does not create new variables, it keeps the old ones
switches 0:5c4d7b2438d3 527 # instead. This ensures compatibility with code that does
switches 0:5c4d7b2438d3 528 # "from tools.targets import TARGET_NAMES"
switches 0:5c4d7b2438d3 529 TARGETS[:] = [Target.get_target(tgt) for tgt, obj
switches 0:5c4d7b2438d3 530 in Target.get_json_target_data().items()
switches 0:5c4d7b2438d3 531 if obj.get("public", True)]
switches 0:5c4d7b2438d3 532 TARGET_MAP.clear()
switches 0:5c4d7b2438d3 533 TARGET_MAP.update(dict([(tgt.name, tgt) for tgt in TARGETS]))
switches 0:5c4d7b2438d3 534 TARGET_NAMES[:] = TARGET_MAP.keys()