jtag_vpi: fix build errors under MinGW
[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
46 int sockfd;
47 struct sockaddr_in serv_addr;
48
49 struct vpi_cmd {
50 int cmd;
51 unsigned char buffer_out[XFERT_MAX_SIZE];
52 unsigned char buffer_in[XFERT_MAX_SIZE];
53 int length;
54 int nb_bits;
55 };
56
57 static int jtag_vpi_send_cmd(struct vpi_cmd *vpi)
58 {
59 int retval = write_socket(sockfd, vpi, sizeof(struct vpi_cmd));
60 if (retval <= 0)
61 return ERROR_FAIL;
62
63 return ERROR_OK;
64 }
65
66 static int jtag_vpi_receive_cmd(struct vpi_cmd *vpi)
67 {
68 int retval = read_socket(sockfd, vpi, sizeof(struct vpi_cmd));
69 if (retval < (int)sizeof(struct vpi_cmd))
70 return ERROR_FAIL;
71
72 return ERROR_OK;
73 }
74
75 /**
76 * jtag_vpi_reset - ask to reset the JTAG device
77 * @trst: 1 if TRST is to be asserted
78 * @srst: 1 if SRST is to be asserted
79 */
80 static int jtag_vpi_reset(int trst, int srst)
81 {
82 struct vpi_cmd vpi;
83
84 vpi.cmd = CMD_RESET;
85 vpi.length = 0;
86 return jtag_vpi_send_cmd(&vpi);
87 }
88
89 /**
90 * jtag_vpi_tms_seq - ask a TMS sequence transition to JTAG
91 * @bits: TMS bits to be written (bit0, bit1 .. bitN)
92 * @nb_bits: number of TMS bits (between 1 and 8)
93 *
94 * Write a serie of TMS transitions, where each transition consists in :
95 * - writing out TCK=0, TMS=<new_state>, TDI=<???>
96 * - writing out TCK=1, TMS=<new_state>, TDI=<???> which triggers the transition
97 * The function ensures that at the end of the sequence, the clock (TCK) is put
98 * low.
99 */
100 static int jtag_vpi_tms_seq(const uint8_t *bits, int nb_bits)
101 {
102 struct vpi_cmd vpi;
103 int nb_bytes;
104
105 nb_bytes = DIV_ROUND_UP(nb_bits, 8);
106
107 vpi.cmd = CMD_TMS_SEQ;
108 memcpy(vpi.buffer_out, bits, nb_bytes);
109 vpi.length = nb_bytes;
110 vpi.nb_bits = nb_bits;
111
112 return jtag_vpi_send_cmd(&vpi);
113 }
114
115 /**
116 * jtag_vpi_path_move - ask a TMS sequence transition to JTAG
117 * @cmd: path transition
118 *
119 * Write a serie of TMS transitions, where each transition consists in :
120 * - writing out TCK=0, TMS=<new_state>, TDI=<???>
121 * - writing out TCK=1, TMS=<new_state>, TDI=<???> which triggers the transition
122 * The function ensures that at the end of the sequence, the clock (TCK) is put
123 * low.
124 */
125
126 static int jtag_vpi_path_move(struct pathmove_command *cmd)
127 {
128 uint8_t trans[DIV_ROUND_UP(cmd->num_states, 8)];
129
130 memset(trans, 0, DIV_ROUND_UP(cmd->num_states, 8));
131
132 for (int i = 0; i < cmd->num_states; i++) {
133 if (tap_state_transition(tap_get_state(), true) == cmd->path[i])
134 buf_set_u32(trans, i, 1, 1);
135 tap_set_state(cmd->path[i]);
136 }
137
138 return jtag_vpi_tms_seq(trans, cmd->num_states);
139 }
140
141 /**
142 * jtag_vpi_tms - ask a tms command
143 * @cmd: tms command
144 */
145 static int jtag_vpi_tms(struct tms_command *cmd)
146 {
147 return jtag_vpi_tms_seq(cmd->bits, cmd->num_bits);
148 }
149
150 static int jtag_vpi_state_move(tap_state_t state)
151 {
152 if (tap_get_state() == state)
153 return ERROR_OK;
154
155 uint8_t tms_scan = tap_get_tms_path(tap_get_state(), state);
156 int tms_len = tap_get_tms_path_len(tap_get_state(), state);
157
158 int retval = jtag_vpi_tms_seq(&tms_scan, tms_len);
159 if (retval != ERROR_OK)
160 return retval;
161
162 tap_set_state(state);
163
164 return ERROR_OK;
165 }
166
167 static int jtag_vpi_queue_tdi_xfer(uint8_t *bits, int nb_bits, int tap_shift)
168 {
169 struct vpi_cmd vpi;
170 int nb_bytes = DIV_ROUND_UP(nb_bits, 8);
171
172 vpi.cmd = tap_shift ? CMD_SCAN_CHAIN_FLIP_TMS : CMD_SCAN_CHAIN;
173
174 if (bits)
175 memcpy(vpi.buffer_out, bits, nb_bytes);
176 else
177 memset(vpi.buffer_out, 0xff, nb_bytes);
178
179 vpi.length = nb_bytes;
180 vpi.nb_bits = nb_bits;
181
182 int retval = jtag_vpi_send_cmd(&vpi);
183 if (retval != ERROR_OK)
184 return retval;
185
186 retval = jtag_vpi_receive_cmd(&vpi);
187 if (retval != ERROR_OK)
188 return retval;
189
190 if (bits)
191 memcpy(bits, vpi.buffer_in, nb_bytes);
192
193 return ERROR_OK;
194 }
195
196 /**
197 * jtag_vpi_queue_tdi - short description
198 * @bits: bits to be queued on TDI (or NULL if 0 are to be queued)
199 * @nb_bits: number of bits
200 */
201 static int jtag_vpi_queue_tdi(uint8_t *bits, int nb_bits, int tap_shift)
202 {
203 int nb_xfer = DIV_ROUND_UP(nb_bits, XFERT_MAX_SIZE * 8);
204 uint8_t *xmit_buffer = bits;
205 int xmit_nb_bits = nb_bits;
206 int i = 0;
207 int retval;
208
209 while (nb_xfer) {
210
211 if (nb_xfer == 1) {
212 retval = jtag_vpi_queue_tdi_xfer(&xmit_buffer[i], xmit_nb_bits, tap_shift);
213 if (retval != ERROR_OK)
214 return retval;
215 } else {
216 retval = jtag_vpi_queue_tdi_xfer(&xmit_buffer[i], XFERT_MAX_SIZE * 8, NO_TAP_SHIFT);
217 if (retval != ERROR_OK)
218 return retval;
219 xmit_nb_bits -= XFERT_MAX_SIZE * 8;
220 i += 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 serv_addr.sin_addr.s_addr = inet_addr(SERVER_ADDRESS);
383
384 if (serv_addr.sin_addr.s_addr == INADDR_NONE) {
385 LOG_ERROR("inet_addr error occured");
386 return ERROR_FAIL;
387 }
388
389 if (connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
390 close(sockfd);
391 LOG_ERROR("Can't connect to %s : %u", SERVER_ADDRESS, server_port);
392 return ERROR_COMMAND_CLOSE_CONNECTION;
393 }
394
395 LOG_INFO("Connection to %s : %u succeed", SERVER_ADDRESS, server_port);
396
397 return ERROR_OK;
398 }
399
400 static int jtag_vpi_quit(void)
401 {
402 return close(sockfd);
403 }
404
405 COMMAND_HANDLER(jtag_vpi_set_port)
406 {
407 if (CMD_ARGC == 0)
408 LOG_WARNING("You need to set a port number");
409 else
410 COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], server_port);
411
412 LOG_INFO("Set server port to %u", server_port);
413
414 return ERROR_OK;
415 }
416
417
418 static const struct command_registration jtag_vpi_command_handlers[] = {
419 {
420 .name = "jtag_vpi_set_port",
421 .handler = &jtag_vpi_set_port,
422 .mode = COMMAND_CONFIG,
423 .help = "set the port of the VPI server",
424 .usage = "description_string",
425 },
426 COMMAND_REGISTRATION_DONE
427 };
428
429 struct jtag_interface jtag_vpi_interface = {
430 .name = "jtag_vpi",
431 .supported = DEBUG_CAP_TMS_SEQ,
432 .commands = jtag_vpi_command_handlers,
433 .transports = jtag_only,
434
435 .init = jtag_vpi_init,
436 .quit = jtag_vpi_quit,
437 .execute_queue = jtag_vpi_execute_queue,
438 };

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)