X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=blobdiff_plain;f=src%2Ftarget%2Fetm.c;h=3126efc2f211f597be37d5bc6b1572005f399238;hp=9cb647cbebff0096328a9df69566ea5e93c85be1;hb=ff5deeeeaa4f394931e3c5ccfb4cfd33beda0743;hpb=26d7ed08f9ff220be583179fdea76466739cf32d diff --git a/src/target/etm.c b/src/target/etm.c index 9cb647cbeb..3126efc2f2 100644 --- a/src/target/etm.c +++ b/src/target/etm.c @@ -435,10 +435,10 @@ int etm_setup(struct target *target) /* initialize some ETM control register settings */ etm_get_reg(etm_ctrl_reg); - etm_ctrl_value = buf_get_u32(etm_ctrl_reg->value, 0, etm_ctrl_reg->size); + etm_ctrl_value = buf_get_u32(etm_ctrl_reg->value, 0, 32); /* clear the ETM powerdown bit (0) */ - etm_ctrl_value &= ~0x1; + etm_ctrl_value &= ~ETM_CTRL_POWERDOWN; /* configure port width (21,6:4), mode (13,17:16) and * for older modules clocking (13) @@ -446,12 +446,15 @@ int etm_setup(struct target *target) etm_ctrl_value = (etm_ctrl_value & ~ETM_PORT_WIDTH_MASK & ~ETM_PORT_MODE_MASK + & ~ETM_CTRL_DBGRQ & ~ETM_PORT_CLOCK_MASK) - | etm_ctx->portmode; + | etm_ctx->control; - buf_set_u32(etm_ctrl_reg->value, 0, etm_ctrl_reg->size, etm_ctrl_value); + buf_set_u32(etm_ctrl_reg->value, 0, 32, etm_ctrl_value); etm_store_reg(etm_ctrl_reg); + etm_ctx->control = etm_ctrl_value; + if ((retval = jtag_execute_queue()) != ERROR_OK) return retval; @@ -727,7 +730,8 @@ static int etmv1_next_packet(struct etm_context *ctx, uint8_t *packet, int apo) continue; } - if ((ctx->portmode & ETM_PORT_WIDTH_MASK) == ETM_PORT_16BIT) + /* FIXME there are more port widths than these... */ + if ((ctx->control & ETM_PORT_WIDTH_MASK) == ETM_PORT_16BIT) { if (ctx->data_half == 0) { @@ -741,7 +745,7 @@ static int etmv1_next_packet(struct etm_context *ctx, uint8_t *packet, int apo) ctx->data_index++; } } - else if ((ctx->portmode & ETM_PORT_WIDTH_MASK) == ETM_PORT_8BIT) + else if ((ctx->control & ETM_PORT_WIDTH_MASK) == ETM_PORT_8BIT) { *packet = ctx->trace_data[ctx->data_index].packet & 0xff; ctx->data_index++; @@ -1058,7 +1062,7 @@ static int etmv1_analyze_trace(struct etm_context *ctx, struct command_context * ctx->data_half = old_data_half; } - if (ctx->tracemode & ETMV1_TRACE_ADDR) + if (ctx->control & ETM_CTRL_TRACE_ADDR) { uint8_t packet; int shift = 0; @@ -1080,7 +1084,7 @@ static int etmv1_analyze_trace(struct etm_context *ctx, struct command_context * } } - if (ctx->tracemode & ETMV1_TRACE_DATA) + if (ctx->control & ETM_CTRL_TRACE_DATA) { if ((instruction.type == ARM_LDM) || (instruction.type == ARM_STM)) { @@ -1140,7 +1144,7 @@ static int etmv1_analyze_trace(struct etm_context *ctx, struct command_context * /* if the trace was captured with cycle accurate tracing enabled, * output the number of cycles since the last executed instruction */ - if (ctx->tracemode & ETMV1_CYCLE_ACCURATE) + if (ctx->control & ETM_CTRL_CYCLE_ACCURATE) { snprintf(cycles_text, 32, " (%i %s)", (int)cycles, @@ -1171,19 +1175,19 @@ static int etmv1_analyze_trace(struct etm_context *ctx, struct command_context * } static COMMAND_HELPER(handle_etm_tracemode_command_update, - etmv1_tracemode_t *mode) + uint32_t *mode) { - etmv1_tracemode_t tracemode; + uint32_t tracemode; /* what parts of data access are traced? */ if (strcmp(CMD_ARGV[0], "none") == 0) - tracemode = ETMV1_TRACE_NONE; + tracemode = 0; else if (strcmp(CMD_ARGV[0], "data") == 0) - tracemode = ETMV1_TRACE_DATA; + tracemode = ETM_CTRL_TRACE_DATA; else if (strcmp(CMD_ARGV[0], "address") == 0) - tracemode = ETMV1_TRACE_ADDR; + tracemode = ETM_CTRL_TRACE_ADDR; else if (strcmp(CMD_ARGV[0], "all") == 0) - tracemode = ETMV1_TRACE_DATA | ETMV1_TRACE_ADDR; + tracemode = ETM_CTRL_TRACE_DATA | ETM_CTRL_TRACE_ADDR; else { command_print(CMD_CTX, "invalid option '%s'", CMD_ARGV[0]); @@ -1195,16 +1199,16 @@ static COMMAND_HELPER(handle_etm_tracemode_command_update, switch (context_id) { case 0: - tracemode |= ETMV1_CONTEXTID_NONE; + tracemode |= ETM_CTRL_CONTEXTID_NONE; break; case 8: - tracemode |= ETMV1_CONTEXTID_8; + tracemode |= ETM_CTRL_CONTEXTID_8; break; case 16: - tracemode |= ETMV1_CONTEXTID_16; + tracemode |= ETM_CTRL_CONTEXTID_16; break; case 32: - tracemode |= ETMV1_CONTEXTID_32; + tracemode |= ETM_CTRL_CONTEXTID_32; break; default: command_print(CMD_CTX, "invalid option '%s'", CMD_ARGV[1]); @@ -1214,11 +1218,12 @@ static COMMAND_HELPER(handle_etm_tracemode_command_update, bool etmv1_cycle_accurate; COMMAND_PARSE_ENABLE(CMD_ARGV[2], etmv1_cycle_accurate); if (etmv1_cycle_accurate) - tracemode |= ETMV1_CYCLE_ACCURATE; + tracemode |= ETM_CTRL_CYCLE_ACCURATE; bool etmv1_branch_output; COMMAND_PARSE_ENABLE(CMD_ARGV[3], etmv1_branch_output); - tracemode |= ETMV1_BRANCH_OUTPUT; + if (etmv1_branch_output) + tracemode |= ETM_CTRL_BRANCH_OUTPUT; /* IGNORED: * - CPRT tracing (coprocessor register transfers) @@ -1247,19 +1252,23 @@ COMMAND_HANDLER(handle_etm_tracemode_command) return ERROR_FAIL; } - etmv1_tracemode_t tracemode = etm->tracemode; + uint32_t tracemode = etm->control; switch (CMD_ARGC) { case 0: break; case 4: - CALL_COMMAND_HANDLER(handle_etm_tracemode_command_update, &tracemode); + CALL_COMMAND_HANDLER(handle_etm_tracemode_command_update, + &tracemode); break; default: - command_print(CMD_CTX, "usage: configure trace mode " - " " - " "); + command_print(CMD_CTX, "usage: tracemode " + "('none'|'data'|'address'|'all') " + "context_id_bits " + "('enable'|'disable') " + "('enable'|'disable')" + ); return ERROR_FAIL; } @@ -1270,39 +1279,39 @@ COMMAND_HANDLER(handle_etm_tracemode_command) command_print(CMD_CTX, "current tracemode configuration:"); - switch (tracemode & ETMV1_TRACE_MASK) + switch (tracemode & ETM_CTRL_TRACE_MASK) { - case ETMV1_TRACE_NONE: + default: command_print(CMD_CTX, "data tracing: none"); break; - case ETMV1_TRACE_DATA: + case ETM_CTRL_TRACE_DATA: command_print(CMD_CTX, "data tracing: data only"); break; - case ETMV1_TRACE_ADDR: + case ETM_CTRL_TRACE_ADDR: command_print(CMD_CTX, "data tracing: address only"); break; - case ETMV1_TRACE_DATA | ETMV1_TRACE_ADDR: + case ETM_CTRL_TRACE_DATA | ETM_CTRL_TRACE_ADDR: command_print(CMD_CTX, "data tracing: address and data"); break; } - switch (tracemode & ETMV1_CONTEXTID_MASK) + switch (tracemode & ETM_CTRL_CONTEXTID_MASK) { - case ETMV1_CONTEXTID_NONE: + case ETM_CTRL_CONTEXTID_NONE: command_print(CMD_CTX, "contextid tracing: none"); break; - case ETMV1_CONTEXTID_8: + case ETM_CTRL_CONTEXTID_8: command_print(CMD_CTX, "contextid tracing: 8 bit"); break; - case ETMV1_CONTEXTID_16: + case ETM_CTRL_CONTEXTID_16: command_print(CMD_CTX, "contextid tracing: 16 bit"); break; - case ETMV1_CONTEXTID_32: + case ETM_CTRL_CONTEXTID_32: command_print(CMD_CTX, "contextid tracing: 32 bit"); break; } - if (tracemode & ETMV1_CYCLE_ACCURATE) + if (tracemode & ETM_CTRL_CYCLE_ACCURATE) { command_print(CMD_CTX, "cycle-accurate tracing enabled"); } @@ -1311,7 +1320,7 @@ COMMAND_HANDLER(handle_etm_tracemode_command) command_print(CMD_CTX, "cycle-accurate tracing disabled"); } - if (tracemode & ETMV1_BRANCH_OUTPUT) + if (tracemode & ETM_CTRL_BRANCH_OUTPUT) { command_print(CMD_CTX, "full branch address output enabled"); } @@ -1320,8 +1329,15 @@ COMMAND_HANDLER(handle_etm_tracemode_command) command_print(CMD_CTX, "full branch address output disabled"); } +#define TRACEMODE_MASK ( \ + ETM_CTRL_CONTEXTID_MASK \ + | ETM_CTRL_BRANCH_OUTPUT \ + | ETM_CTRL_CYCLE_ACCURATE \ + | ETM_CTRL_TRACE_MASK \ + ) + /* only update ETM_CTRL register if tracemode changed */ - if (etm->tracemode != tracemode) + if ((etm->control & TRACEMODE_MASK) != tracemode) { struct reg *etm_ctrl_reg; @@ -1329,16 +1345,12 @@ COMMAND_HANDLER(handle_etm_tracemode_command) if (!etm_ctrl_reg) return ERROR_FAIL; - etm_get_reg(etm_ctrl_reg); + etm->control &= ~TRACEMODE_MASK; + etm->control |= tracemode & TRACEMODE_MASK; - buf_set_u32(etm_ctrl_reg->value, 2, 2, tracemode & ETMV1_TRACE_MASK); - buf_set_u32(etm_ctrl_reg->value, 14, 2, (tracemode & ETMV1_CONTEXTID_MASK) >> 4); - buf_set_u32(etm_ctrl_reg->value, 12, 1, (tracemode & ETMV1_CYCLE_ACCURATE) >> 8); - buf_set_u32(etm_ctrl_reg->value, 8, 1, (tracemode & ETMV1_BRANCH_OUTPUT) >> 9); + buf_set_u32(etm_ctrl_reg->value, 0, 32, etm->control); etm_store_reg(etm_ctrl_reg); - etm->tracemode = tracemode; - /* invalidate old trace data */ etm->capture_status = TRACE_IDLE; if (etm->trace_depth > 0) @@ -1349,6 +1361,8 @@ COMMAND_HANDLER(handle_etm_tracemode_command) etm->trace_depth = 0; } +#undef TRACEMODE_MASK + return ERROR_OK; } @@ -1356,7 +1370,7 @@ COMMAND_HANDLER(handle_etm_config_command) { struct target *target; struct arm *arm; - etm_portmode_t portmode = 0x0; + uint32_t portmode = 0x0; struct etm_context *etm_ctx; int i; @@ -1494,9 +1508,8 @@ COMMAND_HANDLER(handle_etm_config_command) } etm_ctx->target = target; - etm_ctx->trigger_percent = 50; etm_ctx->trace_data = NULL; - etm_ctx->portmode = portmode; + etm_ctx->control = portmode; etm_ctx->core_state = ARM_STATE_ARM; arm->etm = etm_ctx; @@ -1823,8 +1836,7 @@ COMMAND_HANDLER(handle_etm_dump_command) } fileio_write_u32(&file, etm_ctx->capture_status); - fileio_write_u32(&file, etm_ctx->portmode); - fileio_write_u32(&file, etm_ctx->tracemode); + fileio_write_u32(&file, etm_ctx->control); fileio_write_u32(&file, etm_ctx->trace_depth); for (i = 0; i < etm_ctx->trace_depth; i++) @@ -1895,8 +1907,7 @@ COMMAND_HANDLER(handle_etm_load_command) { uint32_t tmp; fileio_read_u32(&file, &tmp); etm_ctx->capture_status = tmp; - fileio_read_u32(&file, &tmp); etm_ctx->portmode = tmp; - fileio_read_u32(&file, &tmp); etm_ctx->tracemode = tmp; + fileio_read_u32(&file, &tmp); etm_ctx->control = tmp; fileio_read_u32(&file, &etm_ctx->trace_depth); } etm_ctx->trace_data = malloc(sizeof(struct etmv1_trace_data) * etm_ctx->trace_depth); @@ -1923,47 +1934,6 @@ COMMAND_HANDLER(handle_etm_load_command) return ERROR_OK; } -COMMAND_HANDLER(handle_etm_trigger_percent_command) -{ - struct target *target; - struct arm *arm; - struct etm_context *etm_ctx; - - target = get_current_target(CMD_CTX); - arm = target_to_arm(target); - if (!is_arm(arm)) - { - command_print(CMD_CTX, "ETM: current target isn't an ARM"); - return ERROR_FAIL; - } - - etm_ctx = arm->etm; - if (!etm_ctx) - { - command_print(CMD_CTX, "current target doesn't have an ETM configured"); - return ERROR_FAIL; - } - - if (CMD_ARGC > 0) - { - uint32_t new_value; - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], new_value); - - if ((new_value < 2) || (new_value > 100)) - { - command_print(CMD_CTX, "valid settings are 2%% to 100%%"); - } - else - { - etm_ctx->trigger_percent = new_value; - } - } - - command_print(CMD_CTX, "%i percent of the tracebuffer reserved for after the trigger", ((int)(etm_ctx->trigger_percent))); - - return ERROR_OK; -} - COMMAND_HANDLER(handle_etm_start_command) { struct target *target; @@ -2051,6 +2021,56 @@ COMMAND_HANDLER(handle_etm_stop_command) return ERROR_OK; } +COMMAND_HANDLER(handle_etm_trigger_debug_command) +{ + struct target *target; + struct arm *arm; + struct etm_context *etm; + + target = get_current_target(CMD_CTX); + arm = target_to_arm(target); + if (!is_arm(arm)) + { + command_print(CMD_CTX, "ETM: %s isn't an ARM", + target_name(target)); + return ERROR_FAIL; + } + + etm = arm->etm; + if (!etm) + { + command_print(CMD_CTX, "ETM: no ETM configured for %s", + target_name(target)); + return ERROR_FAIL; + } + + if (CMD_ARGC == 1) { + struct reg *etm_ctrl_reg; + bool dbgrq; + + etm_ctrl_reg = etm_reg_lookup(etm, ETM_CTRL); + if (!etm_ctrl_reg) + return ERROR_FAIL; + + COMMAND_PARSE_ENABLE(CMD_ARGV[0], dbgrq); + if (dbgrq) + etm->control |= ETM_CTRL_DBGRQ; + else + etm->control &= ~ETM_CTRL_DBGRQ; + + /* etm->control will be written to hardware + * the next time an "etm start" is issued. + */ + buf_set_u32(etm_ctrl_reg->value, 0, 32, etm->control); + } + + command_print(CMD_CTX, "ETM: %s debug halt", + (etm->control & ETM_CTRL_DBGRQ) + ? "triggers" + : "does not trigger"); + return ERROR_OK; +} + COMMAND_HANDLER(handle_etm_analyze_command) { struct target *target; @@ -2096,11 +2116,16 @@ COMMAND_HANDLER(handle_etm_analyze_command) static const struct command_registration etm_config_command_handlers[] = { { + /* NOTE: with ADIv5, ETMs are accessed by DAP operations, + * possibly over SWD, not JTAG scanchain 6 of 'target'. + * + * Also, these parameters don't match ETM v3+ modules... + */ .name = "config", - .handler = &handle_etm_config_command, + .handler = handle_etm_config_command, .mode = COMMAND_CONFIG, - .usage = " " - " ", + .help = "Set up ETM output port.", + .usage = "target port_width port_mode clocking capture_driver", }, COMMAND_REGISTRATION_DONE }; @@ -2116,64 +2141,69 @@ const struct command_registration etm_command_handlers[] = { static const struct command_registration etm_exec_command_handlers[] = { { - .name = "tracemode", handle_etm_tracemode_command, + .name = "tracemode", + .handler = handle_etm_tracemode_command, .mode = COMMAND_EXEC, .help = "configure/display trace mode", - .usage = " " - " ", + .usage = "('none'|'data'|'address'|'all') " + "context_id_bits " + "['enable'|'disable'] " + "['enable'|'disable']", }, { .name = "info", - .handler = &handle_etm_info_command, + .handler = handle_etm_info_command, .mode = COMMAND_EXEC, .help = "display info about the current target's ETM", }, - { - .name = "trigger_percent", - .handler = &handle_etm_trigger_percent_command, - .mode = COMMAND_EXEC, - .help = "amount () of trace buffer " - "to be filled after the trigger occured", - }, { .name = "status", - .handler = &handle_etm_status_command, + .handler = handle_etm_status_command, .mode = COMMAND_EXEC, .help = "display current target's ETM status", }, { .name = "start", - .handler = &handle_etm_start_command, + .handler = handle_etm_start_command, .mode = COMMAND_EXEC, .help = "start ETM trace collection", }, { .name = "stop", - .handler = &handle_etm_stop_command, + .handler = handle_etm_stop_command, .mode = COMMAND_EXEC, .help = "stop ETM trace collection", }, + { + .name = "trigger_debug", + .handler = handle_etm_trigger_debug_command, + .mode = COMMAND_EXEC, + .help = "enable/disable debug entry on trigger", + .usage = "['enable'|'disable']", + }, { .name = "analyze", - .handler = &handle_etm_analyze_command, + .handler = handle_etm_analyze_command, .mode = COMMAND_EXEC, - .help = "anaylze collected ETM trace", + .help = "analyze collected ETM trace", }, { .name = "image", - .handler = &handle_etm_image_command, + .handler = handle_etm_image_command, .mode = COMMAND_EXEC, - .help = "load image from [base address]", + .help = "load image from file with optional offset", + .usage = "filename [offset]", }, { .name = "dump", - .handler = &handle_etm_dump_command, + .handler = handle_etm_dump_command, .mode = COMMAND_EXEC, - .help = "dump captured trace data ", + .help = "dump captured trace data to file", + .usage = "filename", }, { .name = "load", - .handler = &handle_etm_load_command, + .handler = handle_etm_load_command, .mode = COMMAND_EXEC, .help = "load trace data for analysis ", },