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
112 vsllink_end_state(cmd
->cmd
.runtest
->end_state
);
113 vsllink_runtest(cmd
->cmd
.runtest
->num_cycles
);
117 DEBUG_JTAG_IO("statemove end in %s",
118 tap_state_name(cmd
->cmd
.statemove
121 vsllink_end_state(cmd
->cmd
.statemove
123 vsllink_state_move();
127 DEBUG_JTAG_IO("pathmove: %i states, end in %s",
128 cmd
->cmd
.pathmove
->num_states
,
129 tap_state_name(cmd
->cmd
.pathmove
130 ->path
[cmd
->cmd
.pathmove
134 cmd
->cmd
.pathmove
->num_states
,
135 cmd
->cmd
.pathmove
->path
);
139 DEBUG_JTAG_IO("JTAG Scan...");
141 vsllink_end_state(cmd
->cmd
.scan
->end_state
);
143 scan_size
= jtag_build_buffer(
144 cmd
->cmd
.scan
, &buffer
);
146 if (cmd
->cmd
.scan
->ir_scan
)
148 "JTAG Scan write IR(%d bits), "
151 tap_state_name(cmd
->cmd
.scan
156 "JTAG Scan write DR(%d bits), "
159 tap_state_name(cmd
->cmd
.scan
162 #ifdef _DEBUG_JTAG_IO_
163 vsllink_debug_buffer(buffer
,
164 DIV_ROUND_UP(scan_size
, 8));
167 type
= jtag_scan_type(cmd
->cmd
.scan
);
169 vsllink_scan(cmd
->cmd
.scan
->ir_scan
,
170 type
, buffer
, scan_size
,
175 DEBUG_JTAG_IO("reset trst: %i srst %i",
176 cmd
->cmd
.reset
->trst
,
177 cmd
->cmd
.reset
->srst
);
179 vsllink_tap_execute();
181 if (cmd
->cmd
.reset
->trst
== 1)
182 tap_set_state(TAP_RESET
);
184 vsllink_reset(cmd
->cmd
.reset
->trst
,
185 cmd
->cmd
.reset
->srst
);
189 DEBUG_JTAG_IO("sleep %i", cmd
->cmd
.sleep
->us
);
190 vsllink_tap_execute();
191 jtag_sleep(cmd
->cmd
.sleep
->us
);
194 case JTAG_STABLECLOCKS
:
195 DEBUG_JTAG_IO("add %d clocks",
196 cmd
->cmd
.stableclocks
->num_cycles
);
198 switch (tap_get_state()) {
200 /* tms must be '1' to stay
210 /* else, tms should be '0' */
213 /* above stable states are OK */
215 LOG_ERROR("jtag_add_clocks() "
216 "in non-stable state \"%s\"",
217 tap_state_name(tap_get_state())
221 vsllink_stableclocks(cmd
->cmd
.stableclocks
222 ->num_cycles
, scan_size
);
226 DEBUG_JTAG_IO("add %d jtag tms",
227 cmd
->cmd
.tms
->num_bits
);
229 vsllink_tms(cmd
->cmd
.tms
->num_bits
, cmd
->cmd
.tms
->bits
);
233 LOG_ERROR("BUG: unknown JTAG command type "
234 "encountered: %d", cmd
->type
);
240 return vsllink_tap_execute();
243 static int vsllink_speed(int speed
)
245 versaloon_interface
.adaptors
.jtag_raw
.config(0, (uint16_t)speed
);
246 return versaloon_interface
.adaptors
.peripheral_commit();
249 static int vsllink_khz(int khz
, int *jtag_speed
)
256 static int vsllink_speed_div(int jtag_speed
, int *khz
)
263 static void vsllink_free_buffer(void)
265 if (tdi_buffer
!= NULL
)
270 if (tdo_buffer
!= NULL
)
275 if (tms_buffer
!= NULL
)
282 static int vsllink_quit(void)
284 versaloon_interface
.adaptors
.gpio
.config(0, GPIO_SRST
| GPIO_TRST
,
285 0, 0, GPIO_SRST
| GPIO_TRST
);
286 versaloon_interface
.adaptors
.gpio
.fini(0);
287 versaloon_interface
.adaptors
.jtag_raw
.fini(0);
288 versaloon_interface
.adaptors
.peripheral_commit();
289 versaloon_interface
.fini();
291 vsllink_free_buffer();
292 vsllink_usb_close(vsllink_handle
);
297 static int vsllink_init(void)
299 vsllink_handle
= vsllink_usb_open();
300 if (vsllink_handle
== 0) {
301 LOG_ERROR("Can't find USB JTAG Interface!"\
302 "Please check connection and permissions.");
303 return ERROR_JTAG_INIT_FAILED
;
305 LOG_DEBUG("vsllink found on %04X:%04X",
306 versaloon_interface
.usb_setting
.vid
,
307 versaloon_interface
.usb_setting
.pid
);
308 versaloon_usb_device_handle
= vsllink_handle
->usb_handle
;
310 if (ERROR_OK
!= versaloon_interface
.init())
314 if (versaloon_interface
.usb_setting
.buf_size
< 32)
316 versaloon_interface
.fini();
320 // malloc buffer size for tap
321 tap_buffer_size
= versaloon_interface
.usb_setting
.buf_size
- 32;
322 vsllink_free_buffer();
323 tdi_buffer
= (uint8_t *)malloc(tap_buffer_size
);
324 tdo_buffer
= (uint8_t *)malloc(tap_buffer_size
);
325 tms_buffer
= (uint8_t *)malloc(tap_buffer_size
);
326 if ((NULL
== tdi_buffer
) || (NULL
== tdo_buffer
) || (NULL
== tms_buffer
))
332 versaloon_interface
.adaptors
.jtag_raw
.init(0);
333 versaloon_interface
.adaptors
.jtag_raw
.config(0, jtag_get_speed_khz());
334 versaloon_interface
.adaptors
.gpio
.init(0);
335 versaloon_interface
.adaptors
.gpio
.config(0, GPIO_SRST
| GPIO_TRST
,
336 GPIO_TRST
, GPIO_SRST
, GPIO_SRST
);
337 if (ERROR_OK
!= versaloon_interface
.adaptors
.peripheral_commit())
347 /***************************************************************************/
348 /* Queue command implementations */
350 static void vsllink_end_state(tap_state_t state
)
352 if (tap_is_state_stable(state
))
353 tap_set_end_state(state
);
355 LOG_ERROR("BUG: %i is not a valid end state", state
);
360 /* Goes to the end state. */
361 static void vsllink_state_move(void)
364 uint8_t tms_scan
= tap_get_tms_path(tap_get_state(),
365 tap_get_end_state());
366 uint8_t tms_scan_bits
= tap_get_tms_path_len(tap_get_state(),
367 tap_get_end_state());
369 for (i
= 0; i
< tms_scan_bits
; i
++)
370 vsllink_tap_append_step((tms_scan
>> i
) & 1, 0);
372 tap_set_state(tap_get_end_state());
375 static void vsllink_path_move(int num_states
, tap_state_t
*path
)
377 for (int i
= 0; i
< num_states
; i
++) {
378 if (path
[i
] == tap_state_transition(tap_get_state(), false))
379 vsllink_tap_append_step(0, 0);
380 else if (path
[i
] == tap_state_transition(tap_get_state(), true))
381 vsllink_tap_append_step(1, 0);
383 LOG_ERROR("BUG: %s -> %s isn't a valid TAP transition",
384 tap_state_name(tap_get_state()),
385 tap_state_name(path
[i
]));
389 tap_set_state(path
[i
]);
392 tap_set_end_state(tap_get_state());
395 static void vsllink_tms(int num_bits
, const uint8_t *bits
)
397 for (int i
= 0; i
< num_bits
; i
++) {
398 vsllink_tap_append_step((bits
[i
/ 8] >> (i
% 8)) & 1, 0);
402 static void vsllink_stableclocks(int num_cycles
, int tms
)
404 while (num_cycles
> 0) {
405 vsllink_tap_append_step(tms
, 0);
410 static void vsllink_runtest(int num_cycles
)
412 tap_state_t saved_end_state
= tap_get_end_state();
414 if (tap_get_state() != TAP_IDLE
) {
415 /* enter IDLE state */
416 vsllink_end_state(TAP_IDLE
);
417 vsllink_state_move();
420 vsllink_stableclocks(num_cycles
, 0);
424 vsllink_end_state(saved_end_state
);
425 if (tap_get_end_state() != tap_get_end_state())
426 vsllink_state_move();
429 static void vsllink_scan(bool ir_scan
, enum scan_type type
, uint8_t *buffer
,
430 int scan_size
, struct scan_command
*command
)
432 tap_state_t saved_end_state
;
434 saved_end_state
= tap_get_end_state();
436 /* Move to appropriate scan state */
437 vsllink_end_state(ir_scan
? TAP_IRSHIFT
: TAP_DRSHIFT
);
439 if (tap_get_state() != tap_get_end_state())
440 vsllink_state_move();
441 vsllink_end_state(saved_end_state
);
444 vsllink_tap_append_scan(scan_size
, buffer
, command
);
446 /* Goto Pause and record position to insert tms:0 */
447 vsllink_tap_append_step(0, 0);
448 vsllink_tms_offset
= tap_length
;
450 tap_set_state(ir_scan
? TAP_IRPAUSE
: TAP_DRPAUSE
);
452 if (tap_get_state() != tap_get_end_state())
453 vsllink_state_move();
456 static void vsllink_reset(int trst
, int srst
)
458 LOG_DEBUG("trst: %i, srst: %i", trst
, srst
);
461 versaloon_interface
.adaptors
.gpio
.config(0, GPIO_SRST
, 0, GPIO_SRST
, GPIO_SRST
);
463 versaloon_interface
.adaptors
.gpio
.config(0, GPIO_SRST
, GPIO_SRST
, 0, 0);
466 versaloon_interface
.adaptors
.gpio
.out(0, GPIO_TRST
, GPIO_TRST
);
468 versaloon_interface
.adaptors
.gpio
.out(0, GPIO_TRST
, 0);
469 versaloon_interface
.adaptors
.peripheral_commit();
472 COMMAND_HANDLER(vsllink_handle_usb_vid_command
)
475 LOG_ERROR("parameter error, "
476 "should be one parameter for VID");
480 COMMAND_PARSE_NUMBER(u16
, CMD_ARGV
[0],
481 versaloon_interface
.usb_setting
.vid
);
485 COMMAND_HANDLER(vsllink_handle_usb_pid_command
)
488 LOG_ERROR("parameter error, "
489 "should be one parameter for PID");
492 COMMAND_PARSE_NUMBER(u16
, CMD_ARGV
[0],
493 versaloon_interface
.usb_setting
.pid
);
497 COMMAND_HANDLER(vsllink_handle_usb_bulkin_command
)
500 LOG_ERROR("parameter error, "
501 "should be one parameter for BULKIN endpoint");
505 COMMAND_PARSE_NUMBER(u8
, CMD_ARGV
[0],
506 versaloon_interface
.usb_setting
.ep_in
);
508 versaloon_interface
.usb_setting
.ep_in
|= 0x80;
513 COMMAND_HANDLER(vsllink_handle_usb_bulkout_command
)
516 LOG_ERROR("parameter error, "
517 "should be one parameter for BULKOUT endpoint");
521 COMMAND_PARSE_NUMBER(u8
, CMD_ARGV
[0],
522 versaloon_interface
.usb_setting
.ep_out
);
524 versaloon_interface
.usb_setting
.ep_out
&= ~0x80;
529 COMMAND_HANDLER(vsllink_handle_usb_interface_command
)
532 LOG_ERROR("parameter error, "
533 "should be one parameter for interface number");
537 COMMAND_PARSE_NUMBER(u8
, CMD_ARGV
[0],
538 versaloon_interface
.usb_setting
.interface
);
542 /***************************************************************************/
543 /* VSLLink tap functions */
545 static void vsllink_tap_init(void)
548 pending_scan_results_length
= 0;
549 vsllink_tms_offset
= 0;
552 static void vsllink_tap_ensure_pending(int scans
)
554 int available_scans
=
555 MAX_PENDING_SCAN_RESULTS
- pending_scan_results_length
;
557 if (scans
> available_scans
)
558 vsllink_tap_execute();
561 static void vsllink_tap_append_step(int tms
, int tdi
)
563 int index_var
= tap_length
/ 8;
565 int bit_index
= tap_length
% 8;
566 uint8_t bit
= 1 << bit_index
;
569 tms_buffer
[index_var
] |= bit
;
571 tms_buffer
[index_var
] &= ~bit
;
574 tdi_buffer
[index_var
] |= bit
;
576 tdi_buffer
[index_var
] &= ~bit
;
580 if (tap_buffer_size
* 8 <= tap_length
)
581 vsllink_tap_execute();
584 static void vsllink_tap_append_scan(int length
, uint8_t *buffer
,
585 struct scan_command
*command
)
587 struct pending_scan_result
*pending_scan_result
;
588 int len_tmp
, len_all
, i
;
591 while (len_all
< length
) {
592 vsllink_tap_ensure_pending(1);
593 pending_scan_result
=
594 &pending_scan_results_buffer
[
595 pending_scan_results_length
];
597 if ((length
- len_all
) > (tap_buffer_size
* 8 - tap_length
)) {
598 /* Use all memory available
599 vsllink_tap_append_step will commit automatically */
600 len_tmp
= tap_buffer_size
* 8 - tap_length
;
601 pending_scan_result
->last
= false;
603 len_tmp
= length
- len_all
;
604 pending_scan_result
->last
= true;
606 pending_scan_result
->src_offset
= tap_length
;
607 pending_scan_result
->dest_offset
= len_all
;
608 pending_scan_result
->length
= len_tmp
;
609 pending_scan_result
->command
= command
;
610 pending_scan_result
->buffer
= buffer
;
611 pending_scan_results_length
++;
613 for (i
= 0; i
< len_tmp
; i
++) {
614 vsllink_tap_append_step(((len_all
+ i
) < length
-1
616 (buffer
[(len_all
+ i
)/8]
617 >> ((len_all
+ i
)%8)) & 1);
624 static int vsllink_jtag_execute(void)
632 versaloon_interface
.adaptors
.jtag_raw
.execute(0, tdi_buffer
, tms_buffer
,
633 tdo_buffer
, tap_length
);
635 result
= versaloon_interface
.adaptors
.peripheral_commit();
637 if (result
== ERROR_OK
) {
638 for (i
= 0; i
< pending_scan_results_length
; i
++) {
639 struct pending_scan_result
*pending_scan_result
=
640 &pending_scan_results_buffer
[i
];
641 uint8_t *buffer
= pending_scan_result
->buffer
;
642 int length
= pending_scan_result
->length
;
643 int src_first
= pending_scan_result
->src_offset
;
644 int dest_first
= pending_scan_result
->dest_offset
;
645 bool last
= pending_scan_result
->last
;
647 struct scan_command
*command
;
649 command
= pending_scan_result
->command
;
650 buf_set_buf(tdo_buffer
, src_first
, buffer
, dest_first
, length
);
652 #ifdef _DEBUG_JTAG_IO_
654 "JTAG scan read(%d bits, from src %d bits to dest %d bits):",
655 length
, src_first
, dest_first
);
656 vsllink_debug_buffer(buffer
+ dest_first
/ 8,
657 DIV_ROUND_UP(length
, 7));
661 if (jtag_read_buffer(buffer
, command
)
664 return ERROR_JTAG_QUEUE_FAILED
;
667 if (pending_scan_result
->buffer
!= NULL
)
668 free(pending_scan_result
->buffer
);
672 LOG_ERROR("vsllink_jtag_execute failure");
673 return ERROR_JTAG_QUEUE_FAILED
;
681 static int vsllink_tap_execute(void)
683 return vsllink_jtag_execute();
686 /*****************************************************************************/
687 /* VSLLink USB low-level functions */
689 static uint8_t usb_check_string(usb_dev_handle
*usb
, uint8_t stringidx
,
690 char * string
, char * buff
, uint16_t buf_size
)
699 buff
= (char*)malloc(buf_size
);
703 goto free_and_return
;
709 len
= usb_get_string_simple(usb
, stringidx
, (char *)buff
, buf_size
);
710 if ((len
< 0) || (len
!= ((int)strlen((const char *)buff
))))
713 goto free_and_return
;
717 if ((string
!= NULL
) && strcmp((const char *)buff
, string
))
720 goto free_and_return
;
724 if (alloced
&& (buff
!= NULL
))
732 static usb_dev_handle
* find_usb_device(uint16_t VID
, uint16_t PID
,
733 uint8_t interface
, int8_t serialindex
, char *serialstring
,
734 int8_t productindex
, char *productstring
)
736 usb_dev_handle
*dev_handle
= NULL
;
737 struct usb_bus
*busses
;
739 struct usb_device
*dev
;
744 busses
= usb_get_busses();
746 for (bus
= busses
; bus
; bus
= bus
->next
)
748 for (dev
= bus
->devices
; dev
; dev
= dev
->next
)
750 if ((dev
->descriptor
.idVendor
== VID
)
751 && (dev
->descriptor
.idProduct
== PID
))
753 dev_handle
= usb_open(dev
);
754 if (NULL
== dev_handle
)
756 LOG_ERROR("failed to open %04X:%04X, %s", VID
, PID
,
761 // check description string
762 if (((productstring
!= NULL
) && (productindex
>= 0)
763 && !usb_check_string(dev_handle
, productindex
,
764 productstring
, NULL
, 0))
765 || ((serialstring
!= NULL
) && (serialindex
>= 0)
766 && !usb_check_string(dev_handle
, serialindex
,
767 serialstring
, NULL
, 0)))
769 usb_close(dev_handle
);
774 if (usb_claim_interface(dev_handle
, interface
) != 0)
776 LOG_ERROR(ERRMSG_FAILURE_OPERATION_MESSAGE
,
777 "claim interface", usb_strerror());
778 usb_close(dev_handle
);
783 if (dev_handle
!= NULL
)
794 static struct vsllink
*vsllink_usb_open(void)
798 struct usb_dev_handle
*dev
;
800 dev
= find_usb_device(versaloon_interface
.usb_setting
.vid
,
801 versaloon_interface
.usb_setting
.pid
,
802 versaloon_interface
.usb_setting
.interface
,
803 0, NULL
, 2, "Versaloon");
807 struct vsllink
*result
= malloc(sizeof(struct vsllink
));
808 result
->usb_handle
= dev
;
812 static void vsllink_usb_close(struct vsllink
*vsllink
)
816 ret
= usb_release_interface(vsllink
->usb_handle
,
817 versaloon_interface
.usb_setting
.interface
);
819 LOG_ERROR("fail to release interface %d, %d returned",
820 versaloon_interface
.usb_setting
.interface
, ret
);
824 ret
= usb_close(vsllink
->usb_handle
);
826 LOG_ERROR("fail to close usb, %d returned", ret
);
833 #define BYTES_PER_LINE 16
835 #if defined _DEBUG_JTAG_IO_
836 static void vsllink_debug_buffer(uint8_t *buffer
, int length
)
843 for (i
= 0; i
< length
; i
+= BYTES_PER_LINE
) {
844 snprintf(line
, 5, "%04x", i
);
845 for (j
= i
; j
< i
+ BYTES_PER_LINE
&& j
< length
; j
++) {
846 snprintf(s
, 4, " %02x", buffer
[j
]);
849 LOG_DEBUG("%s", line
);
852 #endif /* _DEBUG_JTAG_IO_ */
854 static const struct command_registration vsllink_command_handlers
[] = {
856 .name
= "vsllink_usb_vid",
857 .handler
= &vsllink_handle_usb_vid_command
,
858 .mode
= COMMAND_CONFIG
,
861 .name
= "vsllink_usb_pid",
862 .handler
= &vsllink_handle_usb_pid_command
,
863 .mode
= COMMAND_CONFIG
,
866 .name
= "vsllink_usb_bulkin",
867 .handler
= &vsllink_handle_usb_bulkin_command
,
868 .mode
= COMMAND_CONFIG
,
871 .name
= "vsllink_usb_bulkout",
872 .handler
= &vsllink_handle_usb_bulkout_command
,
873 .mode
= COMMAND_CONFIG
,
876 .name
= "vsllink_usb_interface",
877 .handler
= &vsllink_handle_usb_interface_command
,
878 .mode
= COMMAND_CONFIG
,
880 COMMAND_REGISTRATION_DONE
883 static const char *vsllink_transports
[] = {"jtag", "swd", NULL
};
885 struct jtag_interface vsllink_interface
= {
887 .supported
= DEBUG_CAP_TMS_SEQ
,
888 .commands
= vsllink_command_handlers
,
889 .transports
= vsllink_transports
,
891 .init
= vsllink_init
,
892 .quit
= vsllink_quit
,
894 .speed
= vsllink_speed
,
895 .speed_div
= vsllink_speed_div
,
896 .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)