mirror of https://github.com/ARMmbed/mbed-os.git
Merge pull request #10113 from theotherjimmy/use-ns-rom-in-bl
Use secure/non-secure rom for bl modespull/10086/head
commit
35e30e1b70
|
|
@ -18,15 +18,11 @@ from __future__ import print_function, division, absolute_import
|
||||||
|
|
||||||
from copy import deepcopy
|
from copy import deepcopy
|
||||||
from six import moves
|
from six import moves
|
||||||
import json
|
|
||||||
import six
|
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
from os.path import dirname, abspath, exists, join, isabs
|
from os.path import dirname, abspath, exists, join, isabs
|
||||||
import sys
|
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
from os.path import splitext, relpath
|
from os.path import relpath
|
||||||
from intelhex import IntelHex
|
|
||||||
from jinja2 import FileSystemLoader, StrictUndefined
|
from jinja2 import FileSystemLoader, StrictUndefined
|
||||||
from jinja2.environment import Environment
|
from jinja2.environment import Environment
|
||||||
from jsonschema import Draft4Validator, RefResolver
|
from jsonschema import Draft4Validator, RefResolver
|
||||||
|
|
@ -77,19 +73,21 @@ ALLOWED_FEATURES = [
|
||||||
]
|
]
|
||||||
|
|
||||||
# List of all possible ram memories that can be available for a target
|
# List of all possible ram memories that can be available for a target
|
||||||
RAM_ALL_MEMORIES = ['IRAM1', 'IRAM2', 'IRAM3', 'IRAM4', 'SRAM_OC', \
|
RAM_ALL_MEMORIES = ['IRAM1', 'IRAM2', 'IRAM3', 'IRAM4', 'SRAM_OC',
|
||||||
'SRAM_ITC', 'SRAM_DTC', 'SRAM_UPPER', 'SRAM_LOWER', \
|
'SRAM_ITC', 'SRAM_DTC', 'SRAM_UPPER', 'SRAM_LOWER',
|
||||||
'SRAM']
|
'SRAM']
|
||||||
|
|
||||||
# List of all possible rom memories that can be available for a target
|
# List of all possible rom memories that can be available for a target
|
||||||
ROM_ALL_MEMORIES = ['IROM1', 'PROGRAM_FLASH', 'IROM2']
|
ROM_ALL_MEMORIES = ['IROM1', 'PROGRAM_FLASH', 'IROM2']
|
||||||
|
|
||||||
|
|
||||||
# Base class for all configuration exceptions
|
# Base class for all configuration exceptions
|
||||||
class ConfigException(Exception):
|
class ConfigException(Exception):
|
||||||
"""Config system only exception. Makes it easier to distinguish config
|
"""Config system only exception. Makes it easier to distinguish config
|
||||||
errors"""
|
errors"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class UndefinedParameter(ConfigException):
|
class UndefinedParameter(ConfigException):
|
||||||
def __init__(self, param, name, kind, label):
|
def __init__(self, param, name, kind, label):
|
||||||
self.param = param
|
self.param = param
|
||||||
|
|
@ -103,6 +101,7 @@ class UndefinedParameter(ConfigException):
|
||||||
ConfigParameter.get_display_name(self.name, self.kind, self.label),
|
ConfigParameter.get_display_name(self.name, self.kind, self.label),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class ConfigParameter(object):
|
class ConfigParameter(object):
|
||||||
"""This class keeps information about a single configuration parameter"""
|
"""This class keeps information about a single configuration parameter"""
|
||||||
|
|
||||||
|
|
@ -121,13 +120,13 @@ class ConfigParameter(object):
|
||||||
allow_prefix=False)
|
allow_prefix=False)
|
||||||
self.defined_by = self.get_display_name(unit_name, unit_kind)
|
self.defined_by = self.get_display_name(unit_name, unit_kind)
|
||||||
self.set_value(data.get("value", None), unit_name, unit_kind)
|
self.set_value(data.get("value", None), unit_name, unit_kind)
|
||||||
self.value_min = data.get("value_min")
|
self.value_min = data.get("value_min")
|
||||||
self.value_max = data.get("value_max")
|
self.value_max = data.get("value_max")
|
||||||
self.accepted_values = data.get("accepted_values")
|
self.accepted_values = data.get("accepted_values")
|
||||||
self.help_text = data.get("help", None)
|
self.help_text = data.get("help", None)
|
||||||
self.required = data.get("required", False)
|
self.required = data.get("required", False)
|
||||||
self.conflicts = data.get("conflicts", [])
|
self.conflicts = data.get("conflicts", [])
|
||||||
self.macro_name = data.get("macro_name", "MBED_CONF_%s" %
|
self.macro_name = data.get("macro_name", "MBED_CONF_%s" %
|
||||||
self.sanitize(self.name.upper()))
|
self.sanitize(self.name.upper()))
|
||||||
self.config_errors = []
|
self.config_errors = []
|
||||||
|
|
||||||
|
|
@ -148,7 +147,8 @@ class ConfigParameter(object):
|
||||||
allow_prefix - True to allow the original name to have a prefix, False
|
allow_prefix - True to allow the original name to have a prefix, False
|
||||||
otherwise
|
otherwise
|
||||||
"""
|
"""
|
||||||
if name.find('.') == -1: # the name is not prefixed
|
# the name is not prefixed
|
||||||
|
if name.find('.') == -1:
|
||||||
if unit_kind == "target":
|
if unit_kind == "target":
|
||||||
prefix = "target."
|
prefix = "target."
|
||||||
elif unit_kind == "application":
|
elif unit_kind == "application":
|
||||||
|
|
@ -172,8 +172,10 @@ class ConfigParameter(object):
|
||||||
unit_name, unit_kind, label)))
|
unit_name, unit_kind, label)))
|
||||||
prefix = temp[0]
|
prefix = temp[0]
|
||||||
# Check if the given parameter prefix matches the expected prefix
|
# Check if the given parameter prefix matches the expected prefix
|
||||||
if (unit_kind == "library" and prefix not in [unit_name, "target"]) or \
|
if (
|
||||||
(unit_kind == "target" and prefix != "target"):
|
(unit_kind == "library" and prefix not in [unit_name, "target"]) or
|
||||||
|
(unit_kind == "target" and prefix != "target")
|
||||||
|
):
|
||||||
raise ConfigException(
|
raise ConfigException(
|
||||||
"Invalid prefix '%s' for parameter name '%s' in '%s'" %
|
"Invalid prefix '%s' for parameter name '%s' in '%s'" %
|
||||||
(prefix, name, ConfigParameter.get_display_name(
|
(prefix, name, ConfigParameter.get_display_name(
|
||||||
|
|
@ -197,8 +199,11 @@ class ConfigParameter(object):
|
||||||
return "target:" + unit_name
|
return "target:" + unit_name
|
||||||
elif unit_kind == "application":
|
elif unit_kind == "application":
|
||||||
return "application%s" % ("[%s]" % label if label else "")
|
return "application%s" % ("[%s]" % label if label else "")
|
||||||
else: # library
|
else: # library
|
||||||
return "library:%s%s" % (unit_name, "[%s]" % label if label else "")
|
return "library:%s%s" % (
|
||||||
|
unit_name,
|
||||||
|
"[%s]" % label if label else ""
|
||||||
|
)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def sanitize(name):
|
def sanitize(name):
|
||||||
|
|
@ -258,6 +263,7 @@ class ConfigParameter(object):
|
||||||
desc += " Conflicts with %s" % ", ".join(self.conflicts)
|
desc += " Conflicts with %s" % ", ".join(self.conflicts)
|
||||||
return desc
|
return desc
|
||||||
|
|
||||||
|
|
||||||
class ConfigMacro(object):
|
class ConfigMacro(object):
|
||||||
""" A representation of a configuration macro. It handles both macros
|
""" A representation of a configuration macro. It handles both macros
|
||||||
without a value (MACRO) and with a value (MACRO=VALUE)
|
without a value (MACRO) and with a value (MACRO=VALUE)
|
||||||
|
|
@ -271,7 +277,9 @@ class ConfigMacro(object):
|
||||||
unit_kind - the type of macro this is
|
unit_kind - the type of macro this is
|
||||||
"""
|
"""
|
||||||
self.name = name
|
self.name = name
|
||||||
self.defined_by = ConfigParameter.get_display_name(unit_name, unit_kind)
|
self.defined_by = ConfigParameter.get_display_name(
|
||||||
|
unit_name, unit_kind
|
||||||
|
)
|
||||||
if name.find("=") != -1:
|
if name.find("=") != -1:
|
||||||
tmp = name.split("=")
|
tmp = name.split("=")
|
||||||
if len(tmp) != 2:
|
if len(tmp) != 2:
|
||||||
|
|
@ -283,6 +291,7 @@ class ConfigMacro(object):
|
||||||
self.macro_name = name
|
self.macro_name = name
|
||||||
self.macro_value = None
|
self.macro_value = None
|
||||||
|
|
||||||
|
|
||||||
class ConfigCumulativeOverride(object):
|
class ConfigCumulativeOverride(object):
|
||||||
"""Representation of overrides for cumulative attributes"""
|
"""Representation of overrides for cumulative attributes"""
|
||||||
def __init__(self, name, additions=None, removals=None, strict=False):
|
def __init__(self, name, additions=None, removals=None, strict=False):
|
||||||
|
|
@ -327,8 +336,8 @@ class ConfigCumulativeOverride(object):
|
||||||
"""Extend the list of override additions.
|
"""Extend the list of override additions.
|
||||||
|
|
||||||
Positional arguments:
|
Positional arguments:
|
||||||
overrides - a list of a names that, when the override is evaluated, will
|
overrides - a list of a names that, when the override is evaluated,
|
||||||
be added to the list
|
will be added to the list
|
||||||
"""
|
"""
|
||||||
for override in overrides:
|
for override in overrides:
|
||||||
if override in self.removals or \
|
if override in self.removals or \
|
||||||
|
|
@ -414,6 +423,7 @@ def _process_macros(mlist, macros, unit_name, unit_kind):
|
||||||
Region = namedtuple("Region", "name start size active filename")
|
Region = namedtuple("Region", "name start size active filename")
|
||||||
RamRegion = namedtuple("RamRegion", "name start size active")
|
RamRegion = namedtuple("RamRegion", "name start size active")
|
||||||
|
|
||||||
|
|
||||||
class Config(object):
|
class Config(object):
|
||||||
"""'Config' implements the mbed configuration mechanism"""
|
"""'Config' implements the mbed configuration mechanism"""
|
||||||
|
|
||||||
|
|
@ -432,9 +442,13 @@ class Config(object):
|
||||||
full_path = os.path.join(directory, cls.__mbed_app_config_name)
|
full_path = os.path.join(directory, cls.__mbed_app_config_name)
|
||||||
if os.path.isfile(full_path):
|
if os.path.isfile(full_path):
|
||||||
if app_config_location is not None:
|
if app_config_location is not None:
|
||||||
raise ConfigException("Duplicate '%s' file in '%s' and '%s'"
|
raise ConfigException(
|
||||||
% (cls.__mbed_app_config_name,
|
"Duplicate '{}' file in '{}' and '{}'".format(
|
||||||
cls.app_config_location, full_path))
|
cls.__mbed_app_config_name,
|
||||||
|
cls.app_config_location,
|
||||||
|
full_path
|
||||||
|
)
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
app_config_location = full_path
|
app_config_location = full_path
|
||||||
return app_config_location
|
return app_config_location
|
||||||
|
|
@ -445,7 +459,7 @@ class Config(object):
|
||||||
else:
|
else:
|
||||||
return "in {} element {}: {}".format(
|
return "in {} element {}: {}".format(
|
||||||
path, ".".join(p for p in error.absolute_path),
|
path, ".".join(p for p in error.absolute_path),
|
||||||
error.message.replace('u\'','\''))
|
error.message.replace('u\'', '\''))
|
||||||
|
|
||||||
def __init__(self, tgt, top_level_dirs=None, app_config=None):
|
def __init__(self, tgt, top_level_dirs=None, app_config=None):
|
||||||
"""Construct a mbed configuration
|
"""Construct a mbed configuration
|
||||||
|
|
@ -470,20 +484,26 @@ class Config(object):
|
||||||
if self.app_config_location is None and top_level_dirs:
|
if self.app_config_location is None and top_level_dirs:
|
||||||
self.app_config_location = self.find_app_config(top_level_dirs)
|
self.app_config_location = self.find_app_config(top_level_dirs)
|
||||||
try:
|
try:
|
||||||
self.app_config_data = json_file_to_dict(self.app_config_location) \
|
if self.app_config_location:
|
||||||
if self.app_config_location else {}
|
self.app_config_data = json_file_to_dict(
|
||||||
except ValueError as exc:
|
self.app_config_location
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
self.app_config_data = {}
|
||||||
|
except ValueError:
|
||||||
self.app_config_data = {}
|
self.app_config_data = {}
|
||||||
config_errors.append(
|
config_errors.append(
|
||||||
ConfigException("Could not parse mbed app configuration from %s"
|
ConfigException(
|
||||||
% self.app_config_location))
|
"Could not parse mbed app configuration from %s"
|
||||||
|
% self.app_config_location
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
if self.app_config_location is not None:
|
if self.app_config_location is not None:
|
||||||
# Validate the format of the JSON file based on schema_app.json
|
# Validate the format of the JSON file based on schema_app.json
|
||||||
schema_root = os.path.dirname(os.path.abspath(__file__))
|
schema_root = os.path.dirname(os.path.abspath(__file__))
|
||||||
schema_path = os.path.join(schema_root, "schema_app.json")
|
schema_path = os.path.join(schema_root, "schema_app.json")
|
||||||
schema = json_file_to_dict(schema_path)
|
schema = json_file_to_dict(schema_path)
|
||||||
|
|
||||||
url = moves.urllib.request.pathname2url(schema_path)
|
url = moves.urllib.request.pathname2url(schema_path)
|
||||||
uri = moves.urllib_parse.urljoin("file://", url)
|
uri = moves.urllib_parse.urljoin("file://", url)
|
||||||
|
|
@ -523,7 +543,7 @@ class Config(object):
|
||||||
dirname(self.target._from_file),
|
dirname(self.target._from_file),
|
||||||
getattr(self.target, attr)
|
getattr(self.target, attr)
|
||||||
)
|
)
|
||||||
setattr( self.target, attr, new_path)
|
setattr(self.target, attr, new_path)
|
||||||
|
|
||||||
self.cumulative_overrides = {key: ConfigCumulativeOverride(key)
|
self.cumulative_overrides = {key: ConfigCumulativeOverride(key)
|
||||||
for key in CUMULATIVE_ATTRIBUTES}
|
for key in CUMULATIVE_ATTRIBUTES}
|
||||||
|
|
@ -572,7 +592,9 @@ class Config(object):
|
||||||
if "requires" in self.app_config_data:
|
if "requires" in self.app_config_data:
|
||||||
if cfg["name"] not in self.app_config_data["requires"]:
|
if cfg["name"] not in self.app_config_data["requires"]:
|
||||||
continue
|
continue
|
||||||
self.app_config_data["requires"].extend(cfg.get("requires", []))
|
self.app_config_data["requires"].extend(
|
||||||
|
cfg.get("requires", [])
|
||||||
|
)
|
||||||
|
|
||||||
self.processed_configs[full_path] = True
|
self.processed_configs[full_path] = True
|
||||||
|
|
||||||
|
|
@ -582,9 +604,13 @@ class Config(object):
|
||||||
# name, exit with error
|
# name, exit with error
|
||||||
if cfg["name"] in self.lib_config_data:
|
if cfg["name"] in self.lib_config_data:
|
||||||
raise ConfigException(
|
raise ConfigException(
|
||||||
"Library name '%s' is not unique (defined in '%s' and '%s')"
|
"Library name '{}' is not unique "
|
||||||
% (cfg["name"], full_path,
|
"(defined in '{}' and '{}')".format(
|
||||||
self.lib_config_data[cfg["name"]]["__config_path"]))
|
cfg["name"],
|
||||||
|
full_path,
|
||||||
|
self.lib_config_data[cfg["name"]]["__config_path"]
|
||||||
|
)
|
||||||
|
)
|
||||||
self.lib_config_data[cfg["name"]] = cfg
|
self.lib_config_data[cfg["name"]] = cfg
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
|
@ -663,10 +689,37 @@ class Config(object):
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def _get_primary_rom_override(self):
|
||||||
|
mem_start = None
|
||||||
|
mem_size = None
|
||||||
|
if hasattr(self.target, "mbed_rom_start"):
|
||||||
|
mem_start = getattr(self.target, "mbed_rom_start")
|
||||||
|
if hasattr(self.target, "mbed_rom_size"):
|
||||||
|
mem_size = getattr(self.target, "mbed_rom_size")
|
||||||
|
if (
|
||||||
|
self.target.is_PSA_non_secure_target or
|
||||||
|
self.target.is_PSA_secure_target
|
||||||
|
):
|
||||||
|
config, _ = self.get_config_data()
|
||||||
|
if self.target.is_PSA_secure_target:
|
||||||
|
mem_start = config.get("target.secure-rom-start", mem_start).value
|
||||||
|
mem_size = config.get("target.secure-rom-size", mem_size).value
|
||||||
|
elif self.target.is_PSA_non_secure_target:
|
||||||
|
mem_start = config.get(
|
||||||
|
"target.non-secure-rom-start", mem_start
|
||||||
|
).value
|
||||||
|
mem_size = config.get("target.non-secure-rom-size", mem_size).value
|
||||||
|
if mem_start and not isinstance(mem_start, int):
|
||||||
|
mem_start = int(mem_start, 0)
|
||||||
|
if mem_size and not isinstance(mem_size, int):
|
||||||
|
mem_size = int(mem_size, 0)
|
||||||
|
return mem_start, mem_size
|
||||||
|
|
||||||
def get_all_active_memories(self, memory_list):
|
def get_all_active_memories(self, memory_list):
|
||||||
"""Get information of all available rom/ram memories in the form of dictionary
|
"""Get information of all available rom/ram memories in the form of
|
||||||
{Memory: [start_addr, size]}. Takes in the argument, a list of all available
|
dictionary {Memory: [start_addr, size]}. Takes in the argument, a
|
||||||
regions within the ram/rom memory"""
|
list of all available regions within the ram/rom memory
|
||||||
|
"""
|
||||||
# Override rom_start/rom_size
|
# Override rom_start/rom_size
|
||||||
#
|
#
|
||||||
# This is usually done for a target which:
|
# This is usually done for a target which:
|
||||||
|
|
@ -676,23 +729,43 @@ class Config(object):
|
||||||
# Counter to keep track of ROM/RAM memories supported by target
|
# Counter to keep track of ROM/RAM memories supported by target
|
||||||
active_memory_counter = 0
|
active_memory_counter = 0
|
||||||
# Find which memory we are dealing with, RAM/ROM
|
# Find which memory we are dealing with, RAM/ROM
|
||||||
active_memory = 'ROM' if any('ROM' in mem_list for mem_list in memory_list) else 'RAM'
|
if any('ROM' in mem_list for mem_list in memory_list):
|
||||||
|
active_memory = 'ROM'
|
||||||
|
else:
|
||||||
|
active_memory = 'RAM'
|
||||||
|
|
||||||
try:
|
try:
|
||||||
cmsis_part = self._get_cmsis_part()
|
cmsis_part = self._get_cmsis_part()
|
||||||
except ConfigException:
|
except ConfigException:
|
||||||
""" If the target doesn't exits in cmsis, but present in targets.json
|
""" If the target doesn't exits in cmsis, but present in targets.json
|
||||||
with ram and rom start/size defined"""
|
with ram and rom start/size defined"""
|
||||||
if getattr(self.target, "mbed_ram_start") and \
|
if (
|
||||||
getattr(self.target, "mbed_rom_start"):
|
getattr(self.target, "mbed_ram_start")
|
||||||
mem_start = int(getattr(self.target, "mbed_" + active_memory.lower() + "_start"), 0)
|
and active_memory == 'RAM'
|
||||||
mem_size = int(getattr(self.target, "mbed_" + active_memory.lower() + "_size"), 0)
|
):
|
||||||
|
mem_start = int(getattr(self.target, "mbed_ram_start"), 0)
|
||||||
|
mem_size = int(getattr(self.target, "mbed_ram_size"), 0)
|
||||||
available_memories[active_memory] = [mem_start, mem_size]
|
available_memories[active_memory] = [mem_start, mem_size]
|
||||||
return available_memories
|
return available_memories
|
||||||
|
elif active_memory == 'ROM':
|
||||||
|
start, size = self._get_primary_rom_override()
|
||||||
|
if not start:
|
||||||
|
raise ConfigException(
|
||||||
|
"Bootloader not supported on this target. rom "
|
||||||
|
"start not found in targets.json."
|
||||||
|
)
|
||||||
|
if not size:
|
||||||
|
raise ConfigException(
|
||||||
|
"Bootloader not supported on this target. rom "
|
||||||
|
"size not found in targets.json."
|
||||||
|
)
|
||||||
|
available_memories[active_memory] = [start, size]
|
||||||
|
return available_memories
|
||||||
else:
|
else:
|
||||||
raise ConfigException("Bootloader not supported on this target. "
|
raise ConfigException(
|
||||||
"ram/rom start/size not found in "
|
"Bootloader not supported on this target. ram/rom "
|
||||||
"targets.json.")
|
"start/size not found in targets.json."
|
||||||
|
)
|
||||||
|
|
||||||
present_memories = set(cmsis_part['memories'].keys())
|
present_memories = set(cmsis_part['memories'].keys())
|
||||||
valid_memories = set(memory_list).intersection(present_memories)
|
valid_memories = set(memory_list).intersection(present_memories)
|
||||||
|
|
@ -704,16 +777,20 @@ class Config(object):
|
||||||
for memory in valid_memories:
|
for memory in valid_memories:
|
||||||
mem_start = memories[memory]["start"]
|
mem_start = memories[memory]["start"]
|
||||||
mem_size = memories[memory]["size"]
|
mem_size = memories[memory]["size"]
|
||||||
if memory=='IROM1' or memory=='PROGRAM_FLASH':
|
if memory in ['IROM1', 'PROGRAM_FLASH']:
|
||||||
mem_start = getattr(self.target, "mbed_rom_start", False) or mem_start
|
start, size = self._get_primary_rom_override()
|
||||||
mem_size = getattr(self.target, "mbed_rom_size", False) or mem_size
|
if start:
|
||||||
|
mem_start = start
|
||||||
|
if size:
|
||||||
|
mem_size = size
|
||||||
memory = 'ROM'
|
memory = 'ROM'
|
||||||
elif memory == 'IRAM1' or memory == 'SRAM_OC' or \
|
elif memory in ['IRAM1', 'SRAM_OC', 'SRAM_UPPER', 'SRAM']:
|
||||||
memory == 'SRAM_UPPER' or memory == 'SRAM':
|
|
||||||
if (self.has_ram_regions):
|
if (self.has_ram_regions):
|
||||||
continue
|
continue
|
||||||
mem_start = getattr(self.target, "mbed_ram_start", False) or mem_start
|
if getattr(self.target, "mbed_ram_start", False):
|
||||||
mem_size = getattr(self.target, "mbed_ram_size", False) or mem_size
|
mem_start = getattr(self.target, "mbed_ram_start")
|
||||||
|
if getattr(self.target, "mbed_ram_start", False):
|
||||||
|
mem_size = getattr(self.target, "mbed_ram_size")
|
||||||
memory = 'RAM'
|
memory = 'RAM'
|
||||||
else:
|
else:
|
||||||
active_memory_counter += 1
|
active_memory_counter += 1
|
||||||
|
|
@ -754,23 +831,26 @@ class Config(object):
|
||||||
if not getattr(self.target, "bootloader_supported", False):
|
if not getattr(self.target, "bootloader_supported", False):
|
||||||
raise ConfigException("Bootloader not supported on this target.")
|
raise ConfigException("Bootloader not supported on this target.")
|
||||||
"""Generate a list of regions from the config"""
|
"""Generate a list of regions from the config"""
|
||||||
if ((self.target.bootloader_img or self.target.restrict_size) and
|
if (
|
||||||
(self.target.mbed_app_start or self.target.mbed_app_size)):
|
(self.target.bootloader_img or self.target.restrict_size) and
|
||||||
|
(self.target.mbed_app_start or self.target.mbed_app_size)
|
||||||
|
):
|
||||||
raise ConfigException(
|
raise ConfigException(
|
||||||
"target.bootloader_img and target.restrict_size are "
|
"target.bootloader_img and target.restrict_size are "
|
||||||
"incompatible with target.mbed_app_start and "
|
"incompatible with target.mbed_app_start and "
|
||||||
"target.mbed_app_size")
|
"target.mbed_app_size")
|
||||||
|
rom = self.get_all_active_memories(ROM_ALL_MEMORIES)
|
||||||
if self.target.bootloader_img or self.target.restrict_size:
|
if self.target.bootloader_img or self.target.restrict_size:
|
||||||
return self._generate_bootloader_build(self.get_all_active_memories(ROM_ALL_MEMORIES))
|
return self._generate_bootloader_build(rom)
|
||||||
else:
|
else:
|
||||||
return self._generate_linker_overrides(self.get_all_active_memories(ROM_ALL_MEMORIES))
|
return self._generate_linker_overrides(rom)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def header_member_size(member):
|
def header_member_size(member):
|
||||||
_, _, subtype, _ = member
|
_, _, subtype, _ = member
|
||||||
try:
|
try:
|
||||||
return int(subtype[:-2]) // 8
|
return int(subtype[:-2]) // 8
|
||||||
except:
|
except Exception:
|
||||||
if subtype.startswith("CRCITT32"):
|
if subtype.startswith("CRCITT32"):
|
||||||
return 32 // 8
|
return 32 // 8
|
||||||
elif subtype == "SHA256":
|
elif subtype == "SHA256":
|
||||||
|
|
@ -799,7 +879,10 @@ class Config(object):
|
||||||
for s, e in regions:
|
for s, e in regions:
|
||||||
if newstart > s and newstart < e:
|
if newstart > s and newstart < e:
|
||||||
raise ConfigException(
|
raise ConfigException(
|
||||||
"Can not place %r region inside previous region" % region_name)
|
"Can not place {} region inside previous region".format(
|
||||||
|
region_name
|
||||||
|
)
|
||||||
|
)
|
||||||
return newstart
|
return newstart
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
|
@ -810,7 +893,7 @@ class Config(object):
|
||||||
next section, whichever is smaller
|
next section, whichever is smaller
|
||||||
"""
|
"""
|
||||||
# Sort the list by starting address
|
# Sort the list by starting address
|
||||||
region_list = sorted(region_list, key=lambda x:x[0])
|
region_list = sorted(region_list, key=lambda x: x[0])
|
||||||
for s, e in region_list:
|
for s, e in region_list:
|
||||||
if start_address < s:
|
if start_address < s:
|
||||||
return s
|
return s
|
||||||
|
|
@ -848,17 +931,32 @@ class Config(object):
|
||||||
end_address = stop
|
end_address = stop
|
||||||
else:
|
else:
|
||||||
break
|
break
|
||||||
if end_address == None:
|
if end_address is None:
|
||||||
raise ConfigException("bootloader segments don't fit within rom")
|
raise ConfigException(
|
||||||
part_size = Config._align_ceiling(end_address, self.sectors) - rom_start
|
"bootloader segments don't fit within rom"
|
||||||
# Generate the region in the loop (bootloader0, bootloader1, ...)
|
)
|
||||||
yield Region("bootloader"+str(part_count), start, part_size, False, filename)
|
part_size = Config._align_ceiling(
|
||||||
|
end_address, self.sectors
|
||||||
|
) - rom_start
|
||||||
|
# Generate the region in the loop
|
||||||
|
# (bootloader0, bootloader1, ...)
|
||||||
|
yield Region(
|
||||||
|
"bootloader{}".format(str(part_count)),
|
||||||
|
start,
|
||||||
|
part_size,
|
||||||
|
False,
|
||||||
|
filename
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
# Number of segments is 1
|
# Number of segments is 1
|
||||||
_, end_address = part.segments()[0]
|
_, end_address = part.segments()[0]
|
||||||
if (end_address > rom_end):
|
if (end_address > rom_end):
|
||||||
raise ConfigException("bootloader segments don't fit within rom")
|
raise ConfigException(
|
||||||
part_size = Config._align_ceiling(end_address, self.sectors) - rom_start
|
"bootloader segments don't fit within rom"
|
||||||
|
)
|
||||||
|
part_size = Config._align_ceiling(
|
||||||
|
end_address, self.sectors
|
||||||
|
) - rom_start
|
||||||
yield Region("bootloader", rom_start, part_size, False,
|
yield Region("bootloader", rom_start, part_size, False,
|
||||||
filename)
|
filename)
|
||||||
|
|
||||||
|
|
@ -866,26 +964,42 @@ class Config(object):
|
||||||
if self.target.header_format:
|
if self.target.header_format:
|
||||||
if self.target.header_offset:
|
if self.target.header_offset:
|
||||||
start = self._assign_new_offset(
|
start = self._assign_new_offset(
|
||||||
rom_start, self.target.header_offset, "header", regions)
|
rom_start,
|
||||||
|
self.target.header_offset,
|
||||||
|
"header",
|
||||||
|
regions
|
||||||
|
)
|
||||||
start, region = self._make_header_region(
|
start, region = self._make_header_region(
|
||||||
start, self.target.header_format)
|
start, self.target.header_format)
|
||||||
yield region._replace(filename=self.target.header_format)
|
yield region._replace(filename=self.target.header_format)
|
||||||
|
|
||||||
if self.target.restrict_size is not None:
|
if self.target.restrict_size is not None:
|
||||||
new_size = int(self.target.restrict_size, 0)
|
new_size = int(self.target.restrict_size, 0)
|
||||||
new_size = Config._align_floor(start + new_size, self.sectors) - start
|
new_size = Config._align_floor(
|
||||||
|
start + new_size, self.sectors
|
||||||
|
) - start
|
||||||
|
|
||||||
if self.target.app_offset:
|
if self.target.app_offset:
|
||||||
start = self._assign_new_offset(rom_start, self.target.app_offset, "application", regions)
|
start = self._assign_new_offset(
|
||||||
|
rom_start,
|
||||||
|
self.target.app_offset,
|
||||||
|
"application",
|
||||||
|
regions
|
||||||
|
)
|
||||||
|
|
||||||
yield Region("application", start, new_size, True, None)
|
yield Region("application", start, new_size, True, None)
|
||||||
start += new_size
|
start += new_size
|
||||||
if self.target.header_format and not self.target.bootloader_img:
|
if self.target.header_format and not self.target.bootloader_img:
|
||||||
if self.target.header_offset:
|
if self.target.header_offset:
|
||||||
start = self._assign_new_offset(
|
start = self._assign_new_offset(
|
||||||
rom_start, self.target.header_offset, "header", regions)
|
rom_start,
|
||||||
|
self.target.header_offset,
|
||||||
|
"header",
|
||||||
|
regions
|
||||||
|
)
|
||||||
start, region = self._make_header_region(
|
start, region = self._make_header_region(
|
||||||
start, self.target.header_format)
|
start, self.target.header_format
|
||||||
|
)
|
||||||
yield region
|
yield region
|
||||||
|
|
||||||
yield Region("post_application", start, rom_end - start,
|
yield Region("post_application", start, rom_end - start,
|
||||||
|
|
@ -894,7 +1008,8 @@ class Config(object):
|
||||||
if self.target.app_offset:
|
if self.target.app_offset:
|
||||||
start = self._assign_new_offset(
|
start = self._assign_new_offset(
|
||||||
rom_start, self.target.app_offset, "application", regions)
|
rom_start, self.target.app_offset, "application", regions)
|
||||||
# compute the end address of the application region based on existing segments
|
# compute the end address of the application region based on
|
||||||
|
# existing segments
|
||||||
end = self._get_end_address(regions, start, rom_end)
|
end = self._get_end_address(regions, start, rom_end)
|
||||||
yield Region("application", start, end - start,
|
yield Region("application", start, end - start,
|
||||||
True, None)
|
True, None)
|
||||||
|
|
@ -924,13 +1039,18 @@ class Config(object):
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _align_ceiling(address, sectors):
|
def _align_ceiling(address, sectors):
|
||||||
target_start, target_size = Config._find_sector(address, sectors)
|
target_start, target_size = Config._find_sector(address, sectors)
|
||||||
sector_num = ((address - target_start) + target_size - 1) // target_size
|
sector = ((address - target_start) + target_size - 1) // target_size
|
||||||
return target_start + (sector_num * target_size)
|
return target_start + (sector * target_size)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def report(self):
|
def report(self):
|
||||||
return {'app_config': self.app_config_location,
|
return {
|
||||||
'library_configs': list(map(relpath, self.processed_configs.keys()))}
|
'app_config': self.app_config_location,
|
||||||
|
'library_configs': list(map(
|
||||||
|
relpath,
|
||||||
|
self.processed_configs.keys()
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
def _generate_linker_overrides(self, rom_memories):
|
def _generate_linker_overrides(self, rom_memories):
|
||||||
rom_start, rom_size = rom_memories.get('ROM')
|
rom_start, rom_size = rom_memories.get('ROM')
|
||||||
|
|
@ -948,7 +1068,13 @@ class Config(object):
|
||||||
raise ConfigException("Application ends after ROM")
|
raise ConfigException("Application ends after ROM")
|
||||||
yield Region("application", start, size, True, None)
|
yield Region("application", start, size, True, None)
|
||||||
|
|
||||||
def _process_config_and_overrides(self, data, params, unit_name, unit_kind):
|
def _process_config_and_overrides(
|
||||||
|
self,
|
||||||
|
data,
|
||||||
|
params,
|
||||||
|
unit_name,
|
||||||
|
unit_kind
|
||||||
|
):
|
||||||
"""Process "config_parameters" and "target_config_overrides" into a
|
"""Process "config_parameters" and "target_config_overrides" into a
|
||||||
given dictionary
|
given dictionary
|
||||||
|
|
||||||
|
|
@ -1018,9 +1144,11 @@ class Config(object):
|
||||||
if full_name in params:
|
if full_name in params:
|
||||||
params[full_name].set_value(val, unit_name, unit_kind,
|
params[full_name].set_value(val, unit_name, unit_kind,
|
||||||
label)
|
label)
|
||||||
elif (name.startswith("target.") and
|
elif (
|
||||||
|
name.startswith("target.") and
|
||||||
(unit_kind is "application" or
|
(unit_kind is "application" or
|
||||||
name in BOOTLOADER_OVERRIDES)):
|
name in BOOTLOADER_OVERRIDES)
|
||||||
|
):
|
||||||
_, attribute = name.split(".")
|
_, attribute = name.split(".")
|
||||||
setattr(self.target, attribute, val)
|
setattr(self.target, attribute, val)
|
||||||
continue
|
continue
|
||||||
|
|
@ -1039,9 +1167,10 @@ class Config(object):
|
||||||
|
|
||||||
We consider the resolution order for our target and sort it by level
|
We consider the resolution order for our target and sort it by level
|
||||||
reversed, so that we first look at the top level target (the parent),
|
reversed, so that we first look at the top level target (the parent),
|
||||||
then its direct children, then the children of those children and so on,
|
then its direct children, then the children of those children and so
|
||||||
until we reach self.target
|
on, until we reach self.target
|
||||||
TODO: this might not work so well in some multiple inheritance scenarios
|
TODO: this might not work so well in some multiple inheritance
|
||||||
|
scenarios.
|
||||||
At each step, look at two keys of the target data:
|
At each step, look at two keys of the target data:
|
||||||
- config_parameters: used to define new configuration parameters
|
- config_parameters: used to define new configuration parameters
|
||||||
- config_overrides: used to override already defined configuration
|
- config_overrides: used to override already defined configuration
|
||||||
|
|
@ -1062,12 +1191,14 @@ class Config(object):
|
||||||
tname, "target")
|
tname, "target")
|
||||||
# Then process overrides
|
# Then process overrides
|
||||||
for name, val in target_data.get("overrides", {}).items():
|
for name, val in target_data.get("overrides", {}).items():
|
||||||
full_name = ConfigParameter.get_full_name(name, tname, "target")
|
full_name = ConfigParameter.get_full_name(
|
||||||
|
name, tname, "target"
|
||||||
|
)
|
||||||
# If the parameter name is not defined or if there isn't a path
|
# If the parameter name is not defined or if there isn't a path
|
||||||
# from this target to the target where the parameter was defined
|
# from this target to the target where the parameter was
|
||||||
# in the target inheritance tree, raise an error We need to use
|
# defined in the target inheritance tree, raise an error We
|
||||||
# 'defined_by[7:]' to remove the "target:" prefix from
|
# need to use 'defined_by[7:]' to remove the "target:"
|
||||||
# defined_by
|
# prefix from defined_by
|
||||||
rel_names = [tgt for tgt, _ in
|
rel_names = [tgt for tgt, _ in
|
||||||
get_resolution_order(self.target.json_data, tname,
|
get_resolution_order(self.target.json_data, tname,
|
||||||
[])]
|
[])]
|
||||||
|
|
@ -1082,10 +1213,10 @@ class Config(object):
|
||||||
|
|
||||||
def get_lib_config_data(self, target_data):
|
def get_lib_config_data(self, target_data):
|
||||||
""" Read and interpret configuration data defined by libraries. It is
|
""" Read and interpret configuration data defined by libraries. It is
|
||||||
assumed that "add_config_files" above was already called and the library
|
assumed that "add_config_files" above was already called and the
|
||||||
configuration data exists in self.lib_config_data
|
library configuration data exists in self.lib_config_data
|
||||||
|
|
||||||
Arguments: None
|
Arguments: target_data
|
||||||
"""
|
"""
|
||||||
macros = {}
|
macros = {}
|
||||||
for lib_name, lib_data in self.lib_config_data.items():
|
for lib_name, lib_data in self.lib_config_data.items():
|
||||||
|
|
@ -1161,7 +1292,8 @@ class Config(object):
|
||||||
}
|
}
|
||||||
|
|
||||||
parameter_macros = {
|
parameter_macros = {
|
||||||
p.macro_name: p.value for p in params.values() if p.value is not None
|
p.macro_name: p.value for p in params.values()
|
||||||
|
if p.value is not None
|
||||||
}
|
}
|
||||||
|
|
||||||
all_macros.update(parameter_macros)
|
all_macros.update(parameter_macros)
|
||||||
|
|
@ -1235,23 +1367,29 @@ class Config(object):
|
||||||
err_msg = ""
|
err_msg = ""
|
||||||
|
|
||||||
for name, param in sorted(params.items()):
|
for name, param in sorted(params.items()):
|
||||||
min = param.value_min
|
min = param.value_min
|
||||||
max = param.value_max
|
max = param.value_max
|
||||||
accepted = param.accepted_values
|
accepted = param.accepted_values
|
||||||
value = param.value
|
value = param.value
|
||||||
|
|
||||||
# Config parameters that are only defined but do not have a default
|
# Config parameters that are only defined but do not have a default
|
||||||
# value should not be range limited
|
# value should not be range limited
|
||||||
if value is not None:
|
if value is not None:
|
||||||
if (min is not None or max is not None) and (accepted is not None):
|
if (
|
||||||
err_msg += "\n%s has both a range and list of accepted values specified. Please only "\
|
(min is not None or max is not None) and
|
||||||
"specify either value_min and/or value_max, or accepted_values"\
|
(accepted is not None)
|
||||||
% param
|
):
|
||||||
|
err_msg += (
|
||||||
|
"\n%s has both a range and list of accepted values "
|
||||||
|
"specified. Please only specify either value_min "
|
||||||
|
"and/or value_max, or accepted_values"
|
||||||
|
% param
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
if re.match(r'^(0[xX])[A-Fa-f0-9]+$|^[0-9]+$', str(value)):
|
if re.match(r'^(0[xX])[A-Fa-f0-9]+$|^[0-9]+$', str(value)):
|
||||||
# Value is a hexadecimal or numerical string value
|
# Value is a hexadecimal or numerical string value
|
||||||
# Convert to a python integer and range check/compare to
|
# Convert to a python integer and range check/compare
|
||||||
# accepted list accordingly
|
# to accepted list accordingly
|
||||||
|
|
||||||
if min is not None or max is not None:
|
if min is not None or max is not None:
|
||||||
# Numerical range check
|
# Numerical range check
|
||||||
|
|
@ -1261,31 +1399,54 @@ class Config(object):
|
||||||
min = int(str(min), 0) if min is not None else None
|
min = int(str(min), 0) if min is not None else None
|
||||||
max = int(str(max), 0) if max is not None else None
|
max = int(str(max), 0) if max is not None else None
|
||||||
|
|
||||||
if (min is not None and value < min) or (max is not None and value > max):
|
if (
|
||||||
err_msg += "\nInvalid config range for %s, is not in the required range: [%s:%s]"\
|
(min is not None and value < min) or
|
||||||
% (param,
|
(max is not None and value > max)
|
||||||
min if min is not None else "-inf",
|
):
|
||||||
max if max is not None else "inf")
|
err_msg += (
|
||||||
|
"\nInvalid config range for {}, is not in "
|
||||||
|
"the required range: [{}:{}]".format(
|
||||||
|
param,
|
||||||
|
min if min is not None else "-inf",
|
||||||
|
max if max is not None else "inf"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
# Numerical accepted value check
|
# Numerical accepted value check
|
||||||
elif accepted is not None and value not in accepted:
|
elif accepted is not None and value not in accepted:
|
||||||
err_msg += "\nInvalid value for %s, is not an accepted value: %s"\
|
err_msg += (
|
||||||
% (param, ", ".join(map(str, accepted)))
|
"\nInvalid value for {}, is not an accepted "
|
||||||
|
"value: {}".format(
|
||||||
|
param,
|
||||||
|
", ".join(map(str, accepted))
|
||||||
|
)
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
if min is not None or max is not None:
|
if min is not None or max is not None:
|
||||||
err_msg += "\nInvalid config range settings for %s. Range specifiers are not "\
|
err_msg += (
|
||||||
"applicable to non-decimal/hexadecimal string values" % param
|
"\nInvalid config range settings for {}. "
|
||||||
|
"Range specifiers are not applicable to "
|
||||||
|
"non-decimal/hexadecimal string values".format(
|
||||||
|
param
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
if accepted is not None and value not in accepted:
|
if accepted is not None and value not in accepted:
|
||||||
err_msg += "\nInvalid config range for %s, is not an accepted value: %s"\
|
err_msg += (
|
||||||
% (param, ", ".join(accepted))
|
"\nInvalid config range for {}, is not an "
|
||||||
|
"accepted value: {}".format(
|
||||||
|
param, ", ".join(accepted)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
if (err_msg):
|
if (err_msg):
|
||||||
raise ConfigException(err_msg)
|
raise ConfigException(err_msg)
|
||||||
|
|
||||||
for error in self.config_errors:
|
for error in self.config_errors:
|
||||||
if (isinstance(error, UndefinedParameter) and
|
if (
|
||||||
error.param in params):
|
isinstance(error, UndefinedParameter) and
|
||||||
|
error.param in params
|
||||||
|
):
|
||||||
continue
|
continue
|
||||||
else:
|
else:
|
||||||
raise error
|
raise error
|
||||||
|
|
@ -1309,11 +1470,8 @@ class Config(object):
|
||||||
param.name, param.value, conf.name, conf.value
|
param.name, param.value, conf.name, conf.value
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def name(self):
|
def name(self):
|
||||||
if "artifact_name" in self.app_config_data:
|
if "artifact_name" in self.app_config_data:
|
||||||
|
|
@ -1371,9 +1529,11 @@ class Config(object):
|
||||||
if abspath(ref.path) in all_json_paths
|
if abspath(ref.path) in all_json_paths
|
||||||
]
|
]
|
||||||
resources.filter_by_libraries(included_json_files)
|
resources.filter_by_libraries(included_json_files)
|
||||||
if (hasattr(self.target, "release_versions") and
|
if (
|
||||||
"5" not in self.target.release_versions and
|
hasattr(self.target, "release_versions") and
|
||||||
"rtos" in self.lib_config_data):
|
"5" not in self.target.release_versions and
|
||||||
|
"rtos" in self.lib_config_data
|
||||||
|
):
|
||||||
raise NotSupportedException("Target does not support mbed OS 5")
|
raise NotSupportedException("Target does not support mbed OS 5")
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
|
@ -1393,7 +1553,9 @@ class Config(object):
|
||||||
"""
|
"""
|
||||||
params, macros = config[0] or {}, config[1] or {}
|
params, macros = config[0] or {}, config[1] or {}
|
||||||
Config._check_required_parameters(params)
|
Config._check_required_parameters(params)
|
||||||
params_with_values = [p for p in params.values() if p.value is not None]
|
params_with_values = [
|
||||||
|
p for p in params.values() if p.value is not None
|
||||||
|
]
|
||||||
ctx = {
|
ctx = {
|
||||||
"cfg_params": sorted([
|
"cfg_params": sorted([
|
||||||
(p.macro_name, str(p.value), p.set_by)
|
(p.macro_name, str(p.value), p.set_by)
|
||||||
|
|
@ -1406,9 +1568,9 @@ class Config(object):
|
||||||
"name_len": max([len(m.macro_name) for m in macros.values()] +
|
"name_len": max([len(m.macro_name) for m in macros.values()] +
|
||||||
[len(m.macro_name) for m in params_with_values]
|
[len(m.macro_name) for m in params_with_values]
|
||||||
+ [0]),
|
+ [0]),
|
||||||
"val_len" : max([len(str(m.value)) for m in params_with_values] +
|
"val_len": max([len(str(m.value)) for m in params_with_values] +
|
||||||
[len(m.macro_value or "") for m in macros.values()]
|
[len(m.macro_value or "") for m in macros.values()]
|
||||||
+ [0]),
|
+ [0]),
|
||||||
}
|
}
|
||||||
jinja_loader = FileSystemLoader(dirname(abspath(__file__)))
|
jinja_loader = FileSystemLoader(dirname(abspath(__file__)))
|
||||||
jinja_environment = Environment(loader=jinja_loader,
|
jinja_environment = Environment(loader=jinja_loader,
|
||||||
|
|
|
||||||
|
|
@ -16,16 +16,15 @@ limitations under the License.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import sys
|
|
||||||
import json
|
import json
|
||||||
import pytest
|
import pytest
|
||||||
from mock import patch
|
from mock import patch
|
||||||
from hypothesis import given
|
|
||||||
from hypothesis.strategies import sampled_from
|
|
||||||
from os.path import join, isfile, dirname, abspath
|
from os.path import join, isfile, dirname, abspath
|
||||||
from tools.build_api import get_config
|
from tools.build_api import get_config
|
||||||
from tools.targets import set_targets_json_location, Target, TARGET_NAMES
|
from tools.targets import set_targets_json_location
|
||||||
from tools.config import ConfigException, Config, ConfigParameter, ConfigMacro
|
from tools.config import (
|
||||||
|
ConfigException, Config, ConfigParameter, ConfigMacro, ROM_ALL_MEMORIES
|
||||||
|
)
|
||||||
from tools.resources import Resources
|
from tools.resources import Resources
|
||||||
|
|
||||||
NOT_CONFIG = [
|
NOT_CONFIG = [
|
||||||
|
|
@ -250,3 +249,16 @@ def test_parameters_and_config_macros_to_macros():
|
||||||
|
|
||||||
macro_list = Config._parameters_and_config_macros_to_macros(params, macros)
|
macro_list = Config._parameters_and_config_macros_to_macros(params, macros)
|
||||||
assert macro_list == ["CUSTOM_MACRO_NAME=1"]
|
assert macro_list == ["CUSTOM_MACRO_NAME=1"]
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("target_start_size", [
|
||||||
|
("FUTURE_SEQUANA_PSA", 0x10080000, 0x78000),
|
||||||
|
("FUTURE_SEQUANA_M0_PSA", 0x10000000, 0x80000)
|
||||||
|
])
|
||||||
|
def test_PSA_overrides(target_start_size):
|
||||||
|
target, start, size = target_start_size
|
||||||
|
set_targets_json_location()
|
||||||
|
config = Config(target)
|
||||||
|
roms = config.get_all_active_memories(ROM_ALL_MEMORIES)
|
||||||
|
assert("ROM" in roms)
|
||||||
|
assert(roms["ROM"] == [start, size])
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue