Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions pyocd/coresight/coresight_target.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
from ..core.memory_map import (FlashRegion, MemoryType, RamRegion, DeviceRegion, MemoryMap)
from ..core.soc_target import SoCTarget
from ..core import exceptions
from ..flash.flash import Flash
from . import (dap, discovery)
from ..debug.svd.loader import SVDLoader
from ..utility.sequencer import CallSequence
Expand Down Expand Up @@ -302,6 +303,23 @@ def create_flash(self) -> None:
# Set the region in the flash instance.
obj.region = region

if not getattr(obj, 'has_required_sequences', True):
fallback_flm = region.attributes.get('_fallback_flm')
fallback_msg = " Falling back to FLM." if fallback_flm is not None else ""
LOG.warning("Flash programming debug sequences are not available for region '%s' (address %#010x);"
" check DFP debug description.%s", region.name, region.start, fallback_msg)

# Fall back to FLM if required flash programming sequences are not available.
if fallback_flm is not None:
for subregion in list(region.submap.regions):
region.submap.remove_region(subregion)
region.flash_class = Flash
region.flm = fallback_flm # Also clears region.algo.
if not flm_builder.finalise_region(region):
continue
obj = region.flash_class(self, region.algo)
obj.region = region

# Store the flash object back into the memory region.
region.flash = obj

Expand Down
8 changes: 8 additions & 0 deletions pyocd/flash/flash_dsq.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ class FlashDebugSequence(Flash):
_SEQ_PROGRAM_PAGE = "FlashProgramPage"
_SEQ_CODE_MEM_REMAP = "DebugCodeMemRemap"

## Sequences required for basic flash programming operations.
_REQUIRED_SEQUENCES = (_SEQ_ERASE_SECTOR, _SEQ_PROGRAM_PAGE)

def __init__(self, target) -> None:
super().__init__(target, flash_algo=None)
self._delegate: Optional[DebugSequenceDelegate] = target.debug_sequence_delegate
Expand All @@ -68,6 +71,11 @@ def region(self, flash_region: "FlashRegion") -> None:
def is_erase_all_supported(self) -> bool:
return self._has_sequence(self._SEQ_ERASE_CHIP)

@property
def has_required_sequences(self) -> bool:
return all(self._has_sequence(name) for name in self._REQUIRED_SEQUENCES)


def init(self, operation, address: Optional[int] = None, clock: int = 0, reset: bool = False) -> None:
# clock and reset arguments are ignored in this implementation

