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 static bool scan_is_safe(tap_state_t state
)
68 static int Jim_Command_drscan(Jim_Interp
*interp
, int argc
, Jim_Obj
*const *args
)
71 struct scan_field
*fields
;
80 * args[3] = hex string
81 * ... repeat num bits and hex string ...
84 * args[N-2] = "-endstate"
85 * args[N-1] = statename
87 if ((argc
< 4) || ((argc
% 2) != 0))
89 Jim_WrongNumArgs(interp
, 1, args
, "wrong arguments");
95 script_debug(interp
, "drscan", argc
, args
);
97 /* validate arguments as numbers */
99 for (i
= 2; i
< argc
; i
+= 2)
104 e
= Jim_GetLong(interp
, args
[i
], &bits
);
105 /* If valid - try next arg */
110 /* Not valid.. are we at the end? */
111 if (((i
+ 2) != argc
)) {
112 /* nope, then error */
116 /* it could be: "-endstate FOO"
117 * e.g. DRPAUSE so we can issue more instructions
118 * before entering RUN/IDLE and executing them.
121 /* get arg as a string. */
122 cp
= Jim_GetString(args
[i
], NULL
);
123 /* is it the magic? */
124 if (0 == strcmp("-endstate", cp
)) {
125 /* is the statename valid? */
126 cp
= Jim_GetString(args
[i
+ 1], NULL
);
128 /* see if it is a valid state name */
129 endstate
= tap_state_by_name(cp
);
131 /* update the error message */
132 Jim_SetResult_sprintf(interp
,"endstate: %s invalid", cp
);
134 if (!scan_is_safe(endstate
))
135 LOG_WARNING("drscan with unsafe "
136 "endstate \"%s\"", cp
);
138 /* valid - so clear the error */
140 /* and remove the last 2 args */
145 /* Still an error? */
147 return e
; /* too bad */
149 } /* validate args */
151 tap
= jtag_tap_by_jim_obj(interp
, args
[1]);
156 num_fields
= (argc
-2)/2;
157 fields
= malloc(sizeof(struct scan_field
) * num_fields
);
158 for (i
= 2; i
< argc
; i
+= 2)
164 Jim_GetLong(interp
, args
[i
], &bits
);
165 str
= Jim_GetString(args
[i
+ 1], &len
);
167 fields
[field_count
].tap
= tap
;
168 fields
[field_count
].num_bits
= bits
;
169 fields
[field_count
].out_value
= malloc(DIV_ROUND_UP(bits
, 8));
170 str_to_buf(str
, len
, fields
[field_count
].out_value
, bits
, 0);
171 fields
[field_count
].in_value
= fields
[field_count
].out_value
;
175 jtag_add_dr_scan(num_fields
, fields
, endstate
);
177 retval
= jtag_execute_queue();
178 if (retval
!= ERROR_OK
)
180 Jim_SetResultString(interp
, "drscan: jtag execute failed",-1);
185 Jim_Obj
*list
= Jim_NewListObj(interp
, NULL
, 0);
186 for (i
= 2; i
< argc
; i
+= 2)
191 Jim_GetLong(interp
, args
[i
], &bits
);
192 str
= buf_to_str(fields
[field_count
].in_value
, bits
, 16);
193 free(fields
[field_count
].out_value
);
195 Jim_ListAppendElement(interp
, list
, Jim_NewStringObj(interp
, str
, strlen(str
)));
200 Jim_SetResult(interp
, list
);
208 static int Jim_Command_pathmove(Jim_Interp
*interp
, int argc
, Jim_Obj
*const *args
)
210 tap_state_t states
[8];
212 if ((argc
< 2) || ((size_t)argc
> (ARRAY_SIZE(states
) + 1)))
214 Jim_WrongNumArgs(interp
, 1, args
, "wrong arguments");
218 script_debug(interp
, "pathmove", argc
, args
);
221 for (i
= 0; i
< argc
-1; i
++)
224 cp
= Jim_GetString(args
[i
+ 1], NULL
);
225 states
[i
] = tap_state_by_name(cp
);
228 /* update the error message */
229 Jim_SetResult_sprintf(interp
,"endstate: %s invalid", cp
);
234 if ((jtag_add_statemove(states
[0]) != ERROR_OK
) || (jtag_execute_queue()!= ERROR_OK
))
236 Jim_SetResultString(interp
, "pathmove: jtag execute failed",-1);
240 jtag_add_pathmove(argc
-2, states
+ 1);
242 if (jtag_execute_queue()!= ERROR_OK
)
244 Jim_SetResultString(interp
, "pathmove: failed",-1);
252 static int Jim_Command_flush_count(Jim_Interp
*interp
, int argc
, Jim_Obj
*const *args
)
254 script_debug(interp
, "flush_count", argc
, args
);
256 Jim_SetResult(interp
, Jim_NewIntObj(interp
, jtag_get_flush_queue_count()));
261 static const struct command_registration jtag_command_handlers_to_move
[] = {
264 .mode
= COMMAND_EXEC
,
265 .jim_handler
= &Jim_Command_drscan
,
266 .help
= "execute DR scan <device> "
267 "<num_bits> <value> <num_bits1> <value2> ...",
270 .name
= "flush_count",
271 .mode
= COMMAND_EXEC
,
272 .jim_handler
= &Jim_Command_flush_count
,
273 .help
= "returns number of times the JTAG queue has been flushed",
277 .mode
= COMMAND_EXEC
,
278 .jim_handler
= &Jim_Command_pathmove
,
279 .usage
= "<state1>,<state2>,<state3>... ",
280 .help
= "move JTAG to state1 then to state2, state3, etc.",
282 COMMAND_REGISTRATION_DONE
286 enum jtag_tap_cfg_param
{
290 static Jim_Nvp nvp_config_opts
[] = {
291 { .name
= "-event", .value
= JCFG_EVENT
},
293 { .name
= NULL
, .value
= -1 }
296 static int jtag_tap_configure_event(Jim_GetOptInfo
*goi
, struct jtag_tap
* tap
)
300 Jim_WrongNumArgs(goi
->interp
, goi
->argc
, goi
->argv
, "-event <event-name> ...");
305 int e
= Jim_GetOpt_Nvp(goi
, nvp_jtag_tap_event
, &n
);
308 Jim_GetOpt_NvpUnknown(goi
, nvp_jtag_tap_event
, 1);
312 if (goi
->isconfigure
) {
313 if (goi
->argc
!= 1) {
314 Jim_WrongNumArgs(goi
->interp
, goi
->argc
, goi
->argv
, "-event <event-name> <event-body>");
318 if (goi
->argc
!= 0) {
319 Jim_WrongNumArgs(goi
->interp
, goi
->argc
, goi
->argv
, "-event <event-name>");
324 struct jtag_tap_event_action
*jteap
= tap
->event_action
;
325 /* replace existing event body */
329 if (jteap
->event
== (enum jtag_event
)n
->value
)
337 Jim_SetEmptyResult(goi
->interp
);
339 if (goi
->isconfigure
)
342 jteap
= calloc(1, sizeof(*jteap
));
343 else if (NULL
!= jteap
->body
)
344 Jim_DecrRefCount(goi
->interp
, jteap
->body
);
346 jteap
->interp
= goi
->interp
;
347 jteap
->event
= n
->value
;
350 Jim_GetOpt_Obj(goi
, &o
);
351 jteap
->body
= Jim_DuplicateObj(goi
->interp
, o
);
352 Jim_IncrRefCount(jteap
->body
);
356 /* add to head of event list */
357 jteap
->next
= tap
->event_action
;
358 tap
->event_action
= jteap
;
363 jteap
->interp
= goi
->interp
;
364 Jim_SetResult(goi
->interp
,
365 Jim_DuplicateObj(goi
->interp
, jteap
->body
));
370 static int jtag_tap_configure_cmd(Jim_GetOptInfo
*goi
, struct jtag_tap
* tap
)
372 /* parse config or cget options */
373 while (goi
->argc
> 0)
375 Jim_SetEmptyResult (goi
->interp
);
378 int e
= Jim_GetOpt_Nvp(goi
, nvp_config_opts
, &n
);
381 Jim_GetOpt_NvpUnknown(goi
, nvp_config_opts
, 0);
388 e
= jtag_tap_configure_event(goi
, tap
);
393 Jim_SetResult_sprintf(goi
->interp
, "unknown event: %s", n
->name
);
401 static int is_bad_irval(int ir_length
, jim_wide w
)
411 static int jim_newtap_expected_id(Jim_Nvp
*n
, Jim_GetOptInfo
*goi
,
412 struct jtag_tap
*pTap
)
415 int e
= Jim_GetOpt_Wide(goi
, &w
);
417 Jim_SetResult_sprintf(goi
->interp
, "option: %s bad parameter", n
->name
);
421 unsigned expected_len
= sizeof(uint32_t) * pTap
->expected_ids_cnt
;
422 uint32_t *new_expected_ids
= malloc(expected_len
+ sizeof(uint32_t));
423 if (new_expected_ids
== NULL
)
425 Jim_SetResult_sprintf(goi
->interp
, "no memory");
429 memcpy(new_expected_ids
, pTap
->expected_ids
, expected_len
);
431 new_expected_ids
[pTap
->expected_ids_cnt
] = w
;
433 free(pTap
->expected_ids
);
434 pTap
->expected_ids
= new_expected_ids
;
435 pTap
->expected_ids_cnt
++;
440 #define NTAP_OPT_IRLEN 0
441 #define NTAP_OPT_IRMASK 1
442 #define NTAP_OPT_IRCAPTURE 2
443 #define NTAP_OPT_ENABLED 3
444 #define NTAP_OPT_DISABLED 4
445 #define NTAP_OPT_EXPECTED_ID 5
447 static int jim_newtap_ir_param(Jim_Nvp
*n
, Jim_GetOptInfo
*goi
,
448 struct jtag_tap
*pTap
)
451 int e
= Jim_GetOpt_Wide(goi
, &w
);
454 Jim_SetResult_sprintf(goi
->interp
,
455 "option: %s bad parameter", n
->name
);
456 free((void *)pTap
->dotted_name
);
461 if (w
> (jim_wide
) (8 * sizeof(pTap
->ir_capture_value
)))
463 LOG_WARNING("%s: huge IR length %d",
464 pTap
->dotted_name
, (int) w
);
468 case NTAP_OPT_IRMASK
:
469 if (is_bad_irval(pTap
->ir_length
, w
))
471 LOG_ERROR("%s: IR mask %x too big",
477 LOG_WARNING("%s: nonstandard IR mask", pTap
->dotted_name
);
478 pTap
->ir_capture_mask
= w
;
480 case NTAP_OPT_IRCAPTURE
:
481 if (is_bad_irval(pTap
->ir_length
, w
))
483 LOG_ERROR("%s: IR capture %x too big",
484 pTap
->dotted_name
, (int) w
);
488 LOG_WARNING("%s: nonstandard IR value",
490 pTap
->ir_capture_value
= w
;
498 static int jim_newtap_cmd(Jim_GetOptInfo
*goi
)
500 struct jtag_tap
*pTap
;
505 const Jim_Nvp opts
[] = {
506 { .name
= "-irlen" , .value
= NTAP_OPT_IRLEN
},
507 { .name
= "-irmask" , .value
= NTAP_OPT_IRMASK
},
508 { .name
= "-ircapture" , .value
= NTAP_OPT_IRCAPTURE
},
509 { .name
= "-enable" , .value
= NTAP_OPT_ENABLED
},
510 { .name
= "-disable" , .value
= NTAP_OPT_DISABLED
},
511 { .name
= "-expected-id" , .value
= NTAP_OPT_EXPECTED_ID
},
512 { .name
= NULL
, .value
= -1 },
515 pTap
= calloc(1, sizeof(struct jtag_tap
));
517 Jim_SetResult_sprintf(goi
->interp
, "no memory");
522 * we expect CHIP + TAP + OPTIONS
525 Jim_SetResult_sprintf(goi
->interp
, "Missing CHIP TAP OPTIONS ....");
529 Jim_GetOpt_String(goi
, &cp
, NULL
);
530 pTap
->chip
= strdup(cp
);
532 Jim_GetOpt_String(goi
, &cp
, NULL
);
533 pTap
->tapname
= strdup(cp
);
535 /* name + dot + name + null */
536 x
= strlen(pTap
->chip
) + 1 + strlen(pTap
->tapname
) + 1;
538 sprintf(cp
, "%s.%s", pTap
->chip
, pTap
->tapname
);
539 pTap
->dotted_name
= cp
;
541 LOG_DEBUG("Creating New Tap, Chip: %s, Tap: %s, Dotted: %s, %d params",
542 pTap
->chip
, pTap
->tapname
, pTap
->dotted_name
, goi
->argc
);
544 /* IEEE specifies that the two LSBs of an IR scan are 01, so make
545 * that the default. The "-irlen" and "-irmask" options are only
546 * needed to cope with nonstandard TAPs, or to specify more bits.
548 pTap
->ir_capture_mask
= 0x03;
549 pTap
->ir_capture_value
= 0x01;
552 e
= Jim_GetOpt_Nvp(goi
, opts
, &n
);
554 Jim_GetOpt_NvpUnknown(goi
, opts
, 0);
555 free((void *)pTap
->dotted_name
);
559 LOG_DEBUG("Processing option: %s", n
->name
);
561 case NTAP_OPT_ENABLED
:
562 pTap
->disabled_after_reset
= false;
564 case NTAP_OPT_DISABLED
:
565 pTap
->disabled_after_reset
= true;
567 case NTAP_OPT_EXPECTED_ID
:
568 e
= jim_newtap_expected_id(n
, goi
, pTap
);
571 free((void *)pTap
->dotted_name
);
577 case NTAP_OPT_IRMASK
:
578 case NTAP_OPT_IRCAPTURE
:
579 e
= jim_newtap_ir_param(n
, goi
, pTap
);
582 free((void *)pTap
->dotted_name
);
587 } /* switch (n->value) */
588 } /* while (goi->argc) */
590 /* default is enabled-after-reset */
591 pTap
->enabled
= !pTap
->disabled_after_reset
;
593 /* Did all the required option bits get cleared? */
594 if (pTap
->ir_length
!= 0)
600 Jim_SetResult_sprintf(goi
->interp
,
601 "newtap: %s missing IR length",
607 static void jtag_tap_handle_event(struct jtag_tap
*tap
, enum jtag_event e
)
609 struct jtag_tap_event_action
* jteap
;
611 for (jteap
= tap
->event_action
; jteap
!= NULL
; jteap
= jteap
->next
)
613 if (jteap
->event
!= e
)
616 Jim_Nvp
*nvp
= Jim_Nvp_value2name_simple(nvp_jtag_tap_event
, e
);
617 LOG_DEBUG("JTAG tap: %s event: %d (%s)\n\taction: %s",
618 tap
->dotted_name
, e
, nvp
->name
,
619 Jim_GetString(jteap
->body
, NULL
));
621 if (Jim_EvalObj(jteap
->interp
, jteap
->body
) != JIM_OK
)
623 Jim_PrintErrorMessage(jteap
->interp
);
629 case JTAG_TAP_EVENT_ENABLE
:
630 case JTAG_TAP_EVENT_DISABLE
:
631 /* NOTE: we currently assume the handlers
632 * can't fail. Right here is where we should
633 * really be verifying the scan chains ...
635 tap
->enabled
= (e
== JTAG_TAP_EVENT_ENABLE
);
636 LOG_INFO("JTAG tap: %s %s", tap
->dotted_name
,
637 tap
->enabled
? "enabled" : "disabled");
645 static int jim_jtag_interface(Jim_Interp
*interp
, int argc
, Jim_Obj
*const *argv
)
648 Jim_GetOpt_Setup(&goi
, interp
, argc
-1, argv
+ 1);
650 /* return the name of the interface */
651 /* TCL code might need to know the exact type... */
652 /* FUTURE: we allow this as a means to "set" the interface. */
654 Jim_WrongNumArgs(goi
.interp
, 1, goi
.argv
-1, "(no params)");
657 const char *name
= jtag_interface
? jtag_interface
->name
: NULL
;
658 Jim_SetResultString(goi
.interp
, name
? : "undefined", -1);
662 static int jim_jtag_arp_init(Jim_Interp
*interp
, int argc
, Jim_Obj
*const *argv
)
665 Jim_GetOpt_Setup(&goi
, interp
, argc
-1, argv
+ 1);
667 Jim_WrongNumArgs(goi
.interp
, 1, goi
.argv
-1, "(no params)");
670 struct command_context
*context
= Jim_GetAssocData(interp
, "context");
671 int e
= jtag_init_inner(context
);
673 Jim_SetResult_sprintf(goi
.interp
, "error: %d", e
);
679 static int jim_jtag_arp_init_reset(Jim_Interp
*interp
, int argc
, Jim_Obj
*const *argv
)
682 Jim_GetOpt_Setup(&goi
, interp
, argc
-1, argv
+ 1);
684 Jim_WrongNumArgs(goi
.interp
, 1, goi
.argv
-1, "(no params)");
687 struct command_context
*context
= Jim_GetAssocData(interp
, "context");
688 int e
= jtag_init_reset(context
);
690 Jim_SetResult_sprintf(goi
.interp
, "error: %d", e
);
696 static int jim_jtag_newtap(Jim_Interp
*interp
, int argc
, Jim_Obj
*const *argv
)
699 Jim_GetOpt_Setup(&goi
, interp
, argc
-1, argv
+ 1);
700 return jim_newtap_cmd(&goi
);
703 static bool jtag_tap_enable(struct jtag_tap
*t
)
707 jtag_tap_handle_event(t
, JTAG_TAP_EVENT_ENABLE
);
711 /* FIXME add JTAG sanity checks, w/o TLR
712 * - scan chain length grew by one (this)
713 * - IDs and IR lengths are as expected
715 jtag_call_event_callbacks(JTAG_TAP_EVENT_ENABLE
);
718 static bool jtag_tap_disable(struct jtag_tap
*t
)
722 jtag_tap_handle_event(t
, JTAG_TAP_EVENT_DISABLE
);
726 /* FIXME add JTAG sanity checks, w/o TLR
727 * - scan chain length shrank by one (this)
728 * - IDs and IR lengths are as expected
730 jtag_call_event_callbacks(JTAG_TAP_EVENT_DISABLE
);
734 static int jim_jtag_tap_enabler(Jim_Interp
*interp
, int argc
, Jim_Obj
*const *argv
)
736 const char *cmd_name
= Jim_GetString(argv
[0], NULL
);
738 Jim_GetOpt_Setup(&goi
, interp
, argc
-1, argv
+ 1);
740 Jim_SetResult_sprintf(goi
.interp
, "usage: %s <name>", cmd_name
);
746 t
= jtag_tap_by_jim_obj(goi
.interp
, goi
.argv
[0]);
750 if (strcasecmp(cmd_name
, "tapisenabled") == 0) {
751 // do nothing, just return the value
752 } else if (strcasecmp(cmd_name
, "tapenable") == 0) {
753 if (!jtag_tap_enable(t
))
754 LOG_WARNING("failed to disable tap");
755 } else if (strcasecmp(cmd_name
, "tapdisable") == 0) {
756 if (!jtag_tap_disable(t
))
757 LOG_WARNING("failed to disable tap");
759 LOG_ERROR("command '%s' unknown", cmd_name
);
763 Jim_SetResult(goi
.interp
, Jim_NewIntObj(goi
.interp
, e
));
767 static int jim_jtag_configure(Jim_Interp
*interp
, int argc
, Jim_Obj
*const *argv
)
769 const char *cmd_name
= Jim_GetString(argv
[0], NULL
);
771 Jim_GetOpt_Setup(&goi
, interp
, argc
-1, argv
+ 1);
772 goi
.isconfigure
= !strcmp(cmd_name
, "configure");
773 if (goi
.argc
< 2 + goi
.isconfigure
) {
774 Jim_WrongNumArgs(goi
.interp
, 0, NULL
,
775 "<tap_name> <attribute> ...");
782 Jim_GetOpt_Obj(&goi
, &o
);
783 t
= jtag_tap_by_jim_obj(goi
.interp
, o
);
788 return jtag_tap_configure_cmd(&goi
, t
);
791 static int jim_jtag_names(Jim_Interp
*interp
, int argc
, Jim_Obj
*const *argv
)
794 Jim_GetOpt_Setup(&goi
, interp
, argc
-1, argv
+ 1);
796 Jim_WrongNumArgs(goi
.interp
, 1, goi
.argv
, "Too many parameters");
799 Jim_SetResult(goi
.interp
, Jim_NewListObj(goi
.interp
, NULL
, 0));
800 struct jtag_tap
*tap
;
802 for (tap
= jtag_all_taps(); tap
; tap
= tap
->next_tap
) {
803 Jim_ListAppendElement(goi
.interp
,
804 Jim_GetResult(goi
.interp
),
805 Jim_NewStringObj(goi
.interp
,
806 tap
->dotted_name
, -1));
811 static const struct command_registration jtag_subcommand_handlers
[] = {
815 .jim_handler
= &jim_jtag_interface
,
816 .help
= "Returns the selected interface",
821 .jim_handler
= &jim_jtag_arp_init
,
824 .name
= "arp_init-reset",
826 .jim_handler
= &jim_jtag_arp_init_reset
,
830 .mode
= COMMAND_CONFIG
,
831 .jim_handler
= &jim_jtag_newtap
,
832 .help
= "Create a new TAP instance",
833 .usage
= "<name> <type> -irlen <count> [-ircapture <count>] "
834 "[-irmask <count>] [-enable|-disable]",
837 .name
= "tapisenabled",
838 .mode
= COMMAND_EXEC
,
839 .jim_handler
= &jim_jtag_tap_enabler
,
840 .help
= "Returns a integer indicating TAP state (0/1)",
845 .mode
= COMMAND_EXEC
,
846 .jim_handler
= &jim_jtag_tap_enabler
,
847 .help
= "Enable the specified TAP",
851 .name
= "tapdisable",
852 .mode
= COMMAND_EXEC
,
853 .jim_handler
= &jim_jtag_tap_enabler
,
854 .help
= "Enable the specified TAP",
859 .mode
= COMMAND_EXEC
,
860 .jim_handler
= &jim_jtag_configure
,
861 .help
= "Enable the specified TAP",
862 .usage
= "<name> [<key> <value> ...]",
866 .mode
= COMMAND_EXEC
,
867 .jim_handler
= &jim_jtag_configure
,
868 .help
= "Enable the specified TAP",
869 .usage
= "<name> [<key> <value> ...]",
874 .jim_handler
= &jim_jtag_names
,
875 .help
= "Returns list of all JTAG tap names",
878 .chain
= jtag_command_handlers_to_move
,
880 COMMAND_REGISTRATION_DONE
883 void jtag_notify_event(enum jtag_event event
)
885 struct jtag_tap
*tap
;
887 for (tap
= jtag_all_taps(); tap
; tap
= tap
->next_tap
)
888 jtag_tap_handle_event(tap
, event
);
892 static int default_khz(int khz
, int *jtag_speed
)
894 LOG_ERROR("Translation from khz to jtag_speed not implemented");
898 static int default_speed_div(int speed
, int *khz
)
900 LOG_ERROR("Translation from jtag_speed to khz not implemented");
904 static int default_power_dropout(int *dropout
)
906 *dropout
= 0; /* by default we can't detect power dropout */
910 static int default_srst_asserted(int *srst_asserted
)
912 *srst_asserted
= 0; /* by default we can't detect srst asserted */
916 COMMAND_HANDLER(handle_interface_list_command
)
918 if (strcmp(CMD_NAME
, "interface_list") == 0 && CMD_ARGC
> 0)
919 return ERROR_COMMAND_SYNTAX_ERROR
;
921 command_print(CMD_CTX
, "The following JTAG interfaces are available:");
922 for (unsigned i
= 0; NULL
!= jtag_interfaces
[i
]; i
++)
924 const char *name
= jtag_interfaces
[i
]->name
;
925 command_print(CMD_CTX
, "%u: %s", i
+ 1, name
);
931 COMMAND_HANDLER(handle_interface_command
)
933 /* check whether the interface is already configured */
936 LOG_WARNING("Interface already configured, ignoring");
940 /* interface name is a mandatory argument */
941 if (CMD_ARGC
!= 1 || CMD_ARGV
[0][0] == '\0')
942 return ERROR_COMMAND_SYNTAX_ERROR
;
944 for (unsigned i
= 0; NULL
!= jtag_interfaces
[i
]; i
++)
946 if (strcmp(CMD_ARGV
[0], jtag_interfaces
[i
]->name
) != 0)
949 if (NULL
!= jtag_interfaces
[i
]->commands
)
951 int retval
= register_commands(CMD_CTX
, NULL
,
952 jtag_interfaces
[i
]->commands
);
953 if (ERROR_OK
!= retval
)
957 jtag_interface
= jtag_interfaces
[i
];
959 if (jtag_interface
->khz
== NULL
)
960 jtag_interface
->khz
= default_khz
;
961 if (jtag_interface
->speed_div
== NULL
)
962 jtag_interface
->speed_div
= default_speed_div
;
963 if (jtag_interface
->power_dropout
== NULL
)
964 jtag_interface
->power_dropout
= default_power_dropout
;
965 if (jtag_interface
->srst_asserted
== NULL
)
966 jtag_interface
->srst_asserted
= default_srst_asserted
;
971 /* no valid interface was found (i.e. the configuration option,
972 * didn't match one of the compiled-in interfaces
974 LOG_ERROR("The specified JTAG interface was not found (%s)", CMD_ARGV
[0]);
975 CALL_COMMAND_HANDLER(handle_interface_list_command
);
976 return ERROR_JTAG_INVALID_INTERFACE
;
979 COMMAND_HANDLER(handle_scan_chain_command
)
981 struct jtag_tap
*tap
;
983 tap
= jtag_all_taps();
984 command_print(CMD_CTX
, " TapName | Enabled | IdCode Expected IrLen IrCap IrMask Instr ");
985 command_print(CMD_CTX
, "---|--------------------|---------|------------|------------|------|------|------|---------");
988 uint32_t expected
, expected_mask
, cur_instr
, ii
;
989 expected
= buf_get_u32(tap
->expected
, 0, tap
->ir_length
);
990 expected_mask
= buf_get_u32(tap
->expected_mask
, 0, tap
->ir_length
);
991 cur_instr
= buf_get_u32(tap
->cur_instr
, 0, tap
->ir_length
);
993 command_print(CMD_CTX
,
994 "%2d | %-18s | %c | 0x%08x | 0x%08x | 0x%02x | 0x%02x | 0x%02x | 0x%02x",
995 tap
->abs_chain_position
,
997 tap
->enabled
? 'Y' : 'n',
998 (unsigned int)(tap
->idcode
),
999 (unsigned int)(tap
->expected_ids_cnt
> 0 ? tap
->expected_ids
[0] : 0),
1000 (unsigned int)(tap
->ir_length
),
1001 (unsigned int)(expected
),
1002 (unsigned int)(expected_mask
),
1003 (unsigned int)(cur_instr
));
1005 for (ii
= 1; ii
< tap
->expected_ids_cnt
; ii
++) {
1006 command_print(CMD_CTX
, " | | | | 0x%08x | | | | ",
1007 (unsigned int)(tap
->expected_ids
[ii
]));
1010 tap
= tap
->next_tap
;
1016 COMMAND_HANDLER(handle_reset_config_command
)
1021 /* Original versions cared about the order of these tokens:
1022 * reset_config signals [combination [trst_type [srst_type]]]
1023 * They also clobbered the previous configuration even on error.
1025 * Here we don't care about the order, and only change values
1026 * which have been explicitly specified.
1028 for (; CMD_ARGC
; CMD_ARGC
--, CMD_ARGV
++) {
1033 m
= RESET_SRST_NO_GATING
;
1034 if (strcmp(*CMD_ARGV
, "srst_gates_jtag") == 0)
1035 /* default: don't use JTAG while SRST asserted */;
1036 else if (strcmp(*CMD_ARGV
, "srst_nogate") == 0)
1037 tmp
= RESET_SRST_NO_GATING
;
1041 LOG_ERROR("extra reset_config %s spec (%s)",
1042 "gating", *CMD_ARGV
);
1043 return ERROR_INVALID_ARGUMENTS
;
1049 m
= RESET_HAS_TRST
| RESET_HAS_SRST
;
1050 if (strcmp(*CMD_ARGV
, "none") == 0)
1052 else if (strcmp(*CMD_ARGV
, "trst_only") == 0)
1053 tmp
= RESET_HAS_TRST
;
1054 else if (strcmp(*CMD_ARGV
, "srst_only") == 0)
1055 tmp
= RESET_HAS_SRST
;
1056 else if (strcmp(*CMD_ARGV
, "trst_and_srst") == 0)
1057 tmp
= RESET_HAS_TRST
| RESET_HAS_SRST
;
1061 LOG_ERROR("extra reset_config %s spec (%s)",
1062 "signal", *CMD_ARGV
);
1063 return ERROR_INVALID_ARGUMENTS
;
1068 /* combination (options for broken wiring) */
1069 m
= RESET_SRST_PULLS_TRST
| RESET_TRST_PULLS_SRST
;
1070 if (strcmp(*CMD_ARGV
, "separate") == 0)
1071 /* separate reset lines - default */;
1072 else if (strcmp(*CMD_ARGV
, "srst_pulls_trst") == 0)
1073 tmp
|= RESET_SRST_PULLS_TRST
;
1074 else if (strcmp(*CMD_ARGV
, "trst_pulls_srst") == 0)
1075 tmp
|= RESET_TRST_PULLS_SRST
;
1076 else if (strcmp(*CMD_ARGV
, "combined") == 0)
1077 tmp
|= RESET_SRST_PULLS_TRST
| RESET_TRST_PULLS_SRST
;
1081 LOG_ERROR("extra reset_config %s spec (%s)",
1082 "combination", *CMD_ARGV
);
1083 return ERROR_INVALID_ARGUMENTS
;
1088 /* trst_type (NOP without HAS_TRST) */
1089 m
= RESET_TRST_OPEN_DRAIN
;
1090 if (strcmp(*CMD_ARGV
, "trst_open_drain") == 0)
1091 tmp
|= RESET_TRST_OPEN_DRAIN
;
1092 else if (strcmp(*CMD_ARGV
, "trst_push_pull") == 0)
1093 /* push/pull from adapter - default */;
1097 LOG_ERROR("extra reset_config %s spec (%s)",
1098 "trst_type", *CMD_ARGV
);
1099 return ERROR_INVALID_ARGUMENTS
;
1104 /* srst_type (NOP without HAS_SRST) */
1105 m
|= RESET_SRST_PUSH_PULL
;
1106 if (strcmp(*CMD_ARGV
, "srst_push_pull") == 0)
1107 tmp
|= RESET_SRST_PUSH_PULL
;
1108 else if (strcmp(*CMD_ARGV
, "srst_open_drain") == 0)
1109 /* open drain from adapter - default */;
1113 LOG_ERROR("extra reset_config %s spec (%s)",
1114 "srst_type", *CMD_ARGV
);
1115 return ERROR_INVALID_ARGUMENTS
;
1120 /* caller provided nonsense; fail */
1121 LOG_ERROR("unknown reset_config flag (%s)", *CMD_ARGV
);
1122 return ERROR_INVALID_ARGUMENTS
;
1125 /* Remember the bits which were specified (mask)
1126 * and their new values (new_cfg).
1132 /* clear previous values of those bits, save new values */
1134 int old_cfg
= jtag_get_reset_config();
1138 jtag_set_reset_config(new_cfg
);
1140 new_cfg
= jtag_get_reset_config();
1144 * Display the (now-)current reset mode
1148 /* minimal JTAG has neither SRST nor TRST (so that's the default) */
1149 switch (new_cfg
& (RESET_HAS_TRST
| RESET_HAS_SRST
)) {
1150 case RESET_HAS_SRST
:
1151 modes
[0] = "srst_only";
1153 case RESET_HAS_TRST
:
1154 modes
[0] = "trst_only";
1156 case RESET_TRST_AND_SRST
:
1157 modes
[0] = "trst_and_srst";
1164 /* normally SRST and TRST are decoupled; but bugs happen ... */
1165 switch (new_cfg
& (RESET_SRST_PULLS_TRST
| RESET_TRST_PULLS_SRST
)) {
1166 case RESET_SRST_PULLS_TRST
:
1167 modes
[1] = "srst_pulls_trst";
1169 case RESET_TRST_PULLS_SRST
:
1170 modes
[1] = "trst_pulls_srst";
1172 case RESET_SRST_PULLS_TRST
| RESET_TRST_PULLS_SRST
:
1173 modes
[1] = "combined";
1176 modes
[1] = "separate";
1180 /* TRST-less connectors include Altera, Xilinx, and minimal JTAG */
1181 if (new_cfg
& RESET_HAS_TRST
) {
1182 if (new_cfg
& RESET_TRST_OPEN_DRAIN
)
1183 modes
[3] = " trst_open_drain";
1185 modes
[3] = " trst_push_pull";
1189 /* SRST-less connectors include TI-14, Xilinx, and minimal JTAG */
1190 if (new_cfg
& RESET_HAS_SRST
) {
1191 if (new_cfg
& RESET_SRST_NO_GATING
)
1192 modes
[2] = " srst_nogate";
1194 modes
[2] = " srst_gates_jtag";
1196 if (new_cfg
& RESET_SRST_PUSH_PULL
)
1197 modes
[4] = " srst_push_pull";
1199 modes
[4] = " srst_open_drain";
1205 command_print(CMD_CTX
, "%s %s%s%s%s",
1207 modes
[2], modes
[3], modes
[4]);
1212 COMMAND_HANDLER(handle_jtag_nsrst_delay_command
)
1215 return ERROR_COMMAND_SYNTAX_ERROR
;
1219 COMMAND_PARSE_NUMBER(uint
, CMD_ARGV
[0], delay
);
1221 jtag_set_nsrst_delay(delay
);
1223 command_print(CMD_CTX
, "jtag_nsrst_delay: %u", jtag_get_nsrst_delay());
1227 COMMAND_HANDLER(handle_jtag_ntrst_delay_command
)
1230 return ERROR_COMMAND_SYNTAX_ERROR
;
1234 COMMAND_PARSE_NUMBER(uint
, CMD_ARGV
[0], delay
);
1236 jtag_set_ntrst_delay(delay
);
1238 command_print(CMD_CTX
, "jtag_ntrst_delay: %u", jtag_get_ntrst_delay());
1242 COMMAND_HANDLER(handle_jtag_nsrst_assert_width_command
)
1245 return ERROR_COMMAND_SYNTAX_ERROR
;
1249 COMMAND_PARSE_NUMBER(uint
, CMD_ARGV
[0], delay
);
1251 jtag_set_nsrst_assert_width(delay
);
1253 command_print(CMD_CTX
, "jtag_nsrst_assert_width: %u", jtag_get_nsrst_assert_width());
1257 COMMAND_HANDLER(handle_jtag_ntrst_assert_width_command
)
1260 return ERROR_COMMAND_SYNTAX_ERROR
;
1264 COMMAND_PARSE_NUMBER(uint
, CMD_ARGV
[0], delay
);
1266 jtag_set_ntrst_assert_width(delay
);
1268 command_print(CMD_CTX
, "jtag_ntrst_assert_width: %u", jtag_get_ntrst_assert_width());
1272 COMMAND_HANDLER(handle_jtag_khz_command
)
1275 return ERROR_COMMAND_SYNTAX_ERROR
;
1277 int retval
= ERROR_OK
;
1281 COMMAND_PARSE_NUMBER(uint
, CMD_ARGV
[0], khz
);
1283 retval
= jtag_config_khz(khz
);
1284 if (ERROR_OK
!= retval
)
1288 int cur_speed
= jtag_get_speed_khz();
1289 retval
= jtag_get_speed_readable(&cur_speed
);
1290 if (ERROR_OK
!= retval
)
1294 command_print(CMD_CTX
, "%d kHz", cur_speed
);
1296 command_print(CMD_CTX
, "RCLK - adaptive");
1301 COMMAND_HANDLER(handle_jtag_rclk_command
)
1304 return ERROR_COMMAND_SYNTAX_ERROR
;
1306 int retval
= ERROR_OK
;
1310 COMMAND_PARSE_NUMBER(uint
, CMD_ARGV
[0], khz
);
1312 retval
= jtag_config_rclk(khz
);
1313 if (ERROR_OK
!= retval
)
1317 int cur_khz
= jtag_get_speed_khz();
1318 retval
= jtag_get_speed_readable(&cur_khz
);
1319 if (ERROR_OK
!= retval
)
1323 command_print(CMD_CTX
, "RCLK not supported - fallback to %d kHz", cur_khz
);
1325 command_print(CMD_CTX
, "RCLK - adaptive");
1330 COMMAND_HANDLER(handle_jtag_reset_command
)
1333 return ERROR_COMMAND_SYNTAX_ERROR
;
1336 if (CMD_ARGV
[0][0] == '1')
1338 else if (CMD_ARGV
[0][0] == '0')
1341 return ERROR_COMMAND_SYNTAX_ERROR
;
1344 if (CMD_ARGV
[1][0] == '1')
1346 else if (CMD_ARGV
[1][0] == '0')
1349 return ERROR_COMMAND_SYNTAX_ERROR
;
1351 if (jtag_interface_init(CMD_CTX
) != ERROR_OK
)
1352 return ERROR_JTAG_INIT_FAILED
;
1354 jtag_add_reset(trst
, srst
);
1355 return jtag_execute_queue();
1358 COMMAND_HANDLER(handle_runtest_command
)
1361 return ERROR_COMMAND_SYNTAX_ERROR
;
1363 unsigned num_clocks
;
1364 COMMAND_PARSE_NUMBER(uint
, CMD_ARGV
[0], num_clocks
);
1366 jtag_add_runtest(num_clocks
, TAP_IDLE
);
1367 return jtag_execute_queue();
1371 * For "irscan" or "drscan" commands, the "end" (really, "next") state
1372 * should be stable ... and *NOT* a shift state, otherwise free-running
1373 * jtag clocks could change the values latched by the update state.
1374 * Not surprisingly, this is the same constraint as SVF; the "irscan"
1375 * and "drscan" commands are a write-only subset of what SVF provides.
1378 COMMAND_HANDLER(handle_irscan_command
)
1381 struct scan_field
*fields
;
1382 struct jtag_tap
*tap
;
1383 tap_state_t endstate
;
1385 if ((CMD_ARGC
< 2) || (CMD_ARGC
% 2))
1387 return ERROR_COMMAND_SYNTAX_ERROR
;
1390 /* optional "-endstate" "statename" at the end of the arguments,
1391 * so that e.g. IRPAUSE can let us load the data register before
1392 * entering RUN/IDLE to execute the instruction we load here.
1394 endstate
= TAP_IDLE
;
1396 if (CMD_ARGC
>= 4) {
1397 /* have at least one pair of numbers. */
1398 /* is last pair the magic text? */
1399 if (strcmp("-endstate", CMD_ARGV
[CMD_ARGC
- 2]) == 0) {
1400 endstate
= tap_state_by_name(CMD_ARGV
[CMD_ARGC
- 1]);
1401 if (endstate
== TAP_INVALID
)
1402 return ERROR_COMMAND_SYNTAX_ERROR
;
1403 if (!scan_is_safe(endstate
))
1404 LOG_WARNING("unstable irscan endstate \"%s\"",
1405 CMD_ARGV
[CMD_ARGC
- 1]);
1410 int num_fields
= CMD_ARGC
/ 2;
1411 size_t fields_len
= sizeof(struct scan_field
) * num_fields
;
1412 fields
= malloc(fields_len
);
1413 memset(fields
, 0, fields_len
);
1416 for (i
= 0; i
< num_fields
; i
++)
1418 tap
= jtag_tap_by_string(CMD_ARGV
[i
*2]);
1422 for (j
= 0; j
< i
; j
++)
1423 free(fields
[j
].out_value
);
1425 command_print(CMD_CTX
, "Tap: %s unknown", CMD_ARGV
[i
*2]);
1429 int field_size
= tap
->ir_length
;
1430 fields
[i
].tap
= tap
;
1431 fields
[i
].num_bits
= field_size
;
1432 fields
[i
].out_value
= malloc(DIV_ROUND_UP(field_size
, 8));
1435 retval
= parse_u32(CMD_ARGV
[i
* 2 + 1], &value
);
1436 if (ERROR_OK
!= retval
)
1438 buf_set_u32(fields
[i
].out_value
, 0, field_size
, value
);
1439 fields
[i
].in_value
= NULL
;
1442 /* did we have an endstate? */
1443 jtag_add_ir_scan(num_fields
, fields
, endstate
);
1445 retval
= jtag_execute_queue();
1448 for (i
= 0; i
< num_fields
; i
++)
1450 if (NULL
!= fields
[i
].out_value
)
1451 free(fields
[i
].out_value
);
1460 COMMAND_HANDLER(handle_verify_ircapture_command
)
1463 return ERROR_COMMAND_SYNTAX_ERROR
;
1468 COMMAND_PARSE_ENABLE(CMD_ARGV
[0], enable
);
1469 jtag_set_verify_capture_ir(enable
);
1472 const char *status
= jtag_will_verify_capture_ir() ? "enabled": "disabled";
1473 command_print(CMD_CTX
, "verify Capture-IR is %s", status
);
1478 COMMAND_HANDLER(handle_verify_jtag_command
)
1481 return ERROR_COMMAND_SYNTAX_ERROR
;
1486 COMMAND_PARSE_ENABLE(CMD_ARGV
[0], enable
);
1487 jtag_set_verify(enable
);
1490 const char *status
= jtag_will_verify() ? "enabled": "disabled";
1491 command_print(CMD_CTX
, "verify jtag capture is %s", status
);
1496 COMMAND_HANDLER(handle_tms_sequence_command
)
1499 return ERROR_COMMAND_SYNTAX_ERROR
;
1504 if (strcmp(CMD_ARGV
[0], "short") == 0)
1505 use_new_table
= true;
1506 else if (strcmp(CMD_ARGV
[0], "long") == 0)
1507 use_new_table
= false;
1509 return ERROR_COMMAND_SYNTAX_ERROR
;
1511 tap_use_new_tms_table(use_new_table
);
1514 command_print(CMD_CTX
, "tms sequence is %s",
1515 tap_uses_new_tms_table() ? "short": "long");
1520 static const struct command_registration jtag_command_handlers
[] = {
1522 .name
= "interface",
1523 .handler
= &handle_interface_command
,
1524 .mode
= COMMAND_CONFIG
,
1525 .help
= "select a JTAG interface",
1526 .usage
= "<driver_name>",
1529 .name
= "interface_list",
1530 .handler
= &handle_interface_list_command
,
1531 .mode
= COMMAND_ANY
,
1532 .help
= "list all built-in interfaces",
1536 .handler
= &handle_jtag_khz_command
,
1537 .mode
= COMMAND_ANY
,
1538 .help
= "set maximum jtag speed (if supported)",
1539 .usage
= "<khz:0=rtck>",
1542 .name
= "jtag_rclk",
1543 .handler
= &handle_jtag_rclk_command
,
1544 .mode
= COMMAND_ANY
,
1545 .help
= "set JTAG speed to RCLK or use fallback speed",
1546 .usage
= "<fallback_speed_khz>",
1549 .name
= "reset_config",
1550 .handler
= &handle_reset_config_command
,
1551 .mode
= COMMAND_ANY
,
1552 .help
= "configure JTAG reset behavior",
1553 .usage
= "[none|trst_only|srst_only|trst_and_srst] "
1554 "[srst_pulls_trst|trst_pulls_srst|combined|separate] "
1555 "[srst_gates_jtag|srst_nogate] "
1556 "[trst_push_pull|trst_open_drain] "
1557 "[srst_push_pull|srst_open_drain]",
1560 .name
= "jtag_nsrst_delay",
1561 .handler
= &handle_jtag_nsrst_delay_command
,
1562 .mode
= COMMAND_ANY
,
1563 .help
= "delay after deasserting srst in ms",
1567 .name
= "jtag_ntrst_delay",
1568 .handler
= &handle_jtag_ntrst_delay_command
,
1569 .mode
= COMMAND_ANY
,
1570 .help
= "delay after deasserting trst in ms",
1574 .name
= "jtag_nsrst_assert_width",
1575 .handler
= &handle_jtag_nsrst_assert_width_command
,
1576 .mode
= COMMAND_ANY
,
1577 .help
= "delay after asserting srst in ms",
1581 .name
= "jtag_ntrst_assert_width",
1582 .handler
= &handle_jtag_ntrst_assert_width_command
,
1583 .mode
= COMMAND_ANY
,
1584 .help
= "delay after asserting trst in ms",
1588 .name
= "scan_chain",
1589 .handler
= &handle_scan_chain_command
,
1590 .mode
= COMMAND_EXEC
,
1591 .help
= "print current scan chain configuration",
1594 .name
= "jtag_reset",
1595 .handler
= &handle_jtag_reset_command
,
1596 .mode
= COMMAND_EXEC
,
1597 .help
= "toggle reset lines",
1598 .usage
= "<trst> <srst>",
1602 .handler
= &handle_runtest_command
,
1603 .mode
= COMMAND_EXEC
,
1604 .help
= "move to Run-Test/Idle, and execute <num_cycles>",
1605 .usage
= "<num_cycles>"
1609 .handler
= &handle_irscan_command
,
1610 .mode
= COMMAND_EXEC
,
1611 .help
= "execute IR scan",
1612 .usage
= "<device> <instr> [dev2] [instr2] ...",
1615 .name
= "verify_ircapture",
1616 .handler
= &handle_verify_ircapture_command
,
1617 .mode
= COMMAND_ANY
,
1618 .help
= "verify value captured during Capture-IR",
1619 .usage
= "<enable | disable>",
1622 .name
= "verify_jtag",
1623 .handler
= &handle_verify_jtag_command
,
1624 .mode
= COMMAND_ANY
,
1625 .help
= "verify value capture",
1626 .usage
= "<enable | disable>",
1629 .name
= "tms_sequence",
1630 .handler
= &handle_tms_sequence_command
,
1631 .mode
= COMMAND_ANY
,
1632 .help
= "choose short(default) or long tms_sequence",
1633 .usage
= "<short | long>",
1637 .mode
= COMMAND_ANY
,
1638 .help
= "perform jtag tap actions",
1640 .chain
= jtag_subcommand_handlers
,
1643 .chain
= jtag_command_handlers_to_move
,
1645 COMMAND_REGISTRATION_DONE
1647 int jtag_register_commands(struct command_context
*cmd_ctx
)
1649 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)