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

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)