47a1d794b3bcfd65b86f1363de5b481e2126b620
[openocd.git] / src / jtag / adapter.c
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 /*
3 * Copyright (C) 2005 by Dominic Rath <Dominic.Rath@gmx.de>
4 * Copyright (C) 2007-2010 Øyvind Harboe <oyvind.harboe@zylin.com>
5 * Copyright (C) 2009 SoftPLC Corporation, http://softplc.com, Dick Hollenbeck <dick@softplc.com>
6 * Copyright (C) 2009 Zachary T Welch <zw@superlucidity.net>
7 * Copyright (C) 2018 Pengutronix, Oleksij Rempel <kernel@pengutronix.de>
8 */
9
10 #ifdef HAVE_CONFIG_H
11 #include "config.h"
12 #endif
13
14 #include "adapter.h"
15 #include "jtag.h"
16 #include "minidriver.h"
17 #include "interface.h"
18 #include "interfaces.h"
19 #include <transport/transport.h>
20
21 #ifdef HAVE_STRINGS_H
22 #include <strings.h>
23 #endif
24
25 /**
26 * @file
27 * Holds support for configuring debug adapters from TCl scripts.
28 */
29
30 struct adapter_driver *adapter_driver;
31 const char * const jtag_only[] = { "jtag", NULL };
32
33 /**
34 * Adapter configuration
35 */
36 static struct {
37 char *usb_location;
38 } adapter_config;
39
40 /*
41 * 1 char: bus
42 * 2 * 7 chars: max 7 ports
43 * 1 char: test for overflow
44 * ------
45 * 16 chars
46 */
47 #define USB_MAX_LOCATION_LENGTH 16
48
49 #ifdef HAVE_LIBUSB_GET_PORT_NUMBERS
50 static void adapter_usb_set_location(const char *location)
51 {
52 if (strnlen(location, USB_MAX_LOCATION_LENGTH) == USB_MAX_LOCATION_LENGTH)
53 LOG_WARNING("usb location string is too long!!");
54
55 free(adapter_config.usb_location);
56
57 adapter_config.usb_location = strndup(location, USB_MAX_LOCATION_LENGTH);
58 }
59 #endif /* HAVE_LIBUSB_GET_PORT_NUMBERS */
60
61 const char *adapter_usb_get_location(void)
62 {
63 return adapter_config.usb_location;
64 }
65
66 bool adapter_usb_location_equal(uint8_t dev_bus, uint8_t *port_path, size_t path_len)
67 {
68 size_t path_step, string_length;
69 char *ptr, *loc;
70 bool equal = false;
71
72 if (!adapter_usb_get_location())
73 return equal;
74
75 /* strtok need non const char */
76 loc = strndup(adapter_usb_get_location(), USB_MAX_LOCATION_LENGTH);
77 string_length = strnlen(loc, USB_MAX_LOCATION_LENGTH);
78
79 ptr = strtok(loc, "-");
80 if (!ptr) {
81 LOG_WARNING("no '-' in usb path\n");
82 goto done;
83 }
84
85 string_length -= strnlen(ptr, string_length);
86 /* check bus mismatch */
87 if (atoi(ptr) != dev_bus)
88 goto done;
89
90 path_step = 0;
91 while (path_step < path_len) {
92 ptr = strtok(NULL, ".");
93
94 /* no more tokens in path */
95 if (!ptr)
96 break;
97
98 /* path mismatch at some step */
99 if (path_step < path_len && atoi(ptr) != port_path[path_step])
100 break;
101
102 path_step++;
103 string_length -= strnlen(ptr, string_length) + 1;
104 };
105
106 /* walked the full path, all elements match */
107 if (path_step == path_len && !string_length)
108 equal = true;
109
110 done:
111 free(loc);
112 return equal;
113 }
114
115 static int jim_adapter_name(Jim_Interp *interp, int argc, Jim_Obj * const *argv)
116 {
117 struct jim_getopt_info goi;
118 jim_getopt_setup(&goi, interp, argc-1, argv + 1);
119
120 /* return the name of the interface */
121 /* TCL code might need to know the exact type... */
122 /* FUTURE: we allow this as a means to "set" the interface. */
123 if (goi.argc != 0) {
124 Jim_WrongNumArgs(goi.interp, 1, goi.argv-1, "(no params)");
125 return JIM_ERR;
126 }
127 const char *name = adapter_driver ? adapter_driver->name : NULL;
128 Jim_SetResultString(goi.interp, name ? name : "undefined", -1);
129 return JIM_OK;
130 }
131
132 COMMAND_HANDLER(adapter_transports_command)
133 {
134 char **transports;
135 int retval;
136
137 retval = CALL_COMMAND_HANDLER(transport_list_parse, &transports);
138 if (retval != ERROR_OK)
139 return retval;
140
141 retval = allow_transports(CMD_CTX, (const char **)transports);
142
143 if (retval != ERROR_OK) {
144 for (unsigned i = 0; transports[i]; i++)
145 free(transports[i]);
146 free(transports);
147 }
148 return retval;
149 }
150
151 COMMAND_HANDLER(handle_adapter_list_command)
152 {
153 if (strcmp(CMD_NAME, "list") == 0 && CMD_ARGC > 0)
154 return ERROR_COMMAND_SYNTAX_ERROR;
155
156 command_print(CMD, "The following debug adapters are available:");
157 for (unsigned i = 0; adapter_drivers[i]; i++) {
158 const char *name = adapter_drivers[i]->name;
159 command_print(CMD, "%u: %s", i + 1, name);
160 }
161
162 return ERROR_OK;
163 }
164
165 COMMAND_HANDLER(handle_adapter_driver_command)
166 {
167 int retval;
168
169 /* check whether the interface is already configured */
170 if (adapter_driver) {
171 LOG_WARNING("Interface already configured, ignoring");
172 return ERROR_OK;
173 }
174
175 /* interface name is a mandatory argument */
176 if (CMD_ARGC != 1 || CMD_ARGV[0][0] == '\0')
177 return ERROR_COMMAND_SYNTAX_ERROR;
178
179 for (unsigned i = 0; adapter_drivers[i]; i++) {
180 if (strcmp(CMD_ARGV[0], adapter_drivers[i]->name) != 0)
181 continue;
182
183 if (adapter_drivers[i]->commands) {
184 retval = register_commands(CMD_CTX, NULL,
185 adapter_drivers[i]->commands);
186 if (retval != ERROR_OK)
187 return retval;
188 }
189
190 adapter_driver = adapter_drivers[i];
191
192 return allow_transports(CMD_CTX, adapter_driver->transports);
193 }
194
195 /* no valid interface was found (i.e. the configuration option,
196 * didn't match one of the compiled-in interfaces
197 */
198 LOG_ERROR("The specified debug interface was not found (%s)",
199 CMD_ARGV[0]);
200 CALL_COMMAND_HANDLER(handle_adapter_list_command);
201 return ERROR_JTAG_INVALID_INTERFACE;
202 }
203
204 COMMAND_HANDLER(handle_reset_config_command)
205 {
206 int new_cfg = 0;
207 int mask = 0;
208
209 /* Original versions cared about the order of these tokens:
210 * reset_config signals [combination [trst_type [srst_type]]]
211 * They also clobbered the previous configuration even on error.
212 *
213 * Here we don't care about the order, and only change values
214 * which have been explicitly specified.
215 */
216 for (; CMD_ARGC; CMD_ARGC--, CMD_ARGV++) {
217 int tmp = 0;
218 int m;
219
220 /* gating */
221 m = RESET_SRST_NO_GATING;
222 if (strcmp(*CMD_ARGV, "srst_gates_jtag") == 0)
223 /* default: don't use JTAG while SRST asserted */;
224 else if (strcmp(*CMD_ARGV, "srst_nogate") == 0)
225 tmp = RESET_SRST_NO_GATING;
226 else
227 m = 0;
228 if (mask & m) {
229 LOG_ERROR("extra reset_config %s spec (%s)",
230 "gating", *CMD_ARGV);
231 return ERROR_COMMAND_SYNTAX_ERROR;
232 }
233 if (m)
234 goto next;
235
236 /* signals */
237 m = RESET_HAS_TRST | RESET_HAS_SRST;
238 if (strcmp(*CMD_ARGV, "none") == 0)
239 tmp = RESET_NONE;
240 else if (strcmp(*CMD_ARGV, "trst_only") == 0)
241 tmp = RESET_HAS_TRST;
242 else if (strcmp(*CMD_ARGV, "srst_only") == 0)
243 tmp = RESET_HAS_SRST;
244 else if (strcmp(*CMD_ARGV, "trst_and_srst") == 0)
245 tmp = RESET_HAS_TRST | RESET_HAS_SRST;
246 else
247 m = 0;
248 if (mask & m) {
249 LOG_ERROR("extra reset_config %s spec (%s)",
250 "signal", *CMD_ARGV);
251 return ERROR_COMMAND_SYNTAX_ERROR;
252 }
253 if (m)
254 goto next;
255
256 /* combination (options for broken wiring) */
257 m = RESET_SRST_PULLS_TRST | RESET_TRST_PULLS_SRST;
258 if (strcmp(*CMD_ARGV, "separate") == 0)
259 /* separate reset lines - default */;
260 else if (strcmp(*CMD_ARGV, "srst_pulls_trst") == 0)
261 tmp |= RESET_SRST_PULLS_TRST;
262 else if (strcmp(*CMD_ARGV, "trst_pulls_srst") == 0)
263 tmp |= RESET_TRST_PULLS_SRST;
264 else if (strcmp(*CMD_ARGV, "combined") == 0)
265 tmp |= RESET_SRST_PULLS_TRST | RESET_TRST_PULLS_SRST;
266 else
267 m = 0;
268 if (mask & m) {
269 LOG_ERROR("extra reset_config %s spec (%s)",
270 "combination", *CMD_ARGV);
271 return ERROR_COMMAND_SYNTAX_ERROR;
272 }
273 if (m)
274 goto next;
275
276 /* trst_type (NOP without HAS_TRST) */
277 m = RESET_TRST_OPEN_DRAIN;
278 if (strcmp(*CMD_ARGV, "trst_open_drain") == 0)
279 tmp |= RESET_TRST_OPEN_DRAIN;
280 else if (strcmp(*CMD_ARGV, "trst_push_pull") == 0)
281 /* push/pull from adapter - default */;
282 else
283 m = 0;
284 if (mask & m) {
285 LOG_ERROR("extra reset_config %s spec (%s)",
286 "trst_type", *CMD_ARGV);
287 return ERROR_COMMAND_SYNTAX_ERROR;
288 }
289 if (m)
290 goto next;
291
292 /* srst_type (NOP without HAS_SRST) */
293 m = RESET_SRST_PUSH_PULL;
294 if (strcmp(*CMD_ARGV, "srst_push_pull") == 0)
295 tmp |= RESET_SRST_PUSH_PULL;
296 else if (strcmp(*CMD_ARGV, "srst_open_drain") == 0)
297 /* open drain from adapter - default */;
298 else
299 m = 0;
300 if (mask & m) {
301 LOG_ERROR("extra reset_config %s spec (%s)",
302 "srst_type", *CMD_ARGV);
303 return ERROR_COMMAND_SYNTAX_ERROR;
304 }
305 if (m)
306 goto next;
307
308 /* connect_type - only valid when srst_nogate */
309 m = RESET_CNCT_UNDER_SRST;
310 if (strcmp(*CMD_ARGV, "connect_assert_srst") == 0)
311 tmp |= RESET_CNCT_UNDER_SRST;
312 else if (strcmp(*CMD_ARGV, "connect_deassert_srst") == 0)
313 /* connect normally - default */;
314 else
315 m = 0;
316 if (mask & m) {
317 LOG_ERROR("extra reset_config %s spec (%s)",
318 "connect_type", *CMD_ARGV);
319 return ERROR_COMMAND_SYNTAX_ERROR;
320 }
321 if (m)
322 goto next;
323
324 /* caller provided nonsense; fail */
325 LOG_ERROR("unknown reset_config flag (%s)", *CMD_ARGV);
326 return ERROR_COMMAND_SYNTAX_ERROR;
327
328 next:
329 /* Remember the bits which were specified (mask)
330 * and their new values (new_cfg).
331 */
332 mask |= m;
333 new_cfg |= tmp;
334 }
335
336 /* clear previous values of those bits, save new values */
337 if (mask) {
338 int old_cfg = jtag_get_reset_config();
339
340 old_cfg &= ~mask;
341 new_cfg |= old_cfg;
342 jtag_set_reset_config(new_cfg);
343 } else
344 new_cfg = jtag_get_reset_config();
345
346 /*
347 * Display the (now-)current reset mode
348 */
349 char *modes[6];
350
351 /* minimal JTAG has neither SRST nor TRST (so that's the default) */
352 switch (new_cfg & (RESET_HAS_TRST | RESET_HAS_SRST)) {
353 case RESET_HAS_SRST:
354 modes[0] = "srst_only";
355 break;
356 case RESET_HAS_TRST:
357 modes[0] = "trst_only";
358 break;
359 case RESET_TRST_AND_SRST:
360 modes[0] = "trst_and_srst";
361 break;
362 default:
363 modes[0] = "none";
364 break;
365 }
366
367 /* normally SRST and TRST are decoupled; but bugs happen ... */
368 switch (new_cfg & (RESET_SRST_PULLS_TRST | RESET_TRST_PULLS_SRST)) {
369 case RESET_SRST_PULLS_TRST:
370 modes[1] = "srst_pulls_trst";
371 break;
372 case RESET_TRST_PULLS_SRST:
373 modes[1] = "trst_pulls_srst";
374 break;
375 case RESET_SRST_PULLS_TRST | RESET_TRST_PULLS_SRST:
376 modes[1] = "combined";
377 break;
378 default:
379 modes[1] = "separate";
380 break;
381 }
382
383 /* TRST-less connectors include Altera, Xilinx, and minimal JTAG */
384 if (new_cfg & RESET_HAS_TRST) {
385 if (new_cfg & RESET_TRST_OPEN_DRAIN)
386 modes[3] = " trst_open_drain";
387 else
388 modes[3] = " trst_push_pull";
389 } else
390 modes[3] = "";
391
392 /* SRST-less connectors include TI-14, Xilinx, and minimal JTAG */
393 if (new_cfg & RESET_HAS_SRST) {
394 if (new_cfg & RESET_SRST_NO_GATING)
395 modes[2] = " srst_nogate";
396 else
397 modes[2] = " srst_gates_jtag";
398
399 if (new_cfg & RESET_SRST_PUSH_PULL)
400 modes[4] = " srst_push_pull";
401 else
402 modes[4] = " srst_open_drain";
403
404 if (new_cfg & RESET_CNCT_UNDER_SRST)
405 modes[5] = " connect_assert_srst";
406 else
407 modes[5] = " connect_deassert_srst";
408 } else {
409 modes[2] = "";
410 modes[4] = "";
411 modes[5] = "";
412 }
413
414 command_print(CMD, "%s %s%s%s%s%s",
415 modes[0], modes[1],
416 modes[2], modes[3], modes[4], modes[5]);
417
418 return ERROR_OK;
419 }
420
421 COMMAND_HANDLER(handle_adapter_srst_delay_command)
422 {
423 if (CMD_ARGC > 1)
424 return ERROR_COMMAND_SYNTAX_ERROR;
425 if (CMD_ARGC == 1) {
426 unsigned delay;
427 COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], delay);
428
429 jtag_set_nsrst_delay(delay);
430 }
431 command_print(CMD, "adapter srst delay: %u", jtag_get_nsrst_delay());
432 return ERROR_OK;
433 }
434
435 COMMAND_HANDLER(handle_adapter_srst_pulse_width_command)
436 {
437 if (CMD_ARGC > 1)
438 return ERROR_COMMAND_SYNTAX_ERROR;
439 if (CMD_ARGC == 1) {
440 unsigned width;
441 COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], width);
442
443 jtag_set_nsrst_assert_width(width);
444 }
445 command_print(CMD, "adapter srst pulse_width: %u", jtag_get_nsrst_assert_width());
446 return ERROR_OK;
447 }
448
449 COMMAND_HANDLER(handle_adapter_speed_command)
450 {
451 if (CMD_ARGC > 1)
452 return ERROR_COMMAND_SYNTAX_ERROR;
453
454 int retval = ERROR_OK;
455 if (CMD_ARGC == 1) {
456 unsigned khz = 0;
457 COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], khz);
458
459 retval = jtag_config_khz(khz);
460 if (retval != ERROR_OK)
461 return retval;
462 }
463
464 int cur_speed = jtag_get_speed_khz();
465 retval = jtag_get_speed_readable(&cur_speed);
466 if (retval != ERROR_OK)
467 return retval;
468
469 if (cur_speed)
470 command_print(CMD, "adapter speed: %d kHz", cur_speed);
471 else
472 command_print(CMD, "adapter speed: RCLK - adaptive");
473
474 return retval;
475 }
476
477 COMMAND_HANDLER(handle_adapter_reset_de_assert)
478 {
479 enum values {
480 VALUE_UNDEFINED = -1,
481 VALUE_DEASSERT = 0,
482 VALUE_ASSERT = 1,
483 };
484 enum values value;
485 enum values srst = VALUE_UNDEFINED;
486 enum values trst = VALUE_UNDEFINED;
487 enum reset_types jtag_reset_config = jtag_get_reset_config();
488 char *signal;
489
490 if (CMD_ARGC == 0) {
491 if (transport_is_jtag()) {
492 if (jtag_reset_config & RESET_HAS_TRST)
493 signal = jtag_get_trst() ? "asserted" : "deasserted";
494 else
495 signal = "not present";
496 command_print(CMD, "trst %s", signal);
497 }
498
499 if (jtag_reset_config & RESET_HAS_SRST)
500 signal = jtag_get_srst() ? "asserted" : "deasserted";
501 else
502 signal = "not present";
503 command_print(CMD, "srst %s", signal);
504
505 return ERROR_OK;
506 }
507
508 if (CMD_ARGC != 1 && CMD_ARGC != 3)
509 return ERROR_COMMAND_SYNTAX_ERROR;
510
511 value = (strcmp(CMD_NAME, "assert") == 0) ? VALUE_ASSERT : VALUE_DEASSERT;
512 if (strcmp(CMD_ARGV[0], "srst") == 0)
513 srst = value;
514 else if (strcmp(CMD_ARGV[0], "trst") == 0)
515 trst = value;
516 else
517 return ERROR_COMMAND_SYNTAX_ERROR;
518
519 if (CMD_ARGC == 3) {
520 if (strcmp(CMD_ARGV[1], "assert") == 0)
521 value = VALUE_ASSERT;
522 else if (strcmp(CMD_ARGV[1], "deassert") == 0)
523 value = VALUE_DEASSERT;
524 else
525 return ERROR_COMMAND_SYNTAX_ERROR;
526
527 if (strcmp(CMD_ARGV[2], "srst") == 0 && srst == VALUE_UNDEFINED)
528 srst = value;
529 else if (strcmp(CMD_ARGV[2], "trst") == 0 && trst == VALUE_UNDEFINED)
530 trst = value;
531 else
532 return ERROR_COMMAND_SYNTAX_ERROR;
533 }
534
535 if (trst == VALUE_UNDEFINED) {
536 if (transport_is_jtag())
537 trst = jtag_get_trst() ? VALUE_ASSERT : VALUE_DEASSERT;
538 else
539 trst = VALUE_DEASSERT; /* unused, safe value */
540 }
541
542 if (srst == VALUE_UNDEFINED) {
543 if (jtag_reset_config & RESET_HAS_SRST)
544 srst = jtag_get_srst() ? VALUE_ASSERT : VALUE_DEASSERT;
545 else
546 srst = VALUE_DEASSERT; /* unused, safe value */
547 }
548
549 if (trst == VALUE_ASSERT && !transport_is_jtag()) {
550 LOG_ERROR("transport has no trst signal");
551 return ERROR_FAIL;
552 }
553
554 if (srst == VALUE_ASSERT && !(jtag_reset_config & RESET_HAS_SRST)) {
555 LOG_ERROR("adapter has no srst signal");
556 return ERROR_FAIL;
557 }
558
559 return adapter_resets((trst == VALUE_DEASSERT) ? TRST_DEASSERT : TRST_ASSERT,
560 (srst == VALUE_DEASSERT) ? SRST_DEASSERT : SRST_ASSERT);
561 }
562
563 #ifdef HAVE_LIBUSB_GET_PORT_NUMBERS
564 COMMAND_HANDLER(handle_usb_location_command)
565 {
566 if (CMD_ARGC == 1)
567 adapter_usb_set_location(CMD_ARGV[0]);
568
569 command_print(CMD, "adapter usb location: %s", adapter_usb_get_location());
570
571 return ERROR_OK;
572 }
573 #endif /* HAVE_LIBUSB_GET_PORT_NUMBERS */
574
575 static const struct command_registration adapter_usb_command_handlers[] = {
576 #ifdef HAVE_LIBUSB_GET_PORT_NUMBERS
577 {
578 .name = "location",
579 .handler = &handle_usb_location_command,
580 .mode = COMMAND_CONFIG,
581 .help = "display or set the USB bus location of the USB device",
582 .usage = "[<bus>-port[.port]...]",
583 },
584 #endif /* HAVE_LIBUSB_GET_PORT_NUMBERS */
585 COMMAND_REGISTRATION_DONE
586 };
587
588 static const struct command_registration adapter_srst_command_handlers[] = {
589 {
590 .name = "delay",
591 .handler = handle_adapter_srst_delay_command,
592 .mode = COMMAND_ANY,
593 .help = "delay after deasserting SRST in ms",
594 .usage = "[milliseconds]",
595 },
596 {
597 .name = "pulse_width",
598 .handler = handle_adapter_srst_pulse_width_command,
599 .mode = COMMAND_ANY,
600 .help = "SRST assertion pulse width in ms",
601 .usage = "[milliseconds]",
602 },
603 COMMAND_REGISTRATION_DONE
604 };
605
606 static const struct command_registration adapter_command_handlers[] = {
607 {
608 .name = "driver",
609 .handler = handle_adapter_driver_command,
610 .mode = COMMAND_CONFIG,
611 .help = "Select a debug adapter driver",
612 .usage = "driver_name",
613 },
614 {
615 .name = "speed",
616 .handler = handle_adapter_speed_command,
617 .mode = COMMAND_ANY,
618 .help = "With an argument, change to the specified maximum "
619 "jtag speed. For JTAG, 0 KHz signifies adaptive "
620 "clocking. "
621 "With or without argument, display current setting.",
622 .usage = "[khz]",
623 },
624 {
625 .name = "list",
626 .handler = handle_adapter_list_command,
627 .mode = COMMAND_ANY,
628 .help = "List all built-in debug adapter drivers",
629 .usage = "",
630 },
631 {
632 .name = "name",
633 .mode = COMMAND_ANY,
634 .jim_handler = jim_adapter_name,
635 .help = "Returns the name of the currently "
636 "selected adapter (driver)",
637 },
638 {
639 .name = "srst",
640 .mode = COMMAND_ANY,
641 .help = "srst adapter command group",
642 .usage = "",
643 .chain = adapter_srst_command_handlers,
644 },
645 {
646 .name = "transports",
647 .handler = adapter_transports_command,
648 .mode = COMMAND_CONFIG,
649 .help = "Declare transports the adapter supports.",
650 .usage = "transport ...",
651 },
652 {
653 .name = "usb",
654 .mode = COMMAND_ANY,
655 .help = "usb adapter command group",
656 .usage = "",
657 .chain = adapter_usb_command_handlers,
658 },
659 {
660 .name = "assert",
661 .handler = handle_adapter_reset_de_assert,
662 .mode = COMMAND_EXEC,
663 .help = "Controls SRST and TRST lines.",
664 .usage = "|deassert [srst|trst [assert|deassert srst|trst]]",
665 },
666 {
667 .name = "deassert",
668 .handler = handle_adapter_reset_de_assert,
669 .mode = COMMAND_EXEC,
670 .help = "Controls SRST and TRST lines.",
671 .usage = "|assert [srst|trst [deassert|assert srst|trst]]",
672 },
673 COMMAND_REGISTRATION_DONE
674 };
675
676 static const struct command_registration interface_command_handlers[] = {
677 {
678 .name = "adapter",
679 .mode = COMMAND_ANY,
680 .help = "adapter command group",
681 .usage = "",
682 .chain = adapter_command_handlers,
683 },
684 {
685 .name = "reset_config",
686 .handler = handle_reset_config_command,
687 .mode = COMMAND_ANY,
688 .help = "configure adapter reset behavior",
689 .usage = "[none|trst_only|srst_only|trst_and_srst] "
690 "[srst_pulls_trst|trst_pulls_srst|combined|separate] "
691 "[srst_gates_jtag|srst_nogate] "
692 "[trst_push_pull|trst_open_drain] "
693 "[srst_push_pull|srst_open_drain] "
694 "[connect_deassert_srst|connect_assert_srst]",
695 },
696 COMMAND_REGISTRATION_DONE
697 };
698
699 /**
700 * Register the commands which deal with arbitrary debug adapter drivers.
701 *
702 * @todo Remove internal assumptions that all debug adapters use JTAG for
703 * transport. Various types and data structures are not named generically.
704 */
705 int interface_register_commands(struct command_context *ctx)
706 {
707 return register_commands(ctx, NULL, interface_command_handlers);
708 }

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)