4 * Copyright (C) 2013 Franck Jullien, <elec4fun@gmail.com>
6 * See file CREDITS for list of people who contributed to this
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation; either version 2 of
12 * the License, or (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program. If not, see <http://www.gnu.org/licenses/>.
27 #include <jtag/interface.h>
28 #ifdef HAVE_ARPA_INET_H
29 #include <arpa/inet.h>
33 #include <netinet/tcp.h>
38 #define NO_TAP_SHIFT 0
41 #define SERVER_ADDRESS "127.0.0.1"
42 #define SERVER_PORT 5555
44 #define XFERT_MAX_SIZE 512
48 #define CMD_SCAN_CHAIN 2
49 #define CMD_SCAN_CHAIN_FLIP_TMS 3
50 #define CMD_STOP_SIMU 4
52 /* jtag_vpi server port and address to connect to */
53 static int server_port
= SERVER_PORT
;
54 static char *server_address
;
56 /* Send CMD_STOP_SIMU to server when OpenOCD exits? */
57 static bool stop_sim_on_exit
;
60 static struct sockaddr_in serv_addr
;
62 /* One jtag_vpi "packet" as sent over a TCP channel. */
66 unsigned char cmd_buf
[4];
68 unsigned char buffer_out
[XFERT_MAX_SIZE
];
69 unsigned char buffer_in
[XFERT_MAX_SIZE
];
72 unsigned char length_buf
[4];
76 unsigned char nb_bits_buf
[4];
80 static char *jtag_vpi_cmd_to_str(int cmd_num
)
88 return "CMD_SCAN_CHAIN";
89 case CMD_SCAN_CHAIN_FLIP_TMS
:
90 return "CMD_SCAN_CHAIN_FLIP_TMS";
92 return "CMD_STOP_SIMU";
98 static int jtag_vpi_send_cmd(struct vpi_cmd
*vpi
)
102 /* Optional low-level JTAG debug */
103 if (LOG_LEVEL_IS(LOG_LVL_DEBUG_IO
)) {
104 if (vpi
->nb_bits
> 0) {
105 /* command with a non-empty data payload */
106 char *char_buf
= buf_to_hex_str(vpi
->buffer_out
,
107 (vpi
->nb_bits
> DEBUG_JTAG_IOZ
)
110 LOG_DEBUG_IO("sending JTAG VPI cmd: cmd=%s, "
111 "length=%" PRIu32
", "
112 "nb_bits=%" PRIu32
", "
114 jtag_vpi_cmd_to_str(vpi
->cmd
),
118 (vpi
->nb_bits
> DEBUG_JTAG_IOZ
) ? "(...)" : "");
121 /* command without data payload */
122 LOG_DEBUG_IO("sending JTAG VPI cmd: cmd=%s, "
123 "length=%" PRIu32
", "
125 jtag_vpi_cmd_to_str(vpi
->cmd
),
131 /* Use little endian when transmitting/receiving jtag_vpi cmds.
132 The choice of little endian goes against usual networking conventions
133 but is intentional to remain compatible with most older OpenOCD builds
134 (i.e. builds on little-endian platforms). */
135 h_u32_to_le(vpi
->cmd_buf
, vpi
->cmd
);
136 h_u32_to_le(vpi
->length_buf
, vpi
->length
);
137 h_u32_to_le(vpi
->nb_bits_buf
, vpi
->nb_bits
);
140 retval
= write_socket(sockfd
, vpi
, sizeof(struct vpi_cmd
));
143 /* Account for the case when socket write is interrupted. */
145 int wsa_err
= WSAGetLastError();
146 if (wsa_err
== WSAEINTR
)
152 /* Otherwise this is an error using the socket, most likely fatal
153 for the connection. B*/
154 log_socket_error("jtag_vpi xmit");
155 /* TODO: Clean way how adapter drivers can report fatal errors
156 to upper layers of OpenOCD and let it perform an orderly shutdown? */
158 } else if (retval
< (int)sizeof(struct vpi_cmd
)) {
159 /* This means we could not send all data, which is most likely fatal
160 for the jtag_vpi connection (the underlying TCP connection likely not
162 LOG_ERROR("Could not send all data through jtag_vpi connection.");
166 /* Otherwise the packet has been sent successfully. */
170 static int jtag_vpi_receive_cmd(struct vpi_cmd
*vpi
)
172 unsigned bytes_buffered
= 0;
173 while (bytes_buffered
< sizeof(struct vpi_cmd
)) {
174 int bytes_to_receive
= sizeof(struct vpi_cmd
) - bytes_buffered
;
175 int retval
= read_socket(sockfd
, ((char *)vpi
) + bytes_buffered
, bytes_to_receive
);
178 int wsa_err
= WSAGetLastError();
179 if (wsa_err
== WSAEINTR
) {
180 /* socket read interrupted by WSACancelBlockingCall() */
184 if (errno
== EINTR
) {
185 /* socket read interrupted by a signal */
189 /* Otherwise, this is an error when accessing the socket. */
190 log_socket_error("jtag_vpi recv");
192 } else if (retval
== 0) {
193 /* Connection closed by the other side */
194 LOG_ERROR("Connection prematurely closed by jtag_vpi server.");
197 /* Otherwise, we have successfully received some data */
198 bytes_buffered
+= retval
;
201 /* Use little endian when transmitting/receiving jtag_vpi cmds. */
202 vpi
->cmd
= le_to_h_u32(vpi
->cmd_buf
);
203 vpi
->length
= le_to_h_u32(vpi
->length_buf
);
204 vpi
->nb_bits
= le_to_h_u32(vpi
->nb_bits_buf
);
210 * jtag_vpi_reset - ask to reset the JTAG device
211 * @trst: 1 if TRST is to be asserted
212 * @srst: 1 if SRST is to be asserted
214 static int jtag_vpi_reset(int trst
, int srst
)
217 memset(&vpi
, 0, sizeof(struct vpi_cmd
));
221 return jtag_vpi_send_cmd(&vpi
);
225 * jtag_vpi_tms_seq - ask a TMS sequence transition to JTAG
226 * @bits: TMS bits to be written (bit0, bit1 .. bitN)
227 * @nb_bits: number of TMS bits (between 1 and 8)
229 * Write a series of TMS transitions, where each transition consists in :
230 * - writing out TCK=0, TMS=<new_state>, TDI=<???>
231 * - writing out TCK=1, TMS=<new_state>, TDI=<???> which triggers the transition
232 * The function ensures that at the end of the sequence, the clock (TCK) is put
235 static int jtag_vpi_tms_seq(const uint8_t *bits
, int nb_bits
)
240 memset(&vpi
, 0, sizeof(struct vpi_cmd
));
241 nb_bytes
= DIV_ROUND_UP(nb_bits
, 8);
243 vpi
.cmd
= CMD_TMS_SEQ
;
244 memcpy(vpi
.buffer_out
, bits
, nb_bytes
);
245 vpi
.length
= nb_bytes
;
246 vpi
.nb_bits
= nb_bits
;
248 return jtag_vpi_send_cmd(&vpi
);
252 * jtag_vpi_path_move - ask a TMS sequence transition to JTAG
253 * @cmd: path transition
255 * Write a series of TMS transitions, where each transition consists in :
256 * - writing out TCK=0, TMS=<new_state>, TDI=<???>
257 * - writing out TCK=1, TMS=<new_state>, TDI=<???> which triggers the transition
258 * The function ensures that at the end of the sequence, the clock (TCK) is put
262 static int jtag_vpi_path_move(struct pathmove_command
*cmd
)
264 uint8_t trans
[DIV_ROUND_UP(cmd
->num_states
, 8)];
266 memset(trans
, 0, DIV_ROUND_UP(cmd
->num_states
, 8));
268 for (int i
= 0; i
< cmd
->num_states
; i
++) {
269 if (tap_state_transition(tap_get_state(), true) == cmd
->path
[i
])
270 buf_set_u32(trans
, i
, 1, 1);
271 tap_set_state(cmd
->path
[i
]);
274 return jtag_vpi_tms_seq(trans
, cmd
->num_states
);
278 * jtag_vpi_tms - ask a tms command
281 static int jtag_vpi_tms(struct tms_command
*cmd
)
283 return jtag_vpi_tms_seq(cmd
->bits
, cmd
->num_bits
);
286 static int jtag_vpi_state_move(tap_state_t state
)
288 if (tap_get_state() == state
)
291 uint8_t tms_scan
= tap_get_tms_path(tap_get_state(), state
);
292 int tms_len
= tap_get_tms_path_len(tap_get_state(), state
);
294 int retval
= jtag_vpi_tms_seq(&tms_scan
, tms_len
);
295 if (retval
!= ERROR_OK
)
298 tap_set_state(state
);
303 static int jtag_vpi_queue_tdi_xfer(uint8_t *bits
, int nb_bits
, int tap_shift
)
306 int nb_bytes
= DIV_ROUND_UP(nb_bits
, 8);
308 memset(&vpi
, 0, sizeof(struct vpi_cmd
));
310 vpi
.cmd
= tap_shift
? CMD_SCAN_CHAIN_FLIP_TMS
: CMD_SCAN_CHAIN
;
313 memcpy(vpi
.buffer_out
, bits
, nb_bytes
);
315 memset(vpi
.buffer_out
, 0xff, nb_bytes
);
317 vpi
.length
= nb_bytes
;
318 vpi
.nb_bits
= nb_bits
;
320 int retval
= jtag_vpi_send_cmd(&vpi
);
321 if (retval
!= ERROR_OK
)
324 retval
= jtag_vpi_receive_cmd(&vpi
);
325 if (retval
!= ERROR_OK
)
328 /* Optional low-level JTAG debug */
329 if (LOG_LEVEL_IS(LOG_LVL_DEBUG_IO
)) {
330 char *char_buf
= buf_to_hex_str(vpi
.buffer_in
,
331 (nb_bits
> DEBUG_JTAG_IOZ
) ? DEBUG_JTAG_IOZ
: nb_bits
);
332 LOG_DEBUG_IO("recvd JTAG VPI data: nb_bits=%d, buf_in=0x%s%s",
333 nb_bits
, char_buf
, (nb_bits
> DEBUG_JTAG_IOZ
) ? "(...)" : "");
338 memcpy(bits
, vpi
.buffer_in
, nb_bytes
);
344 * jtag_vpi_queue_tdi - short description
345 * @bits: bits to be queued on TDI (or NULL if 0 are to be queued)
346 * @nb_bits: number of bits
348 static int jtag_vpi_queue_tdi(uint8_t *bits
, int nb_bits
, int tap_shift
)
350 int nb_xfer
= DIV_ROUND_UP(nb_bits
, XFERT_MAX_SIZE
* 8);
355 retval
= jtag_vpi_queue_tdi_xfer(bits
, nb_bits
, tap_shift
);
356 if (retval
!= ERROR_OK
)
359 retval
= jtag_vpi_queue_tdi_xfer(bits
, XFERT_MAX_SIZE
* 8, NO_TAP_SHIFT
);
360 if (retval
!= ERROR_OK
)
362 nb_bits
-= XFERT_MAX_SIZE
* 8;
364 bits
+= XFERT_MAX_SIZE
;
374 * jtag_vpi_clock_tms - clock a TMS transition
375 * @tms: the TMS to be sent
377 * Triggers a TMS transition (ie. one JTAG TAP state move).
379 static int jtag_vpi_clock_tms(int tms
)
381 const uint8_t tms_0
= 0;
382 const uint8_t tms_1
= 1;
384 return jtag_vpi_tms_seq(tms
? &tms_1
: &tms_0
, 1);
388 * jtag_vpi_scan - launches a DR-scan or IR-scan
389 * @cmd: the command to launch
391 * Launch a JTAG IR-scan or DR-scan
393 * Returns ERROR_OK if OK, ERROR_xxx if a read/write error occurred.
395 static int jtag_vpi_scan(struct scan_command
*cmd
)
399 int retval
= ERROR_OK
;
401 scan_bits
= jtag_build_buffer(cmd
, &buf
);
404 retval
= jtag_vpi_state_move(TAP_IRSHIFT
);
405 if (retval
!= ERROR_OK
)
408 retval
= jtag_vpi_state_move(TAP_DRSHIFT
);
409 if (retval
!= ERROR_OK
)
413 if (cmd
->end_state
== TAP_DRSHIFT
) {
414 retval
= jtag_vpi_queue_tdi(buf
, scan_bits
, NO_TAP_SHIFT
);
415 if (retval
!= ERROR_OK
)
418 retval
= jtag_vpi_queue_tdi(buf
, scan_bits
, TAP_SHIFT
);
419 if (retval
!= ERROR_OK
)
423 if (cmd
->end_state
!= TAP_DRSHIFT
) {
425 * As our JTAG is in an unstable state (IREXIT1 or DREXIT1), move it
426 * forward to a stable IRPAUSE or DRPAUSE.
428 retval
= jtag_vpi_clock_tms(0);
429 if (retval
!= ERROR_OK
)
433 tap_set_state(TAP_IRPAUSE
);
435 tap_set_state(TAP_DRPAUSE
);
438 retval
= jtag_read_buffer(buf
, cmd
);
439 if (retval
!= ERROR_OK
)
444 if (cmd
->end_state
!= TAP_DRSHIFT
) {
445 retval
= jtag_vpi_state_move(cmd
->end_state
);
446 if (retval
!= ERROR_OK
)
453 static int jtag_vpi_runtest(int cycles
, tap_state_t state
)
457 retval
= jtag_vpi_state_move(TAP_IDLE
);
458 if (retval
!= ERROR_OK
)
461 retval
= jtag_vpi_queue_tdi(NULL
, cycles
, NO_TAP_SHIFT
);
462 if (retval
!= ERROR_OK
)
465 return jtag_vpi_state_move(state
);
468 static int jtag_vpi_stableclocks(int cycles
)
471 int cycles_remain
= cycles
;
474 const int CYCLES_ONE_BATCH
= sizeof(tms_bits
) * 8;
478 /* use TMS=1 in TAP RESET state, TMS=0 in all other stable states */
479 memset(&tms_bits
, (tap_get_state() == TAP_RESET
) ? 0xff : 0x00, sizeof(tms_bits
));
481 /* send the TMS bits */
482 while (cycles_remain
> 0) {
483 nb_bits
= (cycles_remain
< CYCLES_ONE_BATCH
) ? cycles_remain
: CYCLES_ONE_BATCH
;
484 retval
= jtag_vpi_tms_seq(tms_bits
, nb_bits
);
485 if (retval
!= ERROR_OK
)
487 cycles_remain
-= nb_bits
;
493 static int jtag_vpi_execute_queue(void)
495 struct jtag_command
*cmd
;
496 int retval
= ERROR_OK
;
498 for (cmd
= jtag_command_queue
; retval
== ERROR_OK
&& cmd
!= NULL
;
502 retval
= jtag_vpi_reset(cmd
->cmd
.reset
->trst
, cmd
->cmd
.reset
->srst
);
505 retval
= jtag_vpi_runtest(cmd
->cmd
.runtest
->num_cycles
,
506 cmd
->cmd
.runtest
->end_state
);
508 case JTAG_STABLECLOCKS
:
509 retval
= jtag_vpi_stableclocks(cmd
->cmd
.stableclocks
->num_cycles
);
512 retval
= jtag_vpi_state_move(cmd
->cmd
.statemove
->end_state
);
515 retval
= jtag_vpi_path_move(cmd
->cmd
.pathmove
);
518 retval
= jtag_vpi_tms(cmd
->cmd
.tms
);
521 jtag_sleep(cmd
->cmd
.sleep
->us
);
524 retval
= jtag_vpi_scan(cmd
->cmd
.scan
);
527 LOG_ERROR("BUG: unknown JTAG command type 0x%X",
537 static int jtag_vpi_init(void)
541 sockfd
= socket(AF_INET
, SOCK_STREAM
, 0);
543 LOG_ERROR("Could not create socket");
547 memset(&serv_addr
, 0, sizeof(serv_addr
));
549 serv_addr
.sin_family
= AF_INET
;
550 serv_addr
.sin_port
= htons(server_port
);
553 server_address
= strdup(SERVER_ADDRESS
);
555 serv_addr
.sin_addr
.s_addr
= inet_addr(server_address
);
557 if (serv_addr
.sin_addr
.s_addr
== INADDR_NONE
) {
558 LOG_ERROR("inet_addr error occurred");
562 if (connect(sockfd
, (struct sockaddr
*)&serv_addr
, sizeof(serv_addr
)) < 0) {
564 LOG_ERROR("Can't connect to %s : %u", server_address
, server_port
);
565 return ERROR_COMMAND_CLOSE_CONNECTION
;
568 if (serv_addr
.sin_addr
.s_addr
== htonl(INADDR_LOOPBACK
)) {
569 /* This increases performance dramatically for local
570 * connections, which is the most likely arrangement
571 * for a VPI connection. */
572 setsockopt(sockfd
, IPPROTO_TCP
, TCP_NODELAY
, (char *)&flag
, sizeof(int));
575 LOG_INFO("Connection to %s : %u succeed", server_address
, server_port
);
580 static int jtag_vpi_stop_simulation(void)
583 memset(&cmd
, 0, sizeof(struct vpi_cmd
));
586 cmd
.cmd
= CMD_STOP_SIMU
;
587 return jtag_vpi_send_cmd(&cmd
);
590 static int jtag_vpi_quit(void)
592 if (stop_sim_on_exit
) {
593 if (jtag_vpi_stop_simulation() != ERROR_OK
)
594 LOG_WARNING("jtag_vpi: failed to send \"stop simulation\" command");
596 if (close_socket(sockfd
) != 0) {
597 LOG_WARNING("jtag_vpi: could not close jtag_vpi client socket");
598 log_socket_error("jtag_vpi");
600 free(server_address
);
604 COMMAND_HANDLER(jtag_vpi_set_port
)
607 LOG_WARNING("You need to set a port number");
609 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], server_port
);
611 LOG_INFO("Set server port to %u", server_port
);
616 COMMAND_HANDLER(jtag_vpi_set_address
)
618 free(server_address
);
621 LOG_WARNING("You need to set an address");
622 server_address
= strdup(SERVER_ADDRESS
);
624 server_address
= strdup(CMD_ARGV
[0]);
626 LOG_INFO("Set server address to %s", server_address
);
631 COMMAND_HANDLER(jtag_vpi_stop_sim_on_exit_handler
)
634 LOG_ERROR("jtag_vpi_stop_sim_on_exit expects 1 argument (on|off)");
635 return ERROR_COMMAND_SYNTAX_ERROR
;
637 COMMAND_PARSE_ON_OFF(CMD_ARGV
[0], stop_sim_on_exit
);
642 static const struct command_registration jtag_vpi_command_handlers
[] = {
644 .name
= "jtag_vpi_set_port",
645 .handler
= &jtag_vpi_set_port
,
646 .mode
= COMMAND_CONFIG
,
647 .help
= "set the port of the VPI server",
648 .usage
= "tcp_port_num",
651 .name
= "jtag_vpi_set_address",
652 .handler
= &jtag_vpi_set_address
,
653 .mode
= COMMAND_CONFIG
,
654 .help
= "set the address of the VPI server",
655 .usage
= "ipv4_addr",
658 .name
= "jtag_vpi_stop_sim_on_exit",
659 .handler
= &jtag_vpi_stop_sim_on_exit_handler
,
660 .mode
= COMMAND_CONFIG
,
661 .help
= "Configure if simulation stop command shall be sent "
662 "before OpenOCD exits (default: off)",
665 COMMAND_REGISTRATION_DONE
668 static struct jtag_interface jtag_vpi_interface
= {
669 .supported
= DEBUG_CAP_TMS_SEQ
,
670 .execute_queue
= jtag_vpi_execute_queue
,
673 struct adapter_driver jtag_vpi_adapter_driver
= {
675 .transports
= jtag_only
,
676 .commands
= jtag_vpi_command_handlers
,
678 .init
= jtag_vpi_init
,
679 .quit
= jtag_vpi_quit
,
681 .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)