1 // SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
3 /* Copyright 2020-2022 Cadence Design Systems, Inc. */
8 * @brief the virtual debug interface provides a connection between a sw debugger
9 * and the simulated, emulated core. The openOCD client connects via TCP sockets
10 * with vdebug server and over DPI-based transactor with the emulation or simulation
11 * The vdebug debug driver supports JTAG and DAP-level transports
20 #define WIN32_LEAN_AND_MEAN
24 #include <unistd.h> /* close */
26 #ifdef HAVE_SYS_SOCKET_H
27 #include <sys/socket.h>
29 #ifdef HAVE_ARPA_INET_H
30 #include <arpa/inet.h>
47 #include "jtag/interface.h"
48 #include "jtag/commands.h"
49 #include "transport/transport.h"
50 #include "target/arm_adi_v5.h"
51 #include "helper/time_support.h"
52 #include "helper/replacements.h"
53 #include "helper/log.h"
54 #include "helper/list.h"
57 #define VD_BUFFER_LEN 4024
58 #define VD_CHEADER_LEN 24
59 #define VD_SHEADER_LEN 16
61 #define VD_MAX_MEMORIES 20
62 #define VD_POLL_INTERVAL 500
63 #define VD_SCALE_PSTOMS 1000000000
66 * @brief List of transactor types
69 VD_BFM_JTDP
= 0x0001, /* transactor DAP JTAG DP */
70 VD_BFM_SWDP
= 0x0002, /* transactor DAP SWD DP */
71 VD_BFM_AHB
= 0x0003, /* transactor AMBA AHB */
72 VD_BFM_APB
= 0x0004, /* transactor AMBA APB */
73 VD_BFM_AXI
= 0x0005, /* transactor AMBA AXI */
74 VD_BFM_JTAG
= 0x0006, /* transactor serial JTAG */
75 VD_BFM_SWD
= 0x0007, /* transactor serial SWD */
79 * @brief List of signals that can be read or written by the debugger
82 VD_SIG_TCK
= 0x0001, /* JTAG clock; tclk */
83 VD_SIG_TDI
= 0x0002, /* JTAG TDI; tdi */
84 VD_SIG_TMS
= 0x0004, /* JTAG TMS; tms */
85 VD_SIG_RESET
= 0x0008, /* DUT reset; rst */
86 VD_SIG_TRST
= 0x0010, /* JTAG Reset; trstn */
87 VD_SIG_TDO
= 0x0020, /* JTAG TDO; tdo */
88 VD_SIG_POWER
= 0x0100, /* BFM power; bfm_up */
89 VD_SIG_TCKDIV
= 0x0200, /* JTAG clock divider; tclkdiv */
90 VD_SIG_BUF
= 0x1000, /* memory buffer; mem */
94 * @brief List of errors
97 VD_ERR_NONE
= 0x0000, /* no error */
98 VD_ERR_NOT_IMPL
= 0x0100, /* feature not implemented */
99 VD_ERR_USAGE
= 0x0101, /* incorrect usage */
100 VD_ERR_PARAM
= 0x0102, /* incorrect parameter */
101 VD_ERR_CONFIG
= 0x0107, /* incorrect configuration */
102 VD_ERR_NO_MEMORY
= 0x0104, /* out of memory */
103 VD_ERR_SHM_OPEN
= 0x010a, /* cannot open shared memory */
104 VD_ERR_SHM_MAP
= 0x010b, /* cannot map shared memory */
105 VD_ERR_SOC_OPEN
= 0x011a, /* cannot open socket */
106 VD_ERR_SOC_OPT
= 0x011b, /* cannot set socket option */
107 VD_ERR_SOC_ADDR
= 0x011c, /* cannot resolve host address */
108 VD_ERR_SOC_CONN
= 0x011d, /* cannot connect to host */
109 VD_ERR_SOC_SEND
= 0x011e, /* error sending data on socket */
110 VD_ERR_SOC_RECV
= 0x011f, /* error receiving data from socket */
111 VD_ERR_LOCKED
= 0x0202, /* device locked */
112 VD_ERR_NOT_RUN
= 0x0204, /* transactor not running */
113 VD_ERR_NOT_OPEN
= 0x0205, /* transactor not open/connected */
114 VD_ERR_LICENSE
= 0x0206, /* cannot check out the license */
115 VD_ERR_VERSION
= 0x0207, /* transactor version mismatch */
116 VD_ERR_TIME_OUT
= 0x0301, /* time out, waiting */
117 VD_ERR_NO_POWER
= 0x0302, /* power out error */
118 VD_ERR_BUS_ERROR
= 0x0304, /* bus protocol error, like pslverr */
119 VD_ERR_NO_ACCESS
= 0x0306, /* no access to an object */
120 VD_ERR_INV_HANDLE
= 0x0307, /* invalid object handle */
121 VD_ERR_INV_SCOPE
= 0x0308, /* invalid scope */
127 VD_CMD_CONNECT
= 0x04,
128 VD_CMD_DISCONNECT
= 0x05,
130 VD_CMD_SIGSET
= 0x0a,
131 VD_CMD_SIGGET
= 0x0b,
132 VD_CMD_JTAGCLOCK
= 0x0f,
133 VD_CMD_REGWRITE
= 0x15,
134 VD_CMD_REGREAD
= 0x16,
135 VD_CMD_JTAGSHTAP
= 0x1a,
136 VD_CMD_MEMOPEN
= 0x21,
137 VD_CMD_MEMCLOSE
= 0x22,
138 VD_CMD_MEMWRITE
= 0x23,
155 struct { /* VD_CHEADER_LEN written by client */
156 uint8_t cmd
; /* 000; command */
157 uint8_t type
; /* 001; interface type */
158 uint8_t waddr
[2]; /* 002; write pointer */
159 uint8_t wbytes
[2]; /* 004; data bytes */
160 uint8_t rbytes
[2]; /* 006; data bytes to read */
161 uint8_t wwords
[2]; /* 008; data words */
162 uint8_t rwords
[2]; /* 00a; data words to read */
163 uint8_t rwdata
[4]; /* 00c; read/write data */
164 uint8_t offset
[4]; /* 010; address offset */
165 uint8_t offseth
[2]; /* 014; address offset 47:32 */
166 uint8_t wid
[2]; /* 016; request id*/
168 uint8_t wd8
[VD_BUFFER_LEN
]; /* 018; */
169 struct { /* VD_SHEADER_LEN written by server */
170 uint8_t rid
[2]; /* fd0: request id read */
171 uint8_t awords
[2]; /* fd2: actual data words read back */
172 uint8_t status
[4]; /* fd4; */
173 uint8_t duttime
[8]; /* fd8; */
175 uint8_t rd8
[VD_BUFFER_LEN
]; /* fe0: */
176 uint8_t state
[4]; /* 1f98; connection state */
177 uint8_t count
[4]; /* 1f9c; */
178 uint8_t dummy
[96]; /* 1fa0; 48+40B+8B; */
179 } __attribute__((packed
));
197 uint32_t mem_base
[VD_MAX_MEMORIES
];
198 uint32_t mem_size
[VD_MAX_MEMORIES
];
199 uint32_t mem_width
[VD_MAX_MEMORIES
];
200 uint32_t mem_depth
[VD_MAX_MEMORIES
];
201 uint16_t server_port
;
202 uint32_t poll_cycles
;
207 char server_name
[32];
209 char mem_path
[VD_MAX_MEMORIES
][128];
210 struct vd_rdata rdataq
;
232 static struct vd_shm
*pbuf
;
233 static struct vd_client vdc
;
235 static int vdebug_socket_error(void)
238 return WSAGetLastError();
244 static int vdebug_socket_open(char *server_addr
, uint32_t port
)
248 uint32_t buflen
= sizeof(struct vd_shm
); /* size of the send and rcv buffer */
249 struct addrinfo
*ainfo
= NULL
;
250 struct addrinfo ahint
= { 0, AF_INET
, SOCK_STREAM
, 0, 0, NULL
, NULL
, NULL
};
253 hsock
= socket(AF_INET
, SOCK_STREAM
, IPPROTO_IP
);
254 if (hsock
== INVALID_SOCKET
)
255 rc
= vdebug_socket_error();
257 uint32_t rcvwat
= VD_SHEADER_LEN
; /* size of the rcv header, as rcv min watermark */
258 hsock
= socket(AF_INET
, SOCK_STREAM
, IPPROTO_IP
);
261 else if (setsockopt(hsock
, SOL_SOCKET
, SO_RCVLOWAT
, &rcvwat
, sizeof(rcvwat
)) < 0)
264 else if (setsockopt(hsock
, SOL_SOCKET
, SO_SNDBUF
, (const char *)&buflen
, sizeof(buflen
)) < 0)
265 rc
= vdebug_socket_error();
266 else if (setsockopt(hsock
, SOL_SOCKET
, SO_RCVBUF
, (const char *)&buflen
, sizeof(buflen
)) < 0)
267 rc
= vdebug_socket_error();
270 LOG_ERROR("socket_open: cannot set socket option, error %d", rc
);
271 } else if (getaddrinfo(server_addr
, NULL
, &ahint
, &ainfo
) != 0) {
272 LOG_ERROR("socket_open: cannot resolve address %s, error %d", server_addr
, vdebug_socket_error());
273 rc
= VD_ERR_SOC_ADDR
;
275 buf_set_u32((uint8_t *)ainfo
->ai_addr
->sa_data
, 0, 16, htons(port
));
276 if (connect(hsock
, ainfo
->ai_addr
, sizeof(struct sockaddr
)) < 0) {
277 LOG_ERROR("socket_open: cannot connect to %s:%d, error %d", server_addr
, port
, vdebug_socket_error());
278 rc
= VD_ERR_SOC_CONN
;
293 static int vdebug_socket_receive(int hsock
, struct vd_shm
*pmem
)
297 int offset
= &pmem
->rid
[0] - &pmem
->cmd
;
298 int to_receive
= VD_SHEADER_LEN
+ le_to_h_u16(pmem
->rbytes
);
299 char *pb
= (char *)pmem
;
302 rc
= recv(hsock
, pb
+ offset
, to_receive
, 0);
304 LOG_WARNING("socket_receive: recv failed, error %d", rc
< 0 ? vdebug_socket_error() : 0);
309 LOG_DEBUG_IO("socket_receive: received %d, to receive %d", rc
, to_receive
);
311 } while (to_receive
);
316 static int vdebug_socket_send(int hsock
, struct vd_shm
*pmem
)
318 int rc
= send(hsock
, (const char *)&pmem
->cmd
, VD_CHEADER_LEN
+ le_to_h_u16(pmem
->wbytes
), 0);
320 LOG_WARNING("socket_send: send failed, error %d", vdebug_socket_error());
322 LOG_DEBUG_IO("socket_send: sent %d, to send 0", rc
);
327 static uint32_t vdebug_wait_server(int hsock
, struct vd_shm
*pmem
)
330 return VD_ERR_SOC_OPEN
;
332 int st
= vdebug_socket_send(hsock
, pmem
);
334 return VD_ERR_SOC_SEND
;
336 int rd
= vdebug_socket_receive(hsock
, pmem
);
338 return VD_ERR_SOC_RECV
;
340 int rc
= le_to_h_u32(pmem
->status
);
341 LOG_DEBUG_IO("wait_server: cmd %02" PRIx8
" done, sent %d, rcvd %d, status %d",
342 pmem
->cmd
, st
, rd
, rc
);
347 int vdebug_run_jtag_queue(int hsock
, struct vd_shm
*pm
, unsigned int count
)
349 uint8_t num_pre
, num_post
, tdi
, tms
;
350 unsigned int num
, anum
, bytes
, hwords
, words
;
351 unsigned int req
, waddr
, rwords
;
358 req
= 0; /* beginning of request */
361 h_u16_to_le(pm
->wbytes
, le_to_h_u16(pm
->wwords
) * vdc
.buf_width
);
362 h_u16_to_le(pm
->rbytes
, le_to_h_u16(pm
->rwords
) * vdc
.buf_width
);
364 rc
= vdebug_wait_server(hsock
, pm
);
365 while (!rc
&& (req
< count
)) { /* loop over requests to read data and print out */
366 jhdr
= le_to_h_u64(&pm
->wd8
[waddr
* 4]);
368 hwords
= (jhdr
>> 32) & 0xffff;
369 anum
= jhdr
& 0xffffff;
370 num_pre
= (jhdr
>> 27) & 0x7;
371 num_post
= (jhdr
>> 24) & 0x7;
373 num
= anum
- num_pre
- num_post
+ 1;
375 num
= anum
- num_pre
;
376 bytes
= (num
+ 7) / 8;
377 vdc
.trans_last
= (req
+ 1) < count
? 0 : 1;
378 vdc
.trans_first
= waddr
? 0 : 1;
379 if (((jhdr
>> 30) & 0x3) == 3) { /* cmd is read */
384 rd
= list_first_entry(&vdc
.rdataq
.lh
, struct vd_rdata
, lh
);
389 for (unsigned int j
= 0; j
< bytes
; j
++) {
390 tdo
[j
] = (pm
->rd8
[rwords
* 8 + j
] >> num_pre
) | (pm
->rd8
[rwords
* 8 + j
+ 1] << (8 - num_pre
));
391 LOG_DEBUG_IO("%04x D0[%02x]:%02x", le_to_h_u16(pm
->wid
) - count
+ req
, j
, tdo
[j
]);
393 rwords
+= words
; /* read data offset */
397 waddr
+= sizeof(uint64_t) / 4; /* waddr past header */
398 tdi
= (pm
->wd8
[waddr
* 4] >> num_pre
) | (pm
->wd8
[waddr
* 4 + 1] << (8 - num_pre
));
399 tms
= (pm
->wd8
[waddr
* 4 + 4] >> num_pre
) | (pm
->wd8
[waddr
* 4 + 4 + 1] << (8 - num_pre
));
400 LOG_DEBUG_IO("%04x L:%02d O:%05x @%03x DI:%02x MS:%02x DO:%02x",
401 le_to_h_u16(pm
->wid
) - count
+ req
, num
, (vdc
.trans_first
<< 14) | (vdc
.trans_last
<< 15),
402 waddr
- 2, tdi
, tms
, (tdo
? tdo
[0] : 0xdd));
403 waddr
+= hwords
* 2; /* start of next request */
408 LOG_ERROR("0x%x executing transaction", rc
);
413 vdc
.targ_time
+= (uint32_t)(te
- ts
);
414 h_u16_to_le(pm
->offseth
, 0); /* reset buffer write address */
415 h_u32_to_le(pm
->offset
, 0);
416 h_u16_to_le(pm
->rwords
, 0);
417 h_u16_to_le(pm
->waddr
, 0);
418 assert(list_empty(&vdc
.rdataq
.lh
));/* list should be empty after run queue */
423 int vdebug_run_reg_queue(int hsock
, struct vd_shm
*pm
, unsigned int count
)
425 unsigned int num
, awidth
, wwidth
;
426 unsigned int req
, waddr
, rwords
;
435 req
= 0; /* beginning of request */
438 h_u16_to_le(pm
->wbytes
, le_to_h_u16(pm
->wwords
) * vdc
.buf_width
);
439 h_u16_to_le(pm
->rbytes
, le_to_h_u16(pm
->rwords
) * vdc
.buf_width
);
441 rc
= vdebug_wait_server(hsock
, pm
);
442 while (!rc
&& (req
< count
)) { /* loop over requests to read data and print out */
443 rhdr
= le_to_h_u64(&pm
->wd8
[waddr
* 4]);
444 addr
= rhdr
>> 32; /* reconstruct data for a single request */
445 num
= (rhdr
>> 16) & 0x7ff;
447 awidth
= (1 << ((rhdr
>> 27) & 0x7));
448 wwidth
= (awidth
+ vdc
.buf_width
- 1) / vdc
.buf_width
;
449 vdc
.trans_last
= (req
+ 1) < count
? 0 : 1;
450 vdc
.trans_first
= waddr
? 0 : 1;
451 if (((rhdr
>> 30) & 0x3) == 2) { /* cmd is read */
457 rd
= list_first_entry(&vdc
.rdataq
.lh
, struct vd_rdata
, lh
);
462 for (unsigned int j
= 0; j
< num
; j
++)
463 memcpy(&data
[j
* awidth
], &pm
->rd8
[(rwords
+ j
) * awidth
], awidth
);
465 LOG_DEBUG_IO("read %04x AS:%02x RG:%02x O:%05x @%03x D:%08x", le_to_h_u16(pm
->wid
) - count
+ req
,
466 aspace
, addr
, (vdc
.trans_first
<< 14) | (vdc
.trans_last
<< 15), waddr
,
467 (num
? le_to_h_u32(&pm
->rd8
[rwords
* 4]) : 0xdead));
468 rwords
+= num
* wwidth
;
469 waddr
+= sizeof(uint64_t) / 4; /* waddr past header */
471 LOG_DEBUG_IO("write %04x AS:%02x RG:%02x O:%05x @%03x D:%08x", le_to_h_u16(pm
->wid
) - count
+ req
,
472 aspace
, addr
, (vdc
.trans_first
<< 14) | (vdc
.trans_last
<< 15), waddr
,
473 le_to_h_u32(&pm
->wd8
[(waddr
+ num
+ 1) * 4]));
474 waddr
+= sizeof(uint64_t) / 4 + (num
* wwidth
* awidth
+ 3) / 4;
480 LOG_ERROR("0x%x executing transaction", rc
);
485 vdc
.targ_time
+= (uint32_t)(te
- ts
);
486 h_u16_to_le(pm
->offseth
, 0); /* reset buffer write address */
487 h_u32_to_le(pm
->offset
, 0);
488 h_u16_to_le(pm
->rwords
, 0);
489 h_u16_to_le(pm
->waddr
, 0);
490 assert(list_empty(&vdc
.rdataq
.lh
));/* list should be empty after run queue */
495 static int vdebug_open(int hsock
, struct vd_shm
*pm
, const char *path
,
496 uint8_t type
, uint32_t period_ps
, uint32_t sig_mask
)
498 int rc
= VD_ERR_NOT_OPEN
;
500 pm
->cmd
= VD_CMD_OPEN
;
501 h_u16_to_le(pm
->wid
, VD_VERSION
); /* client version */
502 h_u16_to_le(pm
->wbytes
, 0);
503 h_u16_to_le(pm
->rbytes
, 0);
504 h_u16_to_le(pm
->wwords
, 0);
505 h_u16_to_le(pm
->rwords
, 0);
506 rc
= vdebug_wait_server(hsock
, pm
);
507 if (rc
!= 0) { /* communication problem */
508 LOG_ERROR("0x%x connecting to server", rc
);
509 } else if (le_to_h_u16(pm
->rid
) < le_to_h_u16(pm
->wid
)) {
510 LOG_ERROR("server version %d too old for the client %d", le_to_h_u16(pm
->rid
), le_to_h_u16(pm
->wid
));
511 pm
->cmd
= VD_CMD_CLOSE
; /* let server close the connection */
512 vdebug_wait_server(hsock
, pm
);
515 pm
->cmd
= VD_CMD_CONNECT
;
516 pm
->type
= type
; /* BFM type to connect to, here JTAG */
517 h_u32_to_le(pm
->rwdata
, sig_mask
| VD_SIG_BUF
| (VD_SIG_BUF
<< 16));
518 h_u16_to_le(pm
->wbytes
, strlen(path
) + 1);
519 h_u16_to_le(pm
->rbytes
, 12);
520 h_u16_to_le(pm
->wid
, 0); /* reset wid for transaction ID */
521 h_u16_to_le(pm
->wwords
, 0);
522 h_u16_to_le(pm
->rwords
, 0);
523 memcpy(pm
->wd8
, path
, le_to_h_u16(pm
->wbytes
));
524 rc
= vdebug_wait_server(hsock
, pm
);
525 vdc
.sig_read
= le_to_h_u32(pm
->rwdata
) >> 16; /* signal read mask */
526 vdc
.sig_write
= le_to_h_u32(pm
->rwdata
); /* signal write mask */
527 vdc
.bfm_period
= period_ps
;
528 vdc
.buf_width
= le_to_h_u32(&pm
->rd8
[0]) / 8;/* access width in bytes */
529 vdc
.addr_bits
= le_to_h_u32(&pm
->rd8
[2 * 4]); /* supported address bits */
533 LOG_ERROR("0x%x connecting to BFM %s", rc
, path
);
537 INIT_LIST_HEAD(&vdc
.rdataq
.lh
);
538 LOG_DEBUG("%s type %0x, period %dps, buffer %dx%dB signals r%04xw%04x",
539 path
, type
, vdc
.bfm_period
, VD_BUFFER_LEN
/ vdc
.buf_width
,
540 vdc
.buf_width
, vdc
.sig_read
, vdc
.sig_write
);
545 static int vdebug_close(int hsock
, struct vd_shm
*pm
, uint8_t type
)
547 pm
->cmd
= VD_CMD_DISCONNECT
;
548 pm
->type
= type
; /* BFM type, here JTAG */
549 h_u16_to_le(pm
->wbytes
, 0);
550 h_u16_to_le(pm
->rbytes
, 0);
551 h_u16_to_le(pm
->wwords
, 0);
552 h_u16_to_le(pm
->rwords
, 0);
553 vdebug_wait_server(hsock
, pm
);
554 pm
->cmd
= VD_CMD_CLOSE
;
555 h_u16_to_le(pm
->wid
, VD_VERSION
); /* client version */
556 h_u16_to_le(pm
->wbytes
, 0);
557 h_u16_to_le(pm
->rbytes
, 0);
558 h_u16_to_le(pm
->wwords
, 0);
559 h_u16_to_le(pm
->rwords
, 0);
560 vdebug_wait_server(hsock
, pm
);
561 LOG_DEBUG("type %0x", type
);
566 static int vdebug_wait(int hsock
, struct vd_shm
*pm
, uint32_t cycles
)
569 pm
->cmd
= VD_CMD_WAIT
;
570 h_u16_to_le(pm
->wbytes
, 0);
571 h_u16_to_le(pm
->rbytes
, 0);
572 h_u32_to_le(pm
->rwdata
, cycles
); /* clock sycles to wait */
573 int rc
= vdebug_wait_server(hsock
, pm
);
575 LOG_ERROR("0x%x waiting %" PRIx32
" cycles", rc
, cycles
);
578 LOG_DEBUG("%d cycles", cycles
);
584 static int vdebug_sig_set(int hsock
, struct vd_shm
*pm
, uint32_t write_mask
, uint32_t value
)
586 pm
->cmd
= VD_CMD_SIGSET
;
587 h_u16_to_le(pm
->wbytes
, 0);
588 h_u16_to_le(pm
->rbytes
, 0);
589 h_u32_to_le(pm
->rwdata
, (write_mask
<< 16) | (value
& 0xffff)); /* mask and value of signals to set */
590 int rc
= vdebug_wait_server(hsock
, pm
);
592 LOG_ERROR("0x%x setting signals %04" PRIx32
, rc
, write_mask
);
596 LOG_DEBUG("setting signals %04" PRIx32
" to %04" PRIx32
, write_mask
, value
);
601 static int vdebug_jtag_clock(int hsock
, struct vd_shm
*pm
, uint32_t value
)
603 pm
->cmd
= VD_CMD_JTAGCLOCK
;
604 h_u16_to_le(pm
->wbytes
, 0);
605 h_u16_to_le(pm
->rbytes
, 0);
606 h_u32_to_le(pm
->rwdata
, value
); /* divider value */
607 int rc
= vdebug_wait_server(hsock
, pm
);
609 LOG_ERROR("0x%x setting jtag_clock", rc
);
613 LOG_DEBUG("setting jtag clock divider to %" PRIx32
, value
);
618 static int vdebug_jtag_shift_tap(int hsock
, struct vd_shm
*pm
, uint8_t num_pre
,
619 const uint8_t tms_pre
, uint32_t num
, const uint8_t *tdi
,
620 uint8_t num_post
, const uint8_t tms_post
, uint8_t *tdo
,
623 const uint32_t tobits
= 8;
624 uint16_t bytes
, hwords
, anum
, words
, waddr
;
627 pm
->cmd
= VD_CMD_JTAGSHTAP
;
628 vdc
.trans_last
= f_last
|| (vdc
.trans_batch
== VD_BATCH_NO
);
630 waddr
= 0; /* reset buffer offset */
632 waddr
= le_to_h_u32(pm
->offseth
); /* continue from the previous transaction */
633 if (num_post
) /* actual number of bits to shift */
634 anum
= num
+ num_pre
+ num_post
- 1;
636 anum
= num
+ num_pre
;
637 hwords
= (anum
+ 4 * vdc
.buf_width
- 1) / (4 * vdc
.buf_width
); /* in 4B TDI/TMS words */
638 words
= (hwords
+ 1) / 2; /* in 8B TDO words to read */
639 bytes
= (num
+ 7) / 8; /* data only portion in bytes */
640 /* buffer overflow check and flush */
641 if (4 * waddr
+ sizeof(uint64_t) + 8 * hwords
+ 64 > VD_BUFFER_LEN
) {
642 vdc
.trans_last
= 1; /* force flush within 64B of buffer end */
643 } else if (4 * waddr
+ sizeof(uint64_t) + 8 * hwords
> VD_BUFFER_LEN
) {
644 /* this req does not fit, discard it */
645 LOG_ERROR("%04x L:%02d O:%05x @%04x too many bits to shift",
646 le_to_h_u16(pm
->wid
), anum
, (vdc
.trans_first
<< 14) | (vdc
.trans_last
<< 15), waddr
);
651 uint16_t i
, j
; /* portability requires to use bit operations for 8B JTAG header */
652 uint64_t jhdr
= (tdo
? ((uint64_t)(words
) << 48) : 0) + ((uint64_t)(hwords
) << 32) +
653 ((tdo
? 3UL : 1UL) << 30) + (num_pre
<< 27) + (num_post
<< 24) + anum
;
654 h_u64_to_le(&pm
->wd8
[4 * waddr
], jhdr
);
656 h_u16_to_le(pm
->wid
, le_to_h_u16(pm
->wid
) + 1); /* transaction ID */
657 waddr
+= 2; /* waddr past header */
658 /* TDI/TMS data follows as 32 bit word pairs {TMS,TDI} */
659 pm
->wd8
[4 * waddr
] = (tdi
? (tdi
[0] << num_pre
) : 0);
660 pm
->wd8
[4 * waddr
+ 4] = tms_pre
; /* init with tms_pre */
661 if (num
+ num_pre
<= 8) /* and tms_post for num <=4 */
662 pm
->wd8
[4 * waddr
+ 4] |= (tms_post
<< (num
+ num_pre
- 1));
663 for (i
= 1, j
= 4 * waddr
; i
< bytes
; i
++) {
664 if (i
== bytes
- 1 && num
+ num_pre
<= bytes
* tobits
)
665 pm
->wd8
[j
+ i
+ 4] = tms_post
<< ((num
+ num_pre
- 1) % 8);
667 pm
->wd8
[j
+ i
+ 4] = 0x0;/* placing 4 bytes of TMS bits into high word */
668 if (!tdi
) /* placing 4 bytes of TDI bits into low word */
669 pm
->wd8
[j
+ i
] = 0x0;
671 pm
->wd8
[j
+ i
] = (tdi
[i
] << num_pre
) | (tdi
[i
- 1] >> (8 - num_pre
));
677 if (num
+ num_pre
> bytes
* tobits
) /* in case 1 additional byte needed for TDI */
678 pm
->wd8
[j
+ i
] = (tdi
[i
- 1] >> (8 - num_pre
)); /* put last TDI bits there */
680 if (num
+ num_pre
<= bytes
* tobits
) { /* in case no or 1 additional byte needed */
681 pm
->wd8
[j
+ i
+ 4] = tms_post
>> (8 - (num
+ num_pre
- 1) % 8); /* may need to add higher part */
682 /* in case exactly 1 additional byte needed */
683 } else if (num
+ num_pre
> bytes
* tobits
&& anum
<= (bytes
+ 1) * tobits
) {
684 pm
->wd8
[j
+ i
+ 4] = tms_post
<< ((num
+ num_pre
- 1) % 8); /* add whole tms_post */
685 } else { /* in case 2 additional bytes, tms_post split */
686 pm
->wd8
[j
+ i
+ 4] = tms_post
<< ((num
+ num_pre
- 1) % 8);/* add lower part of tms_post */
687 if (i
% 4 == 3) /* next byte is in the next 32b word */
688 pm
->wd8
[j
+ i
+ 4 + 5] = tms_post
>> (8 - (num
+ num_pre
- 1) % 8); /* and higher part */
689 else /* next byte is in the same 32b word */
690 pm
->wd8
[j
+ i
+ 4 + 1] = tms_post
>> (8 - (num
+ num_pre
- 1) % 8); /* and higher part */
695 if (le_to_h_u16(pm
->rwords
) == 0) {
698 rd
= calloc(1, sizeof(struct vd_rdata
));
699 if (!rd
) /* check allocation for 24B */
701 list_add_tail(&rd
->lh
, &vdc
.rdataq
.lh
);
704 h_u16_to_le(pm
->rwords
, le_to_h_u16(pm
->rwords
) + words
);/* keep track of the words to read */
706 h_u16_to_le(pm
->wwords
, waddr
/ 2 + hwords
); /* payload size *2 to include both TDI and TMS data */
707 h_u16_to_le(pm
->waddr
, le_to_h_u16(pm
->waddr
) + 1);
710 if (!waddr
) /* flush issued, but buffer empty */
712 else if (!vdc
.trans_last
) /* buffered request */
713 h_u16_to_le(pm
->offseth
, waddr
+ hwords
* 2); /* offset for next transaction, must be even */
714 else /* execute batch of requests */
715 rc
= vdebug_run_jtag_queue(hsock
, pm
, le_to_h_u16(pm
->waddr
));
716 vdc
.trans_first
= vdc
.trans_last
; /* flush forces trans_first flag */
721 static int vdebug_reg_write(int hsock
, struct vd_shm
*pm
, const uint32_t reg
,
722 const uint32_t data
, uint8_t aspace
, uint8_t f_last
)
727 pm
->cmd
= VD_CMD_REGWRITE
;
728 vdc
.trans_last
= f_last
|| (vdc
.trans_batch
== VD_BATCH_NO
);
730 waddr
= 0; /* reset buffer offset */
732 waddr
= le_to_h_u16(pm
->offseth
); /* continue from the previous transaction */
734 if (4 * waddr
+ 2 * sizeof(uint64_t) + 4 > VD_BUFFER_LEN
)
735 vdc
.trans_last
= 1; /* force flush, no room for next request */
737 uint64_t rhdr
= ((uint64_t)reg
<< 32) + (1UL << 30) + (2UL << 27) + (1UL << 16) + aspace
;
738 h_u64_to_le(&pm
->wd8
[4 * waddr
], rhdr
);
739 h_u32_to_le(&pm
->wd8
[4 * (waddr
+ 2)], data
);
740 h_u16_to_le(pm
->wid
, le_to_h_u16(pm
->wid
) + 1);
741 h_u16_to_le(pm
->wwords
, waddr
+ 3);
742 h_u16_to_le(pm
->waddr
, le_to_h_u16(pm
->waddr
) + 1);
743 if (!vdc
.trans_last
) /* buffered request */
744 h_u16_to_le(pm
->offseth
, waddr
+ 3);
746 rc
= vdebug_run_reg_queue(hsock
, pm
, le_to_h_u16(pm
->waddr
));
747 vdc
.trans_first
= vdc
.trans_last
; /* flush forces trans_first flag */
752 static int vdebug_reg_read(int hsock
, struct vd_shm
*pm
, const uint32_t reg
,
753 uint32_t *data
, uint8_t aspace
, uint8_t f_last
)
758 pm
->cmd
= VD_CMD_REGREAD
;
759 vdc
.trans_last
= f_last
|| (vdc
.trans_batch
== VD_BATCH_NO
);
761 waddr
= 0; /* reset buffer offset */
763 waddr
= le_to_h_u16(pm
->offseth
); /* continue from the previous transaction */
765 if (4 * waddr
+ 2 * sizeof(uint64_t) + 4 > VD_BUFFER_LEN
)
766 vdc
.trans_last
= 1; /* force flush, no room for next request */
768 uint64_t rhdr
= ((uint64_t)reg
<< 32) + (2UL << 30) + (2UL << 27) + ((data
? 1UL : 0UL) << 16) + aspace
;
769 h_u64_to_le(&pm
->wd8
[4 * waddr
], rhdr
);
770 h_u16_to_le(pm
->wid
, le_to_h_u16(pm
->wid
) + 1);
773 if (le_to_h_u16(pm
->rwords
) == 0) {
776 rd
= calloc(1, sizeof(struct vd_rdata
));
777 if (!rd
) /* check allocation for 24B */
779 list_add_tail(&rd
->lh
, &vdc
.rdataq
.lh
);
781 rd
->rdata
= (uint8_t *)data
;
782 h_u16_to_le(pm
->rwords
, le_to_h_u16(pm
->rwords
) + 1);
784 h_u16_to_le(pm
->wwords
, waddr
+ 2);
785 h_u16_to_le(pm
->waddr
, le_to_h_u16(pm
->waddr
) + 1);
786 if (!vdc
.trans_last
) /* buffered request */
787 h_u16_to_le(pm
->offseth
, waddr
+ 2);
789 rc
= vdebug_run_reg_queue(hsock
, pm
, le_to_h_u16(pm
->waddr
));
790 vdc
.trans_first
= vdc
.trans_last
; /* flush forces trans_first flag */
795 static int vdebug_mem_open(int hsock
, struct vd_shm
*pm
, const char *path
, uint8_t ndx
)
802 pm
->cmd
= VD_CMD_MEMOPEN
;
803 h_u16_to_le(pm
->wbytes
, strlen(path
) + 1); /* includes terminating 0 */
804 h_u16_to_le(pm
->rbytes
, 8);
805 h_u16_to_le(pm
->wwords
, 0);
806 h_u16_to_le(pm
->rwords
, 0);
807 memcpy(pm
->wd8
, path
, le_to_h_u16(pm
->wbytes
));
808 rc
= vdebug_wait_server(hsock
, pm
);
810 LOG_ERROR("0x%x opening memory %s", rc
, path
);
811 } else if (ndx
!= pm
->rd8
[2]) {
812 LOG_WARNING("Invalid memory index %" PRIu16
" returned. Direct memory access disabled", pm
->rd8
[2]);
814 vdc
.mem_width
[ndx
] = le_to_h_u16(&pm
->rd8
[0]) / 8; /* memory width in bytes */
815 vdc
.mem_depth
[ndx
] = le_to_h_u32(&pm
->rd8
[4]); /* memory depth in words */
816 LOG_DEBUG("%" PRIx8
": %s memory %" PRIu32
"x%" PRIu32
"B, buffer %" PRIu32
"x%" PRIu32
"B", ndx
, path
,
817 vdc
.mem_depth
[ndx
], vdc
.mem_width
[ndx
], VD_BUFFER_LEN
/ vdc
.mem_width
[ndx
], vdc
.mem_width
[ndx
]);
823 static void vdebug_mem_close(int hsock
, struct vd_shm
*pm
, uint8_t ndx
)
825 pm
->cmd
= VD_CMD_MEMCLOSE
;
826 h_u32_to_le(pm
->rwdata
, ndx
); /* which memory */
827 h_u16_to_le(pm
->wbytes
, 0);
828 h_u16_to_le(pm
->rbytes
, 0);
829 h_u16_to_le(pm
->wwords
, 0);
830 h_u16_to_le(pm
->rwords
, 0);
831 vdebug_wait_server(hsock
, pm
);
832 LOG_DEBUG("%" PRIx8
": %s", ndx
, vdc
.mem_path
[ndx
]);
836 static int vdebug_init(void)
838 vdc
.hsocket
= vdebug_socket_open(vdc
.server_name
, vdc
.server_port
);
839 pbuf
= calloc(1, sizeof(struct vd_shm
));
841 close_socket(vdc
.hsocket
);
843 LOG_ERROR("cannot allocate %zu bytes", sizeof(struct vd_shm
));
846 if (vdc
.hsocket
<= 0) {
849 LOG_ERROR("cannot connect to vdebug server %s:%" PRIu16
,
850 vdc
.server_name
, vdc
.server_port
);
854 vdc
.poll_cycles
= vdc
.poll_max
;
855 uint32_t sig_mask
= VD_SIG_RESET
;
856 if (transport_is_jtag())
857 sig_mask
|= VD_SIG_TRST
| VD_SIG_TCKDIV
;
859 int rc
= vdebug_open(vdc
.hsocket
, pbuf
, vdc
.bfm_path
, vdc
.bfm_type
, vdc
.bfm_period
, sig_mask
);
861 LOG_ERROR("0x%x cannot connect to %s", rc
, vdc
.bfm_path
);
862 close_socket(vdc
.hsocket
);
867 for (uint8_t i
= 0; i
< vdc
.mem_ndx
; i
++) {
868 rc
= vdebug_mem_open(vdc
.hsocket
, pbuf
, vdc
.mem_path
[i
], i
);
870 LOG_ERROR("0x%x cannot connect to %s", rc
, vdc
.mem_path
[i
]);
873 LOG_INFO("vdebug %d connected to %s through %s:%" PRIu16
,
874 VD_VERSION
, vdc
.bfm_path
, vdc
.server_name
, vdc
.server_port
);
880 static int vdebug_quit(void)
882 for (uint8_t i
= 0; i
< vdc
.mem_ndx
; i
++)
883 if (vdc
.mem_width
[i
])
884 vdebug_mem_close(vdc
.hsocket
, pbuf
, i
);
885 int rc
= vdebug_close(vdc
.hsocket
, pbuf
, vdc
.bfm_type
);
886 LOG_INFO("vdebug %d disconnected from %s through %s:%" PRIu16
" rc:%d", VD_VERSION
,
887 vdc
.bfm_path
, vdc
.server_name
, vdc
.server_port
, rc
);
889 close_socket(vdc
.hsocket
);
896 static int vdebug_reset(int trst
, int srst
)
898 uint16_t sig_val
= 0xffff;
899 uint16_t sig_mask
= 0;
901 sig_mask
|= VD_SIG_RESET
;
903 sig_val
&= ~VD_SIG_RESET
;/* active low */
904 if (transport_is_jtag()) {
905 sig_mask
|= VD_SIG_TRST
;
907 sig_val
&= ~VD_SIG_TRST
; /* active low */
910 LOG_INFO("rst trst:%d srst:%d mask:%" PRIx16
" val:%" PRIx16
, trst
, srst
, sig_mask
, sig_val
);
911 int rc
= vdebug_sig_set(vdc
.hsocket
, pbuf
, sig_mask
, sig_val
);
913 rc
= vdebug_wait(vdc
.hsocket
, pbuf
, 20); /* 20 clock cycles pulse */
918 static int vdebug_jtag_tms_seq(const uint8_t *tms
, int num
, uint8_t f_flush
)
920 LOG_INFO("tms len:%d tms:%x", num
, *tms
);
922 return vdebug_jtag_shift_tap(vdc
.hsocket
, pbuf
, num
, *tms
, 0, NULL
, 0, 0, NULL
, f_flush
);
925 static int vdebug_jtag_path_move(struct pathmove_command
*cmd
, uint8_t f_flush
)
927 uint8_t tms
[DIV_ROUND_UP(cmd
->num_states
, 8)];
928 LOG_INFO("path num states %d", cmd
->num_states
);
930 memset(tms
, 0, DIV_ROUND_UP(cmd
->num_states
, 8));
932 for (uint8_t i
= 0; i
< cmd
->num_states
; i
++) {
933 if (tap_state_transition(tap_get_state(), true) == cmd
->path
[i
])
934 buf_set_u32(tms
, i
, 1, 1);
935 tap_set_state(cmd
->path
[i
]);
938 return vdebug_jtag_tms_seq(tms
, cmd
->num_states
, f_flush
);
941 static int vdebug_jtag_tlr(tap_state_t state
, uint8_t f_flush
)
945 uint8_t cur
= tap_get_state();
946 uint8_t tms_pre
= tap_get_tms_path(cur
, state
);
947 uint8_t num_pre
= tap_get_tms_path_len(cur
, state
);
948 LOG_INFO("tlr from %" PRIx8
" to %" PRIx8
, cur
, state
);
950 rc
= vdebug_jtag_shift_tap(vdc
.hsocket
, pbuf
, num_pre
, tms_pre
, 0, NULL
, 0, 0, NULL
, f_flush
);
951 tap_set_state(state
);
957 static int vdebug_jtag_scan(struct scan_command
*cmd
, uint8_t f_flush
)
961 uint8_t cur
= tap_get_state();
962 uint8_t state
= cmd
->ir_scan
? TAP_IRSHIFT
: TAP_DRSHIFT
;
963 uint8_t tms_pre
= tap_get_tms_path(cur
, state
);
964 uint8_t num_pre
= tap_get_tms_path_len(cur
, state
);
965 uint8_t tms_post
= tap_get_tms_path(state
, cmd
->end_state
);
966 uint8_t num_post
= tap_get_tms_path_len(state
, cmd
->end_state
);
967 int num_bits
= jtag_scan_size(cmd
);
968 LOG_DEBUG("scan len:%d fields:%d ir/!dr:%d state cur:%x end:%x",
969 num_bits
, cmd
->num_fields
, cmd
->ir_scan
, cur
, cmd
->end_state
);
970 for (int i
= 0; i
< cmd
->num_fields
; i
++) {
971 uint8_t cur_num_pre
= i
== 0 ? num_pre
: 0;
972 uint8_t cur_tms_pre
= i
== 0 ? tms_pre
: 0;
973 uint8_t cur_num_post
= i
== cmd
->num_fields
- 1 ? num_post
: 0;
974 uint8_t cur_tms_post
= i
== cmd
->num_fields
- 1 ? tms_post
: 0;
975 uint8_t cur_flush
= i
== cmd
->num_fields
- 1 ? f_flush
: 0;
976 rc
= vdebug_jtag_shift_tap(vdc
.hsocket
, pbuf
, cur_num_pre
, cur_tms_pre
,
977 cmd
->fields
[i
].num_bits
, cmd
->fields
[i
].out_value
, cur_num_post
, cur_tms_post
,
978 cmd
->fields
[i
].in_value
, cur_flush
);
983 if (cur
!= cmd
->end_state
)
984 tap_set_state(cmd
->end_state
);
989 static int vdebug_jtag_runtest(int cycles
, tap_state_t state
, uint8_t f_flush
)
991 uint8_t cur
= tap_get_state();
992 uint8_t tms_pre
= tap_get_tms_path(cur
, state
);
993 uint8_t num_pre
= tap_get_tms_path_len(cur
, state
);
994 LOG_DEBUG("idle len:%d state cur:%x end:%x", cycles
, cur
, state
);
995 int rc
= vdebug_jtag_shift_tap(vdc
.hsocket
, pbuf
, num_pre
, tms_pre
, cycles
, NULL
, 0, 0, NULL
, f_flush
);
997 tap_set_state(state
);
1002 static int vdebug_jtag_stableclocks(int num
, uint8_t f_flush
)
1004 LOG_INFO("stab len:%d state cur:%x", num
, tap_get_state());
1006 return vdebug_jtag_shift_tap(vdc
.hsocket
, pbuf
, 0, 0, num
, NULL
, 0, 0, NULL
, f_flush
);
1009 static int vdebug_sleep(int us
)
1011 LOG_INFO("sleep %d us", us
);
1013 return vdebug_wait(vdc
.hsocket
, pbuf
, us
/ 1000);
1016 static int vdebug_jtag_speed(int speed
)
1018 unsigned int clkmax
= VD_SCALE_PSTOMS
/ (vdc
.bfm_period
* 2); /* kHz */
1019 unsigned int divval
= clkmax
/ speed
;
1020 LOG_INFO("jclk speed:%d kHz set, BFM divider %u", speed
, divval
);
1022 return vdebug_jtag_clock(vdc
.hsocket
, pbuf
, divval
);
1025 static int vdebug_jtag_khz(int khz
, int *jtag_speed
)
1027 unsigned int clkmax
= VD_SCALE_PSTOMS
/ (vdc
.bfm_period
* 2); /* kHz */
1028 unsigned int divval
= khz
? clkmax
/ khz
: 1;
1029 *jtag_speed
= clkmax
/ divval
;
1030 LOG_DEBUG("khz speed:%d from khz:%d", *jtag_speed
, khz
);
1035 static int vdebug_jtag_div(int speed
, int *khz
)
1038 LOG_DEBUG("div khz:%d from speed:%d", *khz
, speed
);
1043 static int vdebug_jtag_execute_queue(void)
1047 for (struct jtag_command
*cmd
= jtag_command_queue
; rc
== ERROR_OK
&& cmd
; cmd
= cmd
->next
) {
1048 switch (cmd
->type
) {
1050 rc
= vdebug_jtag_runtest(cmd
->cmd
.runtest
->num_cycles
, cmd
->cmd
.runtest
->end_state
, !cmd
->next
);
1052 case JTAG_STABLECLOCKS
:
1053 rc
= vdebug_jtag_stableclocks(cmd
->cmd
.stableclocks
->num_cycles
, !cmd
->next
);
1055 case JTAG_TLR_RESET
:
1056 rc
= vdebug_jtag_tlr(cmd
->cmd
.statemove
->end_state
, !cmd
->next
);
1059 rc
= vdebug_jtag_path_move(cmd
->cmd
.pathmove
, !cmd
->next
);
1062 rc
= vdebug_jtag_tms_seq(cmd
->cmd
.tms
->bits
, cmd
->cmd
.tms
->num_bits
, !cmd
->next
);
1065 rc
= vdebug_sleep(cmd
->cmd
.sleep
->us
);
1068 rc
= vdebug_jtag_scan(cmd
->cmd
.scan
, !cmd
->next
);
1071 LOG_ERROR("Unknown JTAG command type 0x%x encountered", cmd
->type
);
1079 static int vdebug_dap_connect(struct adiv5_dap
*dap
)
1081 return dap_dp_init(dap
);
1084 static int vdebug_dap_send_sequence(struct adiv5_dap
*dap
, enum swd_special_seq seq
)
1089 static int vdebug_dap_queue_dp_read(struct adiv5_dap
*dap
, unsigned int reg
, uint32_t *data
)
1091 return vdebug_reg_read(vdc
.hsocket
, pbuf
, (reg
& DP_SELECT_DPBANK
) >> 2, data
, VD_ASPACE_DP
, 0);
1094 static int vdebug_dap_queue_dp_write(struct adiv5_dap
*dap
, unsigned int reg
, uint32_t data
)
1096 return vdebug_reg_write(vdc
.hsocket
, pbuf
, (reg
& DP_SELECT_DPBANK
) >> 2, data
, VD_ASPACE_DP
, 0);
1099 static int vdebug_dap_queue_ap_read(struct adiv5_ap
*ap
, unsigned int reg
, uint32_t *data
)
1101 if ((reg
& DP_SELECT_APBANK
) != ap
->dap
->select
) {
1102 vdebug_reg_write(vdc
.hsocket
, pbuf
, DP_SELECT
>> 2, reg
& DP_SELECT_APBANK
, VD_ASPACE_DP
, 0);
1103 ap
->dap
->select
= reg
& DP_SELECT_APBANK
;
1106 vdebug_reg_read(vdc
.hsocket
, pbuf
, (reg
& DP_SELECT_DPBANK
) >> 2, NULL
, VD_ASPACE_AP
, 0);
1108 return vdebug_reg_read(vdc
.hsocket
, pbuf
, DP_RDBUFF
>> 2, data
, VD_ASPACE_DP
, 0);
1111 static int vdebug_dap_queue_ap_write(struct adiv5_ap
*ap
, unsigned int reg
, uint32_t data
)
1113 if ((reg
& DP_SELECT_APBANK
) != ap
->dap
->select
) {
1114 vdebug_reg_write(vdc
.hsocket
, pbuf
, DP_SELECT
>> 2, reg
& DP_SELECT_APBANK
, VD_ASPACE_DP
, 0);
1115 ap
->dap
->select
= reg
& DP_SELECT_APBANK
;
1118 return vdebug_reg_write(vdc
.hsocket
, pbuf
, (reg
& DP_SELECT_DPBANK
) >> 2, data
, VD_ASPACE_AP
, 0);
1121 static int vdebug_dap_queue_ap_abort(struct adiv5_dap
*dap
, uint8_t *ack
)
1123 return vdebug_reg_write(vdc
.hsocket
, pbuf
, 0, 0x1, VD_ASPACE_AB
, 0);
1126 static int vdebug_dap_run(struct adiv5_dap
*dap
)
1129 return vdebug_run_reg_queue(vdc
.hsocket
, pbuf
, le_to_h_u16(pbuf
->waddr
));
1134 COMMAND_HANDLER(vdebug_set_server
)
1136 if ((CMD_ARGC
!= 1) || !strchr(CMD_ARGV
[0], ':'))
1137 return ERROR_COMMAND_SYNTAX_ERROR
;
1139 char *pchar
= strchr(CMD_ARGV
[0], ':');
1141 strncpy(vdc
.server_name
, CMD_ARGV
[0], sizeof(vdc
.server_name
) - 1);
1142 int port
= atoi(++pchar
);
1143 if (port
< 0 || port
> UINT16_MAX
) {
1144 LOG_ERROR("invalid port number %d specified", port
);
1145 return ERROR_COMMAND_SYNTAX_ERROR
;
1147 vdc
.server_port
= port
;
1148 LOG_DEBUG("server: %s port %u", vdc
.server_name
, vdc
.server_port
);
1153 COMMAND_HANDLER(vdebug_set_bfm
)
1157 if ((CMD_ARGC
!= 2) || (sscanf(CMD_ARGV
[1], "%u%c", &vdc
.bfm_period
, &prefix
) != 2))
1158 return ERROR_COMMAND_SYNTAX_ERROR
;
1160 strncpy(vdc
.bfm_path
, CMD_ARGV
[0], sizeof(vdc
.bfm_path
) - 1);
1163 vdc
.bfm_period
*= 1000000;
1166 vdc
.bfm_period
*= 1000;
1172 if (transport_is_dapdirect_swd())
1173 vdc
.bfm_type
= VD_BFM_SWDP
;
1175 vdc
.bfm_type
= VD_BFM_JTAG
;
1176 LOG_DEBUG("bfm_path: %s clk_period %ups", vdc
.bfm_path
, vdc
.bfm_period
);
1181 COMMAND_HANDLER(vdebug_set_mem
)
1184 return ERROR_COMMAND_SYNTAX_ERROR
;
1186 if (vdc
.mem_ndx
>= VD_MAX_MEMORIES
) {
1187 LOG_ERROR("mem_path declared more than %d allowed times", VD_MAX_MEMORIES
);
1191 strncpy(vdc
.mem_path
[vdc
.mem_ndx
], CMD_ARGV
[0], sizeof(vdc
.mem_path
[vdc
.mem_ndx
]) - 1);
1192 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[1], vdc
.mem_base
[vdc
.mem_ndx
]);
1193 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[2], vdc
.mem_size
[vdc
.mem_ndx
]);
1194 LOG_DEBUG("mem_path: set %s @ 0x%08x+0x%08x", vdc
.mem_path
[vdc
.mem_ndx
],
1195 vdc
.mem_base
[vdc
.mem_ndx
], vdc
.mem_size
[vdc
.mem_ndx
]);
1201 COMMAND_HANDLER(vdebug_set_batching
)
1204 return ERROR_COMMAND_SYNTAX_ERROR
;
1206 if (isdigit((unsigned char)CMD_ARGV
[0][0]))
1207 vdc
.trans_batch
= (CMD_ARGV
[0][0] == '0' ? 0 : (CMD_ARGV
[0][0] == '1' ? 1 : 2));
1208 else if (CMD_ARGV
[0][0] == 'r')
1209 vdc
.trans_batch
= VD_BATCH_WR
;
1210 else if (CMD_ARGV
[0][0] == 'w')
1211 vdc
.trans_batch
= VD_BATCH_WO
;
1213 vdc
.trans_batch
= VD_BATCH_NO
;
1214 LOG_DEBUG("batching: set to %u", vdc
.trans_batch
);
1219 COMMAND_HANDLER(vdebug_set_polling
)
1222 return ERROR_COMMAND_SYNTAX_ERROR
;
1224 vdc
.poll_min
= atoi(CMD_ARGV
[0]);
1225 vdc
.poll_max
= atoi(CMD_ARGV
[1]);
1226 LOG_DEBUG("polling: set min %u max %u", vdc
.poll_min
, vdc
.poll_max
);
1231 static const struct command_registration vdebug_command_handlers
[] = {
1234 .handler
= &vdebug_set_server
,
1235 .mode
= COMMAND_CONFIG
,
1236 .help
= "set the vdebug server name or address",
1237 .usage
= "<host:port>",
1241 .handler
= &vdebug_set_bfm
,
1242 .mode
= COMMAND_CONFIG
,
1243 .help
= "set the vdebug BFM hierarchical path",
1244 .usage
= "<path> <clk_period[p|n|u]s>",
1248 .handler
= &vdebug_set_mem
,
1249 .mode
= COMMAND_ANY
,
1250 .help
= "set the design memory for the code load",
1251 .usage
= "<path> <base_address> <size>",
1255 .handler
= &vdebug_set_batching
,
1256 .mode
= COMMAND_CONFIG
,
1257 .help
= "set the transaction batching no|wr|rd [0|1|2]",
1262 .handler
= &vdebug_set_polling
,
1263 .mode
= COMMAND_CONFIG
,
1264 .help
= "set the polling pause, executing hardware cycles between min and max",
1265 .usage
= "<min cycles> <max cycles>",
1267 COMMAND_REGISTRATION_DONE
1270 static const struct command_registration vdebug_command
[] = {
1273 .chain
= vdebug_command_handlers
,
1274 .mode
= COMMAND_ANY
,
1275 .help
= "vdebug command group",
1278 COMMAND_REGISTRATION_DONE
1281 static struct jtag_interface vdebug_jtag_ops
= {
1282 .supported
= DEBUG_CAP_TMS_SEQ
,
1283 .execute_queue
= vdebug_jtag_execute_queue
,
1286 static const struct dap_ops vdebug_dap_ops
= {
1287 .connect
= vdebug_dap_connect
,
1288 .send_sequence
= vdebug_dap_send_sequence
,
1289 .queue_dp_read
= vdebug_dap_queue_dp_read
,
1290 .queue_dp_write
= vdebug_dap_queue_dp_write
,
1291 .queue_ap_read
= vdebug_dap_queue_ap_read
,
1292 .queue_ap_write
= vdebug_dap_queue_ap_write
,
1293 .queue_ap_abort
= vdebug_dap_queue_ap_abort
,
1294 .run
= vdebug_dap_run
,
1295 .sync
= NULL
, /* optional */
1296 .quit
= NULL
, /* optional */
1299 static const char *const vdebug_transports
[] = { "jtag", "dapdirect_swd", NULL
};
1301 struct adapter_driver vdebug_adapter_driver
= {
1303 .transports
= vdebug_transports
,
1304 .speed
= vdebug_jtag_speed
,
1305 .khz
= vdebug_jtag_khz
,
1306 .speed_div
= vdebug_jtag_div
,
1307 .commands
= vdebug_command
,
1308 .init
= vdebug_init
,
1309 .quit
= vdebug_quit
,
1310 .reset
= vdebug_reset
,
1311 .jtag_ops
= &vdebug_jtag_ops
,
1312 .dap_swd_ops
= &vdebug_dap_ops
,
Linking to existing account procedure
If you already have an account and want to add another login method
you
MUST first sign in with your existing account and
then change URL to read
https://review.openocd.org/login/?link
to get to this page again but this time it'll work for linking. Thank you.
SSH host keys fingerprints
1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=.. |
|+o.. . |
|*.o . . |
|+B . . . |
|Bo. = o S |
|Oo.+ + = |
|oB=.* = . o |
| =+=.+ + E |
|. .=o . o |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)