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

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)