mbed-os for GR-LYCHEE

Dependents:   mbed-os-example-blinky-gr-lychee GR-Boads_Camera_sample GR-Boards_Audio_Recoder GR-Boads_Camera_DisplayApp ... more

Committer:
dkato
Date:
Fri Feb 02 05:42:23 2018 +0000
Revision:
0:f782d9c66c49
mbed-os for GR-LYCHEE

Who changed what in which revision?

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