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 <borneo.antonio@gmail.com>
Reviewed-on: http://openocd.zylin.com/4902
Tested-by: jenkins
Reviewed-by: Tomas Vanek <vanekt@fbl.cz>
This commit is contained in:
Antonio Borneo 2019-01-23 16:46:31 +01:00 committed by Tomas Vanek
parent 5d08bcb715
commit be2d25efcc
5 changed files with 63 additions and 44 deletions

View File

@ -213,14 +213,6 @@ static const uint8_t swd_seq_dormant_to_jtag[] = {
}; };
static const unsigned swd_seq_dormant_to_jtag_len = 160; 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 { struct swd_driver {
/** /**
* Initialize the debug link so it can perform SWD operations. * Initialize the debug link so it can perform SWD operations.

View File

@ -38,6 +38,7 @@
#include "arm_adi_v5.h" #include "arm_adi_v5.h"
#include <helper/time_support.h> #include <helper/time_support.h>
#include <helper/list.h> #include <helper/list.h>
#include <jtag/swd.h>
/*#define DEBUG_WAIT*/ /*#define DEBUG_WAIT*/
@ -663,6 +664,28 @@ static int jtag_check_reconnect(struct adiv5_dap *dap)
return ERROR_OK; 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, static int jtag_dp_q_read(struct adiv5_dap *dap, unsigned reg,
uint32_t *data) uint32_t *data)
{ {
@ -782,6 +805,7 @@ static int jtag_dp_sync(struct adiv5_dap *dap)
*/ */
const struct dap_ops jtag_dp_ops = { const struct dap_ops jtag_dp_ops = {
.connect = jtag_connect, .connect = jtag_connect,
.send_sequence = jtag_send_sequence,
.queue_dp_read = jtag_dp_q_read, .queue_dp_read = jtag_dp_q_read,
.queue_dp_write = jtag_dp_q_write, .queue_dp_write = jtag_dp_q_write,
.queue_ap_read = jtag_ap_q_read, .queue_ap_read = jtag_ap_q_read,

View File

@ -142,6 +142,14 @@ static int swd_connect(struct adiv5_dap *dap)
return status; 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) static inline int check_sync(struct adiv5_dap *dap)
{ {
return do_sync ? swd_run_inner(dap) : ERROR_OK; 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 = { const struct dap_ops swd_dap_ops = {
.connect = swd_connect, .connect = swd_connect,
.send_sequence = swd_send_sequence,
.queue_dp_read = swd_queue_dp_read, .queue_dp_read = swd_queue_dp_read,
.queue_dp_write = swd_queue_dp_write, .queue_dp_write = swd_queue_dp_write,
.queue_ap_read = swd_queue_ap_read, .queue_ap_read = swd_queue_ap_read,

View File

@ -804,26 +804,9 @@ int mem_ap_init(struct adiv5_ap *ap)
*/ */
int dap_to_swd(struct adiv5_dap *dap) int dap_to_swd(struct adiv5_dap *dap)
{ {
int retval;
LOG_DEBUG("Enter SWD mode"); LOG_DEBUG("Enter SWD mode");
if (transport_is_jtag()) { return dap_send_sequence(dap, JTAG_TO_SWD);
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;
} }
/** /**
@ -839,26 +822,9 @@ int dap_to_swd(struct adiv5_dap *dap)
*/ */
int dap_to_jtag(struct adiv5_dap *dap) int dap_to_jtag(struct adiv5_dap *dap)
{ {
int retval;
LOG_DEBUG("Enter JTAG mode"); LOG_DEBUG("Enter JTAG mode");
if (transport_is_jtag()) { return dap_send_sequence(dap, SWD_TO_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;
} }
/* CID interpretation -- see ARM IHI 0029B section 3 /* CID interpretation -- see ARM IHI 0029B section 3

View File

@ -158,6 +158,15 @@
#define DP_APSEL_MAX (255) #define DP_APSEL_MAX (255)
#define DP_APSEL_INVALID (-1) #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). * This represents an ARM Debug Interface (v5) Access Port (AP).
* Most common is a MEM-AP, for memory access. * Most common is a MEM-AP, for memory access.
@ -291,6 +300,10 @@ struct adiv5_dap {
struct dap_ops { struct dap_ops {
/** connect operation for SWD */ /** connect operation for SWD */
int (*connect)(struct adiv5_dap *dap); 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. */ /** DP register read. */
int (*queue_dp_read)(struct adiv5_dap *dap, unsigned reg, int (*queue_dp_read)(struct adiv5_dap *dap, unsigned reg,
uint32_t *data); uint32_t *data);
@ -338,6 +351,21 @@ enum ap_type {
AP_TYPE_AHB5_AP = 0x5, /* AHB5 Memory-AP. */ 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. * Queue a DP register read.
* Note that not all DP registers are readable; also, that JTAG and SWD * Note that not all DP registers are readable; also, that JTAG and SWD