aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTomas Vanek <vanekt@fbl.cz>2022-10-14 09:19:29 +0200
committerAntonio Borneo <borneo.antonio@gmail.com>2023-01-28 15:53:21 +0000
commit148bc7e2151740527b4ca67d0a7c7c9f01725981 (patch)
tree5a5ddbdc0ea61b2e14f9bb35436673673969c078 /src
parent20285b91008106c9fa966cea3269c6f6a81e539a (diff)
downloadriscv-openocd-148bc7e2151740527b4ca67d0a7c7c9f01725981.zip
riscv-openocd-148bc7e2151740527b4ca67d0a7c7c9f01725981.tar.gz
riscv-openocd-148bc7e2151740527b4ca67d0a7c7c9f01725981.tar.bz2
jtag/drivers/bitbang: avoid mostly harmless glitch on SWDIO
bitbang_swd_exchange(rnw=true,...) calls bitbang_interface->swd_write() with swdio clamped to 0. bitbang_swd_write_reg() reads 1 turnaround bit, 3 ack bits and 1 turnaround by one call to bitbang_swd_exchange() and then switches SWDIO to output. AFAIK all bitbang interfaces switch SWDIO GPIO direction immediately in bitbang_interface->swdio_drive(). The GPIO now drives SWDIO line to the value stored in the output register which is always zero from previous bitbang_swd_exchange(rnw=true,...). In case the following data bit (bit 0) is 1 we can observe a glitch on SWDIO: _____ out 1 ____ HiZ/pull-up ----\ / \ / \______ out 0 ______/ swdio_drive(true) swd_write(0,1) The glitch fortunately takes place far enough from SWCLK rising edge where SWDIO is sampled by the target, so I believe it is harmless except some corner cases where the reflected wave is delayed on long line. Anyway keeping electrical signals glitch free is a good practice. To keep performance penalty minimal, pre-write the first data bit to SWDIO GPIO output buffer while clocking the turnaround bit. Following swdio_drive(true) outputs the pre-written value and the same value is rewritten by the next swd_write() instead of glitching SWDIO. Change-Id: I72ea9c0b2fae57e8ff5aa616859182c67abc924f Signed-off-by: Tomas Vanek <vanekt@fbl.cz> Reviewed-on: https://review.openocd.org/c/openocd/+/7260 Tested-by: jenkins Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
Diffstat (limited to 'src')
-rw-r--r--src/jtag/drivers/bitbang.c14
1 files changed, 13 insertions, 1 deletions
diff --git a/src/jtag/drivers/bitbang.c b/src/jtag/drivers/bitbang.c
index 2ab0a2a..665dbf3 100644
--- a/src/jtag/drivers/bitbang.c
+++ b/src/jtag/drivers/bitbang.c
@@ -525,7 +525,19 @@ static void bitbang_swd_write_reg(uint8_t cmd, uint32_t value, uint32_t ap_delay
bitbang_swd_exchange(false, &cmd, 0, 8);
bitbang_interface->swdio_drive(false);
- bitbang_swd_exchange(true, trn_ack_data_parity_trn, 0, 1 + 3 + 1);
+ bitbang_swd_exchange(true, trn_ack_data_parity_trn, 0, 1 + 3);
+
+ /* Avoid a glitch on SWDIO when changing the direction to output.
+ * To keep performance penalty minimal, pre-write the first data
+ * bit to SWDIO GPIO output buffer while clocking the turnaround bit.
+ * Following swdio_drive(true) outputs the pre-written value
+ * and the same value is rewritten by the next swd_write()
+ * instead of glitching SWDIO
+ * HiZ/pull-up --------------> 0 -------------> 1
+ * swdio_drive(true) swd_write(0,1)
+ * in case of data bit 0 = 1
+ */
+ bitbang_swd_exchange(false, trn_ack_data_parity_trn, 1 + 3 + 1, 1);
bitbang_interface->swdio_drive(true);
bitbang_swd_exchange(false, trn_ack_data_parity_trn, 1 + 3 + 1, 32 + 1);