This is an automated email from Gerrit.

"Erhan Kurubas <erhan.kuru...@espressif.com>" just uploaded a new patch set to 
Gerrit, which you can find at https://review.openocd.org/c/openocd/+/7606

-- gerrit

commit 22269a1aefbbf809ca9793e0b59ea839c7b580d4
Author: Erhan Kurubas <erhan.kuru...@espressif.com>
Date:   Fri Apr 14 00:07:18 2023 +0200

    target/espressif: add system level tracing feature
    
    Produces traces compatible with SEGGER SystemView tool.
    
    Signed-off-by: Erhan Kurubas <erhan.kuru...@espressif.com>
    Change-Id: If1057309edbb91ed2cf1ebf9137c378d3deb9b88

diff --git a/doc/openocd.texi b/doc/openocd.texi
index 4154e56b54..684c6e8256 100644
--- a/doc/openocd.texi
+++ b/doc/openocd.texi
@@ -11177,6 +11177,40 @@ w/o OpenOCD command and keeps only the latest data 
window which fit into the buf
 Data will be stored to specified destination.
 @end deffn
 
+@deffn {Command} {esp sysview} (start file://<outfile1> [file://<outfile2>] 
[<poll_period> [<trace_size> [<stop_tmo> [<wait4halt> [<skip_size>]]]]])
+Starts @uref{https://www.segger.com/products/development-tools/systemview/, 
SEGGER SystemView}
+compatible tracing. Data will be stored to specified destination.
+For dual-core chips traces from every core will be saved to separate files.
+Resulting files can be open in "SEGGER SystemView" application.
+@url{https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/app_trace.html#openocd-systemview-tracing-command-options}
+The meaning of the arguments is identical to @command{esp apptrace start}.
+@end deffn
+
+@deffn {Command} {esp sysview} (stop)
+Stops SystremView compatible tracing started with above command.
+@url{https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/app_trace.html#openocd-systemview-tracing-command-options}
+@end deffn
+
+@deffn {Command} {esp sysview} (status)
+Requests ongoing SystremView compatible tracing status.
+@url{https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/app_trace.html#openocd-systemview-tracing-command-options}
+@end deffn
+
+@deffn {Command} {esp sysview_mcore} (start file://<outfile> [<poll_period> 
[<trace_size> [<stop_tmo> [<wait4halt> [<skip_size>]]]]])
+This command is identical to @command{esp sysview start}, but uses Espressif 
multi-core extension to
+@uref{https://www.segger.com/products/development-tools/systemview/, SEGGER 
SystemView} data format.
+Data will be stored to specified destination. Tracing data from all cores are 
saved in the same file.
+The meaning of the arguments is identical to @command{esp sysview start}.
+@end deffn
+
+@deffn {Command} {esp sysview_mcore} (stop)
+Stops Espressif multi-core SystremView tracing started with above command.
+@end deffn
+
+@deffn {Command} {esp sysview_mcore} (status)
+Requests ongoing Espressif multi-core SystremView tracing status.
+@end deffn
+
 @anchor{softwaredebugmessagesandtracing}
 @section Software Debug Messages and Tracing
 @cindex Linux-ARM DCC support
diff --git a/src/target/espressif/Makefile.am b/src/target/espressif/Makefile.am
index c1759ed77f..98731d14ad 100644
--- a/src/target/espressif/Makefile.am
+++ b/src/target/espressif/Makefile.am
@@ -15,5 +15,7 @@ noinst_LTLIBRARIES += %D%/libespressif.la
        %D%/esp32.c \
        %D%/esp32s2.c \
        %D%/esp32s3.c \
+       %D%/esp32_sysview.c \
+       %D%/esp32_sysview.h \
        %D%/esp_semihosting.c \
        %D%/esp_semihosting.h
diff --git a/src/target/espressif/esp32_apptrace.c 
b/src/target/espressif/esp32_apptrace.c
index dfeb794018..4daa7a15d1 100644
--- a/src/target/espressif/esp32_apptrace.c
+++ b/src/target/espressif/esp32_apptrace.c
@@ -32,6 +32,7 @@
 #include "esp_xtensa_smp.h"
 #include "esp_xtensa_apptrace.h"
 #include "esp32_apptrace.h"
+#include "esp32_sysview.h"
 
 #define ESP32_APPTRACE_USER_BLOCK_CORE(_v_)     ((_v_) >> 15)
 #define ESP32_APPTRACE_USER_BLOCK_LEN(_v_)      ((_v_) & ~BIT(15))
@@ -82,6 +83,8 @@ static int esp32_apptrace_safe_halt_targets(struct 
esp32_apptrace_cmd_ctx *ctx,
 static struct esp32_apptrace_block *esp32_apptrace_free_block_get(struct 
esp32_apptrace_cmd_ctx *ctx);
 static int esp32_apptrace_handle_trace_block(struct esp32_apptrace_cmd_ctx 
*ctx,
        struct esp32_apptrace_block *block);
+static int esp32_sysview_start(struct esp32_apptrace_cmd_ctx *ctx);
+static int esp32_sysview_stop(struct esp32_apptrace_cmd_ctx *ctx);
 
 static const bool s_time_stats_enable = true;
 
@@ -1219,6 +1222,11 @@ static int esp32_apptrace_poll(void *priv)
        return ERROR_OK;
 }
 
+static inline bool is_sysview_mode(int mode)
+{
+       return mode == ESP_APPTRACE_CMD_MODE_SYSVIEW || mode == 
ESP_APPTRACE_CMD_MODE_SYSVIEW_MCORE;
+}
+
 static void esp32_apptrace_cmd_stop(struct esp32_apptrace_cmd_ctx *ctx)
 {
        if (duration_measure(&ctx->read_time) != 0)
@@ -1226,7 +1234,12 @@ static void esp32_apptrace_cmd_stop(struct 
esp32_apptrace_cmd_ctx *ctx)
        int res = target_unregister_timer_callback(esp32_apptrace_poll, ctx);
        if (res != ERROR_OK)
                LOG_ERROR("Failed to unregister target timer handler (%d)!", 
res);
-
+       if (is_sysview_mode(ctx->mode)) {
+               /* stop tracing */
+               res = esp32_sysview_stop(ctx);
+               if (res != ERROR_OK)
+                       LOG_ERROR("SEGGER: Failed to stop tracing!");
+       }
        /* data processor is alive, so wait for all received blocks to be 
processed */
        res = esp32_apptrace_wait_tracing_finished(ctx);
        if (res != ERROR_OK)
@@ -1240,6 +1253,203 @@ static void esp32_apptrace_cmd_stop(struct 
esp32_apptrace_cmd_ctx *ctx)
                LOG_ERROR("Failed to cleanup cmd ctx (%d)!", res);
 }
 
+/* this function must be called after connecting to targets */
+static int esp32_sysview_start(struct esp32_apptrace_cmd_ctx *ctx)
+{
+       uint8_t cmds[] = { SEGGER_SYSVIEW_COMMAND_ID_START };
+       uint32_t fired_target_num = 0;
+       struct esp32_apptrace_target_state 
target_state[ESP32_APPTRACE_MAX_CORES_NUM];
+       struct esp32_sysview_cmd_data *cmd_data = (struct 
esp32_sysview_cmd_data *)ctx->cmd_priv;
+
+       /* get current block id */
+       int res = esp32_apptrace_get_data_info(ctx, target_state, 
&fired_target_num);
+       if (res != ERROR_OK) {
+               LOG_ERROR("SEGGER: Failed to read target data info!");
+               return res;
+       }
+       if (fired_target_num == UINT32_MAX) {
+               /* it can happen that there is no pending target data, but 
block was switched
+                * in this case block_ids on both CPUs are equal, so select the 
first one */
+               fired_target_num = 0;
+       }
+       /* start tracing */
+       res =
+               esp_apptrace_usr_block_write(ctx->hw,
+               ctx->cpus[fired_target_num],
+               target_state[fired_target_num].block_id,
+               cmds,
+               sizeof(cmds));
+       if (res != ERROR_OK) {
+               LOG_ERROR("SEGGER: Failed to start tracing!");
+               return res;
+       }
+       cmd_data->sv_trace_running = 1;
+       return res;
+}
+
+static int esp32_sysview_stop(struct esp32_apptrace_cmd_ctx *ctx)
+{
+       uint32_t old_block_id, fired_target_num = 0, empty_target_num = 0;
+       struct esp32_apptrace_target_state 
target_state[ESP32_APPTRACE_MAX_CORES_NUM];
+       struct esp32_sysview_cmd_data *cmd_data = (struct 
esp32_sysview_cmd_data *)ctx->cmd_priv;
+       uint8_t cmds[] = { SEGGER_SYSVIEW_COMMAND_ID_STOP };
+       struct duration wait_time;
+
+       struct esp32_apptrace_block *block = esp32_apptrace_free_block_get(ctx);
+       if (!block) {
+               LOG_ERROR("Failed to get free block for data on (%s)!", 
target_name(ctx->cpus[fired_target_num]));
+               return ERROR_FAIL;
+       }
+
+       /* halt all CPUs (not only one), otherwise it can happen that there is 
no target data and
+        * while we are queueing commands another CPU switches tracing block */
+       int res = esp32_apptrace_safe_halt_targets(ctx, target_state);
+       if (res != ERROR_OK) {
+               LOG_ERROR("SEGGER: Failed to halt targets (%d)!", res);
+               return res;
+       }
+       /* it can happen that there is no pending target data
+        * in this case block_ids on both CPUs are equal, so the first one will 
be selected */
+       for (unsigned int k = 0; k < ctx->cores_num; k++) {
+               if (target_state[k].data_len) {
+                       fired_target_num = k;
+                       break;
+               }
+       }
+       if (target_state[fired_target_num].data_len) {
+               /* read pending data without ack, they will be acked when stop 
command is queued */
+               res =
+                       ctx->hw->data_read(ctx->cpus[fired_target_num],
+                       target_state[fired_target_num].data_len,
+                       block->data,
+                       target_state[fired_target_num].block_id,
+                       0 /*no ack target data*/);
+               if (res != ERROR_OK) {
+                       LOG_ERROR("SEGGER: Failed to read data on (%s)!", 
target_name(ctx->cpus[fired_target_num]));
+                       return res;
+               }
+               /* process data */
+               block->data_len = target_state[fired_target_num].data_len;
+               res = esp32_apptrace_handle_trace_block(ctx, block);
+               if (res != ERROR_OK) {
+                       LOG_ERROR("Failed to process trace block %" PRId32 " 
bytes!", block->data_len);
+                       return res;
+               }
+       }
+       /* stop tracing and ack target data */
+       res =
+               esp_apptrace_usr_block_write(ctx->hw,
+               ctx->cpus[fired_target_num],
+               target_state[fired_target_num].block_id,
+               cmds,
+               sizeof(cmds));
+       if (res != ERROR_OK) {
+               LOG_ERROR("SEGGER: Failed to stop tracing!");
+               return res;
+       }
+       if (ctx->cores_num > 1) {
+               empty_target_num = fired_target_num ? 0 : 1;
+               /* ack target data on another CPU */
+               res =
+                       ctx->hw->ctrl_reg_write(ctx->cpus[empty_target_num],
+                       target_state[fired_target_num].block_id,
+                       0 /*target data ack*/,
+                       true /*host connected*/,
+                       false /*no host data*/);
+               if (res != ERROR_OK) {
+                       LOG_ERROR("SEGGER: Failed to ack data on target '%s' 
(%d)!",
+                               target_name(ctx->cpus[empty_target_num]), res);
+                       return res;
+               }
+       }
+       /* resume targets to allow command processing */
+       LOG_INFO("Resume targets");
+       bool smp_resumed = false;
+       for (unsigned int k = 0; k < ctx->cores_num; k++) {
+               if (smp_resumed && ctx->cpus[k]->smp) {
+                       /* in SMP mode we need to call target_resume for one 
core only */
+                       continue;
+               }
+               res = target_resume(ctx->cpus[k], 1, 0, 1, 0);
+               if (res != ERROR_OK) {
+                       LOG_ERROR("SEGGER: Failed to resume target '%s' (%d)!", 
target_name(ctx->cpus[k]), res);
+                       return res;
+               }
+               if (ctx->cpus[k]->smp)
+                       smp_resumed = true;
+       }
+       /* wait for block switch (command sent), so we can disconnect from 
targets */
+       old_block_id = target_state[fired_target_num].block_id;
+       if (duration_start(&wait_time) != 0) {
+               LOG_ERROR("Failed to start trace stop timeout measurement!");
+               return ERROR_FAIL;
+       }
+       /* we are waiting for the last data from tracing block and also there 
can be data in the pended
+        * data buffer */
+       /* so we are expecting two TRX block switches at most or stopping due 
to timeout */
+       while (cmd_data->sv_trace_running) {
+               res = esp32_apptrace_get_data_info(ctx, target_state, 
&fired_target_num);
+               if (res != ERROR_OK) {
+                       LOG_ERROR("SEGGER: Failed to read targets data info!");
+                       return res;
+               }
+               if (fired_target_num == UINT32_MAX) {
+                       /* it can happen that there is no pending (last) target 
data, but block was
+                        * switched */
+                       /* in this case block_ids on both CPUs are equal, so 
select the first one */
+                       fired_target_num = 0;
+               }
+               if (target_state[fired_target_num].block_id != old_block_id) {
+                       if (target_state[fired_target_num].data_len) {
+                               /* read last data and ack them */
+                               res = 
ctx->hw->data_read(ctx->cpus[fired_target_num],
+                                       target_state[fired_target_num].data_len,
+                                       block->data,
+                                       target_state[fired_target_num].block_id,
+                                       1 /*ack target data*/);
+                               if (res != ERROR_OK) {
+                                       LOG_ERROR("SEGGER: Failed to read last 
data on (%s)!",
+                                               
target_name(ctx->cpus[fired_target_num]));
+                               } else {
+                                       if (ctx->cores_num > 1) {
+                                               /* ack target data on another 
CPU */
+                                               empty_target_num = 
fired_target_num ? 0 : 1;
+                                               res = 
ctx->hw->ctrl_reg_write(ctx->cpus[empty_target_num],
+                                                               
target_state[fired_target_num].block_id,
+                                                               0 /*all read*/,
+                                                               true /*host 
connected*/,
+                                                               false /*no host 
data*/);
+                                               if (res != ERROR_OK) {
+                                                       LOG_ERROR("SEGGER: 
Failed to ack data on target '%s' (%d)!",
+                                                               
target_name(ctx->cpus[empty_target_num]), res);
+                                                       return res;
+                                               }
+                                       }
+                                       /* process data */
+                                       block->data_len = 
target_state[fired_target_num].data_len;
+                                       res = 
esp32_apptrace_handle_trace_block(ctx, block);
+                                       if (res != ERROR_OK) {
+                                               LOG_ERROR("Failed to process 
trace block %" PRId32 " bytes!",
+                                                       block->data_len);
+                                               return res;
+                                       }
+                               }
+                               old_block_id = 
target_state[fired_target_num].block_id;
+                       }
+               }
+               if (duration_measure(&wait_time) != 0) {
+                       LOG_ERROR("Failed to start trace stop timeout 
measurement!");
+                       return ERROR_FAIL;
+               }
+               const float stop_tmo = LOG_LEVEL_IS(LOG_LVL_DEBUG) ? 30.0 : 0.5;
+               if (duration_elapsed(&wait_time) >= stop_tmo) {
+                       LOG_INFO("Stop waiting for the last data due to 
timeout.");
+                       break;
+               }
+       }
+       return res;
+}
+
 int esp32_cmd_apptrace_generic(struct command_invocation *cmd, int mode, const 
char **argv, int argc)
 {
        static struct esp32_apptrace_cmd_ctx s_at_cmd_ctx;
@@ -1268,17 +1478,39 @@ int esp32_cmd_apptrace_generic(struct 
command_invocation *cmd, int mode, const c
        old_state = target->state;
 
        if (strcmp(argv[0], "start") == 0) {
-               res = esp32_apptrace_cmd_init(&s_at_cmd_ctx,
-                       cmd,
-                       mode,
-                       &argv[1],
-                       argc - 1);
-               if (res != ERROR_OK) {
-                       command_print(cmd, "Failed to init cmd ctx (%d)!", res);
-                       return res;
+               if (is_sysview_mode(mode)) {
+                       /* init cmd context */
+                       res = esp32_sysview_cmd_init(&s_at_cmd_ctx,
+                               cmd,
+                               mode,
+                               mode == ESP_APPTRACE_CMD_MODE_SYSVIEW_MCORE,
+                               &argv[1],
+                               argc - 1);
+                       if (res != ERROR_OK) {
+                               command_print(cmd, "Failed to init cmd ctx 
(%d)!", res);
+                               return res;
+                       }
+                       cmd_data = s_at_cmd_ctx.cmd_priv;
+                       if (cmd_data->skip_len != 0) {
+                               s_at_cmd_ctx.running = 0;
+                               esp32_sysview_cmd_cleanup(&s_at_cmd_ctx);
+                               command_print(cmd, "Data skipping not 
supported!");
+                               return ERROR_FAIL;
+                       }
+                       s_at_cmd_ctx.process_data = esp32_sysview_process_data;
+               } else {
+                       res = esp32_apptrace_cmd_init(&s_at_cmd_ctx,
+                               cmd,
+                               mode,
+                               &argv[1],
+                               argc - 1);
+                       if (res != ERROR_OK) {
+                               command_print(cmd, "Failed to init cmd ctx 
(%d)!", res);
+                               return res;
+                       }
+                       cmd_data = s_at_cmd_ctx.cmd_priv;
+                       s_at_cmd_ctx.process_data = esp32_apptrace_process_data;
                }
-               cmd_data = s_at_cmd_ctx.cmd_priv;
-               s_at_cmd_ctx.process_data = esp32_apptrace_process_data;
                s_at_cmd_ctx.auto_clean = esp32_apptrace_cmd_stop;
                if (cmd_data->wait4halt) {
                        res = esp32_apptrace_wait4halt(&s_at_cmd_ctx, target);
@@ -1292,6 +1524,17 @@ int esp32_cmd_apptrace_generic(struct command_invocation 
*cmd, int mode, const c
                        command_print(cmd, "Failed to connect to targets 
(%d)!", res);
                        goto _on_start_error;
                }
+               if (is_sysview_mode(mode)) {
+                       /* start tracing */
+                       res = esp32_sysview_start(&s_at_cmd_ctx);
+                       if (res != ERROR_OK) {
+                               esp32_apptrace_connect_targets(&s_at_cmd_ctx, 
false, old_state == TARGET_RUNNING);
+                               s_at_cmd_ctx.running = 0;
+                               esp32_apptrace_cmd_cleanup(&s_at_cmd_ctx);
+                               command_print(cmd, "SEGGER: Failed to start 
tracing!");
+                               return res;
+                       }
+               }
                res = target_register_timer_callback(esp32_apptrace_poll,
                        cmd_data->poll_period,
                        TARGET_TIMER_TYPE_PERIODIC,
@@ -1313,6 +1556,10 @@ int esp32_cmd_apptrace_generic(struct command_invocation 
*cmd, int mode, const c
                esp32_apptrace_print_stats(&s_at_cmd_ctx);
                return ERROR_OK;
        } else if (strcmp(argv[0], "dump") == 0) {
+               if (is_sysview_mode(mode)) {
+                       command_print(cmd, "Not supported!");
+                       return ERROR_FAIL;
+               }
                /* [dump outfile] - post-mortem dump without connection to 
targets */
                res = esp32_apptrace_cmd_init(&s_at_cmd_ctx,
                        cmd,
@@ -1353,7 +1600,10 @@ int esp32_cmd_apptrace_generic(struct command_invocation 
*cmd, int mode, const c
 
 _on_start_error:
        s_at_cmd_ctx.running = 0;
-       esp32_apptrace_cmd_cleanup(&s_at_cmd_ctx);
+       if (is_sysview_mode(mode))
+               esp32_sysview_cmd_cleanup(&s_at_cmd_ctx);
+       else
+               esp32_apptrace_cmd_cleanup(&s_at_cmd_ctx);
        return res;
 }
 
@@ -1362,6 +1612,16 @@ COMMAND_HANDLER(esp32_cmd_apptrace)
        return esp32_cmd_apptrace_generic(CMD, ESP_APPTRACE_CMD_MODE_GEN, 
CMD_ARGV, CMD_ARGC);
 }
 
+COMMAND_HANDLER(esp32_cmd_sysview)
+{
+       return esp32_cmd_apptrace_generic(CMD, ESP_APPTRACE_CMD_MODE_SYSVIEW, 
CMD_ARGV, CMD_ARGC);
+}
+
+COMMAND_HANDLER(esp32_cmd_sysview_mcore)
+{
+       return esp32_cmd_apptrace_generic(CMD, 
ESP_APPTRACE_CMD_MODE_SYSVIEW_MCORE, CMD_ARGV, CMD_ARGC);
+}
+
 const struct command_registration esp32_apptrace_command_handlers[] = {
        {
                .name = "apptrace",
@@ -1372,5 +1632,23 @@ const struct command_registration 
esp32_apptrace_command_handlers[] = {
                .usage =
                        "[start <destination> [poll_period [trace_size 
[stop_tmo [wait4halt [skip_size]]]]] | [stop] | [status] | [dump 
<destination>]",
        },
+       {
+               .name = "sysview",
+               .handler = esp32_cmd_sysview,
+               .mode = COMMAND_EXEC,
+               .help =
+                       "App Tracing: SEGGER SystemView compatible trace 
control. Starts, stops or queries tracing process status.",
+               .usage =
+                       "[start file://<outfile1> [file://<outfile2>] 
[poll_period [trace_size [stop_tmo [wait4halt [skip_size]]]]] | [stop] | 
[status]",
+       },
+       {
+               .name = "sysview_mcore",
+               .handler = esp32_cmd_sysview_mcore,
+               .mode = COMMAND_EXEC,
+               .help =
+                       "App Tracing: Espressif multi-core SystemView trace 
control. Starts, stops or queries tracing process status.",
+               .usage =
+                       "[start file://<outfile> [poll_period [trace_size 
[stop_tmo [wait4halt [skip_size]]]]] | [stop] | [status]",
+       },
        COMMAND_REGISTRATION_DONE
 };
diff --git a/src/target/espressif/esp32_sysview.c 
b/src/target/espressif/esp32_sysview.c
new file mode 100644
index 0000000000..5286d4c04a
--- /dev/null
+++ b/src/target/espressif/esp32_sysview.c
@@ -0,0 +1,583 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+/***************************************************************************
+ *   ESP32 sysview tracing module                                          *
+ *   Copyright (C) 2020 Espressif Systems Ltd.                             *
+ ***************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <helper/log.h>
+#include "esp32_apptrace.h"
+#include "esp32_sysview.h"
+
+/* in SystemView mode core ID is passed in event ID field */
+#define ESP32_SYSVIEW_USER_BLOCK_CORE(_v_)  (0)        /* not used */
+#define ESP32_SYSVIEW_USER_BLOCK_LEN(_v_)   (_v_)
+#define ESP32_SYSVIEW_USER_BLOCK_HDR_SZ     2
+
+/* grabbed from SystemView target sources */
+#define   SYSVIEW_EVTID_NOP                 0  /* Dummy packet. */
+#define   SYSVIEW_EVTID_OVERFLOW            1
+#define   SYSVIEW_EVTID_ISR_ENTER           2
+#define   SYSVIEW_EVTID_ISR_EXIT            3
+#define   SYSVIEW_EVTID_TASK_START_EXEC     4
+#define   SYSVIEW_EVTID_TASK_STOP_EXEC      5
+#define   SYSVIEW_EVTID_TASK_START_READY    6
+#define   SYSVIEW_EVTID_TASK_STOP_READY     7
+#define   SYSVIEW_EVTID_TASK_CREATE         8
+#define   SYSVIEW_EVTID_TASK_INFO           9
+#define   SYSVIEW_EVTID_TRACE_START         10
+#define   SYSVIEW_EVTID_TRACE_STOP          11
+#define   SYSVIEW_EVTID_SYSTIME_CYCLES      12
+#define   SYSVIEW_EVTID_SYSTIME_US          13
+#define   SYSVIEW_EVTID_SYSDESC             14
+#define   SYSVIEW_EVTID_USER_START          15
+#define   SYSVIEW_EVTID_USER_STOP           16
+#define   SYSVIEW_EVTID_IDLE                17
+#define   SYSVIEW_EVTID_ISR_TO_SCHEDULER    18
+#define   SYSVIEW_EVTID_TIMER_ENTER         19
+#define   SYSVIEW_EVTID_TIMER_EXIT          20
+#define   SYSVIEW_EVTID_STACK_INFO          21
+#define   SYSVIEW_EVTID_MODULEDESC          22
+
+#define   SYSVIEW_EVTID_INIT                24
+#define   SYSVIEW_EVTID_NAME_RESOURCE       25
+#define   SYSVIEW_EVTID_PRINT_FORMATTED     26
+#define   SYSVIEW_EVTID_NUMMODULES          27
+
+#define   SYSVIEW_SYNC_LEN                  10
+
+#define   SYSVIEW_EVENT_ID_MAX             (200)
+
+struct esp_sysview_target2host_hdr {
+       uint8_t block_sz;
+       uint8_t wr_sz;
+};
+#define SYSVIEW_BLOCK_SIZE_OFFSET       0
+#define SYSVIEW_WR_SIZE_OFFSET          1
+
+static int esp_sysview_trace_header_write(struct esp32_apptrace_cmd_ctx *ctx, 
bool mcore_format);
+static int esp32_sysview_core_id_get(struct target *target, uint8_t *hdr_buf);
+static uint32_t esp32_sysview_usr_block_len_get(struct target *target, uint8_t 
*hdr_buf, uint32_t *wr_len);
+
+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)
+{
+       struct esp32_sysview_cmd_data *cmd_data;
+
+       if (argc < 1) {
+               command_print(cmd, "Not enough args! Need trace data 
destination!");
+               return ERROR_FAIL;
+       }
+
+       int res = esp32_apptrace_cmd_ctx_init(cmd_ctx, cmd, mode);
+       if (res != ERROR_OK)
+               return res;
+
+       int core_num = cmd_ctx->cores_num;
+
+       if (!mcore_format && argc < core_num) {
+               command_print(cmd, "Not enough args! Need %d trace data 
destinations!", core_num);
+               res = ERROR_FAIL;
+               goto on_error;
+       }
+
+       cmd_data = calloc(1, sizeof(*cmd_data));
+       assert(cmd_data && "No memory for command data!");
+       cmd_ctx->cmd_priv = cmd_data;
+       cmd_data->mcore_format = mcore_format;
+
+       /*outfile1 [outfile2] [poll_period [trace_size [stop_tmo [wait4halt 
[skip_size]]]]] */
+       int dests_num = esp32_apptrace_dest_init(cmd_data->data_dests, argv, 
!mcore_format ? core_num : 1);
+       if (!mcore_format && dests_num < core_num) {
+               command_print(cmd, "Not enough args! Need %d trace data 
destinations!", core_num);
+               free(cmd_data);
+               res = ERROR_FAIL;
+               goto on_error;
+       }
+       cmd_data->apptrace.max_len = UINT32_MAX;
+       cmd_data->apptrace.poll_period = 0 /*ms*/;
+       cmd_ctx->stop_tmo = -1.0;       /* infinite */
+       if (argc > dests_num) {
+               /* parse remaining args */
+               esp32_apptrace_cmd_args_parse(cmd_ctx,
+                       &cmd_data->apptrace,
+                       &argv[dests_num],
+                       argc - dests_num);
+       }
+       LOG_USER("App trace params: from %d cores, size %u bytes, stop_tmo %g 
s, "
+               "poll period %u ms, wait_rst %d, skip %u bytes",
+               cmd_ctx->cores_num,
+               cmd_data->apptrace.max_len,
+               cmd_ctx->stop_tmo,
+               cmd_data->apptrace.poll_period,
+               cmd_data->apptrace.wait4halt,
+               cmd_data->apptrace.skip_len);
+
+       cmd_ctx->trace_format.hdr_sz = ESP32_SYSVIEW_USER_BLOCK_HDR_SZ;
+       cmd_ctx->trace_format.core_id_get = esp32_sysview_core_id_get;
+       cmd_ctx->trace_format.usr_block_len_get = 
esp32_sysview_usr_block_len_get;
+
+       res = esp_sysview_trace_header_write(cmd_ctx, mcore_format);
+       if (res != ERROR_OK) {
+               command_print(cmd, "Failed to write trace header (%d)!", res);
+               esp32_apptrace_dest_cleanup(cmd_data->data_dests, core_num);
+               free(cmd_data);
+               return res;
+       }
+       return ERROR_OK;
+on_error:
+       cmd_ctx->running = 0;
+       esp32_apptrace_cmd_ctx_cleanup(cmd_ctx);
+       return res;
+}
+
+int esp32_sysview_cmd_cleanup(struct esp32_apptrace_cmd_ctx *cmd_ctx)
+{
+       struct esp32_sysview_cmd_data *cmd_data = cmd_ctx->cmd_priv;
+
+       esp32_apptrace_dest_cleanup(cmd_data->data_dests, cmd_ctx->cores_num);
+       free(cmd_data);
+       cmd_ctx->cmd_priv = NULL;
+       esp32_apptrace_cmd_ctx_cleanup(cmd_ctx);
+       return ERROR_OK;
+}
+
+static int esp32_sysview_core_id_get(struct target *target, uint8_t *hdr_buf)
+{
+       /* for sysview compressed apptrace header is used, so core id is 
encoded in sysview packet */
+       return 0;
+}
+
+static uint32_t esp32_sysview_usr_block_len_get(struct target *target, uint8_t 
*hdr_buf, uint32_t *wr_len)
+{
+       *wr_len = ESP32_SYSVIEW_USER_BLOCK_LEN(hdr_buf[SYSVIEW_WR_SIZE_OFFSET]);
+       return ESP32_SYSVIEW_USER_BLOCK_LEN(hdr_buf[SYSVIEW_BLOCK_SIZE_OFFSET]);
+}
+
+static int esp_sysview_trace_header_write(struct esp32_apptrace_cmd_ctx *ctx, 
bool mcore_format)
+{
+       struct esp32_sysview_cmd_data *cmd_data = ctx->cmd_priv;
+       char *hdr_str;
+       int dests_num;
+
+       if (!mcore_format) {
+               hdr_str = ";\n"
+                       "; Version     SEGGER SystemViewer V2.42\n"
+                       "; Author      Espressif Inc\n"
+                       ";\n";
+               dests_num = ctx->cores_num;
+       } else {
+               hdr_str = ";\n"
+                       "; Version     SEGGER SystemViewer V2.42\n"
+                       "; Author      Espressif Inc\n"
+                       "; ESP_Extension\n"
+                       ";\n";
+               dests_num = 1;
+       }
+
+       int hdr_len = strlen(hdr_str);
+       for (int i = 0; i < dests_num; i++) {
+               int res = 
cmd_data->data_dests[i].write(cmd_data->data_dests[i].priv,
+                       (uint8_t *)hdr_str,
+                       hdr_len);
+               if (res != ERROR_OK) {
+                       LOG_ERROR("SEGGER: Failed to write %u bytes to dest 
%d!", hdr_len, i);
+                       return ERROR_FAIL;
+               }
+       }
+       return ERROR_OK;
+}
+
+static void sysview_encode_u32(uint8_t *dest, uint32_t val)
+{
+       uint8_t *sv_ptr = dest;
+       while (val > 0x7F) {
+               *sv_ptr++ = (uint8_t)(val | 0x80);
+               val >>= 7;
+       }
+       *sv_ptr++ = (uint8_t)val;
+       dest = sv_ptr;
+}
+
+static uint32_t esp_sysview_decode_u32(uint8_t **ptr)
+{
+       uint32_t val = 0;
+       for (int k = 0;; k++, (*ptr)++) {
+               if (**ptr & 0x80) {
+                       val |= (uint32_t)(**ptr & ~0x80) << 7 * k;
+               } else {
+                       val |= (uint32_t)**ptr << 7 * k;
+                       (*ptr)++;
+                       break;
+               }
+       }
+       return val;
+}
+
+static uint16_t esp_sysview_decode_plen(uint8_t **ptr)
+{
+       uint16_t payload_len = 0;
+       uint8_t *p = *ptr;
+       /* here pkt points to encoded payload length */
+       if (*p & 0x80) {
+               payload_len = *(p + 1); /* higher part */
+               payload_len = (payload_len << 7) | (*p & ~0x80);/* lower 7 bits 
*/
+               p += 2; /* payload len (2 bytes) */
+       } else {
+               payload_len = *p;
+               p++;    /* payload len (1 byte) */
+       }
+       *ptr = p;
+
+       return payload_len;
+}
+
+static uint16_t esp_sysview_get_predef_payload_len(uint16_t id, uint8_t *pkt)
+{
+       uint16_t len;
+       uint8_t *ptr = pkt;
+
+       switch (id) {
+       case SYSVIEW_EVTID_OVERFLOW:
+       case SYSVIEW_EVTID_ISR_ENTER:
+       case SYSVIEW_EVTID_TASK_START_EXEC:
+       case SYSVIEW_EVTID_TASK_START_READY:
+       case SYSVIEW_EVTID_TASK_CREATE:
+       case SYSVIEW_EVTID_SYSTIME_CYCLES:
+       case SYSVIEW_EVTID_USER_START:
+       case SYSVIEW_EVTID_USER_STOP:
+       case SYSVIEW_EVTID_TIMER_ENTER:
+               /*ENCODE_U32 */
+               esp_sysview_decode_u32(&ptr);
+               len = ptr - pkt;
+               break;
+       case SYSVIEW_EVTID_TASK_STOP_READY:
+       case SYSVIEW_EVTID_SYSTIME_US:
+               /*2*ENCODE_U32 */
+               esp_sysview_decode_u32(&ptr);
+               esp_sysview_decode_u32(&ptr);
+               len = ptr - pkt;
+               break;
+       case SYSVIEW_EVTID_SYSDESC:
+               /*str(128 + 1) */
+               len = *ptr + 1;
+               break;
+       case SYSVIEW_EVTID_TASK_INFO:
+       case SYSVIEW_EVTID_MODULEDESC:
+               /*2*ENCODE_U32 + str */
+               esp_sysview_decode_u32(&ptr);
+               esp_sysview_decode_u32(&ptr);
+               /* TODO: add support for strings longer then 255 bytes */
+               len = ptr - pkt + *ptr + 1;
+               break;
+       case SYSVIEW_EVTID_STACK_INFO:
+               /*4*ENCODE_U32 */
+               esp_sysview_decode_u32(&ptr);
+               esp_sysview_decode_u32(&ptr);
+               esp_sysview_decode_u32(&ptr);
+               esp_sysview_decode_u32(&ptr);
+               len = ptr - pkt;
+               break;
+       case SYSVIEW_EVTID_ISR_EXIT:
+       case SYSVIEW_EVTID_TASK_STOP_EXEC:
+       case SYSVIEW_EVTID_TRACE_START:
+       case SYSVIEW_EVTID_TRACE_STOP:
+       case SYSVIEW_EVTID_IDLE:
+       case SYSVIEW_EVTID_ISR_TO_SCHEDULER:
+       case SYSVIEW_EVTID_TIMER_EXIT:
+               len = 0;
+               break;
+
+       /*case SYSVIEW_EVTID_NOP: */
+       default:
+               LOG_ERROR("SEGGER: Unsupported predef event %d!", id);
+               len = 0;
+       }
+       return len;
+}
+
+static uint16_t esp_sysview_parse_packet(uint8_t *pkt_buf,
+       uint32_t *pkt_len,
+       unsigned int *pkt_core_id,
+       uint32_t *delta,
+       uint32_t *delta_len,
+       bool clear_core_bit)
+{
+       uint8_t *pkt = pkt_buf;
+       uint16_t event_id = 0, payload_len = 0;
+
+       *pkt_core_id = 0;
+       *pkt_len = 0;
+       /* 1-2 byte of message type, 0-2  byte of payload length, payload, 1-5 
bytes of timestamp. */
+       if (*pkt & 0x80) {
+               if (*(pkt + 1) & (1 << 6)) {
+                       if (clear_core_bit)
+                               *(pkt + 1) &= ~(1 << 6);        /* clear 
core_id bit */
+                       *pkt_core_id = 1;
+               }
+               event_id = *(pkt + 1) & ~(1 << 6);      /* higher part */
+               event_id = (event_id << 7) | (*pkt & ~0x80);    /* lower 7 bits 
*/
+               pkt += 2;       /* event_id (2 bytes) */
+               /* here pkt points to encoded payload length */
+               payload_len = esp_sysview_decode_plen(&pkt);
+       } else {
+               if (*pkt & (1 << 6)) {
+                       if (clear_core_bit)
+                               *pkt &= ~(1 << 6);      /* clear core_id bit */
+                       *pkt_core_id = 1;
+               }
+               /* event_id (1 byte) */
+               event_id = *pkt & ~(1 << 6);
+               pkt++;
+               if (event_id < 24)
+                       payload_len = 
esp_sysview_get_predef_payload_len(event_id, pkt);
+               else
+                       payload_len = esp_sysview_decode_plen(&pkt);
+       }
+       pkt += payload_len;
+       uint8_t *delta_start = pkt;
+       *delta = esp_sysview_decode_u32(&pkt);
+       *delta_len = pkt - delta_start;
+       *pkt_len = pkt - pkt_buf;
+       LOG_DEBUG("SEGGER: evt %d len %d plen %d dlen %d",
+               event_id,
+               *pkt_len,
+               payload_len,
+               *delta_len);
+       return event_id;
+}
+
+static int esp32_sysview_write_packet(struct esp32_sysview_cmd_data *cmd_data,
+       int pkt_core_id, uint32_t pkt_len, uint8_t *pkt_buf, uint32_t 
delta_len, uint8_t *delta_buf)
+{
+       if (!cmd_data->data_dests[pkt_core_id].write)
+               return ERROR_FAIL;
+
+       int res = 
cmd_data->data_dests[pkt_core_id].write(cmd_data->data_dests[pkt_core_id].priv, 
pkt_buf, pkt_len);
+
+       if (res != ERROR_OK) {
+               LOG_ERROR("SEGGER: Failed to write %u bytes to dest %d!", 
pkt_len, pkt_core_id);
+               return res;
+       }
+       if (delta_len) {
+               /* write packet with modified delta */
+               res = 
cmd_data->data_dests[pkt_core_id].write(cmd_data->data_dests[pkt_core_id].priv, 
delta_buf, delta_len);
+               if (res != ERROR_OK) {
+                       LOG_ERROR("SEGGER: Failed to write %u bytes of delta to 
dest %d!", delta_len, pkt_core_id);
+                       return res;
+               }
+       }
+       return ERROR_OK;
+}
+
+static int esp32_sysview_process_packet(struct esp32_apptrace_cmd_ctx *ctx,
+       unsigned int pkt_core_id, uint16_t event_id, uint32_t delta, uint32_t 
delta_len,
+       uint32_t pkt_len, uint8_t *pkt_buf)
+{
+       struct esp32_sysview_cmd_data *cmd_data = ctx->cmd_priv;
+       int pkt_core_changed = 0;
+       uint32_t new_delta_len = 0;
+       uint8_t new_delta_buf[10];
+       uint32_t wr_len = pkt_len;
+
+       if (ctx->cores_num > 1) {
+               if (cmd_data->sv_last_core_id == pkt_core_id) {
+                       /* if this packet is for the same core as the prev one 
acc delta and write packet unmodified */
+                       cmd_data->sv_acc_time_delta += delta;
+               } else {
+                       /* if this packet is for another core then prev one set 
acc delta to the packet's delta */
+                       uint8_t *delta_ptr = new_delta_buf;
+                       sysview_encode_u32(delta_ptr, delta + 
cmd_data->sv_acc_time_delta);
+                       cmd_data->sv_acc_time_delta = delta;
+                       wr_len -= delta_len;
+                       new_delta_len = delta_ptr - new_delta_buf;
+                       pkt_core_changed = 1;
+               }
+               cmd_data->sv_last_core_id = pkt_core_id;
+       }
+       if (pkt_core_id >= ctx->cores_num) {
+               LOG_WARNING("SEGGER: invalid core ID in packet %d, must be less 
then %d! Event id %d",
+                       pkt_core_id,
+                       ctx->cores_num,
+                       event_id);
+               return ERROR_FAIL;
+       }
+       int res = esp32_sysview_write_packet(cmd_data,
+               pkt_core_id,
+               wr_len,
+               pkt_buf,
+               new_delta_len,
+               new_delta_buf);
+       if (res != ERROR_OK)
+               return res;
+       for (unsigned int i = 0; i < ctx->cores_num; i++) {
+               if (pkt_core_id == i)
+                       continue;
+               switch (event_id) {
+               /* messages below should be sent to trace destinations for all 
cores */
+               case SYSVIEW_EVTID_TRACE_START:
+               case SYSVIEW_EVTID_TRACE_STOP:
+               case SYSVIEW_EVTID_SYSTIME_CYCLES:
+               case SYSVIEW_EVTID_SYSTIME_US:
+               case SYSVIEW_EVTID_SYSDESC:
+               case SYSVIEW_EVTID_TASK_INFO:
+               case SYSVIEW_EVTID_STACK_INFO:
+               case SYSVIEW_EVTID_MODULEDESC:
+               case SYSVIEW_EVTID_INIT:
+               case SYSVIEW_EVTID_NUMMODULES:
+               case SYSVIEW_EVTID_OVERFLOW:
+               case SYSVIEW_EVTID_TASK_START_READY:
+                       /* if packet's source core has changed */
+                       wr_len = pkt_len;
+                       if (pkt_core_changed) {
+                               /* clone packet with unmodified delta */
+                               new_delta_len = 0;
+                       } else {
+                               /* clone packet with modified delta */
+                               uint8_t *delta_ptr = new_delta_buf;
+                               sysview_encode_u32(delta_ptr, 
cmd_data->sv_acc_time_delta /*delta has been accumulated above*/);
+                               wr_len -= delta_len;
+                               new_delta_len = delta_ptr - new_delta_buf;
+                       }
+                       LOG_DEBUG("SEGGER: Redirect %d bytes of event %d to 
dest %d", wr_len, event_id, i);
+                       res = esp32_sysview_write_packet(cmd_data,
+                               i,
+                               wr_len,
+                               pkt_buf,
+                               new_delta_len,
+                               new_delta_buf);
+                       if (res != ERROR_OK)
+                               return res;
+                       /* messages above are cloned to trace files for both 
cores,
+                       * so reset acc time delta, both files have actual delta
+                       * info */
+                       cmd_data->sv_acc_time_delta = 0;
+                       break;
+               default:
+                       break;
+               }
+       }
+       return ERROR_OK;
+}
+
+int esp32_sysview_process_data(struct esp32_apptrace_cmd_ctx *ctx,
+       unsigned int core_id,
+       uint8_t *data,
+       uint32_t data_len)
+{
+       struct esp32_sysview_cmd_data *cmd_data = ctx->cmd_priv;
+
+       LOG_DEBUG("SEGGER: Read from target %d bytes [%x %x %x %x]",
+               data_len,
+               data[0],
+               data[1],
+               data[2],
+               data[3]);
+       int res;
+       uint32_t processed = 0;
+       if (core_id >= ctx->cores_num) {
+               LOG_ERROR("SEGGER: Invalid core id %d in user block!", core_id);
+               return ERROR_FAIL;
+       }
+       if (cmd_data->mcore_format)
+               core_id = 0;
+       if (ctx->tot_len == 0) {
+               /* handle sync seq */
+               if (data_len < SYSVIEW_SYNC_LEN) {
+                       LOG_ERROR("SEGGER: Invalid init seq len %d!", data_len);
+                       return ERROR_FAIL;
+               }
+               LOG_DEBUG("SEGGER: Process %d sync bytes", SYSVIEW_SYNC_LEN);
+               uint8_t sync_seq[SYSVIEW_SYNC_LEN] = { 0x0, 0x0, 0x0, 0x0, 0x0, 
0x0, 0x0, 0x0, 0x0, 0x0 };
+               if (memcmp(data, sync_seq, SYSVIEW_SYNC_LEN) != 0) {
+                       LOG_ERROR("SEGGER: Invalid init seq [%x %x %x %x %x %x 
%x %x %x %x]",
+                               data[0], data[1], data[2], data[3], data[4], 
data[5], data[6],
+                               data[7], data[8], data[9]);
+                       return ERROR_FAIL;
+               }
+               res = 
cmd_data->data_dests[core_id].write(cmd_data->data_dests[core_id].priv,
+                       data,
+                       SYSVIEW_SYNC_LEN);
+               if (res != ERROR_OK) {
+                       LOG_ERROR("SEGGER: Failed to write %u sync bytes to 
dest %d!",
+                               SYSVIEW_SYNC_LEN,
+                               core_id);
+                       return res;
+               }
+               if (!cmd_data->mcore_format) {
+                       for (unsigned int i = 0; i < ctx->cores_num; i++) {
+                               if (core_id == i)
+                                       continue;
+                               res =
+                                       
cmd_data->data_dests[i].write(cmd_data->data_dests[i].priv,
+                                       data,
+                                       SYSVIEW_SYNC_LEN);
+                               if (res != ERROR_OK) {
+                                       LOG_ERROR("SEGGER: Failed to write %u 
sync bytes to dest %d!", SYSVIEW_SYNC_LEN, core_id ? 0 : 1);
+                                       return res;
+                               }
+                       }
+               }
+               ctx->tot_len += SYSVIEW_SYNC_LEN;
+               processed += SYSVIEW_SYNC_LEN;
+       }
+       while (processed < data_len) {
+               unsigned int pkt_core_id;
+               uint32_t delta_len = 0;
+               uint32_t pkt_len = 0, delta = 0;
+               uint16_t event_id = esp_sysview_parse_packet(data + processed,
+                       &pkt_len,
+                       &pkt_core_id,
+                       &delta,
+                       &delta_len,
+                       !cmd_data->mcore_format);
+               LOG_DEBUG("SEGGER: Process packet: core %d, %d id, %d bytes [%x 
%x %x %x]",
+                       pkt_core_id,
+                       event_id,
+                       pkt_len,
+                       data[processed + 0],
+                       data[processed + 1],
+                       data[processed + 2],
+                       data[processed + 3]);
+               if (!cmd_data->mcore_format) {
+                       res = esp32_sysview_process_packet(ctx,
+                               pkt_core_id,
+                               event_id,
+                               delta,
+                               delta_len,
+                               pkt_len,
+                               data + processed);
+                       if (res != ERROR_OK)
+                               return res;
+               } else {
+                       res = 
cmd_data->data_dests[0].write(cmd_data->data_dests[0].priv, data + processed, 
pkt_len);
+                       if (res != ERROR_OK) {
+                               LOG_ERROR("SEGGER: Failed to write %u bytes to 
dest %d!", pkt_len, 0);
+                               return res;
+                       }
+               }
+               if (event_id == SYSVIEW_EVTID_TRACE_STOP)
+                       cmd_data->sv_trace_running = 0;
+               ctx->tot_len += pkt_len;
+               processed += pkt_len;
+       }
+       LOG_USER("%u ", ctx->tot_len);
+       /* check for stop condition */
+       if (ctx->tot_len > cmd_data->apptrace.skip_len &&
+               (ctx->tot_len - cmd_data->apptrace.skip_len >= 
cmd_data->apptrace.max_len)) {
+               ctx->running = 0;
+               if (duration_measure(&ctx->read_time) != 0) {
+                       LOG_ERROR("Failed to stop trace read time measure!");
+                       return ERROR_FAIL;
+               }
+       }
+       return ERROR_OK;
+}
diff --git a/src/target/espressif/esp32_sysview.h 
b/src/target/espressif/esp32_sysview.h
new file mode 100644
index 0000000000..da914ade4d
--- /dev/null
+++ b/src/target/espressif/esp32_sysview.h
@@ -0,0 +1,47 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+/***************************************************************************
+ *   ESP32 sysview tracing module                                          *
+ *   Copyright (C) 2020 Espressif Systems Ltd.                             *
+ ***************************************************************************/
+
+#ifndef OPENOCD_TARGET_ESP32_SYSVIEW_H
+#define OPENOCD_TARGET_ESP32_SYSVIEW_H
+
+typedef enum {
+       SEGGER_SYSVIEW_COMMAND_ID_START = 1,
+       SEGGER_SYSVIEW_COMMAND_ID_STOP,
+       SEGGER_SYSVIEW_COMMAND_ID_GET_SYSTIME,
+       SEGGER_SYSVIEW_COMMAND_ID_GET_TASKLIST,
+       SEGGER_SYSVIEW_COMMAND_ID_GET_SYSDESC,
+       SEGGER_SYSVIEW_COMMAND_ID_GET_NUMMODULES,
+       SEGGER_SYSVIEW_COMMAND_ID_GET_MODULEDESC,
+       /* Extended commands: Commands >= 128 have a second parameter */
+       SEGGER_SYSVIEW_COMMAND_ID_GET_MODULE = 128
+} SEGGER_SYSVIEW_COMMAND_ID;
+
+struct esp32_sysview_cmd_data {
+       /* Should be the first field. Generic apptrace command handling code 
accesses it */
+       struct esp32_apptrace_cmd_data apptrace;
+       struct esp32_apptrace_dest data_dests[ESP32_APPTRACE_MAX_CORES_NUM];
+       bool mcore_format;
+       uint32_t sv_acc_time_delta;
+       unsigned int sv_last_core_id;
+       int sv_trace_running;
+};
+
+struct esp32_apptrace_cmd_ctx;
+
+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);
+int esp32_sysview_cmd_cleanup(struct esp32_apptrace_cmd_ctx *cmd_ctx);
+int esp32_sysview_process_data(struct esp32_apptrace_cmd_ctx *ctx,
+       unsigned int core_id,
+       uint8_t *data,
+       uint32_t data_len);
+
+#endif /* OPENOCD_TARGET_ESP32_SYSVIEW_H */

-- 


Reply via email to