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 #include <arpa/inet.h>
28 #define NO_TAP_SHIFT 0
31 #define SERVER_ADDRESS "127.0.0.1"
32 #define SERVER_PORT 5555
34 #define XFERT_MAX_SIZE 512
38 #define CMD_SCAN_CHAIN 2
39 #define CMD_SCAN_CHAIN_FLIP_TMS 3
40 #define CMD_STOP_SIMU 4
42 int server_port
= SERVER_PORT
;
45 struct sockaddr_in serv_addr
;
49 unsigned char buffer_out
[XFERT_MAX_SIZE
];
50 unsigned char buffer_in
[XFERT_MAX_SIZE
];
55 static int jtag_vpi_send_cmd(struct vpi_cmd
*vpi
)
57 int retval
= write(sockfd
, vpi
, sizeof(struct vpi_cmd
));
64 static int jtag_vpi_receive_cmd(struct vpi_cmd
*vpi
)
66 int retval
= read(sockfd
, vpi
, sizeof(struct vpi_cmd
));
67 if (retval
< (int)sizeof(struct vpi_cmd
))
74 * jtag_vpi_reset - ask to reset the JTAG device
75 * @trst: 1 if TRST is to be asserted
76 * @srst: 1 if SRST is to be asserted
78 static int jtag_vpi_reset(int trst
, int srst
)
84 return jtag_vpi_send_cmd(&vpi
);
88 * jtag_vpi_tms_seq - ask a TMS sequence transition to JTAG
89 * @bits: TMS bits to be written (bit0, bit1 .. bitN)
90 * @nb_bits: number of TMS bits (between 1 and 8)
92 * Write a serie of TMS transitions, where each transition consists in :
93 * - writing out TCK=0, TMS=<new_state>, TDI=<???>
94 * - writing out TCK=1, TMS=<new_state>, TDI=<???> which triggers the transition
95 * The function ensures that at the end of the sequence, the clock (TCK) is put
98 static int jtag_vpi_tms_seq(const uint8_t *bits
, int nb_bits
)
103 nb_bytes
= DIV_ROUND_UP(nb_bits
, 8);
105 vpi
.cmd
= CMD_TMS_SEQ
;
106 memcpy(vpi
.buffer_out
, bits
, nb_bytes
);
107 vpi
.length
= nb_bytes
;
108 vpi
.nb_bits
= nb_bits
;
110 return jtag_vpi_send_cmd(&vpi
);
114 * jtag_vpi_path_move - ask a TMS sequence transition to JTAG
115 * @cmd: path transition
117 * Write a serie of TMS transitions, where each transition consists in :
118 * - writing out TCK=0, TMS=<new_state>, TDI=<???>
119 * - writing out TCK=1, TMS=<new_state>, TDI=<???> which triggers the transition
120 * The function ensures that at the end of the sequence, the clock (TCK) is put
124 static int jtag_vpi_path_move(struct pathmove_command
*cmd
)
126 uint8_t trans
[DIV_ROUND_UP(cmd
->num_states
, 8)];
128 memset(trans
, 0, DIV_ROUND_UP(cmd
->num_states
, 8));
130 for (int i
= 0; i
< cmd
->num_states
; i
++) {
131 if (tap_state_transition(tap_get_state(), true) == cmd
->path
[i
])
132 buf_set_u32(trans
, i
, 1, 1);
133 tap_set_state(cmd
->path
[i
]);
136 return jtag_vpi_tms_seq(trans
, cmd
->num_states
);
140 * jtag_vpi_tms - ask a tms command
143 static int jtag_vpi_tms(struct tms_command
*cmd
)
145 return jtag_vpi_tms_seq(cmd
->bits
, cmd
->num_bits
);
148 static int jtag_vpi_state_move(tap_state_t state
)
150 if (tap_get_state() == state
)
153 uint8_t tms_scan
= tap_get_tms_path(tap_get_state(), state
);
154 int tms_len
= tap_get_tms_path_len(tap_get_state(), state
);
156 int retval
= jtag_vpi_tms_seq(&tms_scan
, tms_len
);
157 if (retval
!= ERROR_OK
)
160 tap_set_state(state
);
165 static int jtag_vpi_queue_tdi_xfer(uint8_t *bits
, int nb_bits
, int tap_shift
)
168 int nb_bytes
= DIV_ROUND_UP(nb_bits
, 8);
170 vpi
.cmd
= tap_shift
? CMD_SCAN_CHAIN_FLIP_TMS
: CMD_SCAN_CHAIN
;
173 memcpy(vpi
.buffer_out
, bits
, nb_bytes
);
175 memset(vpi
.buffer_out
, 0xff, nb_bytes
);
177 vpi
.length
= nb_bytes
;
178 vpi
.nb_bits
= nb_bits
;
180 int retval
= jtag_vpi_send_cmd(&vpi
);
181 if (retval
!= ERROR_OK
)
184 retval
= jtag_vpi_receive_cmd(&vpi
);
185 if (retval
!= ERROR_OK
)
189 memcpy(bits
, vpi
.buffer_in
, nb_bytes
);
195 * jtag_vpi_queue_tdi - short description
196 * @bits: bits to be queued on TDI (or NULL if 0 are to be queued)
197 * @nb_bits: number of bits
199 static int jtag_vpi_queue_tdi(uint8_t *bits
, int nb_bits
, int tap_shift
)
201 int nb_xfer
= DIV_ROUND_UP(nb_bits
, XFERT_MAX_SIZE
* 8);
202 uint8_t *xmit_buffer
= bits
;
203 int xmit_nb_bits
= nb_bits
;
210 retval
= jtag_vpi_queue_tdi_xfer(&xmit_buffer
[i
], xmit_nb_bits
, tap_shift
);
211 if (retval
!= ERROR_OK
)
214 retval
= jtag_vpi_queue_tdi_xfer(&xmit_buffer
[i
], XFERT_MAX_SIZE
* 8, NO_TAP_SHIFT
);
215 if (retval
!= ERROR_OK
)
217 xmit_nb_bits
-= XFERT_MAX_SIZE
* 8;
228 * jtag_vpi_clock_tms - clock a TMS transition
229 * @tms: the TMS to be sent
231 * Triggers a TMS transition (ie. one JTAG TAP state move).
233 static int jtag_vpi_clock_tms(int tms
)
235 const uint8_t tms_0
= 0;
236 const uint8_t tms_1
= 1;
238 return jtag_vpi_tms_seq(tms
? &tms_1
: &tms_0
, 1);
242 * jtag_vpi_scan - launches a DR-scan or IR-scan
243 * @cmd: the command to launch
245 * Launch a JTAG IR-scan or DR-scan
247 * Returns ERROR_OK if OK, ERROR_xxx if a read/write error occured.
249 static int jtag_vpi_scan(struct scan_command
*cmd
)
253 int retval
= ERROR_OK
;
255 scan_bits
= jtag_build_buffer(cmd
, &buf
);
258 retval
= jtag_vpi_state_move(TAP_IRSHIFT
);
259 if (retval
!= ERROR_OK
)
262 retval
= jtag_vpi_state_move(TAP_DRSHIFT
);
263 if (retval
!= ERROR_OK
)
267 if (cmd
->end_state
== TAP_DRSHIFT
) {
268 retval
= jtag_vpi_queue_tdi(buf
, scan_bits
, NO_TAP_SHIFT
);
269 if (retval
!= ERROR_OK
)
272 retval
= jtag_vpi_queue_tdi(buf
, scan_bits
, TAP_SHIFT
);
273 if (retval
!= ERROR_OK
)
277 if (cmd
->end_state
!= TAP_DRSHIFT
) {
279 * As our JTAG is in an unstable state (IREXIT1 or DREXIT1), move it
280 * forward to a stable IRPAUSE or DRPAUSE.
282 retval
= jtag_vpi_clock_tms(0);
283 if (retval
!= ERROR_OK
)
287 tap_set_state(TAP_IRPAUSE
);
289 tap_set_state(TAP_DRPAUSE
);
292 retval
= jtag_read_buffer(buf
, cmd
);
293 if (retval
!= ERROR_OK
)
299 if (cmd
->end_state
!= TAP_DRSHIFT
) {
300 retval
= jtag_vpi_state_move(cmd
->end_state
);
301 if (retval
!= ERROR_OK
)
308 static int jtag_vpi_runtest(int cycles
, tap_state_t state
)
312 retval
= jtag_vpi_state_move(TAP_IDLE
);
313 if (retval
!= ERROR_OK
)
316 retval
= jtag_vpi_queue_tdi(NULL
, cycles
, TAP_SHIFT
);
317 if (retval
!= ERROR_OK
)
320 return jtag_vpi_state_move(state
);
323 static int jtag_vpi_stableclocks(int cycles
)
325 return jtag_vpi_queue_tdi(NULL
, cycles
, TAP_SHIFT
);
328 static int jtag_vpi_execute_queue(void)
330 struct jtag_command
*cmd
;
331 int retval
= ERROR_OK
;
333 for (cmd
= jtag_command_queue
; retval
== ERROR_OK
&& cmd
!= NULL
;
337 retval
= jtag_vpi_reset(cmd
->cmd
.reset
->trst
, cmd
->cmd
.reset
->srst
);
340 retval
= jtag_vpi_runtest(cmd
->cmd
.runtest
->num_cycles
,
341 cmd
->cmd
.runtest
->end_state
);
343 case JTAG_STABLECLOCKS
:
344 retval
= jtag_vpi_stableclocks(cmd
->cmd
.stableclocks
->num_cycles
);
347 retval
= jtag_vpi_state_move(cmd
->cmd
.statemove
->end_state
);
350 retval
= jtag_vpi_path_move(cmd
->cmd
.pathmove
);
353 retval
= jtag_vpi_tms(cmd
->cmd
.tms
);
356 jtag_sleep(cmd
->cmd
.sleep
->us
);
359 retval
= jtag_vpi_scan(cmd
->cmd
.scan
);
367 static int jtag_vpi_init(void)
369 sockfd
= socket(AF_INET
, SOCK_STREAM
, 0);
371 LOG_ERROR("Could not create socket");
375 memset(&serv_addr
, 0, sizeof(serv_addr
));
377 serv_addr
.sin_family
= AF_INET
;
378 serv_addr
.sin_port
= htons(server_port
);
380 if (inet_pton(AF_INET
, SERVER_ADDRESS
, &serv_addr
.sin_addr
) <= 0) {
381 LOG_ERROR("inet_pton error occured");
385 if (connect(sockfd
, (struct sockaddr
*)&serv_addr
, sizeof(serv_addr
)) < 0) {
387 LOG_ERROR("Can't connect to %s : %u", SERVER_ADDRESS
, server_port
);
388 return ERROR_COMMAND_CLOSE_CONNECTION
;
391 LOG_INFO("Connection to %s : %u succeed", SERVER_ADDRESS
, server_port
);
396 static int jtag_vpi_quit(void)
398 return close(sockfd
);
401 COMMAND_HANDLER(jtag_vpi_set_port
)
404 LOG_WARNING("You need to set a port number");
406 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], server_port
);
408 LOG_INFO("Set server port to %u", server_port
);
414 static const struct command_registration jtag_vpi_command_handlers
[] = {
416 .name
= "jtag_vpi_set_port",
417 .handler
= &jtag_vpi_set_port
,
418 .mode
= COMMAND_CONFIG
,
419 .help
= "set the port of the VPI server",
420 .usage
= "description_string",
422 COMMAND_REGISTRATION_DONE
425 struct jtag_interface jtag_vpi_interface
= {
427 .supported
= DEBUG_CAP_TMS_SEQ
,
428 .commands
= jtag_vpi_command_handlers
,
429 .transports
= jtag_only
,
431 .init
= jtag_vpi_init
,
432 .quit
= jtag_vpi_quit
,
433 .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)