jtag newtap change & huge manual update
[openocd.git] / src / xsvf / xsvf.c
1 /***************************************************************************
2 * Copyright (C) 2005 by Dominic Rath *
3 * Dominic.Rath@gmx.de *
4 * *
5 * Copyright (C) 2007,2008 Øyvind Harboe *
6 * oyvind.harboe@zylin.com *
7 * *
8 * Copyright (C) 2008 Peter Hettkamp *
9 * peter.hettkamp@htp-tel.de *
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 * This program is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
19 * GNU General Public License for more details. *
20 * *
21 * You should have received a copy of the GNU General Public License *
22 * along with this program; if not, write to the *
23 * Free Software Foundation, Inc., *
24 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
25 ***************************************************************************/
26 #ifdef HAVE_CONFIG_H
27 #include "config.h"
28 #endif
29
30 #include "xsvf.h"
31
32 #include "jtag.h"
33 #include "command.h"
34 #include "log.h"
35
36 #include <stdlib.h>
37 #include <unistd.h>
38 #include <sys/types.h>
39 #include <sys/stat.h>
40 #include <fcntl.h>
41 #include <string.h>
42
43 #include <sys/time.h>
44 #include <time.h>
45
46 #define XSTATE_MAX_PATH (12)
47
48 int handle_xsvf_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
49
50 int xsvf_fd = 0;
51
52 u8 *dr_out_buf; /* from host to device (TDI) */
53 u8 *dr_in_buf; /* from device to host (TDO) */
54 u8 *dr_in_mask;
55
56 int xsdrsize = 0;
57 int xruntest = 0; /* number of TCK cycles / microseconds */
58 int xrepeat = 0x20; /* number of XC9500 retries */
59
60 int xendir = 0;
61 int xenddr = 0;
62
63 enum tap_state xsvf_to_tap[] =
64 {
65 TAP_TLR, TAP_RTI,
66 TAP_SDS, TAP_CD, TAP_SD, TAP_E1D, TAP_PD, TAP_E2D, TAP_UD,
67 TAP_SIS, TAP_CI, TAP_SI, TAP_E1I, TAP_PI, TAP_E2I, TAP_UI,
68 };
69
70 int tap_to_xsvf[] =
71 {
72 0x0, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x1, 0x9, 0xa, 0xb, 0xc, 0xe, 0xf
73 };
74
75
76 /* xsvf has it's own definition of a statemove. This needs
77 * to be handled according to the specs, which has nothing
78 * to do with the JTAG spec or OpenOCD as such.
79 *
80 * Implemented via jtag_add_pathmove().
81 */
82 void xsvf_add_statemove(enum tap_state state)
83 {
84 enum tap_state moves[7]; /* max # of transitions */
85 int i;
86 enum tap_state curstate = cmd_queue_cur_state;
87 u8 move = TAP_MOVE(cmd_queue_cur_state, state);
88
89 if ((state != TAP_TLR) && (state == cmd_queue_cur_state))
90 return;
91
92 if(state==TAP_TLR)
93 {
94 jtag_add_tlr();
95 return;
96 }
97 for (i=0; i<7; i++)
98 {
99 int j = (move >> i) & 1;
100 if (j)
101 {
102 curstate = tap_transitions[curstate].high;
103 } else
104 {
105 curstate = tap_transitions[curstate].low;
106 }
107 moves[i] = curstate;
108 }
109
110 jtag_add_pathmove(7, moves);
111 }
112
113 int xsvf_register_commands(struct command_context_s *cmd_ctx)
114 {
115 register_command(cmd_ctx, NULL, "xsvf", handle_xsvf_command,
116 COMMAND_EXEC, "run xsvf <file>");
117
118 return ERROR_OK;
119 }
120
121 int xsvf_read_buffer(int num_bits, int fd, u8* buf)
122 {
123 int num_bytes;
124
125 for (num_bytes = (num_bits + 7) / 8; num_bytes > 0; num_bytes--)
126 {
127 if (read(fd, buf + num_bytes - 1, 1) < 0)
128 return ERROR_XSVF_EOF;
129 }
130
131 return ERROR_OK;
132 }
133
134 int xsvf_read_xstates(int fd, enum tap_state *path, int max_path, int *path_len)
135 {
136 char c;
137 unsigned char uc;
138
139 while ((read(fd, &c, 1) > 0) && (c == 0x12))
140 {
141 if (*path_len > max_path)
142 {
143 LOG_WARNING("XSTATE path longer than max_path");
144 break;
145 }
146 if (read(fd, &uc, 1) < 0)
147 {
148 return ERROR_XSVF_EOF;
149 }
150 path[(*path_len)++] = xsvf_to_tap[uc];
151 }
152
153 lseek(fd, -1, SEEK_CUR);
154
155 return ERROR_OK;
156 }
157
158 int handle_xsvf_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
159 {
160 char c;
161 u8 buf4[4], buf2[2];
162 unsigned char uc, uc2;
163 unsigned int ui;
164 unsigned short us;
165
166 int do_abort = 0;
167 int unsupported = 0;
168 int tdo_mismatch = 0;
169
170 int runtest_requires_tck = 0;
171
172 jtag_tap_t *tap = NULL;
173 /* use NULL to indicate a "plain" xsvf file which accounts for
174 additional devices in the scan chain, otherwise the device
175 that should be affected */
176
177 if (argc < 2)
178 {
179 command_print(cmd_ctx, "usage: xsvf <device#|plain> <file> <variant>");
180 return ERROR_OK;
181 }
182
183 if (strcmp(args[0], "plain") != 0)
184 {
185 tap = jtag_TapByString( args[0] );
186 if( !tap ){
187 command_print( cmd_ctx, "Tap: %s unknown", args[0] );
188 return ERROR_OK;
189 }
190 }
191
192 if ((xsvf_fd = open(args[1], O_RDONLY)) < 0)
193 {
194 command_print(cmd_ctx, "file %s not found", args[0]);
195 return ERROR_OK;
196 }
197
198 if ((argc > 2) && (strcmp(args[2], "virt2") == 0))
199 {
200 runtest_requires_tck = 1;
201 }
202
203 while (read(xsvf_fd, &c, 1) > 0)
204 {
205 switch (c)
206 {
207 case 0x00: /* XCOMPLETE */
208 LOG_DEBUG("XCOMPLETE");
209 if (jtag_execute_queue() != ERROR_OK)
210 {
211 tdo_mismatch = 1;
212 break;
213 }
214 break;
215 case 0x01: /* XTDOMASK */
216 LOG_DEBUG("XTDOMASK");
217 if (dr_in_mask && (xsvf_read_buffer(xsdrsize, xsvf_fd, dr_in_mask) != ERROR_OK))
218 do_abort = 1;
219 break;
220 case 0x02: /* XSIR */
221 LOG_DEBUG("XSIR");
222 if (read(xsvf_fd, &c, 1) < 0)
223 do_abort = 1;
224 else
225 {
226 u8 *ir_buf = malloc((c + 7) / 8);
227 if (xsvf_read_buffer(c, xsvf_fd, ir_buf) != ERROR_OK)
228 do_abort = 1;
229 else
230 {
231 scan_field_t field;
232 field.tap = tap;
233 field.num_bits = c;
234 field.out_value = ir_buf;
235 field.out_mask = NULL;
236 field.in_value = NULL;
237 field.in_check_value = NULL;
238 field.in_check_mask = NULL;
239 field.in_handler = NULL;
240 field.in_handler_priv = NULL;
241 if (tap == NULL)
242 jtag_add_plain_ir_scan(1, &field, TAP_PI);
243 else
244 jtag_add_ir_scan(1, &field, TAP_PI);
245 if (jtag_execute_queue() != ERROR_OK)
246 {
247 tdo_mismatch = 1;
248 free(ir_buf);
249 break;
250 }
251 if (xruntest)
252 {
253 if (runtest_requires_tck)
254 jtag_add_runtest(xruntest, xsvf_to_tap[xendir]);
255 else
256 {
257 xsvf_add_statemove(TAP_RTI);
258 jtag_add_sleep(xruntest);
259 xsvf_add_statemove(xsvf_to_tap[xendir]);
260 }
261 }
262 else if (xendir != 0xd) /* Pause-IR */
263 xsvf_add_statemove(xsvf_to_tap[xendir]);
264 }
265 free(ir_buf);
266 }
267 break;
268 case 0x03: /* XSDR */
269 LOG_DEBUG("XSDR");
270 if (xsvf_read_buffer(xsdrsize, xsvf_fd, dr_out_buf) != ERROR_OK)
271 do_abort = 1;
272 else
273 {
274 scan_field_t field;
275 field.tap = tap;
276 field.num_bits = xsdrsize;
277 field.out_value = dr_out_buf;
278 field.out_mask = NULL;
279 field.in_value = NULL;
280 jtag_set_check_value(&field, dr_in_buf, dr_in_mask, NULL);
281 if (tap == NULL)
282 jtag_add_plain_dr_scan(1, &field, TAP_PD);
283 else
284 jtag_add_dr_scan(1, &field, TAP_PD);
285 if (jtag_execute_queue() != ERROR_OK)
286 {
287 tdo_mismatch = 1;
288 break;
289 }
290 if (xruntest)
291 {
292 if (runtest_requires_tck)
293 jtag_add_runtest(xruntest, xsvf_to_tap[xenddr]);
294 else
295 {
296 xsvf_add_statemove(TAP_RTI);
297 jtag_add_sleep(xruntest);
298 xsvf_add_statemove(xsvf_to_tap[xenddr]);
299 }
300 }
301 else if (xendir != 0x6) /* Pause-DR */
302 xsvf_add_statemove(xsvf_to_tap[xenddr]);
303 }
304 break;
305 case 0x04: /* XRUNTEST */
306 LOG_DEBUG("XRUNTEST");
307 if (read(xsvf_fd, buf4, 4) < 0)
308 do_abort = 1;
309 else
310 {
311 xruntest = be_to_h_u32(buf4);
312 }
313 break;
314 case 0x07: /* XREPEAT */
315 LOG_DEBUG("XREPEAT");
316 if (read(xsvf_fd, &c, 1) < 0)
317 do_abort = 1;
318 else
319 {
320 xrepeat = c;
321 }
322 break;
323 case 0x08: /* XSDRSIZE */
324 LOG_DEBUG("XSDRSIZE");
325 if (read(xsvf_fd, buf4, 4) < 0)
326 do_abort = 1;
327 else
328 {
329 xsdrsize = be_to_h_u32(buf4);
330 free(dr_out_buf);
331 free(dr_in_buf);
332 free(dr_in_mask);
333 dr_out_buf = malloc((xsdrsize + 7) / 8);
334 dr_in_buf = malloc((xsdrsize + 7) / 8);
335 dr_in_mask = malloc((xsdrsize + 7) / 8);
336 }
337 break;
338 case 0x09: /* XSDRTDO */
339 LOG_DEBUG("XSDRTDO");
340 if (xsvf_read_buffer(xsdrsize, xsvf_fd, dr_out_buf) != ERROR_OK)
341 do_abort = 1;
342 else
343 {
344 if (xsvf_read_buffer(xsdrsize, xsvf_fd, dr_in_buf) != ERROR_OK)
345 do_abort = 1;
346 else
347 {
348 scan_field_t field;
349 field.tap = tap;
350 field.num_bits = xsdrsize;
351 field.out_value = dr_out_buf;
352 field.out_mask = NULL;
353 field.in_value = NULL;
354 jtag_set_check_value(&field, dr_in_buf, dr_in_mask, NULL);
355 if (tap == NULL)
356 jtag_add_plain_dr_scan(1, &field, TAP_PD);
357 else
358 jtag_add_dr_scan(1, &field, TAP_PD);
359 if (jtag_execute_queue() != ERROR_OK)
360 {
361 tdo_mismatch = 1;
362 break;
363 }
364 if (xruntest)
365 {
366 if (runtest_requires_tck)
367 jtag_add_runtest(xruntest, xsvf_to_tap[xenddr]);
368 else
369 {
370 xsvf_add_statemove(TAP_RTI);
371 jtag_add_sleep(xruntest);
372 xsvf_add_statemove(xsvf_to_tap[xenddr]);
373 }
374 }
375 else if (xendir != 0x6) /* Pause-DR */
376 xsvf_add_statemove(xsvf_to_tap[xenddr]);
377 }
378 }
379 break;
380 case 0x0a: /* XSETDRMASKS */
381 LOG_ERROR("unsupported XSETSDRMASKS\n");
382 unsupported = 1;
383 break;
384 case 0x0b: /* XSDRINC */
385 LOG_ERROR("unsupported XSDRINC\n");
386 unsupported = 1;
387 break;
388 case 0x0c: /* XSDRB */
389 unsupported = 1;
390 break;
391 case 0x0d: /* XSDRC */
392 unsupported = 1;
393 break;
394 case 0x0e: /* XSDRE */
395 unsupported = 1;
396 break;
397 case 0x0f: /* XSDRTDOB */
398 unsupported = 1;
399 break;
400 case 0x10: /* XSDRTDOB */
401 unsupported = 1;
402 break;
403 case 0x11: /* XSDRTDOB */
404 unsupported = 1;
405 break;
406 case 0x12: /* XSTATE */
407 LOG_DEBUG("XSTATE");
408 if (read(xsvf_fd, &uc, 1) < 0)
409 do_abort = 1;
410 else
411 {
412 enum tap_state *path = calloc(XSTATE_MAX_PATH, 4);
413 int path_len = 1;
414 path[0] = xsvf_to_tap[uc];
415 if (xsvf_read_xstates(xsvf_fd, path, XSTATE_MAX_PATH, &path_len) != ERROR_OK)
416 do_abort = 1;
417 else
418 {
419 int i,lasti;
420 /* here the trick is that jtag_add_pathmove() must end in a stable
421 state, so we must only invoke jtag_add_tlr() when we absolutely
422 have to
423 */
424 for(i=0,lasti=0;i<path_len;i++)
425 {
426 if(path[i]==TAP_TLR)
427 {
428 if(i>lasti)
429 {
430 jtag_add_pathmove(i-lasti,path+lasti);
431 }
432 lasti=i+1;
433 jtag_add_tlr();
434 }
435 }
436 if(i>=lasti)
437 {
438 jtag_add_pathmove(i-lasti, path+lasti);
439 }
440 }
441 free(path);
442 }
443 break;
444 case 0x13: /* XENDIR */
445 LOG_DEBUG("XENDIR");
446 if (read(xsvf_fd, &c, 1) < 0)
447 do_abort = 1;
448 else
449 {
450 if (c == 0)
451 xendir = 1;
452 else if (c == 1)
453 xendir = 0xd;
454 else
455 {
456 LOG_ERROR("unknown XENDIR endstate");
457 unsupported = 1;
458 }
459 }
460 break;
461 case 0x14: /* XENDDR */
462 LOG_DEBUG("XENDDR");
463 if (read(xsvf_fd, &c, 1) < 0)
464 do_abort = 1;
465 else
466 {
467 if (c == 0)
468 xenddr = 1;
469 else if (c == 1)
470 xenddr = 0x6;
471 else
472 {
473 LOG_ERROR("unknown XENDDR endstate");
474 unsupported = 1;
475 }
476 }
477 break;
478 case 0x15: /* XSIR2 */
479 LOG_DEBUG("XSIR2");
480 if (read(xsvf_fd, buf2, 2) < 0)
481 do_abort = 1;
482 else
483 {
484 u8 *ir_buf;
485 us = be_to_h_u16(buf2);
486 ir_buf = malloc((us + 7) / 8);
487 if (xsvf_read_buffer(us, xsvf_fd, ir_buf) != ERROR_OK)
488 do_abort = 1;
489 else
490 {
491 scan_field_t field;
492 field.tap = tap;
493 field.num_bits = us;
494 field.out_value = ir_buf;
495 field.out_mask = NULL;
496 field.in_value = NULL;
497 field.in_check_value = NULL;
498 field.in_check_mask = NULL;
499 field.in_handler = NULL;
500 field.in_handler_priv = NULL;
501 if (tap == NULL)
502 jtag_add_plain_ir_scan(1, &field, xsvf_to_tap[xendir]);
503 else
504 jtag_add_ir_scan(1, &field, xsvf_to_tap[xendir]);
505 }
506 free(ir_buf);
507 }
508 break;
509 case 0x16: /* XCOMMENT */
510 do
511 {
512 if (read(xsvf_fd, &c, 1) < 0)
513 {
514 do_abort = 1;
515 break;
516 }
517 } while (c != 0);
518 break;
519 case 0x17: /* XWAIT */
520 LOG_DEBUG("XWAIT");
521 if ((read(xsvf_fd, &uc, 1) < 0) || (read(xsvf_fd, &uc2, 1) < 0) || (read(xsvf_fd, buf4, 4) < 0))
522 do_abort = 1;
523 else
524 {
525 xsvf_add_statemove(xsvf_to_tap[uc]);
526 ui = be_to_h_u32(buf4);
527 jtag_add_sleep(ui);
528 xsvf_add_statemove(xsvf_to_tap[uc2]);
529 }
530 break;
531 default:
532 LOG_ERROR("unknown xsvf command (0x%2.2x)\n", c);
533 unsupported = 1;
534 }
535
536 if (do_abort || unsupported || tdo_mismatch)
537 break;
538 }
539
540 if (tdo_mismatch)
541 {
542 command_print(cmd_ctx, "TDO mismatch, aborting");
543 return ERROR_OK;
544 }
545
546 if (unsupported)
547 {
548 command_print(cmd_ctx, "unsupported xsvf command encountered, aborting");
549 return ERROR_OK;
550 }
551
552 if (do_abort)
553 {
554 command_print(cmd_ctx, "premature end detected, aborting");
555 return ERROR_OK;
556 }
557
558 if (dr_out_buf)
559 free(dr_out_buf);
560
561 if (dr_in_buf)
562 free(dr_in_buf);
563
564 if (dr_in_mask)
565 free(dr_in_mask);
566
567 close(xsvf_fd);
568
569 command_print(cmd_ctx, "XSVF file programmed successfully");
570
571 return ERROR_OK;
572 }

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)