From 9363705820d9552bd24a4e876041a90a881ede55 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sun, 10 Jun 2018 14:39:26 +0200 Subject: [PATCH] arm_adi_v5: put SWJ-DP back to JTAG mode at exit When SWD mode is used, current OpenOCD code left the SWJ-DP in SWD mode at exit. Also, current code is unable to switch back the SWJ-DP in JTAG at next run, thus a power cycle of both target and interface is required in order to run OpenOCD in JTAG mode again. Put the SWJ-DP back to JTAG mode before exit from OpenOCD. Use switch_seq(SWD_TO_JTAG) instead of dap_to_jtag(), because the latter is not implemented on some interfaces. This is aligned with the use of switch_seq(JTAG_TO_SWD) in swd_connect(). Change-Id: I55d3faebe60d6402037ec39dd9700dc5f17c53b0 Signed-off-by: Antonio Borneo Reviewed-on: http://openocd.zylin.com/4493 Tested-by: jenkins Reviewed-by: Bohdan Tymkiv Reviewed-by: Matthias Welwarsky --- src/target/adi_v5_swd.c | 11 +++++++++++ src/target/arm_adi_v5.h | 3 +++ src/target/arm_dap.c | 5 +++++ 3 files changed, 19 insertions(+) diff --git a/src/target/adi_v5_swd.c b/src/target/adi_v5_swd.c index 0de272dd9..b520223b0 100644 --- a/src/target/adi_v5_swd.c +++ b/src/target/adi_v5_swd.c @@ -276,6 +276,16 @@ static int swd_run(struct adiv5_dap *dap) return swd_run_inner(dap); } +/** Put the SWJ-DP back to JTAG mode */ +static void swd_quit(struct adiv5_dap *dap) +{ + const struct swd_driver *swd = adiv5_dap_swd_driver(dap); + + swd->switch_seq(SWD_TO_JTAG); + /* flush the queue before exit */ + swd->run(); +} + const struct dap_ops swd_dap_ops = { .connect = swd_connect, .queue_dp_read = swd_queue_dp_read, @@ -284,6 +294,7 @@ const struct dap_ops swd_dap_ops = { .queue_ap_write = swd_queue_ap_write, .queue_ap_abort = swd_queue_ap_abort, .run = swd_run, + .quit = swd_quit, }; /* diff --git a/src/target/arm_adi_v5.h b/src/target/arm_adi_v5.h index 22c316630..883ac8b5d 100644 --- a/src/target/arm_adi_v5.h +++ b/src/target/arm_adi_v5.h @@ -286,6 +286,9 @@ struct dap_ops { /** Executes all queued DAP operations but doesn't check * sticky error conditions */ int (*sync)(struct adiv5_dap *dap); + + /** Optional; called at OpenOCD exit */ + void (*quit)(struct adiv5_dap *dap); }; /* diff --git a/src/target/arm_dap.c b/src/target/arm_dap.c index 8c081800f..3be4d7199 100644 --- a/src/target/arm_dap.c +++ b/src/target/arm_dap.c @@ -132,8 +132,13 @@ static int dap_init_all(void) int dap_cleanup_all(void) { struct arm_dap_object *obj, *tmp; + struct adiv5_dap *dap; list_for_each_entry_safe(obj, tmp, &all_dap, lh) { + dap = &obj->dap; + if (dap->ops && dap->ops->quit) + dap->ops->quit(dap); + free(obj->name); free(obj); }