summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/target/arm11.c61
-rw-r--r--src/target/arm11.h5
-rw-r--r--src/target/arm11_dbgtap.c76
3 files changed, 142 insertions, 0 deletions
diff --git a/src/target/arm11.c b/src/target/arm11.c
index 9d885de4..fe39d6e8 100644
--- a/src/target/arm11.c
+++ b/src/target/arm11.c
@@ -2143,6 +2143,59 @@ static int arm11_mcr(target_t *target, int cpnum,
return arm11_mrc_inner(target, cpnum, op1, op2, CRn, CRm, &value, false);
}
+static int arm11_handle_etm_read_write(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, bool read)
+{
+ if (argc != (read ? 2 : 3))
+ {
+ LOG_ERROR("Invalid number of arguments.");
+ return ERROR_COMMAND_SYNTAX_ERROR;
+ }
+
+ arm11_common_t * arm11 = arm11_find_target(args[0]);
+
+ if (!arm11)
+ {
+ LOG_ERROR("Parameter 1 is not the target name of an ARM11 device.");
+ return ERROR_COMMAND_SYNTAX_ERROR;
+ }
+
+ uint32_t address;
+ COMMAND_PARSE_NUMBER(u32, args[1], address);
+
+ if (!read)
+ {
+ uint32_t value;
+ COMMAND_PARSE_NUMBER(u32, args[2], value);
+
+ LOG_INFO("ETM write register 0x%02" PRIx32 " (%" PRId32 ") = 0x%08" PRIx32 " (%" PRId32 ")",
+ address, address, value, value);
+
+ CHECK_RETVAL(arm11_write_etm(arm11, address, value));
+ }
+ else
+ {
+ uint32_t value;
+
+ CHECK_RETVAL(arm11_read_etm(arm11, address, &value));
+
+ LOG_INFO("ETM read register 0x%02" PRIx32 " (%" PRId32 ") = 0x%08" PRIx32 " (%" PRId32 ")",
+ address, address, value, value);
+ }
+
+ return ERROR_OK;
+}
+
+int arm11_handle_etmr(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+ return arm11_handle_etm_read_write(cmd_ctx, cmd, args, argc, true);
+}
+
+int arm11_handle_etmw(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+ return arm11_handle_etm_read_write(cmd_ctx, cmd, args, argc, false);
+}
+
+
#define ARM11_HANDLER(x) .x = arm11_##x
target_type_t arm11_target = {
@@ -2196,6 +2249,14 @@ int arm11_register_commands(struct command_context_s *cmd_ctx)
top_cmd = register_command(cmd_ctx, NULL, "arm11",
NULL, COMMAND_ANY, NULL);
+ register_command(cmd_ctx, top_cmd, "etmr",
+ arm11_handle_etmr, COMMAND_ANY,
+ "Read Embedded Trace Macrocell (ETM) register. etmr <jtag_target> <ETM register address>");
+
+ register_command(cmd_ctx, top_cmd, "etmw",
+ arm11_handle_etmw, COMMAND_ANY,
+ "Write Embedded Trace Macrocell (ETM) register. etmr <jtag_target> <ETM register address> <value>");
+
/* "hardware_step" is only here to check if the default
* simulate + breakpoint implementation is broken.
* TEMPORARY! NOT DOCUMENTED!
diff --git a/src/target/arm11.h b/src/target/arm11.h
index be5e77bd..100fc26a 100644
--- a/src/target/arm11.h
+++ b/src/target/arm11.h
@@ -184,4 +184,9 @@ typedef struct arm11_reg_state_s
int arm11_register_commands(struct command_context_s *cmd_ctx);
+int arm11_read_etm(arm11_common_t * arm11, uint8_t address, uint32_t *value);
+int arm11_write_etm(arm11_common_t * arm11, uint8_t address, uint32_t value);
+
+
+
#endif /* ARM11_H */
diff --git a/src/target/arm11_dbgtap.c b/src/target/arm11_dbgtap.c
index 0e1160f8..fc7a55c5 100644
--- a/src/target/arm11_dbgtap.c
+++ b/src/target/arm11_dbgtap.c
@@ -940,3 +940,79 @@ int arm11_read_memory_word(arm11_common_t * arm11, uint32_t address, uint32_t *
}
+/** Write Embedded Trace Macrocell (ETM) via Scan chain 6
+ *
+ * http://infocenter.arm.com/help/topic/com.arm.doc.ddi0318e/Bcfddjeh.html#Bcfggcbe
+ *
+ * \param arm11 Target state variable.
+ * \param address 7 bit ETM register address
+ * \param value Value to be written
+ *
+ * \return Error status
+ *
+ * \remarks This is a stand-alone function that executes the JTAG command queue.
+ */
+int arm11_write_etm(arm11_common_t * arm11, uint8_t address, uint32_t value)
+{
+ CHECK_RETVAL(arm11_add_debug_SCAN_N(arm11, 0x06, ARM11_TAP_DEFAULT));
+
+ /* Uses INTEST for read and write */
+ arm11_add_IR(arm11, ARM11_INTEST, ARM11_TAP_DEFAULT);
+
+ scan_field_t chain6_fields[3];
+
+ uint8_t nRW = 1;
+
+ arm11_setup_field(arm11, 32, &value, NULL, chain6_fields + 0);
+ arm11_setup_field(arm11, 7, &address, NULL, chain6_fields + 1);
+ arm11_setup_field(arm11, 1, &nRW, NULL, chain6_fields + 2);
+
+ arm11_add_dr_scan_vc(asizeof(chain6_fields), chain6_fields, TAP_IDLE);
+
+ CHECK_RETVAL(jtag_execute_queue());
+
+ return ERROR_OK;
+}
+
+/** Read Embedded Trace Macrocell (ETM) via Scan chain 6
+ *
+ * http://infocenter.arm.com/help/topic/com.arm.doc.ddi0318e/Bcfddjeh.html#Bcfggcbe
+ *
+ * \param arm11 Target state variable.
+ * \param address 7 bit ETM register address
+ * \param value Pointer that receives value that was read
+ *
+ * \return Error status
+ *
+ * \remarks This is a stand-alone function that executes the JTAG command queue.
+ */
+int arm11_read_etm(arm11_common_t * arm11, uint8_t address, uint32_t * value)
+{
+ CHECK_RETVAL(arm11_add_debug_SCAN_N(arm11, 0x06, ARM11_TAP_DEFAULT));
+
+ /* Uses INTEST for read and write */
+ arm11_add_IR(arm11, ARM11_INTEST, ARM11_TAP_DEFAULT);
+
+ scan_field_t chain6_fields[3];
+
+ uint8_t nRW = 0;
+
+ arm11_setup_field(arm11, 32, NULL, NULL, chain6_fields + 0);
+ arm11_setup_field(arm11, 7, &address, NULL, chain6_fields + 1);
+ arm11_setup_field(arm11, 1, &nRW, NULL, chain6_fields + 2);
+
+ arm11_add_dr_scan_vc(asizeof(chain6_fields), chain6_fields, TAP_IDLE);
+
+ /* Data is made available in Capture-DR and shifted out on the next access */
+
+ arm11_setup_field(arm11, 32, NULL, value, chain6_fields + 0);
+ arm11_setup_field(arm11, 7, &address, NULL, chain6_fields + 1);
+ arm11_setup_field(arm11, 1, &nRW, NULL, chain6_fields + 2);
+
+ arm11_add_dr_scan_vc(asizeof(chain6_fields), chain6_fields, TAP_IDLE);
+
+ CHECK_RETVAL(jtag_execute_queue());
+
+ return ERROR_OK;
+}
+