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
6 changes: 5 additions & 1 deletion pyocd/core/exceptions.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# pyOCD debugger
# Copyright (c) 2018-2020 Arm Limited
# Copyright (c) 2018-2020,2025 Arm Limited
# SPDX-License-Identifier: Apache-2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
Expand Down Expand Up @@ -61,6 +61,10 @@ class TransferTimeoutError(TransferError):
"""@brief An SWD or JTAG timeout occurred"""
pass

class TransferProtocolError(TransferError):
"""@brief SWD transfer protocol error occurred"""
pass

class TransferFaultError(TransferError):
"""@brief A memory fault occurred.

Expand Down
27 changes: 26 additions & 1 deletion pyocd/coresight/dap.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# pyOCD debugger
# Copyright (c) 2015-2020 Arm Limited
# Copyright (c) 2015-2020,2025 Arm Limited
# Copyright (c) 2021-2023 Chris Reed
# Copyright (c) 2022 Clay McClure
# Copyright (c) 2022 Toshiba Electronic Devices & Storage Corporation
Expand Down Expand Up @@ -1016,6 +1016,9 @@ def _handle_error(self, error: Exception, num: int) -> None:
# This may put the AP that was aborted into an unpredictable state. Should consider
# attempting to reset debug logic.
self.write_reg(DP_ABORT, ABORT_DAPABORT)
elif isinstance(error, exceptions.TransferProtocolError):
if self.probe.wire_protocol == DebugProbe.Protocol.SWD:
self._swd_reset()

def clear_sticky_err(self) -> None:
self._invalidate_cache()
Expand All @@ -1028,6 +1031,28 @@ def clear_sticky_err(self) -> None:
else:
assert False

def _swd_reset(self) -> None:
"""@brief Reset the SWD interface.

This method is used to reset the SWD interface when a protocol error occurs. It is not
intended to be used for resetting the target.
"""
self._invalidate_cache()
try:
self.lock()
swj = SWJSequenceSender(self.probe, False)
for i in range(2):
try:
swj.line_reset() # > 50 cycles SWDIO/TMS High.
swj.idle_cycles(8) # At least 2 idle cycles (SWDIO/TMS Low).
self.probe.read_dp(DP_IDR, now=True) # Read DP IDR to take connection out of reset state.
break # Success, so break out of the loop.
except exceptions.TargetError as error:
if i != 0:
raise # Raise the error if this is the second attempt.
finally:
self.unlock()

class APAccessMemoryInterface(memory_interface.MemoryInterface):
"""@brief Memory interface for performing simple APACC transactions.

Expand Down
4 changes: 3 additions & 1 deletion pyocd/probe/cmsis_dap_probe.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# pyOCD debugger
# Copyright (c) 2018-2020 Arm Limited
# Copyright (c) 2018-2020,2025 Arm Limited
# Copyright (c) 2021-2023 Chris Reed
# SPDX-License-Identifier: Apache-2.0
#
Expand Down Expand Up @@ -718,6 +718,8 @@ def _convert_exception(exc: Exception) -> Exception:
return exceptions.TransferFaultError(*exc.args)
elif isinstance(exc, DAPAccess.TransferTimeoutError):
return exceptions.TransferTimeoutError(*exc.args)
elif isinstance(exc, DAPAccess.TransferProtocolError):
return exceptions.TransferProtocolError(*exc.args)
elif isinstance(exc, DAPAccess.TransferError):
return exceptions.TransferError(*exc.args)
elif isinstance(exc, (DAPAccess.DeviceError, DAPAccess.CommandError)):
Expand Down
4 changes: 2 additions & 2 deletions pyocd/probe/pydapaccess/dap_access_cmsis_dap.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# pyOCD debugger
# Copyright (c) 2006-2013,2018-2021 Arm Limited
# Copyright (c) 2006-2013,2018-2021,2025 Arm Limited
# Copyright (c) 2020 Koji Kitayama
# Copyright (c) 2021-2022 Chris Reed
# SPDX-License-Identifier: Apache-2.0
Expand Down Expand Up @@ -373,7 +373,7 @@ def _check_response(self, response):
else:
raise DAPAccessIntf.TransferError("Unexpected ACK value (%d) returned by probe" % ack)
elif (response & DAPTransferResponse.PROTOCOL_ERROR_MASK) != 0:
raise DAPAccessIntf.TransferError("SWD protocol error")
raise DAPAccessIntf.TransferProtocolError("SWD protocol error")

def _decode_transfer_data(self, data):
"""@brief Take a byte array and extract the data from it
Expand Down
Loading