From a6d858ebcdad1cb1284a4168f2884ed524ee6f21 Mon Sep 17 00:00:00 2001
From: dbrownell <dbrownell@b42882b7-edfa-0310-969c-e2dbd0fdcd60>
Date: Wed, 23 Sep 2009 07:49:38 +0000
Subject: [PATCH] Initial ETM cleanups.  Most of these are cosmetic:

 - Add a header comment
 - Line up the ETM context struct, pack it a bit
 - Remove unused context_id (this doesn't support ETMv2 yet)
 - Make most functions static
 - Remove unused string table and other needless lines of code
 - Correct "tracemode" helptext

Also provide and use an etm_reg_lookup() to find entries in the ETM
register cache.  This will help cope with corrected contents of that
cache, which doesn't include entires for non-existent registers.


git-svn-id: svn://svn.berlios.de/openocd/trunk@2750 b42882b7-edfa-0310-969c-e2dbd0fdcd60
---
 src/target/etm.c | 147 ++++++++++++++++++++++++++++++-----------------
 src/target/etm.h |  49 ++++++----------
 2 files changed, 113 insertions(+), 83 deletions(-)

diff --git a/src/target/etm.c b/src/target/etm.c
index 2623ebe53..dfb104e72 100644
--- a/src/target/etm.c
+++ b/src/target/etm.c
@@ -28,20 +28,28 @@
 #include "arm_disassembler.h"
 
 
-/* ETM register access functionality
+/*
+ * ARM "Embedded Trace Macrocell" (ETM) support -- direct JTAG access.
  *
+ * ETM modules collect instruction and/or data trace information, compress
+ * it, and transfer it to a debugging host through either a (buffered) trace
+ * port (often a 38-pin Mictor connector) or an Embedded Trace Buffer (ETB).
+ *
+ * There are several generations of these modules.  Original versions have
+ * JTAG access through a dedicated scan chain.  Recent versions have added
+ * access via coprocessor instructions, memory addressing, and the ARM Debug
+ * Interface v5 (ADIv5); and phased out direct JTAG access.
+ *
+ * This code supports up to the ETMv1.3 architecture, as seen in ETM9 and
+ * most common ARM9 systems.  Note: "CoreSight ETM9" implements ETMv3.2,
+ * implying non-JTAG connectivity options.
+ *
+ * Relevant documentation includes:
+ *  ARM DDI 0157G ... ETM9 (r2p2) Technical Reference Manual
+ *  ARM DDI 0315B ... CoreSight ETM9 (r0p1) Technical Reference Manual
+ *  ARM IHI 0014O ... Embedded Trace Macrocell, Architecture Specification
  */
 
-#if 0
-static bitfield_desc_t etm_comms_ctrl_bitfield_desc[] =
-{
-	{"R", 1},
-	{"W", 1},
-	{"reserved", 26},
-	{"version", 4}
-};
-#endif
-
 static int etm_reg_arch_info[] =
 {
 	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
@@ -196,10 +204,38 @@ static char* etm_reg_list[] =
 static int etm_reg_arch_type = -1;
 
 static int etm_get_reg(reg_t *reg);
+static int etm_read_reg_w_check(reg_t *reg,
+		uint8_t* check_value, uint8_t* check_mask);
+static int etm_register_user_commands(struct command_context_s *cmd_ctx);
+static int etm_set_reg_w_exec(reg_t *reg, uint8_t *buf);
+static int etm_write_reg(reg_t *reg, uint32_t value);
+
+static command_t *etm_cmd;
 
-static command_t *etm_cmd = NULL;
 
-reg_cache_t* etm_build_reg_cache(target_t *target, arm_jtag_t *jtag_info, etm_context_t *etm_ctx)
+/* Look up register by ID ... most ETM instances only
+ * support a subset of the possible registers.
+ */
+static reg_t *etm_reg_lookup(etm_context_t *etm_ctx, unsigned id)
+{
+	reg_cache_t *cache = etm_ctx->reg_cache;
+	int i;
+
+	for (i = 0; i < cache->num_regs; i++) {
+		struct etm_reg_s *reg = cache->reg_list[i].arch_info;
+
+		if (reg->addr == (int) id)
+			return &cache->reg_list[i];
+	}
+
+	/* caller asking for nonexistent register is a bug! */
+	/* REVISIT say which of the N targets was involved */
+	LOG_ERROR("ETM: register 0x%02x not available", id);
+	return NULL;
+}
+
+reg_cache_t *etm_build_reg_cache(target_t *target,
+		arm_jtag_t *jtag_info, etm_context_t *etm_ctx)
 {
 	reg_cache_t *reg_cache = malloc(sizeof(reg_cache_t));
 	reg_t *reg_list = NULL;
@@ -226,10 +262,6 @@ reg_cache_t* etm_build_reg_cache(target_t *target, arm_jtag_t *jtag_info, etm_co
 	{
 		reg_list[i].name = etm_reg_list[i];
 		reg_list[i].size = 32;
-		reg_list[i].dirty = 0;
-		reg_list[i].valid = 0;
-		reg_list[i].bitfield_desc = NULL;
-		reg_list[i].num_bitfields = 0;
 		reg_list[i].value = calloc(1, 4);
 		reg_list[i].arch_info = &arch_info[i];
 		reg_list[i].arch_type = etm_reg_arch_type;
@@ -264,6 +296,16 @@ reg_cache_t* etm_build_reg_cache(target_t *target, arm_jtag_t *jtag_info, etm_co
 	return reg_cache;
 }
 
+static int etm_read_reg(reg_t *reg)
+{
+	return etm_read_reg_w_check(reg, NULL, NULL);
+}
+
+static int etm_store_reg(reg_t *reg)
+{
+	return etm_write_reg(reg, buf_get_u32(reg->value, 0, reg->size));
+}
+
 int etm_setup(target_t *target)
 {
 	int retval;
@@ -271,7 +313,11 @@ int etm_setup(target_t *target)
 	armv4_5_common_t *armv4_5 = target->arch_info;
 	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
 	etm_context_t *etm_ctx = arm7_9->etm_ctx;
-	reg_t *etm_ctrl_reg = &arm7_9->etm_ctx->reg_cache->reg_list[ETM_CTRL];
+	reg_t *etm_ctrl_reg;
+
+	etm_ctrl_reg = etm_reg_lookup(etm_ctx, ETM_CTRL);
+	if (!etm_ctrl_reg)
+		return ERROR_OK;
 
 	/* initialize some ETM control register settings */
 	etm_get_reg(etm_ctrl_reg);
@@ -299,7 +345,7 @@ int etm_setup(target_t *target)
 	return ERROR_OK;
 }
 
-int etm_get_reg(reg_t *reg)
+static int etm_get_reg(reg_t *reg)
 {
 	int retval;
 
@@ -318,7 +364,8 @@ int etm_get_reg(reg_t *reg)
 	return ERROR_OK;
 }
 
-int etm_read_reg_w_check(reg_t *reg, uint8_t* check_value, uint8_t* check_mask)
+static int etm_read_reg_w_check(reg_t *reg,
+		uint8_t* check_value, uint8_t* check_mask)
 {
 	etm_reg_t *etm_reg = reg->arch_info;
 	uint8_t reg_addr = etm_reg->addr & 0x7f;
@@ -367,12 +414,7 @@ int etm_read_reg_w_check(reg_t *reg, uint8_t* check_value, uint8_t* check_mask)
 	return ERROR_OK;
 }
 
-int etm_read_reg(reg_t *reg)
-{
-	return etm_read_reg_w_check(reg, NULL, NULL);
-}
-
-int etm_set_reg(reg_t *reg, uint32_t value)
+static int etm_set_reg(reg_t *reg, uint32_t value)
 {
 	int retval;
 
@@ -389,7 +431,7 @@ int etm_set_reg(reg_t *reg, uint32_t value)
 	return ERROR_OK;
 }
 
-int etm_set_reg_w_exec(reg_t *reg, uint8_t *buf)
+static int etm_set_reg_w_exec(reg_t *reg, uint8_t *buf)
 {
 	int retval;
 
@@ -403,7 +445,7 @@ int etm_set_reg_w_exec(reg_t *reg, uint8_t *buf)
 	return ERROR_OK;
 }
 
-int etm_write_reg(reg_t *reg, uint32_t value)
+static int etm_write_reg(reg_t *reg, uint32_t value)
 {
 	etm_reg_t *etm_reg = reg->arch_info;
 	uint8_t reg_addr = etm_reg->addr & 0x7f;
@@ -441,10 +483,6 @@ int etm_write_reg(reg_t *reg, uint32_t value)
 	return ERROR_OK;
 }
 
-int etm_store_reg(reg_t *reg)
-{
-	return etm_write_reg(reg, buf_get_u32(reg->value, 0, reg->size));
-}
 
 /* ETM trace analysis functionality
  *
@@ -464,18 +502,6 @@ static etm_capture_driver_t *etm_capture_drivers[] =
 	NULL
 };
 
-char *etmv1v1_branch_reason_strings[] =
-{
-	"normal PC change",
-	"tracing enabled",
-	"trace restarted after overflow",
-	"exit from debug",
-	"periodic synchronization",
-	"reserved",
-	"reserved",
-	"reserved",
-};
-
 static int etm_read_instruction(etm_context_t *ctx, arm_instruction_t *instruction)
 {
 	int i;
@@ -1172,7 +1198,11 @@ static int handle_etm_tracemode_command(struct command_context_s *cmd_ctx, char
 	/* only update ETM_CTRL register if tracemode changed */
 	if (arm7_9->etm_ctx->tracemode != tracemode)
 	{
-		reg_t *etm_ctrl_reg = &arm7_9->etm_ctx->reg_cache->reg_list[ETM_CTRL];
+		reg_t *etm_ctrl_reg;
+
+		etm_ctrl_reg = etm_reg_lookup(arm7_9->etm_ctx, ETM_CTRL);
+		if (!etm_ctrl_reg)
+			return ERROR_OK;
 
 		etm_get_reg(etm_ctrl_reg);
 
@@ -1319,7 +1349,6 @@ static int handle_etm_config_command(struct command_context_s *cmd_ctx, char *cm
 	etm_ctx->last_branch_reason = 0x0;
 	etm_ctx->last_ptr = 0x0;
 	etm_ctx->ptr_ok = 0x0;
-	etm_ctx->context_id = 0x0;
 	etm_ctx->last_instruction = 0;
 
 	arm7_9->etm_ctx = etm_ctx;
@@ -1327,7 +1356,8 @@ static int handle_etm_config_command(struct command_context_s *cmd_ctx, char *cm
 	return etm_register_user_commands(cmd_ctx);
 }
 
-int handle_etm_info_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+static int handle_etm_info_command(struct command_context_s *cmd_ctx,
+		char *cmd, char **args, int argc)
 {
 	target_t *target;
 	armv4_5_common_t *armv4_5;
@@ -1351,8 +1381,12 @@ int handle_etm_info_command(struct command_context_s *cmd_ctx, char *cmd, char *
 		return ERROR_OK;
 	}
 
-	etm_config_reg = &arm7_9->etm_ctx->reg_cache->reg_list[ETM_CONFIG];
-	etm_sys_config_reg = &arm7_9->etm_ctx->reg_cache->reg_list[ETM_SYS_CONFIG];
+	etm_config_reg = etm_reg_lookup(arm7_9->etm_ctx, ETM_CONFIG);
+	if (!etm_config_reg)
+		return ERROR_OK;
+	etm_sys_config_reg = etm_reg_lookup(arm7_9->etm_ctx, ETM_SYS_CONFIG);
+	if (!etm_sys_config_reg)
+		return ERROR_OK;
 
 	etm_get_reg(etm_config_reg);
 	command_print(cmd_ctx, "pairs of address comparators: %i", (int)buf_get_u32(etm_config_reg->value, 0, 4));
@@ -1732,7 +1766,10 @@ static int handle_etm_start_command(struct command_context_s *cmd_ctx, char *cmd
 	}
 	arm7_9->etm_ctx->trace_depth = 0;
 
-	etm_ctrl_reg = &arm7_9->etm_ctx->reg_cache->reg_list[ETM_CTRL];
+	etm_ctrl_reg = etm_reg_lookup(etm_ctx, ETM_CTRL);
+	if (!etm_ctrl_reg)
+		return ERROR_OK;
+
 	etm_get_reg(etm_ctrl_reg);
 
 	/* Clear programming bit (10), set port selection bit (11) */
@@ -1768,7 +1805,10 @@ static int handle_etm_stop_command(struct command_context_s *cmd_ctx, char *cmd,
 		return ERROR_OK;
 	}
 
-	etm_ctrl_reg = &arm7_9->etm_ctx->reg_cache->reg_list[ETM_CTRL];
+	etm_ctrl_reg = etm_reg_lookup(etm_ctx, ETM_CTRL);
+	if (!etm_ctrl_reg)
+		return ERROR_OK;
+
 	etm_get_reg(etm_ctrl_reg);
 
 	/* Set programming bit (10), clear port selection bit (11) */
@@ -1835,10 +1875,11 @@ int etm_register_commands(struct command_context_s *cmd_ctx)
 	return ERROR_OK;
 }
 
-int etm_register_user_commands(struct command_context_s *cmd_ctx)
+static int etm_register_user_commands(struct command_context_s *cmd_ctx)
 {
 	register_command(cmd_ctx, etm_cmd, "tracemode", handle_etm_tracemode_command,
-		COMMAND_EXEC, "configure trace mode <none | data | address | all> "
+		COMMAND_EXEC, "configure/display trace mode: "
+			"<none | data | address | all> "
 			"<context_id_bits> <cycle_accurate> <branch_output>");
 
 	register_command(cmd_ctx, etm_cmd, "info", handle_etm_info_command,
diff --git a/src/target/etm.h b/src/target/etm.h
index 14dda4fce..43ec048fb 100644
--- a/src/target/etm.h
+++ b/src/target/etm.h
@@ -139,29 +139,28 @@ typedef struct etmv1_trace_data_s
  */
 typedef struct etm_context_s
 {
-	target_t *target;				/* target this ETM is connected to */
-	reg_cache_t *reg_cache;			/* ETM register cache */
+	target_t *target;		/* target this ETM is connected to */
+	reg_cache_t *reg_cache;		/* ETM register cache */
 	etm_capture_driver_t *capture_driver;	/* driver used to access ETM data */
-	void *capture_driver_priv;		/* capture driver private data */
-	uint32_t trigger_percent;			/* percent of trace buffer to be filled after the trigger */
+	void *capture_driver_priv;	/* capture driver private data */
+	uint32_t trigger_percent;	/* how much trace buffer to fill after trigger */
 	trace_status_t capture_status;	/* current state of capture run */
 	etmv1_trace_data_t *trace_data;	/* trace data */
-	uint32_t trace_depth;				/* number of trace cycles to be analyzed, 0 if no trace data available */
-	etm_portmode_t portmode;		/* normal, multiplexed or demultiplexed */
-	etmv1_tracemode_t tracemode;	/* type of information the trace contains (data, addres, contextID, ...) */
-	armv4_5_state_t core_state;		/* current core state (ARM, Thumb, Jazelle) */
-	struct image_s *image;					/* source for target opcodes */
-	uint32_t pipe_index;					/* current trace cycle */
-	uint32_t data_index;					/* cycle holding next data packet */
-	int data_half;					/* port half on a 16 bit port */
-	uint32_t current_pc;					/* current program counter */
-	uint32_t pc_ok;						/* full PC has been acquired */
-	uint32_t last_branch;				/* last branch address output */
-	uint32_t last_branch_reason;			/* branch reason code for the last branch encountered */
-	uint32_t last_ptr;					/* address of the last data access */
-	uint32_t ptr_ok;						/* whether last_ptr is valid */
-	uint32_t context_id;					/* context ID of the code being traced */
-	uint32_t last_instruction;			/* index of last instruction executed (to calculate cycle timings) */
+	uint32_t trace_depth;		/* number of cycles to be analyzed, 0 if no data available */
+	etm_portmode_t portmode;	/* normal, multiplexed or demultiplexed */
+	etmv1_tracemode_t tracemode;	/* type of info trace contains */
+	armv4_5_state_t core_state;	/* current core state */
+	struct image_s *image;		/* source for target opcodes */
+	uint32_t pipe_index;		/* current trace cycle */
+	uint32_t data_index;		/* cycle holding next data packet */
+	bool data_half;			/* port half on a 16 bit port */
+	bool pc_ok;			/* full PC has been acquired */
+	bool ptr_ok;			/* whether last_ptr is valid */
+	uint32_t current_pc;		/* current program counter */
+	uint32_t last_branch;		/* last branch address output */
+	uint32_t last_branch_reason;	/* type of last branch encountered */
+	uint32_t last_ptr;		/* address of the last data access */
+	uint32_t last_instruction;	/* index of last executed (to calc timings) */
 } etm_context_t;
 
 /* PIPESTAT values */
@@ -190,20 +189,10 @@ typedef enum
 	BR_RSVD7   = 0x7, /* reserved */
 } etmv1_branch_reason_t;
 
-extern char *etmv1v1_branch_reason_strings[];
-
 extern reg_cache_t* etm_build_reg_cache(target_t *target, arm_jtag_t *jtag_info, etm_context_t *etm_ctx);
-extern int etm_read_reg(reg_t *reg);
-extern int etm_write_reg(reg_t *reg, uint32_t value);
-extern int etm_read_reg_w_check(reg_t *reg, uint8_t* check_value, uint8_t* check_mask);
-extern int etm_store_reg(reg_t *reg);
-extern int etm_set_reg(reg_t *reg, uint32_t value);
-extern int etm_set_reg_w_exec(reg_t *reg, uint8_t *buf);
 extern int etm_setup(target_t *target);
 
 int etm_register_commands(struct command_context_s *cmd_ctx);
-int etm_register_user_commands(struct command_context_s *cmd_ctx);
-extern etm_context_t* etm_create_context(etm_portmode_t portmode, char *capture_driver_name);
 
 #define ERROR_ETM_INVALID_DRIVER	(-1300)
 #define ERROR_ETM_PORTMODE_NOT_SUPPORTED	(-1301)
-- 
GitLab