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

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)