1 // SPDX-License-Identifier: GPL-2.0-or-later
3 /***************************************************************************
4 * ESP32xx application tracing module for OpenOCD *
5 * Copyright (C) 2017 Espressif Systems Ltd. *
6 ***************************************************************************/
12 #ifdef HAVE_ARPA_INET_H
13 #include <arpa/inet.h>
21 #include <netinet/tcp.h>
22 #include <sys/ioctl.h>
25 #include <helper/list.h>
26 #include <helper/time_support.h>
27 #include <target/target.h>
28 #include <target/target_type.h>
29 #include <target/smp.h>
30 #include <server/server.h>
31 #include "esp_xtensa.h"
32 #include "esp_xtensa_smp.h"
33 #include "esp_xtensa_apptrace.h"
34 #include "esp32_apptrace.h"
35 #include "esp32_sysview.h"
36 #include "segger_sysview.h"
38 #define ESP32_APPTRACE_USER_BLOCK_CORE(_v_) ((_v_) >> 15)
39 #define ESP32_APPTRACE_USER_BLOCK_LEN(_v_) ((_v_) & ~BIT(15))
41 #define ESP32_APPTRACE_USER_BLOCK_HDR_SZ 4
43 #define ESP_APPTRACE_CMD_MODE_GEN 0
44 #define ESP_APPTRACE_CMD_MODE_SYSVIEW 1
45 #define ESP_APPTRACE_CMD_MODE_SYSVIEW_MCORE 2
46 #define ESP_APPTRACE_CMD_MODE_SYNC 3
48 #define ESP32_APPTRACE_TGT_STATE_TMO 5000
49 #define ESP_APPTRACE_BLOCKS_POOL_SZ 10
51 struct esp32_apptrace_dest_file_data
{
55 struct esp32_apptrace_dest_tcp_data
{
59 struct esp32_apptrace_target_state
{
65 struct esp_apptrace_target2host_hdr
{
69 #define APPTRACE_BLOCK_SIZE_OFFSET 0
70 #define APPTRACE_WR_SIZE_OFFSET 2
72 struct esp32_apptrace_block
{
73 struct list_head node
;
78 static int esp32_apptrace_data_processor(void *priv
);
79 static int esp32_apptrace_get_data_info(struct esp32_apptrace_cmd_ctx
*ctx
,
80 struct esp32_apptrace_target_state
*target_state
,
81 uint32_t *fired_target_num
);
82 static int esp32_apptrace_safe_halt_targets(struct esp32_apptrace_cmd_ctx
*ctx
,
83 struct esp32_apptrace_target_state
*targets
);
84 static struct esp32_apptrace_block
*esp32_apptrace_free_block_get(struct esp32_apptrace_cmd_ctx
*ctx
);
85 static int esp32_apptrace_handle_trace_block(struct esp32_apptrace_cmd_ctx
*ctx
,
86 struct esp32_apptrace_block
*block
);
87 static int esp32_sysview_start(struct esp32_apptrace_cmd_ctx
*ctx
);
88 static int esp32_sysview_stop(struct esp32_apptrace_cmd_ctx
*ctx
);
90 static const bool s_time_stats_enable
= true;
92 /*********************************************************************
93 * Trace destination API
94 **********************************************************************/
96 static int esp32_apptrace_file_dest_write(void *priv
, uint8_t *data
, int size
)
98 struct esp32_apptrace_dest_file_data
*dest_data
= (struct esp32_apptrace_dest_file_data
*)priv
;
100 int wr_sz
= write(dest_data
->fout
, data
, size
);
102 LOG_ERROR("Failed to write %d bytes to out file (%d)! Written %d.", size
, errno
, wr_sz
);
108 static int esp32_apptrace_file_dest_cleanup(void *priv
)
110 struct esp32_apptrace_dest_file_data
*dest_data
= (struct esp32_apptrace_dest_file_data
*)priv
;
112 if (dest_data
->fout
> 0)
113 close(dest_data
->fout
);
118 static int esp32_apptrace_file_dest_init(struct esp32_apptrace_dest
*dest
, const char *dest_name
)
120 struct esp32_apptrace_dest_file_data
*dest_data
= calloc(1, sizeof(*dest_data
));
122 LOG_ERROR("Failed to alloc mem for file dest!");
126 LOG_INFO("Open file %s", dest_name
);
127 dest_data
->fout
= open(dest_name
, O_WRONLY
| O_CREAT
| O_TRUNC
| O_BINARY
, 0666);
128 if (dest_data
->fout
<= 0) {
129 LOG_ERROR("Failed to open file %s", dest_name
);
134 dest
->priv
= dest_data
;
135 dest
->write
= esp32_apptrace_file_dest_write
;
136 dest
->clean
= esp32_apptrace_file_dest_cleanup
;
137 dest
->log_progress
= true;
142 static int esp32_apptrace_console_dest_write(void *priv
, uint8_t *data
, int size
)
144 LOG_USER_N("%.*s", size
, data
);
148 static int esp32_apptrace_console_dest_cleanup(void *priv
)
153 static int esp32_apptrace_console_dest_init(struct esp32_apptrace_dest
*dest
, const char *dest_name
)
156 dest
->write
= esp32_apptrace_console_dest_write
;
157 dest
->clean
= esp32_apptrace_console_dest_cleanup
;
158 dest
->log_progress
= false;
163 static int esp32_apptrace_tcp_dest_write(void *priv
, uint8_t *data
, int size
)
165 struct esp32_apptrace_dest_tcp_data
*dest_data
= (struct esp32_apptrace_dest_tcp_data
*)priv
;
166 int wr_sz
= write_socket(dest_data
->sockfd
, data
, size
);
168 LOG_ERROR("Failed to write %u bytes to out socket (%d)! Written %d.", size
, errno
, wr_sz
);
174 static int esp32_apptrace_tcp_dest_cleanup(void *priv
)
176 struct esp32_apptrace_dest_tcp_data
*dest_data
= (struct esp32_apptrace_dest_tcp_data
*)priv
;
178 if (dest_data
->sockfd
> 0)
179 close_socket(dest_data
->sockfd
);
184 static int esp32_apptrace_tcp_dest_init(struct esp32_apptrace_dest
*dest
, const char *dest_name
)
186 const char *port_sep
= strchr(dest_name
, ':');
187 /* separator not found, or was the first or the last character */
188 if (!port_sep
|| port_sep
== dest_name
|| port_sep
== dest_name
+ strlen(dest_name
) - 1) {
189 LOG_ERROR("apptrace: Invalid connection URI, format should be tcp://host:port");
190 return ERROR_COMMAND_ARGUMENT_INVALID
;
192 size_t hostname_len
= port_sep
- dest_name
;
194 char hostname
[64] = { 0 };
195 if (hostname_len
>= sizeof(hostname
)) {
196 LOG_ERROR("apptrace: Hostname too long");
197 return ERROR_COMMAND_ARGUMENT_INVALID
;
199 memcpy(hostname
, dest_name
, hostname_len
);
201 const char *port_str
= port_sep
+ 1;
204 #ifdef AI_NUMERICSERV
205 flags
|= AI_NUMERICSERV
;
206 #endif /* AI_NUMERICSERV */
207 struct addrinfo hint
= {
208 .ai_family
= AF_UNSPEC
,
209 .ai_socktype
= SOCK_STREAM
,
213 int res
= getaddrinfo(hostname
, port_str
, &hint
, &ai
);
215 LOG_ERROR("apptrace: Failed to resolve host name: %s", hostname
);
219 for (struct addrinfo
*ai_it
= ai
; ai_it
; ai_it
= ai_it
->ai_next
) {
220 sockfd
= socket(ai_it
->ai_family
, ai_it
->ai_socktype
, ai_it
->ai_protocol
);
222 LOG_DEBUG("apptrace: Failed to create socket (%d, %d, %d) (%s)",
230 char cur_hostname
[NI_MAXHOST
];
231 char cur_portname
[NI_MAXSERV
];
233 getnameinfo(ai_it
->ai_addr
, ai_it
->ai_addrlen
, cur_hostname
,
234 sizeof(cur_hostname
),
235 cur_portname
, sizeof(cur_portname
),
236 NI_NUMERICHOST
| NI_NUMERICSERV
);
240 LOG_INFO("apptrace: Trying to connect to %s:%s", cur_hostname
, cur_portname
);
241 if (connect(sockfd
, ai_it
->ai_addr
, ai_it
->ai_addrlen
) < 0) {
242 close_socket(sockfd
);
244 LOG_WARNING("apptrace: Connection failed (%s)", strerror(errno
));
251 LOG_ERROR("apptrace: Could not connect to %s:%s", hostname
, port_str
);
254 LOG_INFO("apptrace: Connected!");
256 struct esp32_apptrace_dest_tcp_data
*dest_data
= calloc(1, sizeof(struct esp32_apptrace_dest_tcp_data
));
258 LOG_ERROR("apptrace: Failed to alloc mem for tcp dest!");
259 close_socket(sockfd
);
263 dest_data
->sockfd
= sockfd
;
264 dest
->priv
= dest_data
;
265 dest
->write
= esp32_apptrace_tcp_dest_write
;
266 dest
->clean
= esp32_apptrace_tcp_dest_cleanup
;
267 dest
->log_progress
= true;
272 int esp32_apptrace_dest_init(struct esp32_apptrace_dest dest
[], const char *dest_paths
[], unsigned int max_dests
)
277 for (i
= 0; i
< max_dests
; i
++) {
278 if (strncmp(dest_paths
[i
], "file://", 7) == 0)
279 res
= esp32_apptrace_file_dest_init(&dest
[i
], &dest_paths
[i
][7]);
280 else if (strncmp(dest_paths
[i
], "con:", 4) == 0)
281 res
= esp32_apptrace_console_dest_init(&dest
[i
], NULL
);
282 else if (strncmp(dest_paths
[i
], "tcp://", 6) == 0)
283 res
= esp32_apptrace_tcp_dest_init(&dest
[i
], &dest_paths
[i
][6]);
287 if (res
!= ERROR_OK
) {
288 LOG_ERROR("apptrace: Failed to init trace data destination '%s'!", dest_paths
[i
]);
296 int esp32_apptrace_dest_cleanup(struct esp32_apptrace_dest dest
[], unsigned int max_dests
)
298 for (unsigned int i
= 0; i
< max_dests
; i
++) {
299 if (dest
[i
].clean
&& dest
[i
].priv
) {
300 int res
= dest
[i
].clean(dest
[i
].priv
);
308 /*********************************************************************
309 * Trace data blocks management API
310 **********************************************************************/
311 static void esp32_apptrace_blocks_pool_cleanup(struct esp32_apptrace_cmd_ctx
*ctx
)
313 struct esp32_apptrace_block
*cur
;
314 struct list_head
*head
= &ctx
->free_trace_blocks
;
315 struct list_head
*tmp
, *pos
;
317 list_for_each_safe(pos
, tmp
, head
) {
318 cur
= list_entry(pos
, struct esp32_apptrace_block
, node
);
320 list_del(&cur
->node
);
326 head
= &ctx
->ready_trace_blocks
;
328 list_for_each_safe(pos
, tmp
, head
) {
329 cur
= list_entry(pos
, struct esp32_apptrace_block
, node
);
331 list_del(&cur
->node
);
338 struct esp32_apptrace_block
*esp32_apptrace_free_block_get(struct esp32_apptrace_cmd_ctx
*ctx
)
340 struct esp32_apptrace_block
*block
= NULL
;
342 if (!list_empty(&ctx
->free_trace_blocks
)) {
344 block
= list_first_entry(&ctx
->free_trace_blocks
, struct esp32_apptrace_block
, node
);
345 list_del(&block
->node
);
351 static int esp32_apptrace_ready_block_put(struct esp32_apptrace_cmd_ctx
*ctx
, struct esp32_apptrace_block
*block
)
353 LOG_DEBUG("esp32_apptrace_ready_block_put");
354 /* add to ready blocks list */
355 INIT_LIST_HEAD(&block
->node
);
356 list_add(&block
->node
, &ctx
->ready_trace_blocks
);
361 static struct esp32_apptrace_block
*esp32_apptrace_ready_block_get(struct esp32_apptrace_cmd_ctx
*ctx
)
363 if (list_empty(&ctx
->ready_trace_blocks
))
366 struct esp32_apptrace_block
*block
=
367 list_last_entry(&ctx
->ready_trace_blocks
, struct esp32_apptrace_block
, node
);
369 /* remove it from ready list */
370 list_del(&block
->node
);
375 static int esp32_apptrace_block_free(struct esp32_apptrace_cmd_ctx
*ctx
, struct esp32_apptrace_block
*block
)
377 /* add to free blocks list */
378 INIT_LIST_HEAD(&block
->node
);
379 list_add(&block
->node
, &ctx
->free_trace_blocks
);
384 static int esp32_apptrace_wait_tracing_finished(struct esp32_apptrace_cmd_ctx
*ctx
)
386 int64_t timeout
= timeval_ms() + (LOG_LEVEL_IS(LOG_LVL_DEBUG
) ? 70000 : 5000);
387 while (!list_empty(&ctx
->ready_trace_blocks
)) {
389 if (timeval_ms() >= timeout
) {
390 LOG_ERROR("Failed to wait for pended trace blocks!");
394 /* signal timer callback to stop */
396 target_unregister_timer_callback(esp32_apptrace_data_processor
, ctx
);
400 /*********************************************************************
402 **********************************************************************/
404 int esp32_apptrace_cmd_ctx_init(struct esp32_apptrace_cmd_ctx
*cmd_ctx
, struct command_invocation
*cmd
, int mode
)
406 struct target
*target
= get_current_target(CMD_CTX
);
408 memset(cmd_ctx
, 0, sizeof(struct esp32_apptrace_cmd_ctx
));
409 cmd_ctx
->target
= target
;
410 cmd_ctx
->mode
= mode
;
411 cmd_ctx
->target_state
= target
->state
;
415 struct target_list
*head
;
418 cmd_ctx
->cores_num
= 0;
419 foreach_smp_target(head
, target
->smp_targets
) {
421 if (i
== ESP32_APPTRACE_MAX_CORES_NUM
) {
422 command_print(cmd
, "Too many cores configured! Max %d cores are supported.",
423 ESP32_APPTRACE_MAX_CORES_NUM
);
426 if (!target_was_examined(curr
))
428 cmd_ctx
->cores_num
++;
429 cmd_ctx
->cpus
[i
++] = curr
;
432 cmd_ctx
->cores_num
= 1;
433 cmd_ctx
->cpus
[0] = target
;
435 /* some relies on ESP32_APPTRACE_MAX_CORES_NUM
436 * TODO: remove that dependency */
437 assert(cmd_ctx
->cores_num
<= ESP32_APPTRACE_MAX_CORES_NUM
&& "Too many cores number!");
439 struct xtensa
*xtensa
= target
->arch_info
;
440 if (xtensa
->common_magic
== XTENSA_COMMON_MAGIC
) {
441 cmd_ctx
->hw
= target_to_esp_xtensa(target
)->apptrace
.hw
;
442 } else { /* TODO: riscv is not supported yet */
443 command_print(cmd
, "Unsupported target arch 0x%X", xtensa
->common_magic
);
447 cmd_ctx
->max_trace_block_sz
= cmd_ctx
->hw
->max_block_size_get(cmd_ctx
->cpus
[0]);
448 if (cmd_ctx
->max_trace_block_sz
== 0) {
449 command_print(cmd
, "Failed to get max trace block size!");
452 LOG_INFO("Total trace memory: %" PRIu32
" bytes", cmd_ctx
->max_trace_block_sz
);
454 INIT_LIST_HEAD(&cmd_ctx
->ready_trace_blocks
);
455 INIT_LIST_HEAD(&cmd_ctx
->free_trace_blocks
);
456 for (unsigned int i
= 0; i
< ESP_APPTRACE_BLOCKS_POOL_SZ
; i
++) {
457 struct esp32_apptrace_block
*block
= calloc(1, sizeof(struct esp32_apptrace_block
));
459 command_print(cmd
, "Failed to alloc trace buffer entry!");
460 esp32_apptrace_blocks_pool_cleanup(cmd_ctx
);
463 block
->data
= malloc(cmd_ctx
->max_trace_block_sz
);
466 command_print(cmd
, "Failed to alloc trace buffer %" PRIu32
" bytes!", cmd_ctx
->max_trace_block_sz
);
467 esp32_apptrace_blocks_pool_cleanup(cmd_ctx
);
470 INIT_LIST_HEAD(&block
->node
);
471 list_add(&block
->node
, &cmd_ctx
->free_trace_blocks
);
474 cmd_ctx
->running
= 1;
475 if (cmd_ctx
->mode
!= ESP_APPTRACE_CMD_MODE_SYNC
) {
476 int res
= target_register_timer_callback(esp32_apptrace_data_processor
,
478 TARGET_TIMER_TYPE_PERIODIC
,
480 if (res
!= ERROR_OK
) {
481 command_print(cmd
, "Failed to start trace data timer callback (%d)!", res
);
482 esp32_apptrace_blocks_pool_cleanup(cmd_ctx
);
487 if (s_time_stats_enable
) {
488 cmd_ctx
->stats
.min_blk_read_time
= 1000000.0;
489 cmd_ctx
->stats
.min_blk_proc_time
= 1000000.0;
491 if (duration_start(&cmd_ctx
->idle_time
) != 0) {
492 command_print(cmd
, "Failed to start idle time measurement!");
493 esp32_apptrace_cmd_ctx_cleanup(cmd_ctx
);
500 int esp32_apptrace_cmd_ctx_cleanup(struct esp32_apptrace_cmd_ctx
*cmd_ctx
)
502 esp32_apptrace_blocks_pool_cleanup(cmd_ctx
);
506 #define ESP32_APPTRACE_CMD_NUM_ARG_CHECK(_cmd_, _arg_, _start_, _end_) \
508 if ((_arg_) == 0 && (_start_) == (_end_)) { \
509 command_print(_cmd_, "Invalid '" # _arg_ "' arg!"); \
514 void esp32_apptrace_cmd_args_parse(struct esp32_apptrace_cmd_ctx
*cmd_ctx
,
515 struct esp32_apptrace_cmd_data
*cmd_data
,
521 cmd_data
->poll_period
= strtoul(argv
[0], &end
, 10);
522 ESP32_APPTRACE_CMD_NUM_ARG_CHECK(cmd_ctx
->cmd
, cmd_data
->poll_period
, argv
[0], end
);
524 cmd_data
->max_len
= strtoul(argv
[1], &end
, 10);
525 ESP32_APPTRACE_CMD_NUM_ARG_CHECK(cmd_ctx
->cmd
, cmd_data
->max_len
, argv
[1], end
);
527 int32_t tmo
= strtol(argv
[2], &end
, 10);
528 ESP32_APPTRACE_CMD_NUM_ARG_CHECK(cmd_ctx
->cmd
, tmo
, argv
[2], end
);
529 cmd_ctx
->stop_tmo
= 1.0 * tmo
;
531 cmd_data
->wait4halt
= strtoul(argv
[3], &end
, 10);
532 ESP32_APPTRACE_CMD_NUM_ARG_CHECK(cmd_ctx
->cmd
, cmd_data
->wait4halt
, argv
[3], end
);
534 cmd_data
->skip_len
= strtoul(argv
[4], &end
, 10);
535 ESP32_APPTRACE_CMD_NUM_ARG_CHECK(cmd_ctx
->cmd
, cmd_data
->skip_len
, argv
[4], end
);
542 static int esp32_apptrace_core_id_get(struct target
*target
, uint8_t *hdr_buf
)
544 return ESP32_APPTRACE_USER_BLOCK_CORE(target_buffer_get_u16(target
, hdr_buf
+ APPTRACE_BLOCK_SIZE_OFFSET
));
547 static uint32_t esp32_apptrace_usr_block_len_get(struct target
*target
, uint8_t *hdr_buf
, uint32_t *wr_len
)
549 *wr_len
= ESP32_APPTRACE_USER_BLOCK_LEN(target_buffer_get_u16(target
, hdr_buf
+ APPTRACE_WR_SIZE_OFFSET
));
550 return ESP32_APPTRACE_USER_BLOCK_LEN(target_buffer_get_u16(target
, hdr_buf
+ APPTRACE_BLOCK_SIZE_OFFSET
));
553 static int esp32_apptrace_cmd_init(struct esp32_apptrace_cmd_ctx
*cmd_ctx
,
554 struct command_invocation
*cmd
,
559 struct esp32_apptrace_cmd_data
*cmd_data
;
562 command_print(cmd
, "Not enough args! Need trace data destination!");
566 int res
= esp32_apptrace_cmd_ctx_init(cmd_ctx
, cmd
, mode
);
570 cmd_data
= calloc(1, sizeof(*cmd_data
));
571 assert(cmd_data
&& "No memory for command data!");
572 cmd_ctx
->cmd_priv
= cmd_data
;
574 /*outfile1 [poll_period [trace_size [stop_tmo [wait4halt [skip_size]]]]] */
575 res
= esp32_apptrace_dest_init(&cmd_data
->data_dest
, argv
, 1);
576 if (res
!= 1) { /* only one destination needs to be initialized */
577 command_print(cmd
, "Wrong args! Needs a trace data destination!");
581 cmd_ctx
->stop_tmo
= -1.0; /* infinite */
582 cmd_data
->max_len
= UINT32_MAX
;
583 cmd_data
->poll_period
= 0 /*ms*/;
585 /* parse remaining args */
586 esp32_apptrace_cmd_args_parse(cmd_ctx
, cmd_data
, &argv
[1], argc
- 1);
588 LOG_USER("App trace params: from %d cores, size %" PRId32
" bytes, stop_tmo %g s, poll period %" PRId32
589 " ms, wait_rst %d, skip %" PRId32
" bytes", cmd_ctx
->cores_num
,
592 cmd_data
->poll_period
,
596 cmd_ctx
->trace_format
.hdr_sz
= ESP32_APPTRACE_USER_BLOCK_HDR_SZ
;
597 cmd_ctx
->trace_format
.core_id_get
= esp32_apptrace_core_id_get
;
598 cmd_ctx
->trace_format
.usr_block_len_get
= esp32_apptrace_usr_block_len_get
;
601 command_print(cmd
, "Not enough args! Need %d trace data destinations!", cmd_ctx
->cores_num
);
602 cmd_ctx
->running
= 0;
603 esp32_apptrace_cmd_ctx_cleanup(cmd_ctx
);
607 static int esp32_apptrace_cmd_cleanup(struct esp32_apptrace_cmd_ctx
*cmd_ctx
)
609 struct esp32_apptrace_cmd_data
*cmd_data
= cmd_ctx
->cmd_priv
;
611 esp32_apptrace_dest_cleanup(&cmd_data
->data_dest
, 1);
613 cmd_ctx
->cmd_priv
= NULL
;
614 esp32_apptrace_cmd_ctx_cleanup(cmd_ctx
);
618 static void esp32_apptrace_print_stats(struct esp32_apptrace_cmd_ctx
*ctx
)
620 struct esp32_apptrace_cmd_data
*cmd_data
= ctx
->cmd_priv
;
621 uint32_t trace_sz
= 0;
624 trace_sz
= ctx
->tot_len
> cmd_data
->skip_len
? ctx
->tot_len
- cmd_data
->skip_len
: 0;
625 LOG_USER("Tracing is %s. Size is %" PRId32
" of %" PRId32
" @ %f (%f) KiB/s",
626 !ctx
->running
? "STOPPED" : "RUNNING",
628 cmd_data
? cmd_data
->max_len
: 0,
629 duration_kbps(&ctx
->read_time
, ctx
->tot_len
),
630 duration_kbps(&ctx
->read_time
, ctx
->raw_tot_len
));
631 LOG_USER("Data: blocks incomplete %" PRId32
", lost bytes: %" PRId32
,
632 ctx
->stats
.incompl_blocks
,
633 ctx
->stats
.lost_bytes
);
634 if (s_time_stats_enable
) {
635 LOG_USER("Block read time [%f..%f] ms",
636 1000 * ctx
->stats
.min_blk_read_time
,
637 1000 * ctx
->stats
.max_blk_read_time
);
638 LOG_USER("Block proc time [%f..%f] ms",
639 1000 * ctx
->stats
.min_blk_proc_time
,
640 1000 * ctx
->stats
.max_blk_proc_time
);
644 static int esp32_apptrace_wait4halt(struct esp32_apptrace_cmd_ctx
*ctx
, struct target
*target
)
646 LOG_USER("Wait for halt...");
647 while (!openocd_is_shutdown_pending()) {
648 int res
= target_poll(target
);
651 if (target
->state
== TARGET_HALTED
) {
652 LOG_USER("%s: HALTED", target
->cmd_name
);
660 int esp32_apptrace_safe_halt_targets(struct esp32_apptrace_cmd_ctx
*ctx
,
661 struct esp32_apptrace_target_state
*targets
)
665 memset(targets
, 0, ctx
->cores_num
* sizeof(struct esp32_apptrace_target_state
));
667 LOG_DEBUG("Halt all targets!");
668 for (unsigned int k
= 0; k
< ctx
->cores_num
; k
++) {
669 if (!target_was_examined(ctx
->cpus
[k
]))
671 if (ctx
->cpus
[k
]->state
== TARGET_HALTED
)
673 res
= target_halt(ctx
->cpus
[k
]);
674 if (res
!= ERROR_OK
) {
675 LOG_ERROR("Failed to halt target (%d)!", res
);
678 res
= target_wait_state(ctx
->cpus
[k
], TARGET_HALTED
, ESP32_APPTRACE_TGT_STATE_TMO
);
679 if (res
!= ERROR_OK
) {
680 LOG_ERROR("Failed to wait halt target %s / %d (%d)!",
681 target_name(ctx
->cpus
[k
]),
687 /* read current block statuses from CPUs */
688 LOG_DEBUG("Read current block statuses");
689 for (unsigned int k
= 0; k
< ctx
->cores_num
; k
++) {
691 res
= ctx
->hw
->status_reg_read(ctx
->cpus
[k
], &stat
);
692 if (res
!= ERROR_OK
) {
693 LOG_ERROR("Failed to read trace status (%d)!", res
);
696 /* check if some CPU stopped inside tracing regs update critical section */
698 if (ctx
->hw
->leave_trace_crit_section_start
) {
699 res
= ctx
->hw
->leave_trace_crit_section_start(ctx
->cpus
[k
]);
703 uint32_t bp_addr
= stat
;
704 res
= breakpoint_add(ctx
->cpus
[k
], bp_addr
, 1, BKPT_HARD
);
705 if (res
!= ERROR_OK
) {
706 LOG_ERROR("Failed to set breakpoint (%d)!", res
);
710 /* allow this CPU to leave ERI write critical section */
711 res
= target_resume(ctx
->cpus
[k
], 1, 0, 1, 0);
712 if (res
!= ERROR_OK
) {
713 LOG_ERROR("Failed to resume target (%d)!", res
);
714 breakpoint_remove(ctx
->cpus
[k
], bp_addr
);
717 /* wait for CPU to be halted on BP */
718 enum target_debug_reason debug_reason
= DBG_REASON_UNDEFINED
;
719 while (debug_reason
!= DBG_REASON_BREAKPOINT
) {
720 res
= target_wait_state(ctx
->cpus
[k
], TARGET_HALTED
,
721 ESP32_APPTRACE_TGT_STATE_TMO
);
722 if (res
!= ERROR_OK
) {
723 LOG_ERROR("Failed to wait halt on bp (%d)!", res
);
724 breakpoint_remove(ctx
->cpus
[k
], bp_addr
);
727 debug_reason
= ctx
->cpus
[k
]->debug_reason
;
729 res
= ctx
->hw
->status_reg_read(ctx
->cpus
[k
], &stat
);
730 if (res
!= ERROR_OK
) {
731 LOG_ERROR("Failed to read trace status (%d)!", res
);
732 breakpoint_remove(ctx
->cpus
[k
], bp_addr
);
736 breakpoint_remove(ctx
->cpus
[k
], bp_addr
);
737 if (ctx
->hw
->leave_trace_crit_section_stop
) {
738 res
= ctx
->hw
->leave_trace_crit_section_stop(ctx
->cpus
[k
]);
743 res
= ctx
->hw
->data_len_read(ctx
->cpus
[k
], &targets
[k
].block_id
, &targets
[k
].data_len
);
744 if (res
!= ERROR_OK
) {
745 LOG_ERROR("Failed to read trace status (%d)!", res
);
753 static int esp32_apptrace_connect_targets(struct esp32_apptrace_cmd_ctx
*ctx
,
757 struct esp32_apptrace_target_state target_to_connect
[ESP32_APPTRACE_MAX_CORES_NUM
];
760 LOG_USER("Connect targets...");
762 LOG_USER("Disconnect targets...");
764 int res
= esp32_apptrace_safe_halt_targets(ctx
, target_to_connect
);
765 if (res
!= ERROR_OK
) {
766 command_print(ctx
->cmd
, "Failed to halt targets (%d)!", res
);
769 if (ctx
->cores_num
> 1) {
770 /* set block ids to the highest value */
772 for (unsigned int k
= 0; k
< ctx
->cores_num
; k
++) {
773 if (target_to_connect
[k
].block_id
> max_id
)
774 max_id
= target_to_connect
[k
].block_id
;
776 for (unsigned int k
= 0; k
< ctx
->cores_num
; k
++)
777 target_to_connect
[k
].block_id
= max_id
;
779 for (unsigned int k
= 0; k
< ctx
->cores_num
; k
++) {
780 /* update host connected status */
781 res
= ctx
->hw
->ctrl_reg_write(ctx
->cpus
[k
],
782 target_to_connect
[k
].block_id
,
783 0 /*ack target data*/,
785 false /*no host data*/);
786 if (res
!= ERROR_OK
) {
787 command_print(ctx
->cmd
, "Failed to read trace status (%d)!", res
);
792 LOG_DEBUG("Resume targets");
793 bool smp_resumed
= false;
794 for (unsigned int k
= 0; k
< ctx
->cores_num
; k
++) {
795 if (smp_resumed
&& ctx
->cpus
[k
]->smp
) {
796 /* in SMP mode we need to call target_resume for one core only */
799 res
= target_resume(ctx
->cpus
[k
], 1, 0, 1, 0);
800 if (res
!= ERROR_OK
) {
801 command_print(ctx
->cmd
, "Failed to resume target (%d)!", res
);
804 if (ctx
->cpus
[k
]->smp
)
809 LOG_INFO("Targets connected.");
811 LOG_INFO("Targets disconnected.");
815 int esp_apptrace_usr_block_write(const struct esp32_apptrace_hw
*hw
, struct target
*target
,
820 struct esp_apptrace_host2target_hdr hdr
= { .block_sz
= size
};
821 uint32_t buf_sz
[2] = { sizeof(hdr
), size
};
822 const uint8_t *bufs
[2] = { (const uint8_t *)&hdr
, data
};
824 if (size
> hw
->usr_block_max_size_get(target
)) {
825 LOG_ERROR("Too large user block %" PRId32
, size
);
829 return hw
->buffs_write(target
,
834 true /*ack target data*/,
838 static uint32_t esp32_apptrace_usr_block_check(struct esp32_apptrace_cmd_ctx
*ctx
, uint8_t *hdr_buf
)
841 uint32_t usr_len
= ctx
->trace_format
.usr_block_len_get(ctx
->target
, hdr_buf
, &wr_len
);
842 if (usr_len
!= wr_len
) {
843 LOG_ERROR("Incomplete block sz %" PRId32
", wr %" PRId32
, usr_len
, wr_len
);
844 ctx
->stats
.incompl_blocks
++;
845 ctx
->stats
.lost_bytes
+= usr_len
- wr_len
;
850 int esp32_apptrace_get_data_info(struct esp32_apptrace_cmd_ctx
*ctx
,
851 struct esp32_apptrace_target_state
*target_state
,
852 uint32_t *fired_target_num
)
854 if (fired_target_num
)
855 *fired_target_num
= UINT32_MAX
;
857 for (unsigned int i
= 0; i
< ctx
->cores_num
; i
++) {
858 int res
= ctx
->hw
->data_len_read(ctx
->cpus
[i
], &target_state
[i
].block_id
, &target_state
[i
].data_len
);
859 if (res
!= ERROR_OK
) {
860 LOG_ERROR("Failed to read data len on (%s)!", target_name(ctx
->cpus
[i
]));
863 if (target_state
[i
].data_len
) {
864 LOG_TARGET_DEBUG(ctx
->cpus
[i
], "Block %" PRId32
", len %" PRId32
" bytes on fired",
865 target_state
[i
].block_id
, target_state
[i
].data_len
);
866 if (fired_target_num
)
867 *fired_target_num
= i
;
874 static int esp32_apptrace_process_data(struct esp32_apptrace_cmd_ctx
*ctx
,
875 unsigned int core_id
,
879 struct esp32_apptrace_cmd_data
*cmd_data
= ctx
->cmd_priv
;
881 LOG_DEBUG("Got block %" PRId32
" bytes [%x %x...%x %x]", data_len
, data
[12], data
[13],
882 data
[data_len
- 2], data
[data_len
- 1]);
883 if (ctx
->tot_len
+ data_len
> cmd_data
->skip_len
) {
884 uint32_t wr_idx
= 0, wr_chunk_len
= data_len
;
885 if (ctx
->tot_len
< cmd_data
->skip_len
) {
886 wr_chunk_len
= (ctx
->tot_len
+ wr_chunk_len
) - cmd_data
->skip_len
;
887 wr_idx
= cmd_data
->skip_len
- ctx
->tot_len
;
889 if (ctx
->tot_len
+ wr_chunk_len
> cmd_data
->max_len
)
890 wr_chunk_len
-= (ctx
->tot_len
+ wr_chunk_len
- cmd_data
->skip_len
) - cmd_data
->max_len
;
891 if (wr_chunk_len
> 0) {
892 int res
= cmd_data
->data_dest
.write(cmd_data
->data_dest
.priv
, data
+ wr_idx
, wr_chunk_len
);
893 if (res
!= ERROR_OK
) {
894 LOG_ERROR("Failed to write %" PRId32
" bytes to dest 0!", data_len
);
898 ctx
->tot_len
+= wr_chunk_len
;
900 ctx
->tot_len
+= data_len
;
903 if (cmd_data
->data_dest
.log_progress
)
904 LOG_USER("%" PRId32
" ", ctx
->tot_len
);
905 /* check for stop condition */
906 if (ctx
->tot_len
> cmd_data
->skip_len
&& (ctx
->tot_len
- cmd_data
->skip_len
>= cmd_data
->max_len
)) {
908 if (duration_measure(&ctx
->read_time
) != 0) {
909 LOG_ERROR("Failed to stop trace read time measure!");
916 static int esp32_apptrace_handle_trace_block(struct esp32_apptrace_cmd_ctx
*ctx
,
917 struct esp32_apptrace_block
*block
)
919 uint32_t processed
= 0;
920 uint32_t hdr_sz
= ctx
->trace_format
.hdr_sz
;
922 LOG_DEBUG("Got block %" PRId32
" bytes", block
->data_len
);
923 /* process user blocks one by one */
924 while (processed
< block
->data_len
) {
925 LOG_DEBUG("Process usr block %" PRId32
"/%" PRId32
, processed
, block
->data_len
);
926 /* process user block */
927 uint32_t usr_len
= esp32_apptrace_usr_block_check(ctx
, block
->data
+ processed
);
928 int core_id
= ctx
->trace_format
.core_id_get(ctx
->target
, block
->data
+ processed
);
929 /* process user data */
930 int res
= ctx
->process_data(ctx
, core_id
, block
->data
+ processed
+ hdr_sz
, usr_len
);
931 if (res
!= ERROR_OK
) {
932 LOG_ERROR("Failed to process %" PRId32
" bytes!", usr_len
);
935 processed
+= usr_len
+ hdr_sz
;
940 static int esp32_apptrace_data_processor(void *priv
)
942 struct esp32_apptrace_cmd_ctx
*ctx
= (struct esp32_apptrace_cmd_ctx
*)priv
;
947 struct esp32_apptrace_block
*block
= esp32_apptrace_ready_block_get(ctx
);
951 int res
= esp32_apptrace_handle_trace_block(ctx
, block
);
952 if (res
!= ERROR_OK
) {
954 LOG_ERROR("Failed to process trace block %" PRId32
" bytes!", block
->data_len
);
957 res
= esp32_apptrace_block_free(ctx
, block
);
958 if (res
!= ERROR_OK
) {
960 LOG_ERROR("Failed to free ready block!");
967 static int esp32_apptrace_check_connection(struct esp32_apptrace_cmd_ctx
*ctx
)
972 unsigned int busy_target_num
= 0;
974 for (unsigned int i
= 0; i
< ctx
->cores_num
; i
++) {
976 int res
= ctx
->hw
->ctrl_reg_read(ctx
->cpus
[i
], NULL
, NULL
, &conn
);
977 if (res
!= ERROR_OK
) {
978 LOG_ERROR("Failed to read apptrace control reg for cpu(%d) res(%d)!", i
, res
);
983 LOG_TARGET_WARNING(ctx
->cpus
[i
], "apptrace connection is lost. Re-connect.");
984 res
= ctx
->hw
->status_reg_read(ctx
->cpus
[i
], &stat
);
985 if (res
!= ERROR_OK
) {
986 LOG_ERROR("Failed to read trace status (%d)!", res
);
990 LOG_TARGET_WARNING(ctx
->cpus
[i
], "in critical state. Retry in next poll");
991 if (++busy_target_num
== ctx
->cores_num
) {
992 LOG_WARNING("No available core");
997 res
= ctx
->hw
->ctrl_reg_write(ctx
->cpus
[i
],
1000 true /*host connected*/,
1001 false /*no host data*/);
1002 if (res
!= ERROR_OK
) {
1003 LOG_ERROR("Failed to write apptrace control reg for cpu(%d) res(%d)!", i
, res
);
1006 if (ctx
->stop_tmo
!= -1.0) {
1007 /* re-start idle time measurement */
1008 if (duration_start(&ctx
->idle_time
) != 0) {
1009 LOG_ERROR("Failed to re-start idle time measure!");
1019 static int esp32_apptrace_poll(void *priv
)
1021 struct esp32_apptrace_cmd_ctx
*ctx
= (struct esp32_apptrace_cmd_ctx
*)priv
;
1023 uint32_t fired_target_num
= 0;
1024 struct esp32_apptrace_target_state target_state
[ESP32_APPTRACE_MAX_CORES_NUM
];
1025 struct duration blk_proc_time
;
1027 if (!ctx
->running
) {
1028 if (ctx
->auto_clean
)
1029 ctx
->auto_clean(ctx
);
1033 /* Check for connection is alive.For some reason target and therefore host_connected flag
1034 * might have been reset */
1035 res
= esp32_apptrace_check_connection(ctx
);
1036 if (res
!= ERROR_OK
) {
1037 if (res
!= ERROR_WAIT
)
1042 /* check for data from target */
1043 res
= esp32_apptrace_get_data_info(ctx
, target_state
, &fired_target_num
);
1044 if (res
!= ERROR_OK
) {
1046 LOG_ERROR("Failed to read data len!");
1049 /* LOG_DEBUG("Block %d (%d bytes) on target (%s)!", target_state[0].block_id,
1050 * target_state[0].data_len, target_name(ctx->cpus[0])); */
1051 if (fired_target_num
== UINT32_MAX
) {
1052 /* no data has been received, but block could be switched due to the data transferred
1053 * from host to target */
1054 if (ctx
->cores_num
> 1) {
1055 uint32_t max_block_id
= 0, min_block_id
= ctx
->hw
->max_block_id
;
1056 /* find maximum block ID and set the same ID in control reg for both cores
1058 for (unsigned int i
= 0; i
< ctx
->cores_num
; i
++) {
1059 if (max_block_id
< target_state
[i
].block_id
)
1060 max_block_id
= target_state
[i
].block_id
;
1061 if (min_block_id
> target_state
[i
].block_id
)
1062 min_block_id
= target_state
[i
].block_id
;
1064 /* handle block ID overflow */
1065 if (max_block_id
== ctx
->hw
->max_block_id
&& min_block_id
== 0)
1067 for (unsigned int i
= 0; i
< ctx
->cores_num
; i
++) {
1068 if (max_block_id
!= target_state
[i
].block_id
) {
1069 LOG_TARGET_DEBUG(ctx
->cpus
[i
], "Ack empty block %" PRId32
"!", max_block_id
);
1070 res
= ctx
->hw
->ctrl_reg_write(ctx
->cpus
[i
],
1073 true /*host connected*/,
1074 false /*no host data*/);
1075 if (res
!= ERROR_OK
) {
1077 LOG_TARGET_ERROR(ctx
->cpus
[i
], "Failed to ack empty data block!");
1082 ctx
->last_blk_id
= max_block_id
;
1084 if (ctx
->stop_tmo
!= -1.0) {
1085 if (duration_measure(&ctx
->idle_time
) != 0) {
1087 LOG_ERROR("Failed to measure idle time!");
1090 if (duration_elapsed(&ctx
->idle_time
) >= ctx
->stop_tmo
) {
1092 LOG_ERROR("Data timeout!");
1096 return ERROR_OK
;/* no data */
1099 if (target_state
[fired_target_num
].data_len
> ctx
->max_trace_block_sz
) {
1101 LOG_ERROR("Too large block size %" PRId32
"!", target_state
[fired_target_num
].data_len
);
1104 if (ctx
->tot_len
== 0) {
1105 if (duration_start(&ctx
->read_time
) != 0) {
1107 LOG_ERROR("Failed to start trace read time measurement!");
1111 struct esp32_apptrace_block
*block
= esp32_apptrace_free_block_get(ctx
);
1114 LOG_TARGET_ERROR(ctx
->cpus
[fired_target_num
], "Failed to get free block for data!");
1117 if (s_time_stats_enable
) {
1119 if (duration_start(&blk_proc_time
) != 0) {
1121 LOG_ERROR("Failed to start block read time measurement!");
1125 res
= ctx
->hw
->data_read(ctx
->cpus
[fired_target_num
], target_state
[fired_target_num
].data_len
, block
->data
,
1126 target_state
[fired_target_num
].block_id
,
1127 /* do not ack target data in sync mode,
1128 esp32_apptrace_handle_trace_block() can write response data and will do ack thereafter */
1129 ctx
->mode
!= ESP_APPTRACE_CMD_MODE_SYNC
);
1130 if (res
!= ERROR_OK
) {
1132 LOG_TARGET_ERROR(ctx
->cpus
[fired_target_num
], "Failed to read data!");
1135 ctx
->last_blk_id
= target_state
[fired_target_num
].block_id
;
1136 block
->data_len
= target_state
[fired_target_num
].data_len
;
1137 ctx
->raw_tot_len
+= block
->data_len
;
1138 if (s_time_stats_enable
) {
1139 if (duration_measure(&blk_proc_time
) != 0) {
1141 LOG_ERROR("Failed to measure block read time!");
1145 float brt
= duration_elapsed(&blk_proc_time
);
1146 if (brt
> ctx
->stats
.max_blk_read_time
)
1147 ctx
->stats
.max_blk_read_time
= brt
;
1148 if (brt
< ctx
->stats
.min_blk_read_time
)
1149 ctx
->stats
.min_blk_read_time
= brt
;
1151 if (duration_start(&blk_proc_time
) != 0) {
1153 LOG_ERROR("Failed to start block proc time measurement!");
1157 /* in sync mode do not ack target data on other cores, esp32_apptrace_handle_trace_block() can write response
1158 * data and will do ack thereafter */
1159 if (ctx
->mode
!= ESP_APPTRACE_CMD_MODE_SYNC
) {
1160 for (unsigned int i
= 0; i
< ctx
->cores_num
; i
++) {
1161 if (i
== fired_target_num
)
1163 res
= ctx
->hw
->ctrl_reg_write(ctx
->cpus
[i
],
1166 true /*host connected*/,
1167 false /*no host data*/);
1168 if (res
!= ERROR_OK
) {
1170 LOG_TARGET_ERROR(ctx
->cpus
[i
], "Failed to ack data!");
1173 LOG_TARGET_DEBUG(ctx
->cpus
[i
], "Ack block %" PRId32
, ctx
->last_blk_id
);
1175 res
= esp32_apptrace_ready_block_put(ctx
, block
);
1176 if (res
!= ERROR_OK
) {
1178 LOG_TARGET_ERROR(ctx
->cpus
[fired_target_num
], "Failed to put ready block of data!");
1182 res
= esp32_apptrace_handle_trace_block(ctx
, block
);
1183 if (res
!= ERROR_OK
) {
1185 LOG_ERROR("Failed to process trace block %" PRId32
" bytes!", block
->data_len
);
1188 res
= esp32_apptrace_block_free(ctx
, block
);
1189 if (res
!= ERROR_OK
) {
1191 LOG_ERROR("Failed to free ready block!");
1195 if (ctx
->stop_tmo
!= -1.0) {
1196 /* start idle time measurement */
1197 if (duration_start(&ctx
->idle_time
) != 0) {
1199 LOG_ERROR("Failed to start idle time measure!");
1203 if (s_time_stats_enable
) {
1204 if (duration_measure(&blk_proc_time
) != 0) {
1206 LOG_ERROR("Failed to stop block proc time measure!");
1210 float bt
= duration_elapsed(&blk_proc_time
);
1211 if (bt
> ctx
->stats
.max_blk_proc_time
)
1212 ctx
->stats
.max_blk_proc_time
= bt
;
1213 if (bt
< ctx
->stats
.min_blk_proc_time
)
1214 ctx
->stats
.min_blk_proc_time
= bt
;
1219 static inline bool is_sysview_mode(int mode
)
1221 return mode
== ESP_APPTRACE_CMD_MODE_SYSVIEW
|| mode
== ESP_APPTRACE_CMD_MODE_SYSVIEW_MCORE
;
1224 static void esp32_apptrace_cmd_stop(struct esp32_apptrace_cmd_ctx
*ctx
)
1226 if (duration_measure(&ctx
->read_time
) != 0)
1227 LOG_ERROR("Failed to stop trace read time measurement!");
1228 int res
= target_unregister_timer_callback(esp32_apptrace_poll
, ctx
);
1229 if (res
!= ERROR_OK
)
1230 LOG_ERROR("Failed to unregister target timer handler (%d)!", res
);
1231 if (is_sysview_mode(ctx
->mode
)) {
1233 res
= esp32_sysview_stop(ctx
);
1234 if (res
!= ERROR_OK
)
1235 LOG_ERROR("sysview: Failed to stop tracing!");
1237 /* data processor is alive, so wait for all received blocks to be processed */
1238 res
= esp32_apptrace_wait_tracing_finished(ctx
);
1239 if (res
!= ERROR_OK
)
1240 LOG_ERROR("Failed to wait for pended blocks (%d)!", res
);
1241 res
= esp32_apptrace_connect_targets(ctx
, false, ctx
->target_state
== TARGET_RUNNING
);
1242 if (res
!= ERROR_OK
)
1243 LOG_ERROR("Failed to disconnect targets (%d)!", res
);
1244 esp32_apptrace_print_stats(ctx
);
1245 res
= esp32_apptrace_cmd_cleanup(ctx
);
1246 if (res
!= ERROR_OK
)
1247 LOG_ERROR("Failed to cleanup cmd ctx (%d)!", res
);
1250 /* this function must be called after connecting to targets */
1251 static int esp32_sysview_start(struct esp32_apptrace_cmd_ctx
*ctx
)
1253 uint8_t cmds
[] = { SEGGER_SYSVIEW_COMMAND_ID_START
};
1254 uint32_t fired_target_num
= 0;
1255 struct esp32_apptrace_target_state target_state
[ESP32_APPTRACE_MAX_CORES_NUM
] = {{0}};
1256 struct esp32_sysview_cmd_data
*cmd_data
= ctx
->cmd_priv
;
1258 /* get current block id */
1259 int res
= esp32_apptrace_get_data_info(ctx
, target_state
, &fired_target_num
);
1260 if (res
!= ERROR_OK
) {
1261 LOG_ERROR("sysview: Failed to read target data info!");
1264 if (fired_target_num
== UINT32_MAX
) {
1265 /* it can happen that there is no pending target data, but block was switched
1266 * in this case block_ids on both CPUs are equal, so select the first one */
1267 fired_target_num
= 0;
1270 res
= esp_apptrace_usr_block_write(ctx
->hw
, ctx
->cpus
[fired_target_num
], target_state
[fired_target_num
].block_id
,
1271 cmds
, sizeof(cmds
));
1272 if (res
!= ERROR_OK
) {
1273 LOG_ERROR("sysview: Failed to start tracing!");
1276 cmd_data
->sv_trace_running
= 1;
1280 static int esp32_sysview_stop(struct esp32_apptrace_cmd_ctx
*ctx
)
1282 uint32_t old_block_id
, fired_target_num
= 0, empty_target_num
= 0;
1283 struct esp32_apptrace_target_state target_state
[ESP32_APPTRACE_MAX_CORES_NUM
];
1284 struct esp32_sysview_cmd_data
*cmd_data
= ctx
->cmd_priv
;
1285 uint8_t cmds
[] = { SEGGER_SYSVIEW_COMMAND_ID_STOP
};
1286 struct duration wait_time
;
1288 struct esp32_apptrace_block
*block
= esp32_apptrace_free_block_get(ctx
);
1290 LOG_ERROR("Failed to get free block for data on (%s)!", target_name(ctx
->cpus
[fired_target_num
]));
1294 /* halt all CPUs (not only one), otherwise it can happen that there is no target data and
1295 * while we are queueing commands another CPU switches tracing block */
1296 int res
= esp32_apptrace_safe_halt_targets(ctx
, target_state
);
1297 if (res
!= ERROR_OK
) {
1298 LOG_ERROR("sysview: Failed to halt targets (%d)!", res
);
1301 /* it can happen that there is no pending target data
1302 * in this case block_ids on both CPUs are equal, so the first one will be selected */
1303 for (unsigned int k
= 0; k
< ctx
->cores_num
; k
++) {
1304 if (target_state
[k
].data_len
) {
1305 fired_target_num
= k
;
1309 if (target_state
[fired_target_num
].data_len
) {
1310 /* read pending data without ack, they will be acked when stop command is queued */
1311 res
= ctx
->hw
->data_read(ctx
->cpus
[fired_target_num
], target_state
[fired_target_num
].data_len
, block
->data
,
1312 target_state
[fired_target_num
].block_id
,
1313 false /*no ack target data*/);
1314 if (res
!= ERROR_OK
) {
1315 LOG_ERROR("sysview: Failed to read data on (%s)!", target_name(ctx
->cpus
[fired_target_num
]));
1319 block
->data_len
= target_state
[fired_target_num
].data_len
;
1320 res
= esp32_apptrace_handle_trace_block(ctx
, block
);
1321 if (res
!= ERROR_OK
) {
1322 LOG_ERROR("Failed to process trace block %" PRId32
" bytes!", block
->data_len
);
1326 /* stop tracing and ack target data */
1327 res
= esp_apptrace_usr_block_write(ctx
->hw
, ctx
->cpus
[fired_target_num
], target_state
[fired_target_num
].block_id
,
1330 if (res
!= ERROR_OK
) {
1331 LOG_ERROR("sysview: Failed to stop tracing!");
1334 if (ctx
->cores_num
> 1) {
1335 empty_target_num
= fired_target_num
? 0 : 1;
1336 /* ack target data on another CPU */
1337 res
= ctx
->hw
->ctrl_reg_write(ctx
->cpus
[empty_target_num
], target_state
[fired_target_num
].block_id
,
1338 0 /*target data ack*/,
1339 true /*host connected*/,
1340 false /*no host data*/);
1341 if (res
!= ERROR_OK
) {
1342 LOG_ERROR("sysview: Failed to ack data on target '%s' (%d)!",
1343 target_name(ctx
->cpus
[empty_target_num
]), res
);
1347 /* resume targets to allow command processing */
1348 LOG_INFO("Resume targets");
1349 bool smp_resumed
= false;
1350 for (unsigned int k
= 0; k
< ctx
->cores_num
; k
++) {
1351 if (smp_resumed
&& ctx
->cpus
[k
]->smp
) {
1352 /* in SMP mode we need to call target_resume for one core only */
1355 res
= target_resume(ctx
->cpus
[k
], 1, 0, 1, 0);
1356 if (res
!= ERROR_OK
) {
1357 LOG_ERROR("sysview: Failed to resume target '%s' (%d)!", target_name(ctx
->cpus
[k
]), res
);
1360 if (ctx
->cpus
[k
]->smp
)
1363 /* wait for block switch (command sent), so we can disconnect from targets */
1364 old_block_id
= target_state
[fired_target_num
].block_id
;
1365 if (duration_start(&wait_time
) != 0) {
1366 LOG_ERROR("Failed to start trace stop timeout measurement!");
1369 /* we are waiting for the last data from tracing block and also there can be data in the pended
1371 /* so we are expecting two TRX block switches at most or stopping due to timeout */
1372 while (cmd_data
->sv_trace_running
) {
1373 res
= esp32_apptrace_get_data_info(ctx
, target_state
, &fired_target_num
);
1374 if (res
!= ERROR_OK
) {
1375 LOG_ERROR("sysview: Failed to read targets data info!");
1378 if (fired_target_num
== UINT32_MAX
) {
1379 /* it can happen that there is no pending (last) target data, but block was
1381 /* in this case block_ids on both CPUs are equal, so select the first one */
1382 fired_target_num
= 0;
1384 if (target_state
[fired_target_num
].block_id
!= old_block_id
) {
1385 if (target_state
[fired_target_num
].data_len
) {
1386 /* read last data and ack them */
1387 res
= ctx
->hw
->data_read(ctx
->cpus
[fired_target_num
],
1388 target_state
[fired_target_num
].data_len
,
1390 target_state
[fired_target_num
].block_id
,
1391 true /*ack target data*/);
1392 if (res
!= ERROR_OK
) {
1393 LOG_ERROR("sysview: Failed to read last data on (%s)!", target_name(ctx
->cpus
[fired_target_num
]));
1395 if (ctx
->cores_num
> 1) {
1396 /* ack target data on another CPU */
1397 empty_target_num
= fired_target_num
? 0 : 1;
1398 res
= ctx
->hw
->ctrl_reg_write(ctx
->cpus
[empty_target_num
],
1399 target_state
[fired_target_num
].block_id
,
1401 true /*host connected*/,
1402 false /*no host data*/);
1403 if (res
!= ERROR_OK
) {
1404 LOG_ERROR("sysview: Failed to ack data on target '%s' (%d)!",
1405 target_name(ctx
->cpus
[empty_target_num
]), res
);
1410 block
->data_len
= target_state
[fired_target_num
].data_len
;
1411 res
= esp32_apptrace_handle_trace_block(ctx
, block
);
1412 if (res
!= ERROR_OK
) {
1413 LOG_ERROR("Failed to process trace block %" PRId32
" bytes!",
1418 old_block_id
= target_state
[fired_target_num
].block_id
;
1421 if (duration_measure(&wait_time
) != 0) {
1422 LOG_ERROR("Failed to start trace stop timeout measurement!");
1425 const float stop_tmo
= LOG_LEVEL_IS(LOG_LVL_DEBUG
) ? 30.0 : 0.5;
1426 if (duration_elapsed(&wait_time
) >= stop_tmo
) {
1427 LOG_INFO("Stop waiting for the last data due to timeout.");
1434 static int esp32_cmd_apptrace_generic(struct command_invocation
*cmd
, int mode
, const char **argv
, int argc
)
1436 static struct esp32_apptrace_cmd_ctx s_at_cmd_ctx
;
1437 struct esp32_apptrace_cmd_data
*cmd_data
;
1438 int res
= ERROR_FAIL
;
1439 enum target_state old_state
;
1440 struct target
*target
= get_current_target(CMD_CTX
);
1443 return ERROR_COMMAND_SYNTAX_ERROR
;
1445 /* command can be invoked on unexamined core, if so find examined one */
1446 if (target
->smp
&& !target_was_examined(target
)) {
1447 struct target_list
*head
;
1448 struct target
*curr
;
1449 LOG_WARNING("Current target '%s' was not examined!", target_name(target
));
1450 foreach_smp_target(head
, target
->smp_targets
) {
1451 curr
= head
->target
;
1452 if (target_was_examined(curr
)) {
1454 LOG_WARNING("Run command on target '%s'", target_name(target
));
1459 old_state
= target
->state
;
1461 if (strcmp(argv
[0], "start") == 0) {
1462 if (is_sysview_mode(mode
)) {
1463 /* init cmd context */
1464 res
= esp32_sysview_cmd_init(&s_at_cmd_ctx
,
1467 mode
== ESP_APPTRACE_CMD_MODE_SYSVIEW_MCORE
,
1470 if (res
!= ERROR_OK
) {
1471 command_print(cmd
, "Failed to init cmd ctx (%d)!", res
);
1474 cmd_data
= s_at_cmd_ctx
.cmd_priv
;
1475 if (cmd_data
->skip_len
!= 0) {
1476 s_at_cmd_ctx
.running
= 0;
1477 esp32_sysview_cmd_cleanup(&s_at_cmd_ctx
);
1478 command_print(cmd
, "Data skipping not supported!");
1481 s_at_cmd_ctx
.process_data
= esp32_sysview_process_data
;
1483 res
= esp32_apptrace_cmd_init(&s_at_cmd_ctx
,
1488 if (res
!= ERROR_OK
) {
1489 command_print(cmd
, "Failed to init cmd ctx (%d)!", res
);
1492 cmd_data
= s_at_cmd_ctx
.cmd_priv
;
1493 s_at_cmd_ctx
.process_data
= esp32_apptrace_process_data
;
1495 s_at_cmd_ctx
.auto_clean
= esp32_apptrace_cmd_stop
;
1496 if (cmd_data
->wait4halt
) {
1497 res
= esp32_apptrace_wait4halt(&s_at_cmd_ctx
, target
);
1498 if (res
!= ERROR_OK
) {
1499 command_print(cmd
, "Failed to wait for halt target (%d)!", res
);
1500 goto _on_start_error
;
1503 res
= esp32_apptrace_connect_targets(&s_at_cmd_ctx
, true, old_state
== TARGET_RUNNING
);
1504 if (res
!= ERROR_OK
) {
1505 command_print(cmd
, "Failed to connect to targets (%d)!", res
);
1506 goto _on_start_error
;
1508 if (is_sysview_mode(mode
)) {
1510 res
= esp32_sysview_start(&s_at_cmd_ctx
);
1511 if (res
!= ERROR_OK
) {
1512 esp32_apptrace_connect_targets(&s_at_cmd_ctx
, false, old_state
== TARGET_RUNNING
);
1513 s_at_cmd_ctx
.running
= 0;
1514 esp32_apptrace_cmd_cleanup(&s_at_cmd_ctx
);
1515 command_print(cmd
, "sysview: Failed to start tracing!");
1519 res
= target_register_timer_callback(esp32_apptrace_poll
,
1520 cmd_data
->poll_period
,
1521 TARGET_TIMER_TYPE_PERIODIC
,
1523 if (res
!= ERROR_OK
) {
1524 command_print(cmd
, "Failed to register target timer handler (%d)!", res
);
1525 goto _on_start_error
;
1527 } else if (strcmp(argv
[0], "stop") == 0) {
1528 if (!s_at_cmd_ctx
.running
) {
1529 command_print(cmd
, "Tracing is not running!");
1532 esp32_apptrace_cmd_stop(&s_at_cmd_ctx
);
1534 } else if (strcmp(argv
[0], "status") == 0) {
1535 if (s_at_cmd_ctx
.running
&& duration_measure(&s_at_cmd_ctx
.read_time
) != 0)
1536 LOG_ERROR("Failed to measure trace read time!");
1537 esp32_apptrace_print_stats(&s_at_cmd_ctx
);
1539 } else if (strcmp(argv
[0], "dump") == 0) {
1540 if (is_sysview_mode(mode
)) {
1541 command_print(cmd
, "Not supported!");
1544 /* [dump outfile] - post-mortem dump without connection to targets */
1545 res
= esp32_apptrace_cmd_init(&s_at_cmd_ctx
,
1550 if (res
!= ERROR_OK
) {
1551 command_print(cmd
, "Failed to init cmd ctx (%d)!", res
);
1554 s_at_cmd_ctx
.stop_tmo
= 0.01; /* use small stop tmo */
1555 s_at_cmd_ctx
.process_data
= esp32_apptrace_process_data
;
1556 /* check for exit signal and command completion */
1557 while (!openocd_is_shutdown_pending() && s_at_cmd_ctx
.running
) {
1558 res
= esp32_apptrace_poll(&s_at_cmd_ctx
);
1559 if (res
!= ERROR_OK
) {
1560 LOG_ERROR("Failed to poll target for trace data (%d)!", res
);
1563 /* let registered timer callbacks to run */
1564 target_call_timer_callbacks();
1566 if (s_at_cmd_ctx
.running
) {
1567 /* data processor is alive, so wait for all received blocks to be processed */
1568 res
= esp32_apptrace_wait_tracing_finished(&s_at_cmd_ctx
);
1569 if (res
!= ERROR_OK
)
1570 LOG_ERROR("Failed to wait for pended blocks (%d)!", res
);
1572 esp32_apptrace_print_stats(&s_at_cmd_ctx
);
1573 res
= esp32_apptrace_cmd_cleanup(&s_at_cmd_ctx
);
1574 if (res
!= ERROR_OK
)
1575 command_print(cmd
, "Failed to cleanup cmd ctx (%d)!", res
);
1577 command_print(cmd
, "Invalid action '%s'!", argv
[0]);
1583 s_at_cmd_ctx
.running
= 0;
1584 if (is_sysview_mode(mode
))
1585 esp32_sysview_cmd_cleanup(&s_at_cmd_ctx
);
1587 esp32_apptrace_cmd_cleanup(&s_at_cmd_ctx
);
1591 COMMAND_HANDLER(esp32_cmd_apptrace
)
1593 return esp32_cmd_apptrace_generic(CMD
, ESP_APPTRACE_CMD_MODE_GEN
, CMD_ARGV
, CMD_ARGC
);
1596 COMMAND_HANDLER(esp32_cmd_sysview
)
1598 return esp32_cmd_apptrace_generic(CMD
, ESP_APPTRACE_CMD_MODE_SYSVIEW
, CMD_ARGV
, CMD_ARGC
);
1601 COMMAND_HANDLER(esp32_cmd_sysview_mcore
)
1603 return esp32_cmd_apptrace_generic(CMD
, ESP_APPTRACE_CMD_MODE_SYSVIEW_MCORE
, CMD_ARGV
, CMD_ARGC
);
1606 const struct command_registration esp32_apptrace_command_handlers
[] = {
1609 .handler
= esp32_cmd_apptrace
,
1610 .mode
= COMMAND_EXEC
,
1612 "App Tracing: application level trace control. Starts, stops or queries tracing process status.",
1614 "(start <destination> [poll_period [trace_size [stop_tmo [wait4halt [skip_size]]]]) | (stop) | (status) | (dump <destination>)",
1618 .handler
= esp32_cmd_sysview
,
1619 .mode
= COMMAND_EXEC
,
1621 "App Tracing: SEGGER SystemView compatible trace control. Starts, stops or queries tracing process status.",
1623 "(start file://<outfile1> [file://<outfile2>] [poll_period [trace_size [stop_tmo [wait4halt [skip_size]]]]) | (stop) | (status)",
1626 .name
= "sysview_mcore",
1627 .handler
= esp32_cmd_sysview_mcore
,
1628 .mode
= COMMAND_EXEC
,
1630 "App Tracing: Espressif multi-core SystemView trace control. Starts, stops or queries tracing process status.",
1632 "(start file://<outfile> [poll_period [trace_size [stop_tmo [wait4halt [skip_size]]]]) | (stop) | (status)",
1634 COMMAND_REGISTRATION_DONE