diff options
author | Tomas Vanek <vanekt@fbl.cz> | 2021-11-12 15:28:30 +0100 |
---|---|---|
committer | Antonio Borneo <borneo.antonio@gmail.com> | 2021-11-20 14:45:18 +0000 |
commit | 9dd39a33e6dbd9d95b5bcfde4b41c498841a27a1 (patch) | |
tree | f0820fdad34f84e7c771aaec3619c3c8b2ae6dcf /src | |
parent | d569b9bd68c9ffb4ee464eb5a40cf2839663965b (diff) | |
download | riscv-openocd-9dd39a33e6dbd9d95b5bcfde4b41c498841a27a1.zip riscv-openocd-9dd39a33e6dbd9d95b5bcfde4b41c498841a27a1.tar.gz riscv-openocd-9dd39a33e6dbd9d95b5bcfde4b41c498841a27a1.tar.bz2 |
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>
Diffstat (limited to 'src')
-rw-r--r-- | src/jtag/drivers/bitbang.c | 75 |
1 files changed, 33 insertions, 42 deletions
diff --git a/src/jtag/drivers/bitbang.c b/src/jtag/drivers/bitbang.c index d202a05..898d6d3 100644 --- a/src/jtag/drivers/bitbang.c +++ b/src/jtag/drivers/bitbang.c @@ -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); 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", cmd & SWD_CMD_APNDP ? "AP" : "DP", - cmd & SWD_CMD_RNW ? "read" : "write", (cmd & SWD_CMD_A32) >> 1, data); - switch (ack) { - 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"); + if (ack == SWD_ACK_WAIT) { swd_clear_sticky_errors(); - break; - case SWD_ACK_FAULT: - LOG_DEBUG("SWD_ACK_FAULT"); - queued_retval = ack; + continue; + } else if (ack != SWD_ACK_OK) { + queued_retval = swd_ack_to_error_code(ack); return; - default: - LOG_DEBUG("No valid acknowledge: ack=%d", ack); - queued_retval = ack; + } + + 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; } + /* Devices do not reply to DP_TARGETSEL write cmd, ignore received ack */ + bool check_ack = swd_cmd_returns_ack(cmd); + for (;;) { 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); @@ -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); 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", cmd & SWD_CMD_APNDP ? "AP" : "DP", - cmd & SWD_CMD_RNW ? "read" : "write", (cmd & SWD_CMD_A32) >> 1, buf_get_u32(trn_ack_data_parity_trn, 1 + 3 + 1, 32)); - switch (ack) { - case SWD_ACK_OK: - 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(); - 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 (check_ack) { + if (ack == SWD_ACK_WAIT) { + swd_clear_sticky_errors(); + continue; + } else if (ack != SWD_ACK_OK) { + queued_retval = swd_ack_to_error_code(ack); + return; + } } + + if (cmd & SWD_CMD_APNDP) + bitbang_swd_exchange(true, NULL, 0, ap_delay_clk); + return; } } |