From 02f882dcf678e445db573d71c04e8d593249f26f Mon Sep 17 00:00:00 2001 From: Teo Mahnic Date: Fri, 18 Sep 2026 13:35:43 +0200 Subject: [PATCH] functions: add support for APv2 target access space - BufferRead/BufferWrite mode bit 9 --- pyocd/debug/sequences/functions.py | 70 ++++++++++++++++++++++-------- 1 file changed, 53 insertions(+), 17 deletions(-) diff --git a/pyocd/debug/sequences/functions.py b/pyocd/debug/sequences/functions.py index e219118ff..a1744cb67 100644 --- a/pyocd/debug/sequences/functions.py +++ b/pyocd/debug/sequences/functions.py @@ -33,12 +33,14 @@ from ...core import exceptions from ...coresight.coresight_target import CoreSightTarget from ...coresight.ap import (APAddressBase, APv1Address, AccessPort, MEM_AP) +from ...coresight.dap import ADIVersion from ...probe.debug_probe import DebugProbe from .delegates import DebugSequenceFunctionsDelegate from .sequences import DebugSequenceRuntimeError if TYPE_CHECKING: from ...coresight.dap import DebugPort + from ...core.memory_interface import MemoryInterface LOG = logging.getLogger(__name__) @@ -150,26 +152,26 @@ def _decode_mode(mode: int) -> Tuple[int, bool]: return access_size_bits // 8, increment - def _read_value(self, ap: MEM_AP, addr: int, size: int) -> int: + def _read_value(self, interface: "MemoryInterface", addr: int, size: int) -> int: if size == 1: - return ap.read8(addr) + return interface.read8(addr) if size == 2: - return ap.read16(addr) + return interface.read16(addr) if size == 4: - return ap.read32(addr) + return interface.read32(addr) if size == 8: - return ap.read64(addr) + return interface.read64(addr) raise DebugSequenceRuntimeError(f"unsupported access size {size * 8}") - def _write_value(self, ap: MEM_AP, addr: int, size: int, value: int) -> None: + def _write_value(self, interface: "MemoryInterface", addr: int, size: int, value: int) -> None: if size == 1: - ap.write8(addr, value) + interface.write8(addr, value) elif size == 2: - ap.write16(addr, value) + interface.write16(addr, value) elif size == 4: - ap.write32(addr, value) + interface.write32(addr, value) elif size == 8: - ap.write64(addr, value) + interface.write64(addr, value) else: raise DebugSequenceRuntimeError(f"unsupported access size {size * 8}") @@ -687,21 +689,38 @@ def bufferread(self, id: int, offset: int, addr: int, length: int, mode: int) -> - Bit 0..8: Debug access size. One of 8, 16, 32 and 64. Specified debug access size must be \ supported by the target hardware. For example a DP register access must always be 32-Bit. - Bit 0: Additionally set this Bit to 1 to increment the target address after each debug read \ - access of the specified size. + access of the specified size. \ + - Bit 9: Target address space. \ + 0: Access target memory using the access port specified by __ap or __apid. \ + 1: Access an address in the system's APv2 (ADIv6) top-level access port space. \ + This address space only supports 32-bit accesses. The debugger must generate \ + an error if a different debug access size is specified. @return: Always 0. Function causes fatal error if not successful. """ + APV2_ADDRESS_SPACE_MASK = 1 << 9 + access_size, increment = self._decode_mode(mode) self._check_alignment(offset, access_size, "buffOffset") self._check_alignment(addr, access_size, "addr") self._check_alignment(length, access_size, "length") + # Check target address space + if mode & APV2_ADDRESS_SPACE_MASK: + dp = self._get_dp() + if dp.adi_version != ADIVersion.ADIv6: + raise DebugSequenceRuntimeError("APv2 top-level access port space requires ADIv6") + if access_size != 4: + raise DebugSequenceRuntimeError("APv2 top-level access port space only supports 32-bit accesses") + interface = dp.apacc_memory_interface + else: + interface = self._get_mem_ap() + buffer = self._buffer_manager.get(id, create=True) end = offset + length self._buffer_manager.ensure_capacity(buffer, end) - ap = self._get_mem_ap() while length > 0: - value = self._read_value(ap, addr, access_size) + value = self._read_value(interface, addr, access_size) buffer.data[offset:offset + access_size] = self._int_to_bytes(value, access_size) if increment: addr += access_size @@ -726,16 +745,34 @@ def bufferwrite(self, id: int, offset: int, addr: int, length: int, mode: int) - - Bit 0..8: Debug access size. One of 8, 16, 32 and 64. Specified debug access size must be \ supported by the target hardware. For example a DP register access must always be 32-Bit. - Bit 0: Additionally set this Bit to 1 to increment the target address after each debug write \ - access of the specified size. + access of the specified size. \ + - Bit 9: Target address space. \ + 0: Access target memory using the access port specified by __ap or __apid. \ + 1: Access an address in the system's APv2 (ADIv6) top-level access port space. \ + This address space only supports 32-bit accesses. The debugger must generate \ + an error if a different debug access size is specified. @return: Number of actually written bytes. """ - buffer = self._buffer_manager.get(id, create=False) + APV2_ADDRESS_SPACE_MASK = 1 << 9 access_size, increment = self._decode_mode(mode) self._check_alignment(offset, access_size, "buffOffset") self._check_alignment(addr, access_size, "addr") self._check_alignment(length, access_size, "length") + # Check target address space + if mode & APV2_ADDRESS_SPACE_MASK: + dp = self._get_dp() + if dp.adi_version != ADIVersion.ADIv6: + raise DebugSequenceRuntimeError("APv2 top-level access port space requires ADIv6") + if access_size != 4: + raise DebugSequenceRuntimeError("APv2 top-level access port space only supports 32-bit accesses") + interface = dp.apacc_memory_interface + else: + interface = self._get_mem_ap() + + buffer = self._buffer_manager.get(id, create=False) + available = len(buffer.data) - offset if available <= 0: return 0 @@ -745,11 +782,10 @@ def bufferwrite(self, id: int, offset: int, addr: int, length: int, mode: int) - if write_len <= 0: return 0 - ap = self._get_mem_ap() remaining = write_len while remaining > 0: value = int.from_bytes(buffer.data[offset:offset + access_size], "little") - self._write_value(ap, addr, access_size, value) + self._write_value(interface, addr, access_size, value) if increment: addr += access_size offset += access_size