This is an automated email from Gerrit. "Tomas Vanek <van...@fbl.cz>" just uploaded a new patch set to Gerrit, which you can find at https://review.openocd.org/c/openocd/+/8437
-- gerrit commit f86d113bfe6fc9555a335e4178bdf0624d14301d Author: Tomas Vanek <van...@fbl.cz> Date: Fri Feb 16 20:23:51 2024 +0100 target/adi_v5_swd: switch to DORMANT to revive stalled DP On several devices it was observed that DAPABORT bit in ABORT DP register does not help to revive DP to functional state. On the other hand, switching the DPv2 or v3 to DORMANT state reliably released the lock up and DP can continue communicating to accessible APs. Although it is not mentioned in ADI reference it looks naturally that the DP logic gets reset after unpowering or deep sleep in the DORMANT state. Alternate issuing DAPABORT and switching to DORMANT state after (re)connect timeout is over. Signed-off-by: Tomas Vanek <van...@fbl.cz> Change-Id: I9afdf971aa4b849ea48fdba40b748d0c7bd65130 diff --git a/src/target/adi_v5_swd.c b/src/target/adi_v5_swd.c index 0c3c64c3cb..a6019c4121 100644 --- a/src/target/adi_v5_swd.c +++ b/src/target/adi_v5_swd.c @@ -296,6 +296,7 @@ static int swd_connect_multidrop(struct adiv5_dap *dap) int64_t timeout = timeval_ms() + 500; bool timeout_reached = false; bool send_dapabort = false; + bool switch_to_dormant = false; for (unsigned int retry_after_timeout = 0; ; ) { /* Do not make any assumptions about SWD state in case of reconnect */ @@ -319,15 +320,20 @@ static int swd_connect_multidrop(struct adiv5_dap *dap) timeout_reached = timeval_ms() > timeout; if (timeout_reached) { retry_after_timeout++; - if (retry_after_timeout > 3) + if (retry_after_timeout > 6) break; - send_dapabort = true; + /* Alternate DAPABORT and DORMANT methods to revive stalled DP */ + send_dapabort = retry_after_timeout & 1; + switch_to_dormant = !send_dapabort; } alive_sleep((retval == ERROR_WAIT && !timeout_reached) ? 10 : 1); swd_multidrop_in_swd_state = false; + + if (switch_to_dormant) + swd_send_sequence(dap, SWD_TO_DORMANT); } if (retval != ERROR_OK) { @@ -350,13 +356,19 @@ static int swd_connect_single(struct adiv5_dap *dap) int64_t timeout = timeval_ms() + 500; bool timeout_reached = false; bool send_dapabort = false; + bool switch_to_dormant = false; uint32_t dpidr = 0xdeadbeef; bool dpidr_was_read = false; for (unsigned int retry_after_timeout = 0; ; ) { if (dpidr_read_retval != ERROR_OK) { if (dap->switch_through_dormant) { - swd_send_sequence(dap, JTAG_TO_DORMANT); + if (switch_to_dormant) { + swd_send_sequence(dap, SWD_TO_DORMANT); + switch_to_dormant = false; + } else { + swd_send_sequence(dap, JTAG_TO_DORMANT); + } swd_send_sequence(dap, DORMANT_TO_SWD); } else { swd_send_sequence(dap, JTAG_TO_SWD); @@ -456,7 +468,7 @@ static int swd_connect_single(struct adiv5_dap *dap) timeout_reached = timeval_ms() > timeout; if (timeout_reached) { retry_after_timeout++; - if (retry_after_timeout > 3) + if (retry_after_timeout > 6) break; } @@ -469,10 +481,12 @@ static int swd_connect_single(struct adiv5_dap *dap) if (retval != ERROR_WAIT) { /* Force SWD sequence and IDR read */ dpidr_read_retval = ERROR_FAIL; - } else if (timeout_reached) { - /* Issue DAPABORT to revive stalled DP */ - send_dapabort = true; + /* Alternate DAPABORT and DORMANT methods to revive stalled DP */ + send_dapabort = retry_after_timeout & 1; + switch_to_dormant = !send_dapabort; + if (switch_to_dormant) + dap->switch_through_dormant = true; /* Force SWD sequence and IDR read */ dpidr_read_retval = ERROR_FAIL; --