1 /***************************************************************************
2 * Copyright (C) 2009-2010 by Simon Qian <SimonQian@SimonQian.com> *
4 * This program is free software; you can redistribute it and/or modify *
5 * it under the terms of the GNU General Public License as published by *
6 * the Free Software Foundation; either version 2 of the License, or *
7 * (at your option) any later version. *
9 * This program is distributed in the hope that it will be useful, *
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
12 * GNU General Public License for more details. *
14 * You should have received a copy of the GNU General Public License *
15 * along with this program; if not, write to the *
16 * Free Software Foundation, Inc., *
17 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
18 ***************************************************************************/
20 /* Versaloon is a programming tool for multiple MCUs.
21 * It's distributed under GPLv3.
22 * You can find it at http://www.Versaloon.com/.
29 #include <jtag/interface.h>
30 #include <jtag/commands.h>
31 #include "usb_common.h"
33 #include "versaloon/versaloon_include.h"
34 #include "versaloon/versaloon.h"
36 static int vsllink_tms_offset
;
38 struct pending_scan_result
{
41 int length
; /* Number of bits to read */
42 struct scan_command
*command
; /* Corresponding scan command */
45 bool last
; /* indicate the last scan pending */
48 #define MAX_PENDING_SCAN_RESULTS 256
50 static int pending_scan_results_length
;
51 static struct pending_scan_result
52 pending_scan_results_buffer
[MAX_PENDING_SCAN_RESULTS
];
54 /* Queue command functions */
55 static void vsllink_end_state(tap_state_t state
);
56 static void vsllink_state_move(void);
57 static void vsllink_path_move(int num_states
, tap_state_t
*path
);
58 static void vsllink_tms(int num_bits
, const uint8_t *bits
);
59 static void vsllink_runtest(int num_cycles
);
60 static void vsllink_stableclocks(int num_cycles
, int tms
);
61 static void vsllink_scan(bool ir_scan
, enum scan_type type
,
62 uint8_t *buffer
, int scan_size
, struct scan_command
*command
);
63 static void vsllink_reset(int trst
, int srst
);
65 /* VSLLink tap buffer functions */
66 static void vsllink_tap_append_step(int tms
, int tdi
);
67 static void vsllink_tap_init(void);
68 static int vsllink_tap_execute(void);
69 static void vsllink_tap_ensure_pending(int scans
);
70 static void vsllink_tap_append_scan(int length
, uint8_t *buffer
,
71 struct scan_command
*command
);
73 /* VSLLink lowlevel functions */
75 struct usb_dev_handle
*usb_handle
;
78 static struct vsllink
*vsllink_usb_open(void);
79 static void vsllink_usb_close(struct vsllink
*vsllink
);
81 #if defined _DEBUG_JTAG_IO_
82 static void vsllink_debug_buffer(uint8_t *buffer
, int length
);
85 static int tap_length
;
86 static int tap_buffer_size
;
87 static uint8_t *tms_buffer
;
88 static uint8_t *tdi_buffer
;
89 static uint8_t *tdo_buffer
;
91 struct vsllink
*vsllink_handle
;
93 static int vsllink_execute_queue(void)
95 struct jtag_command
*cmd
= jtag_command_queue
;
100 DEBUG_JTAG_IO("-------------------------------------"
102 "-------------------------------------");
104 while (cmd
!= NULL
) {
107 DEBUG_JTAG_IO("runtest %i cycles, end in %s",
108 cmd
->cmd
.runtest
->num_cycles
,
109 tap_state_name(cmd
->cmd
.runtest
->end_state
));
111 vsllink_end_state(cmd
->cmd
.runtest
->end_state
);
112 vsllink_runtest(cmd
->cmd
.runtest
->num_cycles
);
116 DEBUG_JTAG_IO("statemove end in %s",
117 tap_state_name(cmd
->cmd
.statemove
->end_state
));
119 vsllink_end_state(cmd
->cmd
.statemove
->end_state
);
120 vsllink_state_move();
124 DEBUG_JTAG_IO("pathmove: %i states, end in %s",
125 cmd
->cmd
.pathmove
->num_states
,
126 tap_state_name(cmd
->cmd
.pathmove
->path
[cmd
->cmd
.pathmove
->num_states
- 1]));
128 vsllink_path_move(cmd
->cmd
.pathmove
->num_states
, cmd
->cmd
.pathmove
->path
);
132 DEBUG_JTAG_IO("JTAG Scan...");
134 vsllink_end_state(cmd
->cmd
.scan
->end_state
);
136 scan_size
= jtag_build_buffer(
137 cmd
->cmd
.scan
, &buffer
);
139 if (cmd
->cmd
.scan
->ir_scan
)
141 "JTAG Scan write IR(%d bits), "
144 tap_state_name(cmd
->cmd
.scan
->end_state
));
148 "JTAG Scan write DR(%d bits), "
151 tap_state_name(cmd
->cmd
.scan
->end_state
));
153 #ifdef _DEBUG_JTAG_IO_
154 vsllink_debug_buffer(buffer
,
155 DIV_ROUND_UP(scan_size
, 8));
158 type
= jtag_scan_type(cmd
->cmd
.scan
);
160 vsllink_scan(cmd
->cmd
.scan
->ir_scan
,
161 type
, buffer
, scan_size
,
166 DEBUG_JTAG_IO("reset trst: %i srst %i",
167 cmd
->cmd
.reset
->trst
,
168 cmd
->cmd
.reset
->srst
);
170 vsllink_tap_execute();
172 if (cmd
->cmd
.reset
->trst
== 1)
173 tap_set_state(TAP_RESET
);
175 vsllink_reset(cmd
->cmd
.reset
->trst
,
176 cmd
->cmd
.reset
->srst
);
180 DEBUG_JTAG_IO("sleep %i", cmd
->cmd
.sleep
->us
);
181 vsllink_tap_execute();
182 jtag_sleep(cmd
->cmd
.sleep
->us
);
185 case JTAG_STABLECLOCKS
:
186 DEBUG_JTAG_IO("add %d clocks",
187 cmd
->cmd
.stableclocks
->num_cycles
);
189 switch (tap_get_state()) {
191 /* tms must be '1' to stay
201 /* else, tms should be '0' */
204 /* above stable states are OK */
206 LOG_ERROR("jtag_add_clocks() "
207 "in non-stable state \"%s\"",
208 tap_state_name(tap_get_state())
212 vsllink_stableclocks(cmd
->cmd
.stableclocks
->num_cycles
, scan_size
);
216 DEBUG_JTAG_IO("add %d jtag tms",
217 cmd
->cmd
.tms
->num_bits
);
219 vsllink_tms(cmd
->cmd
.tms
->num_bits
, cmd
->cmd
.tms
->bits
);
223 LOG_ERROR("BUG: unknown JTAG command type "
224 "encountered: %d", cmd
->type
);
230 return vsllink_tap_execute();
233 static int vsllink_speed(int speed
)
235 versaloon_interface
.adaptors
.jtag_raw
.config(0, (uint16_t)speed
);
236 return versaloon_interface
.adaptors
.peripheral_commit();
239 static int vsllink_khz(int khz
, int *jtag_speed
)
246 static int vsllink_speed_div(int jtag_speed
, int *khz
)
253 static void vsllink_free_buffer(void)
255 if (tdi_buffer
!= NULL
) {
259 if (tdo_buffer
!= NULL
) {
263 if (tms_buffer
!= NULL
) {
269 static int vsllink_quit(void)
271 versaloon_interface
.adaptors
.gpio
.config(0, GPIO_SRST
| GPIO_TRST
,
272 0, 0, GPIO_SRST
| GPIO_TRST
);
273 versaloon_interface
.adaptors
.gpio
.fini(0);
274 versaloon_interface
.adaptors
.jtag_raw
.fini(0);
275 versaloon_interface
.adaptors
.peripheral_commit();
276 versaloon_interface
.fini();
278 vsllink_free_buffer();
279 vsllink_usb_close(vsllink_handle
);
284 static int vsllink_init(void)
286 vsllink_handle
= vsllink_usb_open();
287 if (vsllink_handle
== 0) {
288 LOG_ERROR("Can't find USB JTAG Interface!" \
289 "Please check connection and permissions.");
290 return ERROR_JTAG_INIT_FAILED
;
292 LOG_DEBUG("vsllink found on %04X:%04X",
293 versaloon_interface
.usb_setting
.vid
,
294 versaloon_interface
.usb_setting
.pid
);
295 versaloon_usb_device_handle
= vsllink_handle
->usb_handle
;
297 if (ERROR_OK
!= versaloon_interface
.init())
299 if (versaloon_interface
.usb_setting
.buf_size
< 32) {
300 versaloon_interface
.fini();
304 /* malloc buffer size for tap */
305 tap_buffer_size
= versaloon_interface
.usb_setting
.buf_size
/ 2 - 32;
306 vsllink_free_buffer();
307 tdi_buffer
= (uint8_t *)malloc(tap_buffer_size
);
308 tdo_buffer
= (uint8_t *)malloc(tap_buffer_size
);
309 tms_buffer
= (uint8_t *)malloc(tap_buffer_size
);
310 if ((NULL
== tdi_buffer
) || (NULL
== tdo_buffer
) || (NULL
== tms_buffer
)) {
315 versaloon_interface
.adaptors
.jtag_raw
.init(0);
316 versaloon_interface
.adaptors
.jtag_raw
.config(0, jtag_get_speed_khz());
317 versaloon_interface
.adaptors
.gpio
.init(0);
318 versaloon_interface
.adaptors
.gpio
.config(0, GPIO_SRST
| GPIO_TRST
,
319 GPIO_TRST
, GPIO_SRST
, GPIO_SRST
);
320 if (ERROR_OK
!= versaloon_interface
.adaptors
.peripheral_commit())
328 /**************************************************************************
329 * Queue command implementations */
331 static void vsllink_end_state(tap_state_t state
)
333 if (tap_is_state_stable(state
))
334 tap_set_end_state(state
);
336 LOG_ERROR("BUG: %i is not a valid end state", state
);
341 /* Goes to the end state. */
342 static void vsllink_state_move(void)
345 uint8_t tms_scan
= tap_get_tms_path(tap_get_state(),
346 tap_get_end_state());
347 uint8_t tms_scan_bits
= tap_get_tms_path_len(tap_get_state(),
348 tap_get_end_state());
350 for (i
= 0; i
< tms_scan_bits
; i
++)
351 vsllink_tap_append_step((tms_scan
>> i
) & 1, 0);
353 tap_set_state(tap_get_end_state());
356 static void vsllink_path_move(int num_states
, tap_state_t
*path
)
358 for (int i
= 0; i
< num_states
; i
++) {
359 if (path
[i
] == tap_state_transition(tap_get_state(), false))
360 vsllink_tap_append_step(0, 0);
361 else if (path
[i
] == tap_state_transition(tap_get_state(), true))
362 vsllink_tap_append_step(1, 0);
364 LOG_ERROR("BUG: %s -> %s isn't a valid TAP transition",
365 tap_state_name(tap_get_state()),
366 tap_state_name(path
[i
]));
370 tap_set_state(path
[i
]);
373 tap_set_end_state(tap_get_state());
376 static void vsllink_tms(int num_bits
, const uint8_t *bits
)
378 for (int i
= 0; i
< num_bits
; i
++)
379 vsllink_tap_append_step((bits
[i
/ 8] >> (i
% 8)) & 1, 0);
382 static void vsllink_stableclocks(int num_cycles
, int tms
)
384 while (num_cycles
> 0) {
385 vsllink_tap_append_step(tms
, 0);
390 static void vsllink_runtest(int num_cycles
)
392 tap_state_t saved_end_state
= tap_get_end_state();
394 if (tap_get_state() != TAP_IDLE
) {
395 /* enter IDLE state */
396 vsllink_end_state(TAP_IDLE
);
397 vsllink_state_move();
400 vsllink_stableclocks(num_cycles
, 0);
404 vsllink_end_state(saved_end_state
);
405 if (tap_get_end_state() != tap_get_end_state())
406 vsllink_state_move();
409 static void vsllink_scan(bool ir_scan
, enum scan_type type
, uint8_t *buffer
,
410 int scan_size
, struct scan_command
*command
)
412 tap_state_t saved_end_state
;
414 saved_end_state
= tap_get_end_state();
416 /* Move to appropriate scan state */
417 vsllink_end_state(ir_scan
? TAP_IRSHIFT
: TAP_DRSHIFT
);
419 if (tap_get_state() != tap_get_end_state())
420 vsllink_state_move();
421 vsllink_end_state(saved_end_state
);
424 vsllink_tap_append_scan(scan_size
, buffer
, command
);
426 /* Goto Pause and record position to insert tms:0 */
427 vsllink_tap_append_step(0, 0);
428 vsllink_tms_offset
= tap_length
;
430 tap_set_state(ir_scan
? TAP_IRPAUSE
: TAP_DRPAUSE
);
432 if (tap_get_state() != tap_get_end_state())
433 vsllink_state_move();
436 static void vsllink_reset(int trst
, int srst
)
438 LOG_DEBUG("trst: %i, srst: %i", trst
, srst
);
441 versaloon_interface
.adaptors
.gpio
.config(0, GPIO_SRST
, 0, GPIO_SRST
, GPIO_SRST
);
443 versaloon_interface
.adaptors
.gpio
.config(0, GPIO_SRST
, GPIO_SRST
, 0, 0);
446 versaloon_interface
.adaptors
.gpio
.out(0, GPIO_TRST
, GPIO_TRST
);
448 versaloon_interface
.adaptors
.gpio
.out(0, GPIO_TRST
, 0);
449 versaloon_interface
.adaptors
.peripheral_commit();
452 COMMAND_HANDLER(vsllink_handle_usb_vid_command
)
455 return ERROR_COMMAND_SYNTAX_ERROR
;
457 COMMAND_PARSE_NUMBER(u16
, CMD_ARGV
[0],
458 versaloon_interface
.usb_setting
.vid
);
462 COMMAND_HANDLER(vsllink_handle_usb_pid_command
)
465 return ERROR_COMMAND_SYNTAX_ERROR
;
466 COMMAND_PARSE_NUMBER(u16
, CMD_ARGV
[0],
467 versaloon_interface
.usb_setting
.pid
);
471 COMMAND_HANDLER(vsllink_handle_usb_bulkin_command
)
474 return ERROR_COMMAND_SYNTAX_ERROR
;
476 COMMAND_PARSE_NUMBER(u8
, CMD_ARGV
[0],
477 versaloon_interface
.usb_setting
.ep_in
);
479 versaloon_interface
.usb_setting
.ep_in
|= 0x80;
484 COMMAND_HANDLER(vsllink_handle_usb_bulkout_command
)
487 return ERROR_COMMAND_SYNTAX_ERROR
;
489 COMMAND_PARSE_NUMBER(u8
, CMD_ARGV
[0],
490 versaloon_interface
.usb_setting
.ep_out
);
492 versaloon_interface
.usb_setting
.ep_out
&= ~0x80;
497 COMMAND_HANDLER(vsllink_handle_usb_interface_command
)
500 return ERROR_COMMAND_SYNTAX_ERROR
;
502 COMMAND_PARSE_NUMBER(u8
, CMD_ARGV
[0],
503 versaloon_interface
.usb_setting
.interface
);
507 /**************************************************************************
508 * VSLLink tap functions */
510 static void vsllink_tap_init(void)
513 pending_scan_results_length
= 0;
514 vsllink_tms_offset
= 0;
517 static void vsllink_tap_ensure_pending(int scans
)
519 int available_scans
=
520 MAX_PENDING_SCAN_RESULTS
- pending_scan_results_length
;
522 if (scans
> available_scans
)
523 vsllink_tap_execute();
526 static void vsllink_tap_append_step(int tms
, int tdi
)
528 int index_var
= tap_length
/ 8;
530 int bit_index
= tap_length
% 8;
531 uint8_t bit
= 1 << bit_index
;
534 tms_buffer
[index_var
] |= bit
;
536 tms_buffer
[index_var
] &= ~bit
;
539 tdi_buffer
[index_var
] |= bit
;
541 tdi_buffer
[index_var
] &= ~bit
;
545 if (tap_buffer_size
* 8 <= tap_length
)
546 vsllink_tap_execute();
549 static void vsllink_tap_append_scan(int length
, uint8_t *buffer
,
550 struct scan_command
*command
)
552 struct pending_scan_result
*pending_scan_result
;
553 int len_tmp
, len_all
, i
;
556 while (len_all
< length
) {
557 vsllink_tap_ensure_pending(1);
558 pending_scan_result
=
559 &pending_scan_results_buffer
[
560 pending_scan_results_length
];
562 if ((length
- len_all
) > (tap_buffer_size
* 8 - tap_length
)) {
563 /* Use all memory available
564 vsllink_tap_append_step will commit automatically */
565 len_tmp
= tap_buffer_size
* 8 - tap_length
;
566 pending_scan_result
->last
= false;
568 len_tmp
= length
- len_all
;
569 pending_scan_result
->last
= true;
571 pending_scan_result
->src_offset
= tap_length
;
572 pending_scan_result
->dest_offset
= len_all
;
573 pending_scan_result
->length
= len_tmp
;
574 pending_scan_result
->command
= command
;
575 pending_scan_result
->buffer
= buffer
;
576 pending_scan_results_length
++;
578 for (i
= 0; i
< len_tmp
; i
++) {
579 vsllink_tap_append_step(((len_all
+ i
) < length
-1
581 (buffer
[(len_all
+ i
)/8]
582 >> ((len_all
+ i
)%8)) & 1);
589 static int vsllink_jtag_execute(void)
597 versaloon_interface
.adaptors
.jtag_raw
.execute(0, tdi_buffer
, tms_buffer
,
598 tdo_buffer
, tap_length
);
600 result
= versaloon_interface
.adaptors
.peripheral_commit();
602 if (result
== ERROR_OK
) {
603 for (i
= 0; i
< pending_scan_results_length
; i
++) {
604 struct pending_scan_result
*pending_scan_result
=
605 &pending_scan_results_buffer
[i
];
606 uint8_t *buffer
= pending_scan_result
->buffer
;
607 int length
= pending_scan_result
->length
;
608 int src_first
= pending_scan_result
->src_offset
;
609 int dest_first
= pending_scan_result
->dest_offset
;
610 bool last
= pending_scan_result
->last
;
612 struct scan_command
*command
;
614 command
= pending_scan_result
->command
;
615 buf_set_buf(tdo_buffer
, src_first
, buffer
, dest_first
, length
);
617 #ifdef _DEBUG_JTAG_IO_
619 "JTAG scan read(%d bits, from src %d bits to dest %d bits):",
620 length
, src_first
, dest_first
);
621 vsllink_debug_buffer(buffer
+ dest_first
/ 8,
622 DIV_ROUND_UP(length
, 7));
626 if (jtag_read_buffer(buffer
, command
)
629 return ERROR_JTAG_QUEUE_FAILED
;
632 if (pending_scan_result
->buffer
!= NULL
)
633 free(pending_scan_result
->buffer
);
637 LOG_ERROR("vsllink_jtag_execute failure");
638 return ERROR_JTAG_QUEUE_FAILED
;
646 static int vsllink_tap_execute(void)
648 return vsllink_jtag_execute();
651 /****************************************************************************
652 * VSLLink USB low-level functions */
654 static uint8_t usb_check_string(usb_dev_handle
*usb
, uint8_t stringidx
,
655 char *string
, char *buff
, uint16_t buf_size
)
663 buff
= (char *)malloc(buf_size
);
666 goto free_and_return
;
672 len
= usb_get_string_simple(usb
, stringidx
, (char *)buff
, buf_size
);
673 if ((len
< 0) || (len
!= ((int)strlen((const char *)buff
)))) {
675 goto free_and_return
;
679 if ((string
!= NULL
) && strcmp((const char *)buff
, string
)) {
681 goto free_and_return
;
685 if (alloced
&& (buff
!= NULL
)) {
692 static usb_dev_handle
*find_usb_device(uint16_t VID
, uint16_t PID
,
693 uint8_t interface
, int8_t serialindex
, char *serialstring
,
694 int8_t productindex
, char *productstring
)
696 usb_dev_handle
*dev_handle
= NULL
;
697 struct usb_bus
*busses
;
699 struct usb_device
*dev
;
704 busses
= usb_get_busses();
706 for (bus
= busses
; bus
; bus
= bus
->next
) {
707 for (dev
= bus
->devices
; dev
; dev
= dev
->next
) {
708 if ((dev
->descriptor
.idVendor
== VID
)
709 && (dev
->descriptor
.idProduct
== PID
)) {
710 dev_handle
= usb_open(dev
);
711 if (NULL
== dev_handle
) {
712 LOG_ERROR("failed to open %04X:%04X, %s", VID
, PID
,
717 /* check description string */
718 if (((productstring
!= NULL
) && (productindex
>= 0)
719 && !usb_check_string(dev_handle
, productindex
,
720 productstring
, NULL
, 0))
721 || ((serialstring
!= NULL
) && (serialindex
>= 0)
722 && !usb_check_string(dev_handle
, serialindex
,
723 serialstring
, NULL
, 0))) {
724 usb_close(dev_handle
);
729 if (usb_claim_interface(dev_handle
, interface
) != 0) {
730 LOG_ERROR(ERRMSG_FAILURE_OPERATION_MESSAGE
,
731 "claim interface", usb_strerror());
732 usb_close(dev_handle
);
737 if (dev_handle
!= NULL
)
746 static struct vsllink
*vsllink_usb_open(void)
750 struct usb_dev_handle
*dev
;
752 dev
= find_usb_device(versaloon_interface
.usb_setting
.vid
,
753 versaloon_interface
.usb_setting
.pid
,
754 versaloon_interface
.usb_setting
.interface
,
755 0, NULL
, 2, "Versaloon");
759 struct vsllink
*result
= malloc(sizeof(struct vsllink
));
760 result
->usb_handle
= dev
;
764 static void vsllink_usb_close(struct vsllink
*vsllink
)
768 ret
= usb_release_interface(vsllink
->usb_handle
,
769 versaloon_interface
.usb_setting
.interface
);
771 LOG_ERROR("fail to release interface %d, %d returned",
772 versaloon_interface
.usb_setting
.interface
, ret
);
776 ret
= usb_close(vsllink
->usb_handle
);
778 LOG_ERROR("fail to close usb, %d returned", ret
);
785 #define BYTES_PER_LINE 16
787 #if defined _DEBUG_JTAG_IO_
788 static void vsllink_debug_buffer(uint8_t *buffer
, int length
)
795 for (i
= 0; i
< length
; i
+= BYTES_PER_LINE
) {
796 snprintf(line
, 5, "%04x", i
);
797 for (j
= i
; j
< i
+ BYTES_PER_LINE
&& j
< length
; j
++) {
798 snprintf(s
, 4, " %02x", buffer
[j
]);
801 LOG_DEBUG("%s", line
);
804 #endif /* _DEBUG_JTAG_IO_ */
806 static const struct command_registration vsllink_command_handlers
[] = {
808 .name
= "vsllink_usb_vid",
809 .handler
= &vsllink_handle_usb_vid_command
,
810 .mode
= COMMAND_CONFIG
,
813 .name
= "vsllink_usb_pid",
814 .handler
= &vsllink_handle_usb_pid_command
,
815 .mode
= COMMAND_CONFIG
,
818 .name
= "vsllink_usb_bulkin",
819 .handler
= &vsllink_handle_usb_bulkin_command
,
820 .mode
= COMMAND_CONFIG
,
823 .name
= "vsllink_usb_bulkout",
824 .handler
= &vsllink_handle_usb_bulkout_command
,
825 .mode
= COMMAND_CONFIG
,
828 .name
= "vsllink_usb_interface",
829 .handler
= &vsllink_handle_usb_interface_command
,
830 .mode
= COMMAND_CONFIG
,
832 COMMAND_REGISTRATION_DONE
835 static const char *vsllink_transports
[] = {"jtag", "swd", NULL
};
837 struct jtag_interface vsllink_interface
= {
839 .supported
= DEBUG_CAP_TMS_SEQ
,
840 .commands
= vsllink_command_handlers
,
841 .transports
= vsllink_transports
,
843 .init
= vsllink_init
,
844 .quit
= vsllink_quit
,
846 .speed
= vsllink_speed
,
847 .speed_div
= vsllink_speed_div
,
848 .execute_queue
= vsllink_execute_queue
,
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)