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>
32 #define NO_TAP_SHIFT 0
35 #define SERVER_ADDRESS "127.0.0.1"
36 #define SERVER_PORT 5555
38 #define XFERT_MAX_SIZE 512
42 #define CMD_SCAN_CHAIN 2
43 #define CMD_SCAN_CHAIN_FLIP_TMS 3
44 #define CMD_STOP_SIMU 4
46 int server_port
= SERVER_PORT
;
50 struct sockaddr_in serv_addr
;
54 unsigned char buffer_out
[XFERT_MAX_SIZE
];
55 unsigned char buffer_in
[XFERT_MAX_SIZE
];
60 static int jtag_vpi_send_cmd(struct vpi_cmd
*vpi
)
62 int retval
= write_socket(sockfd
, vpi
, sizeof(struct vpi_cmd
));
69 static int jtag_vpi_receive_cmd(struct vpi_cmd
*vpi
)
71 int retval
= read_socket(sockfd
, vpi
, sizeof(struct vpi_cmd
));
72 if (retval
< (int)sizeof(struct vpi_cmd
))
79 * jtag_vpi_reset - ask to reset the JTAG device
80 * @trst: 1 if TRST is to be asserted
81 * @srst: 1 if SRST is to be asserted
83 static int jtag_vpi_reset(int trst
, int srst
)
89 return jtag_vpi_send_cmd(&vpi
);
93 * jtag_vpi_tms_seq - ask a TMS sequence transition to JTAG
94 * @bits: TMS bits to be written (bit0, bit1 .. bitN)
95 * @nb_bits: number of TMS bits (between 1 and 8)
97 * Write a serie of TMS transitions, where each transition consists in :
98 * - writing out TCK=0, TMS=<new_state>, TDI=<???>
99 * - writing out TCK=1, TMS=<new_state>, TDI=<???> which triggers the transition
100 * The function ensures that at the end of the sequence, the clock (TCK) is put
103 static int jtag_vpi_tms_seq(const uint8_t *bits
, int nb_bits
)
108 nb_bytes
= DIV_ROUND_UP(nb_bits
, 8);
110 vpi
.cmd
= CMD_TMS_SEQ
;
111 memcpy(vpi
.buffer_out
, bits
, nb_bytes
);
112 vpi
.length
= nb_bytes
;
113 vpi
.nb_bits
= nb_bits
;
115 return jtag_vpi_send_cmd(&vpi
);
119 * jtag_vpi_path_move - ask a TMS sequence transition to JTAG
120 * @cmd: path transition
122 * Write a serie of TMS transitions, where each transition consists in :
123 * - writing out TCK=0, TMS=<new_state>, TDI=<???>
124 * - writing out TCK=1, TMS=<new_state>, TDI=<???> which triggers the transition
125 * The function ensures that at the end of the sequence, the clock (TCK) is put
129 static int jtag_vpi_path_move(struct pathmove_command
*cmd
)
131 uint8_t trans
[DIV_ROUND_UP(cmd
->num_states
, 8)];
133 memset(trans
, 0, DIV_ROUND_UP(cmd
->num_states
, 8));
135 for (int i
= 0; i
< cmd
->num_states
; i
++) {
136 if (tap_state_transition(tap_get_state(), true) == cmd
->path
[i
])
137 buf_set_u32(trans
, i
, 1, 1);
138 tap_set_state(cmd
->path
[i
]);
141 return jtag_vpi_tms_seq(trans
, cmd
->num_states
);
145 * jtag_vpi_tms - ask a tms command
148 static int jtag_vpi_tms(struct tms_command
*cmd
)
150 return jtag_vpi_tms_seq(cmd
->bits
, cmd
->num_bits
);
153 static int jtag_vpi_state_move(tap_state_t state
)
155 if (tap_get_state() == state
)
158 uint8_t tms_scan
= tap_get_tms_path(tap_get_state(), state
);
159 int tms_len
= tap_get_tms_path_len(tap_get_state(), state
);
161 int retval
= jtag_vpi_tms_seq(&tms_scan
, tms_len
);
162 if (retval
!= ERROR_OK
)
165 tap_set_state(state
);
170 static int jtag_vpi_queue_tdi_xfer(uint8_t *bits
, int nb_bits
, int tap_shift
)
173 int nb_bytes
= DIV_ROUND_UP(nb_bits
, 8);
175 vpi
.cmd
= tap_shift
? CMD_SCAN_CHAIN_FLIP_TMS
: CMD_SCAN_CHAIN
;
178 memcpy(vpi
.buffer_out
, bits
, nb_bytes
);
180 memset(vpi
.buffer_out
, 0xff, nb_bytes
);
182 vpi
.length
= nb_bytes
;
183 vpi
.nb_bits
= nb_bits
;
185 int retval
= jtag_vpi_send_cmd(&vpi
);
186 if (retval
!= ERROR_OK
)
189 retval
= jtag_vpi_receive_cmd(&vpi
);
190 if (retval
!= ERROR_OK
)
194 memcpy(bits
, vpi
.buffer_in
, nb_bytes
);
200 * jtag_vpi_queue_tdi - short description
201 * @bits: bits to be queued on TDI (or NULL if 0 are to be queued)
202 * @nb_bits: number of bits
204 static int jtag_vpi_queue_tdi(uint8_t *bits
, int nb_bits
, int tap_shift
)
206 int nb_xfer
= DIV_ROUND_UP(nb_bits
, XFERT_MAX_SIZE
* 8);
207 uint8_t *xmit_buffer
= bits
;
208 int xmit_nb_bits
= nb_bits
;
215 retval
= jtag_vpi_queue_tdi_xfer(&xmit_buffer
[i
], xmit_nb_bits
, tap_shift
);
216 if (retval
!= ERROR_OK
)
219 retval
= jtag_vpi_queue_tdi_xfer(&xmit_buffer
[i
], XFERT_MAX_SIZE
* 8, NO_TAP_SHIFT
);
220 if (retval
!= ERROR_OK
)
222 xmit_nb_bits
-= XFERT_MAX_SIZE
* 8;
233 * jtag_vpi_clock_tms - clock a TMS transition
234 * @tms: the TMS to be sent
236 * Triggers a TMS transition (ie. one JTAG TAP state move).
238 static int jtag_vpi_clock_tms(int tms
)
240 const uint8_t tms_0
= 0;
241 const uint8_t tms_1
= 1;
243 return jtag_vpi_tms_seq(tms
? &tms_1
: &tms_0
, 1);
247 * jtag_vpi_scan - launches a DR-scan or IR-scan
248 * @cmd: the command to launch
250 * Launch a JTAG IR-scan or DR-scan
252 * Returns ERROR_OK if OK, ERROR_xxx if a read/write error occured.
254 static int jtag_vpi_scan(struct scan_command
*cmd
)
258 int retval
= ERROR_OK
;
260 scan_bits
= jtag_build_buffer(cmd
, &buf
);
263 retval
= jtag_vpi_state_move(TAP_IRSHIFT
);
264 if (retval
!= ERROR_OK
)
267 retval
= jtag_vpi_state_move(TAP_DRSHIFT
);
268 if (retval
!= ERROR_OK
)
272 if (cmd
->end_state
== TAP_DRSHIFT
) {
273 retval
= jtag_vpi_queue_tdi(buf
, scan_bits
, NO_TAP_SHIFT
);
274 if (retval
!= ERROR_OK
)
277 retval
= jtag_vpi_queue_tdi(buf
, scan_bits
, TAP_SHIFT
);
278 if (retval
!= ERROR_OK
)
282 if (cmd
->end_state
!= TAP_DRSHIFT
) {
284 * As our JTAG is in an unstable state (IREXIT1 or DREXIT1), move it
285 * forward to a stable IRPAUSE or DRPAUSE.
287 retval
= jtag_vpi_clock_tms(0);
288 if (retval
!= ERROR_OK
)
292 tap_set_state(TAP_IRPAUSE
);
294 tap_set_state(TAP_DRPAUSE
);
297 retval
= jtag_read_buffer(buf
, cmd
);
298 if (retval
!= ERROR_OK
)
304 if (cmd
->end_state
!= TAP_DRSHIFT
) {
305 retval
= jtag_vpi_state_move(cmd
->end_state
);
306 if (retval
!= ERROR_OK
)
313 static int jtag_vpi_runtest(int cycles
, tap_state_t state
)
317 retval
= jtag_vpi_state_move(TAP_IDLE
);
318 if (retval
!= ERROR_OK
)
321 retval
= jtag_vpi_queue_tdi(NULL
, cycles
, TAP_SHIFT
);
322 if (retval
!= ERROR_OK
)
325 return jtag_vpi_state_move(state
);
328 static int jtag_vpi_stableclocks(int cycles
)
330 return jtag_vpi_queue_tdi(NULL
, cycles
, TAP_SHIFT
);
333 static int jtag_vpi_execute_queue(void)
335 struct jtag_command
*cmd
;
336 int retval
= ERROR_OK
;
338 for (cmd
= jtag_command_queue
; retval
== ERROR_OK
&& cmd
!= NULL
;
342 retval
= jtag_vpi_reset(cmd
->cmd
.reset
->trst
, cmd
->cmd
.reset
->srst
);
345 retval
= jtag_vpi_runtest(cmd
->cmd
.runtest
->num_cycles
,
346 cmd
->cmd
.runtest
->end_state
);
348 case JTAG_STABLECLOCKS
:
349 retval
= jtag_vpi_stableclocks(cmd
->cmd
.stableclocks
->num_cycles
);
352 retval
= jtag_vpi_state_move(cmd
->cmd
.statemove
->end_state
);
355 retval
= jtag_vpi_path_move(cmd
->cmd
.pathmove
);
358 retval
= jtag_vpi_tms(cmd
->cmd
.tms
);
361 jtag_sleep(cmd
->cmd
.sleep
->us
);
364 retval
= jtag_vpi_scan(cmd
->cmd
.scan
);
372 static int jtag_vpi_init(void)
374 sockfd
= socket(AF_INET
, SOCK_STREAM
, 0);
376 LOG_ERROR("Could not create socket");
380 memset(&serv_addr
, 0, sizeof(serv_addr
));
382 serv_addr
.sin_family
= AF_INET
;
383 serv_addr
.sin_port
= htons(server_port
);
386 server_address
= strdup(SERVER_ADDRESS
);
388 serv_addr
.sin_addr
.s_addr
= inet_addr(server_address
);
390 if (serv_addr
.sin_addr
.s_addr
== INADDR_NONE
) {
391 LOG_ERROR("inet_addr error occured");
395 if (connect(sockfd
, (struct sockaddr
*)&serv_addr
, sizeof(serv_addr
)) < 0) {
397 LOG_ERROR("Can't connect to %s : %u", server_address
, server_port
);
398 return ERROR_COMMAND_CLOSE_CONNECTION
;
401 LOG_INFO("Connection to %s : %u succeed", server_address
, server_port
);
406 static int jtag_vpi_quit(void)
408 free(server_address
);
409 return close(sockfd
);
412 COMMAND_HANDLER(jtag_vpi_set_port
)
415 LOG_WARNING("You need to set a port number");
417 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], server_port
);
419 LOG_INFO("Set server port to %u", server_port
);
424 COMMAND_HANDLER(jtag_vpi_set_address
)
426 free(server_address
);
429 LOG_WARNING("You need to set an address");
430 server_address
= strdup(SERVER_ADDRESS
);
432 server_address
= strdup(CMD_ARGV
[0]);
434 LOG_INFO("Set server address to %s", server_address
);
439 static const struct command_registration jtag_vpi_command_handlers
[] = {
441 .name
= "jtag_vpi_set_port",
442 .handler
= &jtag_vpi_set_port
,
443 .mode
= COMMAND_CONFIG
,
444 .help
= "set the port of the VPI server",
445 .usage
= "description_string",
448 .name
= "jtag_vpi_set_address",
449 .handler
= &jtag_vpi_set_address
,
450 .mode
= COMMAND_CONFIG
,
451 .help
= "set the address of the VPI server",
452 .usage
= "description_string",
454 COMMAND_REGISTRATION_DONE
457 struct jtag_interface jtag_vpi_interface
= {
459 .supported
= DEBUG_CAP_TMS_SEQ
,
460 .commands
= jtag_vpi_command_handlers
,
461 .transports
= jtag_only
,
463 .init
= jtag_vpi_init
,
464 .quit
= jtag_vpi_quit
,
465 .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)