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.
25 #include <jtag/interface.h>
26 #ifdef HAVE_ARPA_INET_H
27 #include <arpa/inet.h>
30 #define NO_TAP_SHIFT 0
33 #define SERVER_ADDRESS "127.0.0.1"
34 #define SERVER_PORT 5555
36 #define XFERT_MAX_SIZE 512
40 #define CMD_SCAN_CHAIN 2
41 #define CMD_SCAN_CHAIN_FLIP_TMS 3
42 #define CMD_STOP_SIMU 4
44 int server_port
= SERVER_PORT
;
47 struct sockaddr_in serv_addr
;
51 unsigned char buffer_out
[XFERT_MAX_SIZE
];
52 unsigned char buffer_in
[XFERT_MAX_SIZE
];
57 static int jtag_vpi_send_cmd(struct vpi_cmd
*vpi
)
59 int retval
= write_socket(sockfd
, vpi
, sizeof(struct vpi_cmd
));
66 static int jtag_vpi_receive_cmd(struct vpi_cmd
*vpi
)
68 int retval
= read_socket(sockfd
, vpi
, sizeof(struct vpi_cmd
));
69 if (retval
< (int)sizeof(struct vpi_cmd
))
76 * jtag_vpi_reset - ask to reset the JTAG device
77 * @trst: 1 if TRST is to be asserted
78 * @srst: 1 if SRST is to be asserted
80 static int jtag_vpi_reset(int trst
, int srst
)
86 return jtag_vpi_send_cmd(&vpi
);
90 * jtag_vpi_tms_seq - ask a TMS sequence transition to JTAG
91 * @bits: TMS bits to be written (bit0, bit1 .. bitN)
92 * @nb_bits: number of TMS bits (between 1 and 8)
94 * Write a serie of TMS transitions, where each transition consists in :
95 * - writing out TCK=0, TMS=<new_state>, TDI=<???>
96 * - writing out TCK=1, TMS=<new_state>, TDI=<???> which triggers the transition
97 * The function ensures that at the end of the sequence, the clock (TCK) is put
100 static int jtag_vpi_tms_seq(const uint8_t *bits
, int nb_bits
)
105 nb_bytes
= DIV_ROUND_UP(nb_bits
, 8);
107 vpi
.cmd
= CMD_TMS_SEQ
;
108 memcpy(vpi
.buffer_out
, bits
, nb_bytes
);
109 vpi
.length
= nb_bytes
;
110 vpi
.nb_bits
= nb_bits
;
112 return jtag_vpi_send_cmd(&vpi
);
116 * jtag_vpi_path_move - ask a TMS sequence transition to JTAG
117 * @cmd: path transition
119 * Write a serie of TMS transitions, where each transition consists in :
120 * - writing out TCK=0, TMS=<new_state>, TDI=<???>
121 * - writing out TCK=1, TMS=<new_state>, TDI=<???> which triggers the transition
122 * The function ensures that at the end of the sequence, the clock (TCK) is put
126 static int jtag_vpi_path_move(struct pathmove_command
*cmd
)
128 uint8_t trans
[DIV_ROUND_UP(cmd
->num_states
, 8)];
130 memset(trans
, 0, DIV_ROUND_UP(cmd
->num_states
, 8));
132 for (int i
= 0; i
< cmd
->num_states
; i
++) {
133 if (tap_state_transition(tap_get_state(), true) == cmd
->path
[i
])
134 buf_set_u32(trans
, i
, 1, 1);
135 tap_set_state(cmd
->path
[i
]);
138 return jtag_vpi_tms_seq(trans
, cmd
->num_states
);
142 * jtag_vpi_tms - ask a tms command
145 static int jtag_vpi_tms(struct tms_command
*cmd
)
147 return jtag_vpi_tms_seq(cmd
->bits
, cmd
->num_bits
);
150 static int jtag_vpi_state_move(tap_state_t state
)
152 if (tap_get_state() == state
)
155 uint8_t tms_scan
= tap_get_tms_path(tap_get_state(), state
);
156 int tms_len
= tap_get_tms_path_len(tap_get_state(), state
);
158 int retval
= jtag_vpi_tms_seq(&tms_scan
, tms_len
);
159 if (retval
!= ERROR_OK
)
162 tap_set_state(state
);
167 static int jtag_vpi_queue_tdi_xfer(uint8_t *bits
, int nb_bits
, int tap_shift
)
170 int nb_bytes
= DIV_ROUND_UP(nb_bits
, 8);
172 vpi
.cmd
= tap_shift
? CMD_SCAN_CHAIN_FLIP_TMS
: CMD_SCAN_CHAIN
;
175 memcpy(vpi
.buffer_out
, bits
, nb_bytes
);
177 memset(vpi
.buffer_out
, 0xff, nb_bytes
);
179 vpi
.length
= nb_bytes
;
180 vpi
.nb_bits
= nb_bits
;
182 int retval
= jtag_vpi_send_cmd(&vpi
);
183 if (retval
!= ERROR_OK
)
186 retval
= jtag_vpi_receive_cmd(&vpi
);
187 if (retval
!= ERROR_OK
)
191 memcpy(bits
, vpi
.buffer_in
, nb_bytes
);
197 * jtag_vpi_queue_tdi - short description
198 * @bits: bits to be queued on TDI (or NULL if 0 are to be queued)
199 * @nb_bits: number of bits
201 static int jtag_vpi_queue_tdi(uint8_t *bits
, int nb_bits
, int tap_shift
)
203 int nb_xfer
= DIV_ROUND_UP(nb_bits
, XFERT_MAX_SIZE
* 8);
204 uint8_t *xmit_buffer
= bits
;
205 int xmit_nb_bits
= nb_bits
;
212 retval
= jtag_vpi_queue_tdi_xfer(&xmit_buffer
[i
], xmit_nb_bits
, tap_shift
);
213 if (retval
!= ERROR_OK
)
216 retval
= jtag_vpi_queue_tdi_xfer(&xmit_buffer
[i
], XFERT_MAX_SIZE
* 8, NO_TAP_SHIFT
);
217 if (retval
!= ERROR_OK
)
219 xmit_nb_bits
-= XFERT_MAX_SIZE
* 8;
230 * jtag_vpi_clock_tms - clock a TMS transition
231 * @tms: the TMS to be sent
233 * Triggers a TMS transition (ie. one JTAG TAP state move).
235 static int jtag_vpi_clock_tms(int tms
)
237 const uint8_t tms_0
= 0;
238 const uint8_t tms_1
= 1;
240 return jtag_vpi_tms_seq(tms
? &tms_1
: &tms_0
, 1);
244 * jtag_vpi_scan - launches a DR-scan or IR-scan
245 * @cmd: the command to launch
247 * Launch a JTAG IR-scan or DR-scan
249 * Returns ERROR_OK if OK, ERROR_xxx if a read/write error occured.
251 static int jtag_vpi_scan(struct scan_command
*cmd
)
255 int retval
= ERROR_OK
;
257 scan_bits
= jtag_build_buffer(cmd
, &buf
);
260 retval
= jtag_vpi_state_move(TAP_IRSHIFT
);
261 if (retval
!= ERROR_OK
)
264 retval
= jtag_vpi_state_move(TAP_DRSHIFT
);
265 if (retval
!= ERROR_OK
)
269 if (cmd
->end_state
== TAP_DRSHIFT
) {
270 retval
= jtag_vpi_queue_tdi(buf
, scan_bits
, NO_TAP_SHIFT
);
271 if (retval
!= ERROR_OK
)
274 retval
= jtag_vpi_queue_tdi(buf
, scan_bits
, TAP_SHIFT
);
275 if (retval
!= ERROR_OK
)
279 if (cmd
->end_state
!= TAP_DRSHIFT
) {
281 * As our JTAG is in an unstable state (IREXIT1 or DREXIT1), move it
282 * forward to a stable IRPAUSE or DRPAUSE.
284 retval
= jtag_vpi_clock_tms(0);
285 if (retval
!= ERROR_OK
)
289 tap_set_state(TAP_IRPAUSE
);
291 tap_set_state(TAP_DRPAUSE
);
294 retval
= jtag_read_buffer(buf
, cmd
);
295 if (retval
!= ERROR_OK
)
301 if (cmd
->end_state
!= TAP_DRSHIFT
) {
302 retval
= jtag_vpi_state_move(cmd
->end_state
);
303 if (retval
!= ERROR_OK
)
310 static int jtag_vpi_runtest(int cycles
, tap_state_t state
)
314 retval
= jtag_vpi_state_move(TAP_IDLE
);
315 if (retval
!= ERROR_OK
)
318 retval
= jtag_vpi_queue_tdi(NULL
, cycles
, TAP_SHIFT
);
319 if (retval
!= ERROR_OK
)
322 return jtag_vpi_state_move(state
);
325 static int jtag_vpi_stableclocks(int cycles
)
327 return jtag_vpi_queue_tdi(NULL
, cycles
, TAP_SHIFT
);
330 static int jtag_vpi_execute_queue(void)
332 struct jtag_command
*cmd
;
333 int retval
= ERROR_OK
;
335 for (cmd
= jtag_command_queue
; retval
== ERROR_OK
&& cmd
!= NULL
;
339 retval
= jtag_vpi_reset(cmd
->cmd
.reset
->trst
, cmd
->cmd
.reset
->srst
);
342 retval
= jtag_vpi_runtest(cmd
->cmd
.runtest
->num_cycles
,
343 cmd
->cmd
.runtest
->end_state
);
345 case JTAG_STABLECLOCKS
:
346 retval
= jtag_vpi_stableclocks(cmd
->cmd
.stableclocks
->num_cycles
);
349 retval
= jtag_vpi_state_move(cmd
->cmd
.statemove
->end_state
);
352 retval
= jtag_vpi_path_move(cmd
->cmd
.pathmove
);
355 retval
= jtag_vpi_tms(cmd
->cmd
.tms
);
358 jtag_sleep(cmd
->cmd
.sleep
->us
);
361 retval
= jtag_vpi_scan(cmd
->cmd
.scan
);
369 static int jtag_vpi_init(void)
371 sockfd
= socket(AF_INET
, SOCK_STREAM
, 0);
373 LOG_ERROR("Could not create socket");
377 memset(&serv_addr
, 0, sizeof(serv_addr
));
379 serv_addr
.sin_family
= AF_INET
;
380 serv_addr
.sin_port
= htons(server_port
);
382 serv_addr
.sin_addr
.s_addr
= inet_addr(SERVER_ADDRESS
);
384 if (serv_addr
.sin_addr
.s_addr
== INADDR_NONE
) {
385 LOG_ERROR("inet_addr error occured");
389 if (connect(sockfd
, (struct sockaddr
*)&serv_addr
, sizeof(serv_addr
)) < 0) {
391 LOG_ERROR("Can't connect to %s : %u", SERVER_ADDRESS
, server_port
);
392 return ERROR_COMMAND_CLOSE_CONNECTION
;
395 LOG_INFO("Connection to %s : %u succeed", SERVER_ADDRESS
, server_port
);
400 static int jtag_vpi_quit(void)
402 return close(sockfd
);
405 COMMAND_HANDLER(jtag_vpi_set_port
)
408 LOG_WARNING("You need to set a port number");
410 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], server_port
);
412 LOG_INFO("Set server port to %u", server_port
);
418 static const struct command_registration jtag_vpi_command_handlers
[] = {
420 .name
= "jtag_vpi_set_port",
421 .handler
= &jtag_vpi_set_port
,
422 .mode
= COMMAND_CONFIG
,
423 .help
= "set the port of the VPI server",
424 .usage
= "description_string",
426 COMMAND_REGISTRATION_DONE
429 struct jtag_interface jtag_vpi_interface
= {
431 .supported
= DEBUG_CAP_TMS_SEQ
,
432 .commands
= jtag_vpi_command_handlers
,
433 .transports
= jtag_only
,
435 .init
= jtag_vpi_init
,
436 .quit
= jtag_vpi_quit
,
437 .execute_queue
= jtag_vpi_execute_queue
,
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)