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

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)