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