Color Oled(SSD1331) connect to STMicroelectronics Nucleo-F466

Dependencies:   ssd1331

Committer:
kadonotakashi
Date:
Thu Oct 11 02:27:46 2018 +0000
Revision:
3:f3764f852aa8
Parent:
0:8fdf9a60065b
Nucreo 446 + SSD1331 test version;

Who changed what in which revision?

UserRevisionLine numberNew contents of line
kadonotakashi 0:8fdf9a60065b 1 """
kadonotakashi 0:8fdf9a60065b 2 mbed SDK
kadonotakashi 0:8fdf9a60065b 3 Copyright (c) 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, division, absolute_import
kadonotakashi 0:8fdf9a60065b 18
kadonotakashi 0:8fdf9a60065b 19 from copy import deepcopy
kadonotakashi 0:8fdf9a60065b 20 from six import moves
kadonotakashi 0:8fdf9a60065b 21 import json
kadonotakashi 0:8fdf9a60065b 22 import six
kadonotakashi 0:8fdf9a60065b 23 import os
kadonotakashi 0:8fdf9a60065b 24 from os.path import dirname, abspath, exists, join, isabs
kadonotakashi 0:8fdf9a60065b 25 import sys
kadonotakashi 0:8fdf9a60065b 26 from collections import namedtuple
kadonotakashi 0:8fdf9a60065b 27 from os.path import splitext, relpath
kadonotakashi 0:8fdf9a60065b 28 from intelhex import IntelHex
kadonotakashi 0:8fdf9a60065b 29 from jinja2 import FileSystemLoader, StrictUndefined
kadonotakashi 0:8fdf9a60065b 30 from jinja2.environment import Environment
kadonotakashi 0:8fdf9a60065b 31 from jsonschema import Draft4Validator, RefResolver
kadonotakashi 0:8fdf9a60065b 32
kadonotakashi 0:8fdf9a60065b 33 from ..resources import FileType
kadonotakashi 0:8fdf9a60065b 34 from ..utils import (json_file_to_dict, intelhex_offset, integer,
kadonotakashi 0:8fdf9a60065b 35 NotSupportedException)
kadonotakashi 0:8fdf9a60065b 36 from ..arm_pack_manager import Cache
kadonotakashi 0:8fdf9a60065b 37 from ..targets import (CUMULATIVE_ATTRIBUTES, TARGET_MAP, generate_py_target,
kadonotakashi 0:8fdf9a60065b 38 get_resolution_order, Target)
kadonotakashi 0:8fdf9a60065b 39
kadonotakashi 0:8fdf9a60065b 40 try:
kadonotakashi 0:8fdf9a60065b 41 unicode
kadonotakashi 0:8fdf9a60065b 42 except NameError:
kadonotakashi 0:8fdf9a60065b 43 unicode = str
kadonotakashi 0:8fdf9a60065b 44 PATH_OVERRIDES = set(["target.bootloader_img"])
kadonotakashi 0:8fdf9a60065b 45 ROM_OVERRIDES = set([
kadonotakashi 0:8fdf9a60065b 46 # managed BL
kadonotakashi 0:8fdf9a60065b 47 "target.bootloader_img", "target.restrict_size",
kadonotakashi 0:8fdf9a60065b 48 "target.header_format", "target.header_offset",
kadonotakashi 0:8fdf9a60065b 49 "target.app_offset",
kadonotakashi 0:8fdf9a60065b 50
kadonotakashi 0:8fdf9a60065b 51 # unmanaged BL
kadonotakashi 0:8fdf9a60065b 52 "target.mbed_app_start", "target.mbed_app_size",
kadonotakashi 0:8fdf9a60065b 53
kadonotakashi 0:8fdf9a60065b 54 # both
kadonotakashi 0:8fdf9a60065b 55 "target.mbed_rom_start", "target.mbed_rom_size",
kadonotakashi 0:8fdf9a60065b 56 ])
kadonotakashi 0:8fdf9a60065b 57 RAM_OVERRIDES = set([
kadonotakashi 0:8fdf9a60065b 58 # both
kadonotakashi 0:8fdf9a60065b 59 "target.mbed_ram_start", "target.mbed_ram_size",
kadonotakashi 0:8fdf9a60065b 60 ])
kadonotakashi 0:8fdf9a60065b 61
kadonotakashi 0:8fdf9a60065b 62 BOOTLOADER_OVERRIDES = ROM_OVERRIDES | RAM_OVERRIDES
kadonotakashi 0:8fdf9a60065b 63
kadonotakashi 0:8fdf9a60065b 64
kadonotakashi 0:8fdf9a60065b 65 ALLOWED_FEATURES = [
kadonotakashi 0:8fdf9a60065b 66 "BOOTLOADER","UVISOR", "BLE", "CLIENT", "IPV4", "LWIP", "COMMON_PAL", "STORAGE",
kadonotakashi 0:8fdf9a60065b 67 "NANOSTACK","CRYPTOCELL310",
kadonotakashi 0:8fdf9a60065b 68 # Nanostack configurations
kadonotakashi 0:8fdf9a60065b 69 "LOWPAN_BORDER_ROUTER", "LOWPAN_HOST", "LOWPAN_ROUTER", "NANOSTACK_FULL",
kadonotakashi 0:8fdf9a60065b 70 "THREAD_BORDER_ROUTER", "THREAD_END_DEVICE", "THREAD_ROUTER",
kadonotakashi 0:8fdf9a60065b 71 "ETHERNET_HOST",
kadonotakashi 0:8fdf9a60065b 72 ]
kadonotakashi 0:8fdf9a60065b 73
kadonotakashi 0:8fdf9a60065b 74 # Base class for all configuration exceptions
kadonotakashi 0:8fdf9a60065b 75 class ConfigException(Exception):
kadonotakashi 0:8fdf9a60065b 76 """Config system only exception. Makes it easier to distinguish config
kadonotakashi 0:8fdf9a60065b 77 errors"""
kadonotakashi 0:8fdf9a60065b 78 pass
kadonotakashi 0:8fdf9a60065b 79
kadonotakashi 0:8fdf9a60065b 80 class UndefinedParameter(ConfigException):
kadonotakashi 0:8fdf9a60065b 81 def __init__(self, param, name, kind, label):
kadonotakashi 0:8fdf9a60065b 82 self.param = param
kadonotakashi 0:8fdf9a60065b 83 self.name = name
kadonotakashi 0:8fdf9a60065b 84 self.kind = kind
kadonotakashi 0:8fdf9a60065b 85 self.label = label
kadonotakashi 0:8fdf9a60065b 86
kadonotakashi 0:8fdf9a60065b 87 def __str__(self):
kadonotakashi 0:8fdf9a60065b 88 return "Attempt to override undefined parameter '{}' in '{}'".format(
kadonotakashi 0:8fdf9a60065b 89 self.param,
kadonotakashi 0:8fdf9a60065b 90 ConfigParameter.get_display_name(self.name, self.kind, self.label),
kadonotakashi 0:8fdf9a60065b 91 )
kadonotakashi 0:8fdf9a60065b 92
kadonotakashi 0:8fdf9a60065b 93 class ConfigParameter(object):
kadonotakashi 0:8fdf9a60065b 94 """This class keeps information about a single configuration parameter"""
kadonotakashi 0:8fdf9a60065b 95
kadonotakashi 0:8fdf9a60065b 96 def __init__(self, name, data, unit_name, unit_kind):
kadonotakashi 0:8fdf9a60065b 97 """Construct a ConfigParameter
kadonotakashi 0:8fdf9a60065b 98
kadonotakashi 0:8fdf9a60065b 99 Positional arguments:
kadonotakashi 0:8fdf9a60065b 100 name - the name of the configuration parameter
kadonotakashi 0:8fdf9a60065b 101 data - the data associated with the configuration parameter
kadonotakashi 0:8fdf9a60065b 102 unit_name - the unit (target/library/application) that defines this
kadonotakashi 0:8fdf9a60065b 103 parameter
kadonotakashi 0:8fdf9a60065b 104 unit_ kind - the kind of the unit ("target", "library" or "application")
kadonotakashi 0:8fdf9a60065b 105 """
kadonotakashi 0:8fdf9a60065b 106 self.name = self.get_full_name(name, unit_name, unit_kind,
kadonotakashi 0:8fdf9a60065b 107 allow_prefix=False)
kadonotakashi 0:8fdf9a60065b 108 self.defined_by = self.get_display_name(unit_name, unit_kind)
kadonotakashi 0:8fdf9a60065b 109 self.set_value(data.get("value", None), unit_name, unit_kind)
kadonotakashi 0:8fdf9a60065b 110 self.help_text = data.get("help", None)
kadonotakashi 0:8fdf9a60065b 111 self.required = data.get("required", False)
kadonotakashi 0:8fdf9a60065b 112 self.macro_name = data.get("macro_name", "MBED_CONF_%s" %
kadonotakashi 0:8fdf9a60065b 113 self.sanitize(self.name.upper()))
kadonotakashi 0:8fdf9a60065b 114 self.config_errors = []
kadonotakashi 0:8fdf9a60065b 115
kadonotakashi 0:8fdf9a60065b 116 @staticmethod
kadonotakashi 0:8fdf9a60065b 117 def get_full_name(name, unit_name, unit_kind, label=None,
kadonotakashi 0:8fdf9a60065b 118 allow_prefix=True):
kadonotakashi 0:8fdf9a60065b 119 """Return the full (prefixed) name of a parameter. If the parameter
kadonotakashi 0:8fdf9a60065b 120 already has a prefix, check if it is valid
kadonotakashi 0:8fdf9a60065b 121
kadonotakashi 0:8fdf9a60065b 122 Positional arguments:
kadonotakashi 0:8fdf9a60065b 123 name - the simple (unqualified) name of the parameter
kadonotakashi 0:8fdf9a60065b 124 unit_name - the unit (target/library/application) that defines this
kadonotakashi 0:8fdf9a60065b 125 parameter
kadonotakashi 0:8fdf9a60065b 126 unit_kind - the kind of the unit ("target", "library" or "application")
kadonotakashi 0:8fdf9a60065b 127
kadonotakashi 0:8fdf9a60065b 128 Keyword arguments:
kadonotakashi 0:8fdf9a60065b 129 label - the name of the label in the 'target_config_overrides' section
kadonotakashi 0:8fdf9a60065b 130 allow_prefix - True to allow the original name to have a prefix, False
kadonotakashi 0:8fdf9a60065b 131 otherwise
kadonotakashi 0:8fdf9a60065b 132 """
kadonotakashi 0:8fdf9a60065b 133 if name.find('.') == -1: # the name is not prefixed
kadonotakashi 0:8fdf9a60065b 134 if unit_kind == "target":
kadonotakashi 0:8fdf9a60065b 135 prefix = "target."
kadonotakashi 0:8fdf9a60065b 136 elif unit_kind == "application":
kadonotakashi 0:8fdf9a60065b 137 prefix = "app."
kadonotakashi 0:8fdf9a60065b 138 else:
kadonotakashi 0:8fdf9a60065b 139 prefix = unit_name + '.'
kadonotakashi 0:8fdf9a60065b 140 return prefix + name
kadonotakashi 0:8fdf9a60065b 141 if name in BOOTLOADER_OVERRIDES:
kadonotakashi 0:8fdf9a60065b 142 return name
kadonotakashi 0:8fdf9a60065b 143 # The name has a prefix, so check if it is valid
kadonotakashi 0:8fdf9a60065b 144 if not allow_prefix:
kadonotakashi 0:8fdf9a60065b 145 raise ConfigException("Invalid parameter name '%s' in '%s'" %
kadonotakashi 0:8fdf9a60065b 146 (name, ConfigParameter.get_display_name(
kadonotakashi 0:8fdf9a60065b 147 unit_name, unit_kind, label)))
kadonotakashi 0:8fdf9a60065b 148 temp = name.split(".")
kadonotakashi 0:8fdf9a60065b 149 # Check if the parameter syntax is correct (must be
kadonotakashi 0:8fdf9a60065b 150 # unit_name.parameter_name)
kadonotakashi 0:8fdf9a60065b 151 if len(temp) != 2:
kadonotakashi 0:8fdf9a60065b 152 raise ConfigException("Invalid parameter name '%s' in '%s'" %
kadonotakashi 0:8fdf9a60065b 153 (name, ConfigParameter.get_display_name(
kadonotakashi 0:8fdf9a60065b 154 unit_name, unit_kind, label)))
kadonotakashi 0:8fdf9a60065b 155 prefix = temp[0]
kadonotakashi 0:8fdf9a60065b 156 # Check if the given parameter prefix matches the expected prefix
kadonotakashi 0:8fdf9a60065b 157 if (unit_kind == "library" and prefix not in [unit_name, "target"]) or \
kadonotakashi 0:8fdf9a60065b 158 (unit_kind == "target" and prefix != "target"):
kadonotakashi 0:8fdf9a60065b 159 raise ConfigException(
kadonotakashi 0:8fdf9a60065b 160 "Invalid prefix '%s' for parameter name '%s' in '%s'" %
kadonotakashi 0:8fdf9a60065b 161 (prefix, name, ConfigParameter.get_display_name(
kadonotakashi 0:8fdf9a60065b 162 unit_name, unit_kind, label)))
kadonotakashi 0:8fdf9a60065b 163 return name
kadonotakashi 0:8fdf9a60065b 164
kadonotakashi 0:8fdf9a60065b 165 @staticmethod
kadonotakashi 0:8fdf9a60065b 166 def get_display_name(unit_name, unit_kind, label=None):
kadonotakashi 0:8fdf9a60065b 167 """Return the name displayed for a unit when interrogating the origin
kadonotakashi 0:8fdf9a60065b 168 and the last set place of a parameter
kadonotakashi 0:8fdf9a60065b 169
kadonotakashi 0:8fdf9a60065b 170 Positional arguments:
kadonotakashi 0:8fdf9a60065b 171 unit_name - the unit (target/library/application) that defines this
kadonotakashi 0:8fdf9a60065b 172 parameter
kadonotakashi 0:8fdf9a60065b 173 unit_kind - the kind of the unit ("target", "library" or "application")
kadonotakashi 0:8fdf9a60065b 174
kadonotakashi 0:8fdf9a60065b 175 Keyword arguments:
kadonotakashi 0:8fdf9a60065b 176 label - the name of the label in the 'target_config_overrides' section
kadonotakashi 0:8fdf9a60065b 177 """
kadonotakashi 0:8fdf9a60065b 178 if unit_kind == "target":
kadonotakashi 0:8fdf9a60065b 179 return "target:" + unit_name
kadonotakashi 0:8fdf9a60065b 180 elif unit_kind == "application":
kadonotakashi 0:8fdf9a60065b 181 return "application%s" % ("[%s]" % label if label else "")
kadonotakashi 0:8fdf9a60065b 182 else: # library
kadonotakashi 0:8fdf9a60065b 183 return "library:%s%s" % (unit_name, "[%s]" % label if label else "")
kadonotakashi 0:8fdf9a60065b 184
kadonotakashi 0:8fdf9a60065b 185 @staticmethod
kadonotakashi 0:8fdf9a60065b 186 def sanitize(name):
kadonotakashi 0:8fdf9a60065b 187 """ "Sanitize" a name so that it is a valid C macro name. Currently it
kadonotakashi 0:8fdf9a60065b 188 simply replaces '.' and '-' with '_'.
kadonotakashi 0:8fdf9a60065b 189
kadonotakashi 0:8fdf9a60065b 190 Positional arguments:
kadonotakashi 0:8fdf9a60065b 191 name - the name to make into a valid C macro
kadonotakashi 0:8fdf9a60065b 192 """
kadonotakashi 0:8fdf9a60065b 193 return name.replace('.', '_').replace('-', '_')
kadonotakashi 0:8fdf9a60065b 194
kadonotakashi 0:8fdf9a60065b 195 def set_value(self, value, unit_name, unit_kind, label=None):
kadonotakashi 0:8fdf9a60065b 196 """ Sets a value for this parameter, remember the place where it was
kadonotakashi 0:8fdf9a60065b 197 set. If the value is a Boolean, it is converted to 1 (for True) or
kadonotakashi 0:8fdf9a60065b 198 to 0 (for False).
kadonotakashi 0:8fdf9a60065b 199
kadonotakashi 0:8fdf9a60065b 200 Positional arguments:
kadonotakashi 0:8fdf9a60065b 201 value - the value of the parameter
kadonotakashi 0:8fdf9a60065b 202 unit_name - the unit (target/library/application) that defines this
kadonotakashi 0:8fdf9a60065b 203 parameter
kadonotakashi 0:8fdf9a60065b 204 unit_kind - the kind of the unit ("target", "library" or "application")
kadonotakashi 0:8fdf9a60065b 205
kadonotakashi 0:8fdf9a60065b 206 Keyword arguments:
kadonotakashi 0:8fdf9a60065b 207 label - the name of the label in the 'target_config_overrides' section
kadonotakashi 0:8fdf9a60065b 208 (optional)
kadonotakashi 0:8fdf9a60065b 209 """
kadonotakashi 0:8fdf9a60065b 210 self.value = int(value) if isinstance(value, bool) else value
kadonotakashi 0:8fdf9a60065b 211 self.set_by = self.get_display_name(unit_name, unit_kind, label)
kadonotakashi 0:8fdf9a60065b 212
kadonotakashi 0:8fdf9a60065b 213 def __str__(self):
kadonotakashi 0:8fdf9a60065b 214 """Return the string representation of this configuration parameter
kadonotakashi 0:8fdf9a60065b 215
kadonotakashi 0:8fdf9a60065b 216 Arguments: None
kadonotakashi 0:8fdf9a60065b 217 """
kadonotakashi 0:8fdf9a60065b 218 if self.value is not None:
kadonotakashi 0:8fdf9a60065b 219 return '%s = %s (macro name: "%s")' % \
kadonotakashi 0:8fdf9a60065b 220 (self.name, self.value, self.macro_name)
kadonotakashi 0:8fdf9a60065b 221 else:
kadonotakashi 0:8fdf9a60065b 222 return '%s has no value' % self.name
kadonotakashi 0:8fdf9a60065b 223
kadonotakashi 0:8fdf9a60065b 224 def get_verbose_description(self):
kadonotakashi 0:8fdf9a60065b 225 """Return a verbose description of this configuration parameter as a
kadonotakashi 0:8fdf9a60065b 226 string
kadonotakashi 0:8fdf9a60065b 227
kadonotakashi 0:8fdf9a60065b 228 Arguments: None
kadonotakashi 0:8fdf9a60065b 229 """
kadonotakashi 0:8fdf9a60065b 230 desc = "Name: %s%s\n" % \
kadonotakashi 0:8fdf9a60065b 231 (self.name, " (required parameter)" if self.required else "")
kadonotakashi 0:8fdf9a60065b 232 if self.help_text:
kadonotakashi 0:8fdf9a60065b 233 desc += " Description: %s\n" % self.help_text
kadonotakashi 0:8fdf9a60065b 234 desc += " Defined by: %s\n" % self.defined_by
kadonotakashi 0:8fdf9a60065b 235 if not self.value:
kadonotakashi 0:8fdf9a60065b 236 return desc + " No value set"
kadonotakashi 0:8fdf9a60065b 237 desc += " Macro name: %s\n" % self.macro_name
kadonotakashi 0:8fdf9a60065b 238 desc += " Value: %s (set by %s)" % (self.value, self.set_by)
kadonotakashi 0:8fdf9a60065b 239 return desc
kadonotakashi 0:8fdf9a60065b 240
kadonotakashi 0:8fdf9a60065b 241 class ConfigMacro(object):
kadonotakashi 0:8fdf9a60065b 242 """ A representation of a configuration macro. It handles both macros
kadonotakashi 0:8fdf9a60065b 243 without a value (MACRO) and with a value (MACRO=VALUE)
kadonotakashi 0:8fdf9a60065b 244 """
kadonotakashi 0:8fdf9a60065b 245 def __init__(self, name, unit_name, unit_kind):
kadonotakashi 0:8fdf9a60065b 246 """Construct a ConfigMacro object
kadonotakashi 0:8fdf9a60065b 247
kadonotakashi 0:8fdf9a60065b 248 Positional arguments:
kadonotakashi 0:8fdf9a60065b 249 name - the macro's name
kadonotakashi 0:8fdf9a60065b 250 unit_name - the location where the macro was defined
kadonotakashi 0:8fdf9a60065b 251 unit_kind - the type of macro this is
kadonotakashi 0:8fdf9a60065b 252 """
kadonotakashi 0:8fdf9a60065b 253 self.name = name
kadonotakashi 0:8fdf9a60065b 254 self.defined_by = ConfigParameter.get_display_name(unit_name, unit_kind)
kadonotakashi 0:8fdf9a60065b 255 if name.find("=") != -1:
kadonotakashi 0:8fdf9a60065b 256 tmp = name.split("=")
kadonotakashi 0:8fdf9a60065b 257 if len(tmp) != 2:
kadonotakashi 0:8fdf9a60065b 258 raise ValueError("Invalid macro definition '%s' in '%s'" %
kadonotakashi 0:8fdf9a60065b 259 (name, self.defined_by))
kadonotakashi 0:8fdf9a60065b 260 self.macro_name = tmp[0]
kadonotakashi 0:8fdf9a60065b 261 self.macro_value = tmp[1]
kadonotakashi 0:8fdf9a60065b 262 else:
kadonotakashi 0:8fdf9a60065b 263 self.macro_name = name
kadonotakashi 0:8fdf9a60065b 264 self.macro_value = None
kadonotakashi 0:8fdf9a60065b 265
kadonotakashi 0:8fdf9a60065b 266 class ConfigCumulativeOverride(object):
kadonotakashi 0:8fdf9a60065b 267 """Representation of overrides for cumulative attributes"""
kadonotakashi 0:8fdf9a60065b 268 def __init__(self, name, additions=None, removals=None, strict=False):
kadonotakashi 0:8fdf9a60065b 269 """Construct a ConfigCumulativeOverride object
kadonotakashi 0:8fdf9a60065b 270
kadonotakashi 0:8fdf9a60065b 271 Positional arguments:
kadonotakashi 0:8fdf9a60065b 272 name - the name of the config file this came from ?
kadonotakashi 0:8fdf9a60065b 273
kadonotakashi 0:8fdf9a60065b 274 Keyword arguments:
kadonotakashi 0:8fdf9a60065b 275 additions - macros to add to the overrides
kadonotakashi 0:8fdf9a60065b 276 removals - macros to remove from the overrides
kadonotakashi 0:8fdf9a60065b 277 strict - Boolean indicating that attempting to remove from an override
kadonotakashi 0:8fdf9a60065b 278 that does not exist should error
kadonotakashi 0:8fdf9a60065b 279 """
kadonotakashi 0:8fdf9a60065b 280 self.name = name
kadonotakashi 0:8fdf9a60065b 281 if additions:
kadonotakashi 0:8fdf9a60065b 282 self.additions = set(additions)
kadonotakashi 0:8fdf9a60065b 283 else:
kadonotakashi 0:8fdf9a60065b 284 self.additions = set()
kadonotakashi 0:8fdf9a60065b 285 if removals:
kadonotakashi 0:8fdf9a60065b 286 self.removals = set(removals)
kadonotakashi 0:8fdf9a60065b 287 else:
kadonotakashi 0:8fdf9a60065b 288 self.removals = set()
kadonotakashi 0:8fdf9a60065b 289 self.strict = strict
kadonotakashi 0:8fdf9a60065b 290
kadonotakashi 0:8fdf9a60065b 291 def remove_cumulative_overrides(self, overrides):
kadonotakashi 0:8fdf9a60065b 292 """Extend the list of override removals.
kadonotakashi 0:8fdf9a60065b 293
kadonotakashi 0:8fdf9a60065b 294 Positional arguments:
kadonotakashi 0:8fdf9a60065b 295 overrides - a list of names that, when the override is evaluated, will
kadonotakashi 0:8fdf9a60065b 296 be removed
kadonotakashi 0:8fdf9a60065b 297 """
kadonotakashi 0:8fdf9a60065b 298 for override in overrides:
kadonotakashi 0:8fdf9a60065b 299 if override in self.additions:
kadonotakashi 0:8fdf9a60065b 300 raise ConfigException(
kadonotakashi 0:8fdf9a60065b 301 "Configuration conflict. The %s %s both added and removed."
kadonotakashi 0:8fdf9a60065b 302 % (self.name[:-1], override))
kadonotakashi 0:8fdf9a60065b 303
kadonotakashi 0:8fdf9a60065b 304 self.removals |= set(overrides)
kadonotakashi 0:8fdf9a60065b 305
kadonotakashi 0:8fdf9a60065b 306 def add_cumulative_overrides(self, overrides):
kadonotakashi 0:8fdf9a60065b 307 """Extend the list of override additions.
kadonotakashi 0:8fdf9a60065b 308
kadonotakashi 0:8fdf9a60065b 309 Positional arguments:
kadonotakashi 0:8fdf9a60065b 310 overrides - a list of a names that, when the override is evaluated, will
kadonotakashi 0:8fdf9a60065b 311 be added to the list
kadonotakashi 0:8fdf9a60065b 312 """
kadonotakashi 0:8fdf9a60065b 313 for override in overrides:
kadonotakashi 0:8fdf9a60065b 314 if override in self.removals or \
kadonotakashi 0:8fdf9a60065b 315 (self.strict and override not in self.additions):
kadonotakashi 0:8fdf9a60065b 316 raise ConfigException(
kadonotakashi 0:8fdf9a60065b 317 "Configuration conflict. The %s %s both added and removed."
kadonotakashi 0:8fdf9a60065b 318 % (self.name[:-1], override))
kadonotakashi 0:8fdf9a60065b 319
kadonotakashi 0:8fdf9a60065b 320 self.additions |= set(overrides)
kadonotakashi 0:8fdf9a60065b 321
kadonotakashi 0:8fdf9a60065b 322 def strict_cumulative_overrides(self, overrides):
kadonotakashi 0:8fdf9a60065b 323 """Remove all overrides that are not the specified ones
kadonotakashi 0:8fdf9a60065b 324
kadonotakashi 0:8fdf9a60065b 325 Positional arguments:
kadonotakashi 0:8fdf9a60065b 326 overrides - a list of names that will replace the entire attribute when
kadonotakashi 0:8fdf9a60065b 327 this override is evaluated.
kadonotakashi 0:8fdf9a60065b 328 """
kadonotakashi 0:8fdf9a60065b 329 self.remove_cumulative_overrides(self.additions - set(overrides))
kadonotakashi 0:8fdf9a60065b 330 self.add_cumulative_overrides(overrides)
kadonotakashi 0:8fdf9a60065b 331 self.strict = True
kadonotakashi 0:8fdf9a60065b 332
kadonotakashi 0:8fdf9a60065b 333 def update_target(self, target):
kadonotakashi 0:8fdf9a60065b 334 """Update the attributes of a target based on this override"""
kadonotakashi 0:8fdf9a60065b 335 setattr(target, self.name,
kadonotakashi 0:8fdf9a60065b 336 list((set(getattr(target, self.name, []))
kadonotakashi 0:8fdf9a60065b 337 | self.additions) - self.removals))
kadonotakashi 0:8fdf9a60065b 338
kadonotakashi 0:8fdf9a60065b 339
kadonotakashi 0:8fdf9a60065b 340 def _process_config_parameters(data, params, unit_name, unit_kind):
kadonotakashi 0:8fdf9a60065b 341 """Process a "config_parameters" section in either a target, a library,
kadonotakashi 0:8fdf9a60065b 342 or the application.
kadonotakashi 0:8fdf9a60065b 343
kadonotakashi 0:8fdf9a60065b 344 Positional arguments:
kadonotakashi 0:8fdf9a60065b 345 data - a dictionary with the configuration parameters
kadonotakashi 0:8fdf9a60065b 346 params - storage for the discovered configuration parameters
kadonotakashi 0:8fdf9a60065b 347 unit_name - the unit (target/library/application) that defines this
kadonotakashi 0:8fdf9a60065b 348 parameter
kadonotakashi 0:8fdf9a60065b 349 unit_kind - the kind of the unit ("target", "library" or "application")
kadonotakashi 0:8fdf9a60065b 350 """
kadonotakashi 0:8fdf9a60065b 351 for name, val in data.items():
kadonotakashi 0:8fdf9a60065b 352 full_name = ConfigParameter.get_full_name(name, unit_name, unit_kind)
kadonotakashi 0:8fdf9a60065b 353 # If the parameter was already defined, raise an error
kadonotakashi 0:8fdf9a60065b 354 if full_name in params:
kadonotakashi 0:8fdf9a60065b 355 raise ConfigException(
kadonotakashi 0:8fdf9a60065b 356 "Parameter name '%s' defined in both '%s' and '%s'" %
kadonotakashi 0:8fdf9a60065b 357 (name, ConfigParameter.get_display_name(unit_name, unit_kind),
kadonotakashi 0:8fdf9a60065b 358 params[full_name].defined_by))
kadonotakashi 0:8fdf9a60065b 359 # Otherwise add it to the list of known parameters
kadonotakashi 0:8fdf9a60065b 360 # If "val" is not a dictionary, this is a shortcut definition,
kadonotakashi 0:8fdf9a60065b 361 # otherwise it is a full definition
kadonotakashi 0:8fdf9a60065b 362 params[full_name] = ConfigParameter(name, val if isinstance(val, dict)
kadonotakashi 0:8fdf9a60065b 363 else {"value": val}, unit_name,
kadonotakashi 0:8fdf9a60065b 364 unit_kind)
kadonotakashi 0:8fdf9a60065b 365 return params
kadonotakashi 0:8fdf9a60065b 366
kadonotakashi 0:8fdf9a60065b 367
kadonotakashi 0:8fdf9a60065b 368 def _process_macros(mlist, macros, unit_name, unit_kind):
kadonotakashi 0:8fdf9a60065b 369 """Process a macro definition and check for incompatible duplicate
kadonotakashi 0:8fdf9a60065b 370 definitions.
kadonotakashi 0:8fdf9a60065b 371
kadonotakashi 0:8fdf9a60065b 372 Positional arguments:
kadonotakashi 0:8fdf9a60065b 373 mlist - list of macro names to process
kadonotakashi 0:8fdf9a60065b 374 macros - dictionary with currently discovered macros
kadonotakashi 0:8fdf9a60065b 375 unit_name - the unit (library/application) that defines this macro
kadonotakashi 0:8fdf9a60065b 376 unit_kind - the kind of the unit ("library" or "application")
kadonotakashi 0:8fdf9a60065b 377 """
kadonotakashi 0:8fdf9a60065b 378 for mname in mlist:
kadonotakashi 0:8fdf9a60065b 379 macro = ConfigMacro(mname, unit_name, unit_kind)
kadonotakashi 0:8fdf9a60065b 380 if (macro.macro_name in macros) and \
kadonotakashi 0:8fdf9a60065b 381 (macros[macro.macro_name].name != mname):
kadonotakashi 0:8fdf9a60065b 382 # Found an incompatible definition of the macro in another module,
kadonotakashi 0:8fdf9a60065b 383 # so raise an error
kadonotakashi 0:8fdf9a60065b 384 full_unit_name = ConfigParameter.get_display_name(unit_name,
kadonotakashi 0:8fdf9a60065b 385 unit_kind)
kadonotakashi 0:8fdf9a60065b 386 raise ConfigException(
kadonotakashi 0:8fdf9a60065b 387 ("Macro '%s' defined in both '%s' and '%s'"
kadonotakashi 0:8fdf9a60065b 388 % (macro.macro_name, macros[macro.macro_name].defined_by,
kadonotakashi 0:8fdf9a60065b 389 full_unit_name)) +
kadonotakashi 0:8fdf9a60065b 390 " with incompatible values")
kadonotakashi 0:8fdf9a60065b 391 macros[macro.macro_name] = macro
kadonotakashi 0:8fdf9a60065b 392
kadonotakashi 0:8fdf9a60065b 393
kadonotakashi 0:8fdf9a60065b 394 Region = namedtuple("Region", "name start size active filename")
kadonotakashi 0:8fdf9a60065b 395 RamRegion = namedtuple("RamRegion", "name start size active")
kadonotakashi 0:8fdf9a60065b 396
kadonotakashi 0:8fdf9a60065b 397 class Config(object):
kadonotakashi 0:8fdf9a60065b 398 """'Config' implements the mbed configuration mechanism"""
kadonotakashi 0:8fdf9a60065b 399
kadonotakashi 0:8fdf9a60065b 400 # Libraries and applications have different names for their configuration
kadonotakashi 0:8fdf9a60065b 401 # files
kadonotakashi 0:8fdf9a60065b 402 __mbed_app_config_name = "mbed_app.json"
kadonotakashi 0:8fdf9a60065b 403 __mbed_lib_config_name = "mbed_lib.json"
kadonotakashi 0:8fdf9a60065b 404
kadonotakashi 0:8fdf9a60065b 405 __unused_overrides = set(["target.bootloader_img", "target.restrict_size",
kadonotakashi 0:8fdf9a60065b 406 "target.mbed_app_start", "target.mbed_app_size"])
kadonotakashi 0:8fdf9a60065b 407
kadonotakashi 0:8fdf9a60065b 408 @classmethod
kadonotakashi 0:8fdf9a60065b 409 def find_app_config(cls, top_level_dirs):
kadonotakashi 0:8fdf9a60065b 410 app_config_location = None
kadonotakashi 0:8fdf9a60065b 411 for directory in top_level_dirs:
kadonotakashi 0:8fdf9a60065b 412 full_path = os.path.join(directory, cls.__mbed_app_config_name)
kadonotakashi 0:8fdf9a60065b 413 if os.path.isfile(full_path):
kadonotakashi 0:8fdf9a60065b 414 if app_config_location is not None:
kadonotakashi 0:8fdf9a60065b 415 raise ConfigException("Duplicate '%s' file in '%s' and '%s'"
kadonotakashi 0:8fdf9a60065b 416 % (cls.__mbed_app_config_name,
kadonotakashi 0:8fdf9a60065b 417 cls.app_config_location, full_path))
kadonotakashi 0:8fdf9a60065b 418 else:
kadonotakashi 0:8fdf9a60065b 419 app_config_location = full_path
kadonotakashi 0:8fdf9a60065b 420 return app_config_location
kadonotakashi 0:8fdf9a60065b 421
kadonotakashi 0:8fdf9a60065b 422 def format_validation_error(self, error, path):
kadonotakashi 0:8fdf9a60065b 423 if error.context:
kadonotakashi 0:8fdf9a60065b 424 return self.format_validation_error(error.context[0], path)
kadonotakashi 0:8fdf9a60065b 425 else:
kadonotakashi 0:8fdf9a60065b 426 return "in {} element {}: {}".format(
kadonotakashi 0:8fdf9a60065b 427 path, ".".join(p for p in error.absolute_path),
kadonotakashi 0:8fdf9a60065b 428 error.message.replace('u\'','\''))
kadonotakashi 0:8fdf9a60065b 429
kadonotakashi 0:8fdf9a60065b 430 def __init__(self, tgt, top_level_dirs=None, app_config=None):
kadonotakashi 0:8fdf9a60065b 431 """Construct a mbed configuration
kadonotakashi 0:8fdf9a60065b 432
kadonotakashi 0:8fdf9a60065b 433 Positional arguments:
kadonotakashi 0:8fdf9a60065b 434 target - the name of the mbed target used for this configuration
kadonotakashi 0:8fdf9a60065b 435 instance
kadonotakashi 0:8fdf9a60065b 436
kadonotakashi 0:8fdf9a60065b 437 Keyword argumets:
kadonotakashi 0:8fdf9a60065b 438 top_level_dirs - a list of top level source directories (where
kadonotakashi 0:8fdf9a60065b 439 mbed_app_config.json could be found)
kadonotakashi 0:8fdf9a60065b 440 app_config - location of a chosen mbed_app.json file
kadonotakashi 0:8fdf9a60065b 441
kadonotakashi 0:8fdf9a60065b 442 NOTE: Construction of a Config object will look for the application
kadonotakashi 0:8fdf9a60065b 443 configuration file in top_level_dirs. If found once, it'll parse it.
kadonotakashi 0:8fdf9a60065b 444 top_level_dirs may be None (in this case, the constructor will not
kadonotakashi 0:8fdf9a60065b 445 search for a configuration file).
kadonotakashi 0:8fdf9a60065b 446 """
kadonotakashi 0:8fdf9a60065b 447 config_errors = []
kadonotakashi 0:8fdf9a60065b 448 self.config_errors = []
kadonotakashi 0:8fdf9a60065b 449 self.app_config_location = app_config
kadonotakashi 0:8fdf9a60065b 450 if self.app_config_location is None and top_level_dirs:
kadonotakashi 0:8fdf9a60065b 451 self.app_config_location = self.find_app_config(top_level_dirs)
kadonotakashi 0:8fdf9a60065b 452 try:
kadonotakashi 0:8fdf9a60065b 453 self.app_config_data = json_file_to_dict(self.app_config_location) \
kadonotakashi 0:8fdf9a60065b 454 if self.app_config_location else {}
kadonotakashi 0:8fdf9a60065b 455 except ValueError as exc:
kadonotakashi 0:8fdf9a60065b 456 self.app_config_data = {}
kadonotakashi 0:8fdf9a60065b 457 config_errors.append(
kadonotakashi 0:8fdf9a60065b 458 ConfigException("Could not parse mbed app configuration from %s"
kadonotakashi 0:8fdf9a60065b 459 % self.app_config_location))
kadonotakashi 0:8fdf9a60065b 460
kadonotakashi 0:8fdf9a60065b 461
kadonotakashi 0:8fdf9a60065b 462 if self.app_config_location is not None:
kadonotakashi 0:8fdf9a60065b 463 # Validate the format of the JSON file based on schema_app.json
kadonotakashi 0:8fdf9a60065b 464 schema_root = os.path.dirname(os.path.abspath(__file__))
kadonotakashi 0:8fdf9a60065b 465 schema_path = os.path.join(schema_root, "schema_app.json")
kadonotakashi 0:8fdf9a60065b 466 schema = json_file_to_dict(schema_path)
kadonotakashi 0:8fdf9a60065b 467
kadonotakashi 0:8fdf9a60065b 468 url = moves.urllib.request.pathname2url(schema_path)
kadonotakashi 0:8fdf9a60065b 469 uri = moves.urllib_parse.urljoin("file://", url)
kadonotakashi 0:8fdf9a60065b 470
kadonotakashi 0:8fdf9a60065b 471 resolver = RefResolver(uri, schema)
kadonotakashi 0:8fdf9a60065b 472 validator = Draft4Validator(schema, resolver=resolver)
kadonotakashi 0:8fdf9a60065b 473
kadonotakashi 0:8fdf9a60065b 474 errors = sorted(validator.iter_errors(self.app_config_data))
kadonotakashi 0:8fdf9a60065b 475
kadonotakashi 0:8fdf9a60065b 476 if errors:
kadonotakashi 0:8fdf9a60065b 477 raise ConfigException("; ".join(
kadonotakashi 0:8fdf9a60065b 478 self.format_validation_error(x, self.app_config_location)
kadonotakashi 0:8fdf9a60065b 479 for x in errors))
kadonotakashi 0:8fdf9a60065b 480
kadonotakashi 0:8fdf9a60065b 481 # Update the list of targets with the ones defined in the application
kadonotakashi 0:8fdf9a60065b 482 # config, if applicable
kadonotakashi 0:8fdf9a60065b 483 self.lib_config_data = {}
kadonotakashi 0:8fdf9a60065b 484 # Make sure that each config is processed only once
kadonotakashi 0:8fdf9a60065b 485 self.processed_configs = {}
kadonotakashi 0:8fdf9a60065b 486 if isinstance(tgt, Target):
kadonotakashi 0:8fdf9a60065b 487 self.target = tgt
kadonotakashi 0:8fdf9a60065b 488 else:
kadonotakashi 0:8fdf9a60065b 489 if tgt in TARGET_MAP:
kadonotakashi 0:8fdf9a60065b 490 self.target = TARGET_MAP[tgt]
kadonotakashi 0:8fdf9a60065b 491 else:
kadonotakashi 0:8fdf9a60065b 492 self.target = generate_py_target(
kadonotakashi 0:8fdf9a60065b 493 self.app_config_data.get("custom_targets", {}), tgt)
kadonotakashi 0:8fdf9a60065b 494 self.target = deepcopy(self.target)
kadonotakashi 0:8fdf9a60065b 495 self.target_labels = self.target.labels
kadonotakashi 0:8fdf9a60065b 496 for override in BOOTLOADER_OVERRIDES:
kadonotakashi 0:8fdf9a60065b 497 _, attr = override.split(".")
kadonotakashi 0:8fdf9a60065b 498 if not hasattr(self.target, attr):
kadonotakashi 0:8fdf9a60065b 499 setattr(self.target, attr, None)
kadonotakashi 0:8fdf9a60065b 500
kadonotakashi 0:8fdf9a60065b 501 self.cumulative_overrides = {key: ConfigCumulativeOverride(key)
kadonotakashi 0:8fdf9a60065b 502 for key in CUMULATIVE_ATTRIBUTES}
kadonotakashi 0:8fdf9a60065b 503
kadonotakashi 0:8fdf9a60065b 504 self._process_config_and_overrides(self.app_config_data, {}, "app",
kadonotakashi 0:8fdf9a60065b 505 "application")
kadonotakashi 0:8fdf9a60065b 506 self.config_errors = config_errors
kadonotakashi 0:8fdf9a60065b 507
kadonotakashi 0:8fdf9a60065b 508 def add_config_files(self, flist):
kadonotakashi 0:8fdf9a60065b 509 """Add configuration files
kadonotakashi 0:8fdf9a60065b 510
kadonotakashi 0:8fdf9a60065b 511 Positional arguments:
kadonotakashi 0:8fdf9a60065b 512 flist - a list of files to add to this configuration
kadonotakashi 0:8fdf9a60065b 513 """
kadonotakashi 0:8fdf9a60065b 514 for config_file in flist:
kadonotakashi 0:8fdf9a60065b 515 if not config_file.endswith(self.__mbed_lib_config_name):
kadonotakashi 0:8fdf9a60065b 516 continue
kadonotakashi 0:8fdf9a60065b 517 full_path = os.path.normpath(os.path.abspath(config_file))
kadonotakashi 0:8fdf9a60065b 518 # Check that we didn't already process this file
kadonotakashi 0:8fdf9a60065b 519 if full_path in self.processed_configs:
kadonotakashi 0:8fdf9a60065b 520 continue
kadonotakashi 0:8fdf9a60065b 521 self.processed_configs[full_path] = True
kadonotakashi 0:8fdf9a60065b 522 # Read the library configuration and add a "__full_config_path"
kadonotakashi 0:8fdf9a60065b 523 # attribute to it
kadonotakashi 0:8fdf9a60065b 524 try:
kadonotakashi 0:8fdf9a60065b 525 cfg = json_file_to_dict(config_file)
kadonotakashi 0:8fdf9a60065b 526 except ValueError as exc:
kadonotakashi 0:8fdf9a60065b 527 raise ConfigException(str(exc))
kadonotakashi 0:8fdf9a60065b 528
kadonotakashi 0:8fdf9a60065b 529 # Validate the format of the JSON file based on the schema_lib.json
kadonotakashi 0:8fdf9a60065b 530 schema_root = os.path.dirname(os.path.abspath(__file__))
kadonotakashi 0:8fdf9a60065b 531 schema_path = os.path.join(schema_root, "schema_lib.json")
kadonotakashi 0:8fdf9a60065b 532 schema_file = json_file_to_dict(schema_path)
kadonotakashi 0:8fdf9a60065b 533
kadonotakashi 0:8fdf9a60065b 534 url = moves.urllib.request.pathname2url(schema_path)
kadonotakashi 0:8fdf9a60065b 535 uri = moves.urllib_parse.urljoin("file://", url)
kadonotakashi 0:8fdf9a60065b 536
kadonotakashi 0:8fdf9a60065b 537 resolver = RefResolver(uri, schema_file)
kadonotakashi 0:8fdf9a60065b 538 validator = Draft4Validator(schema_file, resolver=resolver)
kadonotakashi 0:8fdf9a60065b 539
kadonotakashi 0:8fdf9a60065b 540 errors = sorted(validator.iter_errors(cfg))
kadonotakashi 0:8fdf9a60065b 541
kadonotakashi 0:8fdf9a60065b 542 if errors:
kadonotakashi 0:8fdf9a60065b 543 raise ConfigException("; ".join(
kadonotakashi 0:8fdf9a60065b 544 self.format_validation_error(x, config_file)
kadonotakashi 0:8fdf9a60065b 545 for x in errors))
kadonotakashi 0:8fdf9a60065b 546
kadonotakashi 0:8fdf9a60065b 547 cfg["__config_path"] = full_path
kadonotakashi 0:8fdf9a60065b 548
kadonotakashi 0:8fdf9a60065b 549 # If there's already a configuration for a module with the same
kadonotakashi 0:8fdf9a60065b 550 # name, exit with error
kadonotakashi 0:8fdf9a60065b 551 if cfg["name"] in self.lib_config_data:
kadonotakashi 0:8fdf9a60065b 552 raise ConfigException(
kadonotakashi 0:8fdf9a60065b 553 "Library name '%s' is not unique (defined in '%s' and '%s')"
kadonotakashi 0:8fdf9a60065b 554 % (cfg["name"], full_path,
kadonotakashi 0:8fdf9a60065b 555 self.lib_config_data[cfg["name"]]["__config_path"]))
kadonotakashi 0:8fdf9a60065b 556 self.lib_config_data[cfg["name"]] = cfg
kadonotakashi 0:8fdf9a60065b 557
kadonotakashi 0:8fdf9a60065b 558 @property
kadonotakashi 0:8fdf9a60065b 559 def has_regions(self):
kadonotakashi 0:8fdf9a60065b 560 """Does this config have regions defined?"""
kadonotakashi 0:8fdf9a60065b 561 for override in ROM_OVERRIDES:
kadonotakashi 0:8fdf9a60065b 562 _, attr = override.split(".")
kadonotakashi 0:8fdf9a60065b 563 if getattr(self.target, attr, None):
kadonotakashi 0:8fdf9a60065b 564 return True
kadonotakashi 0:8fdf9a60065b 565 return False
kadonotakashi 0:8fdf9a60065b 566
kadonotakashi 0:8fdf9a60065b 567 @property
kadonotakashi 0:8fdf9a60065b 568 def has_ram_regions(self):
kadonotakashi 0:8fdf9a60065b 569 """Does this config have regions defined?"""
kadonotakashi 0:8fdf9a60065b 570 for override in RAM_OVERRIDES:
kadonotakashi 0:8fdf9a60065b 571 _, attr = override.split(".")
kadonotakashi 0:8fdf9a60065b 572 if getattr(self.target, attr, None):
kadonotakashi 0:8fdf9a60065b 573 return True
kadonotakashi 0:8fdf9a60065b 574 return False
kadonotakashi 0:8fdf9a60065b 575
kadonotakashi 0:8fdf9a60065b 576 @property
kadonotakashi 0:8fdf9a60065b 577 def sectors(self):
kadonotakashi 0:8fdf9a60065b 578 """Return a list of tuples of sector start,size"""
kadonotakashi 0:8fdf9a60065b 579 cache = Cache(False, False)
kadonotakashi 0:8fdf9a60065b 580 if self.target.device_name not in cache.index:
kadonotakashi 0:8fdf9a60065b 581 raise ConfigException("Bootloader not supported on this target: "
kadonotakashi 0:8fdf9a60065b 582 "targets.json `device_name` not found in "
kadonotakashi 0:8fdf9a60065b 583 "arm_pack_manager index.")
kadonotakashi 0:8fdf9a60065b 584 cmsis_part = cache.index[self.target.device_name]
kadonotakashi 0:8fdf9a60065b 585 sectors = cmsis_part['sectors']
kadonotakashi 0:8fdf9a60065b 586 if sectors:
kadonotakashi 0:8fdf9a60065b 587 return sectors
kadonotakashi 0:8fdf9a60065b 588 raise ConfigException("No sector info available")
kadonotakashi 0:8fdf9a60065b 589
kadonotakashi 0:8fdf9a60065b 590 def _get_cmsis_part(self):
kadonotakashi 0:8fdf9a60065b 591 if not getattr(self.target, "bootloader_supported", False):
kadonotakashi 0:8fdf9a60065b 592 raise ConfigException("Bootloader not supported on this target.")
kadonotakashi 0:8fdf9a60065b 593 if not hasattr(self.target, "device_name"):
kadonotakashi 0:8fdf9a60065b 594 raise ConfigException("Bootloader not supported on this target: "
kadonotakashi 0:8fdf9a60065b 595 "targets.json `device_name` not specified.")
kadonotakashi 0:8fdf9a60065b 596 cache = Cache(False, False)
kadonotakashi 0:8fdf9a60065b 597 if self.target.device_name not in cache.index:
kadonotakashi 0:8fdf9a60065b 598 raise ConfigException("Bootloader not supported on this target: "
kadonotakashi 0:8fdf9a60065b 599 "targets.json `device_name` not found in "
kadonotakashi 0:8fdf9a60065b 600 "arm_pack_manager index.")
kadonotakashi 0:8fdf9a60065b 601 return cache.index[self.target.device_name]
kadonotakashi 0:8fdf9a60065b 602
kadonotakashi 0:8fdf9a60065b 603 def _get_mem_specs(self, memories, cmsis_part, exception_text):
kadonotakashi 0:8fdf9a60065b 604 for memory in memories:
kadonotakashi 0:8fdf9a60065b 605 try:
kadonotakashi 0:8fdf9a60065b 606 size = cmsis_part['memory'][memory]['size']
kadonotakashi 0:8fdf9a60065b 607 start = cmsis_part['memory'][memory]['start']
kadonotakashi 0:8fdf9a60065b 608 return (start, size)
kadonotakashi 0:8fdf9a60065b 609 except KeyError:
kadonotakashi 0:8fdf9a60065b 610 continue
kadonotakashi 0:8fdf9a60065b 611 raise ConfigException(exception_text)
kadonotakashi 0:8fdf9a60065b 612
kadonotakashi 0:8fdf9a60065b 613 @property
kadonotakashi 0:8fdf9a60065b 614 def rom(self):
kadonotakashi 0:8fdf9a60065b 615 """Get rom information as a pair of start_addr, size"""
kadonotakashi 0:8fdf9a60065b 616 # Override rom_start/rom_size
kadonotakashi 0:8fdf9a60065b 617 #
kadonotakashi 0:8fdf9a60065b 618 # This is usually done for a target which:
kadonotakashi 0:8fdf9a60065b 619 # 1. Doesn't support CMSIS pack, or
kadonotakashi 0:8fdf9a60065b 620 # 2. Supports TrustZone and user needs to change its flash partition
kadonotakashi 0:8fdf9a60065b 621 cmsis_part = self._get_cmsis_part()
kadonotakashi 0:8fdf9a60065b 622 rom_start, rom_size = self._get_mem_specs(
kadonotakashi 0:8fdf9a60065b 623 ["IROM1", "PROGRAM_FLASH"],
kadonotakashi 0:8fdf9a60065b 624 cmsis_part,
kadonotakashi 0:8fdf9a60065b 625 "Not enough information in CMSIS packs to build a bootloader "
kadonotakashi 0:8fdf9a60065b 626 "project"
kadonotakashi 0:8fdf9a60065b 627 )
kadonotakashi 0:8fdf9a60065b 628 rom_start = int(getattr(self.target, "mbed_rom_start", False) or rom_start, 0)
kadonotakashi 0:8fdf9a60065b 629 rom_size = int(getattr(self.target, "mbed_rom_size", False) or rom_size, 0)
kadonotakashi 0:8fdf9a60065b 630 return (rom_start, rom_size)
kadonotakashi 0:8fdf9a60065b 631
kadonotakashi 0:8fdf9a60065b 632 @property
kadonotakashi 0:8fdf9a60065b 633 def ram_regions(self):
kadonotakashi 0:8fdf9a60065b 634 """Generate a list of ram regions from the config"""
kadonotakashi 0:8fdf9a60065b 635 cmsis_part = self._get_cmsis_part()
kadonotakashi 0:8fdf9a60065b 636 ram_start, ram_size = self._get_mem_specs(
kadonotakashi 0:8fdf9a60065b 637 ["IRAM1", "SRAM0"],
kadonotakashi 0:8fdf9a60065b 638 cmsis_part,
kadonotakashi 0:8fdf9a60065b 639 "Not enough information in CMSIS packs to build a ram sharing project"
kadonotakashi 0:8fdf9a60065b 640 )
kadonotakashi 0:8fdf9a60065b 641 # Override ram_start/ram_size
kadonotakashi 0:8fdf9a60065b 642 #
kadonotakashi 0:8fdf9a60065b 643 # This is usually done for a target which:
kadonotakashi 0:8fdf9a60065b 644 # 1. Doesn't support CMSIS pack, or
kadonotakashi 0:8fdf9a60065b 645 # 2. Supports TrustZone and user needs to change its flash partition
kadonotakashi 0:8fdf9a60065b 646 ram_start = getattr(self.target, "mbed_ram_start", False) or ram_start
kadonotakashi 0:8fdf9a60065b 647 ram_size = getattr(self.target, "mbed_ram_size", False) or ram_size
kadonotakashi 0:8fdf9a60065b 648 return [RamRegion("application_ram", int(ram_start, 0), int(ram_size, 0), True)]
kadonotakashi 0:8fdf9a60065b 649
kadonotakashi 0:8fdf9a60065b 650 @property
kadonotakashi 0:8fdf9a60065b 651 def regions(self):
kadonotakashi 0:8fdf9a60065b 652 """Generate a list of regions from the config"""
kadonotakashi 0:8fdf9a60065b 653 if ((self.target.bootloader_img or self.target.restrict_size) and
kadonotakashi 0:8fdf9a60065b 654 (self.target.mbed_app_start or self.target.mbed_app_size)):
kadonotakashi 0:8fdf9a60065b 655 raise ConfigException(
kadonotakashi 0:8fdf9a60065b 656 "target.bootloader_img and target.restirct_size are "
kadonotakashi 0:8fdf9a60065b 657 "incompatible with target.mbed_app_start and "
kadonotakashi 0:8fdf9a60065b 658 "target.mbed_app_size")
kadonotakashi 0:8fdf9a60065b 659 if self.target.bootloader_img or self.target.restrict_size:
kadonotakashi 0:8fdf9a60065b 660 return self._generate_bootloader_build(*self.rom)
kadonotakashi 0:8fdf9a60065b 661 else:
kadonotakashi 0:8fdf9a60065b 662 return self._generate_linker_overrides(*self.rom)
kadonotakashi 0:8fdf9a60065b 663
kadonotakashi 0:8fdf9a60065b 664 @staticmethod
kadonotakashi 0:8fdf9a60065b 665 def header_member_size(member):
kadonotakashi 0:8fdf9a60065b 666 _, _, subtype, _ = member
kadonotakashi 0:8fdf9a60065b 667 try:
kadonotakashi 0:8fdf9a60065b 668 return int(subtype[:-2]) // 8
kadonotakashi 0:8fdf9a60065b 669 except:
kadonotakashi 0:8fdf9a60065b 670 if subtype.startswith("CRCITT32"):
kadonotakashi 0:8fdf9a60065b 671 return 32 // 8
kadonotakashi 0:8fdf9a60065b 672 elif subtype == "SHA256":
kadonotakashi 0:8fdf9a60065b 673 return 256 // 8
kadonotakashi 0:8fdf9a60065b 674 elif subtype == "SHA512":
kadonotakashi 0:8fdf9a60065b 675 return 512 // 8
kadonotakashi 0:8fdf9a60065b 676 else:
kadonotakashi 0:8fdf9a60065b 677 raise ValueError("target.header_format: subtype %s is not "
kadonotakashi 0:8fdf9a60065b 678 "understood" % subtype)
kadonotakashi 0:8fdf9a60065b 679
kadonotakashi 0:8fdf9a60065b 680 @staticmethod
kadonotakashi 0:8fdf9a60065b 681 def _header_size(format):
kadonotakashi 0:8fdf9a60065b 682 return sum(Config.header_member_size(m) for m in format)
kadonotakashi 0:8fdf9a60065b 683
kadonotakashi 0:8fdf9a60065b 684 def _make_header_region(self, start, header_format, offset=None):
kadonotakashi 0:8fdf9a60065b 685 size = self._header_size(header_format)
kadonotakashi 0:8fdf9a60065b 686 region = Region("header", start, size, False, None)
kadonotakashi 0:8fdf9a60065b 687 start += size
kadonotakashi 0:8fdf9a60065b 688 start = ((start + 7) // 8) * 8
kadonotakashi 0:8fdf9a60065b 689 return (start, region)
kadonotakashi 0:8fdf9a60065b 690
kadonotakashi 0:8fdf9a60065b 691 @staticmethod
kadonotakashi 0:8fdf9a60065b 692 def _assign_new_offset(rom_start, start, new_offset, region_name):
kadonotakashi 0:8fdf9a60065b 693 newstart = rom_start + integer(new_offset, 0)
kadonotakashi 0:8fdf9a60065b 694 if newstart < start:
kadonotakashi 0:8fdf9a60065b 695 raise ConfigException(
kadonotakashi 0:8fdf9a60065b 696 "Can not place % region inside previous region" % region_name)
kadonotakashi 0:8fdf9a60065b 697 return newstart
kadonotakashi 0:8fdf9a60065b 698
kadonotakashi 0:8fdf9a60065b 699 def _generate_bootloader_build(self, rom_start, rom_size):
kadonotakashi 0:8fdf9a60065b 700 start = rom_start
kadonotakashi 0:8fdf9a60065b 701 rom_end = rom_start + rom_size
kadonotakashi 0:8fdf9a60065b 702 if self.target.bootloader_img:
kadonotakashi 0:8fdf9a60065b 703 if isabs(self.target.bootloader_img):
kadonotakashi 0:8fdf9a60065b 704 filename = self.target.bootloader_img
kadonotakashi 0:8fdf9a60065b 705 else:
kadonotakashi 0:8fdf9a60065b 706 basedir = abspath(dirname(self.app_config_location))
kadonotakashi 0:8fdf9a60065b 707 filename = join(basedir, self.target.bootloader_img)
kadonotakashi 0:8fdf9a60065b 708 if not exists(filename):
kadonotakashi 0:8fdf9a60065b 709 raise ConfigException("Bootloader %s not found" % filename)
kadonotakashi 0:8fdf9a60065b 710 part = intelhex_offset(filename, offset=rom_start)
kadonotakashi 0:8fdf9a60065b 711 if part.minaddr() != rom_start:
kadonotakashi 0:8fdf9a60065b 712 raise ConfigException("bootloader executable does not "
kadonotakashi 0:8fdf9a60065b 713 "start at 0x%x" % rom_start)
kadonotakashi 0:8fdf9a60065b 714 part_size = (part.maxaddr() - part.minaddr()) + 1
kadonotakashi 0:8fdf9a60065b 715 part_size = Config._align_ceiling(rom_start + part_size, self.sectors) - rom_start
kadonotakashi 0:8fdf9a60065b 716 yield Region("bootloader", rom_start, part_size, False,
kadonotakashi 0:8fdf9a60065b 717 filename)
kadonotakashi 0:8fdf9a60065b 718 start = rom_start + part_size
kadonotakashi 0:8fdf9a60065b 719 if self.target.header_format:
kadonotakashi 0:8fdf9a60065b 720 if self.target.header_offset:
kadonotakashi 0:8fdf9a60065b 721 start = self._assign_new_offset(
kadonotakashi 0:8fdf9a60065b 722 rom_start, start, self.target.header_offset, "header")
kadonotakashi 0:8fdf9a60065b 723 start, region = self._make_header_region(
kadonotakashi 0:8fdf9a60065b 724 start, self.target.header_format)
kadonotakashi 0:8fdf9a60065b 725 yield region._replace(filename=self.target.header_format)
kadonotakashi 0:8fdf9a60065b 726 if self.target.restrict_size is not None:
kadonotakashi 0:8fdf9a60065b 727 new_size = int(self.target.restrict_size, 0)
kadonotakashi 0:8fdf9a60065b 728 new_size = Config._align_floor(start + new_size, self.sectors) - start
kadonotakashi 0:8fdf9a60065b 729 yield Region("application", start, new_size, True, None)
kadonotakashi 0:8fdf9a60065b 730 start += new_size
kadonotakashi 0:8fdf9a60065b 731 if self.target.header_format and not self.target.bootloader_img:
kadonotakashi 0:8fdf9a60065b 732 if self.target.header_offset:
kadonotakashi 0:8fdf9a60065b 733 start = self._assign_new_offset(
kadonotakashi 0:8fdf9a60065b 734 rom_start, start, self.target.header_offset, "header")
kadonotakashi 0:8fdf9a60065b 735 start, region = self._make_header_region(
kadonotakashi 0:8fdf9a60065b 736 start, self.target.header_format)
kadonotakashi 0:8fdf9a60065b 737 yield region
kadonotakashi 0:8fdf9a60065b 738 if self.target.app_offset:
kadonotakashi 0:8fdf9a60065b 739 start = self._assign_new_offset(
kadonotakashi 0:8fdf9a60065b 740 rom_start, start, self.target.app_offset, "application")
kadonotakashi 0:8fdf9a60065b 741 yield Region("post_application", start, rom_end - start,
kadonotakashi 0:8fdf9a60065b 742 False, None)
kadonotakashi 0:8fdf9a60065b 743 else:
kadonotakashi 0:8fdf9a60065b 744 if self.target.app_offset:
kadonotakashi 0:8fdf9a60065b 745 start = self._assign_new_offset(
kadonotakashi 0:8fdf9a60065b 746 rom_start, start, self.target.app_offset, "application")
kadonotakashi 0:8fdf9a60065b 747 yield Region("application", start, rom_end - start,
kadonotakashi 0:8fdf9a60065b 748 True, None)
kadonotakashi 0:8fdf9a60065b 749 if start > rom_start + rom_size:
kadonotakashi 0:8fdf9a60065b 750 raise ConfigException("Not enough memory on device to fit all "
kadonotakashi 0:8fdf9a60065b 751 "application regions")
kadonotakashi 0:8fdf9a60065b 752
kadonotakashi 0:8fdf9a60065b 753 @staticmethod
kadonotakashi 0:8fdf9a60065b 754 def _find_sector(address, sectors):
kadonotakashi 0:8fdf9a60065b 755 target_size = -1
kadonotakashi 0:8fdf9a60065b 756 target_start = -1
kadonotakashi 0:8fdf9a60065b 757 for (start, size) in sectors:
kadonotakashi 0:8fdf9a60065b 758 if address < start:
kadonotakashi 0:8fdf9a60065b 759 break
kadonotakashi 0:8fdf9a60065b 760 target_start = start
kadonotakashi 0:8fdf9a60065b 761 target_size = size
kadonotakashi 0:8fdf9a60065b 762 if (target_size < 0):
kadonotakashi 0:8fdf9a60065b 763 raise ConfigException("No valid sector found")
kadonotakashi 0:8fdf9a60065b 764 return target_start, target_size
kadonotakashi 0:8fdf9a60065b 765
kadonotakashi 0:8fdf9a60065b 766 @staticmethod
kadonotakashi 0:8fdf9a60065b 767 def _align_floor(address, sectors):
kadonotakashi 0:8fdf9a60065b 768 target_start, target_size = Config._find_sector(address, sectors)
kadonotakashi 0:8fdf9a60065b 769 sector_num = (address - target_start) // target_size
kadonotakashi 0:8fdf9a60065b 770 return target_start + (sector_num * target_size)
kadonotakashi 0:8fdf9a60065b 771
kadonotakashi 0:8fdf9a60065b 772 @staticmethod
kadonotakashi 0:8fdf9a60065b 773 def _align_ceiling(address, sectors):
kadonotakashi 0:8fdf9a60065b 774 target_start, target_size = Config._find_sector(address, sectors)
kadonotakashi 0:8fdf9a60065b 775 sector_num = ((address - target_start) + target_size - 1) // target_size
kadonotakashi 0:8fdf9a60065b 776 return target_start + (sector_num * target_size)
kadonotakashi 0:8fdf9a60065b 777
kadonotakashi 0:8fdf9a60065b 778 @property
kadonotakashi 0:8fdf9a60065b 779 def report(self):
kadonotakashi 0:8fdf9a60065b 780 return {'app_config': self.app_config_location,
kadonotakashi 0:8fdf9a60065b 781 'library_configs': map(relpath, self.processed_configs.keys())}
kadonotakashi 0:8fdf9a60065b 782
kadonotakashi 0:8fdf9a60065b 783 def _generate_linker_overrides(self, rom_start, rom_size):
kadonotakashi 0:8fdf9a60065b 784 if self.target.mbed_app_start is not None:
kadonotakashi 0:8fdf9a60065b 785 start = int(self.target.mbed_app_start, 0)
kadonotakashi 0:8fdf9a60065b 786 else:
kadonotakashi 0:8fdf9a60065b 787 start = rom_start
kadonotakashi 0:8fdf9a60065b 788 if self.target.mbed_app_size is not None:
kadonotakashi 0:8fdf9a60065b 789 size = int(self.target.mbed_app_size, 0)
kadonotakashi 0:8fdf9a60065b 790 else:
kadonotakashi 0:8fdf9a60065b 791 size = (rom_size + rom_start) - start
kadonotakashi 0:8fdf9a60065b 792 if start < rom_start:
kadonotakashi 0:8fdf9a60065b 793 raise ConfigException("Application starts before ROM")
kadonotakashi 0:8fdf9a60065b 794 if size + start > rom_size + rom_start:
kadonotakashi 0:8fdf9a60065b 795 raise ConfigException("Application ends after ROM")
kadonotakashi 0:8fdf9a60065b 796 yield Region("application", start, size, True, None)
kadonotakashi 0:8fdf9a60065b 797
kadonotakashi 0:8fdf9a60065b 798 def _process_config_and_overrides(self, data, params, unit_name, unit_kind):
kadonotakashi 0:8fdf9a60065b 799 """Process "config_parameters" and "target_config_overrides" into a
kadonotakashi 0:8fdf9a60065b 800 given dictionary
kadonotakashi 0:8fdf9a60065b 801
kadonotakashi 0:8fdf9a60065b 802 Positional arguments:
kadonotakashi 0:8fdf9a60065b 803 data - the configuration data of the library/appliation
kadonotakashi 0:8fdf9a60065b 804 params - storage for the discovered configuration parameters
kadonotakashi 0:8fdf9a60065b 805 unit_name - the unit (library/application) that defines this parameter
kadonotakashi 0:8fdf9a60065b 806 unit_kind - the kind of the unit ("library" or "application")
kadonotakashi 0:8fdf9a60065b 807 """
kadonotakashi 0:8fdf9a60065b 808 _process_config_parameters(data.get("config", {}), params, unit_name,
kadonotakashi 0:8fdf9a60065b 809 unit_kind)
kadonotakashi 0:8fdf9a60065b 810 for label, overrides in data.get("target_overrides", {}).items():
kadonotakashi 0:8fdf9a60065b 811 # If the label is defined by the target or it has the special value
kadonotakashi 0:8fdf9a60065b 812 # "*", process the overrides
kadonotakashi 0:8fdf9a60065b 813 if (label == '*') or (label in self.target_labels):
kadonotakashi 0:8fdf9a60065b 814 # Check for invalid cumulative overrides in libraries
kadonotakashi 0:8fdf9a60065b 815 if (unit_kind == 'library' and
kadonotakashi 0:8fdf9a60065b 816 any(attr.startswith('target.extra_labels') for attr
kadonotakashi 0:8fdf9a60065b 817 in overrides.keys())):
kadonotakashi 0:8fdf9a60065b 818 raise ConfigException(
kadonotakashi 0:8fdf9a60065b 819 "Target override 'target.extra_labels' in " +
kadonotakashi 0:8fdf9a60065b 820 ConfigParameter.get_display_name(unit_name, unit_kind,
kadonotakashi 0:8fdf9a60065b 821 label) +
kadonotakashi 0:8fdf9a60065b 822 " is only allowed at the application level")
kadonotakashi 0:8fdf9a60065b 823
kadonotakashi 0:8fdf9a60065b 824 # Parse out cumulative overrides
kadonotakashi 0:8fdf9a60065b 825 for attr, cumulatives in self.cumulative_overrides.items():
kadonotakashi 0:8fdf9a60065b 826 if 'target.'+attr in overrides:
kadonotakashi 0:8fdf9a60065b 827 key = 'target.' + attr
kadonotakashi 0:8fdf9a60065b 828 if not isinstance(overrides[key], list):
kadonotakashi 0:8fdf9a60065b 829 raise ConfigException(
kadonotakashi 0:8fdf9a60065b 830 "The value of %s.%s is not of type %s" %
kadonotakashi 0:8fdf9a60065b 831 (unit_name, "target_overrides." + key,
kadonotakashi 0:8fdf9a60065b 832 "list"))
kadonotakashi 0:8fdf9a60065b 833 cumulatives.strict_cumulative_overrides(overrides[key])
kadonotakashi 0:8fdf9a60065b 834 del overrides[key]
kadonotakashi 0:8fdf9a60065b 835
kadonotakashi 0:8fdf9a60065b 836 if 'target.'+attr+'_add' in overrides:
kadonotakashi 0:8fdf9a60065b 837 key = 'target.' + attr + "_add"
kadonotakashi 0:8fdf9a60065b 838 if not isinstance(overrides[key], list):
kadonotakashi 0:8fdf9a60065b 839 raise ConfigException(
kadonotakashi 0:8fdf9a60065b 840 "The value of %s.%s is not of type %s" %
kadonotakashi 0:8fdf9a60065b 841 (unit_name, "target_overrides." + key,
kadonotakashi 0:8fdf9a60065b 842 "list"))
kadonotakashi 0:8fdf9a60065b 843 cumulatives.add_cumulative_overrides(overrides[key])
kadonotakashi 0:8fdf9a60065b 844 del overrides[key]
kadonotakashi 0:8fdf9a60065b 845
kadonotakashi 0:8fdf9a60065b 846 if 'target.'+attr+'_remove' in overrides:
kadonotakashi 0:8fdf9a60065b 847 key = 'target.' + attr + "_remove"
kadonotakashi 0:8fdf9a60065b 848 if not isinstance(overrides[key], list):
kadonotakashi 0:8fdf9a60065b 849 raise ConfigException(
kadonotakashi 0:8fdf9a60065b 850 "The value of %s.%s is not of type %s" %
kadonotakashi 0:8fdf9a60065b 851 (unit_name, "target_overrides." + key,
kadonotakashi 0:8fdf9a60065b 852 "list"))
kadonotakashi 0:8fdf9a60065b 853 cumulatives.remove_cumulative_overrides(overrides[key])
kadonotakashi 0:8fdf9a60065b 854 del overrides[key]
kadonotakashi 0:8fdf9a60065b 855
kadonotakashi 0:8fdf9a60065b 856 # Consider the others as overrides
kadonotakashi 0:8fdf9a60065b 857 for name, val in overrides.items():
kadonotakashi 0:8fdf9a60065b 858 if (name in PATH_OVERRIDES and "__config_path" in data):
kadonotakashi 0:8fdf9a60065b 859 val = os.path.join(
kadonotakashi 0:8fdf9a60065b 860 os.path.dirname(data["__config_path"]), val)
kadonotakashi 0:8fdf9a60065b 861
kadonotakashi 0:8fdf9a60065b 862 # Get the full name of the parameter
kadonotakashi 0:8fdf9a60065b 863 full_name = ConfigParameter.get_full_name(name, unit_name,
kadonotakashi 0:8fdf9a60065b 864 unit_kind, label)
kadonotakashi 0:8fdf9a60065b 865 if full_name in params:
kadonotakashi 0:8fdf9a60065b 866 params[full_name].set_value(val, unit_name, unit_kind,
kadonotakashi 0:8fdf9a60065b 867 label)
kadonotakashi 0:8fdf9a60065b 868 elif (name.startswith("target.") and
kadonotakashi 0:8fdf9a60065b 869 (unit_kind is "application" or
kadonotakashi 0:8fdf9a60065b 870 name in BOOTLOADER_OVERRIDES)):
kadonotakashi 0:8fdf9a60065b 871 _, attribute = name.split(".")
kadonotakashi 0:8fdf9a60065b 872 setattr(self.target, attribute, val)
kadonotakashi 0:8fdf9a60065b 873 continue
kadonotakashi 0:8fdf9a60065b 874 else:
kadonotakashi 0:8fdf9a60065b 875 self.config_errors.append(
kadonotakashi 0:8fdf9a60065b 876 UndefinedParameter(
kadonotakashi 0:8fdf9a60065b 877 full_name, unit_name, unit_kind, label))
kadonotakashi 0:8fdf9a60065b 878
kadonotakashi 0:8fdf9a60065b 879 for cumulatives in self.cumulative_overrides.values():
kadonotakashi 0:8fdf9a60065b 880 cumulatives.update_target(self.target)
kadonotakashi 0:8fdf9a60065b 881
kadonotakashi 0:8fdf9a60065b 882 return params
kadonotakashi 0:8fdf9a60065b 883
kadonotakashi 0:8fdf9a60065b 884 def get_target_config_data(self):
kadonotakashi 0:8fdf9a60065b 885 """Read and interpret configuration data defined by targets.
kadonotakashi 0:8fdf9a60065b 886
kadonotakashi 0:8fdf9a60065b 887 We consider the resolution order for our target and sort it by level
kadonotakashi 0:8fdf9a60065b 888 reversed, so that we first look at the top level target (the parent),
kadonotakashi 0:8fdf9a60065b 889 then its direct children, then the children of those children and so on,
kadonotakashi 0:8fdf9a60065b 890 until we reach self.target
kadonotakashi 0:8fdf9a60065b 891 TODO: this might not work so well in some multiple inheritance scenarios
kadonotakashi 0:8fdf9a60065b 892 At each step, look at two keys of the target data:
kadonotakashi 0:8fdf9a60065b 893 - config_parameters: used to define new configuration parameters
kadonotakashi 0:8fdf9a60065b 894 - config_overrides: used to override already defined configuration
kadonotakashi 0:8fdf9a60065b 895 parameters
kadonotakashi 0:8fdf9a60065b 896
kadonotakashi 0:8fdf9a60065b 897 Arguments: None
kadonotakashi 0:8fdf9a60065b 898 """
kadonotakashi 0:8fdf9a60065b 899 params, json_data = {}, self.target.json_data
kadonotakashi 0:8fdf9a60065b 900 resolution_order = [e[0] for e
kadonotakashi 0:8fdf9a60065b 901 in sorted(
kadonotakashi 0:8fdf9a60065b 902 self.target.resolution_order,
kadonotakashi 0:8fdf9a60065b 903 key=lambda e: e[1], reverse=True)]
kadonotakashi 0:8fdf9a60065b 904 for tname in resolution_order:
kadonotakashi 0:8fdf9a60065b 905 # Read the target data directly from its description
kadonotakashi 0:8fdf9a60065b 906 target_data = json_data[tname]
kadonotakashi 0:8fdf9a60065b 907 # Process definitions first
kadonotakashi 0:8fdf9a60065b 908 _process_config_parameters(target_data.get("config", {}), params,
kadonotakashi 0:8fdf9a60065b 909 tname, "target")
kadonotakashi 0:8fdf9a60065b 910 # Then process overrides
kadonotakashi 0:8fdf9a60065b 911 for name, val in target_data.get("overrides", {}).items():
kadonotakashi 0:8fdf9a60065b 912 full_name = ConfigParameter.get_full_name(name, tname, "target")
kadonotakashi 0:8fdf9a60065b 913 # If the parameter name is not defined or if there isn't a path
kadonotakashi 0:8fdf9a60065b 914 # from this target to the target where the parameter was defined
kadonotakashi 0:8fdf9a60065b 915 # in the target inheritance tree, raise an error We need to use
kadonotakashi 0:8fdf9a60065b 916 # 'defined_by[7:]' to remove the "target:" prefix from
kadonotakashi 0:8fdf9a60065b 917 # defined_by
kadonotakashi 0:8fdf9a60065b 918 rel_names = [tgt for tgt, _ in
kadonotakashi 0:8fdf9a60065b 919 get_resolution_order(self.target.json_data, tname,
kadonotakashi 0:8fdf9a60065b 920 [])]
kadonotakashi 0:8fdf9a60065b 921 if full_name in BOOTLOADER_OVERRIDES:
kadonotakashi 0:8fdf9a60065b 922 continue
kadonotakashi 0:8fdf9a60065b 923 if (full_name not in params) or \
kadonotakashi 0:8fdf9a60065b 924 (params[full_name].defined_by[7:] not in rel_names):
kadonotakashi 0:8fdf9a60065b 925 raise UndefinedParameter(name, tname, "target", "")
kadonotakashi 0:8fdf9a60065b 926 # Otherwise update the value of the parameter
kadonotakashi 0:8fdf9a60065b 927 params[full_name].set_value(val, tname, "target")
kadonotakashi 0:8fdf9a60065b 928 return params
kadonotakashi 0:8fdf9a60065b 929
kadonotakashi 0:8fdf9a60065b 930 def get_lib_config_data(self, target_data):
kadonotakashi 0:8fdf9a60065b 931 """ Read and interpret configuration data defined by libraries. It is
kadonotakashi 0:8fdf9a60065b 932 assumed that "add_config_files" above was already called and the library
kadonotakashi 0:8fdf9a60065b 933 configuration data exists in self.lib_config_data
kadonotakashi 0:8fdf9a60065b 934
kadonotakashi 0:8fdf9a60065b 935 Arguments: None
kadonotakashi 0:8fdf9a60065b 936 """
kadonotakashi 0:8fdf9a60065b 937 macros = {}
kadonotakashi 0:8fdf9a60065b 938 for lib_name, lib_data in self.lib_config_data.items():
kadonotakashi 0:8fdf9a60065b 939 self._process_config_and_overrides(
kadonotakashi 0:8fdf9a60065b 940 lib_data, target_data, lib_name, "library")
kadonotakashi 0:8fdf9a60065b 941 _process_macros(lib_data.get("macros", []), macros, lib_name,
kadonotakashi 0:8fdf9a60065b 942 "library")
kadonotakashi 0:8fdf9a60065b 943 return target_data, macros
kadonotakashi 0:8fdf9a60065b 944
kadonotakashi 0:8fdf9a60065b 945 def get_app_config_data(self, params, macros):
kadonotakashi 0:8fdf9a60065b 946 """ Read and interpret the configuration data defined by the target. The
kadonotakashi 0:8fdf9a60065b 947 target can override any configuration parameter, as well as define its
kadonotakashi 0:8fdf9a60065b 948 own configuration data.
kadonotakashi 0:8fdf9a60065b 949
kadonotakashi 0:8fdf9a60065b 950 Positional arguments.
kadonotakashi 0:8fdf9a60065b 951 params - the dictionary with configuration parameters found so far (in
kadonotakashi 0:8fdf9a60065b 952 the target and in libraries)
kadonotakashi 0:8fdf9a60065b 953 macros - the list of macros defined in the configuration
kadonotakashi 0:8fdf9a60065b 954 """
kadonotakashi 0:8fdf9a60065b 955 app_cfg = self.app_config_data
kadonotakashi 0:8fdf9a60065b 956 # The application can have a "config_parameters" and a
kadonotakashi 0:8fdf9a60065b 957 # "target_config_overrides" section just like a library
kadonotakashi 0:8fdf9a60065b 958 self._process_config_and_overrides(app_cfg, params, "app",
kadonotakashi 0:8fdf9a60065b 959 "application")
kadonotakashi 0:8fdf9a60065b 960 # The application can also defined macros
kadonotakashi 0:8fdf9a60065b 961 _process_macros(app_cfg.get("macros", []), macros, "app",
kadonotakashi 0:8fdf9a60065b 962 "application")
kadonotakashi 0:8fdf9a60065b 963
kadonotakashi 0:8fdf9a60065b 964 def get_config_data(self):
kadonotakashi 0:8fdf9a60065b 965 """ Return the configuration data in two parts: (params, macros)
kadonotakashi 0:8fdf9a60065b 966 params - a dictionary with mapping a name to a ConfigParam
kadonotakashi 0:8fdf9a60065b 967 macros - the list of macros defined with "macros" in libraries and in
kadonotakashi 0:8fdf9a60065b 968 the application (as ConfigMacro instances)
kadonotakashi 0:8fdf9a60065b 969
kadonotakashi 0:8fdf9a60065b 970 Arguments: None
kadonotakashi 0:8fdf9a60065b 971 """
kadonotakashi 0:8fdf9a60065b 972 all_params = self.get_target_config_data()
kadonotakashi 0:8fdf9a60065b 973 lib_params, macros = self.get_lib_config_data(all_params)
kadonotakashi 0:8fdf9a60065b 974 self.get_app_config_data(lib_params, macros)
kadonotakashi 0:8fdf9a60065b 975 return lib_params, macros
kadonotakashi 0:8fdf9a60065b 976
kadonotakashi 0:8fdf9a60065b 977 @staticmethod
kadonotakashi 0:8fdf9a60065b 978 def _check_required_parameters(params):
kadonotakashi 0:8fdf9a60065b 979 """Check that there are no required parameters without a value
kadonotakashi 0:8fdf9a60065b 980
kadonotakashi 0:8fdf9a60065b 981 Positional arguments:
kadonotakashi 0:8fdf9a60065b 982 params - the list of parameters to check
kadonotakashi 0:8fdf9a60065b 983
kadonotakashi 0:8fdf9a60065b 984 NOTE: This function does not return. Instead, it throws a
kadonotakashi 0:8fdf9a60065b 985 ConfigException when any of the required parameters are missing values
kadonotakashi 0:8fdf9a60065b 986 """
kadonotakashi 0:8fdf9a60065b 987 for param in params.values():
kadonotakashi 0:8fdf9a60065b 988 if param.required and (param.value is None):
kadonotakashi 0:8fdf9a60065b 989 raise ConfigException("Required parameter '" + param.name +
kadonotakashi 0:8fdf9a60065b 990 "' defined by '" + param.defined_by +
kadonotakashi 0:8fdf9a60065b 991 "' doesn't have a value")
kadonotakashi 0:8fdf9a60065b 992
kadonotakashi 0:8fdf9a60065b 993 @staticmethod
kadonotakashi 0:8fdf9a60065b 994 def parameters_to_macros(params):
kadonotakashi 0:8fdf9a60065b 995 """ Encode the configuration parameters as C macro definitions.
kadonotakashi 0:8fdf9a60065b 996
kadonotakashi 0:8fdf9a60065b 997 Positional arguments:
kadonotakashi 0:8fdf9a60065b 998 params - a dictionary mapping a name to a ConfigParameter
kadonotakashi 0:8fdf9a60065b 999
kadonotakashi 0:8fdf9a60065b 1000 Return: a list of strings that encode the configuration parameters as
kadonotakashi 0:8fdf9a60065b 1001 C pre-processor macros
kadonotakashi 0:8fdf9a60065b 1002 """
kadonotakashi 0:8fdf9a60065b 1003 return ['%s=%s' % (m.macro_name, m.value) for m in params.values()
kadonotakashi 0:8fdf9a60065b 1004 if m.value is not None]
kadonotakashi 0:8fdf9a60065b 1005
kadonotakashi 0:8fdf9a60065b 1006 @staticmethod
kadonotakashi 0:8fdf9a60065b 1007 def config_macros_to_macros(macros):
kadonotakashi 0:8fdf9a60065b 1008 """ Return the macro definitions generated for a dictionary of
kadonotakashi 0:8fdf9a60065b 1009 ConfigMacros (as returned by get_config_data).
kadonotakashi 0:8fdf9a60065b 1010
kadonotakashi 0:8fdf9a60065b 1011 Positional arguments:
kadonotakashi 0:8fdf9a60065b 1012 params - a dictionary mapping a name to a ConfigMacro instance
kadonotakashi 0:8fdf9a60065b 1013
kadonotakashi 0:8fdf9a60065b 1014 Return: a list of strings that are the C pre-processor macros
kadonotakashi 0:8fdf9a60065b 1015 """
kadonotakashi 0:8fdf9a60065b 1016 return [m.name for m in macros.values()]
kadonotakashi 0:8fdf9a60065b 1017
kadonotakashi 0:8fdf9a60065b 1018 @staticmethod
kadonotakashi 0:8fdf9a60065b 1019 def config_to_macros(config):
kadonotakashi 0:8fdf9a60065b 1020 """Convert the configuration data to a list of C macros
kadonotakashi 0:8fdf9a60065b 1021
kadonotakashi 0:8fdf9a60065b 1022 Positional arguments:
kadonotakashi 0:8fdf9a60065b 1023 config - configuration data as (ConfigParam instances, ConfigMacro
kadonotakashi 0:8fdf9a60065b 1024 instances) tuple (as returned by get_config_data())
kadonotakashi 0:8fdf9a60065b 1025 """
kadonotakashi 0:8fdf9a60065b 1026 params, macros = config[0], config[1]
kadonotakashi 0:8fdf9a60065b 1027 Config._check_required_parameters(params)
kadonotakashi 0:8fdf9a60065b 1028 return Config.config_macros_to_macros(macros) + \
kadonotakashi 0:8fdf9a60065b 1029 Config.parameters_to_macros(params)
kadonotakashi 0:8fdf9a60065b 1030
kadonotakashi 0:8fdf9a60065b 1031 def get_config_data_macros(self):
kadonotakashi 0:8fdf9a60065b 1032 """ Convert a Config object to a list of C macros
kadonotakashi 0:8fdf9a60065b 1033
kadonotakashi 0:8fdf9a60065b 1034 Arguments: None
kadonotakashi 0:8fdf9a60065b 1035 """
kadonotakashi 0:8fdf9a60065b 1036 return self.config_to_macros(self.get_config_data())
kadonotakashi 0:8fdf9a60065b 1037
kadonotakashi 0:8fdf9a60065b 1038 def get_features(self):
kadonotakashi 0:8fdf9a60065b 1039 """ Extract any features from the configuration data
kadonotakashi 0:8fdf9a60065b 1040
kadonotakashi 0:8fdf9a60065b 1041 Arguments: None
kadonotakashi 0:8fdf9a60065b 1042 """
kadonotakashi 0:8fdf9a60065b 1043 params, _ = self.get_config_data()
kadonotakashi 0:8fdf9a60065b 1044 self._check_required_parameters(params)
kadonotakashi 0:8fdf9a60065b 1045 self.cumulative_overrides['features']\
kadonotakashi 0:8fdf9a60065b 1046 .update_target(self.target)
kadonotakashi 0:8fdf9a60065b 1047
kadonotakashi 0:8fdf9a60065b 1048 for feature in self.target.features:
kadonotakashi 0:8fdf9a60065b 1049 if feature not in ALLOWED_FEATURES:
kadonotakashi 0:8fdf9a60065b 1050 raise ConfigException(
kadonotakashi 0:8fdf9a60065b 1051 "Feature '%s' is not a supported features" % feature)
kadonotakashi 0:8fdf9a60065b 1052
kadonotakashi 0:8fdf9a60065b 1053 return self.target.features
kadonotakashi 0:8fdf9a60065b 1054
kadonotakashi 0:8fdf9a60065b 1055 def validate_config(self):
kadonotakashi 0:8fdf9a60065b 1056 """ Validate configuration settings. This either returns True or
kadonotakashi 0:8fdf9a60065b 1057 raises an exception
kadonotakashi 0:8fdf9a60065b 1058
kadonotakashi 0:8fdf9a60065b 1059 Arguments: None
kadonotakashi 0:8fdf9a60065b 1060 """
kadonotakashi 0:8fdf9a60065b 1061 params, _ = self.get_config_data()
kadonotakashi 0:8fdf9a60065b 1062 for error in self.config_errors:
kadonotakashi 0:8fdf9a60065b 1063 if (isinstance(error, UndefinedParameter) and
kadonotakashi 0:8fdf9a60065b 1064 error.param in params):
kadonotakashi 0:8fdf9a60065b 1065 continue
kadonotakashi 0:8fdf9a60065b 1066 else:
kadonotakashi 0:8fdf9a60065b 1067 raise error
kadonotakashi 0:8fdf9a60065b 1068 return True
kadonotakashi 0:8fdf9a60065b 1069
kadonotakashi 0:8fdf9a60065b 1070
kadonotakashi 0:8fdf9a60065b 1071 @property
kadonotakashi 0:8fdf9a60065b 1072 def name(self):
kadonotakashi 0:8fdf9a60065b 1073 if "artifact_name" in self.app_config_data:
kadonotakashi 0:8fdf9a60065b 1074 return self.app_config_data["artifact_name"]
kadonotakashi 0:8fdf9a60065b 1075 else:
kadonotakashi 0:8fdf9a60065b 1076 return None
kadonotakashi 0:8fdf9a60065b 1077
kadonotakashi 0:8fdf9a60065b 1078 def load_resources(self, resources):
kadonotakashi 0:8fdf9a60065b 1079 """ Load configuration data from a Resources instance and expand it
kadonotakashi 0:8fdf9a60065b 1080 based on defined features.
kadonotakashi 0:8fdf9a60065b 1081
kadonotakashi 0:8fdf9a60065b 1082 Positional arguments:
kadonotakashi 0:8fdf9a60065b 1083 resources - the resources object to load from and expand
kadonotakashi 0:8fdf9a60065b 1084 """
kadonotakashi 0:8fdf9a60065b 1085 # Update configuration files until added features creates no changes
kadonotakashi 0:8fdf9a60065b 1086 prev_features = set()
kadonotakashi 0:8fdf9a60065b 1087 while True:
kadonotakashi 0:8fdf9a60065b 1088 # Add/update the configuration with any .json files found while
kadonotakashi 0:8fdf9a60065b 1089 # scanning
kadonotakashi 0:8fdf9a60065b 1090 self.add_config_files(
kadonotakashi 0:8fdf9a60065b 1091 f.path for f in resources.get_file_refs(FileType.JSON)
kadonotakashi 0:8fdf9a60065b 1092 )
kadonotakashi 0:8fdf9a60065b 1093
kadonotakashi 0:8fdf9a60065b 1094 # Add features while we find new ones
kadonotakashi 0:8fdf9a60065b 1095 features = set(self.get_features())
kadonotakashi 0:8fdf9a60065b 1096 if features == prev_features:
kadonotakashi 0:8fdf9a60065b 1097 break
kadonotakashi 0:8fdf9a60065b 1098
kadonotakashi 0:8fdf9a60065b 1099 resources.add_features(features)
kadonotakashi 0:8fdf9a60065b 1100
kadonotakashi 0:8fdf9a60065b 1101 prev_features = features
kadonotakashi 0:8fdf9a60065b 1102 self.validate_config()
kadonotakashi 0:8fdf9a60065b 1103
kadonotakashi 0:8fdf9a60065b 1104 if (hasattr(self.target, "release_versions") and
kadonotakashi 0:8fdf9a60065b 1105 "5" not in self.target.release_versions and
kadonotakashi 0:8fdf9a60065b 1106 "rtos" in self.lib_config_data):
kadonotakashi 0:8fdf9a60065b 1107 raise NotSupportedException("Target does not support mbed OS 5")
kadonotakashi 0:8fdf9a60065b 1108
kadonotakashi 0:8fdf9a60065b 1109 @staticmethod
kadonotakashi 0:8fdf9a60065b 1110 def config_to_header(config, fname=None):
kadonotakashi 0:8fdf9a60065b 1111 """ Convert the configuration data to the content of a C header file,
kadonotakashi 0:8fdf9a60065b 1112 meant to be included to a C/C++ file. The content is returned as a
kadonotakashi 0:8fdf9a60065b 1113 string.
kadonotakashi 0:8fdf9a60065b 1114
kadonotakashi 0:8fdf9a60065b 1115 Positional arguments:
kadonotakashi 0:8fdf9a60065b 1116 config - configuration data as (ConfigParam instances, ConfigMacro
kadonotakashi 0:8fdf9a60065b 1117 instances) tuple (as returned by get_config_data())
kadonotakashi 0:8fdf9a60065b 1118
kadonotakashi 0:8fdf9a60065b 1119 Keyword arguments:
kadonotakashi 0:8fdf9a60065b 1120 fname - also write the content is to the file called "fname".
kadonotakashi 0:8fdf9a60065b 1121 WARNING: if 'fname' names an existing file, it will be
kadonotakashi 0:8fdf9a60065b 1122 overwritten!
kadonotakashi 0:8fdf9a60065b 1123 """
kadonotakashi 0:8fdf9a60065b 1124 params, macros = config[0] or {}, config[1] or {}
kadonotakashi 0:8fdf9a60065b 1125 Config._check_required_parameters(params)
kadonotakashi 0:8fdf9a60065b 1126 params_with_values = [p for p in params.values() if p.value is not None]
kadonotakashi 0:8fdf9a60065b 1127 ctx = {
kadonotakashi 0:8fdf9a60065b 1128 "cfg_params": sorted([
kadonotakashi 0:8fdf9a60065b 1129 (p.macro_name, str(p.value), p.set_by)
kadonotakashi 0:8fdf9a60065b 1130 for p in params_with_values
kadonotakashi 0:8fdf9a60065b 1131 ]),
kadonotakashi 0:8fdf9a60065b 1132 "macros": sorted([
kadonotakashi 0:8fdf9a60065b 1133 (m.macro_name, str(m.macro_value or ""), m.defined_by)
kadonotakashi 0:8fdf9a60065b 1134 for m in macros.values()
kadonotakashi 0:8fdf9a60065b 1135 ]),
kadonotakashi 0:8fdf9a60065b 1136 "name_len": max([len(m.macro_name) for m in macros.values()] +
kadonotakashi 0:8fdf9a60065b 1137 [len(m.macro_name) for m in params_with_values]
kadonotakashi 0:8fdf9a60065b 1138 + [0]),
kadonotakashi 0:8fdf9a60065b 1139 "val_len" : max([len(str(m.value)) for m in params_with_values] +
kadonotakashi 0:8fdf9a60065b 1140 [len(m.macro_value or "") for m in macros.values()]
kadonotakashi 0:8fdf9a60065b 1141 + [0]),
kadonotakashi 0:8fdf9a60065b 1142 }
kadonotakashi 0:8fdf9a60065b 1143 jinja_loader = FileSystemLoader(dirname(abspath(__file__)))
kadonotakashi 0:8fdf9a60065b 1144 jinja_environment = Environment(loader=jinja_loader,
kadonotakashi 0:8fdf9a60065b 1145 undefined=StrictUndefined)
kadonotakashi 0:8fdf9a60065b 1146 header_data = jinja_environment.get_template("header.tmpl").render(ctx)
kadonotakashi 0:8fdf9a60065b 1147 # If fname is given, write "header_data" to it
kadonotakashi 0:8fdf9a60065b 1148 if fname:
kadonotakashi 0:8fdf9a60065b 1149 with open(fname, "w+") as file_desc:
kadonotakashi 0:8fdf9a60065b 1150 file_desc.write(header_data)
kadonotakashi 0:8fdf9a60065b 1151 return header_data
kadonotakashi 0:8fdf9a60065b 1152
kadonotakashi 0:8fdf9a60065b 1153 def get_config_data_header(self, fname=None):
kadonotakashi 0:8fdf9a60065b 1154 """ Convert a Config instance to the content of a C header file, meant
kadonotakashi 0:8fdf9a60065b 1155 to be included to a C/C++ file. The content is returned as a string.
kadonotakashi 0:8fdf9a60065b 1156
kadonotakashi 0:8fdf9a60065b 1157 Keyword arguments:
kadonotakashi 0:8fdf9a60065b 1158 fname - also write the content to the file called "fname".
kadonotakashi 0:8fdf9a60065b 1159 WARNING: if 'fname' names an existing file, it will be
kadonotakashi 0:8fdf9a60065b 1160 overwritten!
kadonotakashi 0:8fdf9a60065b 1161 """
kadonotakashi 0:8fdf9a60065b 1162 return self.config_to_header(self.get_config_data(), fname)