target/adi_v5_swd: optimize sequences in swd_connect_multidrop()

swd_connect_multidrop() sent DORMANT_TO_SWD and called
swd_multidrop_select_inner(). DORMANT_TO_SWD sequence ends
with a LINE_RESET sequence.
swd_multidrop_select_inner() sent LINE_RESET sequence again.
It was useless in this case.

swd_connect_multidrop() emited JTAG_TO_DORMANT and DORMANT_TO_SWD
sequences before connecting each DAP in SWD multidrop bus.
It is sufficient to emit JTAG_TO_DORMANT and DORMANT_TO_SWD
just once and emit the shorter LINE_RESET instead for subsequent DAPs.

Introduce a global variable swd_multidrop_in_swd_state
and use it to control what sequence is emitted.

In case of reconnect after an error, always use the full switch
JTAG_TO_DORMANT and DORMANT_TO_SWD.

Change-Id: Iba21620f6a9680793208bf398960ed0eb59df3b1
Signed-off-by: Tomas Vanek <vanekt@fbl.cz>
Reviewed-on: https://review.openocd.org/c/openocd/+/7218
Tested-by: jenkins
Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
This commit is contained in:
Tomas Vanek 2023-03-15 14:12:47 +01:00
parent bfc1252239
commit 357996d996
1 changed files with 30 additions and 3 deletions

View File

@ -48,6 +48,8 @@ static bool do_sync;
static struct adiv5_dap *swd_multidrop_selected_dap;
static bool swd_multidrop_in_swd_state;
static int swd_queue_dp_write_inner(struct adiv5_dap *dap, unsigned int reg,
uint32_t data);
@ -187,7 +189,15 @@ static int swd_multidrop_select_inner(struct adiv5_dap *dap, uint32_t *dpidr_ptr
assert(dap_is_multidrop(dap));
swd_send_sequence(dap, LINE_RESET);
/* Send JTAG_TO_DORMANT and DORMANT_TO_SWD just once
* and then use shorter LINE_RESET until communication fails */
if (!swd_multidrop_in_swd_state) {
swd_send_sequence(dap, JTAG_TO_DORMANT);
swd_send_sequence(dap, DORMANT_TO_SWD);
} else {
swd_send_sequence(dap, LINE_RESET);
}
/*
* Zero dap->select and set dap->select_dpbanksel_valid
* to skip the write to DP_SELECT before DPIDR read, avoiding
@ -245,6 +255,7 @@ static int swd_multidrop_select_inner(struct adiv5_dap *dap, uint32_t *dpidr_ptr
LOG_DEBUG_IO("Selected DP_TARGETSEL 0x%08" PRIx32, dap->multidrop_targetsel);
swd_multidrop_selected_dap = dap;
swd_multidrop_in_swd_state = true;
if (dpidr_ptr)
*dpidr_ptr = dpidr;
@ -294,8 +305,9 @@ static int swd_connect_multidrop(struct adiv5_dap *dap)
int64_t timeout = timeval_ms() + 500;
do {
swd_send_sequence(dap, JTAG_TO_DORMANT);
swd_send_sequence(dap, DORMANT_TO_SWD);
/* Do not make any assumptions about SWD state in case of reconnect */
if (dap->do_reconnect)
swd_multidrop_in_swd_state = false;
/* Clear link state, including the SELECT cache. */
dap->do_reconnect = false;
@ -306,6 +318,7 @@ static int swd_connect_multidrop(struct adiv5_dap *dap)
if (retval == ERROR_OK)
break;
swd_multidrop_in_swd_state = false;
alive_sleep(1);
} while (timeval_ms() < timeout);
@ -316,6 +329,7 @@ static int swd_connect_multidrop(struct adiv5_dap *dap)
return retval;
}
swd_multidrop_in_swd_state = true;
LOG_INFO("SWD DPIDR 0x%08" PRIx32 ", DLPIDR 0x%08" PRIx32,
dpidr, dlpidr);
@ -392,6 +406,13 @@ static int swd_connect_single(struct adiv5_dap *dap)
return retval;
}
static int swd_pre_connect(struct adiv5_dap *dap)
{
swd_multidrop_in_swd_state = false;
return ERROR_OK;
}
static int swd_connect(struct adiv5_dap *dap)
{
int status;
@ -627,7 +648,12 @@ static void swd_quit(struct adiv5_dap *dap)
done = true;
if (dap_is_multidrop(dap)) {
/* Emit the switch seq to dormant state regardless the state mirrored
* in swd_multidrop_in_swd_state. Doing so ensures robust operation
* in the case the variable is out of sync.
* Sending SWD_TO_DORMANT makes no change if the DP is already dormant. */
swd->switch_seq(SWD_TO_DORMANT);
swd_multidrop_in_swd_state = false;
/* Revisit!
* Leaving DPs in dormant state was tested and offers some safety
* against DPs mismatch in case of unintentional use of non-multidrop SWD.
@ -648,6 +674,7 @@ static void swd_quit(struct adiv5_dap *dap)
}
const struct dap_ops swd_dap_ops = {
.pre_connect_init = swd_pre_connect,
.connect = swd_connect,
.send_sequence = swd_send_sequence,
.queue_dp_read = swd_queue_dp_read,