Expand Down
34 changes: 33 additions & 1 deletion pyocd/target/pack/cbuild_run.py
Original file line number Diff line number Diff line change
Expand Up @@ -921,6 +921,7 @@ def _add_flashinfo_regions(
flash_start: int,
flash_end: int,
flash_info: Dict[str, Any],
fallback_flm: Optional[PackFlashAlgo] = None,
) -> None:
page_size = flash_info.get('page-size')
blocks = flash_info.get('blocks')
Expand Down Expand Up @@ -967,6 +968,8 @@ def _add_flashinfo_regions(

parent_attrs = {**flash_attrs, 'start': flash_start, 'length': flash_end - flash_start,
'sector_size': max(br[2] for br in block_ranges), 'page_size': page_size, **fi_attrs}
if fallback_flm is not None:
parent_attrs['_fallback_flm'] = fallback_flm
parent_region = MEMORY_TYPE_CLASS_MAP[MemoryType.FLASH](**parent_attrs)

for sub_start, sub_end, block_size, block_arg in block_ranges:
Expand Down Expand Up @@ -1000,7 +1003,11 @@ def _add_flashinfo_regions(
}

if memory.get('defined', False):
fallback_algos = []
for flash in self.flashinfo + self.programming:
if any(flash is fallback_algo for fallback_algo in fallback_algos):
continue

if 'pname' in memory and 'pname' in flash:
if memory['pname'] != flash['pname']:
# Skip this algorithm if 'Pname' exists and does not match
Expand Down Expand Up @@ -1046,7 +1053,32 @@ def _add_flashinfo_regions(
# Create appropriate memory region object and store it
regions.append(MEMORY_TYPE_CLASS_MAP[memory_type](**flash_attrs))
else:
_add_flashinfo_regions(flash_attrs, flash_start, flash_end, flash)
fallback_flm = None
for programming in self.programming:
if 'pname' in memory and 'pname' in programming and memory['pname'] != programming['pname']:
continue

algo_size = programming.get('size')
if algo_size is None:
continue

algo_end = programming['start'] + algo_size
if (flash_start >= algo_end) or (programming['start'] >= flash_end):
continue

fallback_algos.append(programming)
try:
algorithm_path = self._check_path(Path(programming['algorithm']), required=False)
fallback_flm = PackFlashAlgo(str(algorithm_path))
except (exceptions.Error, OSError, ValueError) as err:
LOG.debug("Could not load FLM fallback '%s': %s", programming.get('algorithm'), err)
else:
if 'ram-start' in programming:
flash_attrs['_RAMstart'] = programming['ram-start']
if 'ram-size' in programming:
flash_attrs['_RAMsize'] = programming['ram-size']
break
_add_flashinfo_regions(flash_attrs, flash_start, flash_end, flash, fallback_flm)
# Stop searching for algorithms if one without pname was found
if flash_attrs['pname'] is None:
break
Expand Down
33 changes: 23 additions & 10 deletions pyocd/target/pack/cmsis_pack.py
Original file line number Diff line number Diff line change
Expand Up @@ -799,6 +799,25 @@ def _build_memory_regions(self) -> None:
algo_element = None

# Convert the region to flash if we found a matching algorithm element.
# Check for flashinfo first — debug sequences take precedence over FLM when available.
fi_match = self._find_matching_flashinfo(attrs['start'], attrs['start'] + attrs['length'])
if fi_match is not None:
fi_elem_found, fi_start, fi_end = fi_match
if not self._saw_startup:
attrs['is_boot_memory'] = True
self._saw_startup = True
# If an FLM also covers this region, load it as fallback in case the
# required debug sequences are not available.
fallback_flm = None
if algo_element is not None:
fallback_flm = self._load_flash_algo(algo_element.attrib['name'])
if fallback_flm is not None:
attrs.update(self._get_flash_ram_attributes(algo_element))
self._processed_algos.add(algo_element)
self._add_flashinfo_regions(attrs, fi_start, fi_end, fi_elem_found, fallback_flm)
continue

# No flashinfo; use FLM if available.
if (algo_element is not None) and self._set_flash_attributes(algo_element, attrs):
# Mark this algo as processed.
self._processed_algos.add(algo_element)
Expand All @@ -811,16 +830,7 @@ def _build_memory_regions(self) -> None:
attrs['is_boot_memory'] = True
self._saw_startup = True

# If no algo, check for a matching flashinfo (the two should not cover the same area).
elif algo_element is None:
fi_match = self._find_matching_flashinfo(attrs['start'], attrs['start'] + attrs['length'])
if fi_match is not None:
fi_elem_found, fi_start, fi_end = fi_match
if not self._saw_startup:
attrs['is_boot_memory'] = True
self._saw_startup = True
self._add_flashinfo_regions(attrs, fi_start, fi_end, fi_elem_found)
continue
# No flashinfo and no algo — fall through to create a non-flash region.

# Create the memory region and add to map.
region = MEMORY_TYPE_CLASS_MAP[type](**attrs)
Expand Down Expand Up @@ -969,6 +979,7 @@ def _add_flashinfo_regions(
flash_start: int,
flash_end: int,
fi_elem: Element,
fallback_flm: Optional[PackFlashAlgo] = None,
) -> None:
"""@brief Create flash region(s) from a flashinfo XML element."""
try:
Expand Down Expand Up @@ -1019,6 +1030,8 @@ def _add_flashinfo_regions(
# Parent region spans the full flash range with the maximum sector size.
parent_attrs = {**flash_attrs, 'start': flash_start, 'length': flash_end - flash_start,
'sector_size': max(br[2] for br in block_ranges), 'page_size': page_size, **fi_attrs}
if fallback_flm is not None:
parent_attrs['_fallback_flm'] = fallback_flm
parent_region = MEMORY_TYPE_CLASS_MAP[MemoryType.FLASH](**parent_attrs)

for sub_start, sub_end, block_size, block_arg in block_ranges:
Expand Down
Loading