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>
36 #include "helper/replacements.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("jtag_vpi: 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 * @param trst 1 if TRST is to be asserted
212 * @param 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 * @param bits TMS bits to be written (bit0, bit1 .. bitN)
227 * @param 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 * @param 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
279 * @param cmd 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 * @param bits bits to be queued on TDI (or NULL if 0 are to be queued)
346 * @param nb_bits number of bits
349 static int jtag_vpi_queue_tdi(uint8_t *bits
, int nb_bits
, int tap_shift
)
351 int nb_xfer
= DIV_ROUND_UP(nb_bits
, XFERT_MAX_SIZE
* 8);
356 retval
= jtag_vpi_queue_tdi_xfer(bits
, nb_bits
, tap_shift
);
357 if (retval
!= ERROR_OK
)
360 retval
= jtag_vpi_queue_tdi_xfer(bits
, XFERT_MAX_SIZE
* 8, NO_TAP_SHIFT
);
361 if (retval
!= ERROR_OK
)
363 nb_bits
-= XFERT_MAX_SIZE
* 8;
365 bits
+= XFERT_MAX_SIZE
;
375 * jtag_vpi_clock_tms - clock a TMS transition
376 * @param tms the TMS to be sent
378 * Triggers a TMS transition (ie. one JTAG TAP state move).
380 static int jtag_vpi_clock_tms(int tms
)
382 const uint8_t tms_0
= 0;
383 const uint8_t tms_1
= 1;
385 return jtag_vpi_tms_seq(tms
? &tms_1
: &tms_0
, 1);
389 * jtag_vpi_scan - launches a DR-scan or IR-scan
390 * @param cmd the command to launch
392 * Launch a JTAG IR-scan or DR-scan
394 * Returns ERROR_OK if OK, ERROR_xxx if a read/write error occurred.
396 static int jtag_vpi_scan(struct scan_command
*cmd
)
400 int retval
= ERROR_OK
;
402 scan_bits
= jtag_build_buffer(cmd
, &buf
);
405 retval
= jtag_vpi_state_move(TAP_IRSHIFT
);
406 if (retval
!= ERROR_OK
)
409 retval
= jtag_vpi_state_move(TAP_DRSHIFT
);
410 if (retval
!= ERROR_OK
)
414 if (cmd
->end_state
== TAP_DRSHIFT
) {
415 retval
= jtag_vpi_queue_tdi(buf
, scan_bits
, NO_TAP_SHIFT
);
416 if (retval
!= ERROR_OK
)
419 retval
= jtag_vpi_queue_tdi(buf
, scan_bits
, TAP_SHIFT
);
420 if (retval
!= ERROR_OK
)
424 if (cmd
->end_state
!= TAP_DRSHIFT
) {
426 * As our JTAG is in an unstable state (IREXIT1 or DREXIT1), move it
427 * forward to a stable IRPAUSE or DRPAUSE.
429 retval
= jtag_vpi_clock_tms(0);
430 if (retval
!= ERROR_OK
)
434 tap_set_state(TAP_IRPAUSE
);
436 tap_set_state(TAP_DRPAUSE
);
439 retval
= jtag_read_buffer(buf
, cmd
);
440 if (retval
!= ERROR_OK
)
445 if (cmd
->end_state
!= TAP_DRSHIFT
) {
446 retval
= jtag_vpi_state_move(cmd
->end_state
);
447 if (retval
!= ERROR_OK
)
454 static int jtag_vpi_runtest(int cycles
, tap_state_t state
)
458 retval
= jtag_vpi_state_move(TAP_IDLE
);
459 if (retval
!= ERROR_OK
)
462 retval
= jtag_vpi_queue_tdi(NULL
, cycles
, NO_TAP_SHIFT
);
463 if (retval
!= ERROR_OK
)
466 return jtag_vpi_state_move(state
);
469 static int jtag_vpi_stableclocks(int cycles
)
472 int cycles_remain
= cycles
;
475 const int CYCLES_ONE_BATCH
= sizeof(tms_bits
) * 8;
479 /* use TMS=1 in TAP RESET state, TMS=0 in all other stable states */
480 memset(&tms_bits
, (tap_get_state() == TAP_RESET
) ? 0xff : 0x00, sizeof(tms_bits
));
482 /* send the TMS bits */
483 while (cycles_remain
> 0) {
484 nb_bits
= (cycles_remain
< CYCLES_ONE_BATCH
) ? cycles_remain
: CYCLES_ONE_BATCH
;
485 retval
= jtag_vpi_tms_seq(tms_bits
, nb_bits
);
486 if (retval
!= ERROR_OK
)
488 cycles_remain
-= nb_bits
;
494 static int jtag_vpi_execute_queue(void)
496 struct jtag_command
*cmd
;
497 int retval
= ERROR_OK
;
499 for (cmd
= jtag_command_queue
; retval
== ERROR_OK
&& cmd
;
503 retval
= jtag_vpi_reset(cmd
->cmd
.reset
->trst
, cmd
->cmd
.reset
->srst
);
506 retval
= jtag_vpi_runtest(cmd
->cmd
.runtest
->num_cycles
,
507 cmd
->cmd
.runtest
->end_state
);
509 case JTAG_STABLECLOCKS
:
510 retval
= jtag_vpi_stableclocks(cmd
->cmd
.stableclocks
->num_cycles
);
513 retval
= jtag_vpi_state_move(cmd
->cmd
.statemove
->end_state
);
516 retval
= jtag_vpi_path_move(cmd
->cmd
.pathmove
);
519 retval
= jtag_vpi_tms(cmd
->cmd
.tms
);
522 jtag_sleep(cmd
->cmd
.sleep
->us
);
525 retval
= jtag_vpi_scan(cmd
->cmd
.scan
);
528 LOG_ERROR("BUG: unknown JTAG command type 0x%X",
538 static int jtag_vpi_init(void)
542 sockfd
= socket(AF_INET
, SOCK_STREAM
, 0);
544 LOG_ERROR("jtag_vpi: Could not create client socket");
548 memset(&serv_addr
, 0, sizeof(serv_addr
));
550 serv_addr
.sin_family
= AF_INET
;
551 serv_addr
.sin_port
= htons(server_port
);
554 server_address
= strdup(SERVER_ADDRESS
);
556 serv_addr
.sin_addr
.s_addr
= inet_addr(server_address
);
558 if (serv_addr
.sin_addr
.s_addr
== INADDR_NONE
) {
559 LOG_ERROR("jtag_vpi: inet_addr error occurred");
563 if (connect(sockfd
, (struct sockaddr
*)&serv_addr
, sizeof(serv_addr
)) < 0) {
565 LOG_ERROR("jtag_vpi: Can't connect to %s : %u", server_address
, server_port
);
566 return ERROR_COMMAND_CLOSE_CONNECTION
;
569 if (serv_addr
.sin_addr
.s_addr
== htonl(INADDR_LOOPBACK
)) {
570 /* This increases performance dramatically for local
571 * connections, which is the most likely arrangement
572 * for a VPI connection. */
573 setsockopt(sockfd
, IPPROTO_TCP
, TCP_NODELAY
, (char *)&flag
, sizeof(int));
576 LOG_INFO("jtag_vpi: Connection to %s : %u successful", server_address
, server_port
);
581 static int jtag_vpi_stop_simulation(void)
584 memset(&cmd
, 0, sizeof(struct vpi_cmd
));
587 cmd
.cmd
= CMD_STOP_SIMU
;
588 return jtag_vpi_send_cmd(&cmd
);
591 static int jtag_vpi_quit(void)
593 if (stop_sim_on_exit
) {
594 if (jtag_vpi_stop_simulation() != ERROR_OK
)
595 LOG_WARNING("jtag_vpi: failed to send \"stop simulation\" command");
597 if (close_socket(sockfd
) != 0) {
598 LOG_WARNING("jtag_vpi: could not close jtag_vpi client socket");
599 log_socket_error("jtag_vpi");
601 free(server_address
);
605 COMMAND_HANDLER(jtag_vpi_set_port
)
608 LOG_WARNING("You need to set a port number");
610 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], server_port
);
612 LOG_INFO("Set server port to %u", server_port
);
617 COMMAND_HANDLER(jtag_vpi_set_address
)
619 free(server_address
);
622 LOG_WARNING("You need to set an address");
623 server_address
= strdup(SERVER_ADDRESS
);
625 server_address
= strdup(CMD_ARGV
[0]);
627 LOG_INFO("Set server address to %s", server_address
);
632 COMMAND_HANDLER(jtag_vpi_stop_sim_on_exit_handler
)
635 LOG_ERROR("jtag_vpi_stop_sim_on_exit expects 1 argument (on|off)");
636 return ERROR_COMMAND_SYNTAX_ERROR
;
638 COMMAND_PARSE_ON_OFF(CMD_ARGV
[0], stop_sim_on_exit
);
643 static const struct command_registration jtag_vpi_subcommand_handlers
[] = {
646 .handler
= &jtag_vpi_set_port
,
647 .mode
= COMMAND_CONFIG
,
648 .help
= "set the port of the VPI server",
649 .usage
= "tcp_port_num",
652 .name
= "set_address",
653 .handler
= &jtag_vpi_set_address
,
654 .mode
= COMMAND_CONFIG
,
655 .help
= "set the address of the VPI server",
656 .usage
= "ipv4_addr",
659 .name
= "stop_sim_on_exit",
660 .handler
= &jtag_vpi_stop_sim_on_exit_handler
,
661 .mode
= COMMAND_CONFIG
,
662 .help
= "Configure if simulation stop command shall be sent "
663 "before OpenOCD exits (default: off)",
666 COMMAND_REGISTRATION_DONE
669 static const struct command_registration jtag_vpi_command_handlers
[] = {
673 .help
= "perform jtag_vpi management",
674 .chain
= jtag_vpi_subcommand_handlers
,
677 COMMAND_REGISTRATION_DONE
680 static struct jtag_interface jtag_vpi_interface
= {
681 .supported
= DEBUG_CAP_TMS_SEQ
,
682 .execute_queue
= jtag_vpi_execute_queue
,
685 struct adapter_driver jtag_vpi_adapter_driver
= {
687 .transports
= jtag_only
,
688 .commands
= jtag_vpi_command_handlers
,
690 .init
= jtag_vpi_init
,
691 .quit
= jtag_vpi_quit
,
693 .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)