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

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)