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

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)