Fix a bunch of typos.
[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 } else if (strcasecmp(cmd_name, "tapdisable") == 0) {
780 if (!jtag_tap_disable(t))
781 LOG_WARNING("failed to disable tap %s", t->dotted_name);
782 } else {
783 LOG_ERROR("command '%s' unknown", cmd_name);
784 return JIM_ERR;
785 }
786 bool e = t->enabled;
787 Jim_SetResult(goi.interp, Jim_NewIntObj(goi.interp, e));
788 return JIM_OK;
789 }
790
791 static int jim_jtag_configure(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
792 {
793 const char *cmd_name = Jim_GetString(argv[0], NULL);
794 Jim_GetOptInfo goi;
795 Jim_GetOpt_Setup(&goi, interp, argc-1, argv + 1);
796 goi.isconfigure = !strcmp(cmd_name, "configure");
797 if (goi.argc < 2 + goi.isconfigure) {
798 Jim_WrongNumArgs(goi.interp, 0, NULL,
799 "<tap_name> <attribute> ...");
800 return JIM_ERR;
801 }
802
803 struct jtag_tap *t;
804
805 Jim_Obj *o;
806 Jim_GetOpt_Obj(&goi, &o);
807 t = jtag_tap_by_jim_obj(goi.interp, o);
808 if (t == NULL) {
809 return JIM_ERR;
810 }
811
812 return jtag_tap_configure_cmd(&goi, t);
813 }
814
815 static int jim_jtag_names(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
816 {
817 Jim_GetOptInfo goi;
818 Jim_GetOpt_Setup(&goi, interp, argc-1, argv + 1);
819 if (goi.argc != 0) {
820 Jim_WrongNumArgs(goi.interp, 1, goi.argv, "Too many parameters");
821 return JIM_ERR;
822 }
823 Jim_SetResult(goi.interp, Jim_NewListObj(goi.interp, NULL, 0));
824 struct jtag_tap *tap;
825
826 for (tap = jtag_all_taps(); tap; tap = tap->next_tap) {
827 Jim_ListAppendElement(goi.interp,
828 Jim_GetResult(goi.interp),
829 Jim_NewStringObj(goi.interp,
830 tap->dotted_name, -1));
831 }
832 return JIM_OK;
833 }
834
835 COMMAND_HANDLER(handle_jtag_init_command)
836 {
837 if (CMD_ARGC != 0)
838 return ERROR_COMMAND_SYNTAX_ERROR;
839
840 static bool jtag_initialized = false;
841 if (jtag_initialized)
842 {
843 LOG_INFO("'jtag init' has already been called");
844 return ERROR_OK;
845 }
846 jtag_initialized = true;
847
848 LOG_DEBUG("Initializing jtag devices...");
849 return jtag_init(CMD_CTX);
850 }
851
852 static const struct command_registration jtag_subcommand_handlers[] = {
853 {
854 .name = "init",
855 .mode = COMMAND_ANY,
856 .handler = handle_jtag_init_command,
857 .help = "initialize jtag scan chain",
858 },
859 {
860 .name = "arp_init",
861 .mode = COMMAND_ANY,
862 .jim_handler = jim_jtag_arp_init,
863 .help = "Validates JTAG scan chain against the list of "
864 "declared TAPs using just the four standard JTAG "
865 "signals.",
866 },
867 {
868 .name = "arp_init-reset",
869 .mode = COMMAND_ANY,
870 .jim_handler = jim_jtag_arp_init_reset,
871 .help = "Uses TRST and SRST to try resetting everything on "
872 "the JTAG scan chain, then performs 'jtag arp_init'."
873 },
874 {
875 .name = "newtap",
876 .mode = COMMAND_CONFIG,
877 .jim_handler = jim_jtag_newtap,
878 .help = "Create a new TAP instance named basename.tap_type, "
879 "and appends it to the scan chain.",
880 .usage = "basename tap_type '-irlen' count "
881 "['-enable'|'-disable'] "
882 "['-expected_id' number] "
883 "['-ignore-version'] "
884 "['-ircapture' number] "
885 "['-mask' number] ",
886 },
887 {
888 .name = "tapisenabled",
889 .mode = COMMAND_EXEC,
890 .jim_handler = jim_jtag_tap_enabler,
891 .help = "Returns a Tcl boolean (0/1) indicating whether "
892 "the TAP is enabled (1) or not (0).",
893 .usage = "tap_name",
894 },
895 {
896 .name = "tapenable",
897 .mode = COMMAND_EXEC,
898 .jim_handler = jim_jtag_tap_enabler,
899 .help = "Try to enable the specified TAP using the "
900 "'tap-enable' TAP event.",
901 .usage = "tap_name",
902 },
903 {
904 .name = "tapdisable",
905 .mode = COMMAND_EXEC,
906 .jim_handler = jim_jtag_tap_enabler,
907 .help = "Try to disable the specified TAP using the "
908 "'tap-disable' TAP event.",
909 .usage = "tap_name",
910 },
911 {
912 .name = "configure",
913 .mode = COMMAND_EXEC,
914 .jim_handler = jim_jtag_configure,
915 .help = "Provide a Tcl handler for the specified "
916 "TAP event.",
917 .usage = "tap_name '-event' event_name handler",
918 },
919 {
920 .name = "cget",
921 .mode = COMMAND_EXEC,
922 .jim_handler = jim_jtag_configure,
923 .help = "Return any Tcl handler for the specified "
924 "TAP event.",
925 .usage = "tap_name '-event' event_name",
926 },
927 {
928 .name = "names",
929 .mode = COMMAND_ANY,
930 .jim_handler = jim_jtag_names,
931 .help = "Returns list of all JTAG tap names.",
932 },
933 {
934 .chain = jtag_command_handlers_to_move,
935 },
936 COMMAND_REGISTRATION_DONE
937 };
938
939 void jtag_notify_event(enum jtag_event event)
940 {
941 struct jtag_tap *tap;
942
943 for (tap = jtag_all_taps(); tap; tap = tap->next_tap)
944 jtag_tap_handle_event(tap, event);
945 }
946
947
948 COMMAND_HANDLER(handle_scan_chain_command)
949 {
950 struct jtag_tap *tap;
951 char expected_id[12];
952
953 tap = jtag_all_taps();
954 command_print(CMD_CTX,
955 " TapName Enabled IdCode Expected IrLen IrCap IrMask");
956 command_print(CMD_CTX,
957 "-- ------------------- -------- ---------- ---------- ----- ----- ------");
958
959 while (tap) {
960 uint32_t expected, expected_mask, ii;
961
962 snprintf(expected_id, sizeof expected_id, "0x%08x",
963 (unsigned)((tap->expected_ids_cnt > 0)
964 ? tap->expected_ids[0]
965 : 0));
966 if (tap->ignore_version)
967 expected_id[2] = '*';
968
969 expected = buf_get_u32(tap->expected, 0, tap->ir_length);
970 expected_mask = buf_get_u32(tap->expected_mask, 0, tap->ir_length);
971
972 command_print(CMD_CTX,
973 "%2d %-18s %c 0x%08x %s %5d 0x%02x 0x%02x",
974 tap->abs_chain_position,
975 tap->dotted_name,
976 tap->enabled ? 'Y' : 'n',
977 (unsigned int)(tap->idcode),
978 expected_id,
979 (unsigned int)(tap->ir_length),
980 (unsigned int)(expected),
981 (unsigned int)(expected_mask));
982
983 for (ii = 1; ii < tap->expected_ids_cnt; ii++) {
984 snprintf(expected_id, sizeof expected_id, "0x%08x",
985 (unsigned) tap->expected_ids[1]);
986 if (tap->ignore_version)
987 expected_id[2] = '*';
988
989 command_print(CMD_CTX,
990 " %s",
991 expected_id);
992 }
993
994 tap = tap->next_tap;
995 }
996
997 return ERROR_OK;
998 }
999
1000 COMMAND_HANDLER(handle_jtag_ntrst_delay_command)
1001 {
1002 if (CMD_ARGC > 1)
1003 return ERROR_COMMAND_SYNTAX_ERROR;
1004 if (CMD_ARGC == 1)
1005 {
1006 unsigned delay;
1007 COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], delay);
1008
1009 jtag_set_ntrst_delay(delay);
1010 }
1011 command_print(CMD_CTX, "jtag_ntrst_delay: %u", jtag_get_ntrst_delay());
1012 return ERROR_OK;
1013 }
1014
1015 COMMAND_HANDLER(handle_jtag_ntrst_assert_width_command)
1016 {
1017 if (CMD_ARGC > 1)
1018 return ERROR_COMMAND_SYNTAX_ERROR;
1019 if (CMD_ARGC == 1)
1020 {
1021 unsigned delay;
1022 COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], delay);
1023
1024 jtag_set_ntrst_assert_width(delay);
1025 }
1026 command_print(CMD_CTX, "jtag_ntrst_assert_width: %u", jtag_get_ntrst_assert_width());
1027 return ERROR_OK;
1028 }
1029
1030 COMMAND_HANDLER(handle_jtag_rclk_command)
1031 {
1032 if (CMD_ARGC > 1)
1033 return ERROR_COMMAND_SYNTAX_ERROR;
1034
1035 int retval = ERROR_OK;
1036 if (CMD_ARGC == 1)
1037 {
1038 unsigned khz = 0;
1039 COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], khz);
1040
1041 retval = jtag_config_rclk(khz);
1042 if (ERROR_OK != retval)
1043 return retval;
1044 }
1045
1046 int cur_khz = jtag_get_speed_khz();
1047 retval = jtag_get_speed_readable(&cur_khz);
1048 if (ERROR_OK != retval)
1049 return retval;
1050
1051 if (cur_khz)
1052 command_print(CMD_CTX, "RCLK not supported - fallback to %d kHz", cur_khz);
1053 else
1054 command_print(CMD_CTX, "RCLK - adaptive");
1055
1056 return retval;
1057 }
1058
1059 COMMAND_HANDLER(handle_jtag_reset_command)
1060 {
1061 if (CMD_ARGC != 2)
1062 return ERROR_COMMAND_SYNTAX_ERROR;
1063
1064 int trst = -1;
1065 if (CMD_ARGV[0][0] == '1')
1066 trst = 1;
1067 else if (CMD_ARGV[0][0] == '0')
1068 trst = 0;
1069 else
1070 return ERROR_COMMAND_SYNTAX_ERROR;
1071
1072 int srst = -1;
1073 if (CMD_ARGV[1][0] == '1')
1074 srst = 1;
1075 else if (CMD_ARGV[1][0] == '0')
1076 srst = 0;
1077 else
1078 return ERROR_COMMAND_SYNTAX_ERROR;
1079
1080 if (adapter_init(CMD_CTX) != ERROR_OK)
1081 return ERROR_JTAG_INIT_FAILED;
1082
1083 jtag_add_reset(trst, srst);
1084 return jtag_execute_queue();
1085 }
1086
1087 COMMAND_HANDLER(handle_runtest_command)
1088 {
1089 if (CMD_ARGC != 1)
1090 return ERROR_COMMAND_SYNTAX_ERROR;
1091
1092 unsigned num_clocks;
1093 COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], num_clocks);
1094
1095 jtag_add_runtest(num_clocks, TAP_IDLE);
1096 return jtag_execute_queue();
1097 }
1098
1099 /*
1100 * For "irscan" or "drscan" commands, the "end" (really, "next") state
1101 * should be stable ... and *NOT* a shift state, otherwise free-running
1102 * jtag clocks could change the values latched by the update state.
1103 * Not surprisingly, this is the same constraint as SVF; the "irscan"
1104 * and "drscan" commands are a write-only subset of what SVF provides.
1105 */
1106
1107 COMMAND_HANDLER(handle_irscan_command)
1108 {
1109 int i;
1110 struct scan_field *fields;
1111 struct jtag_tap *tap = NULL;
1112 tap_state_t endstate;
1113
1114 if ((CMD_ARGC < 2) || (CMD_ARGC % 2))
1115 {
1116 return ERROR_COMMAND_SYNTAX_ERROR;
1117 }
1118
1119 /* optional "-endstate" "statename" at the end of the arguments,
1120 * so that e.g. IRPAUSE can let us load the data register before
1121 * entering RUN/IDLE to execute the instruction we load here.
1122 */
1123 endstate = TAP_IDLE;
1124
1125 if (CMD_ARGC >= 4) {
1126 /* have at least one pair of numbers. */
1127 /* is last pair the magic text? */
1128 if (strcmp("-endstate", CMD_ARGV[CMD_ARGC - 2]) == 0) {
1129 endstate = tap_state_by_name(CMD_ARGV[CMD_ARGC - 1]);
1130 if (endstate == TAP_INVALID)
1131 return ERROR_COMMAND_SYNTAX_ERROR;
1132 if (!scan_is_safe(endstate))
1133 LOG_WARNING("unstable irscan endstate \"%s\"",
1134 CMD_ARGV[CMD_ARGC - 1]);
1135 CMD_ARGC -= 2;
1136 }
1137 }
1138
1139 int num_fields = CMD_ARGC / 2;
1140 if (num_fields > 1)
1141 {
1142 /* we really should be looking at plain_ir_scan if we want
1143 * anything more fancy.
1144 */
1145 LOG_ERROR("Specify a single value for tap");
1146 return ERROR_COMMAND_SYNTAX_ERROR;
1147 }
1148
1149 size_t fields_len = sizeof(struct scan_field) * num_fields;
1150 fields = malloc(fields_len);
1151 memset(fields, 0, fields_len);
1152
1153 int retval;
1154 for (i = 0; i < num_fields; i++)
1155 {
1156 tap = jtag_tap_by_string(CMD_ARGV[i*2]);
1157 if (tap == NULL)
1158 {
1159 int j;
1160 for (j = 0; j < i; j++)
1161 free((void *)fields[j].out_value);
1162 free(fields);
1163 command_print(CMD_CTX, "Tap: %s unknown", CMD_ARGV[i*2]);
1164
1165 return ERROR_FAIL;
1166 }
1167 int field_size = tap->ir_length;
1168 fields[i].num_bits = field_size;
1169 fields[i].out_value = malloc(DIV_ROUND_UP(field_size, 8));
1170
1171 uint32_t value;
1172 retval = parse_u32(CMD_ARGV[i * 2 + 1], &value);
1173 if (ERROR_OK != retval)
1174 goto error_return;
1175 void *v = (void *)fields[i].out_value;
1176 buf_set_u32(v, 0, field_size, value);
1177 fields[i].in_value = NULL;
1178 }
1179
1180 /* did we have an endstate? */
1181 jtag_add_ir_scan(tap, fields, endstate);
1182
1183 retval = jtag_execute_queue();
1184
1185 error_return:
1186 for (i = 0; i < num_fields; i++)
1187 {
1188 if (NULL != fields[i].out_value)
1189 free((void *)fields[i].out_value);
1190 }
1191
1192 free (fields);
1193
1194 return retval;
1195 }
1196
1197
1198 COMMAND_HANDLER(handle_verify_ircapture_command)
1199 {
1200 if (CMD_ARGC > 1)
1201 return ERROR_COMMAND_SYNTAX_ERROR;
1202
1203 if (CMD_ARGC == 1)
1204 {
1205 bool enable;
1206 COMMAND_PARSE_ENABLE(CMD_ARGV[0], enable);
1207 jtag_set_verify_capture_ir(enable);
1208 }
1209
1210 const char *status = jtag_will_verify_capture_ir() ? "enabled": "disabled";
1211 command_print(CMD_CTX, "verify Capture-IR is %s", status);
1212
1213 return ERROR_OK;
1214 }
1215
1216 COMMAND_HANDLER(handle_verify_jtag_command)
1217 {
1218 if (CMD_ARGC > 1)
1219 return ERROR_COMMAND_SYNTAX_ERROR;
1220
1221 if (CMD_ARGC == 1)
1222 {
1223 bool enable;
1224 COMMAND_PARSE_ENABLE(CMD_ARGV[0], enable);
1225 jtag_set_verify(enable);
1226 }
1227
1228 const char *status = jtag_will_verify() ? "enabled": "disabled";
1229 command_print(CMD_CTX, "verify jtag capture is %s", status);
1230
1231 return ERROR_OK;
1232 }
1233
1234 COMMAND_HANDLER(handle_tms_sequence_command)
1235 {
1236 if (CMD_ARGC > 1)
1237 return ERROR_COMMAND_SYNTAX_ERROR;
1238
1239 if (CMD_ARGC == 1)
1240 {
1241 bool use_new_table;
1242 if (strcmp(CMD_ARGV[0], "short") == 0)
1243 use_new_table = true;
1244 else if (strcmp(CMD_ARGV[0], "long") == 0)
1245 use_new_table = false;
1246 else
1247 return ERROR_COMMAND_SYNTAX_ERROR;
1248
1249 tap_use_new_tms_table(use_new_table);
1250 }
1251
1252 command_print(CMD_CTX, "tms sequence is %s",
1253 tap_uses_new_tms_table() ? "short": "long");
1254
1255 return ERROR_OK;
1256 }
1257
1258 COMMAND_HANDLER(handle_jtag_flush_queue_sleep)
1259 {
1260 if (CMD_ARGC != 1)
1261 return ERROR_COMMAND_SYNTAX_ERROR;
1262
1263 int sleep_ms;
1264 COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], sleep_ms);
1265
1266 jtag_set_flush_queue_sleep(sleep_ms);
1267
1268 return ERROR_OK;
1269 }
1270
1271 COMMAND_HANDLER(handle_wait_srst_deassert)
1272 {
1273 if (CMD_ARGC != 1)
1274 return ERROR_COMMAND_SYNTAX_ERROR;
1275
1276 int timeout_ms;
1277 COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], timeout_ms);
1278 if ((timeout_ms <= 0) || (timeout_ms > 100000))
1279 {
1280 LOG_ERROR("Timeout must be an integer between 0 and 100000");
1281 return ERROR_FAIL;
1282 }
1283
1284 LOG_USER("Waiting for srst assert + deassert for at most %dms", timeout_ms);
1285 int asserted_yet;
1286 long long then = timeval_ms();
1287 while (jtag_srst_asserted(&asserted_yet) == ERROR_OK)
1288 {
1289 if ((timeval_ms() - then) > timeout_ms)
1290 {
1291 LOG_ERROR("Timed out");
1292 return ERROR_FAIL;
1293 }
1294 if (asserted_yet)
1295 break;
1296 }
1297 while (jtag_srst_asserted(&asserted_yet) == ERROR_OK)
1298 {
1299 if ((timeval_ms() - then) > timeout_ms)
1300 {
1301 LOG_ERROR("Timed out");
1302 return ERROR_FAIL;
1303 }
1304 if (!asserted_yet)
1305 break;
1306 }
1307
1308 return ERROR_OK;
1309 }
1310
1311
1312
1313 static const struct command_registration jtag_command_handlers[] = {
1314
1315 {
1316 .name = "jtag_flush_queue_sleep",
1317 .handler = handle_jtag_flush_queue_sleep,
1318 .mode = COMMAND_ANY,
1319 .help = "For debug purposes(simulate long delays of interface) "
1320 "to test performance or change in behavior. Default 0ms.",
1321 .usage = "[sleep in ms]",
1322 },
1323 {
1324 .name = "jtag_rclk",
1325 .handler = handle_jtag_rclk_command,
1326 .mode = COMMAND_ANY,
1327 .help = "With an argument, change to to use adaptive clocking "
1328 "if possible; else to use the fallback speed. "
1329 "With or without argument, display current setting.",
1330 .usage = "[fallback_speed_khz]",
1331 },
1332 {
1333 .name = "jtag_ntrst_delay",
1334 .handler = handle_jtag_ntrst_delay_command,
1335 .mode = COMMAND_ANY,
1336 .help = "delay after deasserting trst in ms",
1337 .usage = "[milliseconds]",
1338 },
1339 {
1340 .name = "jtag_ntrst_assert_width",
1341 .handler = handle_jtag_ntrst_assert_width_command,
1342 .mode = COMMAND_ANY,
1343 .help = "delay after asserting trst in ms",
1344 .usage = "[milliseconds]",
1345 },
1346 {
1347 .name = "scan_chain",
1348 .handler = handle_scan_chain_command,
1349 .mode = COMMAND_ANY,
1350 .help = "print current scan chain configuration",
1351 },
1352 {
1353 .name = "jtag_reset",
1354 .handler = handle_jtag_reset_command,
1355 .mode = COMMAND_EXEC,
1356 .help = "Set reset line values. Value '1' is active, "
1357 "value '0' is inactive.",
1358 .usage = "trst_active srst_active",
1359 },
1360 {
1361 .name = "runtest",
1362 .handler = handle_runtest_command,
1363 .mode = COMMAND_EXEC,
1364 .help = "Move to Run-Test/Idle, and issue TCK for num_cycles.",
1365 .usage = "num_cycles"
1366 },
1367 {
1368 .name = "irscan",
1369 .handler = handle_irscan_command,
1370 .mode = COMMAND_EXEC,
1371 .help = "Execute Instruction Register (DR) scan. The "
1372 "specified opcodes are put into each TAP's IR, "
1373 "and other TAPs are put in BYPASS.",
1374 .usage = "[tap_name instruction]* ['-endstate' state_name]",
1375 },
1376 {
1377 .name = "verify_ircapture",
1378 .handler = handle_verify_ircapture_command,
1379 .mode = COMMAND_ANY,
1380 .help = "Display or assign flag controlling whether to "
1381 "verify values captured during Capture-IR.",
1382 .usage = "['enable'|'disable']",
1383 },
1384 {
1385 .name = "verify_jtag",
1386 .handler = handle_verify_jtag_command,
1387 .mode = COMMAND_ANY,
1388 .help = "Display or assign flag controlling whether to "
1389 "verify values captured during IR and DR scans.",
1390 .usage = "['enable'|'disable']",
1391 },
1392 {
1393 .name = "tms_sequence",
1394 .handler = handle_tms_sequence_command,
1395 .mode = COMMAND_ANY,
1396 .help = "Display or change what style TMS sequences to use "
1397 "for JTAG state transitions: short (default) or "
1398 "long. Only for working around JTAG bugs.",
1399 /* Specifically for working around DRIVER bugs... */
1400 .usage = "['short'|'long']",
1401 },
1402 {
1403 .name = "wait_srst_deassert",
1404 .handler = handle_wait_srst_deassert,
1405 .mode = COMMAND_ANY,
1406 .help = "Wait for an SRST deassert. "
1407 "Useful for cases where you need something to happen within ms "
1408 "of an srst deassert. Timeout in ms ",
1409 .usage = "ms",
1410 },
1411 {
1412 .name = "jtag",
1413 .mode = COMMAND_ANY,
1414 .help = "perform jtag tap actions",
1415
1416 .chain = jtag_subcommand_handlers,
1417 },
1418 {
1419 .chain = jtag_command_handlers_to_move,
1420 },
1421 COMMAND_REGISTRATION_DONE
1422 };
1423
1424 int jtag_register_commands(struct command_context *cmd_ctx)
1425 {
1426 return register_commands(cmd_ctx, NULL, jtag_command_handlers);
1427 }

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)