From: Michael Bruck Date: Tue, 27 Oct 2009 21:41:00 +0000 (+0100) Subject: arm11: add etmr/etmw registers to access ETM via DBGTAP scan chain X-Git-Tag: v0.4.0-rc1~846 X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=commitdiff_plain;h=627bd197689d71f7beb3e9cd11e2993fe0d4d880 arm11: add etmr/etmw registers to access ETM via DBGTAP scan chain First cut of these commands. Øyvind tinkered a bit with the number parsing to bring it up to speed + rebased it. Ready for testing. Signed-off-by: Øyvind Harboe --- diff --git a/src/target/arm11.c b/src/target/arm11.c index 9d885de445..fe39d6e880 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 "); + + register_command(cmd_ctx, top_cmd, "etmw", + arm11_handle_etmw, COMMAND_ANY, + "Write Embedded Trace Macrocell (ETM) register. etmr "); + /* "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 be5e77bd1a..100fc26a7a 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 0e1160f8a7..fc7a55c5eb 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; +} +