1 // SPDX-License-Identifier: GPL-2.0-or-later
6 * Copyright (C) 2013 Franck Jullien, <elec4fun@gmail.com>
8 * See file CREDITS for list of people who contributed to this
16 #include <jtag/interface.h>
17 #ifdef HAVE_ARPA_INET_H
18 #include <arpa/inet.h>
22 #include <netinet/tcp.h>
25 #include "helper/replacements.h"
27 #define NO_TAP_SHIFT 0
30 #define DEFAULT_SERVER_ADDRESS "127.0.0.1"
31 #define DEFAULT_SERVER_PORT 5555
33 #define XFERT_MAX_SIZE 512
37 #define CMD_SCAN_CHAIN 2
38 #define CMD_SCAN_CHAIN_FLIP_TMS 3
39 #define CMD_STOP_SIMU 4
41 /* jtag_vpi server port and address to connect to */
42 static int server_port
= DEFAULT_SERVER_PORT
;
43 static char *server_address
;
45 /* Send CMD_STOP_SIMU to server when OpenOCD exits? */
46 static bool stop_sim_on_exit
;
49 static struct sockaddr_in serv_addr
;
51 /* One jtag_vpi "packet" as sent over a TCP channel. */
55 unsigned char cmd_buf
[4];
57 unsigned char buffer_out
[XFERT_MAX_SIZE
];
58 unsigned char buffer_in
[XFERT_MAX_SIZE
];
61 unsigned char length_buf
[4];
65 unsigned char nb_bits_buf
[4];
69 static char *jtag_vpi_cmd_to_str(int cmd_num
)
77 return "CMD_SCAN_CHAIN";
78 case CMD_SCAN_CHAIN_FLIP_TMS
:
79 return "CMD_SCAN_CHAIN_FLIP_TMS";
81 return "CMD_STOP_SIMU";
87 static int jtag_vpi_send_cmd(struct vpi_cmd
*vpi
)
91 /* Optional low-level JTAG debug */
92 if (LOG_LEVEL_IS(LOG_LVL_DEBUG_IO
)) {
93 if (vpi
->nb_bits
> 0) {
94 /* command with a non-empty data payload */
95 char *char_buf
= buf_to_hex_str(vpi
->buffer_out
,
96 (vpi
->nb_bits
> DEBUG_JTAG_IOZ
)
99 LOG_DEBUG_IO("sending JTAG VPI cmd: cmd=%s, "
100 "length=%" PRIu32
", "
101 "nb_bits=%" PRIu32
", "
103 jtag_vpi_cmd_to_str(vpi
->cmd
),
107 (vpi
->nb_bits
> DEBUG_JTAG_IOZ
) ? "(...)" : "");
110 /* command without data payload */
111 LOG_DEBUG_IO("sending JTAG VPI cmd: cmd=%s, "
112 "length=%" PRIu32
", "
114 jtag_vpi_cmd_to_str(vpi
->cmd
),
120 /* Use little endian when transmitting/receiving jtag_vpi cmds.
121 The choice of little endian goes against usual networking conventions
122 but is intentional to remain compatible with most older OpenOCD builds
123 (i.e. builds on little-endian platforms). */
124 h_u32_to_le(vpi
->cmd_buf
, vpi
->cmd
);
125 h_u32_to_le(vpi
->length_buf
, vpi
->length
);
126 h_u32_to_le(vpi
->nb_bits_buf
, vpi
->nb_bits
);
129 retval
= write_socket(sockfd
, vpi
, sizeof(struct vpi_cmd
));
132 /* Account for the case when socket write is interrupted. */
134 int wsa_err
= WSAGetLastError();
135 if (wsa_err
== WSAEINTR
)
141 /* Otherwise this is an error using the socket, most likely fatal
142 for the connection. B*/
143 log_socket_error("jtag_vpi xmit");
144 /* TODO: Clean way how adapter drivers can report fatal errors
145 to upper layers of OpenOCD and let it perform an orderly shutdown? */
147 } else if (retval
< (int)sizeof(struct vpi_cmd
)) {
148 /* This means we could not send all data, which is most likely fatal
149 for the jtag_vpi connection (the underlying TCP connection likely not
151 LOG_ERROR("jtag_vpi: Could not send all data through jtag_vpi connection.");
155 /* Otherwise the packet has been sent successfully. */
159 static int jtag_vpi_receive_cmd(struct vpi_cmd
*vpi
)
161 unsigned bytes_buffered
= 0;
162 while (bytes_buffered
< sizeof(struct vpi_cmd
)) {
163 int bytes_to_receive
= sizeof(struct vpi_cmd
) - bytes_buffered
;
164 int retval
= read_socket(sockfd
, ((char *)vpi
) + bytes_buffered
, bytes_to_receive
);
167 int wsa_err
= WSAGetLastError();
168 if (wsa_err
== WSAEINTR
) {
169 /* socket read interrupted by WSACancelBlockingCall() */
173 if (errno
== EINTR
) {
174 /* socket read interrupted by a signal */
178 /* Otherwise, this is an error when accessing the socket. */
179 log_socket_error("jtag_vpi recv");
181 } else if (retval
== 0) {
182 /* Connection closed by the other side */
183 LOG_ERROR("Connection prematurely closed by jtag_vpi server.");
186 /* Otherwise, we have successfully received some data */
187 bytes_buffered
+= retval
;
190 /* Use little endian when transmitting/receiving jtag_vpi cmds. */
191 vpi
->cmd
= le_to_h_u32(vpi
->cmd_buf
);
192 vpi
->length
= le_to_h_u32(vpi
->length_buf
);
193 vpi
->nb_bits
= le_to_h_u32(vpi
->nb_bits_buf
);
199 * jtag_vpi_reset - ask to reset the JTAG device
200 * @param trst 1 if TRST is to be asserted
201 * @param srst 1 if SRST is to be asserted
203 static int jtag_vpi_reset(int trst
, int srst
)
206 memset(&vpi
, 0, sizeof(struct vpi_cmd
));
210 return jtag_vpi_send_cmd(&vpi
);
214 * jtag_vpi_tms_seq - ask a TMS sequence transition to JTAG
215 * @param bits TMS bits to be written (bit0, bit1 .. bitN)
216 * @param nb_bits number of TMS bits (between 1 and 8)
218 * Write a series of TMS transitions, where each transition consists in :
219 * - writing out TCK=0, TMS=\<new_state>, TDI=\<???>
220 * - writing out TCK=1, TMS=\<new_state>, TDI=\<???> which triggers the transition
221 * The function ensures that at the end of the sequence, the clock (TCK) is put
224 static int jtag_vpi_tms_seq(const uint8_t *bits
, int nb_bits
)
229 memset(&vpi
, 0, sizeof(struct vpi_cmd
));
230 nb_bytes
= DIV_ROUND_UP(nb_bits
, 8);
232 vpi
.cmd
= CMD_TMS_SEQ
;
233 memcpy(vpi
.buffer_out
, bits
, nb_bytes
);
234 vpi
.length
= nb_bytes
;
235 vpi
.nb_bits
= nb_bits
;
237 return jtag_vpi_send_cmd(&vpi
);
241 * jtag_vpi_path_move - ask a TMS sequence transition to JTAG
242 * @param cmd path transition
244 * Write a series of TMS transitions, where each transition consists in :
245 * - writing out TCK=0, TMS=\<new_state>, TDI=\<???>
246 * - writing out TCK=1, TMS=\<new_state>, TDI=\<???> which triggers the transition
247 * The function ensures that at the end of the sequence, the clock (TCK) is put
251 static int jtag_vpi_path_move(struct pathmove_command
*cmd
)
253 uint8_t trans
[DIV_ROUND_UP(cmd
->num_states
, 8)];
255 memset(trans
, 0, DIV_ROUND_UP(cmd
->num_states
, 8));
257 for (int i
= 0; i
< cmd
->num_states
; i
++) {
258 if (tap_state_transition(tap_get_state(), true) == cmd
->path
[i
])
259 buf_set_u32(trans
, i
, 1, 1);
260 tap_set_state(cmd
->path
[i
]);
263 return jtag_vpi_tms_seq(trans
, cmd
->num_states
);
267 * jtag_vpi_tms - ask a tms command
268 * @param cmd tms command
270 static int jtag_vpi_tms(struct tms_command
*cmd
)
272 return jtag_vpi_tms_seq(cmd
->bits
, cmd
->num_bits
);
275 static int jtag_vpi_state_move(tap_state_t state
)
277 if (tap_get_state() == state
)
280 uint8_t tms_scan
= tap_get_tms_path(tap_get_state(), state
);
281 int tms_len
= tap_get_tms_path_len(tap_get_state(), state
);
283 int retval
= jtag_vpi_tms_seq(&tms_scan
, tms_len
);
284 if (retval
!= ERROR_OK
)
287 tap_set_state(state
);
292 static int jtag_vpi_queue_tdi_xfer(uint8_t *bits
, int nb_bits
, int tap_shift
)
295 int nb_bytes
= DIV_ROUND_UP(nb_bits
, 8);
297 memset(&vpi
, 0, sizeof(struct vpi_cmd
));
299 vpi
.cmd
= tap_shift
? CMD_SCAN_CHAIN_FLIP_TMS
: CMD_SCAN_CHAIN
;
302 memcpy(vpi
.buffer_out
, bits
, nb_bytes
);
304 memset(vpi
.buffer_out
, 0xff, nb_bytes
);
306 vpi
.length
= nb_bytes
;
307 vpi
.nb_bits
= nb_bits
;
309 int retval
= jtag_vpi_send_cmd(&vpi
);
310 if (retval
!= ERROR_OK
)
313 retval
= jtag_vpi_receive_cmd(&vpi
);
314 if (retval
!= ERROR_OK
)
317 /* Optional low-level JTAG debug */
318 if (LOG_LEVEL_IS(LOG_LVL_DEBUG_IO
)) {
319 char *char_buf
= buf_to_hex_str(vpi
.buffer_in
,
320 (nb_bits
> DEBUG_JTAG_IOZ
) ? DEBUG_JTAG_IOZ
: nb_bits
);
321 LOG_DEBUG_IO("recvd JTAG VPI data: nb_bits=%d, buf_in=0x%s%s",
322 nb_bits
, char_buf
, (nb_bits
> DEBUG_JTAG_IOZ
) ? "(...)" : "");
327 memcpy(bits
, vpi
.buffer_in
, nb_bytes
);
333 * jtag_vpi_queue_tdi - short description
334 * @param bits bits to be queued on TDI (or NULL if 0 are to be queued)
335 * @param nb_bits number of bits
338 static int jtag_vpi_queue_tdi(uint8_t *bits
, int nb_bits
, int tap_shift
)
340 int nb_xfer
= DIV_ROUND_UP(nb_bits
, XFERT_MAX_SIZE
* 8);
345 retval
= jtag_vpi_queue_tdi_xfer(bits
, nb_bits
, tap_shift
);
346 if (retval
!= ERROR_OK
)
349 retval
= jtag_vpi_queue_tdi_xfer(bits
, XFERT_MAX_SIZE
* 8, NO_TAP_SHIFT
);
350 if (retval
!= ERROR_OK
)
352 nb_bits
-= XFERT_MAX_SIZE
* 8;
354 bits
+= XFERT_MAX_SIZE
;
364 * jtag_vpi_clock_tms - clock a TMS transition
365 * @param tms the TMS to be sent
367 * Triggers a TMS transition (ie. one JTAG TAP state move).
369 static int jtag_vpi_clock_tms(int tms
)
371 const uint8_t tms_0
= 0;
372 const uint8_t tms_1
= 1;
374 return jtag_vpi_tms_seq(tms
? &tms_1
: &tms_0
, 1);
378 * jtag_vpi_scan - launches a DR-scan or IR-scan
379 * @param cmd the command to launch
381 * Launch a JTAG IR-scan or DR-scan
383 * Returns ERROR_OK if OK, ERROR_xxx if a read/write error occurred.
385 static int jtag_vpi_scan(struct scan_command
*cmd
)
389 int retval
= ERROR_OK
;
391 scan_bits
= jtag_build_buffer(cmd
, &buf
);
394 retval
= jtag_vpi_state_move(TAP_IRSHIFT
);
395 if (retval
!= ERROR_OK
)
398 retval
= jtag_vpi_state_move(TAP_DRSHIFT
);
399 if (retval
!= ERROR_OK
)
403 if (cmd
->end_state
== TAP_DRSHIFT
) {
404 retval
= jtag_vpi_queue_tdi(buf
, scan_bits
, NO_TAP_SHIFT
);
405 if (retval
!= ERROR_OK
)
408 retval
= jtag_vpi_queue_tdi(buf
, scan_bits
, TAP_SHIFT
);
409 if (retval
!= ERROR_OK
)
413 if (cmd
->end_state
!= TAP_DRSHIFT
) {
415 * As our JTAG is in an unstable state (IREXIT1 or DREXIT1), move it
416 * forward to a stable IRPAUSE or DRPAUSE.
418 retval
= jtag_vpi_clock_tms(0);
419 if (retval
!= ERROR_OK
)
423 tap_set_state(TAP_IRPAUSE
);
425 tap_set_state(TAP_DRPAUSE
);
428 retval
= jtag_read_buffer(buf
, cmd
);
429 if (retval
!= ERROR_OK
)
434 if (cmd
->end_state
!= TAP_DRSHIFT
) {
435 retval
= jtag_vpi_state_move(cmd
->end_state
);
436 if (retval
!= ERROR_OK
)
443 static int jtag_vpi_runtest(int cycles
, tap_state_t state
)
447 retval
= jtag_vpi_state_move(TAP_IDLE
);
448 if (retval
!= ERROR_OK
)
451 retval
= jtag_vpi_queue_tdi(NULL
, cycles
, NO_TAP_SHIFT
);
452 if (retval
!= ERROR_OK
)
455 return jtag_vpi_state_move(state
);
458 static int jtag_vpi_stableclocks(int cycles
)
461 int cycles_remain
= cycles
;
464 const int CYCLES_ONE_BATCH
= sizeof(tms_bits
) * 8;
468 /* use TMS=1 in TAP RESET state, TMS=0 in all other stable states */
469 memset(&tms_bits
, (tap_get_state() == TAP_RESET
) ? 0xff : 0x00, sizeof(tms_bits
));
471 /* send the TMS bits */
472 while (cycles_remain
> 0) {
473 nb_bits
= (cycles_remain
< CYCLES_ONE_BATCH
) ? cycles_remain
: CYCLES_ONE_BATCH
;
474 retval
= jtag_vpi_tms_seq(tms_bits
, nb_bits
);
475 if (retval
!= ERROR_OK
)
477 cycles_remain
-= nb_bits
;
483 static int jtag_vpi_execute_queue(void)
485 struct jtag_command
*cmd
;
486 int retval
= ERROR_OK
;
488 for (cmd
= jtag_command_queue
; retval
== ERROR_OK
&& cmd
;
492 retval
= jtag_vpi_reset(cmd
->cmd
.reset
->trst
, cmd
->cmd
.reset
->srst
);
495 retval
= jtag_vpi_runtest(cmd
->cmd
.runtest
->num_cycles
,
496 cmd
->cmd
.runtest
->end_state
);
498 case JTAG_STABLECLOCKS
:
499 retval
= jtag_vpi_stableclocks(cmd
->cmd
.stableclocks
->num_cycles
);
502 retval
= jtag_vpi_state_move(cmd
->cmd
.statemove
->end_state
);
505 retval
= jtag_vpi_path_move(cmd
->cmd
.pathmove
);
508 retval
= jtag_vpi_tms(cmd
->cmd
.tms
);
511 jtag_sleep(cmd
->cmd
.sleep
->us
);
514 retval
= jtag_vpi_scan(cmd
->cmd
.scan
);
517 LOG_ERROR("BUG: unknown JTAG command type 0x%X",
527 static int jtag_vpi_init(void)
531 sockfd
= socket(AF_INET
, SOCK_STREAM
, 0);
533 LOG_ERROR("jtag_vpi: Could not create client socket");
537 memset(&serv_addr
, 0, sizeof(serv_addr
));
539 serv_addr
.sin_family
= AF_INET
;
540 serv_addr
.sin_port
= htons(server_port
);
543 server_address
= strdup(DEFAULT_SERVER_ADDRESS
);
545 serv_addr
.sin_addr
.s_addr
= inet_addr(server_address
);
547 if (serv_addr
.sin_addr
.s_addr
== INADDR_NONE
) {
548 LOG_ERROR("jtag_vpi: inet_addr error occurred");
552 if (connect(sockfd
, (struct sockaddr
*)&serv_addr
, sizeof(serv_addr
)) < 0) {
554 LOG_ERROR("jtag_vpi: Can't connect to %s : %u", server_address
, server_port
);
555 return ERROR_COMMAND_CLOSE_CONNECTION
;
558 if (serv_addr
.sin_addr
.s_addr
== htonl(INADDR_LOOPBACK
)) {
559 /* This increases performance dramatically for local
560 * connections, which is the most likely arrangement
561 * for a VPI connection. */
562 setsockopt(sockfd
, IPPROTO_TCP
, TCP_NODELAY
, (char *)&flag
, sizeof(int));
565 LOG_INFO("jtag_vpi: Connection to %s : %u successful", server_address
, server_port
);
570 static int jtag_vpi_stop_simulation(void)
573 memset(&cmd
, 0, sizeof(struct vpi_cmd
));
576 cmd
.cmd
= CMD_STOP_SIMU
;
577 return jtag_vpi_send_cmd(&cmd
);
580 static int jtag_vpi_quit(void)
582 if (stop_sim_on_exit
) {
583 if (jtag_vpi_stop_simulation() != ERROR_OK
)
584 LOG_WARNING("jtag_vpi: failed to send \"stop simulation\" command");
586 if (close_socket(sockfd
) != 0) {
587 LOG_WARNING("jtag_vpi: could not close jtag_vpi client socket");
588 log_socket_error("jtag_vpi");
590 free(server_address
);
594 COMMAND_HANDLER(jtag_vpi_set_port
)
597 LOG_ERROR("Command \"jtag_vpi set_port\" expects 1 argument (TCP port number)");
598 return ERROR_COMMAND_SYNTAX_ERROR
;
601 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], server_port
);
602 LOG_INFO("jtag_vpi: server port set to %u", server_port
);
607 COMMAND_HANDLER(jtag_vpi_set_address
)
611 LOG_ERROR("Command \"jtag_vpi set_address\" expects 1 argument (IP address)");
612 return ERROR_COMMAND_SYNTAX_ERROR
;
615 free(server_address
);
616 server_address
= strdup(CMD_ARGV
[0]);
617 LOG_INFO("jtag_vpi: server address set to %s", server_address
);
622 COMMAND_HANDLER(jtag_vpi_stop_sim_on_exit_handler
)
625 LOG_ERROR("Command \"jtag_vpi stop_sim_on_exit\" expects 1 argument (on|off)");
626 return ERROR_COMMAND_SYNTAX_ERROR
;
629 COMMAND_PARSE_ON_OFF(CMD_ARGV
[0], stop_sim_on_exit
);
633 static const struct command_registration jtag_vpi_subcommand_handlers
[] = {
636 .handler
= &jtag_vpi_set_port
,
637 .mode
= COMMAND_CONFIG
,
638 .help
= "set the TCP port number of the jtag_vpi server (default: 5555)",
639 .usage
= "tcp_port_num",
642 .name
= "set_address",
643 .handler
= &jtag_vpi_set_address
,
644 .mode
= COMMAND_CONFIG
,
645 .help
= "set the IP address of the jtag_vpi server (default: 127.0.0.1)",
646 .usage
= "ipv4_addr",
649 .name
= "stop_sim_on_exit",
650 .handler
= &jtag_vpi_stop_sim_on_exit_handler
,
651 .mode
= COMMAND_CONFIG
,
652 .help
= "Configure if simulation stop command shall be sent "
653 "before OpenOCD exits (default: off)",
656 COMMAND_REGISTRATION_DONE
659 static const struct command_registration jtag_vpi_command_handlers
[] = {
663 .help
= "perform jtag_vpi management",
664 .chain
= jtag_vpi_subcommand_handlers
,
667 COMMAND_REGISTRATION_DONE
670 static struct jtag_interface jtag_vpi_interface
= {
671 .supported
= DEBUG_CAP_TMS_SEQ
,
672 .execute_queue
= jtag_vpi_execute_queue
,
675 struct adapter_driver jtag_vpi_adapter_driver
= {
677 .transports
= jtag_only
,
678 .commands
= jtag_vpi_command_handlers
,
680 .init
= jtag_vpi_init
,
681 .quit
= jtag_vpi_quit
,
683 .jtag_ops
= &jtag_vpi_interface
,
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)