This is an automated email from Gerrit.

"liangzhen <[email protected]>" just uploaded a new patch set to Gerrit, 
which you can find at https://review.openocd.org/c/openocd/+/9213

-- gerrit

commit 38cf8f3e36dce575ee39d1070429c0a5f23179c1
Author: liangzhen <[email protected]>
Date:   Mon Oct 27 13:58:39 2025 +0800

    target: cstrace: Add coresight timestamp support
    
    Add support for the coresight timestamp component.
    
    Change-Id: Ib02ab2e1b146e0ecd16c38dad9a2dae7a4dea6f1
    Signed-off-by: liangzhen <[email protected]>

diff --git a/doc/openocd.texi b/doc/openocd.texi
index 1aec747d43..a0f2134c76 100644
--- a/doc/openocd.texi
+++ b/doc/openocd.texi
@@ -10333,6 +10333,7 @@ Lists all supported coresight component types. At this 
writing, the supported co
 @itemize
 @item @code{funnel} - this a coresight funnel component.
 @item @code{tmc} - this a coresight tmc component.
+@item @code{timestamp} - this a coresight timestamp component.
 @end itemize
 @end deffn
 
@@ -10410,6 +10411,14 @@ The commands specific to the @code{tmc} is:
 @item @command{component_name tmc dump} @var{filename} - dump trace data.
 @end itemize
 
+@subsection Timestamp Component
+When the coresight component is a @code{timestamp} type, the configure
+configparams specific to the @code{timestamp} are:
+@itemize
+@item @option{-halt-debug} @code{on|off} - set timestamp run or halt on debug.
+@item @option{-cntval} @emph{cntval} - set the current counter value.
+@end itemize
+
 @anchor{armcrosstrigger}
 @section ARM Cross-Trigger Interface
 @cindex CTI
diff --git a/src/target/Makefile.am b/src/target/Makefile.am
index 040c6223e2..976987b5b6 100644
--- a/src/target/Makefile.am
+++ b/src/target/Makefile.am
@@ -114,7 +114,8 @@ ARM_DEBUG_SRC = \
        %D%/arm_cti.c \
        %D%/coresight_trace.c \
        %D%/coresight_funnel.c \
-       %D%/coresight_tmc.c
+       %D%/coresight_tmc.c \
+       %D%/coresight_timestamp.c
 
 AVR32_SRC = \
        %D%/avr32_ap7k.c \
