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:
parent
5d08bcb715
commit
be2d25efcc
|
@ -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.
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue