jtag: rewrite command 'jtag names' as COMMAND_HANDLER
[openocd.git] / src / jtag / tcl.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2
3 /***************************************************************************
4 * Copyright (C) 2005 by Dominic Rath *
5 * Dominic.Rath@gmx.de *
6 * *
7 * Copyright (C) 2007-2010 Øyvind Harboe *
8 * oyvind.harboe@zylin.com *
9 * *
10 * Copyright (C) 2009 SoftPLC Corporation *
11 * http://softplc.com *
12 * dick@softplc.com *
13 * *
14 * Copyright (C) 2009 Zachary T Welch *
15 * zw@superlucidity.net *
16 ***************************************************************************/
17
18 #ifdef HAVE_CONFIG_H
19 #include "config.h"
20 #endif
21
22 #include "adapter.h"
23 #include "jtag.h"
24 #include "swd.h"
25 #include "minidriver.h"
26 #include "interface.h"
27 #include "interfaces.h"
28 #include "tcl.h"
29
30 #ifdef HAVE_STRINGS_H
31 #include <strings.h>
32 #endif
33
34 #include <helper/time_support.h>
35 #include "transport/transport.h"
36
37 /**
38 * @file
39 * Holds support for accessing JTAG-specific mechanisms from TCl scripts.
40 */
41
42 static const struct jim_nvp nvp_jtag_tap_event[] = {
43 { .value = JTAG_TRST_ASSERTED, .name = "post-reset" },
44 { .value = JTAG_TAP_EVENT_SETUP, .name = "setup" },
45 { .value = JTAG_TAP_EVENT_ENABLE, .name = "tap-enable" },
46 { .value = JTAG_TAP_EVENT_DISABLE, .name = "tap-disable" },
47
48 { .name = NULL, .value = -1 }
49 };
50
51 struct jtag_tap *jtag_tap_by_jim_obj(Jim_Interp *interp, Jim_Obj *o)
52 {
53 const char *cp = Jim_GetString(o, NULL);
54 struct jtag_tap *t = cp ? jtag_tap_by_string(cp) : NULL;
55 if (!cp)
56 cp = "(unknown)";
57 if (!t)
58 Jim_SetResultFormatted(interp, "Tap '%s' could not be found", cp);
59 return t;
60 }
61
62 static bool scan_is_safe(tap_state_t state)
63 {
64 switch (state) {
65 case TAP_RESET:
66 case TAP_IDLE:
67 case TAP_DRPAUSE:
68 case TAP_IRPAUSE:
69 return true;
70 default:
71 return false;
72 }
73 }
74
75 static int jim_command_drscan(Jim_Interp *interp, int argc, Jim_Obj * const *args)
76 {
77 int retval;
78 struct scan_field *fields;
79 int num_fields;
80 int field_count = 0;
81 int i, e;
82 struct jtag_tap *tap;
83 tap_state_t endstate;
84
85 /* args[1] = device
86 * args[2] = num_bits
87 * args[3] = hex string
88 * ... repeat num bits and hex string ...
89 *
90 * .. optionally:
91 * args[N-2] = "-endstate"
92 * args[N-1] = statename
93 */
94 if ((argc < 4) || ((argc % 2) != 0)) {
95 Jim_WrongNumArgs(interp, 1, args, "wrong arguments");
96 return JIM_ERR;
97 }
98
99 endstate = TAP_IDLE;
100
101 /* validate arguments as numbers */
102 e = JIM_OK;
103 for (i = 2; i < argc; i += 2) {
104 long bits;
105 const char *cp;
106
107 e = Jim_GetLong(interp, args[i], &bits);
108 /* If valid - try next arg */
109 if (e == JIM_OK)
110 continue;
111
112 /* Not valid.. are we at the end? */
113 if (((i + 2) != argc)) {
114 /* nope, then error */
115 return e;
116 }
117
118 /* it could be: "-endstate FOO"
119 * e.g. DRPAUSE so we can issue more instructions
120 * before entering RUN/IDLE and executing them.
121 */
122
123 /* get arg as a string. */
124 cp = Jim_GetString(args[i], NULL);
125 /* is it the magic? */
126 if (strcmp("-endstate", cp) == 0) {
127 /* is the statename valid? */
128 cp = Jim_GetString(args[i + 1], NULL);
129
130 /* see if it is a valid state name */
131 endstate = tap_state_by_name(cp);
132 if (endstate < 0) {
133 /* update the error message */
134 Jim_SetResultFormatted(interp, "endstate: %s invalid", cp);
135 } else {
136 if (!scan_is_safe(endstate))
137 LOG_WARNING("drscan with unsafe "
138 "endstate \"%s\"", cp);
139
140 /* valid - so clear the error */
141 e = JIM_OK;
142 /* and remove the last 2 args */
143 argc -= 2;
144 }
145 }
146
147 /* Still an error? */
148 if (e != JIM_OK)
149 return e; /* too bad */
150 } /* validate args */
151
152 assert(e == JIM_OK);
153
154 tap = jtag_tap_by_jim_obj(interp, args[1]);
155 if (!tap)
156 return JIM_ERR;
157
158 num_fields = (argc-2)/2;
159 if (num_fields <= 0) {
160 Jim_SetResultString(interp, "drscan: no scan fields supplied", -1);
161 return JIM_ERR;
162 }
163 fields = malloc(sizeof(struct scan_field) * num_fields);
164 for (i = 2; i < argc; i += 2) {
165 long bits;
166 int len;
167 const char *str;
168
169 Jim_GetLong(interp, args[i], &bits);
170 str = Jim_GetString(args[i + 1], &len);
171
172 fields[field_count].num_bits = bits;
173 void *t = malloc(DIV_ROUND_UP(bits, 8));
174 fields[field_count].out_value = t;
175 str_to_buf(str, len, t, bits, 0);
176 fields[field_count].in_value = t;
177 field_count++;
178 }
179
180 jtag_add_dr_scan(tap, num_fields, fields, endstate);
181
182 retval = jtag_execute_queue();
183 if (retval != ERROR_OK) {
184 Jim_SetResultString(interp, "drscan: jtag execute failed", -1);
185
186 for (i = 0; i < field_count; i++)
187 free(fields[i].in_value);
188 free(fields);
189
190 return JIM_ERR;
191 }
192
193 field_count = 0;
194 Jim_Obj *list = Jim_NewListObj(interp, NULL, 0);
195 for (i = 2; i < argc; i += 2) {
196 long bits;
197 char *str;
198
199 Jim_GetLong(interp, args[i], &bits);
200 str = buf_to_hex_str(fields[field_count].in_value, bits);
201 free(fields[field_count].in_value);
202
203 Jim_ListAppendElement(interp, list, Jim_NewStringObj(interp, str, strlen(str)));
204 free(str);
205 field_count++;
206 }
207
208 Jim_SetResult(interp, list);
209
210 free(fields);
211
212 return JIM_OK;
213 }
214
215
216 static int jim_command_pathmove(Jim_Interp *interp, int argc, Jim_Obj * const *args)
217 {
218 tap_state_t states[8];
219
220 if ((argc < 2) || ((size_t)argc > (ARRAY_SIZE(states) + 1))) {
221 Jim_WrongNumArgs(interp, 1, args, "wrong arguments");
222 return JIM_ERR;
223 }
224
225 int i;
226 for (i = 0; i < argc-1; i++) {
227 const char *cp;
228 cp = Jim_GetString(args[i + 1], NULL);
229 states[i] = tap_state_by_name(cp);
230 if (states[i] < 0) {
231 /* update the error message */
232 Jim_SetResultFormatted(interp, "endstate: %s invalid", cp);
233 return JIM_ERR;
234 }
235 }
236
237 if ((jtag_add_statemove(states[0]) != ERROR_OK) || (jtag_execute_queue() != ERROR_OK)) {
238 Jim_SetResultString(interp, "pathmove: jtag execute failed", -1);
239 return JIM_ERR;
240 }
241
242 jtag_add_pathmove(argc - 2, states + 1);
243
244 if (jtag_execute_queue() != ERROR_OK) {
245 Jim_SetResultString(interp, "pathmove: failed", -1);
246 return JIM_ERR;
247 }
248
249 return JIM_OK;
250 }
251
252
253 static int jim_command_flush_count(Jim_Interp *interp, int argc, Jim_Obj * const *args)
254 {
255 Jim_SetResult(interp, Jim_NewIntObj(interp, jtag_get_flush_queue_count()));
256
257 return JIM_OK;
258 }
259
260 /* REVISIT Just what about these should "move" ... ?
261 * These registrations, into the main JTAG table?
262 *
263 * There's a minor compatibility issue, these all show up twice;
264 * that's not desirable:
265 * - jtag drscan ... NOT DOCUMENTED!
266 * - drscan ...
267 *
268 * The "irscan" command (for example) doesn't show twice.
269 */
270 static const struct command_registration jtag_command_handlers_to_move[] = {
271 {
272 .name = "drscan",
273 .mode = COMMAND_EXEC,
274 .jim_handler = jim_command_drscan,
275 .help = "Execute Data Register (DR) scan for one TAP. "
276 "Other TAPs must be in BYPASS mode.",
277 .usage = "tap_name [num_bits value]* ['-endstate' state_name]",
278 },
279 {
280 .name = "flush_count",
281 .mode = COMMAND_EXEC,
282 .jim_handler = jim_command_flush_count,
283 .help = "Returns the number of times the JTAG queue "
284 "has been flushed.",
285 },
286 {
287 .name = "pathmove",
288 .mode = COMMAND_EXEC,
289 .jim_handler = jim_command_pathmove,
290 .usage = "start_state state1 [state2 [state3 ...]]",
291 .help = "Move JTAG state machine from current state "
292 "(start_state) to state1, then state2, state3, etc.",
293 },
294 COMMAND_REGISTRATION_DONE
295 };
296
297
298 enum jtag_tap_cfg_param {
299 JCFG_EVENT,
300 JCFG_IDCODE,
301 };
302
303 static struct jim_nvp nvp_config_opts[] = {
304 { .name = "-event", .value = JCFG_EVENT },
305 { .name = "-idcode", .value = JCFG_IDCODE },
306
307 { .name = NULL, .value = -1 }
308 };
309
310 static int jtag_tap_configure_event(struct jim_getopt_info *goi, struct jtag_tap *tap)
311 {
312 if (goi->argc == 0) {
313 Jim_WrongNumArgs(goi->interp, goi->argc, goi->argv, "-event <event-name> ...");
314 return JIM_ERR;
315 }
316
317 struct jim_nvp *n;
318 int e = jim_getopt_nvp(goi, nvp_jtag_tap_event, &n);
319 if (e != JIM_OK) {
320 jim_getopt_nvp_unknown(goi, nvp_jtag_tap_event, 1);
321 return e;
322 }
323
324 if (goi->isconfigure) {
325 if (goi->argc != 1) {
326 Jim_WrongNumArgs(goi->interp,
327 goi->argc,
328 goi->argv,
329 "-event <event-name> <event-body>");
330 return JIM_ERR;
331 }
332 } else {
333 if (goi->argc != 0) {
334 Jim_WrongNumArgs(goi->interp, goi->argc, goi->argv, "-event <event-name>");
335 return JIM_ERR;
336 }
337 }
338
339 struct jtag_tap_event_action *jteap = tap->event_action;
340 /* replace existing event body */
341 bool found = false;
342 while (jteap) {
343 if (jteap->event == (enum jtag_event)n->value) {
344 found = true;
345 break;
346 }
347 jteap = jteap->next;
348 }
349
350 Jim_SetEmptyResult(goi->interp);
351
352 if (goi->isconfigure) {
353 if (!found)
354 jteap = calloc(1, sizeof(*jteap));
355 else if (jteap->body)
356 Jim_DecrRefCount(goi->interp, jteap->body);
357
358 jteap->interp = goi->interp;
359 jteap->event = n->value;
360
361 Jim_Obj *o;
362 jim_getopt_obj(goi, &o);
363 jteap->body = Jim_DuplicateObj(goi->interp, o);
364 Jim_IncrRefCount(jteap->body);
365
366 if (!found) {
367 /* add to head of event list */
368 jteap->next = tap->event_action;
369 tap->event_action = jteap;
370 }
371 } else if (found) {
372 jteap->interp = goi->interp;
373 Jim_SetResult(goi->interp,
374 Jim_DuplicateObj(goi->interp, jteap->body));
375 }
376 return JIM_OK;
377 }
378
379 static int jtag_tap_configure_cmd(struct jim_getopt_info *goi, struct jtag_tap *tap)
380 {
381 /* parse config or cget options */
382 while (goi->argc > 0) {
383 Jim_SetEmptyResult(goi->interp);
384
385 struct jim_nvp *n;
386 int e = jim_getopt_nvp(goi, nvp_config_opts, &n);
387 if (e != JIM_OK) {
388 jim_getopt_nvp_unknown(goi, nvp_config_opts, 0);
389 return e;
390 }
391
392 switch (n->value) {
393 case JCFG_EVENT:
394 e = jtag_tap_configure_event(goi, tap);
395 if (e != JIM_OK)
396 return e;
397 break;
398 case JCFG_IDCODE:
399 if (goi->isconfigure) {
400 Jim_SetResultFormatted(goi->interp,
401 "not settable: %s", n->name);
402 return JIM_ERR;
403 } else {
404 if (goi->argc != 0) {
405 Jim_WrongNumArgs(goi->interp,
406 goi->argc, goi->argv,
407 "NO PARAMS");
408 return JIM_ERR;
409 }
410 }
411 Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, tap->idcode));
412 break;
413 default:
414 Jim_SetResultFormatted(goi->interp, "unknown value: %s", n->name);
415 return JIM_ERR;
416 }
417 }
418
419 return JIM_OK;
420 }
421
422 static int is_bad_irval(int ir_length, jim_wide w)
423 {
424 jim_wide v = 1;
425
426 v <<= ir_length;
427 v -= 1;
428 v = ~v;
429 return (w & v) != 0;
430 }
431
432 static int jim_newtap_expected_id(struct jim_nvp *n, struct jim_getopt_info *goi,
433 struct jtag_tap *tap)
434 {
435 jim_wide w;
436 int e = jim_getopt_wide(goi, &w);
437 if (e != JIM_OK) {
438 Jim_SetResultFormatted(goi->interp, "option: %s bad parameter", n->name);
439 return e;
440 }
441
442 uint32_t *p = realloc(tap->expected_ids,
443 (tap->expected_ids_cnt + 1) * sizeof(uint32_t));
444 if (!p) {
445 Jim_SetResultFormatted(goi->interp, "no memory");
446 return JIM_ERR;
447 }
448
449 tap->expected_ids = p;
450 tap->expected_ids[tap->expected_ids_cnt++] = w;
451
452 return JIM_OK;
453 }
454
455 #define NTAP_OPT_IRLEN 0
456 #define NTAP_OPT_IRMASK 1
457 #define NTAP_OPT_IRCAPTURE 2
458 #define NTAP_OPT_ENABLED 3
459 #define NTAP_OPT_DISABLED 4
460 #define NTAP_OPT_EXPECTED_ID 5
461 #define NTAP_OPT_VERSION 6
462 #define NTAP_OPT_BYPASS 7
463
464 static int jim_newtap_ir_param(struct jim_nvp *n, struct jim_getopt_info *goi,
465 struct jtag_tap *tap)
466 {
467 jim_wide w;
468 int e = jim_getopt_wide(goi, &w);
469 if (e != JIM_OK) {
470 Jim_SetResultFormatted(goi->interp,
471 "option: %s bad parameter", n->name);
472 return e;
473 }
474 switch (n->value) {
475 case NTAP_OPT_IRLEN:
476 if (w > (jim_wide) (8 * sizeof(tap->ir_capture_value))) {
477 LOG_WARNING("%s: huge IR length %d",
478 tap->dotted_name, (int) w);
479 }
480 tap->ir_length = w;
481 break;
482 case NTAP_OPT_IRMASK:
483 if (is_bad_irval(tap->ir_length, w)) {
484 LOG_ERROR("%s: IR mask %x too big",
485 tap->dotted_name,
486 (int) w);
487 return JIM_ERR;
488 }
489 if ((w & 3) != 3)
490 LOG_WARNING("%s: nonstandard IR mask", tap->dotted_name);
491 tap->ir_capture_mask = w;
492 break;
493 case NTAP_OPT_IRCAPTURE:
494 if (is_bad_irval(tap->ir_length, w)) {
495 LOG_ERROR("%s: IR capture %x too big",
496 tap->dotted_name, (int) w);
497 return JIM_ERR;
498 }
499 if ((w & 3) != 1)
500 LOG_WARNING("%s: nonstandard IR value",
501 tap->dotted_name);
502 tap->ir_capture_value = w;
503 break;
504 default:
505 return JIM_ERR;
506 }
507 return JIM_OK;
508 }
509
510 static int jim_newtap_cmd(struct jim_getopt_info *goi)
511 {
512 struct jtag_tap *tap;
513 int x;
514 int e;
515 struct jim_nvp *n;
516 char *cp;
517 const struct jim_nvp opts[] = {
518 { .name = "-irlen", .value = NTAP_OPT_IRLEN },
519 { .name = "-irmask", .value = NTAP_OPT_IRMASK },
520 { .name = "-ircapture", .value = NTAP_OPT_IRCAPTURE },
521 { .name = "-enable", .value = NTAP_OPT_ENABLED },
522 { .name = "-disable", .value = NTAP_OPT_DISABLED },
523 { .name = "-expected-id", .value = NTAP_OPT_EXPECTED_ID },
524 { .name = "-ignore-version", .value = NTAP_OPT_VERSION },
525 { .name = "-ignore-bypass", .value = NTAP_OPT_BYPASS },
526 { .name = NULL, .value = -1 },
527 };
528
529 tap = calloc(1, sizeof(struct jtag_tap));
530 if (!tap) {
531 Jim_SetResultFormatted(goi->interp, "no memory");
532 return JIM_ERR;
533 }
534
535 /*
536 * we expect CHIP + TAP + OPTIONS
537 * */
538 if (goi->argc < 3) {
539 Jim_SetResultFormatted(goi->interp, "Missing CHIP TAP OPTIONS ....");
540 free(tap);
541 return JIM_ERR;
542 }
543
544 const char *tmp;
545 jim_getopt_string(goi, &tmp, NULL);
546 tap->chip = strdup(tmp);
547
548 jim_getopt_string(goi, &tmp, NULL);
549 tap->tapname = strdup(tmp);
550
551 /* name + dot + name + null */
552 x = strlen(tap->chip) + 1 + strlen(tap->tapname) + 1;
553 cp = malloc(x);
554 sprintf(cp, "%s.%s", tap->chip, tap->tapname);
555 tap->dotted_name = cp;
556
557 LOG_DEBUG("Creating New Tap, Chip: %s, Tap: %s, Dotted: %s, %d params",
558 tap->chip, tap->tapname, tap->dotted_name, goi->argc);
559
560 /* IEEE specifies that the two LSBs of an IR scan are 01, so make
561 * that the default. The "-ircapture" and "-irmask" options are only
562 * needed to cope with nonstandard TAPs, or to specify more bits.
563 */
564 tap->ir_capture_mask = 0x03;
565 tap->ir_capture_value = 0x01;
566
567 while (goi->argc) {
568 e = jim_getopt_nvp(goi, opts, &n);
569 if (e != JIM_OK) {
570 jim_getopt_nvp_unknown(goi, opts, 0);
571 free(cp);
572 free(tap);
573 return e;
574 }
575 LOG_DEBUG("Processing option: %s", n->name);
576 switch (n->value) {
577 case NTAP_OPT_ENABLED:
578 tap->disabled_after_reset = false;
579 break;
580 case NTAP_OPT_DISABLED:
581 tap->disabled_after_reset = true;
582 break;
583 case NTAP_OPT_EXPECTED_ID:
584 e = jim_newtap_expected_id(n, goi, tap);
585 if (e != JIM_OK) {
586 free(cp);
587 free(tap);
588 return e;
589 }
590 break;
591 case NTAP_OPT_IRLEN:
592 case NTAP_OPT_IRMASK:
593 case NTAP_OPT_IRCAPTURE:
594 e = jim_newtap_ir_param(n, goi, tap);
595 if (e != JIM_OK) {
596 free(cp);
597 free(tap);
598 return e;
599 }
600 break;
601 case NTAP_OPT_VERSION:
602 tap->ignore_version = true;
603 break;
604 case NTAP_OPT_BYPASS:
605 tap->ignore_bypass = true;
606 break;
607 } /* switch (n->value) */
608 } /* while (goi->argc) */
609
610 /* default is enabled-after-reset */
611 tap->enabled = !tap->disabled_after_reset;
612
613 /* Did all the required option bits get cleared? */
614 if (!transport_is_jtag() || tap->ir_length != 0) {
615 jtag_tap_init(tap);
616 return JIM_OK;
617 }
618
619 Jim_SetResultFormatted(goi->interp,
620 "newtap: %s missing IR length",
621 tap->dotted_name);
622 jtag_tap_free(tap);
623 return JIM_ERR;
624 }
625
626 static void jtag_tap_handle_event(struct jtag_tap *tap, enum jtag_event e)
627 {
628 struct jtag_tap_event_action *jteap;
629 int retval;
630
631 for (jteap = tap->event_action; jteap; jteap = jteap->next) {
632 if (jteap->event != e)
633 continue;
634
635 struct jim_nvp *nvp = jim_nvp_value2name_simple(nvp_jtag_tap_event, e);
636 LOG_DEBUG("JTAG tap: %s event: %d (%s)\n\taction: %s",
637 tap->dotted_name, e, nvp->name,
638 Jim_GetString(jteap->body, NULL));
639
640 retval = Jim_EvalObj(jteap->interp, jteap->body);
641 if (retval == JIM_RETURN)
642 retval = jteap->interp->returnCode;
643
644 if (retval != JIM_OK) {
645 Jim_MakeErrorMessage(jteap->interp);
646 LOG_USER("%s", Jim_GetString(Jim_GetResult(jteap->interp), NULL));
647 continue;
648 }
649
650 switch (e) {
651 case JTAG_TAP_EVENT_ENABLE:
652 case JTAG_TAP_EVENT_DISABLE:
653 /* NOTE: we currently assume the handlers
654 * can't fail. Right here is where we should
655 * really be verifying the scan chains ...
656 */
657 tap->enabled = (e == JTAG_TAP_EVENT_ENABLE);
658 LOG_INFO("JTAG tap: %s %s", tap->dotted_name,
659 tap->enabled ? "enabled" : "disabled");
660 break;
661 default:
662 break;
663 }
664 }
665 }
666
667 static int jim_jtag_arp_init(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
668 {
669 struct jim_getopt_info goi;
670 jim_getopt_setup(&goi, interp, argc-1, argv + 1);
671 if (goi.argc != 0) {
672 Jim_WrongNumArgs(goi.interp, 1, goi.argv-1, "(no params)");
673 return JIM_ERR;
674 }
675 struct command_context *context = current_command_context(interp);
676 int e = jtag_init_inner(context);
677 if (e != ERROR_OK) {
678 Jim_Obj *obj = Jim_NewIntObj(goi.interp, e);
679 Jim_SetResultFormatted(goi.interp, "error: %#s", obj);
680 return JIM_ERR;
681 }
682 return JIM_OK;
683 }
684
685 static int jim_jtag_arp_init_reset(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
686 {
687 int e = ERROR_OK;
688 struct jim_getopt_info goi;
689 jim_getopt_setup(&goi, interp, argc-1, argv + 1);
690 if (goi.argc != 0) {
691 Jim_WrongNumArgs(goi.interp, 1, goi.argv-1, "(no params)");
692 return JIM_ERR;
693 }
694 struct command_context *context = current_command_context(interp);
695 if (transport_is_jtag())
696 e = jtag_init_reset(context);
697 else if (transport_is_swd())
698 e = swd_init_reset(context);
699
700 if (e != ERROR_OK) {
701 Jim_Obj *obj = Jim_NewIntObj(goi.interp, e);
702 Jim_SetResultFormatted(goi.interp, "error: %#s", obj);
703 return JIM_ERR;
704 }
705 return JIM_OK;
706 }
707
708 int jim_jtag_newtap(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
709 {
710 struct jim_getopt_info goi;
711 jim_getopt_setup(&goi, interp, argc-1, argv + 1);
712 return jim_newtap_cmd(&goi);
713 }
714
715 static bool jtag_tap_enable(struct jtag_tap *t)
716 {
717 if (t->enabled)
718 return false;
719 jtag_tap_handle_event(t, JTAG_TAP_EVENT_ENABLE);
720 if (!t->enabled)
721 return false;
722
723 /* FIXME add JTAG sanity checks, w/o TLR
724 * - scan chain length grew by one (this)
725 * - IDs and IR lengths are as expected
726 */
727 jtag_call_event_callbacks(JTAG_TAP_EVENT_ENABLE);
728 return true;
729 }
730 static bool jtag_tap_disable(struct jtag_tap *t)
731 {
732 if (!t->enabled)
733 return false;
734 jtag_tap_handle_event(t, JTAG_TAP_EVENT_DISABLE);
735 if (t->enabled)
736 return false;
737
738 /* FIXME add JTAG sanity checks, w/o TLR
739 * - scan chain length shrank by one (this)
740 * - IDs and IR lengths are as expected
741 */
742 jtag_call_event_callbacks(JTAG_TAP_EVENT_DISABLE);
743 return true;
744 }
745
746 int jim_jtag_tap_enabler(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
747 {
748 struct command *c = jim_to_command(interp);
749 const char *cmd_name = c->name;
750 struct jim_getopt_info goi;
751 jim_getopt_setup(&goi, interp, argc-1, argv + 1);
752 if (goi.argc != 1) {
753 Jim_SetResultFormatted(goi.interp, "usage: %s <name>", cmd_name);
754 return JIM_ERR;
755 }
756
757 struct jtag_tap *t;
758
759 t = jtag_tap_by_jim_obj(goi.interp, goi.argv[0]);
760 if (!t)
761 return JIM_ERR;
762
763 if (strcasecmp(cmd_name, "tapisenabled") == 0) {
764 /* do nothing, just return the value */
765 } else if (strcasecmp(cmd_name, "tapenable") == 0) {
766 if (!jtag_tap_enable(t)) {
767 LOG_WARNING("failed to enable tap %s", t->dotted_name);
768 return JIM_ERR;
769 }
770 } else if (strcasecmp(cmd_name, "tapdisable") == 0) {
771 if (!jtag_tap_disable(t)) {
772 LOG_WARNING("failed to disable tap %s", t->dotted_name);
773 return JIM_ERR;
774 }
775 } else {
776 LOG_ERROR("command '%s' unknown", cmd_name);
777 return JIM_ERR;
778 }
779 bool e = t->enabled;
780 Jim_SetResult(goi.interp, Jim_NewIntObj(goi.interp, e));
781 return JIM_OK;
782 }
783
784 int jim_jtag_configure(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
785 {
786 struct command *c = jim_to_command(interp);
787 const char *cmd_name = c->name;
788 struct jim_getopt_info goi;
789 jim_getopt_setup(&goi, interp, argc-1, argv + 1);
790 goi.isconfigure = !strcmp(cmd_name, "configure");
791 if (goi.argc < 2 + goi.isconfigure) {
792 Jim_WrongNumArgs(goi.interp, 0, NULL,
793 "<tap_name> <attribute> ...");
794 return JIM_ERR;
795 }
796
797 struct jtag_tap *t;
798
799 Jim_Obj *o;
800 jim_getopt_obj(&goi, &o);
801 t = jtag_tap_by_jim_obj(goi.interp, o);
802 if (!t)
803 return JIM_ERR;
804
805 return jtag_tap_configure_cmd(&goi, t);
806 }
807
808 COMMAND_HANDLER(handle_jtag_names)
809 {
810 if (CMD_ARGC != 0)
811 return ERROR_COMMAND_SYNTAX_ERROR;
812
813 for (struct jtag_tap *tap = jtag_all_taps(); tap; tap = tap->next_tap)
814 command_print(CMD, "%s", tap->dotted_name);
815
816 return ERROR_OK;
817 }
818
819 COMMAND_HANDLER(handle_jtag_init_command)
820 {
821 if (CMD_ARGC != 0)
822 return ERROR_COMMAND_SYNTAX_ERROR;
823
824 static bool jtag_initialized;
825 if (jtag_initialized) {
826 LOG_INFO("'jtag init' has already been called");
827 return ERROR_OK;
828 }
829 jtag_initialized = true;
830
831 LOG_DEBUG("Initializing jtag devices...");
832 return jtag_init(CMD_CTX);
833 }
834
835 static const struct command_registration jtag_subcommand_handlers[] = {
836 {
837 .name = "init",
838 .mode = COMMAND_ANY,
839 .handler = handle_jtag_init_command,
840 .help = "initialize jtag scan chain",
841 .usage = ""
842 },
843 {
844 .name = "arp_init",
845 .mode = COMMAND_ANY,
846 .jim_handler = jim_jtag_arp_init,
847 .help = "Validates JTAG scan chain against the list of "
848 "declared TAPs using just the four standard JTAG "
849 "signals.",
850 },
851 {
852 .name = "arp_init-reset",
853 .mode = COMMAND_ANY,
854 .jim_handler = jim_jtag_arp_init_reset,
855 .help = "Uses TRST and SRST to try resetting everything on "
856 "the JTAG scan chain, then performs 'jtag arp_init'."
857 },
858 {
859 .name = "newtap",
860 .mode = COMMAND_CONFIG,
861 .jim_handler = jim_jtag_newtap,
862 .help = "Create a new TAP instance named basename.tap_type, "
863 "and appends it to the scan chain.",
864 .usage = "basename tap_type '-irlen' count "
865 "['-enable'|'-disable'] "
866 "['-expected_id' number] "
867 "['-ignore-version'] "
868 "['-ignore-bypass'] "
869 "['-ircapture' number] "
870 "['-mask' number]",
871 },
872 {
873 .name = "tapisenabled",
874 .mode = COMMAND_EXEC,
875 .jim_handler = jim_jtag_tap_enabler,
876 .help = "Returns a Tcl boolean (0/1) indicating whether "
877 "the TAP is enabled (1) or not (0).",
878 .usage = "tap_name",
879 },
880 {
881 .name = "tapenable",
882 .mode = COMMAND_EXEC,
883 .jim_handler = jim_jtag_tap_enabler,
884 .help = "Try to enable the specified TAP using the "
885 "'tap-enable' TAP event.",
886 .usage = "tap_name",
887 },
888 {
889 .name = "tapdisable",
890 .mode = COMMAND_EXEC,
891 .jim_handler = jim_jtag_tap_enabler,
892 .help = "Try to disable the specified TAP using the "
893 "'tap-disable' TAP event.",
894 .usage = "tap_name",
895 },
896 {
897 .name = "configure",
898 .mode = COMMAND_ANY,
899 .jim_handler = jim_jtag_configure,
900 .help = "Provide a Tcl handler for the specified "
901 "TAP event.",
902 .usage = "tap_name '-event' event_name handler",
903 },
904 {
905 .name = "cget",
906 .mode = COMMAND_EXEC,
907 .jim_handler = jim_jtag_configure,
908 .help = "Return any Tcl handler for the specified "
909 "TAP event.",
910 .usage = "tap_name '-event' event_name",
911 },
912 {
913 .name = "names",
914 .mode = COMMAND_ANY,
915 .handler = handle_jtag_names,
916 .help = "Returns list of all JTAG tap names.",
917 .usage = "",
918 },
919 {
920 .chain = jtag_command_handlers_to_move,
921 },
922 COMMAND_REGISTRATION_DONE
923 };
924
925 void jtag_notify_event(enum jtag_event event)
926 {
927 struct jtag_tap *tap;
928
929 for (tap = jtag_all_taps(); tap; tap = tap->next_tap)
930 jtag_tap_handle_event(tap, event);
931 }
932
933
934 COMMAND_HANDLER(handle_scan_chain_command)
935 {
936 struct jtag_tap *tap;
937 char expected_id[12];
938
939 tap = jtag_all_taps();
940 command_print(CMD,
941 " TapName Enabled IdCode Expected IrLen IrCap IrMask");
942 command_print(CMD,
943 "-- ------------------- -------- ---------- ---------- ----- ----- ------");
944
945 while (tap) {
946 uint32_t expected, expected_mask, ii;
947
948 snprintf(expected_id, sizeof(expected_id), "0x%08x",
949 (unsigned)((tap->expected_ids_cnt > 0)
950 ? tap->expected_ids[0]
951 : 0));
952 if (tap->ignore_version)
953 expected_id[2] = '*';
954
955 expected = buf_get_u32(tap->expected, 0, tap->ir_length);
956 expected_mask = buf_get_u32(tap->expected_mask, 0, tap->ir_length);
957
958 command_print(CMD,
959 "%2d %-18s %c 0x%08x %s %5d 0x%02x 0x%02x",
960 tap->abs_chain_position,
961 tap->dotted_name,
962 tap->enabled ? 'Y' : 'n',
963 (unsigned int)(tap->idcode),
964 expected_id,
965 (unsigned int)(tap->ir_length),
966 (unsigned int)(expected),
967 (unsigned int)(expected_mask));
968
969 for (ii = 1; ii < tap->expected_ids_cnt; ii++) {
970 snprintf(expected_id, sizeof(expected_id), "0x%08x",
971 (unsigned) tap->expected_ids[ii]);
972 if (tap->ignore_version)
973 expected_id[2] = '*';
974
975 command_print(CMD,
976 " %s",
977 expected_id);
978 }
979
980 tap = tap->next_tap;
981 }
982
983 return ERROR_OK;
984 }
985
986 COMMAND_HANDLER(handle_jtag_ntrst_delay_command)
987 {
988 if (CMD_ARGC > 1)
989 return ERROR_COMMAND_SYNTAX_ERROR;
990 if (CMD_ARGC == 1) {
991 unsigned delay;
992 COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], delay);
993
994 jtag_set_ntrst_delay(delay);
995 }
996 command_print(CMD, "jtag_ntrst_delay: %u", jtag_get_ntrst_delay());
997 return ERROR_OK;
998 }
999
1000 COMMAND_HANDLER(handle_jtag_ntrst_assert_width_command)
1001 {
1002 if (CMD_ARGC > 1)
1003 return ERROR_COMMAND_SYNTAX_ERROR;
1004 if (CMD_ARGC == 1) {
1005 unsigned delay;
1006 COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], delay);
1007
1008 jtag_set_ntrst_assert_width(delay);
1009 }
1010 command_print(CMD, "jtag_ntrst_assert_width: %u", jtag_get_ntrst_assert_width());
1011 return ERROR_OK;
1012 }
1013
1014 COMMAND_HANDLER(handle_jtag_rclk_command)
1015 {
1016 if (CMD_ARGC > 1)
1017 return ERROR_COMMAND_SYNTAX_ERROR;
1018
1019 int retval = ERROR_OK;
1020 if (CMD_ARGC == 1) {
1021 unsigned khz = 0;
1022 COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], khz);
1023
1024 retval = adapter_config_rclk(khz);
1025 if (retval != ERROR_OK)
1026 return retval;
1027 }
1028
1029 int cur_khz = adapter_get_speed_khz();
1030 retval = adapter_get_speed_readable(&cur_khz);
1031 if (retval != ERROR_OK)
1032 return retval;
1033
1034 if (cur_khz)
1035 command_print(CMD, "RCLK not supported - fallback to %d kHz", cur_khz);
1036 else
1037 command_print(CMD, "RCLK - adaptive");
1038
1039 return retval;
1040 }
1041
1042 COMMAND_HANDLER(handle_runtest_command)
1043 {
1044 if (CMD_ARGC != 1)
1045 return ERROR_COMMAND_SYNTAX_ERROR;
1046
1047 unsigned num_clocks;
1048 COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], num_clocks);
1049
1050 jtag_add_runtest(num_clocks, TAP_IDLE);
1051 return jtag_execute_queue();
1052 }
1053
1054 /*
1055 * For "irscan" or "drscan" commands, the "end" (really, "next") state
1056 * should be stable ... and *NOT* a shift state, otherwise free-running
1057 * jtag clocks could change the values latched by the update state.
1058 * Not surprisingly, this is the same constraint as SVF; the "irscan"
1059 * and "drscan" commands are a write-only subset of what SVF provides.
1060 */
1061
1062 COMMAND_HANDLER(handle_irscan_command)
1063 {
1064 int i;
1065 struct scan_field *fields;
1066 struct jtag_tap *tap = NULL;
1067 tap_state_t endstate;
1068
1069 if ((CMD_ARGC < 2) || (CMD_ARGC % 2))
1070 return ERROR_COMMAND_SYNTAX_ERROR;
1071
1072 /* optional "-endstate" "statename" at the end of the arguments,
1073 * so that e.g. IRPAUSE can let us load the data register before
1074 * entering RUN/IDLE to execute the instruction we load here.
1075 */
1076 endstate = TAP_IDLE;
1077
1078 if (CMD_ARGC >= 4) {
1079 /* have at least one pair of numbers.
1080 * is last pair the magic text? */
1081 if (strcmp("-endstate", CMD_ARGV[CMD_ARGC - 2]) == 0) {
1082 endstate = tap_state_by_name(CMD_ARGV[CMD_ARGC - 1]);
1083 if (endstate == TAP_INVALID)
1084 return ERROR_COMMAND_SYNTAX_ERROR;
1085 if (!scan_is_safe(endstate))
1086 LOG_WARNING("unstable irscan endstate \"%s\"",
1087 CMD_ARGV[CMD_ARGC - 1]);
1088 CMD_ARGC -= 2;
1089 }
1090 }
1091
1092 int num_fields = CMD_ARGC / 2;
1093 if (num_fields > 1) {
1094 /* we really should be looking at plain_ir_scan if we want
1095 * anything more fancy.
1096 */
1097 LOG_ERROR("Specify a single value for tap");
1098 return ERROR_COMMAND_SYNTAX_ERROR;
1099 }
1100
1101 fields = calloc(num_fields, sizeof(*fields));
1102
1103 int retval;
1104 for (i = 0; i < num_fields; i++) {
1105 tap = jtag_tap_by_string(CMD_ARGV[i*2]);
1106 if (!tap) {
1107 free(fields);
1108 command_print(CMD, "Tap: %s unknown", CMD_ARGV[i*2]);
1109
1110 return ERROR_FAIL;
1111 }
1112 uint64_t value;
1113 retval = parse_u64(CMD_ARGV[i * 2 + 1], &value);
1114 if (retval != ERROR_OK)
1115 goto error_return;
1116
1117 int field_size = tap->ir_length;
1118 fields[i].num_bits = field_size;
1119 uint8_t *v = calloc(1, DIV_ROUND_UP(field_size, 8));
1120 if (!v) {
1121 LOG_ERROR("Out of memory");
1122 goto error_return;
1123 }
1124
1125 buf_set_u64(v, 0, field_size, value);
1126 fields[i].out_value = v;
1127 fields[i].in_value = NULL;
1128 }
1129
1130 /* did we have an endstate? */
1131 jtag_add_ir_scan(tap, fields, endstate);
1132
1133 retval = jtag_execute_queue();
1134
1135 error_return:
1136 for (i = 0; i < num_fields; i++)
1137 free((void *)fields[i].out_value);
1138
1139 free(fields);
1140
1141 return retval;
1142 }
1143
1144 COMMAND_HANDLER(handle_verify_ircapture_command)
1145 {
1146 if (CMD_ARGC > 1)
1147 return ERROR_COMMAND_SYNTAX_ERROR;
1148
1149 if (CMD_ARGC == 1) {
1150 bool enable;
1151 COMMAND_PARSE_ENABLE(CMD_ARGV[0], enable);
1152 jtag_set_verify_capture_ir(enable);
1153 }
1154
1155 const char *status = jtag_will_verify_capture_ir() ? "enabled" : "disabled";
1156 command_print(CMD, "verify Capture-IR is %s", status);
1157
1158 return ERROR_OK;
1159 }
1160
1161 COMMAND_HANDLER(handle_verify_jtag_command)
1162 {
1163 if (CMD_ARGC > 1)
1164 return ERROR_COMMAND_SYNTAX_ERROR;
1165
1166 if (CMD_ARGC == 1) {
1167 bool enable;
1168 COMMAND_PARSE_ENABLE(CMD_ARGV[0], enable);
1169 jtag_set_verify(enable);
1170 }
1171
1172 const char *status = jtag_will_verify() ? "enabled" : "disabled";
1173 command_print(CMD, "verify jtag capture is %s", status);
1174
1175 return ERROR_OK;
1176 }
1177
1178 COMMAND_HANDLER(handle_tms_sequence_command)
1179 {
1180 if (CMD_ARGC > 1)
1181 return ERROR_COMMAND_SYNTAX_ERROR;
1182
1183 if (CMD_ARGC == 1) {
1184 bool use_new_table;
1185 if (strcmp(CMD_ARGV[0], "short") == 0)
1186 use_new_table = true;
1187 else if (strcmp(CMD_ARGV[0], "long") == 0)
1188 use_new_table = false;
1189 else
1190 return ERROR_COMMAND_SYNTAX_ERROR;
1191
1192 tap_use_new_tms_table(use_new_table);
1193 }
1194
1195 command_print(CMD, "tms sequence is %s",
1196 tap_uses_new_tms_table() ? "short" : "long");
1197
1198 return ERROR_OK;
1199 }
1200
1201 COMMAND_HANDLER(handle_jtag_flush_queue_sleep)
1202 {
1203 if (CMD_ARGC != 1)
1204 return ERROR_COMMAND_SYNTAX_ERROR;
1205
1206 int sleep_ms;
1207 COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], sleep_ms);
1208
1209 jtag_set_flush_queue_sleep(sleep_ms);
1210
1211 return ERROR_OK;
1212 }
1213
1214 COMMAND_HANDLER(handle_wait_srst_deassert)
1215 {
1216 if (CMD_ARGC != 1)
1217 return ERROR_COMMAND_SYNTAX_ERROR;
1218
1219 int timeout_ms;
1220 COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], timeout_ms);
1221 if ((timeout_ms <= 0) || (timeout_ms > 100000)) {
1222 LOG_ERROR("Timeout must be an integer between 0 and 100000");
1223 return ERROR_FAIL;
1224 }
1225
1226 LOG_USER("Waiting for srst assert + deassert for at most %dms", timeout_ms);
1227 int asserted_yet;
1228 int64_t then = timeval_ms();
1229 while (jtag_srst_asserted(&asserted_yet) == ERROR_OK) {
1230 if ((timeval_ms() - then) > timeout_ms) {
1231 LOG_ERROR("Timed out");
1232 return ERROR_FAIL;
1233 }
1234 if (asserted_yet)
1235 break;
1236 }
1237 while (jtag_srst_asserted(&asserted_yet) == ERROR_OK) {
1238 if ((timeval_ms() - then) > timeout_ms) {
1239 LOG_ERROR("Timed out");
1240 return ERROR_FAIL;
1241 }
1242 if (!asserted_yet)
1243 break;
1244 }
1245
1246 return ERROR_OK;
1247 }
1248
1249 static const struct command_registration jtag_command_handlers[] = {
1250
1251 {
1252 .name = "jtag_flush_queue_sleep",
1253 .handler = handle_jtag_flush_queue_sleep,
1254 .mode = COMMAND_ANY,
1255 .help = "For debug purposes(simulate long delays of interface) "
1256 "to test performance or change in behavior. Default 0ms.",
1257 .usage = "[sleep in ms]",
1258 },
1259 {
1260 .name = "jtag_rclk",
1261 .handler = handle_jtag_rclk_command,
1262 .mode = COMMAND_ANY,
1263 .help = "With an argument, change to to use adaptive clocking "
1264 "if possible; else to use the fallback speed. "
1265 "With or without argument, display current setting.",
1266 .usage = "[fallback_speed_khz]",
1267 },
1268 {
1269 .name = "jtag_ntrst_delay",
1270 .handler = handle_jtag_ntrst_delay_command,
1271 .mode = COMMAND_ANY,
1272 .help = "delay after deasserting trst in ms",
1273 .usage = "[milliseconds]",
1274 },
1275 {
1276 .name = "jtag_ntrst_assert_width",
1277 .handler = handle_jtag_ntrst_assert_width_command,
1278 .mode = COMMAND_ANY,
1279 .help = "delay after asserting trst in ms",
1280 .usage = "[milliseconds]",
1281 },
1282 {
1283 .name = "scan_chain",
1284 .handler = handle_scan_chain_command,
1285 .mode = COMMAND_ANY,
1286 .help = "print current scan chain configuration",
1287 .usage = ""
1288 },
1289 {
1290 .name = "runtest",
1291 .handler = handle_runtest_command,
1292 .mode = COMMAND_EXEC,
1293 .help = "Move to Run-Test/Idle, and issue TCK for num_cycles.",
1294 .usage = "num_cycles"
1295 },
1296 {
1297 .name = "irscan",
1298 .handler = handle_irscan_command,
1299 .mode = COMMAND_EXEC,
1300 .help = "Execute Instruction Register (IR) scan. The "
1301 "specified opcodes are put into each TAP's IR, "
1302 "and other TAPs are put in BYPASS.",
1303 .usage = "[tap_name instruction]* ['-endstate' state_name]",
1304 },
1305 {
1306 .name = "verify_ircapture",
1307 .handler = handle_verify_ircapture_command,
1308 .mode = COMMAND_ANY,
1309 .help = "Display or assign flag controlling whether to "
1310 "verify values captured during Capture-IR.",
1311 .usage = "['enable'|'disable']",
1312 },
1313 {
1314 .name = "verify_jtag",
1315 .handler = handle_verify_jtag_command,
1316 .mode = COMMAND_ANY,
1317 .help = "Display or assign flag controlling whether to "
1318 "verify values captured during IR and DR scans.",
1319 .usage = "['enable'|'disable']",
1320 },
1321 {
1322 .name = "tms_sequence",
1323 .handler = handle_tms_sequence_command,
1324 .mode = COMMAND_ANY,
1325 .help = "Display or change what style TMS sequences to use "
1326 "for JTAG state transitions: short (default) or "
1327 "long. Only for working around JTAG bugs.",
1328 /* Specifically for working around DRIVER bugs... */
1329 .usage = "['short'|'long']",
1330 },
1331 {
1332 .name = "wait_srst_deassert",
1333 .handler = handle_wait_srst_deassert,
1334 .mode = COMMAND_ANY,
1335 .help = "Wait for an SRST deassert. "
1336 "Useful for cases where you need something to happen within ms "
1337 "of an srst deassert. Timeout in ms",
1338 .usage = "ms",
1339 },
1340 {
1341 .name = "jtag",
1342 .mode = COMMAND_ANY,
1343 .help = "perform jtag tap actions",
1344 .usage = "",
1345
1346 .chain = jtag_subcommand_handlers,
1347 },
1348 {
1349 .chain = jtag_command_handlers_to_move,
1350 },
1351 COMMAND_REGISTRATION_DONE
1352 };
1353
1354 int jtag_register_commands(struct command_context *cmd_ctx)
1355 {
1356 return register_commands(cmd_ctx, NULL, jtag_command_handlers);
1357 }

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)