drivers/bitbang: add support for SWD multidrop
Ignore ack received after DP_TARGETSEL write to prevent false error. This change also fixes a bug: Received ACK FAULT or JUNK value were incorrectly stored to queued_retval and later used as bitbang_swd_run_queue() error return. Use LOG_ERROR for parity mismatch. Change-Id: I5ff1f658f221af78d8bbec8416a7a0fc64ba2550 Signed-off-by: Tomas Vanek <vanekt@fbl.cz> Reviewed-on: https://review.openocd.org/c/openocd/+/6700 Tested-by: jenkins Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
This commit is contained in:
parent
d569b9bd68
commit
9dd39a33e6
|
@ -492,38 +492,30 @@ static void bitbang_swd_read_reg(uint8_t cmd, uint32_t *value, uint32_t ap_delay
|
||||||
uint32_t data = buf_get_u32(trn_ack_data_parity_trn, 1 + 3, 32);
|
uint32_t data = buf_get_u32(trn_ack_data_parity_trn, 1 + 3, 32);
|
||||||
int parity = buf_get_u32(trn_ack_data_parity_trn, 1 + 3 + 32, 1);
|
int parity = buf_get_u32(trn_ack_data_parity_trn, 1 + 3 + 32, 1);
|
||||||
|
|
||||||
LOG_DEBUG("%s %s %s reg %X = %08"PRIx32,
|
LOG_DEBUG("%s %s read reg %X = %08"PRIx32,
|
||||||
ack == SWD_ACK_OK ? "OK" : ack == SWD_ACK_WAIT ? "WAIT" : ack == SWD_ACK_FAULT ? "FAULT" : "JUNK",
|
ack == SWD_ACK_OK ? "OK" : ack == SWD_ACK_WAIT ? "WAIT" : ack == SWD_ACK_FAULT ? "FAULT" : "JUNK",
|
||||||
cmd & SWD_CMD_APNDP ? "AP" : "DP",
|
cmd & SWD_CMD_APNDP ? "AP" : "DP",
|
||||||
cmd & SWD_CMD_RNW ? "read" : "write",
|
|
||||||
(cmd & SWD_CMD_A32) >> 1,
|
(cmd & SWD_CMD_A32) >> 1,
|
||||||
data);
|
data);
|
||||||
|
|
||||||
switch (ack) {
|
if (ack == SWD_ACK_WAIT) {
|
||||||
case SWD_ACK_OK:
|
|
||||||
if (parity != parity_u32(data)) {
|
|
||||||
LOG_DEBUG("Wrong parity detected");
|
|
||||||
queued_retval = ERROR_FAIL;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (value)
|
|
||||||
*value = data;
|
|
||||||
if (cmd & SWD_CMD_APNDP)
|
|
||||||
bitbang_swd_exchange(true, NULL, 0, ap_delay_clk);
|
|
||||||
return;
|
|
||||||
case SWD_ACK_WAIT:
|
|
||||||
LOG_DEBUG("SWD_ACK_WAIT");
|
|
||||||
swd_clear_sticky_errors();
|
swd_clear_sticky_errors();
|
||||||
break;
|
continue;
|
||||||
case SWD_ACK_FAULT:
|
} else if (ack != SWD_ACK_OK) {
|
||||||
LOG_DEBUG("SWD_ACK_FAULT");
|
queued_retval = swd_ack_to_error_code(ack);
|
||||||
queued_retval = ack;
|
|
||||||
return;
|
|
||||||
default:
|
|
||||||
LOG_DEBUG("No valid acknowledge: ack=%d", ack);
|
|
||||||
queued_retval = ack;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (parity != parity_u32(data)) {
|
||||||
|
LOG_ERROR("Wrong parity detected");
|
||||||
|
queued_retval = ERROR_FAIL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (value)
|
||||||
|
*value = data;
|
||||||
|
if (cmd & SWD_CMD_APNDP)
|
||||||
|
bitbang_swd_exchange(true, NULL, 0, ap_delay_clk);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -537,6 +529,9 @@ static void bitbang_swd_write_reg(uint8_t cmd, uint32_t value, uint32_t ap_delay
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Devices do not reply to DP_TARGETSEL write cmd, ignore received ack */
|
||||||
|
bool check_ack = swd_cmd_returns_ack(cmd);
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
uint8_t trn_ack_data_parity_trn[DIV_ROUND_UP(4 + 3 + 32 + 1 + 4, 8)];
|
uint8_t trn_ack_data_parity_trn[DIV_ROUND_UP(4 + 3 + 32 + 1 + 4, 8)];
|
||||||
buf_set_u32(trn_ack_data_parity_trn, 1 + 3 + 1, 32, value);
|
buf_set_u32(trn_ack_data_parity_trn, 1 + 3 + 1, 32, value);
|
||||||
|
@ -551,31 +546,27 @@ static void bitbang_swd_write_reg(uint8_t cmd, uint32_t value, uint32_t ap_delay
|
||||||
bitbang_swd_exchange(false, trn_ack_data_parity_trn, 1 + 3 + 1, 32 + 1);
|
bitbang_swd_exchange(false, trn_ack_data_parity_trn, 1 + 3 + 1, 32 + 1);
|
||||||
|
|
||||||
int ack = buf_get_u32(trn_ack_data_parity_trn, 1, 3);
|
int ack = buf_get_u32(trn_ack_data_parity_trn, 1, 3);
|
||||||
LOG_DEBUG("%s %s %s reg %X = %08"PRIx32,
|
|
||||||
|
LOG_DEBUG("%s%s %s write reg %X = %08"PRIx32,
|
||||||
|
check_ack ? "" : "ack ignored ",
|
||||||
ack == SWD_ACK_OK ? "OK" : ack == SWD_ACK_WAIT ? "WAIT" : ack == SWD_ACK_FAULT ? "FAULT" : "JUNK",
|
ack == SWD_ACK_OK ? "OK" : ack == SWD_ACK_WAIT ? "WAIT" : ack == SWD_ACK_FAULT ? "FAULT" : "JUNK",
|
||||||
cmd & SWD_CMD_APNDP ? "AP" : "DP",
|
cmd & SWD_CMD_APNDP ? "AP" : "DP",
|
||||||
cmd & SWD_CMD_RNW ? "read" : "write",
|
|
||||||
(cmd & SWD_CMD_A32) >> 1,
|
(cmd & SWD_CMD_A32) >> 1,
|
||||||
buf_get_u32(trn_ack_data_parity_trn, 1 + 3 + 1, 32));
|
buf_get_u32(trn_ack_data_parity_trn, 1 + 3 + 1, 32));
|
||||||
|
|
||||||
switch (ack) {
|
if (check_ack) {
|
||||||
case SWD_ACK_OK:
|
if (ack == SWD_ACK_WAIT) {
|
||||||
if (cmd & SWD_CMD_APNDP)
|
swd_clear_sticky_errors();
|
||||||
bitbang_swd_exchange(true, NULL, 0, ap_delay_clk);
|
continue;
|
||||||
return;
|
} else if (ack != SWD_ACK_OK) {
|
||||||
case SWD_ACK_WAIT:
|
queued_retval = swd_ack_to_error_code(ack);
|
||||||
LOG_DEBUG("SWD_ACK_WAIT");
|
return;
|
||||||
swd_clear_sticky_errors();
|
}
|
||||||
break;
|
|
||||||
case SWD_ACK_FAULT:
|
|
||||||
LOG_DEBUG("SWD_ACK_FAULT");
|
|
||||||
queued_retval = ack;
|
|
||||||
return;
|
|
||||||
default:
|
|
||||||
LOG_DEBUG("No valid acknowledge: ack=%d", ack);
|
|
||||||
queued_retval = ack;
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cmd & SWD_CMD_APNDP)
|
||||||
|
bitbang_swd_exchange(true, NULL, 0, ap_delay_clk);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue