|
|
@ -1,6 +1,6 @@
|
|
|
|
/* SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) */
|
|
|
|
/* SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) */
|
|
|
|
/*----------------------------------------------------------------------------
|
|
|
|
/*----------------------------------------------------------------------------
|
|
|
|
* Copyright 2020-2021 Cadence Design Systems, Inc.
|
|
|
|
* Copyright 2020-2022 Cadence Design Systems, Inc.
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without modification,
|
|
|
|
* Redistribution and use in source and binary forms, with or without modification,
|
|
|
|
* are permitted provided that the following conditions are met:
|
|
|
|
* are permitted provided that the following conditions are met:
|
|
|
@ -27,9 +27,9 @@
|
|
|
|
* @file
|
|
|
|
* @file
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* @brief the virtual debug interface provides a connection between a sw debugger
|
|
|
|
* @brief the virtual debug interface provides a connection between a sw debugger
|
|
|
|
* and the simulated, emulated core over a soft connection, implemented by DPI
|
|
|
|
* and the simulated, emulated core. The openOCD client connects via TCP sockets
|
|
|
|
* The vdebug debug driver currently supports JTAG transport
|
|
|
|
* with vdebug server and over DPI-based transactor with the emulation or simulation
|
|
|
|
* TODO: implement support and test big endian platforms
|
|
|
|
* The vdebug debug driver supports JTAG and DAP-level transports
|
|
|
|
*
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
@ -68,16 +68,18 @@
|
|
|
|
#include "jtag/interface.h"
|
|
|
|
#include "jtag/interface.h"
|
|
|
|
#include "jtag/commands.h"
|
|
|
|
#include "jtag/commands.h"
|
|
|
|
#include "transport/transport.h"
|
|
|
|
#include "transport/transport.h"
|
|
|
|
|
|
|
|
#include "target/arm_adi_v5.h"
|
|
|
|
#include "helper/time_support.h"
|
|
|
|
#include "helper/time_support.h"
|
|
|
|
#include "helper/replacements.h"
|
|
|
|
#include "helper/replacements.h"
|
|
|
|
#include "helper/log.h"
|
|
|
|
#include "helper/log.h"
|
|
|
|
|
|
|
|
#include "helper/list.h"
|
|
|
|
|
|
|
|
|
|
|
|
#define VD_VERSION 43
|
|
|
|
#define VD_VERSION 44
|
|
|
|
#define VD_BUFFER_LEN 4024
|
|
|
|
#define VD_BUFFER_LEN 4024
|
|
|
|
#define VD_CHEADER_LEN 24
|
|
|
|
#define VD_CHEADER_LEN 24
|
|
|
|
#define VD_SHEADER_LEN 16
|
|
|
|
#define VD_SHEADER_LEN 16
|
|
|
|
|
|
|
|
|
|
|
|
#define VD_MAX_MEMORIES 4
|
|
|
|
#define VD_MAX_MEMORIES 20
|
|
|
|
#define VD_POLL_INTERVAL 500
|
|
|
|
#define VD_POLL_INTERVAL 500
|
|
|
|
#define VD_SCALE_PSTOMS 1000000000
|
|
|
|
#define VD_SCALE_PSTOMS 1000000000
|
|
|
|
|
|
|
|
|
|
|
@ -149,12 +151,21 @@ enum {
|
|
|
|
VD_CMD_SIGSET = 0x0a,
|
|
|
|
VD_CMD_SIGSET = 0x0a,
|
|
|
|
VD_CMD_SIGGET = 0x0b,
|
|
|
|
VD_CMD_SIGGET = 0x0b,
|
|
|
|
VD_CMD_JTAGCLOCK = 0x0f,
|
|
|
|
VD_CMD_JTAGCLOCK = 0x0f,
|
|
|
|
|
|
|
|
VD_CMD_REGWRITE = 0x15,
|
|
|
|
|
|
|
|
VD_CMD_REGREAD = 0x16,
|
|
|
|
VD_CMD_JTAGSHTAP = 0x1a,
|
|
|
|
VD_CMD_JTAGSHTAP = 0x1a,
|
|
|
|
VD_CMD_MEMOPEN = 0x21,
|
|
|
|
VD_CMD_MEMOPEN = 0x21,
|
|
|
|
VD_CMD_MEMCLOSE = 0x22,
|
|
|
|
VD_CMD_MEMCLOSE = 0x22,
|
|
|
|
VD_CMD_MEMWRITE = 0x23,
|
|
|
|
VD_CMD_MEMWRITE = 0x23,
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
enum {
|
|
|
|
|
|
|
|
VD_ASPACE_AP = 0x01,
|
|
|
|
|
|
|
|
VD_ASPACE_DP = 0x02,
|
|
|
|
|
|
|
|
VD_ASPACE_ID = 0x03,
|
|
|
|
|
|
|
|
VD_ASPACE_AB = 0x04,
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
enum {
|
|
|
|
enum {
|
|
|
|
VD_BATCH_NO = 0,
|
|
|
|
VD_BATCH_NO = 0,
|
|
|
|
VD_BATCH_WO = 1,
|
|
|
|
VD_BATCH_WO = 1,
|
|
|
@ -165,37 +176,32 @@ struct vd_shm {
|
|
|
|
struct { /* VD_CHEADER_LEN written by client */
|
|
|
|
struct { /* VD_CHEADER_LEN written by client */
|
|
|
|
uint8_t cmd; /* 000; command */
|
|
|
|
uint8_t cmd; /* 000; command */
|
|
|
|
uint8_t type; /* 001; interface type */
|
|
|
|
uint8_t type; /* 001; interface type */
|
|
|
|
uint16_t waddr; /* 002; write pointer */
|
|
|
|
uint8_t waddr[2]; /* 002; write pointer */
|
|
|
|
uint16_t wbytes; /* 004; data bytes */
|
|
|
|
uint8_t wbytes[2]; /* 004; data bytes */
|
|
|
|
uint16_t rbytes; /* 006; data bytes to read */
|
|
|
|
uint8_t rbytes[2]; /* 006; data bytes to read */
|
|
|
|
uint16_t wwords; /* 008; data words */
|
|
|
|
uint8_t wwords[2]; /* 008; data words */
|
|
|
|
uint16_t rwords; /* 00a; data words to read */
|
|
|
|
uint8_t rwords[2]; /* 00a; data words to read */
|
|
|
|
uint32_t rwdata; /* 00c; read/write data */
|
|
|
|
uint8_t rwdata[4]; /* 00c; read/write data */
|
|
|
|
uint32_t offset; /* 010; address offset */
|
|
|
|
uint8_t offset[4]; /* 010; address offset */
|
|
|
|
uint16_t offseth; /* 014; address offset 47:32 */
|
|
|
|
uint8_t offseth[2]; /* 014; address offset 47:32 */
|
|
|
|
uint16_t wid; /* 016; request id*/
|
|
|
|
uint8_t wid[2]; /* 016; request id*/
|
|
|
|
};
|
|
|
|
|
|
|
|
union { /* 018; */
|
|
|
|
|
|
|
|
uint8_t wd8[VD_BUFFER_LEN];
|
|
|
|
|
|
|
|
uint16_t wd16[VD_BUFFER_LEN / 2];
|
|
|
|
|
|
|
|
uint32_t wd32[VD_BUFFER_LEN / 4];
|
|
|
|
|
|
|
|
uint64_t wd64[VD_BUFFER_LEN / 8];
|
|
|
|
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
uint8_t wd8[VD_BUFFER_LEN]; /* 018; */
|
|
|
|
struct { /* VD_SHEADER_LEN written by server */
|
|
|
|
struct { /* VD_SHEADER_LEN written by server */
|
|
|
|
uint16_t rid; /* fd0: request id read */
|
|
|
|
uint8_t rid[2]; /* fd0: request id read */
|
|
|
|
uint16_t awords; /* fd2: actual data words read back */
|
|
|
|
uint8_t awords[2]; /* fd2: actual data words read back */
|
|
|
|
int32_t status; /* fd4; */
|
|
|
|
uint8_t status[4]; /* fd4; */
|
|
|
|
uint64_t duttime; /* fd8; */
|
|
|
|
uint8_t duttime[8]; /* fd8; */
|
|
|
|
};
|
|
|
|
};
|
|
|
|
union { /* fe0: */
|
|
|
|
uint8_t rd8[VD_BUFFER_LEN]; /* fe0: */
|
|
|
|
uint8_t rd8[VD_BUFFER_LEN];
|
|
|
|
uint8_t state[4]; /* 1f98; connection state */
|
|
|
|
uint16_t rd16[VD_BUFFER_LEN / 2];
|
|
|
|
uint8_t count[4]; /* 1f9c; */
|
|
|
|
uint32_t rd32[VD_BUFFER_LEN / 4];
|
|
|
|
|
|
|
|
uint64_t rd64[VD_BUFFER_LEN / 8];
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
uint32_t state; /* 1f98; connection state */
|
|
|
|
|
|
|
|
uint32_t count; /* 1f9c; */
|
|
|
|
|
|
|
|
uint8_t dummy[96]; /* 1fa0; 48+40B+8B; */
|
|
|
|
uint8_t dummy[96]; /* 1fa0; 48+40B+8B; */
|
|
|
|
|
|
|
|
} __attribute__((packed));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct vd_rdata {
|
|
|
|
|
|
|
|
struct list_head lh;
|
|
|
|
|
|
|
|
uint8_t *rdata;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
struct vd_client {
|
|
|
|
struct vd_client {
|
|
|
@ -222,7 +228,7 @@ struct vd_client {
|
|
|
|
char server_name[32];
|
|
|
|
char server_name[32];
|
|
|
|
char bfm_path[128];
|
|
|
|
char bfm_path[128];
|
|
|
|
char mem_path[VD_MAX_MEMORIES][128];
|
|
|
|
char mem_path[VD_MAX_MEMORIES][128];
|
|
|
|
uint8_t *tdo;
|
|
|
|
struct vd_rdata rdataq;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
struct vd_jtag_hdr {
|
|
|
|
struct vd_jtag_hdr {
|
|
|
@ -234,6 +240,16 @@ struct vd_jtag_hdr {
|
|
|
|
uint64_t rlen:16;
|
|
|
|
uint64_t rlen:16;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct vd_reg_hdr {
|
|
|
|
|
|
|
|
uint64_t prot:3;
|
|
|
|
|
|
|
|
uint64_t nonincr:1;
|
|
|
|
|
|
|
|
uint64_t haddr:12;
|
|
|
|
|
|
|
|
uint64_t tlen:11;
|
|
|
|
|
|
|
|
uint64_t asize:3;
|
|
|
|
|
|
|
|
uint64_t cmd:2;
|
|
|
|
|
|
|
|
uint64_t addr:32;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static struct vd_shm *pbuf;
|
|
|
|
static struct vd_shm *pbuf;
|
|
|
|
static struct vd_client vdc;
|
|
|
|
static struct vd_client vdc;
|
|
|
|
|
|
|
|
|
|
|
@ -277,7 +293,7 @@ static int vdebug_socket_open(char *server_addr, uint32_t port)
|
|
|
|
LOG_ERROR("socket_open: cannot resolve address %s, error %d", server_addr, vdebug_socket_error());
|
|
|
|
LOG_ERROR("socket_open: cannot resolve address %s, error %d", server_addr, vdebug_socket_error());
|
|
|
|
rc = VD_ERR_SOC_ADDR;
|
|
|
|
rc = VD_ERR_SOC_ADDR;
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
((struct sockaddr_in *)(ainfo->ai_addr))->sin_port = htons(port);
|
|
|
|
buf_set_u32((uint8_t *)ainfo->ai_addr->sa_data, 0, 16, htons(port));
|
|
|
|
if (connect(hsock, ainfo->ai_addr, sizeof(struct sockaddr)) < 0) {
|
|
|
|
if (connect(hsock, ainfo->ai_addr, sizeof(struct sockaddr)) < 0) {
|
|
|
|
LOG_ERROR("socket_open: cannot connect to %s:%d, error %d", server_addr, port, vdebug_socket_error());
|
|
|
|
LOG_ERROR("socket_open: cannot connect to %s:%d, error %d", server_addr, port, vdebug_socket_error());
|
|
|
|
rc = VD_ERR_SOC_CONN;
|
|
|
|
rc = VD_ERR_SOC_CONN;
|
|
|
@ -299,8 +315,8 @@ static int vdebug_socket_receive(int hsock, struct vd_shm *pmem)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
int rc;
|
|
|
|
int rc;
|
|
|
|
int dreceived = 0;
|
|
|
|
int dreceived = 0;
|
|
|
|
int offset = (uint8_t *)&pmem->rid - &pmem->cmd;
|
|
|
|
int offset = &pmem->rid[0] - &pmem->cmd;
|
|
|
|
int to_receive = VD_SHEADER_LEN + pmem->rbytes;
|
|
|
|
int to_receive = VD_SHEADER_LEN + le_to_h_u16(pmem->rbytes);
|
|
|
|
char *pb = (char *)pmem;
|
|
|
|
char *pb = (char *)pmem;
|
|
|
|
|
|
|
|
|
|
|
|
do {
|
|
|
|
do {
|
|
|
@ -320,7 +336,7 @@ static int vdebug_socket_receive(int hsock, struct vd_shm *pmem)
|
|
|
|
|
|
|
|
|
|
|
|
static int vdebug_socket_send(int hsock, struct vd_shm *pmem)
|
|
|
|
static int vdebug_socket_send(int hsock, struct vd_shm *pmem)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
int rc = send(hsock, (const char *)&pmem->cmd, VD_CHEADER_LEN + pmem->wbytes, 0);
|
|
|
|
int rc = send(hsock, (const char *)&pmem->cmd, VD_CHEADER_LEN + le_to_h_u16(pmem->wbytes), 0);
|
|
|
|
if (rc <= 0)
|
|
|
|
if (rc <= 0)
|
|
|
|
LOG_WARNING("socket_send: send failed, error %d", vdebug_socket_error());
|
|
|
|
LOG_WARNING("socket_send: send failed, error %d", vdebug_socket_error());
|
|
|
|
else
|
|
|
|
else
|
|
|
@ -333,6 +349,7 @@ static uint32_t vdebug_wait_server(int hsock, struct vd_shm *pmem)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (!hsock)
|
|
|
|
if (!hsock)
|
|
|
|
return VD_ERR_SOC_OPEN;
|
|
|
|
return VD_ERR_SOC_OPEN;
|
|
|
|
|
|
|
|
|
|
|
|
int st = vdebug_socket_send(hsock, pmem);
|
|
|
|
int st = vdebug_socket_send(hsock, pmem);
|
|
|
|
if (st <= 0)
|
|
|
|
if (st <= 0)
|
|
|
|
return VD_ERR_SOC_SEND;
|
|
|
|
return VD_ERR_SOC_SEND;
|
|
|
@ -341,9 +358,9 @@ static uint32_t vdebug_wait_server(int hsock, struct vd_shm *pmem)
|
|
|
|
if (rd <= 0)
|
|
|
|
if (rd <= 0)
|
|
|
|
return VD_ERR_SOC_RECV;
|
|
|
|
return VD_ERR_SOC_RECV;
|
|
|
|
|
|
|
|
|
|
|
|
int rc = pmem->status;
|
|
|
|
int rc = le_to_h_u32(pmem->status);
|
|
|
|
LOG_DEBUG_IO("wait_server: cmd %02" PRIx8 " done, sent %d, rcvd %d, status %d",
|
|
|
|
LOG_DEBUG_IO("wait_server: cmd %02" PRIx8 " done, sent %d, rcvd %d, status %d",
|
|
|
|
pmem->cmd, st, rd, rc);
|
|
|
|
pmem->cmd, st, rd, rc);
|
|
|
|
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -356,22 +373,23 @@ int vdebug_run_jtag_queue(int hsock, struct vd_shm *pm, unsigned int count)
|
|
|
|
int64_t ts, te;
|
|
|
|
int64_t ts, te;
|
|
|
|
uint8_t *tdo;
|
|
|
|
uint8_t *tdo;
|
|
|
|
int rc;
|
|
|
|
int rc;
|
|
|
|
struct vd_jtag_hdr *hdr;
|
|
|
|
uint64_t jhdr;
|
|
|
|
|
|
|
|
struct vd_rdata *rd;
|
|
|
|
|
|
|
|
|
|
|
|
req = 0; /* beginning of request */
|
|
|
|
req = 0; /* beginning of request */
|
|
|
|
waddr = 0;
|
|
|
|
waddr = 0;
|
|
|
|
rwords = 0;
|
|
|
|
rwords = 0;
|
|
|
|
pm->wbytes = pm->wwords * vdc.buf_width;
|
|
|
|
h_u16_to_le(pm->wbytes, le_to_h_u16(pm->wwords) * vdc.buf_width);
|
|
|
|
pm->rbytes = pm->rwords * vdc.buf_width;
|
|
|
|
h_u16_to_le(pm->rbytes, le_to_h_u16(pm->rwords) * vdc.buf_width);
|
|
|
|
ts = timeval_ms();
|
|
|
|
ts = timeval_ms();
|
|
|
|
rc = vdebug_wait_server(hsock, pm);
|
|
|
|
rc = vdebug_wait_server(hsock, pm);
|
|
|
|
while (!rc && (req < count)) { /* loop over requests to read data and print out */
|
|
|
|
while (!rc && (req < count)) { /* loop over requests to read data and print out */
|
|
|
|
hdr = (struct vd_jtag_hdr *)&pm->wd8[waddr * 4];
|
|
|
|
jhdr = le_to_h_u64(&pm->wd8[waddr * 4]);
|
|
|
|
hwords = hdr->wlen;
|
|
|
|
words = jhdr >> 48;
|
|
|
|
words = hdr->rlen;
|
|
|
|
hwords = (jhdr >> 32) & 0xffff;
|
|
|
|
anum = hdr->tlen;
|
|
|
|
anum = jhdr & 0xffffff;
|
|
|
|
num_pre = hdr->pre;
|
|
|
|
num_pre = (jhdr >> 27) & 0x7;
|
|
|
|
num_post = hdr->post;
|
|
|
|
num_post = (jhdr >> 24) & 0x7;
|
|
|
|
if (num_post)
|
|
|
|
if (num_post)
|
|
|
|
num = anum - num_pre - num_post + 1;
|
|
|
|
num = anum - num_pre - num_post + 1;
|
|
|
|
else
|
|
|
|
else
|
|
|
@ -379,21 +397,29 @@ int vdebug_run_jtag_queue(int hsock, struct vd_shm *pm, unsigned int count)
|
|
|
|
bytes = (num + 7) / 8;
|
|
|
|
bytes = (num + 7) / 8;
|
|
|
|
vdc.trans_last = (req + 1) < count ? 0 : 1;
|
|
|
|
vdc.trans_last = (req + 1) < count ? 0 : 1;
|
|
|
|
vdc.trans_first = waddr ? 0 : 1;
|
|
|
|
vdc.trans_first = waddr ? 0 : 1;
|
|
|
|
if (hdr->cmd == 3) { /* read */
|
|
|
|
if (((jhdr >> 30) & 0x3) == 3) { /* cmd is read */
|
|
|
|
tdo = vdc.tdo;
|
|
|
|
if (!rwords) {
|
|
|
|
|
|
|
|
rd = &vdc.rdataq;
|
|
|
|
|
|
|
|
tdo = rd->rdata;
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
rd = list_first_entry(&vdc.rdataq.lh, struct vd_rdata, lh);
|
|
|
|
|
|
|
|
tdo = rd->rdata;
|
|
|
|
|
|
|
|
list_del(&rd->lh);
|
|
|
|
|
|
|
|
free(rd);
|
|
|
|
|
|
|
|
}
|
|
|
|
for (unsigned int j = 0; j < bytes; j++) {
|
|
|
|
for (unsigned int j = 0; j < bytes; j++) {
|
|
|
|
tdo[j] = (pm->rd8[rwords * 8 + j] >> num_pre) | (pm->rd8[rwords * 8 + j + 1] << (8 - num_pre));
|
|
|
|
tdo[j] = (pm->rd8[rwords * 8 + j] >> num_pre) | (pm->rd8[rwords * 8 + j + 1] << (8 - num_pre));
|
|
|
|
LOG_DEBUG_IO("%04x D0[%02x]:%02x", pm->wid - count + req, j, tdo[j]);
|
|
|
|
LOG_DEBUG_IO("%04x D0[%02x]:%02x", le_to_h_u16(pm->wid) - count + req, j, tdo[j]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
rwords += words; /* read data offset */
|
|
|
|
rwords += words; /* read data offset */
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
tdo = NULL;
|
|
|
|
tdo = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
waddr += sizeof(struct vd_jtag_hdr) / 4; /* waddr past header */
|
|
|
|
waddr += sizeof(uint64_t) / 4; /* waddr past header */
|
|
|
|
tdi = (pm->wd8[waddr * 4] >> num_pre) | (pm->wd8[waddr * 4 + 1] << (8 - num_pre));
|
|
|
|
tdi = (pm->wd8[waddr * 4] >> num_pre) | (pm->wd8[waddr * 4 + 1] << (8 - num_pre));
|
|
|
|
tms = (pm->wd8[waddr * 4 + 4] >> num_pre) | (pm->wd8[waddr * 4 + 4 + 1] << (8 - num_pre));
|
|
|
|
tms = (pm->wd8[waddr * 4 + 4] >> num_pre) | (pm->wd8[waddr * 4 + 4 + 1] << (8 - num_pre));
|
|
|
|
LOG_DEBUG("%04x L:%02d O:%05x @%03x DI:%02x MS:%02x DO:%02x",
|
|
|
|
LOG_DEBUG_IO("%04x L:%02d O:%05x @%03x DI:%02x MS:%02x DO:%02x",
|
|
|
|
pm->wid - count + req, num, (vdc.trans_first << 14) | (vdc.trans_last << 15),
|
|
|
|
le_to_h_u16(pm->wid) - count + req, num, (vdc.trans_first << 14) | (vdc.trans_last << 15),
|
|
|
|
waddr - 2, tdi, tms, (tdo ? tdo[0] : 0xdd));
|
|
|
|
waddr - 2, tdi, tms, (tdo ? tdo[0] : 0xdd));
|
|
|
|
waddr += hwords * 2; /* start of next request */
|
|
|
|
waddr += hwords * 2; /* start of next request */
|
|
|
|
req += 1;
|
|
|
|
req += 1;
|
|
|
@ -406,10 +432,83 @@ int vdebug_run_jtag_queue(int hsock, struct vd_shm *pm, unsigned int count)
|
|
|
|
|
|
|
|
|
|
|
|
te = timeval_ms();
|
|
|
|
te = timeval_ms();
|
|
|
|
vdc.targ_time += (uint32_t)(te - ts);
|
|
|
|
vdc.targ_time += (uint32_t)(te - ts);
|
|
|
|
pm->offseth = 0; /* reset buffer write address */
|
|
|
|
h_u16_to_le(pm->offseth, 0); /* reset buffer write address */
|
|
|
|
pm->offset = 0;
|
|
|
|
h_u32_to_le(pm->offset, 0);
|
|
|
|
pm->rwords = 0;
|
|
|
|
h_u16_to_le(pm->rwords, 0);
|
|
|
|
pm->waddr = 0;
|
|
|
|
h_u16_to_le(pm->waddr, 0);
|
|
|
|
|
|
|
|
assert(list_empty(&vdc.rdataq.lh));/* list should be empty after run queue */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int vdebug_run_reg_queue(int hsock, struct vd_shm *pm, unsigned int count)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
unsigned int num, awidth, wwidth;
|
|
|
|
|
|
|
|
unsigned int req, waddr, rwords;
|
|
|
|
|
|
|
|
uint8_t aspace;
|
|
|
|
|
|
|
|
uint32_t addr;
|
|
|
|
|
|
|
|
int64_t ts, te;
|
|
|
|
|
|
|
|
uint8_t *data;
|
|
|
|
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
uint64_t rhdr;
|
|
|
|
|
|
|
|
struct vd_rdata *rd;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
req = 0; /* beginning of request */
|
|
|
|
|
|
|
|
waddr = 0;
|
|
|
|
|
|
|
|
rwords = 0;
|
|
|
|
|
|
|
|
h_u16_to_le(pm->wbytes, le_to_h_u16(pm->wwords) * vdc.buf_width);
|
|
|
|
|
|
|
|
h_u16_to_le(pm->rbytes, le_to_h_u16(pm->rwords) * vdc.buf_width);
|
|
|
|
|
|
|
|
ts = timeval_ms();
|
|
|
|
|
|
|
|
rc = vdebug_wait_server(hsock, pm);
|
|
|
|
|
|
|
|
while (!rc && (req < count)) { /* loop over requests to read data and print out */
|
|
|
|
|
|
|
|
rhdr = le_to_h_u64(&pm->wd8[waddr * 4]);
|
|
|
|
|
|
|
|
addr = rhdr >> 32; /* reconstruct data for a single request */
|
|
|
|
|
|
|
|
num = (rhdr >> 16) & 0x7ff;
|
|
|
|
|
|
|
|
aspace = rhdr & 0x3;
|
|
|
|
|
|
|
|
awidth = (1 << ((rhdr >> 27) & 0x7));
|
|
|
|
|
|
|
|
wwidth = (awidth + vdc.buf_width - 1) / vdc.buf_width;
|
|
|
|
|
|
|
|
vdc.trans_last = (req + 1) < count ? 0 : 1;
|
|
|
|
|
|
|
|
vdc.trans_first = waddr ? 0 : 1;
|
|
|
|
|
|
|
|
if (((rhdr >> 30) & 0x3) == 2) { /* cmd is read */
|
|
|
|
|
|
|
|
if (num) {
|
|
|
|
|
|
|
|
if (!rwords) {
|
|
|
|
|
|
|
|
rd = &vdc.rdataq;
|
|
|
|
|
|
|
|
data = rd->rdata;
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
rd = list_first_entry(&vdc.rdataq.lh, struct vd_rdata, lh);
|
|
|
|
|
|
|
|
data = rd->rdata;
|
|
|
|
|
|
|
|
list_del(&rd->lh);
|
|
|
|
|
|
|
|
free(rd);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
for (unsigned int j = 0; j < num; j++)
|
|
|
|
|
|
|
|
memcpy(&data[j * awidth], &pm->rd8[(rwords + j) * awidth], awidth);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
LOG_DEBUG_IO("read %04x AS:%02x RG:%02x O:%05x @%03x D:%08x", le_to_h_u16(pm->wid) - count + req,
|
|
|
|
|
|
|
|
aspace, addr, (vdc.trans_first << 14) | (vdc.trans_last << 15), waddr,
|
|
|
|
|
|
|
|
(num ? le_to_h_u32(&pm->rd8[rwords * 4]) : 0xdead));
|
|
|
|
|
|
|
|
rwords += num * wwidth;
|
|
|
|
|
|
|
|
waddr += sizeof(uint64_t) / 4; /* waddr past header */
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
LOG_DEBUG_IO("write %04x AS:%02x RG:%02x O:%05x @%03x D:%08x", le_to_h_u16(pm->wid) - count + req,
|
|
|
|
|
|
|
|
aspace, addr, (vdc.trans_first << 14) | (vdc.trans_last << 15), waddr,
|
|
|
|
|
|
|
|
le_to_h_u32(&pm->wd8[(waddr + num + 1) * 4]));
|
|
|
|
|
|
|
|
waddr += sizeof(uint64_t) / 4 + (num * wwidth * awidth + 3) / 4;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
req += 1;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (rc) {
|
|
|
|
|
|
|
|
LOG_ERROR("0x%x executing transaction", rc);
|
|
|
|
|
|
|
|
rc = ERROR_FAIL;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
te = timeval_ms();
|
|
|
|
|
|
|
|
vdc.targ_time += (uint32_t)(te - ts);
|
|
|
|
|
|
|
|
h_u16_to_le(pm->offseth, 0); /* reset buffer write address */
|
|
|
|
|
|
|
|
h_u32_to_le(pm->offset, 0);
|
|
|
|
|
|
|
|
h_u16_to_le(pm->rwords, 0);
|
|
|
|
|
|
|
|
h_u16_to_le(pm->waddr, 0);
|
|
|
|
|
|
|
|
assert(list_empty(&vdc.rdataq.lh));/* list should be empty after run queue */
|
|
|
|
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -420,35 +519,35 @@ static int vdebug_open(int hsock, struct vd_shm *pm, const char *path,
|
|
|
|
int rc = VD_ERR_NOT_OPEN;
|
|
|
|
int rc = VD_ERR_NOT_OPEN;
|
|
|
|
|
|
|
|
|
|
|
|
pm->cmd = VD_CMD_OPEN;
|
|
|
|
pm->cmd = VD_CMD_OPEN;
|
|
|
|
pm->wid = VD_VERSION; /* client version */
|
|
|
|
h_u16_to_le(pm->wid, VD_VERSION); /* client version */
|
|
|
|
pm->wbytes = 0;
|
|
|
|
h_u16_to_le(pm->wbytes, 0);
|
|
|
|
pm->rbytes = 0;
|
|
|
|
h_u16_to_le(pm->rbytes, 0);
|
|
|
|
pm->wwords = 0;
|
|
|
|
h_u16_to_le(pm->wwords, 0);
|
|
|
|
pm->rwords = 0;
|
|
|
|
h_u16_to_le(pm->rwords, 0);
|
|
|
|
rc = vdebug_wait_server(hsock, pm);
|
|
|
|
rc = vdebug_wait_server(hsock, pm);
|
|
|
|
if (rc != 0) { /* communication problem */
|
|
|
|
if (rc != 0) { /* communication problem */
|
|
|
|
LOG_ERROR("0x%x connecting to server", rc);
|
|
|
|
LOG_ERROR("0x%x connecting to server", rc);
|
|
|
|
} else if (pm->rid < pm->wid) {
|
|
|
|
} else if (le_to_h_u16(pm->rid) < le_to_h_u16(pm->wid)) {
|
|
|
|
LOG_ERROR("server version %d too old for the client %d", pm->rid, pm->wid);
|
|
|
|
LOG_ERROR("server version %d too old for the client %d", le_to_h_u16(pm->rid), le_to_h_u16(pm->wid));
|
|
|
|
pm->cmd = VD_CMD_CLOSE; /* let server close the connection */
|
|
|
|
pm->cmd = VD_CMD_CLOSE; /* let server close the connection */
|
|
|
|
vdebug_wait_server(hsock, pm);
|
|
|
|
vdebug_wait_server(hsock, pm);
|
|
|
|
rc = VD_ERR_VERSION;
|
|
|
|
rc = VD_ERR_VERSION;
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
pm->cmd = VD_CMD_CONNECT;
|
|
|
|
pm->cmd = VD_CMD_CONNECT;
|
|
|
|
pm->type = type; /* BFM type to connect to, here JTAG */
|
|
|
|
pm->type = type; /* BFM type to connect to, here JTAG */
|
|
|
|
pm->rwdata = sig_mask | VD_SIG_BUF | (VD_SIG_BUF << 16);
|
|
|
|
h_u32_to_le(pm->rwdata, sig_mask | VD_SIG_BUF | (VD_SIG_BUF << 16));
|
|
|
|
pm->wbytes = strlen(path) + 1;
|
|
|
|
h_u16_to_le(pm->wbytes, strlen(path) + 1);
|
|
|
|
pm->rbytes = 12;
|
|
|
|
h_u16_to_le(pm->rbytes, 12);
|
|
|
|
pm->wid = 0; /* reset wid for transaction ID */
|
|
|
|
h_u16_to_le(pm->wid, 0); /* reset wid for transaction ID */
|
|
|
|
pm->wwords = 0;
|
|
|
|
h_u16_to_le(pm->wwords, 0);
|
|
|
|
pm->rwords = 0;
|
|
|
|
h_u16_to_le(pm->rwords, 0);
|
|
|
|
memcpy(pm->wd8, path, pm->wbytes + 1);
|
|
|
|
memcpy(pm->wd8, path, le_to_h_u16(pm->wbytes));
|
|
|
|
rc = vdebug_wait_server(hsock, pm);
|
|
|
|
rc = vdebug_wait_server(hsock, pm);
|
|
|
|
vdc.sig_read = pm->rwdata >> 16; /* signal read mask */
|
|
|
|
vdc.sig_read = le_to_h_u32(pm->rwdata) >> 16; /* signal read mask */
|
|
|
|
vdc.sig_write = pm->rwdata; /* signal write mask */
|
|
|
|
vdc.sig_write = le_to_h_u32(pm->rwdata); /* signal write mask */
|
|
|
|
vdc.bfm_period = period_ps;
|
|
|
|
vdc.bfm_period = period_ps;
|
|
|
|
vdc.buf_width = pm->rd32[0] / 8;/* access width in bytes */
|
|
|
|
vdc.buf_width = le_to_h_u32(&pm->rd8[0]) / 8;/* access width in bytes */
|
|
|
|
vdc.addr_bits = pm->rd32[2]; /* supported address bits */
|
|
|
|
vdc.addr_bits = le_to_h_u32(&pm->rd8[2 * 4]); /* supported address bits */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (rc) {
|
|
|
|
if (rc) {
|
|
|
@ -456,6 +555,7 @@ static int vdebug_open(int hsock, struct vd_shm *pm, const char *path,
|
|
|
|
return ERROR_FAIL;
|
|
|
|
return ERROR_FAIL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
INIT_LIST_HEAD(&vdc.rdataq.lh);
|
|
|
|
LOG_DEBUG("%s type %0x, period %dps, buffer %dx%dB signals r%04xw%04x",
|
|
|
|
LOG_DEBUG("%s type %0x, period %dps, buffer %dx%dB signals r%04xw%04x",
|
|
|
|
path, type, vdc.bfm_period, VD_BUFFER_LEN / vdc.buf_width,
|
|
|
|
path, type, vdc.bfm_period, VD_BUFFER_LEN / vdc.buf_width,
|
|
|
|
vdc.buf_width, vdc.sig_read, vdc.sig_write);
|
|
|
|
vdc.buf_width, vdc.sig_read, vdc.sig_write);
|
|
|
@ -467,17 +567,17 @@ static int vdebug_close(int hsock, struct vd_shm *pm, uint8_t type)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
pm->cmd = VD_CMD_DISCONNECT;
|
|
|
|
pm->cmd = VD_CMD_DISCONNECT;
|
|
|
|
pm->type = type; /* BFM type, here JTAG */
|
|
|
|
pm->type = type; /* BFM type, here JTAG */
|
|
|
|
pm->wbytes = 0;
|
|
|
|
h_u16_to_le(pm->wbytes, 0);
|
|
|
|
pm->rbytes = 0;
|
|
|
|
h_u16_to_le(pm->rbytes, 0);
|
|
|
|
pm->wwords = 0;
|
|
|
|
h_u16_to_le(pm->wwords, 0);
|
|
|
|
pm->rwords = 0;
|
|
|
|
h_u16_to_le(pm->rwords, 0);
|
|
|
|
vdebug_wait_server(hsock, pm);
|
|
|
|
vdebug_wait_server(hsock, pm);
|
|
|
|
pm->cmd = VD_CMD_CLOSE;
|
|
|
|
pm->cmd = VD_CMD_CLOSE;
|
|
|
|
pm->wid = VD_VERSION; /* client version */
|
|
|
|
h_u16_to_le(pm->wid, VD_VERSION); /* client version */
|
|
|
|
pm->wbytes = 0;
|
|
|
|
h_u16_to_le(pm->wbytes, 0);
|
|
|
|
pm->rbytes = 0;
|
|
|
|
h_u16_to_le(pm->rbytes, 0);
|
|
|
|
pm->wwords = 0;
|
|
|
|
h_u16_to_le(pm->wwords, 0);
|
|
|
|
pm->rwords = 0;
|
|
|
|
h_u16_to_le(pm->rwords, 0);
|
|
|
|
vdebug_wait_server(hsock, pm);
|
|
|
|
vdebug_wait_server(hsock, pm);
|
|
|
|
LOG_DEBUG("type %0x", type);
|
|
|
|
LOG_DEBUG("type %0x", type);
|
|
|
|
|
|
|
|
|
|
|
@ -488,9 +588,9 @@ static int vdebug_wait(int hsock, struct vd_shm *pm, uint32_t cycles)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (cycles) {
|
|
|
|
if (cycles) {
|
|
|
|
pm->cmd = VD_CMD_WAIT;
|
|
|
|
pm->cmd = VD_CMD_WAIT;
|
|
|
|
pm->wbytes = 0;
|
|
|
|
h_u16_to_le(pm->wbytes, 0);
|
|
|
|
pm->rbytes = 0;
|
|
|
|
h_u16_to_le(pm->rbytes, 0);
|
|
|
|
pm->rwdata = cycles; /* clock sycles to wait */
|
|
|
|
h_u32_to_le(pm->rwdata, cycles); /* clock sycles to wait */
|
|
|
|
int rc = vdebug_wait_server(hsock, pm);
|
|
|
|
int rc = vdebug_wait_server(hsock, pm);
|
|
|
|
if (rc) {
|
|
|
|
if (rc) {
|
|
|
|
LOG_ERROR("0x%x waiting %" PRIx32 " cycles", rc, cycles);
|
|
|
|
LOG_ERROR("0x%x waiting %" PRIx32 " cycles", rc, cycles);
|
|
|
@ -505,9 +605,9 @@ static int vdebug_wait(int hsock, struct vd_shm *pm, uint32_t cycles)
|
|
|
|
static int vdebug_sig_set(int hsock, struct vd_shm *pm, uint32_t write_mask, uint32_t value)
|
|
|
|
static int vdebug_sig_set(int hsock, struct vd_shm *pm, uint32_t write_mask, uint32_t value)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
pm->cmd = VD_CMD_SIGSET;
|
|
|
|
pm->cmd = VD_CMD_SIGSET;
|
|
|
|
pm->wbytes = 0;
|
|
|
|
h_u16_to_le(pm->wbytes, 0);
|
|
|
|
pm->rbytes = 0;
|
|
|
|
h_u16_to_le(pm->rbytes, 0);
|
|
|
|
pm->rwdata = (write_mask << 16) | (value & 0xffff); /* mask and value of signals to set */
|
|
|
|
h_u32_to_le(pm->rwdata, (write_mask << 16) | (value & 0xffff)); /* mask and value of signals to set */
|
|
|
|
int rc = vdebug_wait_server(hsock, pm);
|
|
|
|
int rc = vdebug_wait_server(hsock, pm);
|
|
|
|
if (rc) {
|
|
|
|
if (rc) {
|
|
|
|
LOG_ERROR("0x%x setting signals %04" PRIx32, rc, write_mask);
|
|
|
|
LOG_ERROR("0x%x setting signals %04" PRIx32, rc, write_mask);
|
|
|
@ -522,9 +622,9 @@ static int vdebug_sig_set(int hsock, struct vd_shm *pm, uint32_t write_mask, uin
|
|
|
|
static int vdebug_jtag_clock(int hsock, struct vd_shm *pm, uint32_t value)
|
|
|
|
static int vdebug_jtag_clock(int hsock, struct vd_shm *pm, uint32_t value)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
pm->cmd = VD_CMD_JTAGCLOCK;
|
|
|
|
pm->cmd = VD_CMD_JTAGCLOCK;
|
|
|
|
pm->wbytes = 0;
|
|
|
|
h_u16_to_le(pm->wbytes, 0);
|
|
|
|
pm->rbytes = 0;
|
|
|
|
h_u16_to_le(pm->rbytes, 0);
|
|
|
|
pm->rwdata = value; /* divider value */
|
|
|
|
h_u32_to_le(pm->rwdata, value); /* divider value */
|
|
|
|
int rc = vdebug_wait_server(hsock, pm);
|
|
|
|
int rc = vdebug_wait_server(hsock, pm);
|
|
|
|
if (rc) {
|
|
|
|
if (rc) {
|
|
|
|
LOG_ERROR("0x%x setting jtag_clock", rc);
|
|
|
|
LOG_ERROR("0x%x setting jtag_clock", rc);
|
|
|
@ -546,11 +646,11 @@ static int vdebug_jtag_shift_tap(int hsock, struct vd_shm *pm, uint8_t num_pre,
|
|
|
|
int rc = 0;
|
|
|
|
int rc = 0;
|
|
|
|
|
|
|
|
|
|
|
|
pm->cmd = VD_CMD_JTAGSHTAP;
|
|
|
|
pm->cmd = VD_CMD_JTAGSHTAP;
|
|
|
|
vdc.trans_last = f_last || (vdc.trans_batch == VD_BATCH_NO) || tdo;
|
|
|
|
vdc.trans_last = f_last || (vdc.trans_batch == VD_BATCH_NO);
|
|
|
|
if (vdc.trans_first)
|
|
|
|
if (vdc.trans_first)
|
|
|
|
waddr = 0; /* reset buffer offset */
|
|
|
|
waddr = 0; /* reset buffer offset */
|
|
|
|
else
|
|
|
|
else
|
|
|
|
waddr = pm->offseth; /* continue from the previous transaction */
|
|
|
|
waddr = le_to_h_u32(pm->offseth); /* continue from the previous transaction */
|
|
|
|
if (num_post) /* actual number of bits to shift */
|
|
|
|
if (num_post) /* actual number of bits to shift */
|
|
|
|
anum = num + num_pre + num_post - 1;
|
|
|
|
anum = num + num_pre + num_post - 1;
|
|
|
|
else
|
|
|
|
else
|
|
|
@ -559,25 +659,22 @@ static int vdebug_jtag_shift_tap(int hsock, struct vd_shm *pm, uint8_t num_pre,
|
|
|
|
words = (hwords + 1) / 2; /* in 8B TDO words to read */
|
|
|
|
words = (hwords + 1) / 2; /* in 8B TDO words to read */
|
|
|
|
bytes = (num + 7) / 8; /* data only portion in bytes */
|
|
|
|
bytes = (num + 7) / 8; /* data only portion in bytes */
|
|
|
|
/* buffer overflow check and flush */
|
|
|
|
/* buffer overflow check and flush */
|
|
|
|
if (4 * waddr + sizeof(struct vd_jtag_hdr) + 8 * hwords + 64 > VD_BUFFER_LEN) {
|
|
|
|
if (4 * waddr + sizeof(uint64_t) + 8 * hwords + 64 > VD_BUFFER_LEN) {
|
|
|
|
vdc.trans_last = 1; /* force flush within 64B of buffer end */
|
|
|
|
vdc.trans_last = 1; /* force flush within 64B of buffer end */
|
|
|
|
} else if (4 * waddr + sizeof(struct vd_jtag_hdr) + 8 * hwords > VD_BUFFER_LEN) {
|
|
|
|
} else if (4 * waddr + sizeof(uint64_t) + 8 * hwords > VD_BUFFER_LEN) {
|
|
|
|
/* this req does not fit, discard it */
|
|
|
|
/* this req does not fit, discard it */
|
|
|
|
LOG_ERROR("%04x L:%02d O:%05x @%04x too many bits to shift",
|
|
|
|
LOG_ERROR("%04x L:%02d O:%05x @%04x too many bits to shift",
|
|
|
|
pm->wid, anum, (vdc.trans_first << 14) | (vdc.trans_last << 15), waddr);
|
|
|
|
le_to_h_u16(pm->wid), anum, (vdc.trans_first << 14) | (vdc.trans_last << 15), waddr);
|
|
|
|
rc = ERROR_FAIL;
|
|
|
|
rc = ERROR_FAIL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (!rc && anum) {
|
|
|
|
if (!rc && anum) {
|
|
|
|
uint16_t i, j;
|
|
|
|
uint16_t i, j; /* portability requires to use bit operations for 8B JTAG header */
|
|
|
|
struct vd_jtag_hdr *hdr = (struct vd_jtag_hdr *)&pm->wd8[4 * waddr]; /* 8 bytes header */
|
|
|
|
uint64_t jhdr = (tdo ? ((uint64_t)(words) << 48) : 0) + ((uint64_t)(hwords) << 32) +
|
|
|
|
hdr->cmd = (tdo ? 3 : 1); /* R and W bits */
|
|
|
|
((tdo ? 3UL : 1UL) << 30) + (num_pre << 27) + (num_post << 24) + anum;
|
|
|
|
hdr->pre = num_pre;
|
|
|
|
h_u64_to_le(&pm->wd8[4 * waddr], jhdr);
|
|
|
|
hdr->post = num_post;
|
|
|
|
|
|
|
|
hdr->tlen = anum;
|
|
|
|
h_u16_to_le(pm->wid, le_to_h_u16(pm->wid) + 1); /* transaction ID */
|
|
|
|
hdr->wlen = hwords;
|
|
|
|
|
|
|
|
hdr->rlen = words;
|
|
|
|
|
|
|
|
pm->wid++; /* transaction ID */
|
|
|
|
|
|
|
|
waddr += 2; /* waddr past header */
|
|
|
|
waddr += 2; /* waddr past header */
|
|
|
|
/* TDI/TMS data follows as 32 bit word pairs {TMS,TDI} */
|
|
|
|
/* TDI/TMS data follows as 32 bit word pairs {TMS,TDI} */
|
|
|
|
pm->wd8[4 * waddr] = (tdi ? (tdi[0] << num_pre) : 0);
|
|
|
|
pm->wd8[4 * waddr] = (tdi ? (tdi[0] << num_pre) : 0);
|
|
|
@ -615,19 +712,102 @@ static int vdebug_jtag_shift_tap(int hsock, struct vd_shm *pm, uint8_t num_pre,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (tdo) {
|
|
|
|
if (tdo) {
|
|
|
|
pm->rwords += words; /* keep track of the words to read */
|
|
|
|
struct vd_rdata *rd;
|
|
|
|
vdc.tdo = tdo;
|
|
|
|
if (le_to_h_u16(pm->rwords) == 0) {
|
|
|
|
|
|
|
|
rd = &vdc.rdataq;
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
rd = calloc(1, sizeof(struct vd_rdata));
|
|
|
|
|
|
|
|
if (!rd) /* check allocation for 24B */
|
|
|
|
|
|
|
|
return ERROR_FAIL;
|
|
|
|
|
|
|
|
list_add_tail(&rd->lh, &vdc.rdataq.lh);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
rd->rdata = tdo;
|
|
|
|
|
|
|
|
h_u16_to_le(pm->rwords, le_to_h_u16(pm->rwords) + words);/* keep track of the words to read */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
pm->wwords = waddr / 2 + hwords; /* payload size *2 to include both TDI and TMS data */
|
|
|
|
h_u16_to_le(pm->wwords, waddr / 2 + hwords); /* payload size *2 to include both TDI and TMS data */
|
|
|
|
pm->waddr++;
|
|
|
|
h_u16_to_le(pm->waddr, le_to_h_u16(pm->waddr) + 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (!waddr) /* flush issued, but buffer empty */
|
|
|
|
if (!waddr) /* flush issued, but buffer empty */
|
|
|
|
;
|
|
|
|
;
|
|
|
|
else if (!vdc.trans_last) /* buffered request */
|
|
|
|
else if (!vdc.trans_last) /* buffered request */
|
|
|
|
pm->offseth = waddr + hwords * 2; /* offset for next transaction, must be even */
|
|
|
|
h_u16_to_le(pm->offseth, waddr + hwords * 2); /* offset for next transaction, must be even */
|
|
|
|
else /* execute batch of requests */
|
|
|
|
else /* execute batch of requests */
|
|
|
|
rc = vdebug_run_jtag_queue(hsock, pm, pm->waddr);
|
|
|
|
rc = vdebug_run_jtag_queue(hsock, pm, le_to_h_u16(pm->waddr));
|
|
|
|
|
|
|
|
vdc.trans_first = vdc.trans_last; /* flush forces trans_first flag */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int vdebug_reg_write(int hsock, struct vd_shm *pm, const uint32_t reg,
|
|
|
|
|
|
|
|
const uint32_t data, uint8_t aspace, uint8_t f_last)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
uint32_t waddr;
|
|
|
|
|
|
|
|
int rc = ERROR_OK;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pm->cmd = VD_CMD_REGWRITE;
|
|
|
|
|
|
|
|
vdc.trans_last = f_last || (vdc.trans_batch == VD_BATCH_NO);
|
|
|
|
|
|
|
|
if (vdc.trans_first)
|
|
|
|
|
|
|
|
waddr = 0; /* reset buffer offset */
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
waddr = le_to_h_u16(pm->offseth); /* continue from the previous transaction */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (4 * waddr + 2 * sizeof(uint64_t) + 4 > VD_BUFFER_LEN)
|
|
|
|
|
|
|
|
vdc.trans_last = 1; /* force flush, no room for next request */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
uint64_t rhdr = ((uint64_t)reg << 32) + (1UL << 30) + (2UL << 27) + (1UL << 16) + aspace;
|
|
|
|
|
|
|
|
h_u64_to_le(&pm->wd8[4 * waddr], rhdr);
|
|
|
|
|
|
|
|
h_u32_to_le(&pm->wd8[4 * (waddr + 2)], data);
|
|
|
|
|
|
|
|
h_u16_to_le(pm->wid, le_to_h_u16(pm->wid) + 1);
|
|
|
|
|
|
|
|
h_u16_to_le(pm->wwords, waddr + 3);
|
|
|
|
|
|
|
|
h_u16_to_le(pm->waddr, le_to_h_u16(pm->waddr) + 1);
|
|
|
|
|
|
|
|
if (!vdc.trans_last) /* buffered request */
|
|
|
|
|
|
|
|
h_u16_to_le(pm->offseth, waddr + 3);
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
rc = vdebug_run_reg_queue(hsock, pm, le_to_h_u16(pm->waddr));
|
|
|
|
|
|
|
|
vdc.trans_first = vdc.trans_last; /* flush forces trans_first flag */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int vdebug_reg_read(int hsock, struct vd_shm *pm, const uint32_t reg,
|
|
|
|
|
|
|
|
uint32_t *data, uint8_t aspace, uint8_t f_last)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
uint32_t waddr;
|
|
|
|
|
|
|
|
int rc = ERROR_OK;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pm->cmd = VD_CMD_REGREAD;
|
|
|
|
|
|
|
|
vdc.trans_last = f_last || (vdc.trans_batch == VD_BATCH_NO);
|
|
|
|
|
|
|
|
if (vdc.trans_first)
|
|
|
|
|
|
|
|
waddr = 0; /* reset buffer offset */
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
waddr = le_to_h_u16(pm->offseth); /* continue from the previous transaction */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (4 * waddr + 2 * sizeof(uint64_t) + 4 > VD_BUFFER_LEN)
|
|
|
|
|
|
|
|
vdc.trans_last = 1; /* force flush, no room for next request */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
uint64_t rhdr = ((uint64_t)reg << 32) + (2UL << 30) + (2UL << 27) + ((data ? 1UL : 0UL) << 16) + aspace;
|
|
|
|
|
|
|
|
h_u64_to_le(&pm->wd8[4 * waddr], rhdr);
|
|
|
|
|
|
|
|
h_u16_to_le(pm->wid, le_to_h_u16(pm->wid) + 1);
|
|
|
|
|
|
|
|
if (data) {
|
|
|
|
|
|
|
|
struct vd_rdata *rd;
|
|
|
|
|
|
|
|
if (le_to_h_u16(pm->rwords) == 0) {
|
|
|
|
|
|
|
|
rd = &vdc.rdataq;
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
rd = calloc(1, sizeof(struct vd_rdata));
|
|
|
|
|
|
|
|
if (!rd) /* check allocation for 24B */
|
|
|
|
|
|
|
|
return ERROR_FAIL;
|
|
|
|
|
|
|
|
list_add_tail(&rd->lh, &vdc.rdataq.lh);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
rd->rdata = (uint8_t *)data;
|
|
|
|
|
|
|
|
h_u16_to_le(pm->rwords, le_to_h_u16(pm->rwords) + 1);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
h_u16_to_le(pm->wwords, waddr + 2);
|
|
|
|
|
|
|
|
h_u16_to_le(pm->waddr, le_to_h_u16(pm->waddr) + 1);
|
|
|
|
|
|
|
|
if (!vdc.trans_last) /* buffered request */
|
|
|
|
|
|
|
|
h_u16_to_le(pm->offseth, waddr + 2);
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
rc = vdebug_run_reg_queue(hsock, pm, le_to_h_u16(pm->waddr));
|
|
|
|
vdc.trans_first = vdc.trans_last; /* flush forces trans_first flag */
|
|
|
|
vdc.trans_first = vdc.trans_last; /* flush forces trans_first flag */
|
|
|
|
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
return rc;
|
|
|
@ -641,19 +821,19 @@ static int vdebug_mem_open(int hsock, struct vd_shm *pm, const char *path, uint8
|
|
|
|
return ERROR_OK;
|
|
|
|
return ERROR_OK;
|
|
|
|
|
|
|
|
|
|
|
|
pm->cmd = VD_CMD_MEMOPEN;
|
|
|
|
pm->cmd = VD_CMD_MEMOPEN;
|
|
|
|
pm->wbytes = strlen(path) + 1; /* includes terminating 0 */
|
|
|
|
h_u16_to_le(pm->wbytes, strlen(path) + 1); /* includes terminating 0 */
|
|
|
|
pm->rbytes = 8;
|
|
|
|
h_u16_to_le(pm->rbytes, 8);
|
|
|
|
pm->wwords = 0;
|
|
|
|
h_u16_to_le(pm->wwords, 0);
|
|
|
|
pm->rwords = 0;
|
|
|
|
h_u16_to_le(pm->rwords, 0);
|
|
|
|
memcpy(pm->wd8, path, pm->wbytes);
|
|
|
|
memcpy(pm->wd8, path, le_to_h_u16(pm->wbytes));
|
|
|
|
rc = vdebug_wait_server(hsock, pm);
|
|
|
|
rc = vdebug_wait_server(hsock, pm);
|
|
|
|
if (rc) {
|
|
|
|
if (rc) {
|
|
|
|
LOG_ERROR("0x%x opening memory %s", rc, path);
|
|
|
|
LOG_ERROR("0x%x opening memory %s", rc, path);
|
|
|
|
} else if (ndx != pm->rd16[1]) {
|
|
|
|
} else if (ndx != pm->rd8[2]) {
|
|
|
|
LOG_WARNING("Invalid memory index %" PRIu16 " returned. Direct memory access disabled", pm->rd16[1]);
|
|
|
|
LOG_WARNING("Invalid memory index %" PRIu16 " returned. Direct memory access disabled", pm->rd8[2]);
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
vdc.mem_width[ndx] = pm->rd16[0] / 8; /* memory width in bytes */
|
|
|
|
vdc.mem_width[ndx] = le_to_h_u16(&pm->rd8[0]) / 8; /* memory width in bytes */
|
|
|
|
vdc.mem_depth[ndx] = pm->rd32[1]; /* memory depth in words */
|
|
|
|
vdc.mem_depth[ndx] = le_to_h_u32(&pm->rd8[4]); /* memory depth in words */
|
|
|
|
LOG_DEBUG("%" PRIx8 ": %s memory %" PRIu32 "x%" PRIu32 "B, buffer %" PRIu32 "x%" PRIu32 "B", ndx, path,
|
|
|
|
LOG_DEBUG("%" PRIx8 ": %s memory %" PRIu32 "x%" PRIu32 "B, buffer %" PRIu32 "x%" PRIu32 "B", ndx, path,
|
|
|
|
vdc.mem_depth[ndx], vdc.mem_width[ndx], VD_BUFFER_LEN / vdc.mem_width[ndx], vdc.mem_width[ndx]);
|
|
|
|
vdc.mem_depth[ndx], vdc.mem_width[ndx], VD_BUFFER_LEN / vdc.mem_width[ndx], vdc.mem_width[ndx]);
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -664,15 +844,16 @@ static int vdebug_mem_open(int hsock, struct vd_shm *pm, const char *path, uint8
|
|
|
|
static void vdebug_mem_close(int hsock, struct vd_shm *pm, uint8_t ndx)
|
|
|
|
static void vdebug_mem_close(int hsock, struct vd_shm *pm, uint8_t ndx)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
pm->cmd = VD_CMD_MEMCLOSE;
|
|
|
|
pm->cmd = VD_CMD_MEMCLOSE;
|
|
|
|
pm->rwdata = ndx; /* which memory */
|
|
|
|
h_u32_to_le(pm->rwdata, ndx); /* which memory */
|
|
|
|
pm->wbytes = 0;
|
|
|
|
h_u16_to_le(pm->wbytes, 0);
|
|
|
|
pm->rbytes = 0;
|
|
|
|
h_u16_to_le(pm->rbytes, 0);
|
|
|
|
pm->wwords = 0;
|
|
|
|
h_u16_to_le(pm->wwords, 0);
|
|
|
|
pm->rwords = 0;
|
|
|
|
h_u16_to_le(pm->rwords, 0);
|
|
|
|
vdebug_wait_server(hsock, pm);
|
|
|
|
vdebug_wait_server(hsock, pm);
|
|
|
|
LOG_DEBUG("%" PRIx8 ": %s", ndx, vdc.mem_path[ndx]);
|
|
|
|
LOG_DEBUG("%" PRIx8 ": %s", ndx, vdc.mem_path[ndx]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int vdebug_init(void)
|
|
|
|
static int vdebug_init(void)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
vdc.hsocket = vdebug_socket_open(vdc.server_name, vdc.server_port);
|
|
|
|
vdc.hsocket = vdebug_socket_open(vdc.server_name, vdc.server_port);
|
|
|
@ -680,7 +861,7 @@ static int vdebug_init(void)
|
|
|
|
if (!pbuf) {
|
|
|
|
if (!pbuf) {
|
|
|
|
close_socket(vdc.hsocket);
|
|
|
|
close_socket(vdc.hsocket);
|
|
|
|
vdc.hsocket = 0;
|
|
|
|
vdc.hsocket = 0;
|
|
|
|
LOG_ERROR("cannot allocate %lu bytes", sizeof(struct vd_shm));
|
|
|
|
LOG_ERROR("cannot allocate %zu bytes", sizeof(struct vd_shm));
|
|
|
|
return ERROR_FAIL;
|
|
|
|
return ERROR_FAIL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (vdc.hsocket <= 0) {
|
|
|
|
if (vdc.hsocket <= 0) {
|
|
|
@ -692,10 +873,13 @@ static int vdebug_init(void)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
vdc.trans_first = 1;
|
|
|
|
vdc.trans_first = 1;
|
|
|
|
vdc.poll_cycles = vdc.poll_max;
|
|
|
|
vdc.poll_cycles = vdc.poll_max;
|
|
|
|
uint32_t sig_mask = VD_SIG_RESET | VD_SIG_TRST | VD_SIG_TCKDIV;
|
|
|
|
uint32_t sig_mask = VD_SIG_RESET;
|
|
|
|
|
|
|
|
if (transport_is_jtag())
|
|
|
|
|
|
|
|
sig_mask |= VD_SIG_TRST | VD_SIG_TCKDIV;
|
|
|
|
|
|
|
|
|
|
|
|
int rc = vdebug_open(vdc.hsocket, pbuf, vdc.bfm_path, vdc.bfm_type, vdc.bfm_period, sig_mask);
|
|
|
|
int rc = vdebug_open(vdc.hsocket, pbuf, vdc.bfm_path, vdc.bfm_type, vdc.bfm_period, sig_mask);
|
|
|
|
if (rc != 0) {
|
|
|
|
if (rc != 0) {
|
|
|
|
LOG_ERROR("cannot connect to %s, rc 0x%x", vdc.bfm_path, rc);
|
|
|
|
LOG_ERROR("0x%x cannot connect to %s", rc, vdc.bfm_path);
|
|
|
|
close_socket(vdc.hsocket);
|
|
|
|
close_socket(vdc.hsocket);
|
|
|
|
vdc.hsocket = 0;
|
|
|
|
vdc.hsocket = 0;
|
|
|
|
free(pbuf);
|
|
|
|
free(pbuf);
|
|
|
@ -704,7 +888,7 @@ static int vdebug_init(void)
|
|
|
|
for (uint8_t i = 0; i < vdc.mem_ndx; i++) {
|
|
|
|
for (uint8_t i = 0; i < vdc.mem_ndx; i++) {
|
|
|
|
rc = vdebug_mem_open(vdc.hsocket, pbuf, vdc.mem_path[i], i);
|
|
|
|
rc = vdebug_mem_open(vdc.hsocket, pbuf, vdc.mem_path[i], i);
|
|
|
|
if (rc != 0)
|
|
|
|
if (rc != 0)
|
|
|
|
LOG_ERROR("cannot connect to %s, rc 0x%x", vdc.mem_path[i], rc);
|
|
|
|
LOG_ERROR("0x%x cannot connect to %s", rc, vdc.mem_path[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
LOG_INFO("vdebug %d connected to %s through %s:%" PRIu16,
|
|
|
|
LOG_INFO("vdebug %d connected to %s through %s:%" PRIu16,
|
|
|
@ -754,7 +938,7 @@ static int vdebug_reset(int trst, int srst)
|
|
|
|
|
|
|
|
|
|
|
|
static int vdebug_jtag_tms_seq(const uint8_t *tms, int num, uint8_t f_flush)
|
|
|
|
static int vdebug_jtag_tms_seq(const uint8_t *tms, int num, uint8_t f_flush)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
LOG_INFO("tms len:%d tms:%x", num, *(const uint32_t *)tms);
|
|
|
|
LOG_INFO("tms len:%d tms:%x", num, *tms);
|
|
|
|
|
|
|
|
|
|
|
|
return vdebug_jtag_shift_tap(vdc.hsocket, pbuf, num, *tms, 0, NULL, 0, 0, NULL, f_flush);
|
|
|
|
return vdebug_jtag_shift_tap(vdc.hsocket, pbuf, num, *tms, 0, NULL, 0, 0, NULL, f_flush);
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -811,8 +995,8 @@ static int vdebug_jtag_scan(struct scan_command *cmd, uint8_t f_flush)
|
|
|
|
uint8_t cur_tms_post = i == cmd->num_fields - 1 ? tms_post : 0;
|
|
|
|
uint8_t cur_tms_post = i == cmd->num_fields - 1 ? tms_post : 0;
|
|
|
|
uint8_t cur_flush = i == cmd->num_fields - 1 ? f_flush : 0;
|
|
|
|
uint8_t cur_flush = i == cmd->num_fields - 1 ? f_flush : 0;
|
|
|
|
rc = vdebug_jtag_shift_tap(vdc.hsocket, pbuf, cur_num_pre, cur_tms_pre,
|
|
|
|
rc = vdebug_jtag_shift_tap(vdc.hsocket, pbuf, cur_num_pre, cur_tms_pre,
|
|
|
|
cmd->fields[i].num_bits, cmd->fields[i].out_value, cur_num_post, cur_tms_post,
|
|
|
|
cmd->fields[i].num_bits, cmd->fields[i].out_value, cur_num_post, cur_tms_post,
|
|
|
|
cmd->fields[i].in_value, cur_flush);
|
|
|
|
cmd->fields[i].in_value, cur_flush);
|
|
|
|
if (rc)
|
|
|
|
if (rc)
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -913,6 +1097,61 @@ static int vdebug_jtag_execute_queue(void)
|
|
|
|
return rc;
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int vdebug_dap_connect(struct adiv5_dap *dap)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
return dap_dp_init(dap);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int vdebug_dap_send_sequence(struct adiv5_dap *dap, enum swd_special_seq seq)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
return ERROR_OK;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int vdebug_dap_queue_dp_read(struct adiv5_dap *dap, unsigned int reg, uint32_t *data)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
return vdebug_reg_read(vdc.hsocket, pbuf, (reg & DP_SELECT_DPBANK) >> 2, data, VD_ASPACE_DP, 0);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int vdebug_dap_queue_dp_write(struct adiv5_dap *dap, unsigned int reg, uint32_t data)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
return vdebug_reg_write(vdc.hsocket, pbuf, (reg & DP_SELECT_DPBANK) >> 2, data, VD_ASPACE_DP, 0);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int vdebug_dap_queue_ap_read(struct adiv5_ap *ap, unsigned int reg, uint32_t *data)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if ((reg & DP_SELECT_APBANK) != ap->dap->select) {
|
|
|
|
|
|
|
|
vdebug_reg_write(vdc.hsocket, pbuf, DP_SELECT >> 2, reg & DP_SELECT_APBANK, VD_ASPACE_DP, 0);
|
|
|
|
|
|
|
|
ap->dap->select = reg & DP_SELECT_APBANK;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
vdebug_reg_read(vdc.hsocket, pbuf, (reg & DP_SELECT_DPBANK) >> 2, NULL, VD_ASPACE_AP, 0);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return vdebug_reg_read(vdc.hsocket, pbuf, DP_RDBUFF >> 2, data, VD_ASPACE_DP, 0);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int vdebug_dap_queue_ap_write(struct adiv5_ap *ap, unsigned int reg, uint32_t data)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if ((reg & DP_SELECT_APBANK) != ap->dap->select) {
|
|
|
|
|
|
|
|
vdebug_reg_write(vdc.hsocket, pbuf, DP_SELECT >> 2, reg & DP_SELECT_APBANK, VD_ASPACE_DP, 0);
|
|
|
|
|
|
|
|
ap->dap->select = reg & DP_SELECT_APBANK;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return vdebug_reg_write(vdc.hsocket, pbuf, (reg & DP_SELECT_DPBANK) >> 2, data, VD_ASPACE_AP, 0);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int vdebug_dap_queue_ap_abort(struct adiv5_dap *dap, uint8_t *ack)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
return vdebug_reg_write(vdc.hsocket, pbuf, 0, 0x1, VD_ASPACE_AB, 0);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int vdebug_dap_run(struct adiv5_dap *dap)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if (pbuf->waddr)
|
|
|
|
|
|
|
|
return vdebug_run_reg_queue(vdc.hsocket, pbuf, le_to_h_u16(pbuf->waddr));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return ERROR_OK;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
COMMAND_HANDLER(vdebug_set_server)
|
|
|
|
COMMAND_HANDLER(vdebug_set_server)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if ((CMD_ARGC != 1) || !strchr(CMD_ARGV[0], ':'))
|
|
|
|
if ((CMD_ARGC != 1) || !strchr(CMD_ARGV[0], ':'))
|
|
|
@ -951,7 +1190,10 @@ COMMAND_HANDLER(vdebug_set_bfm)
|
|
|
|
default:
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
vdc.bfm_type = VD_BFM_JTAG;
|
|
|
|
if (transport_is_dapdirect_swd())
|
|
|
|
|
|
|
|
vdc.bfm_type = VD_BFM_SWDP;
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
vdc.bfm_type = VD_BFM_JTAG;
|
|
|
|
LOG_DEBUG("bfm_path: %s clk_period %ups", vdc.bfm_path, vdc.bfm_period);
|
|
|
|
LOG_DEBUG("bfm_path: %s clk_period %ups", vdc.bfm_path, vdc.bfm_period);
|
|
|
|
|
|
|
|
|
|
|
|
return ERROR_OK;
|
|
|
|
return ERROR_OK;
|
|
|
@ -1062,9 +1304,24 @@ static struct jtag_interface vdebug_jtag_ops = {
|
|
|
|
.execute_queue = vdebug_jtag_execute_queue,
|
|
|
|
.execute_queue = vdebug_jtag_execute_queue,
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static const struct dap_ops vdebug_dap_ops = {
|
|
|
|
|
|
|
|
.connect = vdebug_dap_connect,
|
|
|
|
|
|
|
|
.send_sequence = vdebug_dap_send_sequence,
|
|
|
|
|
|
|
|
.queue_dp_read = vdebug_dap_queue_dp_read,
|
|
|
|
|
|
|
|
.queue_dp_write = vdebug_dap_queue_dp_write,
|
|
|
|
|
|
|
|
.queue_ap_read = vdebug_dap_queue_ap_read,
|
|
|
|
|
|
|
|
.queue_ap_write = vdebug_dap_queue_ap_write,
|
|
|
|
|
|
|
|
.queue_ap_abort = vdebug_dap_queue_ap_abort,
|
|
|
|
|
|
|
|
.run = vdebug_dap_run,
|
|
|
|
|
|
|
|
.sync = NULL, /* optional */
|
|
|
|
|
|
|
|
.quit = NULL, /* optional */
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static const char *const vdebug_transports[] = { "jtag", "dapdirect_swd", NULL };
|
|
|
|
|
|
|
|
|
|
|
|
struct adapter_driver vdebug_adapter_driver = {
|
|
|
|
struct adapter_driver vdebug_adapter_driver = {
|
|
|
|
.name = "vdebug",
|
|
|
|
.name = "vdebug",
|
|
|
|
.transports = jtag_only,
|
|
|
|
.transports = vdebug_transports,
|
|
|
|
.speed = vdebug_jtag_speed,
|
|
|
|
.speed = vdebug_jtag_speed,
|
|
|
|
.khz = vdebug_jtag_khz,
|
|
|
|
.khz = vdebug_jtag_khz,
|
|
|
|
.speed_div = vdebug_jtag_div,
|
|
|
|
.speed_div = vdebug_jtag_div,
|
|
|
@ -1073,4 +1330,5 @@ struct adapter_driver vdebug_adapter_driver = {
|
|
|
|
.quit = vdebug_quit,
|
|
|
|
.quit = vdebug_quit,
|
|
|
|
.reset = vdebug_reset,
|
|
|
|
.reset = vdebug_reset,
|
|
|
|
.jtag_ops = &vdebug_jtag_ops,
|
|
|
|
.jtag_ops = &vdebug_jtag_ops,
|
|
|
|
|
|
|
|
.dap_swd_ops = &vdebug_dap_ops,
|
|
|
|
};
|
|
|
|
};
|
|
|
|