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;

-- 

Reply via email to