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_str(vpi
->buffer_out
,
107 (vpi
->nb_bits
> DEBUG_JTAG_IOZ
)
111 LOG_DEBUG_IO("sending JTAG VPI cmd: cmd=%s, "
112 "length=%" PRIu32
", "
113 "nb_bits=%" PRIu32
", "
115 jtag_vpi_cmd_to_str(vpi
->cmd
),
119 (vpi
->nb_bits
> DEBUG_JTAG_IOZ
) ? "(...)" : "");
122 /* command without data payload */
123 LOG_DEBUG_IO("sending JTAG VPI cmd: cmd=%s, "
124 "length=%" PRIu32
", "
126 jtag_vpi_cmd_to_str(vpi
->cmd
),
132 /* Use little endian when transmitting/receiving jtag_vpi cmds.
133 The choice of little endian goes against usual networking conventions
134 but is intentional to remain compatible with most older OpenOCD builds
135 (i.e. builds on little-endian platforms). */
136 h_u32_to_le(vpi
->cmd_buf
, vpi
->cmd
);
137 h_u32_to_le(vpi
->length_buf
, vpi
->length
);
138 h_u32_to_le(vpi
->nb_bits_buf
, vpi
->nb_bits
);
141 retval
= write_socket(sockfd
, vpi
, sizeof(struct vpi_cmd
));
144 /* Account for the case when socket write is interrupted. */
146 int wsa_err
= WSAGetLastError();
147 if (wsa_err
== WSAEINTR
)
153 /* Otherwise this is an error using the socket, most likely fatal
154 for the connection. B*/
155 log_socket_error("jtag_vpi xmit");
156 /* TODO: Clean way how adapter drivers can report fatal errors
157 to upper layers of OpenOCD and let it perform an orderly shutdown? */
159 } else if (retval
< (int)sizeof(struct vpi_cmd
)) {
160 /* This means we could not send all data, which is most likely fatal
161 for the jtag_vpi connection (the underlying TCP connection likely not
163 LOG_ERROR("Could not send all data through jtag_vpi connection.");
167 /* Otherwise the packet has been sent successfully. */
171 static int jtag_vpi_receive_cmd(struct vpi_cmd
*vpi
)
173 unsigned bytes_buffered
= 0;
174 while (bytes_buffered
< sizeof(struct vpi_cmd
)) {
175 int bytes_to_receive
= sizeof(struct vpi_cmd
) - bytes_buffered
;
176 int retval
= read_socket(sockfd
, ((char *)vpi
) + bytes_buffered
, bytes_to_receive
);
179 int wsa_err
= WSAGetLastError();
180 if (wsa_err
== WSAEINTR
) {
181 /* socket read interrupted by WSACancelBlockingCall() */
185 if (errno
== EINTR
) {
186 /* socket read interrupted by a signal */
190 /* Otherwise, this is an error when accessing the socket. */
191 log_socket_error("jtag_vpi recv");
193 } else if (retval
== 0) {
194 /* Connection closed by the other side */
195 LOG_ERROR("Connection prematurely closed by jtag_vpi server.");
198 /* Otherwise, we have successfully received some data */
199 bytes_buffered
+= retval
;
202 /* Use little endian when transmitting/receiving jtag_vpi cmds. */
203 vpi
->cmd
= le_to_h_u32(vpi
->cmd_buf
);
204 vpi
->length
= le_to_h_u32(vpi
->length_buf
);
205 vpi
->nb_bits
= le_to_h_u32(vpi
->nb_bits_buf
);
211 * jtag_vpi_reset - ask to reset the JTAG device
212 * @trst: 1 if TRST is to be asserted
213 * @srst: 1 if SRST is to be asserted
215 static int jtag_vpi_reset(int trst
, int srst
)
218 memset(&vpi
, 0, sizeof(struct vpi_cmd
));
222 return jtag_vpi_send_cmd(&vpi
);
226 * jtag_vpi_tms_seq - ask a TMS sequence transition to JTAG
227 * @bits: TMS bits to be written (bit0, bit1 .. bitN)
228 * @nb_bits: number of TMS bits (between 1 and 8)
230 * Write a serie of TMS transitions, where each transition consists in :
231 * - writing out TCK=0, TMS=<new_state>, TDI=<???>
232 * - writing out TCK=1, TMS=<new_state>, TDI=<???> which triggers the transition
233 * The function ensures that at the end of the sequence, the clock (TCK) is put
236 static int jtag_vpi_tms_seq(const uint8_t *bits
, int nb_bits
)
241 memset(&vpi
, 0, sizeof(struct vpi_cmd
));
242 nb_bytes
= DIV_ROUND_UP(nb_bits
, 8);
244 vpi
.cmd
= CMD_TMS_SEQ
;
245 memcpy(vpi
.buffer_out
, bits
, nb_bytes
);
246 vpi
.length
= nb_bytes
;
247 vpi
.nb_bits
= nb_bits
;
249 return jtag_vpi_send_cmd(&vpi
);
253 * jtag_vpi_path_move - ask a TMS sequence transition to JTAG
254 * @cmd: path transition
256 * Write a serie of TMS transitions, where each transition consists in :
257 * - writing out TCK=0, TMS=<new_state>, TDI=<???>
258 * - writing out TCK=1, TMS=<new_state>, TDI=<???> which triggers the transition
259 * The function ensures that at the end of the sequence, the clock (TCK) is put
263 static int jtag_vpi_path_move(struct pathmove_command
*cmd
)
265 uint8_t trans
[DIV_ROUND_UP(cmd
->num_states
, 8)];
267 memset(trans
, 0, DIV_ROUND_UP(cmd
->num_states
, 8));
269 for (int i
= 0; i
< cmd
->num_states
; i
++) {
270 if (tap_state_transition(tap_get_state(), true) == cmd
->path
[i
])
271 buf_set_u32(trans
, i
, 1, 1);
272 tap_set_state(cmd
->path
[i
]);
275 return jtag_vpi_tms_seq(trans
, cmd
->num_states
);
279 * jtag_vpi_tms - ask a tms command
282 static int jtag_vpi_tms(struct tms_command
*cmd
)
284 return jtag_vpi_tms_seq(cmd
->bits
, cmd
->num_bits
);
287 static int jtag_vpi_state_move(tap_state_t state
)
289 if (tap_get_state() == state
)
292 uint8_t tms_scan
= tap_get_tms_path(tap_get_state(), state
);
293 int tms_len
= tap_get_tms_path_len(tap_get_state(), state
);
295 int retval
= jtag_vpi_tms_seq(&tms_scan
, tms_len
);
296 if (retval
!= ERROR_OK
)
299 tap_set_state(state
);
304 static int jtag_vpi_queue_tdi_xfer(uint8_t *bits
, int nb_bits
, int tap_shift
)
307 int nb_bytes
= DIV_ROUND_UP(nb_bits
, 8);
309 memset(&vpi
, 0, sizeof(struct vpi_cmd
));
311 vpi
.cmd
= tap_shift
? CMD_SCAN_CHAIN_FLIP_TMS
: CMD_SCAN_CHAIN
;
314 memcpy(vpi
.buffer_out
, bits
, nb_bytes
);
316 memset(vpi
.buffer_out
, 0xff, nb_bytes
);
318 vpi
.length
= nb_bytes
;
319 vpi
.nb_bits
= nb_bits
;
321 int retval
= jtag_vpi_send_cmd(&vpi
);
322 if (retval
!= ERROR_OK
)
325 retval
= jtag_vpi_receive_cmd(&vpi
);
326 if (retval
!= ERROR_OK
)
329 /* Optional low-level JTAG debug */
330 if (LOG_LEVEL_IS(LOG_LVL_DEBUG_IO
)) {
331 char *char_buf
= buf_to_str(vpi
.buffer_in
,
332 (nb_bits
> DEBUG_JTAG_IOZ
) ? DEBUG_JTAG_IOZ
: nb_bits
,
334 LOG_DEBUG_IO("recvd JTAG VPI data: nb_bits=%d, buf_in=0x%s%s",
335 nb_bits
, char_buf
, (nb_bits
> DEBUG_JTAG_IOZ
) ? "(...)" : "");
340 memcpy(bits
, vpi
.buffer_in
, nb_bytes
);
346 * jtag_vpi_queue_tdi - short description
347 * @bits: bits to be queued on TDI (or NULL if 0 are to be queued)
348 * @nb_bits: number of bits
350 static int jtag_vpi_queue_tdi(uint8_t *bits
, int nb_bits
, int tap_shift
)
352 int nb_xfer
= DIV_ROUND_UP(nb_bits
, XFERT_MAX_SIZE
* 8);
357 retval
= jtag_vpi_queue_tdi_xfer(bits
, nb_bits
, tap_shift
);
358 if (retval
!= ERROR_OK
)
361 retval
= jtag_vpi_queue_tdi_xfer(bits
, XFERT_MAX_SIZE
* 8, NO_TAP_SHIFT
);
362 if (retval
!= ERROR_OK
)
364 nb_bits
-= XFERT_MAX_SIZE
* 8;
366 bits
+= XFERT_MAX_SIZE
;
376 * jtag_vpi_clock_tms - clock a TMS transition
377 * @tms: the TMS to be sent
379 * Triggers a TMS transition (ie. one JTAG TAP state move).
381 static int jtag_vpi_clock_tms(int tms
)
383 const uint8_t tms_0
= 0;
384 const uint8_t tms_1
= 1;
386 return jtag_vpi_tms_seq(tms
? &tms_1
: &tms_0
, 1);
390 * jtag_vpi_scan - launches a DR-scan or IR-scan
391 * @cmd: the command to launch
393 * Launch a JTAG IR-scan or DR-scan
395 * Returns ERROR_OK if OK, ERROR_xxx if a read/write error occured.
397 static int jtag_vpi_scan(struct scan_command
*cmd
)
401 int retval
= ERROR_OK
;
403 scan_bits
= jtag_build_buffer(cmd
, &buf
);
406 retval
= jtag_vpi_state_move(TAP_IRSHIFT
);
407 if (retval
!= ERROR_OK
)
410 retval
= jtag_vpi_state_move(TAP_DRSHIFT
);
411 if (retval
!= ERROR_OK
)
415 if (cmd
->end_state
== TAP_DRSHIFT
) {
416 retval
= jtag_vpi_queue_tdi(buf
, scan_bits
, NO_TAP_SHIFT
);
417 if (retval
!= ERROR_OK
)
420 retval
= jtag_vpi_queue_tdi(buf
, scan_bits
, TAP_SHIFT
);
421 if (retval
!= ERROR_OK
)
425 if (cmd
->end_state
!= TAP_DRSHIFT
) {
427 * As our JTAG is in an unstable state (IREXIT1 or DREXIT1), move it
428 * forward to a stable IRPAUSE or DRPAUSE.
430 retval
= jtag_vpi_clock_tms(0);
431 if (retval
!= ERROR_OK
)
435 tap_set_state(TAP_IRPAUSE
);
437 tap_set_state(TAP_DRPAUSE
);
440 retval
= jtag_read_buffer(buf
, cmd
);
441 if (retval
!= ERROR_OK
)
447 if (cmd
->end_state
!= TAP_DRSHIFT
) {
448 retval
= jtag_vpi_state_move(cmd
->end_state
);
449 if (retval
!= ERROR_OK
)
456 static int jtag_vpi_runtest(int cycles
, tap_state_t state
)
460 retval
= jtag_vpi_state_move(TAP_IDLE
);
461 if (retval
!= ERROR_OK
)
464 retval
= jtag_vpi_queue_tdi(NULL
, cycles
, NO_TAP_SHIFT
);
465 if (retval
!= ERROR_OK
)
468 return jtag_vpi_state_move(state
);
471 static int jtag_vpi_stableclocks(int cycles
)
474 int cycles_remain
= cycles
;
477 const int CYCLES_ONE_BATCH
= sizeof(tms_bits
) * 8;
481 /* use TMS=1 in TAP RESET state, TMS=0 in all other stable states */
482 memset(&tms_bits
, (tap_get_state() == TAP_RESET
) ? 0xff : 0x00, sizeof(tms_bits
));
484 /* send the TMS bits */
485 while (cycles_remain
> 0) {
486 nb_bits
= (cycles_remain
< CYCLES_ONE_BATCH
) ? cycles_remain
: CYCLES_ONE_BATCH
;
487 retval
= jtag_vpi_tms_seq(tms_bits
, nb_bits
);
488 if (retval
!= ERROR_OK
)
490 cycles_remain
-= nb_bits
;
496 static int jtag_vpi_execute_queue(void)
498 struct jtag_command
*cmd
;
499 int retval
= ERROR_OK
;
501 for (cmd
= jtag_command_queue
; retval
== ERROR_OK
&& cmd
!= NULL
;
505 retval
= jtag_vpi_reset(cmd
->cmd
.reset
->trst
, cmd
->cmd
.reset
->srst
);
508 retval
= jtag_vpi_runtest(cmd
->cmd
.runtest
->num_cycles
,
509 cmd
->cmd
.runtest
->end_state
);
511 case JTAG_STABLECLOCKS
:
512 retval
= jtag_vpi_stableclocks(cmd
->cmd
.stableclocks
->num_cycles
);
515 retval
= jtag_vpi_state_move(cmd
->cmd
.statemove
->end_state
);
518 retval
= jtag_vpi_path_move(cmd
->cmd
.pathmove
);
521 retval
= jtag_vpi_tms(cmd
->cmd
.tms
);
524 jtag_sleep(cmd
->cmd
.sleep
->us
);
527 retval
= jtag_vpi_scan(cmd
->cmd
.scan
);
530 LOG_ERROR("BUG: unknown JTAG command type 0x%X",
540 static int jtag_vpi_init(void)
544 sockfd
= socket(AF_INET
, SOCK_STREAM
, 0);
546 LOG_ERROR("Could not create socket");
550 memset(&serv_addr
, 0, sizeof(serv_addr
));
552 serv_addr
.sin_family
= AF_INET
;
553 serv_addr
.sin_port
= htons(server_port
);
556 server_address
= strdup(SERVER_ADDRESS
);
558 serv_addr
.sin_addr
.s_addr
= inet_addr(server_address
);
560 if (serv_addr
.sin_addr
.s_addr
== INADDR_NONE
) {
561 LOG_ERROR("inet_addr error occured");
565 if (connect(sockfd
, (struct sockaddr
*)&serv_addr
, sizeof(serv_addr
)) < 0) {
567 LOG_ERROR("Can't connect to %s : %u", server_address
, server_port
);
568 return ERROR_COMMAND_CLOSE_CONNECTION
;
571 if (serv_addr
.sin_addr
.s_addr
== htonl(INADDR_LOOPBACK
)) {
572 /* This increases performance drematically for local
573 * connections, which is the most likely arrangement
574 * for a VPI connection. */
575 setsockopt(sockfd
, IPPROTO_TCP
, TCP_NODELAY
, (char *)&flag
, sizeof(int));
578 LOG_INFO("Connection to %s : %u succeed", server_address
, server_port
);
583 static int jtag_vpi_stop_simulation(void)
586 memset(&cmd
, 0, sizeof(struct vpi_cmd
));
589 cmd
.cmd
= CMD_STOP_SIMU
;
590 return jtag_vpi_send_cmd(&cmd
);
593 static int jtag_vpi_quit(void)
595 if (stop_sim_on_exit
) {
596 if (jtag_vpi_stop_simulation() != ERROR_OK
)
597 LOG_WARNING("jtag_vpi: failed to send \"stop simulation\" command");
599 if (close_socket(sockfd
) != 0) {
600 LOG_WARNING("jtag_vpi: could not close jtag_vpi client socket");
601 log_socket_error("jtag_vpi");
603 free(server_address
);
607 COMMAND_HANDLER(jtag_vpi_set_port
)
610 LOG_WARNING("You need to set a port number");
612 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], server_port
);
614 LOG_INFO("Set server port to %u", server_port
);
619 COMMAND_HANDLER(jtag_vpi_set_address
)
621 free(server_address
);
624 LOG_WARNING("You need to set an address");
625 server_address
= strdup(SERVER_ADDRESS
);
627 server_address
= strdup(CMD_ARGV
[0]);
629 LOG_INFO("Set server address to %s", server_address
);
634 COMMAND_HANDLER(jtag_vpi_stop_sim_on_exit_handler
)
637 LOG_ERROR("jtag_vpi_stop_sim_on_exit expects 1 argument (on|off)");
638 return ERROR_COMMAND_SYNTAX_ERROR
;
640 COMMAND_PARSE_ON_OFF(CMD_ARGV
[0], stop_sim_on_exit
);
645 static const struct command_registration jtag_vpi_command_handlers
[] = {
647 .name
= "jtag_vpi_set_port",
648 .handler
= &jtag_vpi_set_port
,
649 .mode
= COMMAND_CONFIG
,
650 .help
= "set the port of the VPI server",
651 .usage
= "tcp_port_num",
654 .name
= "jtag_vpi_set_address",
655 .handler
= &jtag_vpi_set_address
,
656 .mode
= COMMAND_CONFIG
,
657 .help
= "set the address of the VPI server",
658 .usage
= "ipv4_addr",
661 .name
= "jtag_vpi_stop_sim_on_exit",
662 .handler
= &jtag_vpi_stop_sim_on_exit_handler
,
663 .mode
= COMMAND_CONFIG
,
664 .help
= "Configure if simulation stop command shall be sent "
665 "before OpenOCD exits (default: off)",
668 COMMAND_REGISTRATION_DONE
671 static struct jtag_interface jtag_vpi_interface
= {
672 .supported
= DEBUG_CAP_TMS_SEQ
,
673 .execute_queue
= jtag_vpi_execute_queue
,
676 struct adapter_driver jtag_vpi_adapter_driver
= {
678 .transports
= jtag_only
,
679 .commands
= jtag_vpi_command_handlers
,
681 .init
= jtag_vpi_init
,
682 .quit
= jtag_vpi_quit
,
684 .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)