Clone of official tools

Committer:
screamer
Date:
Sat Jul 16 00:34:03 2016 +0100
Revision:
22:9e85236d8716
Parent:
16:a6285a7e5cc6
Child:
27:5461402c33f8
Sync with the mbedmicro/mbed tools

Who changed what in which revision?

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