diff --git a/src/target/coresight_timestamp.c b/src/target/coresight_timestamp.c
new file mode 100644
index 0000000000..1ae6127562
--- /dev/null
+++ b/src/target/coresight_timestamp.c
@@ -0,0 +1,247 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+/***************************************************************************
+ *   Copyright (C) 2025 by liangzhen                                       *
+ *   [email protected]                                               *
+ ***************************************************************************/
+
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <helper/log.h>
+#include <helper/types.h>
+#include "helper/command.h"
+#include "helper/jim-nvp.h"
+#include "coresight_trace.h"
+
+#define CS_TIMESTAMP_CNTCR             0x000
+#define CS_TIMESTAMP_CNTSR             0x004
+#define CS_TIMESTAMP_CNTCVL            0x008
+#define CS_TIMESTAMP_CNTCVU            0x00c
+
+/* register description */
+/* CS_TIMESTAMP_CNTCR - 0x000 */
+#define CS_TIMESTAMP_CNTCR_EN          0x1
+#define CS_TIMESTAMP_CNTCR_HDBG                0x2
+
+/* CS_TIMESTAMP_CNTSR - 0x004 */
+#define CS_TIMESTAMP_CNTSR_DBGH        0x2
+
+struct cs_timestamp_private_config {
+       bool halt_debug;
+       uint64_t cntval;
+};
+
+static inline struct cs_timestamp_private_config
+*cs_timestamp_private_config(struct cstrace_component *comp)
+{
+       assert(comp->private_config);
+       return comp->private_config;
+}
+
+static struct cs_timestamp_private_config 
*alloc_default_cs_timestamp_private_config(void)
+{
+       struct cs_timestamp_private_config *config =  malloc(sizeof(struct 
cs_timestamp_private_config));
+       if (!config) {
+               LOG_ERROR("Out of memory!");
+               return NULL;
+       }
+
+       config->halt_debug = false;
+
+       return config;
+}
+
+#define CS_TIMESTAMP_CONFIG(F) struct cs_timestamp_private_config *F = 
cs_timestamp_private_config(comp);
+
+static const struct {
+       uint32_t offset;
+       const char *label;
+} timestamp_names[] = {
+       { CS_TIMESTAMP_CNTCR, "CNTCR" },
+       { CS_TIMESTAMP_CNTSR, "CNTSR" },
+       { CS_TIMESTAMP_CNTCVL, "CNTCVL" },
+       { CS_TIMESTAMP_CNTCVU, "CNTCVU" },
+};
+
+static int timestamp_find_reg_offset(const char *name)
+{
+       for (size_t i = 0; i < ARRAY_SIZE(timestamp_names); i++) {
+               if (!strcasecmp(name, timestamp_names[i].label))
+                       return timestamp_names[i].offset;
+       }
+
+       LOG_ERROR("unknown coresight timestamp register %s", name);
+       return -1;
+}
+
+static int timestamp_create(struct cstrace_component *comp)
+{
+       LOG_DEBUG("timestamp_create()");
+       struct cs_timestamp_private_config *config = comp->private_config;
+       if (!config) {
+               config = alloc_default_cs_timestamp_private_config();
+               if (!config)
+                       return ERROR_FAIL;
+               comp->private_config = config;
+       }
+       return ERROR_OK;
+}
+
+static struct jim_nvp nvp_halt_debug_opts[] = {
+       { .name = "off", .value = false },
+       { .name = "on", .value = true },
+       { .name = NULL, .value = -1 }
+};
+
+enum timestamp_cfg_opts {
+       CS_TIMESTAMP_CFG_HDBG,
+       CS_TIMESTAMP_CFG_CNTVAL
+};
+
+static struct jim_nvp nvp_config_opts[] = {
+       { .name = "-halt-debug", .value = CS_TIMESTAMP_CFG_HDBG },
+       { .name = "-cntval", .value = CS_TIMESTAMP_CFG_CNTVAL },
+       { .name = NULL, .value = -1 }
+};
+
+static int timestamp_jim_configure(struct cstrace_component *comp, struct 
jim_getopt_info *goi)
+{
+       struct cs_timestamp_private_config *config = comp->private_config;
+       if (!config) {
+               config = alloc_default_cs_timestamp_private_config();
+               if (!config)
+                       return JIM_ERR;
+               comp->private_config = config;
+       }
+
+       if (!goi->argc)
+               return JIM_OK;
+
+       struct jim_nvp *n;
+       int e = jim_nvp_name2value_obj(goi->interp, nvp_config_opts, 
goi->argv[0], &n);
+
+       if (e != JIM_OK)
+               return JIM_CONTINUE;
+
+       e = jim_getopt_obj(goi, NULL);
+       if (e != JIM_OK)
+               return e;
+
+       if (!goi->is_configure && goi->argc > 0) {
+               /*no arguments */
+               Jim_WrongNumArgs(goi->interp, 2, goi->argv - 2, "");
+               return JIM_ERR;
+       }
+
+       switch (n->value) {
+       case CS_TIMESTAMP_CFG_HDBG:
+               if (goi->is_configure) {
+                       struct jim_nvp *halt_debug_nvp;
+                       e = jim_getopt_nvp(goi, nvp_halt_debug_opts, 
&halt_debug_nvp);
+                       if (e != JIM_OK) {
+                               jim_getopt_nvp_unknown(goi, 
nvp_halt_debug_opts, /*hadprefix*/ true);
+                               return e;
+                       }
+                       config->halt_debug = halt_debug_nvp->value;
+               } else {
+                       Jim_SetResultString(goi->interp, 
jim_nvp_value2name_simple(nvp_halt_debug_opts, config->halt_debug)->name, -1);
+               }
+               break;
+       case CS_TIMESTAMP_CFG_CNTVAL:
+               if (goi->is_configure) {
+                       jim_wide w;
+                       e = jim_getopt_wide(goi, &w);
+                       if (e != JIM_OK)
+                               return e;
+                       config->cntval = (uint64_t)w;
+               } else {
+                       Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, 
config->cntval));
+               }
+               break;
+       }
+       return JIM_OK;
+}
+
+static int timestamp_enable(struct cstrace_component *comp)
+{
+       CS_TIMESTAMP_CONFIG(config);
+
+       if (coresight_write_reg(comp, CS_TIMESTAMP_CNTCVL, config->cntval & 
0xffffffff) != ERROR_OK)
+               return ERROR_FAIL;
+
+       if (coresight_write_reg(comp, CS_TIMESTAMP_CNTCVU, config->cntval >> 
32) != ERROR_OK)
+               return ERROR_FAIL;
+
+       uint32_t cntcr = CS_TIMESTAMP_CNTCR_EN;
+       cntcr = set_field(cntcr, CS_TIMESTAMP_CNTCR_HDBG, config->halt_debug);
+
+       return coresight_write_reg(comp, CS_TIMESTAMP_CNTCR, cntcr);
+}
+
+static int timestamp_disable(struct cstrace_component *comp)
+{
+       uint32_t cntcr;
+       if (coresight_read_reg(comp, CS_TIMESTAMP_CNTCR, &cntcr) != ERROR_OK)
+               return ERROR_FAIL;
+
+       cntcr = set_field(cntcr, CS_TIMESTAMP_CNTCR_EN, 0x0);
+
+       return coresight_write_reg(comp, CS_TIMESTAMP_CNTCR, cntcr);
+}
+
+static int timestamp_status(struct cstrace_component *comp, struct 
command_invocation *cmd)
+{
+       uint32_t cntcr, cntsr, cntcvl, cntcvu;
+
+       if (coresight_read_reg(comp, CS_TIMESTAMP_CNTCR, &cntcr) != ERROR_OK)
+               return ERROR_FAIL;
+
+       if (coresight_read_reg(comp, CS_TIMESTAMP_CNTSR, &cntsr) != ERROR_OK)
+               return ERROR_FAIL;
+
+       if (coresight_read_reg(comp, CS_TIMESTAMP_CNTCVL, &cntcvl) != ERROR_OK)
+               return ERROR_FAIL;
+
+       if (coresight_read_reg(comp, CS_TIMESTAMP_CNTCVU, &cntcvu) != ERROR_OK)
+               return ERROR_FAIL;
+
+       command_print(CMD, "Timestamp counter status: %s", get_field(cntcr, 
CS_TIMESTAMP_CNTCR_EN) ? "enabled" : "disabled");
+       command_print(CMD, "Timestamp counter in debug mode: %s", 
+                       jim_nvp_value2name_simple(nvp_halt_debug_opts, 
get_field(cntsr, CS_TIMESTAMP_CNTSR_DBGH))->name);
+       command_print(CMD, "Timestamp counter value lower: 0x%x", cntcvl);
+       command_print(CMD, "Timestamp counter value upper: 0x%x", cntcvu);
+
+       return ERROR_OK;
+}
+
+static int timestamp_write(struct cstrace_component *comp, const char 
*reg_name, uint32_t value)
+{
+       int offset = timestamp_find_reg_offset(reg_name);
+       if (offset < 0)
+               return ERROR_FAIL;
+
+       return coresight_write_reg(comp, offset, value);
+}
+
+static int timestamp_read(struct cstrace_component *comp, const char 
*reg_name, uint32_t *value)
+{
+       int offset = timestamp_find_reg_offset(reg_name);
+       if (offset < 0)
+               return ERROR_FAIL;
+
+       return coresight_read_reg(comp, offset, value);
+}
+
+struct coresight_type coresight_timestamp = {
+       .name = "timestamp",
+
+       .coresight_create = timestamp_create,
+       .coresight_jim_configure = timestamp_jim_configure,
+
+       .enable = timestamp_enable,
+       .disable = timestamp_disable,
+       .status = timestamp_status,
+       .write = timestamp_write,
+       .read = timestamp_read,
+};
diff --git a/src/target/coresight_trace.c b/src/target/coresight_trace.c
index 436754700c..e0e6360cb6 100644
--- a/src/target/coresight_trace.c
+++ b/src/target/coresight_trace.c
@@ -25,6 +25,7 @@ static OOCD_LIST_HEAD(all_cstrace_component);
 static struct coresight_type *coresight_type[] = {
        &coresight_funnel,
        &coresight_tmc,
+       &coresight_timestamp,
 };
 
 int coresight_write_reg(const struct cstrace_component *comp, unsigned int 
reg, uint32_t value)
diff --git a/src/target/coresight_trace.h b/src/target/coresight_trace.h
index ecd7957824..c4bcb465ab 100644
--- a/src/target/coresight_trace.h
+++ b/src/target/coresight_trace.h
@@ -70,5 +70,6 @@ int cstrace_register_commands(struct command_context 
*cmd_ctx);
 
 extern struct coresight_type coresight_funnel;
 extern struct coresight_type coresight_tmc;
+extern struct coresight_type coresight_timestamp;
 
 #endif /* OPENOCD_TARGET_CORESIGHT_TRACE_H */

-- 

Reply via email to