target: esp_xtensa_smp: fix clang report
[openocd.git] / src / target / espressif / esp_xtensa_smp.c
1 /***************************************************************************
2 * ESP Xtensa SMP target API for OpenOCD *
3 * Copyright (C) 2020 Espressif Systems Ltd. Co *
4 * Author: Alexey Gerenkov <alexey@espressif.com> *
5 * *
6 * This program is free software; you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by *
8 * the Free Software Foundation; either version 2 of the License, or *
9 * (at your option) any later version. *
10 * *
11 * This program is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 * GNU General Public License for more details. *
15 * *
16 * You should have received a copy of the GNU General Public License *
17 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
18 ***************************************************************************/
19
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23
24 #include "assert.h"
25 #include <target/target.h>
26 #include <target/target_type.h>
27 #include <target/smp.h>
28 #include "esp_xtensa_smp.h"
29
30 /*
31 Multiprocessor stuff common:
32
33 The ESP Xtensa chip can have several cores in it, which can run in SMP-mode if an
34 SMP-capable OS is running. The hardware has a few features which makes
35 SMP debugging much easier.
36
37 First of all, there's something called a 'break network', consisting of a
38 BreakIn input and a BreakOut output on each CPU. The idea is that as soon
39 as a CPU goes into debug mode for whatever reason, it'll signal that using
40 its DebugOut pin. This signal is connected to the other CPU's DebugIn
41 input, causing this CPU also to go into debugging mode. To resume execution
42 when using only this break network, we will need to manually resume both
43 CPUs.
44
45 An alternative to this is the XOCDMode output and the RunStall (or DebugStall)
46 input. When these are cross-connected, a CPU that goes into debug mode will
47 halt execution entirely on the other CPU. Execution on the other CPU can be
48 resumed by either the first CPU going out of debug mode, or the second CPU
49 going into debug mode: the stall is temporarily lifted as long as the stalled
50 CPU is in debug mode.
51
52 A third, separate, signal is CrossTrigger. This is connected in the same way
53 as the breakIn/breakOut network, but is for the TRAX (trace memory) feature;
54 it does not affect OCD in any way.
55 */
56
57 /*
58 Multiprocessor stuff:
59
60 The ESP Xtensa chip has several Xtensa cores inside, but represent themself to the OCD
61 as one chip that works in multithreading mode under FreeRTOS OS.
62 The core that initiate the stop condition will be defined as an active cpu.
63 When one core stops, then other core will be stopped automatically by smpbreak.
64 The core that initiates stop condition will be defined as an active core, and
65 registers of this core will be transferred.
66 */
67
68 #define ESP_XTENSA_SMP_EXAMINE_OTHER_CORES 5
69
70 static int esp_xtensa_smp_update_halt_gdb(struct target *target, bool *need_resume);
71
72 static inline struct esp_xtensa_smp_common *target_to_esp_xtensa_smp(struct target *target)
73 {
74 return container_of(target->arch_info, struct esp_xtensa_smp_common, esp_xtensa);
75 }
76
77 int esp_xtensa_smp_assert_reset(struct target *target)
78 {
79 return ERROR_OK;
80 }
81
82 int esp_xtensa_smp_deassert_reset(struct target *target)
83 {
84 LOG_TARGET_DEBUG(target, "begin");
85
86 int ret = xtensa_deassert_reset(target);
87 if (ret != ERROR_OK)
88 return ret;
89 /* in SMP mode when chip was running single-core app the other core can be left un-examined,
90 because examination is done before SOC reset. But after SOC reset it is functional and should be handled.
91 So try to examine un-examined core just after SOC reset */
92 if (target->smp && !target_was_examined(target))
93 ret = xtensa_examine(target);
94 return ret;
95 }
96
97 int esp_xtensa_smp_soft_reset_halt(struct target *target)
98 {
99 int res;
100 struct target_list *head;
101 struct esp_xtensa_smp_common *esp_xtensa_smp = target_to_esp_xtensa_smp(target);
102
103 LOG_TARGET_DEBUG(target, "begin");
104 /* in SMP mode we need to ensure that at first we reset SOC on PRO-CPU
105 and then call xtensa_assert_reset() for all cores */
106 if (target->smp && target->coreid != 0)
107 return ERROR_OK;
108 /* Reset the SoC first */
109 if (esp_xtensa_smp->chip_ops->reset) {
110 res = esp_xtensa_smp->chip_ops->reset(target);
111 if (res != ERROR_OK)
112 return res;
113 }
114 if (!target->smp)
115 return xtensa_assert_reset(target);
116
117 foreach_smp_target(head, target->smp_targets) {
118 res = xtensa_assert_reset(head->target);
119 if (res != ERROR_OK)
120 return res;
121 }
122 return ERROR_OK;
123 }
124
125 static struct target *get_halted_esp_xtensa_smp(struct target *target, int32_t coreid)
126 {
127 struct target_list *head;
128 struct target *curr;
129
130 foreach_smp_target(head, target->smp_targets) {
131 curr = head->target;
132 if ((curr->coreid == coreid) && (curr->state == TARGET_HALTED))
133 return curr;
134 }
135
136 return target;
137 }
138
139 int esp_xtensa_smp_poll(struct target *target)
140 {
141 enum target_state old_state = target->state;
142 struct esp_xtensa_smp_common *esp_xtensa_smp = target_to_esp_xtensa_smp(target);
143 struct target_list *head;
144 struct target *curr;
145 bool other_core_resume_req = false;
146
147 if (target->state == TARGET_HALTED && target->smp && target->gdb_service && !target->gdb_service->target) {
148 target->gdb_service->target = get_halted_esp_xtensa_smp(target, target->gdb_service->core[1]);
149 LOG_INFO("Switch GDB target to '%s'", target_name(target->gdb_service->target));
150 if (esp_xtensa_smp->chip_ops->on_halt)
151 esp_xtensa_smp->chip_ops->on_halt(target);
152 target_call_event_callbacks(target, TARGET_EVENT_HALTED);
153 return ERROR_OK;
154 }
155
156 int ret = esp_xtensa_poll(target);
157 if (ret != ERROR_OK)
158 return ret;
159
160 if (target->smp) {
161 if (target->state == TARGET_RESET) {
162 esp_xtensa_smp->examine_other_cores = ESP_XTENSA_SMP_EXAMINE_OTHER_CORES;
163 } else if (esp_xtensa_smp->examine_other_cores > 0 &&
164 (target->state == TARGET_RUNNING || target->state == TARGET_HALTED)) {
165 LOG_TARGET_DEBUG(target, "Check for unexamined cores after reset");
166 bool all_examined = true;
167 foreach_smp_target(head, target->smp_targets) {
168 curr = head->target;
169 if (curr == target)
170 continue;
171 if (!target_was_examined(curr)) {
172 if (target_examine_one(curr) != ERROR_OK) {
173 LOG_DEBUG("Failed to examine!");
174 all_examined = false;
175 }
176 }
177 }
178 if (all_examined)
179 esp_xtensa_smp->examine_other_cores = 0;
180 else
181 esp_xtensa_smp->examine_other_cores--;
182 }
183 }
184
185 if (old_state != TARGET_HALTED && target->state == TARGET_HALTED) {
186 if (target->smp) {
187 ret = esp_xtensa_smp_update_halt_gdb(target, &other_core_resume_req);
188 if (ret != ERROR_OK)
189 return ret;
190 }
191 /* Call any event callbacks that are applicable */
192 if (old_state == TARGET_DEBUG_RUNNING) {
193 target_call_event_callbacks(target, TARGET_EVENT_DEBUG_HALTED);
194 } else {
195 /* check whether any core polled by esp_xtensa_smp_update_halt_gdb() requested resume */
196 if (target->smp && other_core_resume_req) {
197 /* Resume xtensa_resume will handle BREAK instruction. */
198 ret = target_resume(target, 1, 0, 1, 0);
199 if (ret != ERROR_OK) {
200 LOG_ERROR("Failed to resume target");
201 return ret;
202 }
203 return ERROR_OK;
204 }
205 if (esp_xtensa_smp->chip_ops->on_halt)
206 esp_xtensa_smp->chip_ops->on_halt(target);
207 target_call_event_callbacks(target, TARGET_EVENT_HALTED);
208 }
209 }
210
211 return ERROR_OK;
212 }
213
214 static int esp_xtensa_smp_update_halt_gdb(struct target *target, bool *need_resume)
215 {
216 struct esp_xtensa_smp_common *esp_xtensa_smp;
217 struct target *gdb_target = NULL;
218 struct target_list *head;
219 struct target *curr;
220 int ret = ERROR_OK;
221
222 *need_resume = false;
223
224 if (target->gdb_service && target->gdb_service->target)
225 LOG_DEBUG("GDB target '%s'", target_name(target->gdb_service->target));
226
227 if (target->gdb_service && target->gdb_service->core[0] == -1) {
228 target->gdb_service->target = target;
229 target->gdb_service->core[0] = target->coreid;
230 LOG_INFO("Set GDB target to '%s'", target_name(target));
231 }
232
233 if (target->gdb_service)
234 gdb_target = target->gdb_service->target;
235
236 /* due to smpbreak config other cores can also go to HALTED state */
237 foreach_smp_target(head, target->smp_targets) {
238 curr = head->target;
239 LOG_DEBUG("Check target '%s'", target_name(curr));
240 /* skip calling context */
241 if (curr == target)
242 continue;
243 if (!target_was_examined(curr)) {
244 curr->state = TARGET_HALTED;
245 continue;
246 }
247 /* skip targets that were already halted */
248 if (curr->state == TARGET_HALTED)
249 continue;
250 /* Skip gdb_target; it alerts GDB so has to be polled as last one */
251 if (curr == gdb_target)
252 continue;
253 LOG_DEBUG("Poll target '%s'", target_name(curr));
254
255 esp_xtensa_smp = target_to_esp_xtensa_smp(curr);
256 /* avoid auto-resume after syscall, it will be done later */
257 esp_xtensa_smp->other_core_does_resume = true;
258 /* avoid recursion in esp_xtensa_smp_poll() */
259 curr->smp = 0;
260 if (esp_xtensa_smp->chip_ops->poll)
261 ret = esp_xtensa_smp->chip_ops->poll(curr);
262 else
263 ret = esp_xtensa_smp_poll(curr);
264 curr->smp = 1;
265 if (ret != ERROR_OK)
266 return ret;
267 esp_xtensa_smp->other_core_does_resume = false;
268 }
269
270 /* after all targets were updated, poll the gdb serving target */
271 if (gdb_target && gdb_target != target) {
272 esp_xtensa_smp = target_to_esp_xtensa_smp(gdb_target);
273 if (esp_xtensa_smp->chip_ops->poll)
274 ret = esp_xtensa_smp->chip_ops->poll(gdb_target);
275 else
276 ret = esp_xtensa_smp_poll(gdb_target);
277 }
278
279 LOG_DEBUG("exit");
280
281 return ret;
282 }
283
284 static inline int esp_xtensa_smp_smpbreak_disable(struct target *target, uint32_t *smp_break)
285 {
286 int res = xtensa_smpbreak_get(target, smp_break);
287 if (res != ERROR_OK)
288 return res;
289 return xtensa_smpbreak_set(target, 0);
290 }
291
292 static inline int esp_xtensa_smp_smpbreak_restore(struct target *target, uint32_t smp_break)
293 {
294 return xtensa_smpbreak_set(target, smp_break);
295 }
296
297 static int esp_xtensa_smp_resume_cores(struct target *target,
298 int handle_breakpoints,
299 int debug_execution)
300 {
301 struct target_list *head;
302 struct target *curr;
303
304 LOG_TARGET_DEBUG(target, "begin");
305
306 foreach_smp_target(head, target->smp_targets) {
307 curr = head->target;
308 /* in single-core mode disabled core cannot be examined, but need to be resumed too*/
309 if ((curr != target) && (curr->state != TARGET_RUNNING) && target_was_examined(curr)) {
310 /* resume current address, not in SMP mode */
311 curr->smp = 0;
312 int res = esp_xtensa_smp_resume(curr, 1, 0, handle_breakpoints, debug_execution);
313 curr->smp = 1;
314 if (res != ERROR_OK)
315 return res;
316 }
317 }
318 return ERROR_OK;
319 }
320
321 int esp_xtensa_smp_resume(struct target *target,
322 int current,
323 target_addr_t address,
324 int handle_breakpoints,
325 int debug_execution)
326 {
327 int res;
328 uint32_t smp_break;
329
330 xtensa_smpbreak_get(target, &smp_break);
331 LOG_TARGET_DEBUG(target, "smp_break=0x%" PRIx32, smp_break);
332
333 /* dummy resume for smp toggle in order to reduce gdb impact */
334 if ((target->smp) && (target->gdb_service) && (target->gdb_service->core[1] != -1)) {
335 /* simulate a start and halt of target */
336 target->gdb_service->target = NULL;
337 target->gdb_service->core[0] = target->gdb_service->core[1];
338 /* fake resume at next poll we play the target core[1], see poll*/
339 LOG_TARGET_DEBUG(target, "Fake resume");
340 target_call_event_callbacks(target, TARGET_EVENT_RESUMED);
341 return ERROR_OK;
342 }
343
344 /* xtensa_prepare_resume() can step over breakpoint/watchpoint and generate signals on BreakInOut circuit for
345 * other cores. So disconnect this core from BreakInOut circuit and do xtensa_prepare_resume(). */
346 res = esp_xtensa_smp_smpbreak_disable(target, &smp_break);
347 if (res != ERROR_OK)
348 return res;
349 res = xtensa_prepare_resume(target, current, address, handle_breakpoints, debug_execution);
350 /* restore configured BreakInOut signals config */
351 int ret = esp_xtensa_smp_smpbreak_restore(target, smp_break);
352 if (ret != ERROR_OK)
353 return ret;
354 if (res != ERROR_OK) {
355 LOG_TARGET_ERROR(target, "Failed to prepare for resume!");
356 return res;
357 }
358
359 if (target->smp) {
360 if (target->gdb_service)
361 target->gdb_service->core[0] = -1;
362 res = esp_xtensa_smp_resume_cores(target, handle_breakpoints, debug_execution);
363 if (res != ERROR_OK)
364 return res;
365 }
366
367 res = xtensa_do_resume(target);
368 if (res != ERROR_OK) {
369 LOG_TARGET_ERROR(target, "Failed to resume!");
370 return res;
371 }
372
373 target->debug_reason = DBG_REASON_NOTHALTED;
374 if (!debug_execution)
375 target->state = TARGET_RUNNING;
376 else
377 target->state = TARGET_DEBUG_RUNNING;
378
379 target_call_event_callbacks(target, TARGET_EVENT_RESUMED);
380 return ERROR_OK;
381 }
382
383 int esp_xtensa_smp_step(struct target *target,
384 int current,
385 target_addr_t address,
386 int handle_breakpoints)
387 {
388 int res;
389 uint32_t smp_break = 0;
390 struct esp_xtensa_smp_common *esp_xtensa_smp = target_to_esp_xtensa_smp(target);
391
392 if (target->smp) {
393 res = esp_xtensa_smp_smpbreak_disable(target, &smp_break);
394 if (res != ERROR_OK)
395 return res;
396 }
397 res = xtensa_step(target, current, address, handle_breakpoints);
398
399 if (res == ERROR_OK) {
400 if (esp_xtensa_smp->chip_ops->on_halt)
401 esp_xtensa_smp->chip_ops->on_halt(target);
402 target_call_event_callbacks(target, TARGET_EVENT_HALTED);
403 }
404
405 if (target->smp) {
406 int ret = esp_xtensa_smp_smpbreak_restore(target, smp_break);
407 if (ret != ERROR_OK)
408 return ret;
409 }
410
411 return res;
412 }
413
414 int esp_xtensa_smp_watchpoint_add(struct target *target, struct watchpoint *watchpoint)
415 {
416 int res = xtensa_watchpoint_add(target, watchpoint);
417 if (res != ERROR_OK)
418 return res;
419
420 if (!target->smp)
421 return ERROR_OK;
422
423 struct target_list *head;
424 foreach_smp_target(head, target->smp_targets) {
425 struct target *curr = head->target;
426 if (curr == target || !target_was_examined(curr))
427 continue;
428 /* Need to use high level API here because every target for core contains list of watchpoints.
429 * GDB works with active core only, so we need to duplicate every watchpoint on other cores,
430 * otherwise watchpoint_free() on active core can fail if WP has been initially added on another core. */
431 curr->smp = 0;
432 res = watchpoint_add(curr, watchpoint->address, watchpoint->length,
433 watchpoint->rw, watchpoint->value, watchpoint->mask);
434 curr->smp = 1;
435 if (res != ERROR_OK)
436 return res;
437 }
438 return ERROR_OK;
439 }
440
441 int esp_xtensa_smp_watchpoint_remove(struct target *target, struct watchpoint *watchpoint)
442 {
443 int res = xtensa_watchpoint_remove(target, watchpoint);
444 if (res != ERROR_OK)
445 return res;
446
447 if (!target->smp)
448 return ERROR_OK;
449
450 struct target_list *head;
451 foreach_smp_target(head, target->smp_targets) {
452 struct target *curr = head->target;
453 if (curr == target)
454 continue;
455 /* see big comment in esp_xtensa_smp_watchpoint_add() */
456 curr->smp = 0;
457 watchpoint_remove(curr, watchpoint->address);
458 curr->smp = 1;
459 }
460 return ERROR_OK;
461 }
462
463 int esp_xtensa_smp_init_arch_info(struct target *target,
464 struct esp_xtensa_smp_common *esp_xtensa_smp,
465 const struct xtensa_config *xtensa_cfg,
466 struct xtensa_debug_module_config *dm_cfg,
467 const struct esp_xtensa_smp_chip_ops *chip_ops)
468 {
469 int ret = esp_xtensa_init_arch_info(target, &esp_xtensa_smp->esp_xtensa, xtensa_cfg, dm_cfg);
470 if (ret != ERROR_OK)
471 return ret;
472 esp_xtensa_smp->chip_ops = chip_ops;
473 esp_xtensa_smp->examine_other_cores = ESP_XTENSA_SMP_EXAMINE_OTHER_CORES;
474 return ERROR_OK;
475 }
476
477 int esp_xtensa_smp_target_init(struct command_context *cmd_ctx, struct target *target)
478 {
479 return esp_xtensa_target_init(cmd_ctx, target);
480 }
481
482 COMMAND_HANDLER(esp_xtensa_smp_cmd_permissive_mode)
483 {
484 struct target *target = get_current_target(CMD_CTX);
485 if (target->smp && CMD_ARGC > 0) {
486 struct target_list *head;
487 struct target *curr;
488 foreach_smp_target(head, target->smp_targets) {
489 curr = head->target;
490 int ret = CALL_COMMAND_HANDLER(xtensa_cmd_permissive_mode_do,
491 target_to_xtensa(curr));
492 if (ret != ERROR_OK)
493 return ret;
494 }
495 return ERROR_OK;
496 }
497 return CALL_COMMAND_HANDLER(xtensa_cmd_permissive_mode_do,
498 target_to_xtensa(target));
499 }
500
501 COMMAND_HANDLER(esp_xtensa_smp_cmd_smpbreak)
502 {
503 struct target *target = get_current_target(CMD_CTX);
504 if (target->smp && CMD_ARGC > 0) {
505 struct target_list *head;
506 struct target *curr;
507 foreach_smp_target(head, target->smp_targets) {
508 curr = head->target;
509 int ret = CALL_COMMAND_HANDLER(xtensa_cmd_smpbreak_do, curr);
510 if (ret != ERROR_OK)
511 return ret;
512 }
513 return ERROR_OK;
514 }
515 return CALL_COMMAND_HANDLER(xtensa_cmd_smpbreak_do, target);
516 }
517
518 COMMAND_HANDLER(esp_xtensa_smp_cmd_mask_interrupts)
519 {
520 struct target *target = get_current_target(CMD_CTX);
521 if (target->smp && CMD_ARGC > 0) {
522 struct target_list *head;
523 struct target *curr;
524 foreach_smp_target(head, target->smp_targets) {
525 curr = head->target;
526 int ret = CALL_COMMAND_HANDLER(xtensa_cmd_mask_interrupts_do,
527 target_to_xtensa(curr));
528 if (ret != ERROR_OK)
529 return ret;
530 }
531 return ERROR_OK;
532 }
533 return CALL_COMMAND_HANDLER(xtensa_cmd_mask_interrupts_do,
534 target_to_xtensa(target));
535 }
536
537 COMMAND_HANDLER(esp_xtensa_smp_cmd_perfmon_enable)
538 {
539 struct target *target = get_current_target(CMD_CTX);
540 if (target->smp && CMD_ARGC > 0) {
541 struct target_list *head;
542 struct target *curr;
543 foreach_smp_target(head, target->smp_targets) {
544 curr = head->target;
545 int ret = CALL_COMMAND_HANDLER(xtensa_cmd_perfmon_enable_do,
546 target_to_xtensa(curr));
547 if (ret != ERROR_OK)
548 return ret;
549 }
550 return ERROR_OK;
551 }
552 return CALL_COMMAND_HANDLER(xtensa_cmd_perfmon_enable_do,
553 target_to_xtensa(target));
554 }
555
556 COMMAND_HANDLER(esp_xtensa_smp_cmd_perfmon_dump)
557 {
558 struct target *target = get_current_target(CMD_CTX);
559 if (target->smp) {
560 struct target_list *head;
561 struct target *curr;
562 foreach_smp_target(head, target->smp_targets) {
563 curr = head->target;
564 LOG_INFO("CPU%d:", curr->coreid);
565 int ret = CALL_COMMAND_HANDLER(xtensa_cmd_perfmon_dump_do,
566 target_to_xtensa(curr));
567 if (ret != ERROR_OK)
568 return ret;
569 }
570 return ERROR_OK;
571 }
572 return CALL_COMMAND_HANDLER(xtensa_cmd_perfmon_dump_do,
573 target_to_xtensa(target));
574 }
575
576 COMMAND_HANDLER(esp_xtensa_smp_cmd_tracestart)
577 {
578 struct target *target = get_current_target(CMD_CTX);
579 if (target->smp) {
580 struct target_list *head;
581 struct target *curr;
582 foreach_smp_target(head, target->smp_targets) {
583 curr = head->target;
584 int ret = CALL_COMMAND_HANDLER(xtensa_cmd_tracestart_do,
585 target_to_xtensa(curr));
586 if (ret != ERROR_OK)
587 return ret;
588 }
589 return ERROR_OK;
590 }
591 return CALL_COMMAND_HANDLER(xtensa_cmd_tracestart_do,
592 target_to_xtensa(target));
593 }
594
595 COMMAND_HANDLER(esp_xtensa_smp_cmd_tracestop)
596 {
597 struct target *target = get_current_target(CMD_CTX);
598 if (target->smp) {
599 struct target_list *head;
600 struct target *curr;
601 foreach_smp_target(head, target->smp_targets) {
602 curr = head->target;
603 int ret = CALL_COMMAND_HANDLER(xtensa_cmd_tracestop_do,
604 target_to_xtensa(curr));
605 if (ret != ERROR_OK)
606 return ret;
607 }
608 return ERROR_OK;
609 }
610 return CALL_COMMAND_HANDLER(xtensa_cmd_tracestop_do,
611 target_to_xtensa(target));
612 }
613
614 COMMAND_HANDLER(esp_xtensa_smp_cmd_tracedump)
615 {
616 struct target *target = get_current_target(CMD_CTX);
617 if (target->smp) {
618 struct target_list *head;
619 struct target *curr;
620 int32_t cores_max_id = 0;
621 /* assume that core IDs are assigned to SMP targets sequentially: 0,1,2... */
622 foreach_smp_target(head, target->smp_targets) {
623 curr = head->target;
624 if (cores_max_id < curr->coreid)
625 cores_max_id = curr->coreid;
626 }
627 if (CMD_ARGC < ((uint32_t)cores_max_id + 1)) {
628 command_print(CMD,
629 "Need %d filenames to dump to as output!",
630 cores_max_id + 1);
631 return ERROR_FAIL;
632 }
633 foreach_smp_target(head, target->smp_targets) {
634 curr = head->target;
635 int ret = CALL_COMMAND_HANDLER(xtensa_cmd_tracedump_do,
636 target_to_xtensa(curr), CMD_ARGV[curr->coreid]);
637 if (ret != ERROR_OK)
638 return ret;
639 }
640 return ERROR_OK;
641 }
642 return CALL_COMMAND_HANDLER(xtensa_cmd_tracedump_do,
643 target_to_xtensa(target), CMD_ARGV[0]);
644 }
645
646 const struct command_registration esp_xtensa_smp_xtensa_command_handlers[] = {
647 {
648 .name = "set_permissive",
649 .handler = esp_xtensa_smp_cmd_permissive_mode,
650 .mode = COMMAND_ANY,
651 .help = "When set to 1, enable Xtensa permissive mode (less client-side checks)",
652 .usage = "[0|1]",
653 },
654 {
655 .name = "maskisr",
656 .handler = esp_xtensa_smp_cmd_mask_interrupts,
657 .mode = COMMAND_ANY,
658 .help = "mask Xtensa interrupts at step",
659 .usage = "['on'|'off']",
660 },
661 {
662 .name = "smpbreak",
663 .handler = esp_xtensa_smp_cmd_smpbreak,
664 .mode = COMMAND_ANY,
665 .help = "Set the way the CPU chains OCD breaks",
666 .usage =
667 "[none|breakinout|runstall] | [BreakIn] [BreakOut] [RunStallIn] [DebugModeOut]",
668 },
669 {
670 .name = "perfmon_enable",
671 .handler = esp_xtensa_smp_cmd_perfmon_enable,
672 .mode = COMMAND_EXEC,
673 .help = "Enable and start performance counter",
674 .usage = "<counter_id> <select> [mask] [kernelcnt] [tracelevel]",
675 },
676 {
677 .name = "perfmon_dump",
678 .handler = esp_xtensa_smp_cmd_perfmon_dump,
679 .mode = COMMAND_EXEC,
680 .help =
681 "Dump performance counter value. If no argument specified, dumps all counters.",
682 .usage = "[counter_id]",
683 },
684 {
685 .name = "tracestart",
686 .handler = esp_xtensa_smp_cmd_tracestart,
687 .mode = COMMAND_EXEC,
688 .help =
689 "Tracing: Set up and start a trace. Optionally set stop trigger address and amount of data captured after.",
690 .usage = "[pc <pcval>/[maskbitcount]] [after <n> [ins|words]]",
691 },
692 {
693 .name = "tracestop",
694 .handler = esp_xtensa_smp_cmd_tracestop,
695 .mode = COMMAND_EXEC,
696 .help = "Tracing: Stop current trace as started by the tracestart command",
697 .usage = "",
698 },
699 {
700 .name = "tracedump",
701 .handler = esp_xtensa_smp_cmd_tracedump,
702 .mode = COMMAND_EXEC,
703 .help = "Tracing: Dump trace memory to a files. One file per core.",
704 .usage = "<outfile1> <outfile2>",
705 },
706 COMMAND_REGISTRATION_DONE
707 };
708
709 const struct command_registration esp_xtensa_smp_command_handlers[] = {
710 {
711 .name = "xtensa",
712 .usage = "",
713 .chain = esp_xtensa_smp_xtensa_command_handlers,
714 },
715 COMMAND_REGISTRATION_DONE
716 };

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)