Rtos API example

Committer:
marcozecchini
Date:
Sat Feb 23 12:13:36 2019 +0000
Revision:
0:9fca2b23d0ba
final commit

Who changed what in which revision?

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