Skip to content

Commit 46e3e02

Browse files
authored
dap: add TransferProtocolError exception and do swd_reset when it occurs (#1784)
1 parent 4d4c35b commit 46e3e02

4 files changed

Lines changed: 36 additions & 5 deletions

File tree

pyocd/core/exceptions.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# pyOCD debugger
2-
# Copyright (c) 2018-2020 Arm Limited
2+
# Copyright (c) 2018-2020,2025 Arm Limited
33
# SPDX-License-Identifier: Apache-2.0
44
#
55
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -61,6 +61,10 @@ class TransferTimeoutError(TransferError):
6161
"""@brief An SWD or JTAG timeout occurred"""
6262
pass
6363

64+
class TransferProtocolError(TransferError):
65+
"""@brief SWD transfer protocol error occurred"""
66+
pass
67+
6468
class TransferFaultError(TransferError):
6569
"""@brief A memory fault occurred.
6670

pyocd/coresight/dap.py

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# pyOCD debugger
2-
# Copyright (c) 2015-2020 Arm Limited
2+
# Copyright (c) 2015-2020,2025 Arm Limited
33
# Copyright (c) 2021-2023 Chris Reed
44
# Copyright (c) 2022 Clay McClure
55
# Copyright (c) 2022 Toshiba Electronic Devices & Storage Corporation
@@ -1016,6 +1016,9 @@ def _handle_error(self, error: Exception, num: int) -> None:
10161016
# This may put the AP that was aborted into an unpredictable state. Should consider
10171017
# attempting to reset debug logic.
10181018
self.write_reg(DP_ABORT, ABORT_DAPABORT)
1019+
elif isinstance(error, exceptions.TransferProtocolError):
1020+
if self.probe.wire_protocol == DebugProbe.Protocol.SWD:
1021+
self._swd_reset()
10191022

10201023
def clear_sticky_err(self) -> None:
10211024
self._invalidate_cache()
@@ -1028,6 +1031,28 @@ def clear_sticky_err(self) -> None:
10281031
else:
10291032
assert False
10301033

1034+
def _swd_reset(self) -> None:
1035+
"""@brief Reset the SWD interface.
1036+
1037+
This method is used to reset the SWD interface when a protocol error occurs. It is not
1038+
intended to be used for resetting the target.
1039+
"""
1040+
self._invalidate_cache()
1041+
try:
1042+
self.lock()
1043+
swj = SWJSequenceSender(self.probe, False)
1044+
for i in range(2):
1045+
try:
1046+
swj.line_reset() # > 50 cycles SWDIO/TMS High.
1047+
swj.idle_cycles(8) # At least 2 idle cycles (SWDIO/TMS Low).
1048+
self.probe.read_dp(DP_IDR, now=True) # Read DP IDR to take connection out of reset state.
1049+
break # Success, so break out of the loop.
1050+
except exceptions.TargetError as error:
1051+
if i != 0:
1052+
raise # Raise the error if this is the second attempt.
1053+
finally:
1054+
self.unlock()
1055+
10311056
class APAccessMemoryInterface(memory_interface.MemoryInterface):
10321057
"""@brief Memory interface for performing simple APACC transactions.
10331058

pyocd/probe/cmsis_dap_probe.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# pyOCD debugger
2-
# Copyright (c) 2018-2020 Arm Limited
2+
# Copyright (c) 2018-2020,2025 Arm Limited
33
# Copyright (c) 2021-2023 Chris Reed
44
# SPDX-License-Identifier: Apache-2.0
55
#
@@ -718,6 +718,8 @@ def _convert_exception(exc: Exception) -> Exception:
718718
return exceptions.TransferFaultError(*exc.args)
719719
elif isinstance(exc, DAPAccess.TransferTimeoutError):
720720
return exceptions.TransferTimeoutError(*exc.args)
721+
elif isinstance(exc, DAPAccess.TransferProtocolError):
722+
return exceptions.TransferProtocolError(*exc.args)
721723
elif isinstance(exc, DAPAccess.TransferError):
722724
return exceptions.TransferError(*exc.args)
723725
elif isinstance(exc, (DAPAccess.DeviceError, DAPAccess.CommandError)):

pyocd/probe/pydapaccess/dap_access_cmsis_dap.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# pyOCD debugger
2-
# Copyright (c) 2006-2013,2018-2021 Arm Limited
2+
# Copyright (c) 2006-2013,2018-2021,2025 Arm Limited
33
# Copyright (c) 2020 Koji Kitayama
44
# Copyright (c) 2021-2022 Chris Reed
55
# SPDX-License-Identifier: Apache-2.0
@@ -373,7 +373,7 @@ def _check_response(self, response):
373373
else:
374374
raise DAPAccessIntf.TransferError("Unexpected ACK value (%d) returned by probe" % ack)
375375
elif (response & DAPTransferResponse.PROTOCOL_ERROR_MASK) != 0:
376-
raise DAPAccessIntf.TransferError("SWD protocol error")
376+
raise DAPAccessIntf.TransferProtocolError("SWD protocol error")
377377

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

0 commit comments

Comments
 (0)