jtag: linuxgpiod: drop extra parenthesis
[openocd.git] / src / target / arm_tpiu_swo.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2
3 /**
4 * @file
5 * This file implements support for the ARM CoreSight components Trace Port
6 * Interface Unit (TPIU) and Serial Wire Output (SWO). It also supports the
7 * CoreSight TPIU-Lite and the special TPIU version present with Cortex-M3
8 * and Cortex-M4 (that includes SWO).
9 */
10
11 /*
12 * Relevant specifications from ARM include:
13 *
14 * CoreSight(tm) Components Technical Reference Manual ARM DDI 0314H
15 * CoreSight(tm) TPIU-Lite Technical Reference Manual ARM DDI 0317A
16 * Cortex(tm)-M3 Technical Reference Manual ARM DDI 0337G
17 * Cortex(tm)-M4 Technical Reference Manual ARM DDI 0439B
18 * CoreSight(tm) SoC-400 Technical Reference Manual ARM DDI 0480F
19 */
20
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24
25 #include <stdlib.h>
26 #include <jim.h>
27
28 #include <helper/bits.h>
29 #include <helper/command.h>
30 #include <helper/jim-nvp.h>
31 #include <helper/list.h>
32 #include <helper/log.h>
33 #include <helper/types.h>
34 #include <jtag/interface.h>
35 #include <server/server.h>
36 #include <target/arm_adi_v5.h>
37 #include <target/target.h>
38 #include <transport/transport.h>
39 #include "arm_tpiu_swo.h"
40
41 /* START_DEPRECATED_TPIU */
42 #include <target/cortex_m.h>
43 #include <target/target_type.h>
44 #define MSG "DEPRECATED \'tpiu config\' command: "
45 /* END_DEPRECATED_TPIU */
46
47 #define TCP_SERVICE_NAME "tpiu_swo_trace"
48
49 /* default for Cortex-M3 and Cortex-M4 specific TPIU */
50 #define TPIU_SWO_DEFAULT_BASE 0xE0040000
51
52 #define TPIU_SSPSR_OFFSET 0x000
53 #define TPIU_CSPSR_OFFSET 0x004
54 #define TPIU_ACPR_OFFSET 0x010
55 #define TPIU_SPPR_OFFSET 0x0F0
56 #define TPIU_FFSR_OFFSET 0x300
57 #define TPIU_FFCR_OFFSET 0x304
58 #define TPIU_FSCR_OFFSET 0x308
59 #define TPIU_DEVID_OFFSET 0xfc8
60
61 #define TPIU_ACPR_MAX_PRESCALER 0x1fff
62 #define TPIU_SPPR_PROTOCOL_SYNC (TPIU_PIN_PROTOCOL_SYNC)
63 #define TPIU_SPPR_PROTOCOL_MANCHESTER (TPIU_PIN_PROTOCOL_ASYNC_MANCHESTER)
64 #define TPIU_SPPR_PROTOCOL_UART (TPIU_PIN_PROTOCOL_ASYNC_UART)
65 #define TPIU_DEVID_NOSUPPORT_SYNC BIT(9)
66 #define TPIU_DEVID_SUPPORT_MANCHESTER BIT(10)
67 #define TPIU_DEVID_SUPPORT_UART BIT(11)
68
69 enum arm_tpiu_swo_event {
70 TPIU_SWO_EVENT_PRE_ENABLE,
71 TPIU_SWO_EVENT_POST_ENABLE,
72 TPIU_SWO_EVENT_PRE_DISABLE,
73 TPIU_SWO_EVENT_POST_DISABLE,
74 };
75
76 static const struct jim_nvp nvp_arm_tpiu_swo_event[] = {
77 { .value = TPIU_SWO_EVENT_PRE_ENABLE, .name = "pre-enable" },
78 { .value = TPIU_SWO_EVENT_POST_ENABLE, .name = "post-enable" },
79 { .value = TPIU_SWO_EVENT_PRE_DISABLE, .name = "pre-disable" },
80 { .value = TPIU_SWO_EVENT_POST_DISABLE, .name = "post-disable" },
81 };
82
83 struct arm_tpiu_swo_event_action {
84 enum arm_tpiu_swo_event event;
85 Jim_Interp *interp;
86 Jim_Obj *body;
87 struct arm_tpiu_swo_event_action *next;
88 };
89
90 struct arm_tpiu_swo_object {
91 struct list_head lh;
92 struct adiv5_mem_ap_spot spot;
93 struct adiv5_ap *ap;
94 char *name;
95 struct arm_tpiu_swo_event_action *event_action;
96 /* record enable before init */
97 bool deferred_enable;
98 bool enabled;
99 bool en_capture;
100 /** Handle to output trace data in INTERNAL capture mode */
101 /** Synchronous output port width */
102 uint32_t port_width;
103 FILE *file;
104 /** output mode */
105 unsigned int pin_protocol;
106 /** Enable formatter */
107 bool en_formatter;
108 /** frequency of TRACECLKIN (usually matches HCLK) */
109 unsigned int traceclkin_freq;
110 /** SWO pin frequency */
111 unsigned int swo_pin_freq;
112 /** where to dump the captured output trace data */
113 char *out_filename;
114 /** track TCP connections */
115 struct list_head connections;
116 /* START_DEPRECATED_TPIU */
117 bool recheck_ap_cur_target;
118 /* END_DEPRECATED_TPIU */
119 };
120
121 struct arm_tpiu_swo_connection {
122 struct list_head lh;
123 struct connection *connection;
124 };
125
126 struct arm_tpiu_swo_priv_connection {
127 struct arm_tpiu_swo_object *obj;
128 };
129
130 static LIST_HEAD(all_tpiu_swo);
131
132 #define ARM_TPIU_SWO_TRACE_BUF_SIZE 4096
133
134 static int arm_tpiu_swo_poll_trace(void *priv)
135 {
136 struct arm_tpiu_swo_object *obj = priv;
137 uint8_t buf[ARM_TPIU_SWO_TRACE_BUF_SIZE];
138 size_t size = sizeof(buf);
139 struct arm_tpiu_swo_connection *c;
140
141 int retval = adapter_poll_trace(buf, &size);
142 if (retval != ERROR_OK || !size)
143 return retval;
144
145 target_call_trace_callbacks(/*target*/NULL, size, buf);
146
147 if (obj->file) {
148 if (fwrite(buf, 1, size, obj->file) == size) {
149 fflush(obj->file);
150 } else {
151 LOG_ERROR("Error writing to the SWO trace destination file");
152 return ERROR_FAIL;
153 }
154 }
155
156 if (obj->out_filename && obj->out_filename[0] == ':')
157 list_for_each_entry(c, &obj->connections, lh)
158 if (connection_write(c->connection, buf, size) != (int)size)
159 LOG_ERROR("Error writing to connection"); /* FIXME: which connection? */
160
161 return ERROR_OK;
162 }
163
164 static void arm_tpiu_swo_handle_event(struct arm_tpiu_swo_object *obj, enum arm_tpiu_swo_event event)
165 {
166 for (struct arm_tpiu_swo_event_action *ea = obj->event_action; ea; ea = ea->next) {
167 if (ea->event != event)
168 continue;
169
170 LOG_DEBUG("TPIU/SWO: %s event: %s (%d) action : %s",
171 obj->name,
172 jim_nvp_value2name_simple(nvp_arm_tpiu_swo_event, event)->name,
173 event,
174 Jim_GetString(ea->body, NULL));
175
176 /* prevent event execution to change current target */
177 struct command_context *cmd_ctx = current_command_context(ea->interp);
178 struct target *saved_target = cmd_ctx->current_target;
179 int retval = Jim_EvalObj(ea->interp, ea->body);
180 cmd_ctx->current_target = saved_target;
181
182 if (retval == JIM_RETURN)
183 retval = ea->interp->returnCode;
184 if (retval == JIM_OK || retval == ERROR_COMMAND_CLOSE_CONNECTION)
185 return;
186
187 Jim_MakeErrorMessage(ea->interp);
188 LOG_USER("Error executing event %s on TPIU/SWO %s:\n%s",
189 jim_nvp_value2name_simple(nvp_arm_tpiu_swo_event, event)->name,
190 obj->name,
191 Jim_GetString(Jim_GetResult(ea->interp), NULL));
192 /* clean both error code and stacktrace before return */
193 Jim_Eval(ea->interp, "error \"\" \"\"");
194 return;
195 }
196 }
197
198 static void arm_tpiu_swo_close_output(struct arm_tpiu_swo_object *obj)
199 {
200 if (obj->file) {
201 fclose(obj->file);
202 obj->file = NULL;
203 }
204 if (obj->out_filename && obj->out_filename[0] == ':')
205 remove_service(TCP_SERVICE_NAME, &obj->out_filename[1]);
206 }
207
208 int arm_tpiu_swo_cleanup_all(void)
209 {
210 struct arm_tpiu_swo_object *obj, *tmp;
211
212 list_for_each_entry_safe(obj, tmp, &all_tpiu_swo, lh) {
213 if (obj->enabled)
214 arm_tpiu_swo_handle_event(obj, TPIU_SWO_EVENT_PRE_DISABLE);
215
216 arm_tpiu_swo_close_output(obj);
217
218 if (obj->en_capture) {
219 target_unregister_timer_callback(arm_tpiu_swo_poll_trace, obj);
220
221 int retval = adapter_config_trace(false, 0, 0, NULL, 0, NULL);
222 if (retval != ERROR_OK)
223 LOG_ERROR("Failed to stop adapter's trace");
224 }
225
226 if (obj->enabled)
227 arm_tpiu_swo_handle_event(obj, TPIU_SWO_EVENT_POST_DISABLE);
228
229 struct arm_tpiu_swo_event_action *ea = obj->event_action;
230 while (ea) {
231 struct arm_tpiu_swo_event_action *next = ea->next;
232 Jim_DecrRefCount(ea->interp, ea->body);
233 free(ea);
234 ea = next;
235 }
236
237 if (obj->ap)
238 dap_put_ap(obj->ap);
239
240 free(obj->name);
241 free(obj->out_filename);
242 free(obj);
243 }
244
245 return ERROR_OK;
246 }
247
248 static int arm_tpiu_swo_service_new_connection(struct connection *connection)
249 {
250 struct arm_tpiu_swo_priv_connection *priv = connection->service->priv;
251 struct arm_tpiu_swo_object *obj = priv->obj;
252 struct arm_tpiu_swo_connection *c = malloc(sizeof(*c));
253 if (!c) {
254 LOG_ERROR("Out of memory");
255 return ERROR_FAIL;
256 }
257 c->connection = connection;
258 list_add(&c->lh, &obj->connections);
259 return ERROR_OK;
260 }
261
262 static int arm_tpiu_swo_service_input(struct connection *connection)
263 {
264 /* read a dummy buffer to check if the connection is still active */
265 long dummy;
266 int bytes_read = connection_read(connection, &dummy, sizeof(dummy));
267
268 if (bytes_read == 0) {
269 return ERROR_SERVER_REMOTE_CLOSED;
270 } else if (bytes_read == -1) {
271 LOG_ERROR("error during read: %s", strerror(errno));
272 return ERROR_SERVER_REMOTE_CLOSED;
273 }
274
275 return ERROR_OK;
276 }
277
278 static int arm_tpiu_swo_service_connection_closed(struct connection *connection)
279 {
280 struct arm_tpiu_swo_priv_connection *priv = connection->service->priv;
281 struct arm_tpiu_swo_object *obj = priv->obj;
282 struct arm_tpiu_swo_connection *c, *tmp;
283
284 list_for_each_entry_safe(c, tmp, &obj->connections, lh)
285 if (c->connection == connection) {
286 list_del(&c->lh);
287 free(c);
288 return ERROR_OK;
289 }
290 LOG_ERROR("Failed to find connection to close!");
291 return ERROR_FAIL;
292 }
293
294 COMMAND_HANDLER(handle_arm_tpiu_swo_event_list)
295 {
296 struct arm_tpiu_swo_object *obj = CMD_DATA;
297
298 command_print(CMD, "Event actions for TPIU/SWO %s\n", obj->name);
299 command_print(CMD, "%-25s | Body", "Event");
300 command_print(CMD, "------------------------- | "
301 "----------------------------------------");
302
303 for (struct arm_tpiu_swo_event_action *ea = obj->event_action; ea; ea = ea->next) {
304 struct jim_nvp *opt = jim_nvp_value2name_simple(nvp_arm_tpiu_swo_event, ea->event);
305 command_print(CMD, "%-25s | %s",
306 opt->name, Jim_GetString(ea->body, NULL));
307 }
308 command_print(CMD, "***END***");
309 return ERROR_OK;
310 }
311
312 enum arm_tpiu_swo_cfg_param {
313 CFG_PORT_WIDTH,
314 CFG_PROTOCOL,
315 CFG_FORMATTER,
316 CFG_TRACECLKIN,
317 CFG_BITRATE,
318 CFG_OUTFILE,
319 CFG_EVENT,
320 };
321
322 static const struct jim_nvp nvp_arm_tpiu_swo_config_opts[] = {
323 { .name = "-port-width", .value = CFG_PORT_WIDTH },
324 { .name = "-protocol", .value = CFG_PROTOCOL },
325 { .name = "-formatter", .value = CFG_FORMATTER },
326 { .name = "-traceclk", .value = CFG_TRACECLKIN },
327 { .name = "-pin-freq", .value = CFG_BITRATE },
328 { .name = "-output", .value = CFG_OUTFILE },
329 { .name = "-event", .value = CFG_EVENT },
330 /* handled by mem_ap_spot, added for jim_getopt_nvp_unknown() */
331 { .name = "-dap", .value = -1 },
332 { .name = "-ap-num", .value = -1 },
333 { .name = "-baseaddr", .value = -1 },
334 { .name = NULL, .value = -1 },
335 };
336
337 static const struct jim_nvp nvp_arm_tpiu_swo_protocol_opts[] = {
338 { .name = "sync", .value = TPIU_SPPR_PROTOCOL_SYNC },
339 { .name = "uart", .value = TPIU_SPPR_PROTOCOL_UART },
340 { .name = "manchester", .value = TPIU_SPPR_PROTOCOL_MANCHESTER },
341 { .name = NULL, .value = -1 },
342 };
343
344 static const struct jim_nvp nvp_arm_tpiu_swo_bool_opts[] = {
345 { .name = "on", .value = 1 },
346 { .name = "yes", .value = 1 },
347 { .name = "1", .value = 1 },
348 { .name = "true", .value = 1 },
349 { .name = "off", .value = 0 },
350 { .name = "no", .value = 0 },
351 { .name = "0", .value = 0 },
352 { .name = "false", .value = 0 },
353 { .name = NULL, .value = -1 },
354 };
355
356 static int arm_tpiu_swo_configure(struct jim_getopt_info *goi, struct arm_tpiu_swo_object *obj)
357 {
358 assert(obj);
359
360 if (goi->isconfigure && obj->enabled) {
361 Jim_SetResultFormatted(goi->interp, "Cannot configure TPIU/SWO; %s is enabled!", obj->name);
362 return JIM_ERR;
363 }
364
365 /* parse config or cget options ... */
366 while (goi->argc > 0) {
367 Jim_SetEmptyResult(goi->interp);
368
369 int e = adiv5_jim_mem_ap_spot_configure(&obj->spot, goi);
370 if (e == JIM_OK)
371 continue;
372 if (e == JIM_ERR)
373 return e;
374
375 struct jim_nvp *n;
376 e = jim_getopt_nvp(goi, nvp_arm_tpiu_swo_config_opts, &n);
377 if (e != JIM_OK) {
378 jim_getopt_nvp_unknown(goi, nvp_arm_tpiu_swo_config_opts, 0);
379 return e;
380 }
381
382 switch (n->value) {
383 case CFG_PORT_WIDTH:
384 if (goi->isconfigure) {
385 jim_wide port_width;
386 e = jim_getopt_wide(goi, &port_width);
387 if (e != JIM_OK)
388 return e;
389 if (port_width < 1 || port_width > 32) {
390 Jim_SetResultString(goi->interp, "Invalid port width!", -1);
391 return JIM_ERR;
392 }
393 obj->port_width = (uint32_t)port_width;
394 } else {
395 if (goi->argc)
396 goto err_no_params;
397 Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, obj->port_width));
398 }
399 break;
400 case CFG_PROTOCOL:
401 if (goi->isconfigure) {
402 struct jim_nvp *p;
403 e = jim_getopt_nvp(goi, nvp_arm_tpiu_swo_protocol_opts, &p);
404 if (e != JIM_OK)
405 return e;
406 obj->pin_protocol = p->value;
407 } else {
408 if (goi->argc)
409 goto err_no_params;
410 struct jim_nvp *p;
411 e = jim_nvp_value2name(goi->interp, nvp_arm_tpiu_swo_protocol_opts, obj->pin_protocol, &p);
412 if (e != JIM_OK) {
413 Jim_SetResultString(goi->interp, "protocol error", -1);
414 return JIM_ERR;
415 }
416 Jim_SetResult(goi->interp, Jim_NewStringObj(goi->interp, p->name, -1));
417 }
418 break;
419 case CFG_FORMATTER:
420 if (goi->isconfigure) {
421 struct jim_nvp *p;
422 e = jim_getopt_nvp(goi, nvp_arm_tpiu_swo_bool_opts, &p);
423 if (e != JIM_OK)
424 return e;
425 obj->en_formatter = p->value;
426 } else {
427 if (goi->argc)
428 goto err_no_params;
429 struct jim_nvp *p;
430 e = jim_nvp_value2name(goi->interp, nvp_arm_tpiu_swo_bool_opts, obj->en_formatter, &p);
431 if (e != JIM_OK) {
432 Jim_SetResultString(goi->interp, "formatter error", -1);
433 return JIM_ERR;
434 }
435 Jim_SetResult(goi->interp, Jim_NewStringObj(goi->interp, p->name, -1));
436 }
437 break;
438 case CFG_TRACECLKIN:
439 if (goi->isconfigure) {
440 jim_wide clk;
441 e = jim_getopt_wide(goi, &clk);
442 if (e != JIM_OK)
443 return e;
444 obj->traceclkin_freq = clk;
445 } else {
446 if (goi->argc)
447 goto err_no_params;
448 Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, obj->traceclkin_freq));
449 }
450 break;
451 case CFG_BITRATE:
452 if (goi->isconfigure) {
453 jim_wide clk;
454 e = jim_getopt_wide(goi, &clk);
455 if (e != JIM_OK)
456 return e;
457 obj->swo_pin_freq = clk;
458 } else {
459 if (goi->argc)
460 goto err_no_params;
461 Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, obj->swo_pin_freq));
462 }
463 break;
464 case CFG_OUTFILE:
465 if (goi->isconfigure) {
466 const char *s;
467 e = jim_getopt_string(goi, &s, NULL);
468 if (e != JIM_OK)
469 return e;
470 if (s[0] == ':') {
471 char *end;
472 long port = strtol(s + 1, &end, 0);
473 if (port <= 0 || port > UINT16_MAX || *end != '\0') {
474 Jim_SetResultFormatted(goi->interp, "Invalid TCP port \'%s\'", s + 1);
475 return JIM_ERR;
476 }
477 }
478 free(obj->out_filename);
479 obj->out_filename = strdup(s);
480 if (!obj->out_filename) {
481 LOG_ERROR("Out of memory");
482 return JIM_ERR;
483 }
484 } else {
485 if (goi->argc)
486 goto err_no_params;
487 if (obj->out_filename)
488 Jim_SetResult(goi->interp, Jim_NewStringObj(goi->interp, obj->out_filename, -1));
489 }
490 break;
491 case CFG_EVENT:
492 if (goi->isconfigure) {
493 if (goi->argc < 2) {
494 Jim_WrongNumArgs(goi->interp, goi->argc, goi->argv, "-event ?event-name? ?EVENT-BODY?");
495 return JIM_ERR;
496 }
497 } else {
498 if (goi->argc != 1) {
499 Jim_WrongNumArgs(goi->interp, goi->argc, goi->argv, "-event ?event-name?");
500 return JIM_ERR;
501 }
502 }
503
504 {
505 struct jim_nvp *p;
506 Jim_Obj *o;
507 struct arm_tpiu_swo_event_action *ea = obj->event_action;
508
509 e = jim_getopt_nvp(goi, nvp_arm_tpiu_swo_event, &p);
510 if (e != JIM_OK) {
511 jim_getopt_nvp_unknown(goi, nvp_arm_tpiu_swo_event, 1);
512 return e;
513 }
514
515 while (ea) {
516 /* replace existing? */
517 if (ea->event == (enum arm_tpiu_swo_event)p->value)
518 break;
519 ea = ea->next;
520 }
521
522 if (goi->isconfigure) {
523 if (!ea) {
524 ea = calloc(1, sizeof(*ea));
525 if (!ea) {
526 LOG_ERROR("Out of memory");
527 return JIM_ERR;
528 }
529 ea->next = obj->event_action;
530 obj->event_action = ea;
531 }
532 if (ea->body)
533 Jim_DecrRefCount(ea->interp, ea->body);
534 ea->event = p->value;
535 ea->interp = goi->interp;
536 jim_getopt_obj(goi, &o);
537 ea->body = Jim_DuplicateObj(goi->interp, o);
538 Jim_IncrRefCount(ea->body);
539 } else {
540 if (ea)
541 Jim_SetResult(goi->interp, Jim_DuplicateObj(goi->interp, ea->body));
542 }
543 }
544 break;
545 }
546 }
547
548 return JIM_OK;
549
550 err_no_params:
551 Jim_WrongNumArgs(goi->interp, goi->argc, goi->argv, "NO PARAMS");
552 return JIM_ERR;
553 }
554
555 static int jim_arm_tpiu_swo_configure(Jim_Interp *interp, int argc, Jim_Obj * const *argv)
556 {
557 struct command *c = jim_to_command(interp);
558 struct jim_getopt_info goi;
559
560 jim_getopt_setup(&goi, interp, argc - 1, argv + 1);
561 goi.isconfigure = !strcmp(c->name, "configure");
562 if (goi.argc < 1) {
563 Jim_WrongNumArgs(goi.interp, goi.argc, goi.argv,
564 "missing: -option ...");
565 return JIM_ERR;
566 }
567 struct arm_tpiu_swo_object *obj = c->jim_handler_data;
568 return arm_tpiu_swo_configure(&goi, obj);
569 }
570
571 static int wrap_write_u32(struct target *target, struct adiv5_ap *tpiu_ap,
572 target_addr_t address, uint32_t value)
573 {
574 if (transport_is_hla())
575 return target_write_u32(target, address, value);
576 else
577 return mem_ap_write_atomic_u32(tpiu_ap, address, value);
578 }
579
580 static int wrap_read_u32(struct target *target, struct adiv5_ap *tpiu_ap,
581 target_addr_t address, uint32_t *value)
582 {
583 if (transport_is_hla())
584 return target_read_u32(target, address, value);
585 else
586 return mem_ap_read_atomic_u32(tpiu_ap, address, value);
587 }
588
589 static const struct service_driver arm_tpiu_swo_service_driver = {
590 .name = "tpiu_swo_trace",
591 .new_connection_during_keep_alive_handler = NULL,
592 .new_connection_handler = arm_tpiu_swo_service_new_connection,
593 .input_handler = arm_tpiu_swo_service_input,
594 .connection_closed_handler = arm_tpiu_swo_service_connection_closed,
595 .keep_client_alive_handler = NULL,
596 };
597
598 static int jim_arm_tpiu_swo_enable(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
599 {
600 struct command *c = jim_to_command(interp);
601 struct arm_tpiu_swo_object *obj = c->jim_handler_data;
602 struct command_context *cmd_ctx = current_command_context(interp);
603 uint32_t value;
604 int retval;
605
606 if (argc != 1) {
607 Jim_WrongNumArgs(interp, 1, argv, "Too many parameters");
608 return JIM_ERR;
609 }
610
611 if (cmd_ctx->mode == COMMAND_CONFIG) {
612 LOG_DEBUG("%s: enable deferred", obj->name);
613 obj->deferred_enable = true;
614 return JIM_OK;
615 }
616
617 if (obj->enabled)
618 return JIM_OK;
619
620 if (transport_is_hla() && obj->spot.ap_num != 0) {
621 LOG_ERROR("Invalid access port 0x%" PRIx64 ". Only AP#0 allowed with hla transport", obj->spot.ap_num);
622 return JIM_ERR;
623 }
624
625 if (!obj->traceclkin_freq) {
626 LOG_ERROR("Trace clock-in frequency not set");
627 return JIM_ERR;
628 }
629
630 if (obj->pin_protocol == TPIU_SPPR_PROTOCOL_MANCHESTER || obj->pin_protocol == TPIU_SPPR_PROTOCOL_UART)
631 if (!obj->swo_pin_freq)
632 LOG_DEBUG("SWO pin frequency not set, will be autodetected by the adapter");
633
634 struct target *target = get_current_target(cmd_ctx);
635
636 /* START_DEPRECATED_TPIU */
637 if (obj->recheck_ap_cur_target) {
638 if (strcmp(target->type->name, "cortex_m") &&
639 strcmp(target->type->name, "hla_target")) {
640 LOG_ERROR(MSG "Current target is not a Cortex-M nor a HLA");
641 return JIM_ERR;
642 }
643 if (!target_was_examined(target)) {
644 LOG_ERROR(MSG "Current target not examined yet");
645 return JIM_ERR;
646 }
647 struct cortex_m_common *cm = target_to_cm(target);
648 obj->recheck_ap_cur_target = false;
649 obj->spot.ap_num = cm->armv7m.debug_ap->ap_num;
650 if (obj->spot.ap_num == 0)
651 LOG_INFO(MSG "Confirmed TPIU %s is on AP 0", obj->name);
652 else
653 LOG_INFO(MSG "Target %s is on AP#0x%" PRIx64 ". Revised command is "
654 "\'tpiu create %s -dap %s -ap-num 0x%" PRIx64 "\'",
655 target_name(target), obj->spot.ap_num,
656 obj->name, adiv5_dap_name(obj->spot.dap), obj->spot.ap_num);
657 }
658 /* END_DEPRECATED_TPIU */
659
660 if (!obj->ap) {
661 obj->ap = dap_get_ap(obj->spot.dap, obj->spot.ap_num);
662 if (!obj->ap) {
663 LOG_ERROR("Cannot get AP");
664 return JIM_ERR;
665 }
666 }
667
668 /* trigger the event before any attempt to R/W in the TPIU/SWO */
669 arm_tpiu_swo_handle_event(obj, TPIU_SWO_EVENT_PRE_ENABLE);
670
671 retval = wrap_read_u32(target, obj->ap, obj->spot.base + TPIU_DEVID_OFFSET, &value);
672 if (retval != ERROR_OK) {
673 LOG_ERROR("Unable to read %s", obj->name);
674 return JIM_ERR;
675 }
676 switch (obj->pin_protocol) {
677 case TPIU_SPPR_PROTOCOL_SYNC:
678 value = !(value & TPIU_DEVID_NOSUPPORT_SYNC);
679 break;
680 case TPIU_SPPR_PROTOCOL_UART:
681 value &= TPIU_DEVID_SUPPORT_UART;
682 break;
683 case TPIU_SPPR_PROTOCOL_MANCHESTER:
684 value &= TPIU_DEVID_SUPPORT_MANCHESTER;
685 break;
686 default:
687 value = 0;
688 }
689 if (!value) {
690 struct jim_nvp *p;
691 jim_nvp_value2name(interp, nvp_arm_tpiu_swo_protocol_opts, obj->pin_protocol, &p);
692 LOG_ERROR("%s does not support protocol %s", obj->name, p->name);
693 return JIM_ERR;
694 }
695
696 if (obj->pin_protocol == TPIU_SPPR_PROTOCOL_SYNC) {
697 retval = wrap_read_u32(target, obj->ap, obj->spot.base + TPIU_SSPSR_OFFSET, &value);
698 if (retval != ERROR_OK) {
699 LOG_ERROR("Cannot read TPIU register SSPSR");
700 return JIM_ERR;
701 }
702 if (!(value & BIT(obj->port_width - 1))) {
703 LOG_ERROR("TPIU does not support port-width of %d bits", obj->port_width);
704 return JIM_ERR;
705 }
706 }
707
708 uint16_t prescaler = 1; /* dummy value */
709 unsigned int swo_pin_freq = obj->swo_pin_freq; /* could be replaced */
710
711 if (obj->out_filename && strcmp(obj->out_filename, "external") && obj->out_filename[0]) {
712 if (obj->out_filename[0] == ':') {
713 struct arm_tpiu_swo_priv_connection *priv = malloc(sizeof(*priv));
714 if (!priv) {
715 LOG_ERROR("Out of memory");
716 return JIM_ERR;
717 }
718 priv->obj = obj;
719 LOG_INFO("starting trace server for %s on %s", obj->name, &obj->out_filename[1]);
720 retval = add_service(&arm_tpiu_swo_service_driver, &obj->out_filename[1],
721 CONNECTION_LIMIT_UNLIMITED, priv);
722 if (retval != ERROR_OK) {
723 LOG_ERROR("Can't configure trace TCP port %s", &obj->out_filename[1]);
724 return JIM_ERR;
725 }
726 } else if (strcmp(obj->out_filename, "-")) {
727 obj->file = fopen(obj->out_filename, "ab");
728 if (!obj->file) {
729 LOG_ERROR("Can't open trace destination file \"%s\"", obj->out_filename);
730 return JIM_ERR;
731 }
732 }
733
734 retval = adapter_config_trace(true, obj->pin_protocol, obj->port_width,
735 &swo_pin_freq, obj->traceclkin_freq, &prescaler);
736 if (retval != ERROR_OK) {
737 LOG_ERROR("Failed to start adapter's trace");
738 arm_tpiu_swo_close_output(obj);
739 return JIM_ERR;
740 }
741
742 if (obj->pin_protocol == TPIU_SPPR_PROTOCOL_MANCHESTER || obj->pin_protocol == TPIU_SPPR_PROTOCOL_UART)
743 if (!swo_pin_freq) {
744 if (obj->swo_pin_freq)
745 LOG_ERROR("Adapter rejected SWO pin frequency %d Hz", obj->swo_pin_freq);
746 else
747 LOG_ERROR("Adapter does not support auto-detection of SWO pin frequency nor a default value");
748
749 arm_tpiu_swo_close_output(obj);
750 return JIM_ERR;
751 }
752
753 if (obj->swo_pin_freq != swo_pin_freq)
754 LOG_INFO("SWO pin data rate adjusted by adapter to %d Hz", swo_pin_freq);
755 obj->swo_pin_freq = swo_pin_freq;
756
757 target_register_timer_callback(arm_tpiu_swo_poll_trace, 1,
758 TARGET_TIMER_TYPE_PERIODIC, obj);
759
760 obj->en_capture = true;
761 } else if (obj->pin_protocol == TPIU_SPPR_PROTOCOL_MANCHESTER || obj->pin_protocol == TPIU_SPPR_PROTOCOL_UART) {
762 prescaler = (obj->traceclkin_freq + obj->swo_pin_freq / 2) / obj->swo_pin_freq;
763 if (prescaler > TPIU_ACPR_MAX_PRESCALER)
764 prescaler = TPIU_ACPR_MAX_PRESCALER;
765 swo_pin_freq = obj->traceclkin_freq / prescaler;
766
767 if (obj->swo_pin_freq != swo_pin_freq)
768 LOG_INFO("SWO pin data rate adjusted to %d Hz", swo_pin_freq);
769 obj->swo_pin_freq = swo_pin_freq;
770 }
771
772 retval = wrap_write_u32(target, obj->ap, obj->spot.base + TPIU_CSPSR_OFFSET, BIT(obj->port_width - 1));
773 if (retval != ERROR_OK)
774 goto error_exit;
775
776 retval = wrap_write_u32(target, obj->ap, obj->spot.base + TPIU_ACPR_OFFSET, prescaler - 1);
777 if (retval != ERROR_OK)
778 goto error_exit;
779
780 retval = wrap_write_u32(target, obj->ap, obj->spot.base + TPIU_SPPR_OFFSET, obj->pin_protocol);
781 if (retval != ERROR_OK)
782 goto error_exit;
783
784 retval = wrap_read_u32(target, obj->ap, obj->spot.base + TPIU_FFCR_OFFSET, &value);
785 if (retval != ERROR_OK)
786 goto error_exit;
787 if (obj->en_formatter)
788 value |= BIT(1);
789 else
790 value &= ~BIT(1);
791 retval = wrap_write_u32(target, obj->ap, obj->spot.base + TPIU_FFCR_OFFSET, value);
792 if (retval != ERROR_OK)
793 goto error_exit;
794
795 arm_tpiu_swo_handle_event(obj, TPIU_SWO_EVENT_POST_ENABLE);
796
797 /* START_DEPRECATED_TPIU */
798 target_handle_event(target, TARGET_EVENT_TRACE_CONFIG);
799 /* END_DEPRECATED_TPIU */
800
801 obj->enabled = true;
802 return JIM_OK;
803
804 error_exit:
805 LOG_ERROR("Error!");
806
807 if (obj->en_capture) {
808 obj->en_capture = false;
809
810 arm_tpiu_swo_close_output(obj);
811
812 target_unregister_timer_callback(arm_tpiu_swo_poll_trace, obj);
813
814 retval = adapter_config_trace(false, 0, 0, NULL, 0, NULL);
815 if (retval != ERROR_OK) {
816 LOG_ERROR("Failed to stop adapter's trace");
817 return JIM_ERR;
818 }
819 }
820 return JIM_ERR;
821 }
822
823 static int jim_arm_tpiu_swo_disable(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
824 {
825 struct command *c = jim_to_command(interp);
826 struct arm_tpiu_swo_object *obj = c->jim_handler_data;
827
828 if (argc != 1) {
829 Jim_WrongNumArgs(interp, 1, argv, "Too many parameters");
830 return JIM_ERR;
831 }
832
833 if (!obj->enabled)
834 return JIM_OK;
835 obj->enabled = false;
836
837 arm_tpiu_swo_handle_event(obj, TPIU_SWO_EVENT_PRE_DISABLE);
838
839 if (obj->en_capture) {
840 obj->en_capture = false;
841
842 arm_tpiu_swo_close_output(obj);
843
844 target_unregister_timer_callback(arm_tpiu_swo_poll_trace, obj);
845
846 int retval = adapter_config_trace(false, 0, 0, NULL, 0, NULL);
847 if (retval != ERROR_OK) {
848 LOG_ERROR("Failed to stop adapter's trace");
849 return JIM_ERR;
850 }
851 }
852
853 arm_tpiu_swo_handle_event(obj, TPIU_SWO_EVENT_POST_DISABLE);
854
855 /* START_DEPRECATED_TPIU */
856 struct command_context *cmd_ctx = current_command_context(interp);
857 struct target *target = get_current_target(cmd_ctx);
858 target_handle_event(target, TARGET_EVENT_TRACE_CONFIG);
859 /* END_DEPRECATED_TPIU */
860
861 return JIM_OK;
862 }
863
864 static const struct command_registration arm_tpiu_swo_instance_command_handlers[] = {
865 {
866 .name = "configure",
867 .mode = COMMAND_ANY,
868 .jim_handler = jim_arm_tpiu_swo_configure,
869 .help = "configure a new TPIU/SWO for use",
870 .usage = "[attribute value ...]",
871 },
872 {
873 .name = "cget",
874 .mode = COMMAND_ANY,
875 .jim_handler = jim_arm_tpiu_swo_configure,
876 .help = "returns the specified TPIU/SWO attribute",
877 .usage = "attribute",
878 },
879 {
880 .name = "eventlist",
881 .mode = COMMAND_ANY,
882 .handler = handle_arm_tpiu_swo_event_list,
883 .help = "displays a table of events defined for this TPIU/SWO",
884 .usage = "",
885 },
886 {
887 .name = "enable",
888 .mode = COMMAND_ANY,
889 .jim_handler = jim_arm_tpiu_swo_enable,
890 .usage = "",
891 .help = "Enables the TPIU/SWO output",
892 },
893 {
894 .name = "disable",
895 .mode = COMMAND_EXEC,
896 .jim_handler = jim_arm_tpiu_swo_disable,
897 .usage = "",
898 .help = "Disables the TPIU/SWO output",
899 },
900 COMMAND_REGISTRATION_DONE
901 };
902
903 static int arm_tpiu_swo_create(Jim_Interp *interp, struct arm_tpiu_swo_object *obj)
904 {
905 struct command_context *cmd_ctx;
906 Jim_Cmd *cmd;
907 int e;
908
909 cmd_ctx = current_command_context(interp);
910 assert(cmd_ctx);
911
912 /* does this command exist? */
913 cmd = Jim_GetCommand(interp, Jim_NewStringObj(interp, obj->name, -1), JIM_NONE);
914 if (cmd) {
915 Jim_SetResultFormatted(interp, "cannot create TPIU object because a command with name '%s' already exists",
916 obj->name);
917 return JIM_ERR;
918 }
919
920 /* now - create the new tpiu/swo name command */
921 const struct command_registration obj_commands[] = {
922 {
923 .name = obj->name,
924 .mode = COMMAND_ANY,
925 .help = "tpiu/swo instance command group",
926 .usage = "",
927 .chain = arm_tpiu_swo_instance_command_handlers,
928 },
929 COMMAND_REGISTRATION_DONE
930 };
931 e = register_commands_with_data(cmd_ctx, NULL, obj_commands, obj);
932 if (e != ERROR_OK)
933 return JIM_ERR;
934
935 list_add_tail(&obj->lh, &all_tpiu_swo);
936
937 return JIM_OK;
938 }
939
940 static int jim_arm_tpiu_swo_create(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
941 {
942 struct jim_getopt_info goi;
943 jim_getopt_setup(&goi, interp, argc - 1, argv + 1);
944 if (goi.argc < 1) {
945 Jim_WrongNumArgs(interp, 1, argv, "name ?option option ...?");
946 return JIM_ERR;
947 }
948
949 struct arm_tpiu_swo_object *obj = calloc(1, sizeof(struct arm_tpiu_swo_object));
950 if (!obj) {
951 LOG_ERROR("Out of memory");
952 return JIM_ERR;
953 }
954 INIT_LIST_HEAD(&obj->connections);
955 adiv5_mem_ap_spot_init(&obj->spot);
956 obj->spot.base = TPIU_SWO_DEFAULT_BASE;
957 obj->port_width = 1;
958
959 Jim_Obj *n;
960 jim_getopt_obj(&goi, &n);
961 obj->name = strdup(Jim_GetString(n, NULL));
962 if (!obj->name) {
963 LOG_ERROR("Out of memory");
964 free(obj);
965 return JIM_ERR;
966 }
967
968 /* Do the rest as "configure" options */
969 goi.isconfigure = 1;
970 int e = arm_tpiu_swo_configure(&goi, obj);
971 if (e != JIM_OK)
972 goto err_exit;
973
974 if (!obj->spot.dap || obj->spot.ap_num == DP_APSEL_INVALID) {
975 Jim_SetResultString(goi.interp, "-dap and -ap-num required when creating TPIU", -1);
976 goto err_exit;
977 }
978
979 e = arm_tpiu_swo_create(goi.interp, obj);
980 if (e != JIM_OK)
981 goto err_exit;
982
983 return JIM_OK;
984
985 err_exit:
986 free(obj->name);
987 free(obj->out_filename);
988 free(obj);
989 return JIM_ERR;
990 }
991
992 static int jim_arm_tpiu_swo_names(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
993 {
994 struct arm_tpiu_swo_object *obj;
995
996 if (argc != 1) {
997 Jim_WrongNumArgs(interp, 1, argv, "Too many parameters");
998 return JIM_ERR;
999 }
1000 Jim_SetResult(interp, Jim_NewListObj(interp, NULL, 0));
1001 list_for_each_entry(obj, &all_tpiu_swo, lh) {
1002 Jim_ListAppendElement(interp, Jim_GetResult(interp),
1003 Jim_NewStringObj(interp, obj->name, -1));
1004 }
1005 return JIM_OK;
1006 }
1007
1008 static int jim_arm_tpiu_swo_init(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
1009 {
1010 struct command_context *cmd_ctx = current_command_context(interp);
1011 struct arm_tpiu_swo_object *obj;
1012 int retval = JIM_OK;
1013
1014 if (argc != 1) {
1015 Jim_WrongNumArgs(interp, 1, argv, "Too many parameters");
1016 return JIM_ERR;
1017 }
1018 list_for_each_entry(obj, &all_tpiu_swo, lh) {
1019 if (!obj->deferred_enable)
1020 continue;
1021 LOG_DEBUG("%s: running enable during init", obj->name);
1022 int retval2 = command_run_linef(cmd_ctx, "%s enable", obj->name);
1023 if (retval2 != ERROR_OK)
1024 retval = JIM_ERR;
1025 }
1026 return retval;
1027 }
1028
1029 /* START_DEPRECATED_TPIU */
1030 /* DEPRECATED: emulation of old command 'tpiu config' */
1031 COMMAND_HANDLER(handle_tpiu_deprecated_config_command)
1032 {
1033 struct target *target = get_current_target(CMD_CTX);
1034 struct arm_tpiu_swo_object *obj = NULL;
1035 int retval;
1036
1037 if (strcmp(target->type->name, "cortex_m") &&
1038 strcmp(target->type->name, "hla_target")) {
1039 LOG_ERROR(MSG "Current target is not a Cortex-M nor a HLA");
1040 return ERROR_FAIL;
1041 }
1042
1043 if (!list_empty(&all_tpiu_swo)) {
1044 obj = list_first_entry(&all_tpiu_swo, typeof(*obj), lh);
1045 LOG_INFO(MSG "Using %s", obj->name);
1046 } else {
1047 struct cortex_m_common *cm = target_to_cm(target);
1048 struct adiv5_private_config *pc = target->private_config;
1049 struct adiv5_dap *dap = pc->dap;
1050 uint64_t ap_num = pc->ap_num;
1051 bool set_recheck_ap_cur_target = false;
1052
1053 LOG_INFO(MSG "Adding a TPIU \'%s.tpiu\' in the configuration", target_name(target));
1054
1055 if (ap_num == DP_APSEL_INVALID && transport_is_hla())
1056 ap_num = 0; /* HLA should only support AP 0 */
1057
1058 if (ap_num == DP_APSEL_INVALID && target_was_examined(target))
1059 ap_num = cm->armv7m.debug_ap->ap_num;
1060
1061 if (ap_num == DP_APSEL_INVALID) {
1062 LOG_INFO(MSG "Target %s uses AP autodetection. Adding TPIU on AP 0; can be revised later",
1063 target_name(target));
1064 ap_num = 0;
1065 set_recheck_ap_cur_target = true;
1066 }
1067
1068 LOG_INFO(MSG "Running: \'tpiu create %s.tpiu -dap %s -ap-num 0x%" PRIx64 "\'",
1069 target_name(target), adiv5_dap_name(dap), ap_num);
1070
1071 retval = command_run_linef(CMD_CTX, "tpiu create %s.tpiu -dap %s -ap-num 0x%" PRIx64,
1072 target_name(target), adiv5_dap_name(dap), ap_num);
1073 if (retval != ERROR_OK)
1074 return retval;
1075
1076 obj = list_first_entry(&all_tpiu_swo, typeof(*obj), lh);
1077 if (set_recheck_ap_cur_target)
1078 obj->recheck_ap_cur_target = true;
1079 }
1080
1081 unsigned int cmd_idx = 0;
1082 if (cmd_idx == CMD_ARGC)
1083 return ERROR_COMMAND_SYNTAX_ERROR;
1084
1085 if (!strcmp(CMD_ARGV[cmd_idx], "disable")) {
1086 if (CMD_ARGC != cmd_idx + 1)
1087 return ERROR_COMMAND_SYNTAX_ERROR;
1088 LOG_INFO(MSG "Running: \'%s disable\'", obj->name);
1089 return command_run_linef(CMD_CTX, "%s disable", obj->name);
1090 }
1091
1092 const char *output = NULL;
1093 const char *protocol;
1094 const char *formatter = NULL;
1095 const char *port_width = NULL;
1096 const char *trace_clk;
1097 const char *pin_clk = NULL;
1098 if (!strcmp(CMD_ARGV[cmd_idx], "internal")) {
1099 cmd_idx++;
1100 if (cmd_idx == CMD_ARGC)
1101 return ERROR_COMMAND_SYNTAX_ERROR;
1102 output = CMD_ARGV[cmd_idx];
1103 } else if (strcmp(CMD_ARGV[cmd_idx], "external"))
1104 return ERROR_COMMAND_SYNTAX_ERROR;
1105 cmd_idx++;
1106 if (cmd_idx == CMD_ARGC)
1107 return ERROR_COMMAND_SYNTAX_ERROR;
1108 if (!strcmp(CMD_ARGV[cmd_idx], "sync")) {
1109 protocol = CMD_ARGV[cmd_idx];
1110 cmd_idx++;
1111 if (cmd_idx == CMD_ARGC)
1112 return ERROR_COMMAND_SYNTAX_ERROR;
1113 port_width = CMD_ARGV[cmd_idx];
1114 } else {
1115 if (strcmp(CMD_ARGV[cmd_idx], "manchester") && strcmp(CMD_ARGV[cmd_idx], "uart"))
1116 return ERROR_COMMAND_SYNTAX_ERROR;
1117 protocol = CMD_ARGV[cmd_idx];
1118 cmd_idx++;
1119 if (cmd_idx == CMD_ARGC)
1120 return ERROR_COMMAND_SYNTAX_ERROR;
1121 formatter = CMD_ARGV[cmd_idx];
1122 }
1123 cmd_idx++;
1124 if (cmd_idx == CMD_ARGC)
1125 return ERROR_COMMAND_SYNTAX_ERROR;
1126 trace_clk = CMD_ARGV[cmd_idx];
1127 cmd_idx++;
1128 if (cmd_idx != CMD_ARGC) {
1129 pin_clk = CMD_ARGV[cmd_idx];
1130 cmd_idx++;
1131 }
1132 if (cmd_idx != CMD_ARGC)
1133 return ERROR_COMMAND_SYNTAX_ERROR;
1134
1135 LOG_INFO(MSG "Running: \'%s configure -protocol %s -traceclk %s" "%s%s" "%s%s" "%s%s" "%s%s\'",
1136 obj->name, protocol, trace_clk,
1137 pin_clk ? " -pin-freq " : "", pin_clk ? pin_clk : "",
1138 output ? " -output " : "", output ? output : "",
1139 formatter ? " -formatter " : "", formatter ? formatter : "",
1140 port_width ? " -port-width " : "", port_width ? port_width : "");
1141
1142 retval = command_run_linef(CMD_CTX,
1143 "%s configure -protocol %s -traceclk %s" "%s%s" "%s%s" "%s%s" "%s%s",
1144 obj->name, protocol, trace_clk,
1145 pin_clk ? " -pin-freq " : "", pin_clk ? pin_clk : "",
1146 output ? " -output " : "", output ? output : "",
1147 formatter ? " -formatter " : "", formatter ? formatter : "",
1148 port_width ? " -port-width " : "", port_width ? port_width : "");
1149 if (retval != ERROR_OK)
1150 return retval;
1151
1152 LOG_INFO(MSG "Running: \'%s enable\'", obj->name);
1153 retval = command_run_linef(CMD_CTX, "%s enable", obj->name);
1154 if (retval != ERROR_OK)
1155 return retval;
1156
1157 return ERROR_OK;
1158 }
1159
1160 static const struct command_registration arm_tpiu_deprecated_subcommand_handlers[] = {
1161 {
1162 .name = "config",
1163 .handler = handle_tpiu_deprecated_config_command,
1164 .mode = COMMAND_ANY,
1165 .help = "Configure TPIU features, DEPRECATED, use \'tpiu create\'",
1166 .usage = "(disable | "
1167 "((external | internal (<filename> | <:port> | -)) "
1168 "(sync <port width> | ((manchester | uart) <formatter enable>)) "
1169 "<TRACECLKIN freq> [<trace freq>]))",
1170 },
1171 COMMAND_REGISTRATION_DONE
1172 };
1173
1174 const struct command_registration arm_tpiu_deprecated_command_handlers[] = {
1175 {
1176 .name = "tpiu",
1177 .chain = arm_tpiu_deprecated_subcommand_handlers,
1178 .usage = "",
1179 .help = "tpiu command group",
1180 },
1181 COMMAND_REGISTRATION_DONE
1182 };
1183 /* END_DEPRECATED_TPIU */
1184
1185 static const struct command_registration arm_tpiu_swo_subcommand_handlers[] = {
1186 {
1187 .name = "create",
1188 .mode = COMMAND_ANY,
1189 .jim_handler = jim_arm_tpiu_swo_create,
1190 .usage = "name [-dap dap] [-ap-num num] [-baseaddr baseaddr]",
1191 .help = "Creates a new TPIU or SWO object",
1192 },
1193 {
1194 .name = "names",
1195 .mode = COMMAND_ANY,
1196 .jim_handler = jim_arm_tpiu_swo_names,
1197 .usage = "",
1198 .help = "Lists all registered TPIU and SWO objects by name",
1199 },
1200 {
1201 .name = "init",
1202 .mode = COMMAND_EXEC,
1203 .jim_handler = jim_arm_tpiu_swo_init,
1204 .usage = "",
1205 .help = "Initialize TPIU and SWO",
1206 },
1207 COMMAND_REGISTRATION_DONE
1208 };
1209
1210 static const struct command_registration arm_tpiu_swo_command_handlers[] = {
1211 {
1212 .name = "tpiu",
1213 .chain = arm_tpiu_swo_subcommand_handlers,
1214 .usage = "",
1215 .help = "tpiu command group",
1216 },
1217 {
1218 .name = "swo",
1219 .chain = arm_tpiu_swo_subcommand_handlers,
1220 .usage = "",
1221 .help = "swo command group",
1222 },
1223 COMMAND_REGISTRATION_DONE
1224 };
1225
1226 int arm_tpiu_swo_register_commands(struct command_context *cmd_ctx)
1227 {
1228 return register_commands(cmd_ctx, NULL, arm_tpiu_swo_command_handlers);
1229 }

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)