From a1ae91311c11a8595f005aac3e6806f7757c77cc Mon Sep 17 00:00:00 2001 From: ALTracer <11005378+ALTracer@users.noreply.github.com> Date: Sun, 9 Feb 2025 20:42:25 +0300 Subject: [PATCH 1/4] adiv5_jtag: Restore lost JTAG-DP state across resets * In some targets like AT32F403A, a nRST falling edge behaves like TRST. IR is loaded with IDCODE. Next transaction expects DPACC but gets a 8974008e:7. * Mangle internal JTAG IR cache to BYPASS state so that daisy-chaining works. For the active/attached target, BMD logic should run through Capture-IR. * Nothing is needed in SWD transport, so avoid calling a null pointer. --- src/target/adiv5_internal.h | 1 + src/target/adiv5_jtag.c | 12 ++++++++++++ src/target/cortexm.c | 8 ++++++++ 3 files changed, 21 insertions(+) diff --git a/src/target/adiv5_internal.h b/src/target/adiv5_internal.h index f5bc882757c..525b6c43c58 100644 --- a/src/target/adiv5_internal.h +++ b/src/target/adiv5_internal.h @@ -203,6 +203,7 @@ struct adiv5_debug_port { uint32_t (*error)(adiv5_debug_port_s *dp, bool protocol_recovery); uint32_t (*low_access)(adiv5_debug_port_s *dp, uint8_t RnW, uint16_t addr, uint32_t value); void (*abort)(adiv5_debug_port_s *dp, uint32_t abort); + void (*ensure_idle)(adiv5_debug_port_s *dp); #if CONFIG_BMDA == 1 void (*ap_regs_read)(adiv5_access_port_s *ap, void *data); diff --git a/src/target/adiv5_jtag.c b/src/target/adiv5_jtag.c index 6667a658866..6bb3ae256b9 100644 --- a/src/target/adiv5_jtag.c +++ b/src/target/adiv5_jtag.c @@ -41,6 +41,17 @@ #define IR_DPACC 0xaU #define IR_APACC 0xbU +static void adiv5_jtag_ensure_idle(adiv5_debug_port_s *dp) +{ + /* + * On devices where nRST pulls TRST, the JTAG-DP's IR is reset + * from DPACC/APACC to IDCODE. We want BYPASS in case of daisy-chaining. + */ + jtag_devs[dp->dev_index].current_ir = 0xffU; + /* Go from TLR to RTI. */ + jtagtap_return_idle(1); +} + void adiv5_jtag_dp_handler(const uint8_t dev_index) { adiv5_debug_port_s *dp = calloc(1, sizeof(*dp)); @@ -55,6 +66,7 @@ void adiv5_jtag_dp_handler(const uint8_t dev_index) dp->low_access = adiv5_jtag_raw_access; dp->error = adiv5_jtag_clear_error; dp->abort = adiv5_jtag_abort; + dp->ensure_idle = adiv5_jtag_ensure_idle; #if CONFIG_BMDA == 1 bmda_jtag_dp_init(dp); #endif diff --git a/src/target/cortexm.c b/src/target/cortexm.c index c2a20e2ca8b..2744463f985 100644 --- a/src/target/cortexm.c +++ b/src/target/cortexm.c @@ -784,6 +784,11 @@ static void cortexm_reset(target_s *const target) platform_delay(10); } + adiv5_access_port_s *ap = cortex_ap(target); + adiv5_debug_port_s *dp = ap->dp; + if (dp->ensure_idle) + dp->ensure_idle(dp); + /* Check if the reset succeeded */ const uint32_t status = target_mem32_read32(target, CORTEXM_DHCSR); if (!(status & CORTEXM_DHCSR_S_RESET_ST)) { @@ -792,6 +797,9 @@ static void cortexm_reset(target_s *const target) * Trigger reset by AIRCR. */ target_mem32_write32(target, CORTEXM_AIRCR, CORTEXM_AIRCR_VECTKEY | CORTEXM_AIRCR_SYSRESETREQ); + platform_delay(10); + if (dp->ensure_idle) + dp->ensure_idle(dp); } /* If target needs to do something extra (see Atmel SAM4L for example) */ From 40623272ea016e446bce4a3cd1710de0386305f0 Mon Sep 17 00:00:00 2001 From: ALTracer <11005378+ALTracer@users.noreply.github.com> Date: Sun, 9 Feb 2025 23:23:23 +0300 Subject: [PATCH 2/4] adiv5_jtag: Make _ensure_idle method public --- src/target/adiv5.h | 1 + src/target/adiv5_jtag.c | 22 +++++++++++----------- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/target/adiv5.h b/src/target/adiv5.h index 198ddc6cb12..374786d056a 100644 --- a/src/target/adiv5.h +++ b/src/target/adiv5.h @@ -294,5 +294,6 @@ uint32_t adiv5_jtag_read(adiv5_debug_port_s *dp, uint16_t addr); uint32_t adiv5_jtag_raw_access(adiv5_debug_port_s *dp, uint8_t rnw, uint16_t addr, uint32_t value); uint32_t adiv5_jtag_clear_error(adiv5_debug_port_s *dp, bool protocol_recovery); void adiv5_jtag_abort(adiv5_debug_port_s *dp, uint32_t abort); +void adiv5_jtag_ensure_idle(adiv5_debug_port_s *dp); #endif /* TARGET_ADIV5_H */ diff --git a/src/target/adiv5_jtag.c b/src/target/adiv5_jtag.c index 6bb3ae256b9..d91671569af 100644 --- a/src/target/adiv5_jtag.c +++ b/src/target/adiv5_jtag.c @@ -41,17 +41,6 @@ #define IR_DPACC 0xaU #define IR_APACC 0xbU -static void adiv5_jtag_ensure_idle(adiv5_debug_port_s *dp) -{ - /* - * On devices where nRST pulls TRST, the JTAG-DP's IR is reset - * from DPACC/APACC to IDCODE. We want BYPASS in case of daisy-chaining. - */ - jtag_devs[dp->dev_index].current_ir = 0xffU; - /* Go from TLR to RTI. */ - jtagtap_return_idle(1); -} - void adiv5_jtag_dp_handler(const uint8_t dev_index) { adiv5_debug_port_s *dp = calloc(1, sizeof(*dp)); @@ -187,3 +176,14 @@ void adiv5_jtag_abort(adiv5_debug_port_s *dp, uint32_t abort) jtag_dev_write_ir(dp->dev_index, IR_ABORT); jtag_dev_shift_dr(dp->dev_index, NULL, (const uint8_t *)&request, 35); } + +void adiv5_jtag_ensure_idle(adiv5_debug_port_s *dp) +{ + /* + * On devices where nRST pulls TRST, the JTAG-DP's IR is reset + * from DPACC/APACC to IDCODE. We want BYPASS in case of daisy-chaining. + */ + jtag_devs[dp->dev_index].current_ir = 0xffU; + /* Go from TLR to RTI. */ + jtagtap_return_idle(1); +} From 4b82ba59007b42109c6e85ea1cbe94cf6c90ab16 Mon Sep 17 00:00:00 2001 From: ALTracer <11005378+ALTracer@users.noreply.github.com> Date: Sun, 9 Feb 2025 23:23:56 +0300 Subject: [PATCH 3/4] remote: Add JTAG ensure idle command (!JI#) --- src/remote.c | 6 ++++++ src/remote.h | 2 ++ 2 files changed, 8 insertions(+) diff --git a/src/remote.c b/src/remote.c index 5fdf5094c25..1807f49bf93 100644 --- a/src/remote.c +++ b/src/remote.c @@ -192,6 +192,7 @@ static void remote_packet_process_jtag(const char *const packet, const size_t pa remote_dp.error = adiv5_jtag_clear_error; remote_dp.low_access = adiv5_jtag_raw_access; remote_dp.abort = adiv5_jtag_abort; + remote_dp.ensure_idle = adiv5_jtag_ensure_idle; jtagtap_init(); remote_respond(REMOTE_RESP_OK, 0); break; @@ -249,6 +250,11 @@ static void remote_packet_process_jtag(const char *const packet, const size_t pa break; } + case REMOTE_JTAG_ENSURE_IDLE: /* JI = re-cycle IR after indirect resets */ + remote_dp.ensure_idle(&remote_dp); + remote_respond(REMOTE_RESP_OK, 0); + break; + default: remote_respond(REMOTE_RESP_ERR, REMOTE_ERROR_UNRECOGNISED); break; diff --git a/src/remote.h b/src/remote.h index a87db8f1397..89c453cde1c 100644 --- a/src/remote.h +++ b/src/remote.h @@ -253,6 +253,8 @@ #define REMOTE_ACCEL_RISCV (1U << 2U) #define REMOTE_ACCEL_ADIV6 (1U << 3U) +#define REMOTE_JTAG_ENSURE_IDLE 'I' + /* ADIv5 accleration protocol elements */ #define REMOTE_ADIV5_PACKET 'A' #define REMOTE_DP_READ 'd' From 8e1bf49fd5598a099ff9a3c5c92fb14775528d8f Mon Sep 17 00:00:00 2001 From: ALTracer <11005378+ALTracer@users.noreply.github.com> Date: Sun, 9 Feb 2025 23:24:32 +0300 Subject: [PATCH 4/4] hosted/remote/protocol_v4: Add JTAG ensure idle command (!JI#) --- src/platforms/hosted/remote/protocol_v4.c | 16 ++++++++++++++++ src/platforms/hosted/remote/protocol_v4.h | 1 + src/platforms/hosted/remote/protocol_v4_defs.h | 7 +++++++ 3 files changed, 24 insertions(+) diff --git a/src/platforms/hosted/remote/protocol_v4.c b/src/platforms/hosted/remote/protocol_v4.c index 2e756c551e1..403c8b3a299 100644 --- a/src/platforms/hosted/remote/protocol_v4.c +++ b/src/platforms/hosted/remote/protocol_v4.c @@ -103,6 +103,7 @@ bool remote_v4_adiv5_init(adiv5_debug_port_s *const dp) dp->ap_write = remote_v4_adiv5_ap_write; dp->mem_read = remote_v4_adiv5_mem_read_bytes; dp->mem_write = remote_v4_adiv5_mem_write_bytes; + dp->ensure_idle = remote_v4_jtag_ensure_idle; return true; } @@ -133,3 +134,18 @@ bool remote_v4_riscv_jtag_init(riscv_dmi_s *const dmi) dmi->write = remote_v4_riscv_jtag_dmi_write; return true; } + +void remote_v4_jtag_ensure_idle(adiv5_debug_port_s *dp) +{ + /* Ask remote_dp !JI# to set IR cache to BYPASS (because a reset happened) */ + platform_buffer_write(REMOTE_JTAG_ENSURE_IDLE_STR, sizeof(REMOTE_JTAG_ENSURE_IDLE_STR)); + char buffer[REMOTE_MAX_MSG_SIZE]; + /* Read back the answer and check for errors */ + const int length = platform_buffer_read(buffer, REMOTE_MAX_MSG_SIZE); + if (length < 1 || buffer[0U] != REMOTE_RESP_OK) { + DEBUG_ERROR("%s failed, error %s\n", __func__, length ? buffer + 1 : "with communication"); + return; + } + jtag_devs[dp->dev_index].current_ir = 0xffU; + jtagtap_return_idle(1); +} diff --git a/src/platforms/hosted/remote/protocol_v4.h b/src/platforms/hosted/remote/protocol_v4.h index c8f6d5b609f..47d649c770a 100644 --- a/src/platforms/hosted/remote/protocol_v4.h +++ b/src/platforms/hosted/remote/protocol_v4.h @@ -43,5 +43,6 @@ bool remote_v4_init(void); bool remote_v4_adiv5_init(adiv5_debug_port_s *dp); bool remote_v4_adiv6_init(adiv5_debug_port_s *dp); bool remote_v4_riscv_jtag_init(riscv_dmi_s *dmi); +void remote_v4_jtag_ensure_idle(adiv5_debug_port_s *dp); #endif /*PLATFORMS_HOSTED_REMOTE_PROTOCOL_V4_H*/ diff --git a/src/platforms/hosted/remote/protocol_v4_defs.h b/src/platforms/hosted/remote/protocol_v4_defs.h index 49726eebc1b..7b2e2c63bd1 100644 --- a/src/platforms/hosted/remote/protocol_v4_defs.h +++ b/src/platforms/hosted/remote/protocol_v4_defs.h @@ -101,6 +101,13 @@ REMOTE_SOM, REMOTE_ADIV5_PACKET, REMOTE_DP_TARGETSEL, REMOTE_ADIV5_DATA, REMOTE_EOM, 0 \ } +#define REMOTE_JTAG_ENSURE_IDLE 'I' +#define REMOTE_JTAG_ENSURE_IDLE_STR \ + (char[]) \ + { \ + REMOTE_SOM, REMOTE_JTAG_PACKET, REMOTE_JTAG_ENSURE_IDLE, REMOTE_EOM, 0 \ + } + /* ADIv6 acceleration protocol elements */ #define REMOTE_ADIV6_PACKET '6'