OpenOCD
esp32_apptrace.c
Go to the documentation of this file.
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 
3 /***************************************************************************
4  * ESP32xx application tracing module for OpenOCD *
5  * Copyright (C) 2017 Espressif Systems Ltd. *
6  ***************************************************************************/
7 
8 #ifdef HAVE_CONFIG_H
9 #include "config.h"
10 #endif
11 
12 #ifdef HAVE_ARPA_INET_H
13 #include <arpa/inet.h>
14 #endif
15 
16 #ifdef HAVE_NETDB_H
17 #include <netdb.h>
18 #endif
19 
20 #ifndef _WIN32
21 #include <netinet/tcp.h>
22 #include <sys/ioctl.h>
23 #endif
24 
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"
37 
38 #define ESP32_APPTRACE_USER_BLOCK_CORE(_v_) ((_v_) >> 15)
39 #define ESP32_APPTRACE_USER_BLOCK_LEN(_v_) ((_v_) & ~BIT(15))
40 
41 #define ESP32_APPTRACE_USER_BLOCK_HDR_SZ 4
42 
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
47 
48 #define ESP32_APPTRACE_TGT_STATE_TMO 5000
49 #define ESP_APPTRACE_BLOCKS_POOL_SZ 10
50 
52  int fout;
53 };
54 
56  int sockfd;
57 };
58 
60  int running;
61  uint32_t block_id;
62  uint32_t data_len;
63 };
64 
66  uint16_t block_sz;
67  uint16_t wr_sz;
68 };
69 #define APPTRACE_BLOCK_SIZE_OFFSET 0
70 #define APPTRACE_WR_SIZE_OFFSET 2
71 
73  struct list_head node;
74  uint8_t *data;
75  uint32_t data_len;
76 };
77 
78 static int esp32_apptrace_data_processor(void *priv);
81  uint32_t *fired_target_num);
83  struct esp32_apptrace_target_state *targets);
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);
89 
90 static const bool s_time_stats_enable = true;
91 
92 /*********************************************************************
93 * Trace destination API
94 **********************************************************************/
95 
96 static int esp32_apptrace_file_dest_write(void *priv, uint8_t *data, int size)
97 {
99 
100  int wr_sz = write(dest_data->fout, data, size);
101  if (wr_sz != size) {
102  LOG_ERROR("Failed to write %d bytes to out file (%d)! Written %d.", size, errno, wr_sz);
103  return ERROR_FAIL;
104  }
105  return ERROR_OK;
106 }
107 
109 {
111 
112  if (dest_data->fout > 0)
113  close(dest_data->fout);
114  free(dest_data);
115  return ERROR_OK;
116 }
117 
118 static int esp32_apptrace_file_dest_init(struct esp32_apptrace_dest *dest, const char *dest_name)
119 {
120  struct esp32_apptrace_dest_file_data *dest_data = calloc(1, sizeof(*dest_data));
121  if (!dest_data) {
122  LOG_ERROR("Failed to alloc mem for file dest!");
123  return ERROR_FAIL;
124  }
125 
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);
130  free(dest_data);
131  return ERROR_FAIL;
132  }
133 
134  dest->priv = dest_data;
137  dest->log_progress = true;
138 
139  return ERROR_OK;
140 }
141 
142 static int esp32_apptrace_console_dest_write(void *priv, uint8_t *data, int size)
143 {
144  LOG_USER_N("%.*s", size, data);
145  return ERROR_OK;
146 }
147 
149 {
150  return ERROR_OK;
151 }
152 
153 static int esp32_apptrace_console_dest_init(struct esp32_apptrace_dest *dest, const char *dest_name)
154 {
155  dest->priv = NULL;
158  dest->log_progress = false;
159 
160  return ERROR_OK;
161 }
162 
163 static int esp32_apptrace_tcp_dest_write(void *priv, uint8_t *data, int size)
164 {
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);
167  if (wr_sz != size) {
168  LOG_ERROR("Failed to write %u bytes to out socket (%d)! Written %d.", size, errno, wr_sz);
169  return ERROR_FAIL;
170  }
171  return ERROR_OK;
172 }
173 
175 {
176  struct esp32_apptrace_dest_tcp_data *dest_data = (struct esp32_apptrace_dest_tcp_data *)priv;
177 
178  if (dest_data->sockfd > 0)
179  close_socket(dest_data->sockfd);
180  free(dest_data);
181  return ERROR_OK;
182 }
183 
184 static int esp32_apptrace_tcp_dest_init(struct esp32_apptrace_dest *dest, const char *dest_name)
185 {
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");
191  }
192  size_t hostname_len = port_sep - dest_name;
193 
194  char hostname[64] = { 0 };
195  if (hostname_len >= sizeof(hostname)) {
196  LOG_ERROR("apptrace: Hostname too long");
198  }
199  memcpy(hostname, dest_name, hostname_len);
200 
201  const char *port_str = port_sep + 1;
202  struct addrinfo *ai;
203  int flags = 0;
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,
210  .ai_protocol = 0,
211  .ai_flags = flags
212  };
213  int res = getaddrinfo(hostname, port_str, &hint, &ai);
214  if (res != 0) {
215  LOG_ERROR("apptrace: Failed to resolve host name: %s", hostname);
216  return ERROR_FAIL;
217  }
218  int sockfd = -1;
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);
221  if (sockfd < 0) {
222  LOG_DEBUG("apptrace: Failed to create socket (%d, %d, %d) (%s)",
223  ai_it->ai_family,
224  ai_it->ai_socktype,
225  ai_it->ai_protocol,
226  strerror(errno));
227  continue;
228  }
229 
230  char cur_hostname[NI_MAXHOST];
231  char cur_portname[NI_MAXSERV];
232  res =
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);
237  if (res != 0)
238  continue;
239 
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) {
243  sockfd = -1;
244  LOG_WARNING("apptrace: Connection failed (%s)", strerror(errno));
245  continue;
246  }
247  break;
248  }
249  freeaddrinfo(ai);
250  if (sockfd < 0) {
251  LOG_ERROR("apptrace: Could not connect to %s:%s", hostname, port_str);
252  return ERROR_FAIL;
253  }
254  LOG_INFO("apptrace: Connected!");
255 
256  struct esp32_apptrace_dest_tcp_data *dest_data = calloc(1, sizeof(struct esp32_apptrace_dest_tcp_data));
257  if (!dest_data) {
258  LOG_ERROR("apptrace: Failed to alloc mem for tcp dest!");
260  return ERROR_FAIL;
261  }
262 
263  dest_data->sockfd = sockfd;
264  dest->priv = dest_data;
267  dest->log_progress = true;
268 
269  return ERROR_OK;
270 }
271 
272 int esp32_apptrace_dest_init(struct esp32_apptrace_dest dest[], const char *dest_paths[], unsigned int max_dests)
273 {
274  int res;
275  unsigned int i;
276 
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]);
284  else
285  break;
286 
287  if (res != ERROR_OK) {
288  LOG_ERROR("apptrace: Failed to init trace data destination '%s'!", dest_paths[i]);
289  return 0;
290  }
291  }
292 
293  return i;
294 }
295 
296 int esp32_apptrace_dest_cleanup(struct esp32_apptrace_dest dest[], unsigned int max_dests)
297 {
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);
301  dest[i].priv = NULL;
302  return res;
303  }
304  }
305  return ERROR_OK;
306 }
307 
308 /*********************************************************************
309 * Trace data blocks management API
310 **********************************************************************/
312 {
313  struct esp32_apptrace_block *cur;
314  struct list_head *head = &ctx->free_trace_blocks;
315  struct list_head *tmp, *pos;
316 
317  list_for_each_safe(pos, tmp, head) {
318  cur = list_entry(pos, struct esp32_apptrace_block, node);
319  if (cur) {
320  list_del(&cur->node);
321  free(cur->data);
322  free(cur);
323  }
324  }
325 
326  head = &ctx->ready_trace_blocks;
327 
328  list_for_each_safe(pos, tmp, head) {
329  cur = list_entry(pos, struct esp32_apptrace_block, node);
330  if (cur) {
331  list_del(&cur->node);
332  free(cur->data);
333  free(cur);
334  }
335  }
336 }
337 
339 {
340  struct esp32_apptrace_block *block = NULL;
341 
342  if (!list_empty(&ctx->free_trace_blocks)) {
343  /*get first */
345  list_del(&block->node);
346  }
347 
348  return block;
349 }
350 
352 {
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);
357 
358  return ERROR_OK;
359 }
360 
362 {
363  if (list_empty(&ctx->ready_trace_blocks))
364  return NULL;
365 
366  struct esp32_apptrace_block *block =
368 
369  /* remove it from ready list */
370  list_del(&block->node);
371 
372  return block;
373 }
374 
376 {
377  /* add to free blocks list */
378  INIT_LIST_HEAD(&block->node);
379  list_add(&block->node, &ctx->free_trace_blocks);
380 
381  return ERROR_OK;
382 }
383 
385 {
386  int64_t timeout = timeval_ms() + (LOG_LEVEL_IS(LOG_LVL_DEBUG) ? 70000 : 5000);
387  while (!list_empty(&ctx->ready_trace_blocks)) {
388  alive_sleep(100);
389  if (timeval_ms() >= timeout) {
390  LOG_ERROR("Failed to wait for pended trace blocks!");
391  return ERROR_FAIL;
392  }
393  }
394  /* signal timer callback to stop */
395  ctx->running = 0;
397  return ERROR_OK;
398 }
399 
400 /*********************************************************************
401 * Trace commands
402 **********************************************************************/
403 
405 {
407 
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;
412  cmd_ctx->cmd = cmd;
413 
414  if (target->smp) {
415  struct target_list *head;
416  struct target *curr;
417  unsigned int i = 0;
418  cmd_ctx->cores_num = 0;
420  curr = head->target;
421  if (i == ESP32_APPTRACE_MAX_CORES_NUM) {
422  command_print(cmd, "Too many cores configured! Max %d cores are supported.",
424  return ERROR_FAIL;
425  }
426  if (!target_was_examined(curr))
427  continue;
428  cmd_ctx->cores_num++;
429  cmd_ctx->cpus[i++] = curr;
430  }
431  } else {
432  cmd_ctx->cores_num = 1;
433  cmd_ctx->cpus[0] = target;
434  }
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!");
438 
439  struct xtensa *xtensa = target->arch_info;
442  } else { /* TODO: riscv is not supported yet */
443  command_print(cmd, "Unsupported target arch 0x%X", xtensa->common_magic);
444  return ERROR_FAIL;
445  }
446 
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!");
450  return ERROR_FAIL;
451  }
452  LOG_INFO("Total trace memory: %" PRIu32 " bytes", cmd_ctx->max_trace_block_sz);
453 
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));
458  if (!block) {
459  command_print(cmd, "Failed to alloc trace buffer entry!");
461  return ERROR_FAIL;
462  }
463  block->data = malloc(cmd_ctx->max_trace_block_sz);
464  if (!block->data) {
465  free(block);
466  command_print(cmd, "Failed to alloc trace buffer %" PRIu32 " bytes!", cmd_ctx->max_trace_block_sz);
468  return ERROR_FAIL;
469  }
470  INIT_LIST_HEAD(&block->node);
471  list_add(&block->node, &cmd_ctx->free_trace_blocks);
472  }
473 
474  cmd_ctx->running = 1;
475  if (cmd_ctx->mode != ESP_APPTRACE_CMD_MODE_SYNC) {
477  0,
479  cmd_ctx);
480  if (res != ERROR_OK) {
481  command_print(cmd, "Failed to start trace data timer callback (%d)!", res);
483  return ERROR_FAIL;
484  }
485  }
486 
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;
490  }
491  if (duration_start(&cmd_ctx->idle_time) != 0) {
492  command_print(cmd, "Failed to start idle time measurement!");
494  return ERROR_FAIL;
495  }
496 
497  return ERROR_OK;
498 }
499 
501 {
503  return ERROR_OK;
504 }
505 
506 #define ESP32_APPTRACE_CMD_NUM_ARG_CHECK(_cmd_, _arg_, _start_, _end_) \
507  do { \
508  if ((_arg_) == 0 && (_start_) == (_end_)) { \
509  command_print(_cmd_, "Invalid '" # _arg_ "' arg!"); \
510  return; \
511  } \
512  } while (0)
513 
515  struct esp32_apptrace_cmd_data *cmd_data,
516  const char **argv,
517  int argc)
518 {
519  char *end;
520 
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);
523  if (argc > 1) {
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);
526  if (argc > 2) {
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;
530  if (argc > 3) {
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);
533  if (argc > 4) {
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);
536  }
537  }
538  }
539  }
540 }
541 
542 static int esp32_apptrace_core_id_get(struct target *target, uint8_t *hdr_buf)
543 {
545 }
546 
547 static uint32_t esp32_apptrace_usr_block_len_get(struct target *target, uint8_t *hdr_buf, uint32_t *wr_len)
548 {
551 }
552 
554  struct command_invocation *cmd,
555  int mode,
556  const char **argv,
557  int argc)
558 {
559  struct esp32_apptrace_cmd_data *cmd_data;
560 
561  if (argc < 1) {
562  command_print(cmd, "Not enough args! Need trace data destination!");
563  return ERROR_FAIL;
564  }
565 
566  int res = esp32_apptrace_cmd_ctx_init(cmd_ctx, cmd, mode);
567  if (res != ERROR_OK)
568  return res;
569 
570  cmd_data = calloc(1, sizeof(*cmd_data));
571  assert(cmd_data && "No memory for command data!");
572  cmd_ctx->cmd_priv = cmd_data;
573 
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!");
578  free(cmd_data);
579  goto on_error;
580  }
581  cmd_ctx->stop_tmo = -1.0; /* infinite */
582  cmd_data->max_len = UINT32_MAX;
583  cmd_data->poll_period = 0 /*ms*/;
584  if (argc > 1)
585  /* parse remaining args */
586  esp32_apptrace_cmd_args_parse(cmd_ctx, cmd_data, &argv[1], argc - 1);
587 
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,
590  cmd_data->max_len,
591  cmd_ctx->stop_tmo,
592  cmd_data->poll_period,
593  cmd_data->wait4halt,
594  cmd_data->skip_len);
595 
599  return ERROR_OK;
600 on_error:
601  command_print(cmd, "Not enough args! Need %d trace data destinations!", cmd_ctx->cores_num);
602  cmd_ctx->running = 0;
604  return res;
605 }
606 
608 {
609  struct esp32_apptrace_cmd_data *cmd_data = cmd_ctx->cmd_priv;
610 
611  esp32_apptrace_dest_cleanup(&cmd_data->data_dest, 1);
612  free(cmd_data);
613  cmd_ctx->cmd_priv = NULL;
615  return ERROR_OK;
616 }
617 
619 {
620  struct esp32_apptrace_cmd_data *cmd_data = ctx->cmd_priv;
621  uint32_t trace_sz = 0;
622 
623  if (cmd_data)
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",
627  trace_sz,
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);
641  }
642 }
643 
645 {
646  LOG_USER("Wait for halt...");
647  while (!openocd_is_shutdown_pending()) {
648  int res = target_poll(target);
649  if (res != ERROR_OK)
650  return res;
651  if (target->state == TARGET_HALTED) {
652  LOG_USER("%s: HALTED", target->cmd_name);
653  break;
654  }
655  alive_sleep(500);
656  }
657  return ERROR_OK;
658 }
659 
661  struct esp32_apptrace_target_state *targets)
662 {
663  int res = ERROR_OK;
664 
665  memset(targets, 0, ctx->cores_num * sizeof(struct esp32_apptrace_target_state));
666  /* halt all CPUs */
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]))
670  continue;
671  if (ctx->cpus[k]->state == TARGET_HALTED)
672  continue;
673  res = target_halt(ctx->cpus[k]);
674  if (res != ERROR_OK) {
675  LOG_ERROR("Failed to halt target (%d)!", res);
676  return res;
677  }
679  if (res != ERROR_OK) {
680  LOG_ERROR("Failed to wait halt target %s / %d (%d)!",
681  target_name(ctx->cpus[k]),
682  ctx->cpus[k]->state,
683  res);
684  return res;
685  }
686  }
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++) {
690  uint32_t stat;
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);
694  return res;
695  }
696  /* check if some CPU stopped inside tracing regs update critical section */
697  if (stat) {
699  res = ctx->hw->leave_trace_crit_section_start(ctx->cpus[k]);
700  if (res != ERROR_OK)
701  return res;
702  }
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);
707  return res;
708  }
709  while (stat) {
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);
715  return res;
716  }
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,
722  if (res != ERROR_OK) {
723  LOG_ERROR("Failed to wait halt on bp (%d)!", res);
724  breakpoint_remove(ctx->cpus[k], bp_addr);
725  return res;
726  }
727  debug_reason = ctx->cpus[k]->debug_reason;
728  }
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);
733  return res;
734  }
735  }
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]);
739  if (res != ERROR_OK)
740  return res;
741  }
742  }
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);
746  return res;
747  }
748  }
749 
750  return ERROR_OK;
751 }
752 
754  bool conn,
755  bool resume_target)
756 {
758 
759  if (conn)
760  LOG_USER("Connect targets...");
761  else
762  LOG_USER("Disconnect targets...");
763 
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);
767  return res;
768  }
769  if (ctx->cores_num > 1) {
770  /* set block ids to the highest value */
771  uint32_t max_id = 0;
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;
775  }
776  for (unsigned int k = 0; k < ctx->cores_num; k++)
777  target_to_connect[k].block_id = max_id;
778  }
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*/,
784  conn,
785  false /*no host data*/);
786  if (res != ERROR_OK) {
787  command_print(ctx->cmd, "Failed to read trace status (%d)!", res);
788  return res;
789  }
790  }
791  if (resume_target) {
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 */
797  continue;
798  }
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);
802  return res;
803  }
804  if (ctx->cpus[k]->smp)
805  smp_resumed = true;
806  }
807  }
808  if (conn)
809  LOG_INFO("Targets connected.");
810  else
811  LOG_INFO("Targets disconnected.");
812  return ERROR_OK;
813 }
814 
816  uint32_t block_id,
817  const uint8_t *data,
818  uint32_t size)
819 {
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 };
823 
824  if (size > hw->usr_block_max_size_get(target)) {
825  LOG_ERROR("Too large user block %" PRId32, size);
826  return ERROR_FAIL;
827  }
828 
829  return hw->buffs_write(target,
830  ARRAY_SIZE(buf_sz),
831  buf_sz,
832  bufs,
833  block_id,
834  true /*ack target data*/,
835  true /*host data*/);
836 }
837 
838 static uint32_t esp32_apptrace_usr_block_check(struct esp32_apptrace_cmd_ctx *ctx, uint8_t *hdr_buf)
839 {
840  uint32_t wr_len = 0;
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;
846  }
847  return usr_len;
848 }
849 
852  uint32_t *fired_target_num)
853 {
854  if (fired_target_num)
855  *fired_target_num = UINT32_MAX;
856 
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]));
861  return res;
862  }
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;
868  break;
869  }
870  }
871  return ERROR_OK;
872 }
873 
875  unsigned int core_id,
876  uint8_t *data,
877  uint32_t data_len)
878 {
879  struct esp32_apptrace_cmd_data *cmd_data = ctx->cmd_priv;
880 
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;
888  }
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);
895  return res;
896  }
897  }
898  ctx->tot_len += wr_chunk_len;
899  } else {
900  ctx->tot_len += data_len;
901  }
902 
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)) {
907  ctx->running = 0;
908  if (duration_measure(&ctx->read_time) != 0) {
909  LOG_ERROR("Failed to stop trace read time measure!");
910  return ERROR_FAIL;
911  }
912  }
913  return ERROR_OK;
914 }
915 
917  struct esp32_apptrace_block *block)
918 {
919  uint32_t processed = 0;
920  uint32_t hdr_sz = ctx->trace_format.hdr_sz;
921 
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);
933  return res;
934  }
935  processed += usr_len + hdr_sz;
936  }
937  return ERROR_OK;
938 }
939 
941 {
942  struct esp32_apptrace_cmd_ctx *ctx = (struct esp32_apptrace_cmd_ctx *)priv;
943 
944  if (!ctx->running)
945  return ERROR_OK;
946 
948  if (!block)
949  return ERROR_OK;
950 
951  int res = esp32_apptrace_handle_trace_block(ctx, block);
952  if (res != ERROR_OK) {
953  ctx->running = 0;
954  LOG_ERROR("Failed to process trace block %" PRId32 " bytes!", block->data_len);
955  return res;
956  }
957  res = esp32_apptrace_block_free(ctx, block);
958  if (res != ERROR_OK) {
959  ctx->running = 0;
960  LOG_ERROR("Failed to free ready block!");
961  return res;
962  }
963 
964  return ERROR_OK;
965 }
966 
968 {
969  if (!ctx)
970  return ERROR_FAIL;
971 
972  unsigned int busy_target_num = 0;
973 
974  for (unsigned int i = 0; i < ctx->cores_num; i++) {
975  bool conn = true;
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);
979  return res;
980  }
981  if (!conn) {
982  uint32_t stat = 0;
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);
987  return res;
988  }
989  if (stat) {
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");
993  return ERROR_WAIT;
994  }
995  continue;
996  }
997  res = ctx->hw->ctrl_reg_write(ctx->cpus[i],
998  0,
999  0,
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);
1004  return res;
1005  }
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!");
1010  return ERROR_FAIL;
1011  }
1012  }
1013  }
1014  }
1015 
1016  return ERROR_OK;
1017 }
1018 
1019 static int esp32_apptrace_poll(void *priv)
1020 {
1021  struct esp32_apptrace_cmd_ctx *ctx = (struct esp32_apptrace_cmd_ctx *)priv;
1022  int res;
1023  uint32_t fired_target_num = 0;
1025  struct duration blk_proc_time;
1026 
1027  if (!ctx->running) {
1028  if (ctx->auto_clean)
1029  ctx->auto_clean(ctx);
1030  return ERROR_FAIL;
1031  }
1032 
1033  /* Check for connection is alive.For some reason target and therefore host_connected flag
1034  * might have been reset */
1036  if (res != ERROR_OK) {
1037  if (res != ERROR_WAIT)
1038  ctx->running = 0;
1039  return res;
1040  }
1041 
1042  /* check for data from target */
1043  res = esp32_apptrace_get_data_info(ctx, target_state, &fired_target_num);
1044  if (res != ERROR_OK) {
1045  ctx->running = 0;
1046  LOG_ERROR("Failed to read data len!");
1047  return res;
1048  }
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
1057  * */
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;
1063  }
1064  /* handle block ID overflow */
1065  if (max_block_id == ctx->hw->max_block_id && min_block_id == 0)
1066  max_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],
1071  max_block_id,
1072  0 /*all read*/,
1073  true /*host connected*/,
1074  false /*no host data*/);
1075  if (res != ERROR_OK) {
1076  ctx->running = 0;
1077  LOG_TARGET_ERROR(ctx->cpus[i], "Failed to ack empty data block!");
1078  return res;
1079  }
1080  }
1081  }
1082  ctx->last_blk_id = max_block_id;
1083  }
1084  if (ctx->stop_tmo != -1.0) {
1085  if (duration_measure(&ctx->idle_time) != 0) {
1086  ctx->running = 0;
1087  LOG_ERROR("Failed to measure idle time!");
1088  return ERROR_FAIL;
1089  }
1090  if (duration_elapsed(&ctx->idle_time) >= ctx->stop_tmo) {
1091  ctx->running = 0;
1092  LOG_ERROR("Data timeout!");
1093  return ERROR_FAIL;
1094  }
1095  }
1096  return ERROR_OK;/* no data */
1097  }
1098  /* sanity check */
1099  if (target_state[fired_target_num].data_len > ctx->max_trace_block_sz) {
1100  ctx->running = 0;
1101  LOG_ERROR("Too large block size %" PRId32 "!", target_state[fired_target_num].data_len);
1102  return ERROR_FAIL;
1103  }
1104  if (ctx->tot_len == 0) {
1105  if (duration_start(&ctx->read_time) != 0) {
1106  ctx->running = 0;
1107  LOG_ERROR("Failed to start trace read time measurement!");
1108  return ERROR_FAIL;
1109  }
1110  }
1112  if (!block) {
1113  ctx->running = 0;
1114  LOG_TARGET_ERROR(ctx->cpus[fired_target_num], "Failed to get free block for data!");
1115  return ERROR_FAIL;
1116  }
1117  if (s_time_stats_enable) {
1118  /* read block */
1119  if (duration_start(&blk_proc_time) != 0) {
1120  ctx->running = 0;
1121  LOG_ERROR("Failed to start block read time measurement!");
1122  return ERROR_FAIL;
1123  }
1124  }
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 */
1130  if (res != ERROR_OK) {
1131  ctx->running = 0;
1132  LOG_TARGET_ERROR(ctx->cpus[fired_target_num], "Failed to read data!");
1133  return res;
1134  }
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) {
1140  ctx->running = 0;
1141  LOG_ERROR("Failed to measure block read time!");
1142  return ERROR_FAIL;
1143  }
1144  /* update stats */
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;
1150 
1151  if (duration_start(&blk_proc_time) != 0) {
1152  ctx->running = 0;
1153  LOG_ERROR("Failed to start block proc time measurement!");
1154  return ERROR_FAIL;
1155  }
1156  }
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)
1162  continue;
1163  res = ctx->hw->ctrl_reg_write(ctx->cpus[i],
1164  ctx->last_blk_id,
1165  0 /*all read*/,
1166  true /*host connected*/,
1167  false /*no host data*/);
1168  if (res != ERROR_OK) {
1169  ctx->running = 0;
1170  LOG_TARGET_ERROR(ctx->cpus[i], "Failed to ack data!");
1171  return res;
1172  }
1173  LOG_TARGET_DEBUG(ctx->cpus[i], "Ack block %" PRId32, ctx->last_blk_id);
1174  }
1175  res = esp32_apptrace_ready_block_put(ctx, block);
1176  if (res != ERROR_OK) {
1177  ctx->running = 0;
1178  LOG_TARGET_ERROR(ctx->cpus[fired_target_num], "Failed to put ready block of data!");
1179  return res;
1180  }
1181  } else {
1182  res = esp32_apptrace_handle_trace_block(ctx, block);
1183  if (res != ERROR_OK) {
1184  ctx->running = 0;
1185  LOG_ERROR("Failed to process trace block %" PRId32 " bytes!", block->data_len);
1186  return res;
1187  }
1188  res = esp32_apptrace_block_free(ctx, block);
1189  if (res != ERROR_OK) {
1190  ctx->running = 0;
1191  LOG_ERROR("Failed to free ready block!");
1192  return res;
1193  }
1194  }
1195  if (ctx->stop_tmo != -1.0) {
1196  /* start idle time measurement */
1197  if (duration_start(&ctx->idle_time) != 0) {
1198  ctx->running = 0;
1199  LOG_ERROR("Failed to start idle time measure!");
1200  return ERROR_FAIL;
1201  }
1202  }
1203  if (s_time_stats_enable) {
1204  if (duration_measure(&blk_proc_time) != 0) {
1205  ctx->running = 0;
1206  LOG_ERROR("Failed to stop block proc time measure!");
1207  return ERROR_FAIL;
1208  }
1209  /* update stats */
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;
1215  }
1216  return ERROR_OK;
1217 }
1218 
1219 static inline bool is_sysview_mode(int mode)
1220 {
1222 }
1223 
1225 {
1226  if (duration_measure(&ctx->read_time) != 0)
1227  LOG_ERROR("Failed to stop trace read time measurement!");
1229  if (res != ERROR_OK)
1230  LOG_ERROR("Failed to unregister target timer handler (%d)!", res);
1231  if (is_sysview_mode(ctx->mode)) {
1232  /* stop tracing */
1233  res = esp32_sysview_stop(ctx);
1234  if (res != ERROR_OK)
1235  LOG_ERROR("sysview: Failed to stop tracing!");
1236  }
1237  /* data processor is alive, so wait for all received blocks to be processed */
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);
1245  res = esp32_apptrace_cmd_cleanup(ctx);
1246  if (res != ERROR_OK)
1247  LOG_ERROR("Failed to cleanup cmd ctx (%d)!", res);
1248 }
1249 
1250 /* this function must be called after connecting to targets */
1252 {
1253  uint8_t cmds[] = { SEGGER_SYSVIEW_COMMAND_ID_START };
1254  uint32_t fired_target_num = 0;
1256  struct esp32_sysview_cmd_data *cmd_data = ctx->cmd_priv;
1257 
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!");
1262  return res;
1263  }
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;
1268  }
1269  /* start tracing */
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!");
1274  return res;
1275  }
1276  cmd_data->sv_trace_running = 1;
1277  return res;
1278 }
1279 
1281 {
1282  uint32_t old_block_id, fired_target_num = 0, empty_target_num = 0;
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;
1287 
1289  if (!block) {
1290  LOG_ERROR("Failed to get free block for data on (%s)!", target_name(ctx->cpus[fired_target_num]));
1291  return ERROR_FAIL;
1292  }
1293 
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 */
1297  if (res != ERROR_OK) {
1298  LOG_ERROR("sysview: Failed to halt targets (%d)!", res);
1299  return res;
1300  }
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;
1306  break;
1307  }
1308  }
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]));
1316  return res;
1317  }
1318  /* process data */
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);
1323  return res;
1324  }
1325  }
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,
1328  cmds,
1329  sizeof(cmds));
1330  if (res != ERROR_OK) {
1331  LOG_ERROR("sysview: Failed to stop tracing!");
1332  return res;
1333  }
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);
1344  return res;
1345  }
1346  }
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 */
1353  continue;
1354  }
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);
1358  return res;
1359  }
1360  if (ctx->cpus[k]->smp)
1361  smp_resumed = true;
1362  }
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!");
1367  return ERROR_FAIL;
1368  }
1369  /* we are waiting for the last data from tracing block and also there can be data in the pended
1370  * data buffer */
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!");
1376  return res;
1377  }
1378  if (fired_target_num == UINT32_MAX) {
1379  /* it can happen that there is no pending (last) target data, but block was
1380  * switched */
1381  /* in this case block_ids on both CPUs are equal, so select the first one */
1382  fired_target_num = 0;
1383  }
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,
1389  block->data,
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]));
1394  } else {
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,
1400  0 /*all read*/,
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);
1406  return res;
1407  }
1408  }
1409  /* process data */
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!",
1414  block->data_len);
1415  return res;
1416  }
1417  }
1418  old_block_id = target_state[fired_target_num].block_id;
1419  }
1420  }
1421  if (duration_measure(&wait_time) != 0) {
1422  LOG_ERROR("Failed to start trace stop timeout measurement!");
1423  return ERROR_FAIL;
1424  }
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.");
1428  break;
1429  }
1430  }
1431  return res;
1432 }
1433 
1434 static int esp32_cmd_apptrace_generic(struct command_invocation *cmd, int mode, const char **argv, int argc)
1435 {
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;
1441 
1442  if (argc < 1)
1444 
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));
1451  curr = head->target;
1452  if (target_was_examined(curr)) {
1453  target = curr;
1454  LOG_WARNING("Run command on target '%s'", target_name(target));
1455  break;
1456  }
1457  }
1458  }
1459  old_state = target->state;
1460 
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,
1465  cmd,
1466  mode,
1468  &argv[1],
1469  argc - 1);
1470  if (res != ERROR_OK) {
1471  command_print(cmd, "Failed to init cmd ctx (%d)!", res);
1472  return res;
1473  }
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!");
1479  return ERROR_FAIL;
1480  }
1482  } else {
1483  res = esp32_apptrace_cmd_init(&s_at_cmd_ctx,
1484  cmd,
1485  mode,
1486  &argv[1],
1487  argc - 1);
1488  if (res != ERROR_OK) {
1489  command_print(cmd, "Failed to init cmd ctx (%d)!", res);
1490  return res;
1491  }
1492  cmd_data = s_at_cmd_ctx.cmd_priv;
1494  }
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;
1501  }
1502  }
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;
1507  }
1508  if (is_sysview_mode(mode)) {
1509  /* start tracing */
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!");
1516  return res;
1517  }
1518  }
1520  cmd_data->poll_period,
1522  &s_at_cmd_ctx);
1523  if (res != ERROR_OK) {
1524  command_print(cmd, "Failed to register target timer handler (%d)!", res);
1525  goto _on_start_error;
1526  }
1527  } else if (strcmp(argv[0], "stop") == 0) {
1528  if (!s_at_cmd_ctx.running) {
1529  command_print(cmd, "Tracing is not running!");
1530  return ERROR_FAIL;
1531  }
1532  esp32_apptrace_cmd_stop(&s_at_cmd_ctx);
1533  return ERROR_OK;
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);
1538  return ERROR_OK;
1539  } else if (strcmp(argv[0], "dump") == 0) {
1540  if (is_sysview_mode(mode)) {
1541  command_print(cmd, "Not supported!");
1542  return ERROR_FAIL;
1543  }
1544  /* [dump outfile] - post-mortem dump without connection to targets */
1545  res = esp32_apptrace_cmd_init(&s_at_cmd_ctx,
1546  cmd,
1547  mode,
1548  &argv[1],
1549  argc - 1);
1550  if (res != ERROR_OK) {
1551  command_print(cmd, "Failed to init cmd ctx (%d)!", res);
1552  return res;
1553  }
1554  s_at_cmd_ctx.stop_tmo = 0.01; /* use small stop tmo */
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);
1561  break;
1562  }
1563  /* let registered timer callbacks to run */
1565  }
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);
1571  }
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);
1576  } else {
1577  command_print(cmd, "Invalid action '%s'!", argv[0]);
1578  }
1579 
1580  return res;
1581 
1582 _on_start_error:
1583  s_at_cmd_ctx.running = 0;
1584  if (is_sysview_mode(mode))
1585  esp32_sysview_cmd_cleanup(&s_at_cmd_ctx);
1586  else
1587  esp32_apptrace_cmd_cleanup(&s_at_cmd_ctx);
1588  return res;
1589 }
1590 
1591 COMMAND_HANDLER(esp32_cmd_apptrace)
1592 {
1594 }
1595 
1596 COMMAND_HANDLER(esp32_cmd_sysview)
1597 {
1599 }
1600 
1601 COMMAND_HANDLER(esp32_cmd_sysview_mcore)
1602 {
1604 }
1605 
1607  {
1608  .name = "apptrace",
1609  .handler = esp32_cmd_apptrace,
1610  .mode = COMMAND_EXEC,
1611  .help =
1612  "App Tracing: application level trace control. Starts, stops or queries tracing process status.",
1613  .usage =
1614  "(start <destination> [poll_period [trace_size [stop_tmo [wait4halt [skip_size]]]]) | (stop) | (status) | (dump <destination>)",
1615  },
1616  {
1617  .name = "sysview",
1618  .handler = esp32_cmd_sysview,
1619  .mode = COMMAND_EXEC,
1620  .help =
1621  "App Tracing: SEGGER SystemView compatible trace control. Starts, stops or queries tracing process status.",
1622  .usage =
1623  "(start file://<outfile1> [file://<outfile2>] [poll_period [trace_size [stop_tmo [wait4halt [skip_size]]]]) | (stop) | (status)",
1624  },
1625  {
1626  .name = "sysview_mcore",
1627  .handler = esp32_cmd_sysview_mcore,
1628  .mode = COMMAND_EXEC,
1629  .help =
1630  "App Tracing: Espressif multi-core SystemView trace control. Starts, stops or queries tracing process status.",
1631  .usage =
1632  "(start file://<outfile> [poll_period [trace_size [stop_tmo [wait4halt [skip_size]]]]) | (stop) | (status)",
1633  },
1635 };
enum arm_mode mode
Definition: armv4_5.c:277
int breakpoint_remove(struct target *target, target_addr_t address)
Definition: breakpoints.c:344
int breakpoint_add(struct target *target, target_addr_t address, uint32_t length, enum breakpoint_type type)
Definition: breakpoints.c:208
@ BKPT_HARD
Definition: breakpoints.h:18
void command_print(struct command_invocation *cmd, const char *format,...)
Definition: command.c:443
#define CMD
Use this macro to access the command being handled, rather than accessing the variable directly.
Definition: command.h:141
#define CMD_ARGV
Use this macro to access the arguments for the command being handled, rather than accessing the varia...
Definition: command.h:156
#define ERROR_COMMAND_SYNTAX_ERROR
Definition: command.h:402
#define CMD_ARGC
Use this macro to access the number of arguments for the command being handled, rather than accessing...
Definition: command.h:151
#define CMD_CTX
Use this macro to access the context of the command being handled, rather than accessing the variable...
Definition: command.h:146
#define COMMAND_REGISTRATION_DONE
Use this as the last entry in an array of command_registration records.
Definition: command.h:253
#define ERROR_COMMAND_ARGUMENT_INVALID
Definition: command.h:404
@ COMMAND_EXEC
Definition: command.h:40
static int esp32_apptrace_cmd_cleanup(struct esp32_apptrace_cmd_ctx *cmd_ctx)
static int esp32_apptrace_check_connection(struct esp32_apptrace_cmd_ctx *ctx)
static struct esp32_apptrace_block * esp32_apptrace_ready_block_get(struct esp32_apptrace_cmd_ctx *ctx)
int esp_apptrace_usr_block_write(const struct esp32_apptrace_hw *hw, struct target *target, uint32_t block_id, const uint8_t *data, uint32_t size)
#define ESP_APPTRACE_CMD_MODE_SYNC
static int esp32_apptrace_console_dest_write(void *priv, uint8_t *data, int size)
static int esp32_apptrace_safe_halt_targets(struct esp32_apptrace_cmd_ctx *ctx, struct esp32_apptrace_target_state *targets)
static uint32_t esp32_apptrace_usr_block_check(struct esp32_apptrace_cmd_ctx *ctx, uint8_t *hdr_buf)
COMMAND_HANDLER(esp32_cmd_apptrace)
static bool is_sysview_mode(int mode)
#define ESP32_APPTRACE_USER_BLOCK_LEN(_v_)
static int esp32_apptrace_wait4halt(struct esp32_apptrace_cmd_ctx *ctx, struct target *target)
static int esp32_sysview_stop(struct esp32_apptrace_cmd_ctx *ctx)
static uint32_t esp32_apptrace_usr_block_len_get(struct target *target, uint8_t *hdr_buf, uint32_t *wr_len)
static int esp32_apptrace_tcp_dest_init(struct esp32_apptrace_dest *dest, const char *dest_name)
static int esp32_apptrace_ready_block_put(struct esp32_apptrace_cmd_ctx *ctx, struct esp32_apptrace_block *block)
void esp32_apptrace_cmd_args_parse(struct esp32_apptrace_cmd_ctx *cmd_ctx, struct esp32_apptrace_cmd_data *cmd_data, const char **argv, int argc)
static int esp32_apptrace_file_dest_cleanup(void *priv)
static int esp32_apptrace_wait_tracing_finished(struct esp32_apptrace_cmd_ctx *ctx)
int esp32_apptrace_dest_cleanup(struct esp32_apptrace_dest dest[], unsigned int max_dests)
#define ESP_APPTRACE_CMD_MODE_SYSVIEW
#define APPTRACE_WR_SIZE_OFFSET
#define ESP_APPTRACE_CMD_MODE_GEN
static int esp32_apptrace_file_dest_init(struct esp32_apptrace_dest *dest, const char *dest_name)
static int esp32_apptrace_file_dest_write(void *priv, uint8_t *data, int size)
static int esp32_apptrace_console_dest_cleanup(void *priv)
#define APPTRACE_BLOCK_SIZE_OFFSET
static void esp32_apptrace_cmd_stop(struct esp32_apptrace_cmd_ctx *ctx)
#define ESP32_APPTRACE_CMD_NUM_ARG_CHECK(_cmd_, _arg_, _start_, _end_)
#define ESP32_APPTRACE_USER_BLOCK_CORE(_v_)
#define ESP32_APPTRACE_TGT_STATE_TMO
static int esp32_apptrace_tcp_dest_write(void *priv, uint8_t *data, int size)
static int esp32_apptrace_handle_trace_block(struct esp32_apptrace_cmd_ctx *ctx, struct esp32_apptrace_block *block)
static const bool s_time_stats_enable
static int esp32_apptrace_data_processor(void *priv)
static int esp32_apptrace_block_free(struct esp32_apptrace_cmd_ctx *ctx, struct esp32_apptrace_block *block)
static int esp32_cmd_apptrace_generic(struct command_invocation *cmd, int mode, const char **argv, int argc)
static int esp32_apptrace_process_data(struct esp32_apptrace_cmd_ctx *ctx, unsigned int core_id, uint8_t *data, uint32_t data_len)
static struct esp32_apptrace_block * esp32_apptrace_free_block_get(struct esp32_apptrace_cmd_ctx *ctx)
#define ESP_APPTRACE_BLOCKS_POOL_SZ
static void esp32_apptrace_print_stats(struct esp32_apptrace_cmd_ctx *ctx)
static int esp32_apptrace_poll(void *priv)
static int esp32_apptrace_get_data_info(struct esp32_apptrace_cmd_ctx *ctx, struct esp32_apptrace_target_state *target_state, uint32_t *fired_target_num)
#define ESP32_APPTRACE_USER_BLOCK_HDR_SZ
static int esp32_sysview_start(struct esp32_apptrace_cmd_ctx *ctx)
static int esp32_apptrace_cmd_init(struct esp32_apptrace_cmd_ctx *cmd_ctx, struct command_invocation *cmd, int mode, const char **argv, int argc)
static int esp32_apptrace_connect_targets(struct esp32_apptrace_cmd_ctx *ctx, bool conn, bool resume_target)
int esp32_apptrace_dest_init(struct esp32_apptrace_dest dest[], const char *dest_paths[], unsigned int max_dests)
int esp32_apptrace_cmd_ctx_init(struct esp32_apptrace_cmd_ctx *cmd_ctx, struct command_invocation *cmd, int mode)
const struct command_registration esp32_apptrace_command_handlers[]
static int esp32_apptrace_tcp_dest_cleanup(void *priv)
int esp32_apptrace_cmd_ctx_cleanup(struct esp32_apptrace_cmd_ctx *cmd_ctx)
static int esp32_apptrace_core_id_get(struct target *target, uint8_t *hdr_buf)
static int esp32_apptrace_console_dest_init(struct esp32_apptrace_dest *dest, const char *dest_name)
static void esp32_apptrace_blocks_pool_cleanup(struct esp32_apptrace_cmd_ctx *ctx)
#define ESP_APPTRACE_CMD_MODE_SYSVIEW_MCORE
#define ESP32_APPTRACE_MAX_CORES_NUM
int esp32_sysview_cmd_init(struct esp32_apptrace_cmd_ctx *cmd_ctx, struct command_invocation *cmd, int mode, bool mcore_format, const char **argv, int argc)
Definition: esp32_sysview.c:33
int esp32_sysview_process_data(struct esp32_apptrace_cmd_ctx *ctx, unsigned int core_id, uint8_t *data, uint32_t data_len)
int esp32_sysview_cmd_cleanup(struct esp32_apptrace_cmd_ctx *cmd_ctx)
static struct esp_usb_jtag * priv
Definition: esp_usb_jtag.c:219
static struct esp_xtensa_common * target_to_esp_xtensa(struct target *target)
Definition: esp_xtensa.h:24
static int sockfd
Definition: jtag_dpi.c:33
static void list_add(struct list_head *new, struct list_head *head)
Definition: list.h:193
#define list_first_entry(ptr, type, member)
Definition: list.h:127
static int list_empty(const struct list_head *head)
Definition: list.h:60
#define list_last_entry(ptr, type, member)
Definition: list.h:130
static void list_del(struct list_head *entry)
Definition: list.h:87
#define list_entry(ptr, type, field)
Definition: list.h:125
#define list_for_each_safe(p, n, head)
Definition: list.h:148
static void INIT_LIST_HEAD(struct list_head *list)
Definition: list.h:53
void alive_sleep(uint64_t ms)
Definition: log.c:456
#define LOG_USER(expr ...)
Definition: log.h:135
#define LOG_TARGET_WARNING(target, fmt_str,...)
Definition: log.h:155
#define ERROR_WAIT
Definition: log.h:171
#define LOG_WARNING(expr ...)
Definition: log.h:129
#define ERROR_FAIL
Definition: log.h:170
#define LOG_TARGET_ERROR(target, fmt_str,...)
Definition: log.h:158
#define LOG_TARGET_DEBUG(target, fmt_str,...)
Definition: log.h:149
#define LOG_USER_N(expr ...)
Definition: log.h:138
#define LOG_ERROR(expr ...)
Definition: log.h:132
#define LOG_LEVEL_IS(FOO)
Definition: log.h:99
#define LOG_INFO(expr ...)
Definition: log.h:126
#define LOG_DEBUG(expr ...)
Definition: log.h:109
#define ERROR_OK
Definition: log.h:164
@ LOG_LVL_DEBUG
Definition: log.h:47
#define O_BINARY
Definition: replacements.h:37
static int close_socket(int sock)
Definition: replacements.h:184
static int write_socket(int handle, const void *buffer, unsigned int count)
Definition: replacements.h:166
struct target * target
Definition: rtt/rtt.c:26
size_t size
Size of the control block search area.
Definition: rtt/rtt.c:30
@ SEGGER_SYSVIEW_COMMAND_ID_STOP
@ SEGGER_SYSVIEW_COMMAND_ID_START
bool openocd_is_shutdown_pending(void)
Definition: server.c:752
#define foreach_smp_target(pos, head)
Definition: smp.h:15
When run_command is called, a new instance will be created on the stack, filled with the proper value...
Definition: command.h:76
const char * name
Definition: command.h:235
struct list_head node
struct target * cpus[ESP32_APPTRACE_MAX_CORES_NUM]
enum target_state target_state
struct target * target
struct duration idle_time
struct duration read_time
struct list_head ready_trace_blocks
struct esp32_apptrace_cmd_stats stats
int(* process_data)(struct esp32_apptrace_cmd_ctx *ctx, unsigned int core_id, uint8_t *data, uint32_t data_len)
struct command_invocation * cmd
const struct esp32_apptrace_hw * hw
void(* auto_clean)(struct esp32_apptrace_cmd_ctx *ctx)
struct list_head free_trace_blocks
struct esp32_apptrace_format trace_format
struct esp32_apptrace_dest data_dest
int(* write)(void *priv, uint8_t *data, int size)
int(* clean)(void *priv)
int(* core_id_get)(struct target *target, uint8_t *hdr_buf)
uint32_t(* usr_block_len_get)(struct target *target, uint8_t *hdr_buf, uint32_t *wr_len)
uint32_t(* usr_block_max_size_get)(struct target *target)
int(* leave_trace_crit_section_stop)(struct target *target)
int(* ctrl_reg_read)(struct target *target, uint32_t *block_id, uint32_t *len, bool *conn)
int(* data_read)(struct target *target, uint32_t size, uint8_t *buffer, uint32_t block_id, bool ack)
int(* data_len_read)(struct target *target, uint32_t *block_id, uint32_t *len)
int(* leave_trace_crit_section_start)(struct target *target)
uint32_t(* max_block_size_get)(struct target *target)
int(* ctrl_reg_write)(struct target *target, uint32_t block_id, uint32_t len, bool conn, bool data)
int(* status_reg_read)(struct target *target, uint32_t *stat)
int(* buffs_write)(struct target *target, uint32_t bufs_num, uint32_t buf_sz[], const uint8_t *bufs[], uint32_t block_id, bool ack, bool data)
const struct esp32_apptrace_hw * hw
struct esp_xtensa_apptrace_info apptrace
Definition: esp_xtensa.h:21
Definition: list.h:40
struct target * target
Definition: target.h:214
Definition: target.h:116
int smp
Definition: target.h:187
enum target_debug_reason debug_reason
Definition: target.h:154
enum target_state state
Definition: target.h:157
struct list_head * smp_targets
Definition: target.h:188
void * arch_info
Definition: target.h:164
char * cmd_name
Definition: target.h:118
Definition: psoc6.c:84
Represents a generic Xtensa core.
Definition: xtensa.h:241
unsigned int common_magic
Definition: xtensa.h:242
int target_halt(struct target *target)
Definition: target.c:507
int target_unregister_timer_callback(int(*callback)(void *priv), void *priv)
Definition: target.c:1748
int target_call_timer_callbacks(void)
Definition: target.c:1878
int target_poll(struct target *target)
Definition: target.c:477
int target_register_timer_callback(int(*callback)(void *priv), unsigned int time_ms, enum target_timer_type type, void *priv)
The period is very approximate, the callback can happen much more often or much more rarely than spec...
Definition: target.c:1658
uint16_t target_buffer_get_u16(struct target *target, const uint8_t *buffer)
Definition: target.c:334
int target_wait_state(struct target *target, enum target_state state, unsigned int ms)
Definition: target.c:3207
struct target * get_current_target(struct command_context *cmd_ctx)
Definition: target.c:458
int target_resume(struct target *target, int current, target_addr_t address, int handle_breakpoints, int debug_execution)
Make the target (re)start executing using its saved execution context (possibly with some modificatio...
Definition: target.c:556
target_debug_reason
Definition: target.h:68
@ DBG_REASON_UNDEFINED
Definition: target.h:77
@ DBG_REASON_BREAKPOINT
Definition: target.h:70
static bool target_was_examined(const struct target *target)
Definition: target.h:436
@ TARGET_TIMER_TYPE_PERIODIC
Definition: target.h:327
static const char * target_name(const struct target *target)
Returns the instance-specific name of the specified target.
Definition: target.h:233
target_state
Definition: target.h:53
@ TARGET_HALTED
Definition: target.h:56
@ TARGET_RUNNING
Definition: target.h:55
float duration_elapsed(const struct duration *duration)
Definition: time_support.c:83
int duration_measure(struct duration *duration)
Update the duration->elapsed field to finish the duration measurement.
Definition: time_support.c:74
int duration_start(struct duration *duration)
Update the duration->start field to start the duration measurement.
Definition: time_support.c:69
float duration_kbps(const struct duration *duration, size_t count)
Definition: time_support.c:90
int64_t timeval_ms(void)
#define ARRAY_SIZE(x)
Compute the number of elements of a variable length array.
Definition: types.h:57
#define NULL
Definition: usb.h:16
uint8_t cmd
Definition: vdebug.c:1
#define XTENSA_COMMON_MAGIC
Definition: xtensa.h:236