From be2d25efcc0132e02c76c304487a8759ca587b0c Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Wed, 23 Jan 2019 16:46:31 +0100 Subject: [PATCH] arm_adi_v5: add API send_sequence() and use it The method to send an arbitrary sequence to DAP depends on the transport and is thus different on JTAG and SWD. This is already coded in dap_to_jtag() and dap_to_swd(). Add a new API send_sequence() in struct dap_ops. Add the implementations of send_sequence() in adi_v5_jtag.c and adi_v5_swd.c Rewrite dap_to_jtag() and dap_to_swd() using the new API. Move the enum swd_special_seq in arm_adi_v5.h to solve a circular dependencies among swd.h and arm_adi_v5.h Change-Id: I9db13a00f129761eab283783c094cfff2dd92610 Signed-off-by: Antonio Borneo Reviewed-on: http://openocd.zylin.com/4902 Tested-by: jenkins Reviewed-by: Tomas Vanek --- src/jtag/swd.h | 8 -------- src/target/adi_v5_jtag.c | 24 ++++++++++++++++++++++++ src/target/adi_v5_swd.c | 9 +++++++++ src/target/arm_adi_v5.c | 38 ++------------------------------------ src/target/arm_adi_v5.h | 28 ++++++++++++++++++++++++++++ 5 files changed, 63 insertions(+), 44 deletions(-) diff --git a/src/jtag/swd.h b/src/jtag/swd.h index 0b32105a2..0d1702c73 100644 --- a/src/jtag/swd.h +++ b/src/jtag/swd.h @@ -213,14 +213,6 @@ static const uint8_t swd_seq_dormant_to_jtag[] = { }; static const unsigned swd_seq_dormant_to_jtag_len = 160; -enum swd_special_seq { - LINE_RESET, - JTAG_TO_SWD, - SWD_TO_JTAG, - SWD_TO_DORMANT, - DORMANT_TO_SWD, -}; - struct swd_driver { /** * Initialize the debug link so it can perform SWD operations. diff --git a/src/target/adi_v5_jtag.c b/src/target/adi_v5_jtag.c index df8113492..c2100eb47 100644 --- a/src/target/adi_v5_jtag.c +++ b/src/target/adi_v5_jtag.c @@ -38,6 +38,7 @@ #include "arm_adi_v5.h" #include #include +#include /*#define DEBUG_WAIT*/ @@ -663,6 +664,28 @@ static int jtag_check_reconnect(struct adiv5_dap *dap) return ERROR_OK; } +static int jtag_send_sequence(struct adiv5_dap *dap, enum swd_special_seq seq) +{ + int retval; + + switch (seq) { + case JTAG_TO_SWD: + retval = jtag_add_tms_seq(swd_seq_jtag_to_swd_len, + swd_seq_jtag_to_swd, TAP_INVALID); + break; + case SWD_TO_JTAG: + retval = jtag_add_tms_seq(swd_seq_swd_to_jtag_len, + swd_seq_swd_to_jtag, TAP_RESET); + break; + default: + LOG_ERROR("Sequence %d not supported", seq); + return ERROR_FAIL; + } + if (retval == ERROR_OK) + retval = jtag_execute_queue(); + return retval; +} + static int jtag_dp_q_read(struct adiv5_dap *dap, unsigned reg, uint32_t *data) { @@ -782,6 +805,7 @@ static int jtag_dp_sync(struct adiv5_dap *dap) */ const struct dap_ops jtag_dp_ops = { .connect = jtag_connect, + .send_sequence = jtag_send_sequence, .queue_dp_read = jtag_dp_q_read, .queue_dp_write = jtag_dp_q_write, .queue_ap_read = jtag_ap_q_read, diff --git a/src/target/adi_v5_swd.c b/src/target/adi_v5_swd.c index 594b5081f..a3735661b 100644 --- a/src/target/adi_v5_swd.c +++ b/src/target/adi_v5_swd.c @@ -142,6 +142,14 @@ static int swd_connect(struct adiv5_dap *dap) return status; } +static int swd_send_sequence(struct adiv5_dap *dap, enum swd_special_seq seq) +{ + const struct swd_driver *swd = adiv5_dap_swd_driver(dap); + assert(swd); + + return swd->switch_seq(seq); +} + static inline int check_sync(struct adiv5_dap *dap) { return do_sync ? swd_run_inner(dap) : ERROR_OK; @@ -320,6 +328,7 @@ static void swd_quit(struct adiv5_dap *dap) const struct dap_ops swd_dap_ops = { .connect = swd_connect, + .send_sequence = swd_send_sequence, .queue_dp_read = swd_queue_dp_read, .queue_dp_write = swd_queue_dp_write, .queue_ap_read = swd_queue_ap_read, diff --git a/src/target/arm_adi_v5.c b/src/target/arm_adi_v5.c index d2ec960a8..2d47da3ea 100644 --- a/src/target/arm_adi_v5.c +++ b/src/target/arm_adi_v5.c @@ -804,26 +804,9 @@ int mem_ap_init(struct adiv5_ap *ap) */ int dap_to_swd(struct adiv5_dap *dap) { - int retval; - LOG_DEBUG("Enter SWD mode"); - if (transport_is_jtag()) { - retval = jtag_add_tms_seq(swd_seq_jtag_to_swd_len, - swd_seq_jtag_to_swd, TAP_INVALID); - if (retval == ERROR_OK) - retval = jtag_execute_queue(); - return retval; - } - - if (transport_is_swd()) { - const struct swd_driver *swd = adiv5_dap_swd_driver(dap); - - return swd->switch_seq(JTAG_TO_SWD); - } - - LOG_ERROR("Nor JTAG nor SWD transport"); - return ERROR_FAIL; + return dap_send_sequence(dap, JTAG_TO_SWD); } /** @@ -839,26 +822,9 @@ int dap_to_swd(struct adiv5_dap *dap) */ int dap_to_jtag(struct adiv5_dap *dap) { - int retval; - LOG_DEBUG("Enter JTAG mode"); - if (transport_is_jtag()) { - retval = jtag_add_tms_seq(swd_seq_swd_to_jtag_len, - swd_seq_swd_to_jtag, TAP_RESET); - if (retval == ERROR_OK) - retval = jtag_execute_queue(); - return retval; - } - - if (transport_is_swd()) { - const struct swd_driver *swd = adiv5_dap_swd_driver(dap); - - return swd->switch_seq(SWD_TO_JTAG); - } - - LOG_ERROR("Nor JTAG nor SWD transport"); - return ERROR_FAIL; + return dap_send_sequence(dap, SWD_TO_JTAG); } /* CID interpretation -- see ARM IHI 0029B section 3 diff --git a/src/target/arm_adi_v5.h b/src/target/arm_adi_v5.h index ee04d4177..88b7e5c87 100644 --- a/src/target/arm_adi_v5.h +++ b/src/target/arm_adi_v5.h @@ -158,6 +158,15 @@ #define DP_APSEL_MAX (255) #define DP_APSEL_INVALID (-1) +/* FIXME: not SWD specific; should be renamed, e.g. adiv5_special_seq */ +enum swd_special_seq { + LINE_RESET, + JTAG_TO_SWD, + SWD_TO_JTAG, + SWD_TO_DORMANT, + DORMANT_TO_SWD, +}; + /** * This represents an ARM Debug Interface (v5) Access Port (AP). * Most common is a MEM-AP, for memory access. @@ -291,6 +300,10 @@ struct adiv5_dap { struct dap_ops { /** connect operation for SWD */ int (*connect)(struct adiv5_dap *dap); + + /** send a sequence to the DAP */ + int (*send_sequence)(struct adiv5_dap *dap, enum swd_special_seq seq); + /** DP register read. */ int (*queue_dp_read)(struct adiv5_dap *dap, unsigned reg, uint32_t *data); @@ -338,6 +351,21 @@ enum ap_type { AP_TYPE_AHB5_AP = 0x5, /* AHB5 Memory-AP. */ }; +/** + * Send an adi-v5 sequence to the DAP. + * + * @param dap The DAP used for reading. + * @param seq The sequence to send. + * + * @return ERROR_OK for success, else a fault code. + */ +static inline int dap_send_sequence(struct adiv5_dap *dap, + enum swd_special_seq seq) +{ + assert(dap->ops != NULL); + return dap->ops->send_sequence(dap, seq); +} + /** * Queue a DP register read. * Note that not all DP registers are readable; also, that JTAG and SWD