7c42220d62ef4c9e357db54a7bd0faad23d28d4e
[openocd.git] / src / jtag / drivers / jtag_vpi.c
1 /*
2 * JTAG to VPI driver
3 *
4 * Copyright (C) 2013 Franck Jullien, <elec4fun@gmail.com>
5 *
6 * See file CREDITS for list of people who contributed to this
7 * project.
8 *
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.
13 *
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.
18 *
19 */
20
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24
25 #include <jtag/interface.h>
26 #ifdef HAVE_ARPA_INET_H
27 #include <arpa/inet.h>
28 #endif
29
30 #define NO_TAP_SHIFT 0
31 #define TAP_SHIFT 1
32
33 #define SERVER_ADDRESS "127.0.0.1"
34 #define SERVER_PORT 5555
35
36 #define XFERT_MAX_SIZE 512
37
38 #define CMD_RESET 0
39 #define CMD_TMS_SEQ 1
40 #define CMD_SCAN_CHAIN 2
41 #define CMD_SCAN_CHAIN_FLIP_TMS 3
42 #define CMD_STOP_SIMU 4
43
44 int server_port = SERVER_PORT;
45 char *server_address;
46
47 int sockfd;
48 struct sockaddr_in serv_addr;
49
50 struct vpi_cmd {
51 int cmd;
52 unsigned char buffer_out[XFERT_MAX_SIZE];
53 unsigned char buffer_in[XFERT_MAX_SIZE];
54 int length;
55 int nb_bits;
56 };
57
58 static int jtag_vpi_send_cmd(struct vpi_cmd *vpi)
59 {
60 int retval = write_socket(sockfd, vpi, sizeof(struct vpi_cmd));
61 if (retval <= 0)
62 return ERROR_FAIL;
63
64 return ERROR_OK;
65 }
66
67 static int jtag_vpi_receive_cmd(struct vpi_cmd *vpi)
68 {
69 int retval = read_socket(sockfd, vpi, sizeof(struct vpi_cmd));
70 if (retval < (int)sizeof(struct vpi_cmd))
71 return ERROR_FAIL;
72
73 return ERROR_OK;
74 }
75
76 /**
77 * jtag_vpi_reset - ask to reset the JTAG device
78 * @trst: 1 if TRST is to be asserted
79 * @srst: 1 if SRST is to be asserted
80 */
81 static int jtag_vpi_reset(int trst, int srst)
82 {
83 struct vpi_cmd vpi;
84
85 vpi.cmd = CMD_RESET;
86 vpi.length = 0;
87 return jtag_vpi_send_cmd(&vpi);
88 }
89
90 /**
91 * jtag_vpi_tms_seq - ask a TMS sequence transition to JTAG
92 * @bits: TMS bits to be written (bit0, bit1 .. bitN)
93 * @nb_bits: number of TMS bits (between 1 and 8)
94 *
95 * Write a serie of TMS transitions, where each transition consists in :
96 * - writing out TCK=0, TMS=<new_state>, TDI=<???>
97 * - writing out TCK=1, TMS=<new_state>, TDI=<???> which triggers the transition
98 * The function ensures that at the end of the sequence, the clock (TCK) is put
99 * low.
100 */
101 static int jtag_vpi_tms_seq(const uint8_t *bits, int nb_bits)
102 {
103 struct vpi_cmd vpi;
104 int nb_bytes;
105
106 nb_bytes = DIV_ROUND_UP(nb_bits, 8);
107
108 vpi.cmd = CMD_TMS_SEQ;
109 memcpy(vpi.buffer_out, bits, nb_bytes);
110 vpi.length = nb_bytes;
111 vpi.nb_bits = nb_bits;
112
113 return jtag_vpi_send_cmd(&vpi);
114 }
115
116 /**
117 * jtag_vpi_path_move - ask a TMS sequence transition to JTAG
118 * @cmd: path transition
119 *
120 * Write a serie of TMS transitions, where each transition consists in :
121 * - writing out TCK=0, TMS=<new_state>, TDI=<???>
122 * - writing out TCK=1, TMS=<new_state>, TDI=<???> which triggers the transition
123 * The function ensures that at the end of the sequence, the clock (TCK) is put
124 * low.
125 */
126
127 static int jtag_vpi_path_move(struct pathmove_command *cmd)
128 {
129 uint8_t trans[DIV_ROUND_UP(cmd->num_states, 8)];
130
131 memset(trans, 0, DIV_ROUND_UP(cmd->num_states, 8));
132
133 for (int i = 0; i < cmd->num_states; i++) {
134 if (tap_state_transition(tap_get_state(), true) == cmd->path[i])
135 buf_set_u32(trans, i, 1, 1);
136 tap_set_state(cmd->path[i]);
137 }
138
139 return jtag_vpi_tms_seq(trans, cmd->num_states);
140 }
141
142 /**
143 * jtag_vpi_tms - ask a tms command
144 * @cmd: tms command
145 */
146 static int jtag_vpi_tms(struct tms_command *cmd)
147 {
148 return jtag_vpi_tms_seq(cmd->bits, cmd->num_bits);
149 }
150
151 static int jtag_vpi_state_move(tap_state_t state)
152 {
153 if (tap_get_state() == state)
154 return ERROR_OK;
155
156 uint8_t tms_scan = tap_get_tms_path(tap_get_state(), state);
157 int tms_len = tap_get_tms_path_len(tap_get_state(), state);
158
159 int retval = jtag_vpi_tms_seq(&tms_scan, tms_len);
160 if (retval != ERROR_OK)
161 return retval;
162
163 tap_set_state(state);
164
165 return ERROR_OK;
166 }
167
168 static int jtag_vpi_queue_tdi_xfer(uint8_t *bits, int nb_bits, int tap_shift)
169 {
170 struct vpi_cmd vpi;
171 int nb_bytes = DIV_ROUND_UP(nb_bits, 8);
172
173 vpi.cmd = tap_shift ? CMD_SCAN_CHAIN_FLIP_TMS : CMD_SCAN_CHAIN;
174
175 if (bits)
176 memcpy(vpi.buffer_out, bits, nb_bytes);
177 else
178 memset(vpi.buffer_out, 0xff, nb_bytes);
179
180 vpi.length = nb_bytes;
181 vpi.nb_bits = nb_bits;
182
183 int retval = jtag_vpi_send_cmd(&vpi);
184 if (retval != ERROR_OK)
185 return retval;
186
187 retval = jtag_vpi_receive_cmd(&vpi);
188 if (retval != ERROR_OK)
189 return retval;
190
191 if (bits)
192 memcpy(bits, vpi.buffer_in, nb_bytes);
193
194 return ERROR_OK;
195 }
196
197 /**
198 * jtag_vpi_queue_tdi - short description
199 * @bits: bits to be queued on TDI (or NULL if 0 are to be queued)
200 * @nb_bits: number of bits
201 */
202 static int jtag_vpi_queue_tdi(uint8_t *bits, int nb_bits, int tap_shift)
203 {
204 int nb_xfer = DIV_ROUND_UP(nb_bits, XFERT_MAX_SIZE * 8);
205 uint8_t *xmit_buffer = bits;
206 int xmit_nb_bits = nb_bits;
207 int i = 0;
208 int retval;
209
210 while (nb_xfer) {
211
212 if (nb_xfer == 1) {
213 retval = jtag_vpi_queue_tdi_xfer(&xmit_buffer[i], xmit_nb_bits, tap_shift);
214 if (retval != ERROR_OK)
215 return retval;
216 } else {
217 retval = jtag_vpi_queue_tdi_xfer(&xmit_buffer[i], XFERT_MAX_SIZE * 8, NO_TAP_SHIFT);
218 if (retval != ERROR_OK)
219 return retval;
220 xmit_nb_bits -= XFERT_MAX_SIZE * 8;
221 i += XFERT_MAX_SIZE;
222 }
223
224 nb_xfer--;
225 }
226
227 return ERROR_OK;
228 }
229
230 /**
231 * jtag_vpi_clock_tms - clock a TMS transition
232 * @tms: the TMS to be sent
233 *
234 * Triggers a TMS transition (ie. one JTAG TAP state move).
235 */
236 static int jtag_vpi_clock_tms(int tms)
237 {
238 const uint8_t tms_0 = 0;
239 const uint8_t tms_1 = 1;
240
241 return jtag_vpi_tms_seq(tms ? &tms_1 : &tms_0, 1);
242 }
243
244 /**
245 * jtag_vpi_scan - launches a DR-scan or IR-scan
246 * @cmd: the command to launch
247 *
248 * Launch a JTAG IR-scan or DR-scan
249 *
250 * Returns ERROR_OK if OK, ERROR_xxx if a read/write error occured.
251 */
252 static int jtag_vpi_scan(struct scan_command *cmd)
253 {
254 int scan_bits;
255 uint8_t *buf = NULL;
256 int retval = ERROR_OK;
257
258 scan_bits = jtag_build_buffer(cmd, &buf);
259
260 if (cmd->ir_scan) {
261 retval = jtag_vpi_state_move(TAP_IRSHIFT);
262 if (retval != ERROR_OK)
263 return retval;
264 } else {
265 retval = jtag_vpi_state_move(TAP_DRSHIFT);
266 if (retval != ERROR_OK)
267 return retval;
268 }
269
270 if (cmd->end_state == TAP_DRSHIFT) {
271 retval = jtag_vpi_queue_tdi(buf, scan_bits, NO_TAP_SHIFT);
272 if (retval != ERROR_OK)
273 return retval;
274 } else {
275 retval = jtag_vpi_queue_tdi(buf, scan_bits, TAP_SHIFT);
276 if (retval != ERROR_OK)
277 return retval;
278 }
279
280 if (cmd->end_state != TAP_DRSHIFT) {
281 /*
282 * As our JTAG is in an unstable state (IREXIT1 or DREXIT1), move it
283 * forward to a stable IRPAUSE or DRPAUSE.
284 */
285 retval = jtag_vpi_clock_tms(0);
286 if (retval != ERROR_OK)
287 return retval;
288
289 if (cmd->ir_scan)
290 tap_set_state(TAP_IRPAUSE);
291 else
292 tap_set_state(TAP_DRPAUSE);
293 }
294
295 retval = jtag_read_buffer(buf, cmd);
296 if (retval != ERROR_OK)
297 return retval;
298
299 if (buf)
300 free(buf);
301
302 if (cmd->end_state != TAP_DRSHIFT) {
303 retval = jtag_vpi_state_move(cmd->end_state);
304 if (retval != ERROR_OK)
305 return retval;
306 }
307
308 return ERROR_OK;
309 }
310
311 static int jtag_vpi_runtest(int cycles, tap_state_t state)
312 {
313 int retval;
314
315 retval = jtag_vpi_state_move(TAP_IDLE);
316 if (retval != ERROR_OK)
317 return retval;
318
319 retval = jtag_vpi_queue_tdi(NULL, cycles, TAP_SHIFT);
320 if (retval != ERROR_OK)
321 return retval;
322
323 return jtag_vpi_state_move(state);
324 }
325
326 static int jtag_vpi_stableclocks(int cycles)
327 {
328 return jtag_vpi_queue_tdi(NULL, cycles, TAP_SHIFT);
329 }
330
331 static int jtag_vpi_execute_queue(void)
332 {
333 struct jtag_command *cmd;
334 int retval = ERROR_OK;
335
336 for (cmd = jtag_command_queue; retval == ERROR_OK && cmd != NULL;
337 cmd = cmd->next) {
338 switch (cmd->type) {
339 case JTAG_RESET:
340 retval = jtag_vpi_reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst);
341 break;
342 case JTAG_RUNTEST:
343 retval = jtag_vpi_runtest(cmd->cmd.runtest->num_cycles,
344 cmd->cmd.runtest->end_state);
345 break;
346 case JTAG_STABLECLOCKS:
347 retval = jtag_vpi_stableclocks(cmd->cmd.stableclocks->num_cycles);
348 break;
349 case JTAG_TLR_RESET:
350 retval = jtag_vpi_state_move(cmd->cmd.statemove->end_state);
351 break;
352 case JTAG_PATHMOVE:
353 retval = jtag_vpi_path_move(cmd->cmd.pathmove);
354 break;
355 case JTAG_TMS:
356 retval = jtag_vpi_tms(cmd->cmd.tms);
357 break;
358 case JTAG_SLEEP:
359 jtag_sleep(cmd->cmd.sleep->us);
360 break;
361 case JTAG_SCAN:
362 retval = jtag_vpi_scan(cmd->cmd.scan);
363 break;
364 }
365 }
366
367 return retval;
368 }
369
370 static int jtag_vpi_init(void)
371 {
372 sockfd = socket(AF_INET, SOCK_STREAM, 0);
373 if (sockfd < 0) {
374 LOG_ERROR("Could not create socket");
375 return ERROR_FAIL;
376 }
377
378 memset(&serv_addr, 0, sizeof(serv_addr));
379
380 serv_addr.sin_family = AF_INET;
381 serv_addr.sin_port = htons(server_port);
382
383 if (!server_address)
384 server_address = strdup(SERVER_ADDRESS);
385
386 serv_addr.sin_addr.s_addr = inet_addr(server_address);
387
388 if (serv_addr.sin_addr.s_addr == INADDR_NONE) {
389 LOG_ERROR("inet_addr error occured");
390 return ERROR_FAIL;
391 }
392
393 if (connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
394 close(sockfd);
395 LOG_ERROR("Can't connect to %s : %u", server_address, server_port);
396 return ERROR_COMMAND_CLOSE_CONNECTION;
397 }
398
399 LOG_INFO("Connection to %s : %u succeed", server_address, server_port);
400
401 return ERROR_OK;
402 }
403
404 static int jtag_vpi_quit(void)
405 {
406 free(server_address);
407 return close(sockfd);
408 }
409
410 COMMAND_HANDLER(jtag_vpi_set_port)
411 {
412 if (CMD_ARGC == 0)
413 LOG_WARNING("You need to set a port number");
414 else
415 COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], server_port);
416
417 LOG_INFO("Set server port to %u", server_port);
418
419 return ERROR_OK;
420 }
421
422 COMMAND_HANDLER(jtag_vpi_set_address)
423 {
424 free(server_address);
425
426 if (CMD_ARGC == 0) {
427 LOG_WARNING("You need to set an address");
428 server_address = strdup(SERVER_ADDRESS);
429 } else
430 server_address = strdup(CMD_ARGV[0]);
431
432 LOG_INFO("Set server address to %s", server_address);
433
434 return ERROR_OK;
435 }
436
437 static const struct command_registration jtag_vpi_command_handlers[] = {
438 {
439 .name = "jtag_vpi_set_port",
440 .handler = &jtag_vpi_set_port,
441 .mode = COMMAND_CONFIG,
442 .help = "set the port of the VPI server",
443 .usage = "description_string",
444 },
445 {
446 .name = "jtag_vpi_set_address",
447 .handler = &jtag_vpi_set_address,
448 .mode = COMMAND_CONFIG,
449 .help = "set the address of the VPI server",
450 .usage = "description_string",
451 },
452 COMMAND_REGISTRATION_DONE
453 };
454
455 struct jtag_interface jtag_vpi_interface = {
456 .name = "jtag_vpi",
457 .supported = DEBUG_CAP_TMS_SEQ,
458 .commands = jtag_vpi_command_handlers,
459 .transports = jtag_only,
460
461 .init = jtag_vpi_init,
462 .quit = jtag_vpi_quit,
463 .execute_queue = jtag_vpi_execute_queue,
464 };

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)