1 /***************************************************************************
2 * Copyright (C) 2005 by Dominic Rath *
3 * Dominic.Rath@gmx.de *
5 * Copyright (C) 2007,2008 Øyvind Harboe *
6 * oyvind.harboe@zylin.com *
8 * Copyright (C) 2009 SoftPLC Corporation *
12 * Copyright (C) 2009 Zachary T Welch *
13 * zw@superlucidity.net *
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. *
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. *
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 ***************************************************************************/
35 #include "minidriver.h"
36 #include "interface.h"
37 #include "interfaces.h"
43 static const Jim_Nvp nvp_jtag_tap_event
[] = {
44 { .value
= JTAG_TRST_ASSERTED
, .name
= "post-reset" },
45 { .value
= JTAG_TAP_EVENT_SETUP
, .name
= "setup" },
46 { .value
= JTAG_TAP_EVENT_ENABLE
, .name
= "tap-enable" },
47 { .value
= JTAG_TAP_EVENT_DISABLE
, .name
= "tap-disable" },
49 { .name
= NULL
, .value
= -1 }
52 extern struct jtag_interface
*jtag_interface
;
54 struct jtag_tap
*jtag_tap_by_jim_obj(Jim_Interp
*interp
, Jim_Obj
*o
)
56 const char *cp
= Jim_GetString(o
, NULL
);
57 struct jtag_tap
*t
= cp
? jtag_tap_by_string(cp
) : NULL
;
61 Jim_SetResult_sprintf(interp
, "Tap '%s' could not be found", cp
);
65 static bool scan_is_safe(tap_state_t state
)
79 static int Jim_Command_drscan(Jim_Interp
*interp
, int argc
, Jim_Obj
*const *args
)
82 struct scan_field
*fields
;
91 * args[3] = hex string
92 * ... repeat num bits and hex string ...
95 * args[N-2] = "-endstate"
96 * args[N-1] = statename
98 if ((argc
< 4) || ((argc
% 2) != 0))
100 Jim_WrongNumArgs(interp
, 1, args
, "wrong arguments");
106 script_debug(interp
, "drscan", argc
, args
);
108 /* validate arguments as numbers */
110 for (i
= 2; i
< argc
; i
+= 2)
115 e
= Jim_GetLong(interp
, args
[i
], &bits
);
116 /* If valid - try next arg */
121 /* Not valid.. are we at the end? */
122 if (((i
+ 2) != argc
)) {
123 /* nope, then error */
127 /* it could be: "-endstate FOO"
128 * e.g. DRPAUSE so we can issue more instructions
129 * before entering RUN/IDLE and executing them.
132 /* get arg as a string. */
133 cp
= Jim_GetString(args
[i
], NULL
);
134 /* is it the magic? */
135 if (0 == strcmp("-endstate", cp
)) {
136 /* is the statename valid? */
137 cp
= Jim_GetString(args
[i
+ 1], NULL
);
139 /* see if it is a valid state name */
140 endstate
= tap_state_by_name(cp
);
142 /* update the error message */
143 Jim_SetResult_sprintf(interp
,"endstate: %s invalid", cp
);
145 if (!scan_is_safe(endstate
))
146 LOG_WARNING("drscan with unsafe "
147 "endstate \"%s\"", cp
);
149 /* valid - so clear the error */
151 /* and remove the last 2 args */
156 /* Still an error? */
158 return e
; /* too bad */
160 } /* validate args */
162 tap
= jtag_tap_by_jim_obj(interp
, args
[1]);
167 num_fields
= (argc
-2)/2;
168 fields
= malloc(sizeof(struct scan_field
) * num_fields
);
169 for (i
= 2; i
< argc
; i
+= 2)
175 Jim_GetLong(interp
, args
[i
], &bits
);
176 str
= Jim_GetString(args
[i
+ 1], &len
);
178 fields
[field_count
].tap
= tap
;
179 fields
[field_count
].num_bits
= bits
;
180 fields
[field_count
].out_value
= malloc(DIV_ROUND_UP(bits
, 8));
181 str_to_buf(str
, len
, fields
[field_count
].out_value
, bits
, 0);
182 fields
[field_count
].in_value
= fields
[field_count
].out_value
;
186 jtag_add_dr_scan(num_fields
, fields
, endstate
);
188 retval
= jtag_execute_queue();
189 if (retval
!= ERROR_OK
)
191 Jim_SetResultString(interp
, "drscan: jtag execute failed",-1);
196 Jim_Obj
*list
= Jim_NewListObj(interp
, NULL
, 0);
197 for (i
= 2; i
< argc
; i
+= 2)
202 Jim_GetLong(interp
, args
[i
], &bits
);
203 str
= buf_to_str(fields
[field_count
].in_value
, bits
, 16);
204 free(fields
[field_count
].out_value
);
206 Jim_ListAppendElement(interp
, list
, Jim_NewStringObj(interp
, str
, strlen(str
)));
211 Jim_SetResult(interp
, list
);
219 static int Jim_Command_pathmove(Jim_Interp
*interp
, int argc
, Jim_Obj
*const *args
)
221 tap_state_t states
[8];
223 if ((argc
< 2) || ((size_t)argc
> (ARRAY_SIZE(states
) + 1)))
225 Jim_WrongNumArgs(interp
, 1, args
, "wrong arguments");
229 script_debug(interp
, "pathmove", argc
, args
);
232 for (i
= 0; i
< argc
-1; i
++)
235 cp
= Jim_GetString(args
[i
+ 1], NULL
);
236 states
[i
] = tap_state_by_name(cp
);
239 /* update the error message */
240 Jim_SetResult_sprintf(interp
,"endstate: %s invalid", cp
);
245 if ((jtag_add_statemove(states
[0]) != ERROR_OK
) || (jtag_execute_queue()!= ERROR_OK
))
247 Jim_SetResultString(interp
, "pathmove: jtag execute failed",-1);
251 jtag_add_pathmove(argc
-2, states
+ 1);
253 if (jtag_execute_queue()!= ERROR_OK
)
255 Jim_SetResultString(interp
, "pathmove: failed",-1);
263 static int Jim_Command_flush_count(Jim_Interp
*interp
, int argc
, Jim_Obj
*const *args
)
265 script_debug(interp
, "flush_count", argc
, args
);
267 Jim_SetResult(interp
, Jim_NewIntObj(interp
, jtag_get_flush_queue_count()));
272 static const struct command_registration jtag_command_handlers_to_move
[] = {
275 .mode
= COMMAND_EXEC
,
276 .jim_handler
= &Jim_Command_drscan
,
277 .help
= "execute DR scan <device> "
278 "<num_bits> <value> <num_bits1> <value2> ...",
281 .name
= "flush_count",
282 .mode
= COMMAND_EXEC
,
283 .jim_handler
= &Jim_Command_flush_count
,
284 .help
= "returns number of times the JTAG queue has been flushed",
288 .mode
= COMMAND_EXEC
,
289 .jim_handler
= &Jim_Command_pathmove
,
290 .usage
= "<state1>,<state2>,<state3>... ",
291 .help
= "move JTAG to state1 then to state2, state3, etc.",
293 COMMAND_REGISTRATION_DONE
297 enum jtag_tap_cfg_param
{
301 static Jim_Nvp nvp_config_opts
[] = {
302 { .name
= "-event", .value
= JCFG_EVENT
},
304 { .name
= NULL
, .value
= -1 }
307 static int jtag_tap_configure_event(Jim_GetOptInfo
*goi
, struct jtag_tap
* tap
)
311 Jim_WrongNumArgs(goi
->interp
, goi
->argc
, goi
->argv
, "-event <event-name> ...");
316 int e
= Jim_GetOpt_Nvp(goi
, nvp_jtag_tap_event
, &n
);
319 Jim_GetOpt_NvpUnknown(goi
, nvp_jtag_tap_event
, 1);
323 if (goi
->isconfigure
) {
324 if (goi
->argc
!= 1) {
325 Jim_WrongNumArgs(goi
->interp
, goi
->argc
, goi
->argv
, "-event <event-name> <event-body>");
329 if (goi
->argc
!= 0) {
330 Jim_WrongNumArgs(goi
->interp
, goi
->argc
, goi
->argv
, "-event <event-name>");
335 struct jtag_tap_event_action
*jteap
= tap
->event_action
;
336 /* replace existing event body */
340 if (jteap
->event
== (enum jtag_event
)n
->value
)
348 Jim_SetEmptyResult(goi
->interp
);
350 if (goi
->isconfigure
)
353 jteap
= calloc(1, sizeof(*jteap
));
354 else if (NULL
!= jteap
->body
)
355 Jim_DecrRefCount(goi
->interp
, jteap
->body
);
357 jteap
->interp
= goi
->interp
;
358 jteap
->event
= n
->value
;
361 Jim_GetOpt_Obj(goi
, &o
);
362 jteap
->body
= Jim_DuplicateObj(goi
->interp
, o
);
363 Jim_IncrRefCount(jteap
->body
);
367 /* add to head of event list */
368 jteap
->next
= tap
->event_action
;
369 tap
->event_action
= jteap
;
374 jteap
->interp
= goi
->interp
;
375 Jim_SetResult(goi
->interp
,
376 Jim_DuplicateObj(goi
->interp
, jteap
->body
));
381 static int jtag_tap_configure_cmd(Jim_GetOptInfo
*goi
, struct jtag_tap
* tap
)
383 /* parse config or cget options */
384 while (goi
->argc
> 0)
386 Jim_SetEmptyResult (goi
->interp
);
389 int e
= Jim_GetOpt_Nvp(goi
, nvp_config_opts
, &n
);
392 Jim_GetOpt_NvpUnknown(goi
, nvp_config_opts
, 0);
399 e
= jtag_tap_configure_event(goi
, tap
);
404 Jim_SetResult_sprintf(goi
->interp
, "unknown event: %s", n
->name
);
412 static int is_bad_irval(int ir_length
, jim_wide w
)
422 static int jim_newtap_expected_id(Jim_Nvp
*n
, Jim_GetOptInfo
*goi
,
423 struct jtag_tap
*pTap
)
426 int e
= Jim_GetOpt_Wide(goi
, &w
);
428 Jim_SetResult_sprintf(goi
->interp
, "option: %s bad parameter", n
->name
);
432 unsigned expected_len
= sizeof(uint32_t) * pTap
->expected_ids_cnt
;
433 uint32_t *new_expected_ids
= malloc(expected_len
+ sizeof(uint32_t));
434 if (new_expected_ids
== NULL
)
436 Jim_SetResult_sprintf(goi
->interp
, "no memory");
440 memcpy(new_expected_ids
, pTap
->expected_ids
, expected_len
);
442 new_expected_ids
[pTap
->expected_ids_cnt
] = w
;
444 free(pTap
->expected_ids
);
445 pTap
->expected_ids
= new_expected_ids
;
446 pTap
->expected_ids_cnt
++;
451 #define NTAP_OPT_IRLEN 0
452 #define NTAP_OPT_IRMASK 1
453 #define NTAP_OPT_IRCAPTURE 2
454 #define NTAP_OPT_ENABLED 3
455 #define NTAP_OPT_DISABLED 4
456 #define NTAP_OPT_EXPECTED_ID 5
458 static int jim_newtap_ir_param(Jim_Nvp
*n
, Jim_GetOptInfo
*goi
,
459 struct jtag_tap
*pTap
)
462 int e
= Jim_GetOpt_Wide(goi
, &w
);
465 Jim_SetResult_sprintf(goi
->interp
,
466 "option: %s bad parameter", n
->name
);
467 free((void *)pTap
->dotted_name
);
472 if (w
> (jim_wide
) (8 * sizeof(pTap
->ir_capture_value
)))
474 LOG_WARNING("%s: huge IR length %d",
475 pTap
->dotted_name
, (int) w
);
479 case NTAP_OPT_IRMASK
:
480 if (is_bad_irval(pTap
->ir_length
, w
))
482 LOG_ERROR("%s: IR mask %x too big",
488 LOG_WARNING("%s: nonstandard IR mask", pTap
->dotted_name
);
489 pTap
->ir_capture_mask
= w
;
491 case NTAP_OPT_IRCAPTURE
:
492 if (is_bad_irval(pTap
->ir_length
, w
))
494 LOG_ERROR("%s: IR capture %x too big",
495 pTap
->dotted_name
, (int) w
);
499 LOG_WARNING("%s: nonstandard IR value",
501 pTap
->ir_capture_value
= w
;
509 static int jim_newtap_cmd(Jim_GetOptInfo
*goi
)
511 struct jtag_tap
*pTap
;
516 const Jim_Nvp opts
[] = {
517 { .name
= "-irlen" , .value
= NTAP_OPT_IRLEN
},
518 { .name
= "-irmask" , .value
= NTAP_OPT_IRMASK
},
519 { .name
= "-ircapture" , .value
= NTAP_OPT_IRCAPTURE
},
520 { .name
= "-enable" , .value
= NTAP_OPT_ENABLED
},
521 { .name
= "-disable" , .value
= NTAP_OPT_DISABLED
},
522 { .name
= "-expected-id" , .value
= NTAP_OPT_EXPECTED_ID
},
523 { .name
= NULL
, .value
= -1 },
526 pTap
= calloc(1, sizeof(struct jtag_tap
));
528 Jim_SetResult_sprintf(goi
->interp
, "no memory");
533 * we expect CHIP + TAP + OPTIONS
536 Jim_SetResult_sprintf(goi
->interp
, "Missing CHIP TAP OPTIONS ....");
540 Jim_GetOpt_String(goi
, &cp
, NULL
);
541 pTap
->chip
= strdup(cp
);
543 Jim_GetOpt_String(goi
, &cp
, NULL
);
544 pTap
->tapname
= strdup(cp
);
546 /* name + dot + name + null */
547 x
= strlen(pTap
->chip
) + 1 + strlen(pTap
->tapname
) + 1;
549 sprintf(cp
, "%s.%s", pTap
->chip
, pTap
->tapname
);
550 pTap
->dotted_name
= cp
;
552 LOG_DEBUG("Creating New Tap, Chip: %s, Tap: %s, Dotted: %s, %d params",
553 pTap
->chip
, pTap
->tapname
, pTap
->dotted_name
, goi
->argc
);
555 /* IEEE specifies that the two LSBs of an IR scan are 01, so make
556 * that the default. The "-irlen" and "-irmask" options are only
557 * needed to cope with nonstandard TAPs, or to specify more bits.
559 pTap
->ir_capture_mask
= 0x03;
560 pTap
->ir_capture_value
= 0x01;
563 e
= Jim_GetOpt_Nvp(goi
, opts
, &n
);
565 Jim_GetOpt_NvpUnknown(goi
, opts
, 0);
566 free((void *)pTap
->dotted_name
);
570 LOG_DEBUG("Processing option: %s", n
->name
);
572 case NTAP_OPT_ENABLED
:
573 pTap
->disabled_after_reset
= false;
575 case NTAP_OPT_DISABLED
:
576 pTap
->disabled_after_reset
= true;
578 case NTAP_OPT_EXPECTED_ID
:
579 e
= jim_newtap_expected_id(n
, goi
, pTap
);
582 free((void *)pTap
->dotted_name
);
588 case NTAP_OPT_IRMASK
:
589 case NTAP_OPT_IRCAPTURE
:
590 e
= jim_newtap_ir_param(n
, goi
, pTap
);
593 free((void *)pTap
->dotted_name
);
598 } /* switch (n->value) */
599 } /* while (goi->argc) */
601 /* default is enabled-after-reset */
602 pTap
->enabled
= !pTap
->disabled_after_reset
;
604 /* Did all the required option bits get cleared? */
605 if (pTap
->ir_length
!= 0)
611 Jim_SetResult_sprintf(goi
->interp
,
612 "newtap: %s missing IR length",
618 static void jtag_tap_handle_event(struct jtag_tap
*tap
, enum jtag_event e
)
620 struct jtag_tap_event_action
* jteap
;
622 for (jteap
= tap
->event_action
; jteap
!= NULL
; jteap
= jteap
->next
)
624 if (jteap
->event
!= e
)
627 Jim_Nvp
*nvp
= Jim_Nvp_value2name_simple(nvp_jtag_tap_event
, e
);
628 LOG_DEBUG("JTAG tap: %s event: %d (%s)\n\taction: %s",
629 tap
->dotted_name
, e
, nvp
->name
,
630 Jim_GetString(jteap
->body
, NULL
));
632 if (Jim_EvalObj(jteap
->interp
, jteap
->body
) != JIM_OK
)
634 Jim_PrintErrorMessage(jteap
->interp
);
640 case JTAG_TAP_EVENT_ENABLE
:
641 case JTAG_TAP_EVENT_DISABLE
:
642 /* NOTE: we currently assume the handlers
643 * can't fail. Right here is where we should
644 * really be verifying the scan chains ...
646 tap
->enabled
= (e
== JTAG_TAP_EVENT_ENABLE
);
647 LOG_INFO("JTAG tap: %s %s", tap
->dotted_name
,
648 tap
->enabled
? "enabled" : "disabled");
656 static int jim_jtag_interface(Jim_Interp
*interp
, int argc
, Jim_Obj
*const *argv
)
659 Jim_GetOpt_Setup(&goi
, interp
, argc
-1, argv
+ 1);
661 /* return the name of the interface */
662 /* TCL code might need to know the exact type... */
663 /* FUTURE: we allow this as a means to "set" the interface. */
665 Jim_WrongNumArgs(goi
.interp
, 1, goi
.argv
-1, "(no params)");
668 const char *name
= jtag_interface
? jtag_interface
->name
: NULL
;
669 Jim_SetResultString(goi
.interp
, name
? : "undefined", -1);
673 static int jim_jtag_arp_init(Jim_Interp
*interp
, int argc
, Jim_Obj
*const *argv
)
676 Jim_GetOpt_Setup(&goi
, interp
, argc
-1, argv
+ 1);
678 Jim_WrongNumArgs(goi
.interp
, 1, goi
.argv
-1, "(no params)");
681 struct command_context
*context
= Jim_GetAssocData(interp
, "context");
682 int e
= jtag_init_inner(context
);
684 Jim_SetResult_sprintf(goi
.interp
, "error: %d", e
);
690 static int jim_jtag_arp_init_reset(Jim_Interp
*interp
, int argc
, Jim_Obj
*const *argv
)
693 Jim_GetOpt_Setup(&goi
, interp
, argc
-1, argv
+ 1);
695 Jim_WrongNumArgs(goi
.interp
, 1, goi
.argv
-1, "(no params)");
698 struct command_context
*context
= Jim_GetAssocData(interp
, "context");
699 int e
= jtag_init_reset(context
);
701 Jim_SetResult_sprintf(goi
.interp
, "error: %d", e
);
707 static int jim_jtag_newtap(Jim_Interp
*interp
, int argc
, Jim_Obj
*const *argv
)
710 Jim_GetOpt_Setup(&goi
, interp
, argc
-1, argv
+ 1);
711 return jim_newtap_cmd(&goi
);
714 static bool jtag_tap_enable(struct jtag_tap
*t
)
718 jtag_tap_handle_event(t
, JTAG_TAP_EVENT_ENABLE
);
722 /* FIXME add JTAG sanity checks, w/o TLR
723 * - scan chain length grew by one (this)
724 * - IDs and IR lengths are as expected
726 jtag_call_event_callbacks(JTAG_TAP_EVENT_ENABLE
);
729 static bool jtag_tap_disable(struct jtag_tap
*t
)
733 jtag_tap_handle_event(t
, JTAG_TAP_EVENT_DISABLE
);
737 /* FIXME add JTAG sanity checks, w/o TLR
738 * - scan chain length shrank by one (this)
739 * - IDs and IR lengths are as expected
741 jtag_call_event_callbacks(JTAG_TAP_EVENT_DISABLE
);
745 static int jim_jtag_tap_enabler(Jim_Interp
*interp
, int argc
, Jim_Obj
*const *argv
)
747 const char *cmd_name
= Jim_GetString(argv
[0], NULL
);
749 Jim_GetOpt_Setup(&goi
, interp
, argc
-1, argv
+ 1);
751 Jim_SetResult_sprintf(goi
.interp
, "usage: %s <name>", cmd_name
);
757 t
= jtag_tap_by_jim_obj(goi
.interp
, goi
.argv
[0]);
761 if (strcasecmp(cmd_name
, "tapisenabled") == 0) {
762 // do nothing, just return the value
763 } else if (strcasecmp(cmd_name
, "tapenable") == 0) {
764 if (!jtag_tap_enable(t
))
765 LOG_WARNING("failed to disable tap");
766 } else if (strcasecmp(cmd_name
, "tapdisable") == 0) {
767 if (!jtag_tap_disable(t
))
768 LOG_WARNING("failed to disable tap");
770 LOG_ERROR("command '%s' unknown", cmd_name
);
774 Jim_SetResult(goi
.interp
, Jim_NewIntObj(goi
.interp
, e
));
778 static int jim_jtag_configure(Jim_Interp
*interp
, int argc
, Jim_Obj
*const *argv
)
780 const char *cmd_name
= Jim_GetString(argv
[0], NULL
);
782 Jim_GetOpt_Setup(&goi
, interp
, argc
-1, argv
+ 1);
783 goi
.isconfigure
= !strcmp(cmd_name
, "configure");
784 if (goi
.argc
< 2 + goi
.isconfigure
) {
785 Jim_WrongNumArgs(goi
.interp
, 0, NULL
,
786 "<tap_name> <attribute> ...");
793 Jim_GetOpt_Obj(&goi
, &o
);
794 t
= jtag_tap_by_jim_obj(goi
.interp
, o
);
799 return jtag_tap_configure_cmd(&goi
, t
);
802 static int jim_jtag_names(Jim_Interp
*interp
, int argc
, Jim_Obj
*const *argv
)
805 Jim_GetOpt_Setup(&goi
, interp
, argc
-1, argv
+ 1);
807 Jim_WrongNumArgs(goi
.interp
, 1, goi
.argv
, "Too many parameters");
810 Jim_SetResult(goi
.interp
, Jim_NewListObj(goi
.interp
, NULL
, 0));
811 struct jtag_tap
*tap
;
813 for (tap
= jtag_all_taps(); tap
; tap
= tap
->next_tap
) {
814 Jim_ListAppendElement(goi
.interp
,
815 Jim_GetResult(goi
.interp
),
816 Jim_NewStringObj(goi
.interp
,
817 tap
->dotted_name
, -1));
822 COMMAND_HANDLER(handle_jtag_init_command
)
825 return ERROR_COMMAND_SYNTAX_ERROR
;
827 static bool jtag_initialized
= false;
828 if (jtag_initialized
)
830 LOG_INFO("'jtag init' has already been called");
833 jtag_initialized
= true;
835 LOG_DEBUG("Initializing jtag devices...");
836 return jtag_init(CMD_CTX
);
839 static const struct command_registration jtag_subcommand_handlers
[] = {
843 .handler
= &handle_jtag_init_command
,
844 .help
= "initialize jtag scan chain",
849 .jim_handler
= &jim_jtag_interface
,
850 .help
= "Returns the selected interface",
855 .jim_handler
= &jim_jtag_arp_init
,
858 .name
= "arp_init-reset",
860 .jim_handler
= &jim_jtag_arp_init_reset
,
864 .mode
= COMMAND_CONFIG
,
865 .jim_handler
= &jim_jtag_newtap
,
866 .help
= "Create a new TAP instance",
867 .usage
= "<name> <type> -irlen <count> [-ircapture <count>] "
868 "[-irmask <count>] [-enable|-disable]",
871 .name
= "tapisenabled",
872 .mode
= COMMAND_EXEC
,
873 .jim_handler
= &jim_jtag_tap_enabler
,
874 .help
= "Returns a integer indicating TAP state (0/1)",
879 .mode
= COMMAND_EXEC
,
880 .jim_handler
= &jim_jtag_tap_enabler
,
881 .help
= "Enable the specified TAP",
885 .name
= "tapdisable",
886 .mode
= COMMAND_EXEC
,
887 .jim_handler
= &jim_jtag_tap_enabler
,
888 .help
= "Enable the specified TAP",
893 .mode
= COMMAND_EXEC
,
894 .jim_handler
= &jim_jtag_configure
,
895 .help
= "Enable the specified TAP",
896 .usage
= "<name> [<key> <value> ...]",
900 .mode
= COMMAND_EXEC
,
901 .jim_handler
= &jim_jtag_configure
,
902 .help
= "Enable the specified TAP",
903 .usage
= "<name> [<key> <value> ...]",
908 .jim_handler
= &jim_jtag_names
,
909 .help
= "Returns list of all JTAG tap names",
912 .chain
= jtag_command_handlers_to_move
,
914 COMMAND_REGISTRATION_DONE
917 void jtag_notify_event(enum jtag_event event
)
919 struct jtag_tap
*tap
;
921 for (tap
= jtag_all_taps(); tap
; tap
= tap
->next_tap
)
922 jtag_tap_handle_event(tap
, event
);
926 static int default_khz(int khz
, int *jtag_speed
)
928 LOG_ERROR("Translation from khz to jtag_speed not implemented");
932 static int default_speed_div(int speed
, int *khz
)
934 LOG_ERROR("Translation from jtag_speed to khz not implemented");
938 static int default_power_dropout(int *dropout
)
940 *dropout
= 0; /* by default we can't detect power dropout */
944 static int default_srst_asserted(int *srst_asserted
)
946 *srst_asserted
= 0; /* by default we can't detect srst asserted */
950 COMMAND_HANDLER(handle_interface_list_command
)
952 if (strcmp(CMD_NAME
, "interface_list") == 0 && CMD_ARGC
> 0)
953 return ERROR_COMMAND_SYNTAX_ERROR
;
955 command_print(CMD_CTX
, "The following JTAG interfaces are available:");
956 for (unsigned i
= 0; NULL
!= jtag_interfaces
[i
]; i
++)
958 const char *name
= jtag_interfaces
[i
]->name
;
959 command_print(CMD_CTX
, "%u: %s", i
+ 1, name
);
965 COMMAND_HANDLER(handle_interface_command
)
967 /* check whether the interface is already configured */
970 LOG_WARNING("Interface already configured, ignoring");
974 /* interface name is a mandatory argument */
975 if (CMD_ARGC
!= 1 || CMD_ARGV
[0][0] == '\0')
976 return ERROR_COMMAND_SYNTAX_ERROR
;
978 for (unsigned i
= 0; NULL
!= jtag_interfaces
[i
]; i
++)
980 if (strcmp(CMD_ARGV
[0], jtag_interfaces
[i
]->name
) != 0)
983 if (NULL
!= jtag_interfaces
[i
]->commands
)
985 int retval
= register_commands(CMD_CTX
, NULL
,
986 jtag_interfaces
[i
]->commands
);
987 if (ERROR_OK
!= retval
)
991 jtag_interface
= jtag_interfaces
[i
];
993 if (jtag_interface
->khz
== NULL
)
994 jtag_interface
->khz
= default_khz
;
995 if (jtag_interface
->speed_div
== NULL
)
996 jtag_interface
->speed_div
= default_speed_div
;
997 if (jtag_interface
->power_dropout
== NULL
)
998 jtag_interface
->power_dropout
= default_power_dropout
;
999 if (jtag_interface
->srst_asserted
== NULL
)
1000 jtag_interface
->srst_asserted
= default_srst_asserted
;
1005 /* no valid interface was found (i.e. the configuration option,
1006 * didn't match one of the compiled-in interfaces
1008 LOG_ERROR("The specified JTAG interface was not found (%s)", CMD_ARGV
[0]);
1009 CALL_COMMAND_HANDLER(handle_interface_list_command
);
1010 return ERROR_JTAG_INVALID_INTERFACE
;
1013 COMMAND_HANDLER(handle_scan_chain_command
)
1015 struct jtag_tap
*tap
;
1017 tap
= jtag_all_taps();
1018 command_print(CMD_CTX
, " TapName | Enabled | IdCode Expected IrLen IrCap IrMask Instr ");
1019 command_print(CMD_CTX
, "---|--------------------|---------|------------|------------|------|------|------|---------");
1022 uint32_t expected
, expected_mask
, cur_instr
, ii
;
1023 expected
= buf_get_u32(tap
->expected
, 0, tap
->ir_length
);
1024 expected_mask
= buf_get_u32(tap
->expected_mask
, 0, tap
->ir_length
);
1025 cur_instr
= buf_get_u32(tap
->cur_instr
, 0, tap
->ir_length
);
1027 command_print(CMD_CTX
,
1028 "%2d | %-18s | %c | 0x%08x | 0x%08x | 0x%02x | 0x%02x | 0x%02x | 0x%02x",
1029 tap
->abs_chain_position
,
1031 tap
->enabled
? 'Y' : 'n',
1032 (unsigned int)(tap
->idcode
),
1033 (unsigned int)(tap
->expected_ids_cnt
> 0 ? tap
->expected_ids
[0] : 0),
1034 (unsigned int)(tap
->ir_length
),
1035 (unsigned int)(expected
),
1036 (unsigned int)(expected_mask
),
1037 (unsigned int)(cur_instr
));
1039 for (ii
= 1; ii
< tap
->expected_ids_cnt
; ii
++) {
1040 command_print(CMD_CTX
, " | | | | 0x%08x | | | | ",
1041 (unsigned int)(tap
->expected_ids
[ii
]));
1044 tap
= tap
->next_tap
;
1050 COMMAND_HANDLER(handle_reset_config_command
)
1055 /* Original versions cared about the order of these tokens:
1056 * reset_config signals [combination [trst_type [srst_type]]]
1057 * They also clobbered the previous configuration even on error.
1059 * Here we don't care about the order, and only change values
1060 * which have been explicitly specified.
1062 for (; CMD_ARGC
; CMD_ARGC
--, CMD_ARGV
++) {
1067 m
= RESET_SRST_NO_GATING
;
1068 if (strcmp(*CMD_ARGV
, "srst_gates_jtag") == 0)
1069 /* default: don't use JTAG while SRST asserted */;
1070 else if (strcmp(*CMD_ARGV
, "srst_nogate") == 0)
1071 tmp
= RESET_SRST_NO_GATING
;
1075 LOG_ERROR("extra reset_config %s spec (%s)",
1076 "gating", *CMD_ARGV
);
1077 return ERROR_INVALID_ARGUMENTS
;
1083 m
= RESET_HAS_TRST
| RESET_HAS_SRST
;
1084 if (strcmp(*CMD_ARGV
, "none") == 0)
1086 else if (strcmp(*CMD_ARGV
, "trst_only") == 0)
1087 tmp
= RESET_HAS_TRST
;
1088 else if (strcmp(*CMD_ARGV
, "srst_only") == 0)
1089 tmp
= RESET_HAS_SRST
;
1090 else if (strcmp(*CMD_ARGV
, "trst_and_srst") == 0)
1091 tmp
= RESET_HAS_TRST
| RESET_HAS_SRST
;
1095 LOG_ERROR("extra reset_config %s spec (%s)",
1096 "signal", *CMD_ARGV
);
1097 return ERROR_INVALID_ARGUMENTS
;
1102 /* combination (options for broken wiring) */
1103 m
= RESET_SRST_PULLS_TRST
| RESET_TRST_PULLS_SRST
;
1104 if (strcmp(*CMD_ARGV
, "separate") == 0)
1105 /* separate reset lines - default */;
1106 else if (strcmp(*CMD_ARGV
, "srst_pulls_trst") == 0)
1107 tmp
|= RESET_SRST_PULLS_TRST
;
1108 else if (strcmp(*CMD_ARGV
, "trst_pulls_srst") == 0)
1109 tmp
|= RESET_TRST_PULLS_SRST
;
1110 else if (strcmp(*CMD_ARGV
, "combined") == 0)
1111 tmp
|= RESET_SRST_PULLS_TRST
| RESET_TRST_PULLS_SRST
;
1115 LOG_ERROR("extra reset_config %s spec (%s)",
1116 "combination", *CMD_ARGV
);
1117 return ERROR_INVALID_ARGUMENTS
;
1122 /* trst_type (NOP without HAS_TRST) */
1123 m
= RESET_TRST_OPEN_DRAIN
;
1124 if (strcmp(*CMD_ARGV
, "trst_open_drain") == 0)
1125 tmp
|= RESET_TRST_OPEN_DRAIN
;
1126 else if (strcmp(*CMD_ARGV
, "trst_push_pull") == 0)
1127 /* push/pull from adapter - default */;
1131 LOG_ERROR("extra reset_config %s spec (%s)",
1132 "trst_type", *CMD_ARGV
);
1133 return ERROR_INVALID_ARGUMENTS
;
1138 /* srst_type (NOP without HAS_SRST) */
1139 m
|= RESET_SRST_PUSH_PULL
;
1140 if (strcmp(*CMD_ARGV
, "srst_push_pull") == 0)
1141 tmp
|= RESET_SRST_PUSH_PULL
;
1142 else if (strcmp(*CMD_ARGV
, "srst_open_drain") == 0)
1143 /* open drain from adapter - default */;
1147 LOG_ERROR("extra reset_config %s spec (%s)",
1148 "srst_type", *CMD_ARGV
);
1149 return ERROR_INVALID_ARGUMENTS
;
1154 /* caller provided nonsense; fail */
1155 LOG_ERROR("unknown reset_config flag (%s)", *CMD_ARGV
);
1156 return ERROR_INVALID_ARGUMENTS
;
1159 /* Remember the bits which were specified (mask)
1160 * and their new values (new_cfg).
1166 /* clear previous values of those bits, save new values */
1168 int old_cfg
= jtag_get_reset_config();
1172 jtag_set_reset_config(new_cfg
);
1174 new_cfg
= jtag_get_reset_config();
1178 * Display the (now-)current reset mode
1182 /* minimal JTAG has neither SRST nor TRST (so that's the default) */
1183 switch (new_cfg
& (RESET_HAS_TRST
| RESET_HAS_SRST
)) {
1184 case RESET_HAS_SRST
:
1185 modes
[0] = "srst_only";
1187 case RESET_HAS_TRST
:
1188 modes
[0] = "trst_only";
1190 case RESET_TRST_AND_SRST
:
1191 modes
[0] = "trst_and_srst";
1198 /* normally SRST and TRST are decoupled; but bugs happen ... */
1199 switch (new_cfg
& (RESET_SRST_PULLS_TRST
| RESET_TRST_PULLS_SRST
)) {
1200 case RESET_SRST_PULLS_TRST
:
1201 modes
[1] = "srst_pulls_trst";
1203 case RESET_TRST_PULLS_SRST
:
1204 modes
[1] = "trst_pulls_srst";
1206 case RESET_SRST_PULLS_TRST
| RESET_TRST_PULLS_SRST
:
1207 modes
[1] = "combined";
1210 modes
[1] = "separate";
1214 /* TRST-less connectors include Altera, Xilinx, and minimal JTAG */
1215 if (new_cfg
& RESET_HAS_TRST
) {
1216 if (new_cfg
& RESET_TRST_OPEN_DRAIN
)
1217 modes
[3] = " trst_open_drain";
1219 modes
[3] = " trst_push_pull";
1223 /* SRST-less connectors include TI-14, Xilinx, and minimal JTAG */
1224 if (new_cfg
& RESET_HAS_SRST
) {
1225 if (new_cfg
& RESET_SRST_NO_GATING
)
1226 modes
[2] = " srst_nogate";
1228 modes
[2] = " srst_gates_jtag";
1230 if (new_cfg
& RESET_SRST_PUSH_PULL
)
1231 modes
[4] = " srst_push_pull";
1233 modes
[4] = " srst_open_drain";
1239 command_print(CMD_CTX
, "%s %s%s%s%s",
1241 modes
[2], modes
[3], modes
[4]);
1246 COMMAND_HANDLER(handle_jtag_nsrst_delay_command
)
1249 return ERROR_COMMAND_SYNTAX_ERROR
;
1253 COMMAND_PARSE_NUMBER(uint
, CMD_ARGV
[0], delay
);
1255 jtag_set_nsrst_delay(delay
);
1257 command_print(CMD_CTX
, "jtag_nsrst_delay: %u", jtag_get_nsrst_delay());
1261 COMMAND_HANDLER(handle_jtag_ntrst_delay_command
)
1264 return ERROR_COMMAND_SYNTAX_ERROR
;
1268 COMMAND_PARSE_NUMBER(uint
, CMD_ARGV
[0], delay
);
1270 jtag_set_ntrst_delay(delay
);
1272 command_print(CMD_CTX
, "jtag_ntrst_delay: %u", jtag_get_ntrst_delay());
1276 COMMAND_HANDLER(handle_jtag_nsrst_assert_width_command
)
1279 return ERROR_COMMAND_SYNTAX_ERROR
;
1283 COMMAND_PARSE_NUMBER(uint
, CMD_ARGV
[0], delay
);
1285 jtag_set_nsrst_assert_width(delay
);
1287 command_print(CMD_CTX
, "jtag_nsrst_assert_width: %u", jtag_get_nsrst_assert_width());
1291 COMMAND_HANDLER(handle_jtag_ntrst_assert_width_command
)
1294 return ERROR_COMMAND_SYNTAX_ERROR
;
1298 COMMAND_PARSE_NUMBER(uint
, CMD_ARGV
[0], delay
);
1300 jtag_set_ntrst_assert_width(delay
);
1302 command_print(CMD_CTX
, "jtag_ntrst_assert_width: %u", jtag_get_ntrst_assert_width());
1306 COMMAND_HANDLER(handle_jtag_khz_command
)
1309 return ERROR_COMMAND_SYNTAX_ERROR
;
1311 int retval
= ERROR_OK
;
1315 COMMAND_PARSE_NUMBER(uint
, CMD_ARGV
[0], khz
);
1317 retval
= jtag_config_khz(khz
);
1318 if (ERROR_OK
!= retval
)
1322 int cur_speed
= jtag_get_speed_khz();
1323 retval
= jtag_get_speed_readable(&cur_speed
);
1324 if (ERROR_OK
!= retval
)
1328 command_print(CMD_CTX
, "%d kHz", cur_speed
);
1330 command_print(CMD_CTX
, "RCLK - adaptive");
1335 COMMAND_HANDLER(handle_jtag_rclk_command
)
1338 return ERROR_COMMAND_SYNTAX_ERROR
;
1340 int retval
= ERROR_OK
;
1344 COMMAND_PARSE_NUMBER(uint
, CMD_ARGV
[0], khz
);
1346 retval
= jtag_config_rclk(khz
);
1347 if (ERROR_OK
!= retval
)
1351 int cur_khz
= jtag_get_speed_khz();
1352 retval
= jtag_get_speed_readable(&cur_khz
);
1353 if (ERROR_OK
!= retval
)
1357 command_print(CMD_CTX
, "RCLK not supported - fallback to %d kHz", cur_khz
);
1359 command_print(CMD_CTX
, "RCLK - adaptive");
1364 COMMAND_HANDLER(handle_jtag_reset_command
)
1367 return ERROR_COMMAND_SYNTAX_ERROR
;
1370 if (CMD_ARGV
[0][0] == '1')
1372 else if (CMD_ARGV
[0][0] == '0')
1375 return ERROR_COMMAND_SYNTAX_ERROR
;
1378 if (CMD_ARGV
[1][0] == '1')
1380 else if (CMD_ARGV
[1][0] == '0')
1383 return ERROR_COMMAND_SYNTAX_ERROR
;
1385 if (jtag_interface_init(CMD_CTX
) != ERROR_OK
)
1386 return ERROR_JTAG_INIT_FAILED
;
1388 jtag_add_reset(trst
, srst
);
1389 return jtag_execute_queue();
1392 COMMAND_HANDLER(handle_runtest_command
)
1395 return ERROR_COMMAND_SYNTAX_ERROR
;
1397 unsigned num_clocks
;
1398 COMMAND_PARSE_NUMBER(uint
, CMD_ARGV
[0], num_clocks
);
1400 jtag_add_runtest(num_clocks
, TAP_IDLE
);
1401 return jtag_execute_queue();
1405 * For "irscan" or "drscan" commands, the "end" (really, "next") state
1406 * should be stable ... and *NOT* a shift state, otherwise free-running
1407 * jtag clocks could change the values latched by the update state.
1408 * Not surprisingly, this is the same constraint as SVF; the "irscan"
1409 * and "drscan" commands are a write-only subset of what SVF provides.
1412 COMMAND_HANDLER(handle_irscan_command
)
1415 struct scan_field
*fields
;
1416 struct jtag_tap
*tap
;
1417 tap_state_t endstate
;
1419 if ((CMD_ARGC
< 2) || (CMD_ARGC
% 2))
1421 return ERROR_COMMAND_SYNTAX_ERROR
;
1424 /* optional "-endstate" "statename" at the end of the arguments,
1425 * so that e.g. IRPAUSE can let us load the data register before
1426 * entering RUN/IDLE to execute the instruction we load here.
1428 endstate
= TAP_IDLE
;
1430 if (CMD_ARGC
>= 4) {
1431 /* have at least one pair of numbers. */
1432 /* is last pair the magic text? */
1433 if (strcmp("-endstate", CMD_ARGV
[CMD_ARGC
- 2]) == 0) {
1434 endstate
= tap_state_by_name(CMD_ARGV
[CMD_ARGC
- 1]);
1435 if (endstate
== TAP_INVALID
)
1436 return ERROR_COMMAND_SYNTAX_ERROR
;
1437 if (!scan_is_safe(endstate
))
1438 LOG_WARNING("unstable irscan endstate \"%s\"",
1439 CMD_ARGV
[CMD_ARGC
- 1]);
1444 int num_fields
= CMD_ARGC
/ 2;
1445 size_t fields_len
= sizeof(struct scan_field
) * num_fields
;
1446 fields
= malloc(fields_len
);
1447 memset(fields
, 0, fields_len
);
1450 for (i
= 0; i
< num_fields
; i
++)
1452 tap
= jtag_tap_by_string(CMD_ARGV
[i
*2]);
1456 for (j
= 0; j
< i
; j
++)
1457 free(fields
[j
].out_value
);
1459 command_print(CMD_CTX
, "Tap: %s unknown", CMD_ARGV
[i
*2]);
1463 int field_size
= tap
->ir_length
;
1464 fields
[i
].tap
= tap
;
1465 fields
[i
].num_bits
= field_size
;
1466 fields
[i
].out_value
= malloc(DIV_ROUND_UP(field_size
, 8));
1469 retval
= parse_u32(CMD_ARGV
[i
* 2 + 1], &value
);
1470 if (ERROR_OK
!= retval
)
1472 buf_set_u32(fields
[i
].out_value
, 0, field_size
, value
);
1473 fields
[i
].in_value
= NULL
;
1476 /* did we have an endstate? */
1477 jtag_add_ir_scan(num_fields
, fields
, endstate
);
1479 retval
= jtag_execute_queue();
1482 for (i
= 0; i
< num_fields
; i
++)
1484 if (NULL
!= fields
[i
].out_value
)
1485 free(fields
[i
].out_value
);
1494 COMMAND_HANDLER(handle_verify_ircapture_command
)
1497 return ERROR_COMMAND_SYNTAX_ERROR
;
1502 COMMAND_PARSE_ENABLE(CMD_ARGV
[0], enable
);
1503 jtag_set_verify_capture_ir(enable
);
1506 const char *status
= jtag_will_verify_capture_ir() ? "enabled": "disabled";
1507 command_print(CMD_CTX
, "verify Capture-IR is %s", status
);
1512 COMMAND_HANDLER(handle_verify_jtag_command
)
1515 return ERROR_COMMAND_SYNTAX_ERROR
;
1520 COMMAND_PARSE_ENABLE(CMD_ARGV
[0], enable
);
1521 jtag_set_verify(enable
);
1524 const char *status
= jtag_will_verify() ? "enabled": "disabled";
1525 command_print(CMD_CTX
, "verify jtag capture is %s", status
);
1530 COMMAND_HANDLER(handle_tms_sequence_command
)
1533 return ERROR_COMMAND_SYNTAX_ERROR
;
1538 if (strcmp(CMD_ARGV
[0], "short") == 0)
1539 use_new_table
= true;
1540 else if (strcmp(CMD_ARGV
[0], "long") == 0)
1541 use_new_table
= false;
1543 return ERROR_COMMAND_SYNTAX_ERROR
;
1545 tap_use_new_tms_table(use_new_table
);
1548 command_print(CMD_CTX
, "tms sequence is %s",
1549 tap_uses_new_tms_table() ? "short": "long");
1554 static const struct command_registration jtag_command_handlers
[] = {
1556 .name
= "interface",
1557 .handler
= &handle_interface_command
,
1558 .mode
= COMMAND_CONFIG
,
1559 .help
= "select a JTAG interface",
1560 .usage
= "<driver_name>",
1563 .name
= "interface_list",
1564 .handler
= &handle_interface_list_command
,
1565 .mode
= COMMAND_ANY
,
1566 .help
= "list all built-in interfaces",
1570 .handler
= &handle_jtag_khz_command
,
1571 .mode
= COMMAND_ANY
,
1572 .help
= "set maximum jtag speed (if supported)",
1573 .usage
= "<khz:0=rtck>",
1576 .name
= "jtag_rclk",
1577 .handler
= &handle_jtag_rclk_command
,
1578 .mode
= COMMAND_ANY
,
1579 .help
= "set JTAG speed to RCLK or use fallback speed",
1580 .usage
= "<fallback_speed_khz>",
1583 .name
= "reset_config",
1584 .handler
= &handle_reset_config_command
,
1585 .mode
= COMMAND_ANY
,
1586 .help
= "configure JTAG reset behavior",
1587 .usage
= "[none|trst_only|srst_only|trst_and_srst] "
1588 "[srst_pulls_trst|trst_pulls_srst|combined|separate] "
1589 "[srst_gates_jtag|srst_nogate] "
1590 "[trst_push_pull|trst_open_drain] "
1591 "[srst_push_pull|srst_open_drain]",
1594 .name
= "jtag_nsrst_delay",
1595 .handler
= &handle_jtag_nsrst_delay_command
,
1596 .mode
= COMMAND_ANY
,
1597 .help
= "delay after deasserting srst in ms",
1601 .name
= "jtag_ntrst_delay",
1602 .handler
= &handle_jtag_ntrst_delay_command
,
1603 .mode
= COMMAND_ANY
,
1604 .help
= "delay after deasserting trst in ms",
1608 .name
= "jtag_nsrst_assert_width",
1609 .handler
= &handle_jtag_nsrst_assert_width_command
,
1610 .mode
= COMMAND_ANY
,
1611 .help
= "delay after asserting srst in ms",
1615 .name
= "jtag_ntrst_assert_width",
1616 .handler
= &handle_jtag_ntrst_assert_width_command
,
1617 .mode
= COMMAND_ANY
,
1618 .help
= "delay after asserting trst in ms",
1622 .name
= "scan_chain",
1623 .handler
= &handle_scan_chain_command
,
1624 .mode
= COMMAND_EXEC
,
1625 .help
= "print current scan chain configuration",
1628 .name
= "jtag_reset",
1629 .handler
= &handle_jtag_reset_command
,
1630 .mode
= COMMAND_EXEC
,
1631 .help
= "toggle reset lines",
1632 .usage
= "<trst> <srst>",
1636 .handler
= &handle_runtest_command
,
1637 .mode
= COMMAND_EXEC
,
1638 .help
= "move to Run-Test/Idle, and execute <num_cycles>",
1639 .usage
= "<num_cycles>"
1643 .handler
= &handle_irscan_command
,
1644 .mode
= COMMAND_EXEC
,
1645 .help
= "execute IR scan",
1646 .usage
= "<device> <instr> [dev2] [instr2] ...",
1649 .name
= "verify_ircapture",
1650 .handler
= &handle_verify_ircapture_command
,
1651 .mode
= COMMAND_ANY
,
1652 .help
= "verify value captured during Capture-IR",
1653 .usage
= "<enable | disable>",
1656 .name
= "verify_jtag",
1657 .handler
= &handle_verify_jtag_command
,
1658 .mode
= COMMAND_ANY
,
1659 .help
= "verify value capture",
1660 .usage
= "<enable | disable>",
1663 .name
= "tms_sequence",
1664 .handler
= &handle_tms_sequence_command
,
1665 .mode
= COMMAND_ANY
,
1666 .help
= "choose short(default) or long tms_sequence",
1667 .usage
= "<short | long>",
1671 .mode
= COMMAND_ANY
,
1672 .help
= "perform jtag tap actions",
1674 .chain
= jtag_subcommand_handlers
,
1677 .chain
= jtag_command_handlers_to_move
,
1679 COMMAND_REGISTRATION_DONE
1681 int jtag_register_commands(struct command_context
*cmd_ctx
)
1683 return register_commands(cmd_ctx
, NULL
, jtag_command_handlers
);
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)