jtag interfaces: Reduce usage of global for jtag queue
[openocd.git] / src / jtag / drivers / bitbang.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2
3 /***************************************************************************
4 * Copyright (C) 2005 by Dominic Rath *
5 * Dominic.Rath@gmx.de *
6 * *
7 * Copyright (C) 2007,2008 Øyvind Harboe *
8 * oyvind.harboe@zylin.com *
9 ***************************************************************************/
10
11 /* 2014-12: Addition of the SWD protocol support is based on the initial work
12 * by Paul Fertser and modifications by Jean-Christian de Rivaz. */
13
14 #ifdef HAVE_CONFIG_H
15 #include "config.h"
16 #endif
17
18 #include <jtag/jtag.h> /* Added to avoid include loop in commands.h */
19 #include "bitbang.h"
20 #include <jtag/interface.h>
21 #include <jtag/commands.h>
22
23 /**
24 * Function bitbang_stableclocks
25 * issues a number of clock cycles while staying in a stable state.
26 * Because the TMS value required to stay in the RESET state is a 1, whereas
27 * the TMS value required to stay in any of the other stable states is a 0,
28 * this function checks the current stable state to decide on the value of TMS
29 * to use.
30 */
31 static int bitbang_stableclocks(int num_cycles);
32
33 static void bitbang_swd_write_reg(uint8_t cmd, uint32_t value, uint32_t ap_delay_clk);
34
35 struct bitbang_interface *bitbang_interface;
36
37 /* DANGER!!!! clock absolutely *MUST* be 0 in idle or reset won't work!
38 *
39 * Set this to 1 and str912 reset halt will fail.
40 *
41 * If someone can submit a patch with an explanation it will be greatly
42 * appreciated, but as far as I can tell (ØH) DCLK is generated upon
43 * clk = 0 in TAP_IDLE. Good luck deducing that from the ARM documentation!
44 * The ARM documentation uses the term "DCLK is asserted while in the TAP_IDLE
45 * state". With hardware there is no such thing as *while* in a state. There
46 * are only edges. So clk => 0 is in fact a very subtle state transition that
47 * happens *while* in the TAP_IDLE state. "#&¤"#¤&"#&"#&
48 *
49 * For "reset halt" the last thing that happens before srst is asserted
50 * is that the breakpoint is set up. If DCLK is not wiggled one last
51 * time before the reset, then the breakpoint is not set up and
52 * "reset halt" will fail to halt.
53 *
54 */
55 #define CLOCK_IDLE() 0
56
57 /* The bitbang driver leaves the TCK 0 when in idle */
58 static void bitbang_end_state(tap_state_t state)
59 {
60 assert(tap_is_state_stable(state));
61 tap_set_end_state(state);
62 }
63
64 static int bitbang_state_move(int skip)
65 {
66 int i = 0, tms = 0;
67 uint8_t tms_scan = tap_get_tms_path(tap_get_state(), tap_get_end_state());
68 int tms_count = tap_get_tms_path_len(tap_get_state(), tap_get_end_state());
69
70 for (i = skip; i < tms_count; i++) {
71 tms = (tms_scan >> i) & 1;
72 if (bitbang_interface->write(0, tms, 0) != ERROR_OK)
73 return ERROR_FAIL;
74 if (bitbang_interface->write(1, tms, 0) != ERROR_OK)
75 return ERROR_FAIL;
76 }
77 if (bitbang_interface->write(CLOCK_IDLE(), tms, 0) != ERROR_OK)
78 return ERROR_FAIL;
79
80 tap_set_state(tap_get_end_state());
81 return ERROR_OK;
82 }
83
84 /**
85 * Clock a bunch of TMS (or SWDIO) transitions, to change the JTAG
86 * (or SWD) state machine.
87 */
88 static int bitbang_execute_tms(struct jtag_command *cmd)
89 {
90 unsigned num_bits = cmd->cmd.tms->num_bits;
91 const uint8_t *bits = cmd->cmd.tms->bits;
92
93 LOG_DEBUG_IO("TMS: %d bits", num_bits);
94
95 int tms = 0;
96 for (unsigned i = 0; i < num_bits; i++) {
97 tms = ((bits[i/8] >> (i % 8)) & 1);
98 if (bitbang_interface->write(0, tms, 0) != ERROR_OK)
99 return ERROR_FAIL;
100 if (bitbang_interface->write(1, tms, 0) != ERROR_OK)
101 return ERROR_FAIL;
102 }
103 if (bitbang_interface->write(CLOCK_IDLE(), tms, 0) != ERROR_OK)
104 return ERROR_FAIL;
105
106 return ERROR_OK;
107 }
108
109 static int bitbang_path_move(struct pathmove_command *cmd)
110 {
111 int num_states = cmd->num_states;
112 int state_count;
113 int tms = 0;
114
115 state_count = 0;
116 while (num_states) {
117 if (tap_state_transition(tap_get_state(), false) == cmd->path[state_count])
118 tms = 0;
119 else if (tap_state_transition(tap_get_state(), true) == cmd->path[state_count])
120 tms = 1;
121 else {
122 LOG_ERROR("BUG: %s -> %s isn't a valid TAP transition",
123 tap_state_name(tap_get_state()),
124 tap_state_name(cmd->path[state_count]));
125 exit(-1);
126 }
127
128 if (bitbang_interface->write(0, tms, 0) != ERROR_OK)
129 return ERROR_FAIL;
130 if (bitbang_interface->write(1, tms, 0) != ERROR_OK)
131 return ERROR_FAIL;
132
133 tap_set_state(cmd->path[state_count]);
134 state_count++;
135 num_states--;
136 }
137
138 if (bitbang_interface->write(CLOCK_IDLE(), tms, 0) != ERROR_OK)
139 return ERROR_FAIL;
140
141 tap_set_end_state(tap_get_state());
142 return ERROR_OK;
143 }
144
145 static int bitbang_runtest(int num_cycles)
146 {
147 int i;
148
149 tap_state_t saved_end_state = tap_get_end_state();
150
151 /* only do a state_move when we're not already in IDLE */
152 if (tap_get_state() != TAP_IDLE) {
153 bitbang_end_state(TAP_IDLE);
154 if (bitbang_state_move(0) != ERROR_OK)
155 return ERROR_FAIL;
156 }
157
158 /* execute num_cycles */
159 for (i = 0; i < num_cycles; i++) {
160 if (bitbang_interface->write(0, 0, 0) != ERROR_OK)
161 return ERROR_FAIL;
162 if (bitbang_interface->write(1, 0, 0) != ERROR_OK)
163 return ERROR_FAIL;
164 }
165 if (bitbang_interface->write(CLOCK_IDLE(), 0, 0) != ERROR_OK)
166 return ERROR_FAIL;
167
168 /* finish in end_state */
169 bitbang_end_state(saved_end_state);
170 if (tap_get_state() != tap_get_end_state())
171 if (bitbang_state_move(0) != ERROR_OK)
172 return ERROR_FAIL;
173
174 return ERROR_OK;
175 }
176
177 static int bitbang_stableclocks(int num_cycles)
178 {
179 int tms = (tap_get_state() == TAP_RESET ? 1 : 0);
180 int i;
181
182 /* send num_cycles clocks onto the cable */
183 for (i = 0; i < num_cycles; i++) {
184 if (bitbang_interface->write(1, tms, 0) != ERROR_OK)
185 return ERROR_FAIL;
186 if (bitbang_interface->write(0, tms, 0) != ERROR_OK)
187 return ERROR_FAIL;
188 }
189
190 return ERROR_OK;
191 }
192
193 static int bitbang_scan(bool ir_scan, enum scan_type type, uint8_t *buffer,
194 unsigned scan_size)
195 {
196 tap_state_t saved_end_state = tap_get_end_state();
197 unsigned bit_cnt;
198
199 if (!((!ir_scan &&
200 (tap_get_state() == TAP_DRSHIFT)) ||
201 (ir_scan && (tap_get_state() == TAP_IRSHIFT)))) {
202 if (ir_scan)
203 bitbang_end_state(TAP_IRSHIFT);
204 else
205 bitbang_end_state(TAP_DRSHIFT);
206
207 if (bitbang_state_move(0) != ERROR_OK)
208 return ERROR_FAIL;
209 bitbang_end_state(saved_end_state);
210 }
211
212 size_t buffered = 0;
213 for (bit_cnt = 0; bit_cnt < scan_size; bit_cnt++) {
214 int tms = (bit_cnt == scan_size-1) ? 1 : 0;
215 int tdi;
216 int bytec = bit_cnt/8;
217 int bcval = 1 << (bit_cnt % 8);
218
219 /* if we're just reading the scan, but don't care about the output
220 * default to outputting 'low', this also makes valgrind traces more readable,
221 * as it removes the dependency on an uninitialised value
222 */
223 tdi = 0;
224 if ((type != SCAN_IN) && (buffer[bytec] & bcval))
225 tdi = 1;
226
227 if (bitbang_interface->write(0, tms, tdi) != ERROR_OK)
228 return ERROR_FAIL;
229
230 if (type != SCAN_OUT) {
231 if (bitbang_interface->buf_size) {
232 if (bitbang_interface->sample() != ERROR_OK)
233 return ERROR_FAIL;
234 buffered++;
235 } else {
236 switch (bitbang_interface->read()) {
237 case BB_LOW:
238 buffer[bytec] &= ~bcval;
239 break;
240 case BB_HIGH:
241 buffer[bytec] |= bcval;
242 break;
243 default:
244 return ERROR_FAIL;
245 }
246 }
247 }
248
249 if (bitbang_interface->write(1, tms, tdi) != ERROR_OK)
250 return ERROR_FAIL;
251
252 if (type != SCAN_OUT && bitbang_interface->buf_size &&
253 (buffered == bitbang_interface->buf_size ||
254 bit_cnt == scan_size - 1)) {
255 for (unsigned i = bit_cnt + 1 - buffered; i <= bit_cnt; i++) {
256 switch (bitbang_interface->read_sample()) {
257 case BB_LOW:
258 buffer[i/8] &= ~(1 << (i % 8));
259 break;
260 case BB_HIGH:
261 buffer[i/8] |= 1 << (i % 8);
262 break;
263 default:
264 return ERROR_FAIL;
265 }
266 }
267 buffered = 0;
268 }
269 }
270
271 if (tap_get_state() != tap_get_end_state()) {
272 /* we *KNOW* the above loop transitioned out of
273 * the shift state, so we skip the first state
274 * and move directly to the end state.
275 */
276 if (bitbang_state_move(1) != ERROR_OK)
277 return ERROR_FAIL;
278 }
279 return ERROR_OK;
280 }
281
282 static void bitbang_sleep(unsigned int microseconds)
283 {
284 if (bitbang_interface->sleep) {
285 bitbang_interface->sleep(microseconds);
286 } else {
287 jtag_sleep(microseconds);
288 }
289 }
290
291 int bitbang_execute_queue(struct jtag_command *cmd_queue)
292 {
293 struct jtag_command *cmd = cmd_queue; /* currently processed command */
294 int scan_size;
295 enum scan_type type;
296 uint8_t *buffer;
297 int retval;
298
299 if (!bitbang_interface) {
300 LOG_ERROR("BUG: Bitbang interface called, but not yet initialized");
301 exit(-1);
302 }
303
304 /* return ERROR_OK, unless a jtag_read_buffer returns a failed check
305 * that wasn't handled by a caller-provided error handler
306 */
307 retval = ERROR_OK;
308
309 if (bitbang_interface->blink) {
310 if (bitbang_interface->blink(1) != ERROR_OK)
311 return ERROR_FAIL;
312 }
313
314 while (cmd) {
315 switch (cmd->type) {
316 case JTAG_RUNTEST:
317 LOG_DEBUG_IO("runtest %i cycles, end in %s",
318 cmd->cmd.runtest->num_cycles,
319 tap_state_name(cmd->cmd.runtest->end_state));
320 bitbang_end_state(cmd->cmd.runtest->end_state);
321 if (bitbang_runtest(cmd->cmd.runtest->num_cycles) != ERROR_OK)
322 return ERROR_FAIL;
323 break;
324
325 case JTAG_STABLECLOCKS:
326 /* this is only allowed while in a stable state. A check for a stable
327 * state was done in jtag_add_clocks()
328 */
329 if (bitbang_stableclocks(cmd->cmd.stableclocks->num_cycles) != ERROR_OK)
330 return ERROR_FAIL;
331 break;
332
333 case JTAG_TLR_RESET:
334 LOG_DEBUG_IO("statemove end in %s",
335 tap_state_name(cmd->cmd.statemove->end_state));
336 bitbang_end_state(cmd->cmd.statemove->end_state);
337 if (bitbang_state_move(0) != ERROR_OK)
338 return ERROR_FAIL;
339 break;
340 case JTAG_PATHMOVE:
341 LOG_DEBUG_IO("pathmove: %i states, end in %s",
342 cmd->cmd.pathmove->num_states,
343 tap_state_name(cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]));
344 if (bitbang_path_move(cmd->cmd.pathmove) != ERROR_OK)
345 return ERROR_FAIL;
346 break;
347 case JTAG_SCAN:
348 bitbang_end_state(cmd->cmd.scan->end_state);
349 scan_size = jtag_build_buffer(cmd->cmd.scan, &buffer);
350 LOG_DEBUG_IO("%s scan %d bits; end in %s",
351 (cmd->cmd.scan->ir_scan) ? "IR" : "DR",
352 scan_size,
353 tap_state_name(cmd->cmd.scan->end_state));
354 type = jtag_scan_type(cmd->cmd.scan);
355 if (bitbang_scan(cmd->cmd.scan->ir_scan, type, buffer,
356 scan_size) != ERROR_OK)
357 return ERROR_FAIL;
358 if (jtag_read_buffer(buffer, cmd->cmd.scan) != ERROR_OK)
359 retval = ERROR_JTAG_QUEUE_FAILED;
360 free(buffer);
361 break;
362 case JTAG_SLEEP:
363 LOG_DEBUG_IO("sleep %" PRIu32, cmd->cmd.sleep->us);
364 if (bitbang_interface->flush && (bitbang_interface->flush() != ERROR_OK))
365 return ERROR_FAIL;
366 bitbang_sleep(cmd->cmd.sleep->us);
367 break;
368 case JTAG_TMS:
369 retval = bitbang_execute_tms(cmd);
370 break;
371 default:
372 LOG_ERROR("BUG: unknown JTAG command type encountered");
373 exit(-1);
374 }
375 cmd = cmd->next;
376 }
377 if (bitbang_interface->blink) {
378 if (bitbang_interface->blink(0) != ERROR_OK)
379 return ERROR_FAIL;
380 }
381
382 return retval;
383 }
384
385 static int queued_retval;
386
387 static int bitbang_swd_init(void)
388 {
389 LOG_DEBUG("bitbang_swd_init");
390 return ERROR_OK;
391 }
392
393 static void bitbang_swd_exchange(bool rnw, uint8_t buf[], unsigned int offset, unsigned int bit_cnt)
394 {
395 if (bitbang_interface->blink) {
396 /* FIXME: we should manage errors */
397 bitbang_interface->blink(1);
398 }
399
400 for (unsigned int i = offset; i < bit_cnt + offset; i++) {
401 int bytec = i/8;
402 int bcval = 1 << (i % 8);
403 int swdio = !rnw && (buf[bytec] & bcval);
404
405 bitbang_interface->swd_write(0, swdio);
406
407 if (rnw && buf) {
408 if (bitbang_interface->swdio_read())
409 buf[bytec] |= bcval;
410 else
411 buf[bytec] &= ~bcval;
412 }
413
414 bitbang_interface->swd_write(1, swdio);
415 }
416
417 if (bitbang_interface->blink) {
418 /* FIXME: we should manage errors */
419 bitbang_interface->blink(0);
420 }
421 }
422
423 static int bitbang_swd_switch_seq(enum swd_special_seq seq)
424 {
425 switch (seq) {
426 case LINE_RESET:
427 LOG_DEBUG_IO("SWD line reset");
428 bitbang_swd_exchange(false, (uint8_t *)swd_seq_line_reset, 0, swd_seq_line_reset_len);
429 break;
430 case JTAG_TO_SWD:
431 LOG_DEBUG("JTAG-to-SWD");
432 bitbang_swd_exchange(false, (uint8_t *)swd_seq_jtag_to_swd, 0, swd_seq_jtag_to_swd_len);
433 break;
434 case JTAG_TO_DORMANT:
435 LOG_DEBUG("JTAG-to-DORMANT");
436 bitbang_swd_exchange(false, (uint8_t *)swd_seq_jtag_to_dormant, 0, swd_seq_jtag_to_dormant_len);
437 break;
438 case SWD_TO_JTAG:
439 LOG_DEBUG("SWD-to-JTAG");
440 bitbang_swd_exchange(false, (uint8_t *)swd_seq_swd_to_jtag, 0, swd_seq_swd_to_jtag_len);
441 break;
442 case SWD_TO_DORMANT:
443 LOG_DEBUG("SWD-to-DORMANT");
444 bitbang_swd_exchange(false, (uint8_t *)swd_seq_swd_to_dormant, 0, swd_seq_swd_to_dormant_len);
445 break;
446 case DORMANT_TO_SWD:
447 LOG_DEBUG("DORMANT-to-SWD");
448 bitbang_swd_exchange(false, (uint8_t *)swd_seq_dormant_to_swd, 0, swd_seq_dormant_to_swd_len);
449 break;
450 case DORMANT_TO_JTAG:
451 LOG_DEBUG("DORMANT-to-JTAG");
452 bitbang_swd_exchange(false, (uint8_t *)swd_seq_dormant_to_jtag, 0, swd_seq_dormant_to_jtag_len);
453 break;
454 default:
455 LOG_ERROR("Sequence %d not supported", seq);
456 return ERROR_FAIL;
457 }
458
459 return ERROR_OK;
460 }
461
462 static void swd_clear_sticky_errors(void)
463 {
464 bitbang_swd_write_reg(swd_cmd(false, false, DP_ABORT),
465 STKCMPCLR | STKERRCLR | WDERRCLR | ORUNERRCLR, 0);
466 }
467
468 static void bitbang_swd_read_reg(uint8_t cmd, uint32_t *value, uint32_t ap_delay_clk)
469 {
470 assert(cmd & SWD_CMD_RNW);
471
472 if (queued_retval != ERROR_OK) {
473 LOG_DEBUG("Skip bitbang_swd_read_reg because queued_retval=%d", queued_retval);
474 return;
475 }
476
477 for (;;) {
478 uint8_t trn_ack_data_parity_trn[DIV_ROUND_UP(4 + 3 + 32 + 1 + 4, 8)];
479
480 cmd |= SWD_CMD_START | SWD_CMD_PARK;
481 bitbang_swd_exchange(false, &cmd, 0, 8);
482
483 bitbang_interface->swdio_drive(false);
484 bitbang_swd_exchange(true, trn_ack_data_parity_trn, 0, 1 + 3 + 32 + 1 + 1);
485 bitbang_interface->swdio_drive(true);
486
487 int ack = buf_get_u32(trn_ack_data_parity_trn, 1, 3);
488 uint32_t data = buf_get_u32(trn_ack_data_parity_trn, 1 + 3, 32);
489 int parity = buf_get_u32(trn_ack_data_parity_trn, 1 + 3 + 32, 1);
490
491 LOG_DEBUG_IO("%s %s read reg %X = %08" PRIx32,
492 ack == SWD_ACK_OK ? "OK" : ack == SWD_ACK_WAIT ? "WAIT" : ack == SWD_ACK_FAULT ? "FAULT" : "JUNK",
493 cmd & SWD_CMD_APNDP ? "AP" : "DP",
494 (cmd & SWD_CMD_A32) >> 1,
495 data);
496
497 if (ack == SWD_ACK_WAIT) {
498 swd_clear_sticky_errors();
499 continue;
500 } else if (ack != SWD_ACK_OK) {
501 queued_retval = swd_ack_to_error_code(ack);
502 return;
503 }
504
505 if (parity != parity_u32(data)) {
506 LOG_ERROR("Wrong parity detected");
507 queued_retval = ERROR_FAIL;
508 return;
509 }
510 if (value)
511 *value = data;
512 if (cmd & SWD_CMD_APNDP)
513 bitbang_swd_exchange(true, NULL, 0, ap_delay_clk);
514 return;
515 }
516 }
517
518 static void bitbang_swd_write_reg(uint8_t cmd, uint32_t value, uint32_t ap_delay_clk)
519 {
520 assert(!(cmd & SWD_CMD_RNW));
521
522 if (queued_retval != ERROR_OK) {
523 LOG_DEBUG("Skip bitbang_swd_write_reg because queued_retval=%d", queued_retval);
524 return;
525 }
526
527 /* Devices do not reply to DP_TARGETSEL write cmd, ignore received ack */
528 bool check_ack = swd_cmd_returns_ack(cmd);
529
530 /* init the array to silence scan-build */
531 uint8_t trn_ack_data_parity_trn[DIV_ROUND_UP(4 + 3 + 32 + 1 + 4, 8)] = {0};
532 for (;;) {
533 buf_set_u32(trn_ack_data_parity_trn, 1 + 3 + 1, 32, value);
534 buf_set_u32(trn_ack_data_parity_trn, 1 + 3 + 1 + 32, 1, parity_u32(value));
535
536 cmd |= SWD_CMD_START | SWD_CMD_PARK;
537 bitbang_swd_exchange(false, &cmd, 0, 8);
538
539 bitbang_interface->swdio_drive(false);
540 bitbang_swd_exchange(true, trn_ack_data_parity_trn, 0, 1 + 3);
541
542 /* Avoid a glitch on SWDIO when changing the direction to output.
543 * To keep performance penalty minimal, pre-write the first data
544 * bit to SWDIO GPIO output buffer while clocking the turnaround bit.
545 * Following swdio_drive(true) outputs the pre-written value
546 * and the same value is rewritten by the next swd_write()
547 * instead of glitching SWDIO
548 * HiZ/pull-up --------------> 0 -------------> 1
549 * swdio_drive(true) swd_write(0,1)
550 * in case of data bit 0 = 1
551 */
552 bitbang_swd_exchange(false, trn_ack_data_parity_trn, 1 + 3 + 1, 1);
553 bitbang_interface->swdio_drive(true);
554 bitbang_swd_exchange(false, trn_ack_data_parity_trn, 1 + 3 + 1, 32 + 1);
555
556 int ack = buf_get_u32(trn_ack_data_parity_trn, 1, 3);
557
558 LOG_DEBUG_IO("%s%s %s write reg %X = %08" PRIx32,
559 check_ack ? "" : "ack ignored ",
560 ack == SWD_ACK_OK ? "OK" : ack == SWD_ACK_WAIT ? "WAIT" : ack == SWD_ACK_FAULT ? "FAULT" : "JUNK",
561 cmd & SWD_CMD_APNDP ? "AP" : "DP",
562 (cmd & SWD_CMD_A32) >> 1,
563 buf_get_u32(trn_ack_data_parity_trn, 1 + 3 + 1, 32));
564
565 if (check_ack) {
566 if (ack == SWD_ACK_WAIT) {
567 swd_clear_sticky_errors();
568 continue;
569 } else if (ack != SWD_ACK_OK) {
570 queued_retval = swd_ack_to_error_code(ack);
571 return;
572 }
573 }
574
575 if (cmd & SWD_CMD_APNDP)
576 bitbang_swd_exchange(true, NULL, 0, ap_delay_clk);
577 return;
578 }
579 }
580
581 static int bitbang_swd_run_queue(void)
582 {
583 /* A transaction must be followed by another transaction or at least 8 idle cycles to
584 * ensure that data is clocked through the AP. */
585 bitbang_swd_exchange(true, NULL, 0, 8);
586
587 int retval = queued_retval;
588 queued_retval = ERROR_OK;
589 LOG_DEBUG_IO("SWD queue return value: %02x", retval);
590 return retval;
591 }
592
593 const struct swd_driver bitbang_swd = {
594 .init = bitbang_swd_init,
595 .switch_seq = bitbang_swd_switch_seq,
596 .read_reg = bitbang_swd_read_reg,
597 .write_reg = bitbang_swd_write_reg,
598 .run = bitbang_swd_run_queue,
599 };

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)