ETM: add "etm trigger_debug" command
[openocd.git] / src / target / etm.c
index f01f3666fbac29032a13892fc95d014181760875..d22bc4070a6bc8086fc4f628fd2449cf6c273618 100644 (file)
 #include "config.h"
 #endif
 
-#include "armv4_5.h"
+#include "arm.h"
+#include "etm.h"
 #include "etb.h"
 #include "image.h"
 #include "arm_disassembler.h"
+#include "register.h"
+#include "etm_dummy.h"
+
+#if BUILD_OOCD_TRACE == 1
+#include "oocd_trace.h"
+#endif
 
 
 /*
@@ -49,8 +56,6 @@
  *  ARM IHI 0014O ... Embedded Trace Macrocell, Architecture Specification
  */
 
-#define ARRAY_SIZE(x)  ((int)(sizeof(x)/sizeof((x)[0])))
-
 enum {
        RO,                             /* read/only */
        WO,                             /* write/only */
@@ -214,28 +219,28 @@ static const struct etm_reg_info etm_outputs[] = {
        { 0x6f, 32, RO, 0x20, "ETM_contextid_comparator_mask", }
 #endif
 
-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,
+static int etm_get_reg(struct reg *reg);
+static int etm_read_reg_w_check(struct reg *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 int etm_register_user_commands(struct command_context *cmd_ctx);
+static int etm_set_reg_w_exec(struct reg *reg, uint8_t *buf);
+static int etm_write_reg(struct reg *reg, uint32_t value);
 
+static const struct reg_arch_type etm_scan6_type = {
+       .get = etm_get_reg,
+       .set = etm_set_reg_w_exec,
+};
 
 /* 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)
+static struct reg *etm_reg_lookup(struct etm_context *etm_ctx, unsigned id)
 {
-       reg_cache_t *cache = etm_ctx->reg_cache;
-       int i;
+       struct reg_cache *cache = etm_ctx->reg_cache;
+       unsigned i;
 
        for (i = 0; i < cache->num_regs; i++) {
-               struct etm_reg_s *reg = cache->reg_list[i].arch_info;
+               struct etm_reg *reg = cache->reg_list[i].arch_info;
 
                if (reg->reg_info->addr == id)
                        return &cache->reg_list[i];
@@ -247,11 +252,11 @@ static reg_t *etm_reg_lookup(etm_context_t *etm_ctx, unsigned id)
        return NULL;
 }
 
-static void etm_reg_add(unsigned bcd_vers, arm_jtag_t *jtag_info,
-               reg_cache_t *cache, etm_reg_t *ereg,
+static void etm_reg_add(unsigned bcd_vers, struct arm_jtag *jtag_info,
+               struct reg_cache *cache, struct etm_reg *ereg,
                const struct etm_reg_info *r, unsigned nreg)
 {
-       reg_t *reg = cache->reg_list;
+       struct reg *reg = cache->reg_list;
 
        reg += cache->num_regs;
        ereg += cache->num_regs;
@@ -269,7 +274,7 @@ static void etm_reg_add(unsigned bcd_vers, arm_jtag_t *jtag_info,
                reg->size = r->size;
                reg->value = &ereg->value;
                reg->arch_info = ereg;
-               reg->arch_type = etm_reg_arch_type;
+               reg->type = &etm_scan6_type;
                reg++;
                cache->num_regs++;
 
@@ -279,22 +284,17 @@ static void etm_reg_add(unsigned bcd_vers, arm_jtag_t *jtag_info,
        }
 }
 
-reg_cache_t *etm_build_reg_cache(target_t *target,
-               arm_jtag_t *jtag_info, etm_context_t *etm_ctx)
+struct reg_cache *etm_build_reg_cache(struct target *target,
+               struct arm_jtag *jtag_info, struct etm_context *etm_ctx)
 {
-       reg_cache_t *reg_cache = malloc(sizeof(reg_cache_t));
-       reg_t *reg_list = NULL;
-       etm_reg_t *arch_info = NULL;
+       struct reg_cache *reg_cache = malloc(sizeof(struct reg_cache));
+       struct reg *reg_list = NULL;
+       struct etm_reg *arch_info = NULL;
        unsigned bcd_vers, config;
 
-       /* register a register arch-type for etm registers only once */
-       if (etm_reg_arch_type == -1)
-               etm_reg_arch_type = register_reg_arch_type(etm_get_reg,
-                               etm_set_reg_w_exec);
-
        /* the actual registers are kept in two arrays */
-       reg_list = calloc(128, sizeof(reg_t));
-       arch_info = calloc(128, sizeof(etm_reg_t));
+       reg_list = calloc(128, sizeof(struct reg));
+       arch_info = calloc(128, sizeof(struct etm_reg));
 
        /* fill in values for the reg cache */
        reg_cache->name = "etm registers";
@@ -349,10 +349,7 @@ reg_cache_t *etm_build_reg_cache(target_t *target,
                        break;
                default:
                        LOG_WARNING("Bad ETMv1 protocol %d", config >> 28);
-                       free(reg_cache);
-                       free(reg_list);
-                       free(arch_info);
-                       return ERROR_OK;
+                       goto fail;
                }
        }
        etm_ctx->bcd_vers = bcd_vers;
@@ -391,15 +388,12 @@ reg_cache_t *etm_build_reg_cache(target_t *target,
        /* the ETM might have an ETB connected */
        if (strcmp(etm_ctx->capture_driver->name, "etb") == 0)
        {
-               etb_t *etb = etm_ctx->capture_driver_priv;
+               struct etb *etb = etm_ctx->capture_driver_priv;
 
                if (!etb)
                {
                        LOG_ERROR("etb selected as etm capture driver, but no ETB configured");
-                       free(reg_cache);
-                       free(reg_list);
-                       free(arch_info);
-                       return ERROR_OK;
+                       goto fail;
                }
 
                reg_cache->next = etb_build_reg_cache(etb);
@@ -409,25 +403,31 @@ reg_cache_t *etm_build_reg_cache(target_t *target,
 
        etm_ctx->reg_cache = reg_cache;
        return reg_cache;
+
+fail:
+       free(reg_cache);
+       free(reg_list);
+       free(arch_info);
+       return NULL;
 }
 
-static int etm_read_reg(reg_t *reg)
+static int etm_read_reg(struct reg *reg)
 {
        return etm_read_reg_w_check(reg, NULL, NULL);
 }
 
-static int etm_store_reg(reg_t *reg)
+static int etm_store_reg(struct reg *reg)
 {
        return etm_write_reg(reg, buf_get_u32(reg->value, 0, reg->size));
 }
 
-int etm_setup(target_t *target)
+int etm_setup(struct target *target)
 {
        int retval;
        uint32_t etm_ctrl_value;
        struct arm *arm = target_to_arm(target);
-       etm_context_t *etm_ctx = arm->etm;
-       reg_t *etm_ctrl_reg;
+       struct etm_context *etm_ctx = arm->etm;
+       struct reg *etm_ctrl_reg;
 
        etm_ctrl_reg = etm_reg_lookup(etm_ctx, ETM_CTRL);
        if (!etm_ctrl_reg)
@@ -435,10 +435,10 @@ int etm_setup(target_t *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(target_t *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;
 
@@ -467,7 +470,7 @@ int etm_setup(target_t *target)
        return ERROR_OK;
 }
 
-static int etm_get_reg(reg_t *reg)
+static int etm_get_reg(struct reg *reg)
 {
        int retval;
 
@@ -486,13 +489,13 @@ static int etm_get_reg(reg_t *reg)
        return ERROR_OK;
 }
 
-static int etm_read_reg_w_check(reg_t *reg,
+static int etm_read_reg_w_check(struct reg *reg,
                uint8_t* check_value, uint8_t* check_mask)
 {
-       etm_reg_t *etm_reg = reg->arch_info;
+       struct etm_reg *etm_reg = reg->arch_info;
        const struct etm_reg_info *r = etm_reg->reg_info;
        uint8_t reg_addr = r->addr & 0x7f;
-       scan_field_t fields[3];
+       struct scan_field fields[3];
 
        if (etm_reg->reg_info->mode == WO) {
                LOG_ERROR("BUG: can't read write-only register %s", r->name);
@@ -542,7 +545,7 @@ static int etm_read_reg_w_check(reg_t *reg,
        return ERROR_OK;
 }
 
-static int etm_set_reg(reg_t *reg, uint32_t value)
+static int etm_set_reg(struct reg *reg, uint32_t value)
 {
        int retval;
 
@@ -559,7 +562,7 @@ static int etm_set_reg(reg_t *reg, uint32_t value)
        return ERROR_OK;
 }
 
-static int etm_set_reg_w_exec(reg_t *reg, uint8_t *buf)
+static int etm_set_reg_w_exec(struct reg *reg, uint8_t *buf)
 {
        int retval;
 
@@ -573,12 +576,12 @@ static int etm_set_reg_w_exec(reg_t *reg, uint8_t *buf)
        return ERROR_OK;
 }
 
-static int etm_write_reg(reg_t *reg, uint32_t value)
+static int etm_write_reg(struct reg *reg, uint32_t value)
 {
-       etm_reg_t *etm_reg = reg->arch_info;
+       struct etm_reg *etm_reg = reg->arch_info;
        const struct etm_reg_info *r = etm_reg->reg_info;
        uint8_t reg_addr = r->addr & 0x7f;
-       scan_field_t fields[3];
+       struct scan_field fields[3];
 
        if (etm_reg->reg_info->mode == RO) {
                LOG_ERROR("BUG: can't write read--only register %s", r->name);
@@ -618,15 +621,9 @@ static int etm_write_reg(reg_t *reg, uint32_t value)
 }
 
 
-/* ETM trace analysis functionality
- *
- */
-extern etm_capture_driver_t etm_dummy_capture_driver;
-#if BUILD_OOCD_TRACE == 1
-extern etm_capture_driver_t oocd_trace_capture_driver;
-#endif
+/* ETM trace analysis functionality */
 
-static etm_capture_driver_t *etm_capture_drivers[] =
+static struct etm_capture_driver *etm_capture_drivers[] =
 {
        &etb_capture_driver,
        &etm_dummy_capture_driver,
@@ -636,11 +633,11 @@ static etm_capture_driver_t *etm_capture_drivers[] =
        NULL
 };
 
-static int etm_read_instruction(etm_context_t *ctx, arm_instruction_t *instruction)
+static int etm_read_instruction(struct etm_context *ctx, struct arm_instruction *instruction)
 {
        int i;
        int section = -1;
-       uint32_t size_read;
+       size_t size_read;
        uint32_t opcode;
        int retval;
 
@@ -664,7 +661,7 @@ static int etm_read_instruction(etm_context_t *ctx, arm_instruction_t *instructi
                return ERROR_TRACE_INSTRUCTION_UNAVAILABLE;
        }
 
-       if (ctx->core_state == ARMV4_5_STATE_ARM)
+       if (ctx->core_state == ARM_STATE_ARM)
        {
                uint8_t buf[4];
                if ((retval = image_read_section(ctx->image, section,
@@ -677,7 +674,7 @@ static int etm_read_instruction(etm_context_t *ctx, arm_instruction_t *instructi
                opcode = target_buffer_get_u32(ctx->target, buf);
                arm_evaluate_opcode(opcode, ctx->current_pc, instruction);
        }
-       else if (ctx->core_state == ARMV4_5_STATE_THUMB)
+       else if (ctx->core_state == ARM_STATE_THUMB)
        {
                uint8_t buf[2];
                if ((retval = image_read_section(ctx->image, section,
@@ -690,7 +687,7 @@ static int etm_read_instruction(etm_context_t *ctx, arm_instruction_t *instructi
                opcode = target_buffer_get_u16(ctx->target, buf);
                thumb_evaluate_opcode(opcode, ctx->current_pc, instruction);
        }
-       else if (ctx->core_state == ARMV4_5_STATE_JAZELLE)
+       else if (ctx->core_state == ARM_STATE_JAZELLE)
        {
                LOG_ERROR("BUG: tracing of jazelle code not supported");
                return ERROR_FAIL;
@@ -704,7 +701,7 @@ static int etm_read_instruction(etm_context_t *ctx, arm_instruction_t *instructi
        return ERROR_OK;
 }
 
-static int etmv1_next_packet(etm_context_t *ctx, uint8_t *packet, int apo)
+static int etmv1_next_packet(struct etm_context *ctx, uint8_t *packet, int apo)
 {
        while (ctx->data_index < ctx->trace_depth)
        {
@@ -733,7 +730,8 @@ static int etmv1_next_packet(etm_context_t *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)
                        {
@@ -747,7 +745,7 @@ static int etmv1_next_packet(etm_context_t *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++;
@@ -769,7 +767,7 @@ static int etmv1_next_packet(etm_context_t *ctx, uint8_t *packet, int apo)
        return -1;
 }
 
-static int etmv1_branch_address(etm_context_t *ctx)
+static int etmv1_branch_address(struct etm_context *ctx)
 {
        int retval;
        uint8_t packet;
@@ -834,7 +832,7 @@ static int etmv1_branch_address(etm_context_t *ctx)
        /* if a full address was output, we might have branched into Jazelle state */
        if ((shift == 32) && (packet & 0x80))
        {
-               ctx->core_state = ARMV4_5_STATE_JAZELLE;
+               ctx->core_state = ARM_STATE_JAZELLE;
        }
        else
        {
@@ -842,12 +840,12 @@ static int etmv1_branch_address(etm_context_t *ctx)
                 * encoded in bit 0 of the branch target address */
                if (ctx->last_branch & 0x1)
                {
-                       ctx->core_state = ARMV4_5_STATE_THUMB;
+                       ctx->core_state = ARM_STATE_THUMB;
                        ctx->last_branch &= ~0x1;
                }
                else
                {
-                       ctx->core_state = ARMV4_5_STATE_ARM;
+                       ctx->core_state = ARM_STATE_ARM;
                        ctx->last_branch &= ~0x3;
                }
        }
@@ -855,7 +853,7 @@ static int etmv1_branch_address(etm_context_t *ctx)
        return 0;
 }
 
-static int etmv1_data(etm_context_t *ctx, int size, uint32_t *data)
+static int etmv1_data(struct etm_context *ctx, int size, uint32_t *data)
 {
        int j;
        uint8_t buf[4];
@@ -884,10 +882,10 @@ static int etmv1_data(etm_context_t *ctx, int size, uint32_t *data)
        return 0;
 }
 
-static int etmv1_analyze_trace(etm_context_t *ctx, struct command_context_s *cmd_ctx)
+static int etmv1_analyze_trace(struct etm_context *ctx, struct command_context *cmd_ctx)
 {
        int retval;
-       arm_instruction_t instruction;
+       struct arm_instruction instruction;
 
        /* read the trace data if it wasn't read already */
        if (ctx->trace_depth == 0)
@@ -1064,7 +1062,7 @@ static int etmv1_analyze_trace(etm_context_t *ctx, struct command_context_s *cmd
                                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;
@@ -1086,7 +1084,7 @@ static int etmv1_analyze_trace(etm_context_t *ctx, struct command_context_s *cmd
                                }
                        }
 
-                       if (ctx->tracemode & ETMV1_TRACE_DATA)
+                       if (ctx->control & ETM_CTRL_TRACE_DATA)
                        {
                                if ((instruction.type == ARM_LDM) || (instruction.type == ARM_STM))
                                {
@@ -1131,12 +1129,12 @@ static int etmv1_analyze_trace(etm_context_t *ctx, struct command_context_s *cmd
                        }
                        else
                        {
-                               next_pc += (ctx->core_state == ARMV4_5_STATE_ARM) ? 4 : 2;
+                               next_pc += (ctx->core_state == ARM_STATE_ARM) ? 4 : 2;
                        }
                }
                else if (pipestat == STAT_IN)
                {
-                       next_pc += (ctx->core_state == ARMV4_5_STATE_ARM) ? 4 : 2;
+                       next_pc += (ctx->core_state == ARM_STATE_ARM) ? 4 : 2;
                }
 
                if ((pipestat != STAT_TD) && (pipestat != STAT_WT))
@@ -1146,7 +1144,7 @@ static int etmv1_analyze_trace(etm_context_t *ctx, struct command_context_s *cmd
                        /* 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,
@@ -1176,67 +1174,56 @@ static int etmv1_analyze_trace(etm_context_t *ctx, struct command_context_s *cmd
        return ERROR_OK;
 }
 
-static int handle_etm_tracemode_command_update(
-               struct command_context_s *cmd_ctx,
-               char **args, etmv1_tracemode_t *mode)
+static COMMAND_HELPER(handle_etm_tracemode_command_update,
+               uint32_t *mode)
 {
-       etmv1_tracemode_t tracemode;
+       uint32_t tracemode;
 
        /* what parts of data access are traced? */
-       if (strcmp(args[0], "none") == 0)
-               tracemode = ETMV1_TRACE_NONE;
-       else if (strcmp(args[0], "data") == 0)
-               tracemode = ETMV1_TRACE_DATA;
-       else if (strcmp(args[0], "address") == 0)
-               tracemode = ETMV1_TRACE_ADDR;
-       else if (strcmp(args[0], "all") == 0)
-               tracemode = ETMV1_TRACE_DATA | ETMV1_TRACE_ADDR;
+       if (strcmp(CMD_ARGV[0], "none") == 0)
+               tracemode = 0;
+       else if (strcmp(CMD_ARGV[0], "data") == 0)
+               tracemode = ETM_CTRL_TRACE_DATA;
+       else if (strcmp(CMD_ARGV[0], "address") == 0)
+               tracemode = ETM_CTRL_TRACE_ADDR;
+       else if (strcmp(CMD_ARGV[0], "all") == 0)
+               tracemode = ETM_CTRL_TRACE_DATA | ETM_CTRL_TRACE_ADDR;
        else
        {
-               command_print(cmd_ctx, "invalid option '%s'", args[0]);
+               command_print(CMD_CTX, "invalid option '%s'", CMD_ARGV[0]);
                return ERROR_INVALID_ARGUMENTS;
        }
 
        uint8_t context_id;
-       COMMAND_PARSE_NUMBER(u8, args[1], context_id);
+       COMMAND_PARSE_NUMBER(u8, CMD_ARGV[1], context_id);
        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'", args[1]);
+               command_print(CMD_CTX, "invalid option '%s'", CMD_ARGV[1]);
                return ERROR_INVALID_ARGUMENTS;
        }
 
-       if (strcmp(args[2], "enable") == 0)
-               tracemode |= ETMV1_CYCLE_ACCURATE;
-       else if (strcmp(args[2], "disable") == 0)
-               tracemode |= 0;
-       else
-       {
-               command_print(cmd_ctx, "invalid option '%s'", args[2]);
-               return ERROR_INVALID_ARGUMENTS;
-       }
+       bool etmv1_cycle_accurate;
+       COMMAND_PARSE_ENABLE(CMD_ARGV[2], etmv1_cycle_accurate);
+       if (etmv1_cycle_accurate)
+               tracemode |= ETM_CTRL_CYCLE_ACCURATE;
 
-       if (strcmp(args[3], "enable") == 0)
-               tracemode |= ETMV1_BRANCH_OUTPUT;
-       else if (strcmp(args[3], "disable") == 0)
-               tracemode |= 0;
-       else
-       {
-               command_print(cmd_ctx, "invalid option '%s'", args[3]);
-               return ERROR_INVALID_ARGUMENTS;
-       }
+       bool etmv1_branch_output;
+       COMMAND_PARSE_ENABLE(CMD_ARGV[3], etmv1_branch_output);
+       if (etmv1_branch_output)
+               tracemode |= ETM_CTRL_BRANCH_OUTPUT;
 
        /* IGNORED:
         *  - CPRT tracing (coprocessor register transfers)
@@ -1248,35 +1235,34 @@ static int handle_etm_tracemode_command_update(
        return ERROR_OK;
 }
 
-static int handle_etm_tracemode_command(struct command_context_s *cmd_ctx,
-               char *cmd, char **args, int argc)
+COMMAND_HANDLER(handle_etm_tracemode_command)
 {
-       target_t *target = get_current_target(cmd_ctx);
+       struct target *target = get_current_target(CMD_CTX);
        struct arm *arm = target_to_arm(target);
-       struct etm *etm;
+       struct etm_context *etm;
 
        if (!is_arm(arm)) {
-               command_print(cmd_ctx, "ETM: current target isn't an ARM");
+               command_print(CMD_CTX, "ETM: current target isn't an ARM");
                return ERROR_FAIL;
        }
 
        etm = arm->etm;
        if (!etm) {
-               command_print(cmd_ctx, "current target doesn't have an ETM configured");
+               command_print(CMD_CTX, "current target doesn't have an ETM configured");
                return ERROR_FAIL;
        }
 
-       etmv1_tracemode_t tracemode = etm->tracemode;
+       uint32_t tracemode = etm->control;
 
-       switch (argc)
+       switch (CMD_ARGC)
        {
        case 0:
                break;
        case 4:
-               handle_etm_tracemode_command_update(cmd_ctx, args, &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: configure trace mode "
                                "<none | data | address | all> "
                                "<context id bits> <cycle accurate> <branch output>");
                return ERROR_FAIL;
@@ -1287,77 +1273,80 @@ static int handle_etm_tracemode_command(struct command_context_s *cmd_ctx,
         * or couldn't be written; display actual hardware state...
         */
 
-       command_print(cmd_ctx, "current tracemode configuration:");
+       command_print(CMD_CTX, "current tracemode configuration:");
 
-       switch (tracemode & ETMV1_TRACE_MASK)
+       switch (tracemode & ETM_CTRL_TRACE_MASK)
        {
-               case ETMV1_TRACE_NONE:
-                       command_print(cmd_ctx, "data tracing: none");
+               default:
+                       command_print(CMD_CTX, "data tracing: none");
                        break;
-               case ETMV1_TRACE_DATA:
-                       command_print(cmd_ctx, "data tracing: data only");
+               case ETM_CTRL_TRACE_DATA:
+                       command_print(CMD_CTX, "data tracing: data only");
                        break;
-               case ETMV1_TRACE_ADDR:
-                       command_print(cmd_ctx, "data tracing: address only");
+               case ETM_CTRL_TRACE_ADDR:
+                       command_print(CMD_CTX, "data tracing: address only");
                        break;
-               case ETMV1_TRACE_DATA | ETMV1_TRACE_ADDR:
-                       command_print(cmd_ctx, "data tracing: address and data");
+               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:
-                       command_print(cmd_ctx, "contextid tracing: none");
+               case ETM_CTRL_CONTEXTID_NONE:
+                       command_print(CMD_CTX, "contextid tracing: none");
                        break;
-               case ETMV1_CONTEXTID_8:
-                       command_print(cmd_ctx, "contextid tracing: 8 bit");
+               case ETM_CTRL_CONTEXTID_8:
+                       command_print(CMD_CTX, "contextid tracing: 8 bit");
                        break;
-               case ETMV1_CONTEXTID_16:
-                       command_print(cmd_ctx, "contextid tracing: 16 bit");
+               case ETM_CTRL_CONTEXTID_16:
+                       command_print(CMD_CTX, "contextid tracing: 16 bit");
                        break;
-               case ETMV1_CONTEXTID_32:
-                       command_print(cmd_ctx, "contextid tracing: 32 bit");
+               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");
+               command_print(CMD_CTX, "cycle-accurate tracing enabled");
        }
        else
        {
-               command_print(cmd_ctx, "cycle-accurate tracing disabled");
+               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");
+               command_print(CMD_CTX, "full branch address output enabled");
        }
        else
        {
-               command_print(cmd_ctx, "full branch address output disabled");
+               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)
        {
-               reg_t *etm_ctrl_reg;
+               struct reg *etm_ctrl_reg;
 
                etm_ctrl_reg = etm_reg_lookup(etm, ETM_CTRL);
                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)
@@ -1368,32 +1357,34 @@ static int handle_etm_tracemode_command(struct command_context_s *cmd_ctx,
                etm->trace_depth = 0;
        }
 
+#undef TRACEMODE_MASK
+
        return ERROR_OK;
 }
 
-static int handle_etm_config_command(struct command_context_s *cmd_ctx,
-               char *cmd, char **args, int argc)
+COMMAND_HANDLER(handle_etm_config_command)
 {
-       target_t *target;
+       struct target *target;
        struct arm *arm;
-       etm_portmode_t portmode = 0x0;
-       struct etm *etm_ctx;
+       uint32_t portmode = 0x0;
+       struct etm_context *etm_ctx;
        int i;
 
-       if (argc != 5)
+       if (CMD_ARGC != 5)
                return ERROR_COMMAND_SYNTAX_ERROR;
 
-       target = get_target(args[0]);
+       target = get_target(CMD_ARGV[0]);
        if (!target)
        {
-               LOG_ERROR("target '%s' not defined", args[0]);
+               LOG_ERROR("target '%s' not defined", CMD_ARGV[0]);
                return ERROR_FAIL;
        }
 
        arm = target_to_arm(target);
        if (!is_arm(arm)) {
-               command_print(cmd_ctx, "target '%s' is '%s'; not an ARM",
-                               target->cmd_name, target_get_name(target));
+               command_print(CMD_CTX, "target '%s' is '%s'; not an ARM",
+                               target_name(target),
+                               target_type_name(target));
                return ERROR_FAIL;
        }
 
@@ -1410,7 +1401,7 @@ static int handle_etm_config_command(struct command_context_s *cmd_ctx,
         *    "normal full" ...
         */
        uint8_t port_width;
-       COMMAND_PARSE_NUMBER(u8, args[1], port_width);
+       COMMAND_PARSE_NUMBER(u8, CMD_ARGV[1], port_width);
        switch (port_width)
        {
                /* before ETMv3.0 */
@@ -1443,44 +1434,44 @@ static int handle_etm_config_command(struct command_context_s *cmd_ctx,
                        portmode |= ETM_PORT_2BIT;
                        break;
                default:
-                       command_print(cmd_ctx,
-                               "unsupported ETM port width '%s'", args[1]);
+                       command_print(CMD_CTX,
+                               "unsupported ETM port width '%s'", CMD_ARGV[1]);
                        return ERROR_FAIL;
        }
 
-       if (strcmp("normal", args[2]) == 0)
+       if (strcmp("normal", CMD_ARGV[2]) == 0)
        {
                portmode |= ETM_PORT_NORMAL;
        }
-       else if (strcmp("multiplexed", args[2]) == 0)
+       else if (strcmp("multiplexed", CMD_ARGV[2]) == 0)
        {
                portmode |= ETM_PORT_MUXED;
        }
-       else if (strcmp("demultiplexed", args[2]) == 0)
+       else if (strcmp("demultiplexed", CMD_ARGV[2]) == 0)
        {
                portmode |= ETM_PORT_DEMUXED;
        }
        else
        {
-               command_print(cmd_ctx, "unsupported ETM port mode '%s', must be 'normal', 'multiplexed' or 'demultiplexed'", args[2]);
+               command_print(CMD_CTX, "unsupported ETM port mode '%s', must be 'normal', 'multiplexed' or 'demultiplexed'", CMD_ARGV[2]);
                return ERROR_FAIL;
        }
 
-       if (strcmp("half", args[3]) == 0)
+       if (strcmp("half", CMD_ARGV[3]) == 0)
        {
                portmode |= ETM_PORT_HALF_CLOCK;
        }
-       else if (strcmp("full", args[3]) == 0)
+       else if (strcmp("full", CMD_ARGV[3]) == 0)
        {
                portmode |= ETM_PORT_FULL_CLOCK;
        }
        else
        {
-               command_print(cmd_ctx, "unsupported ETM port clocking '%s', must be 'full' or 'half'", args[3]);
+               command_print(CMD_CTX, "unsupported ETM port clocking '%s', must be 'full' or 'half'", CMD_ARGV[3]);
                return ERROR_FAIL;
        }
 
-       etm_ctx = calloc(1, sizeof(etm_context_t));
+       etm_ctx = calloc(1, sizeof(struct etm_context));
        if (!etm_ctx) {
                LOG_DEBUG("out of memory");
                return ERROR_FAIL;
@@ -1488,10 +1479,11 @@ static int handle_etm_config_command(struct command_context_s *cmd_ctx,
 
        for (i = 0; etm_capture_drivers[i]; i++)
        {
-               if (strcmp(args[4], etm_capture_drivers[i]->name) == 0)
+               if (strcmp(CMD_ARGV[4], etm_capture_drivers[i]->name) == 0)
                {
-                       int retval;
-                       if ((retval = etm_capture_drivers[i]->register_commands(cmd_ctx)) != ERROR_OK)
+                       int retval = register_commands(CMD_CTX, NULL,
+                                       etm_capture_drivers[i]->commands);
+                       if (ERROR_OK != retval)
                        {
                                free(etm_ctx);
                                return retval;
@@ -1507,74 +1499,72 @@ static int handle_etm_config_command(struct command_context_s *cmd_ctx,
        {
                /* no supported capture driver found, don't register an ETM */
                free(etm_ctx);
-               LOG_ERROR("trace capture driver '%s' not found", args[4]);
+               LOG_ERROR("trace capture driver '%s' not found", CMD_ARGV[4]);
                return ERROR_FAIL;
        }
 
        etm_ctx->target = target;
-       etm_ctx->trigger_percent = 50;
        etm_ctx->trace_data = NULL;
-       etm_ctx->portmode = portmode;
-       etm_ctx->core_state = ARMV4_5_STATE_ARM;
+       etm_ctx->control = portmode;
+       etm_ctx->core_state = ARM_STATE_ARM;
 
        arm->etm = etm_ctx;
 
-       return etm_register_user_commands(cmd_ctx);
+       return etm_register_user_commands(CMD_CTX);
 }
 
-static int handle_etm_info_command(struct command_context_s *cmd_ctx,
-               char *cmd, char **args, int argc)
+COMMAND_HANDLER(handle_etm_info_command)
 {
-       target_t *target;
+       struct target *target;
        struct arm *arm;
-       etm_context_t *etm;
-       reg_t *etm_sys_config_reg;
+       struct etm_context *etm;
+       struct reg *etm_sys_config_reg;
        int max_port_size;
        uint32_t config;
 
-       target = get_current_target(cmd_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");
+               command_print(CMD_CTX, "ETM: current target isn't an ARM");
                return ERROR_FAIL;
        }
 
        etm = arm->etm;
        if (!etm)
        {
-               command_print(cmd_ctx, "current target doesn't have an ETM configured");
+               command_print(CMD_CTX, "current target doesn't have an ETM configured");
                return ERROR_FAIL;
        }
 
-       command_print(cmd_ctx, "ETM v%d.%d",
+       command_print(CMD_CTX, "ETM v%d.%d",
                        etm->bcd_vers >> 4, etm->bcd_vers & 0xf);
-       command_print(cmd_ctx, "pairs of address comparators: %i",
+       command_print(CMD_CTX, "pairs of address comparators: %i",
                        (int) (etm->config >> 0) & 0x0f);
-       command_print(cmd_ctx, "data comparators: %i",
+       command_print(CMD_CTX, "data comparators: %i",
                        (int) (etm->config >> 4) & 0x0f);
-       command_print(cmd_ctx, "memory map decoders: %i",
+       command_print(CMD_CTX, "memory map decoders: %i",
                        (int) (etm->config >> 8) & 0x1f);
-       command_print(cmd_ctx, "number of counters: %i",
+       command_print(CMD_CTX, "number of counters: %i",
                        (int) (etm->config >> 13) & 0x07);
-       command_print(cmd_ctx, "sequencer %spresent",
+       command_print(CMD_CTX, "sequencer %spresent",
                        (int) (etm->config & (1 << 16)) ? "" : "not ");
-       command_print(cmd_ctx, "number of ext. inputs: %i",
+       command_print(CMD_CTX, "number of ext. inputs: %i",
                        (int) (etm->config >> 17) & 0x07);
-       command_print(cmd_ctx, "number of ext. outputs: %i",
+       command_print(CMD_CTX, "number of ext. outputs: %i",
                        (int) (etm->config >> 20) & 0x07);
-       command_print(cmd_ctx, "FIFO full %spresent",
+       command_print(CMD_CTX, "FIFO full %spresent",
                        (int) (etm->config & (1 << 23)) ? "" : "not ");
        if (etm->bcd_vers < 0x20)
-               command_print(cmd_ctx, "protocol version: %i",
+               command_print(CMD_CTX, "protocol version: %i",
                                (int) (etm->config >> 28) & 0x07);
        else {
-               command_print(cmd_ctx,
+               command_print(CMD_CTX,
                                "coprocessor and memory access %ssupported",
                                (etm->config & (1 << 26)) ? "" : "not ");
-               command_print(cmd_ctx, "trace start/stop %spresent",
+               command_print(CMD_CTX, "trace start/stop %spresent",
                                (etm->config & (1 << 26)) ? "" : "not ");
-               command_print(cmd_ctx, "number of context comparators: %i",
+               command_print(CMD_CTX, "number of context comparators: %i",
                                (int) (etm->config >> 24) & 0x03);
        }
 
@@ -1626,61 +1616,60 @@ static int handle_etm_info_command(struct command_context_s *cmd_ctx,
                        LOG_ERROR("Illegal max_port_size");
                        return ERROR_FAIL;
        }
-       command_print(cmd_ctx, "max. port size: %i", max_port_size);
+       command_print(CMD_CTX, "max. port size: %i", max_port_size);
 
        if (etm->bcd_vers < 0x30) {
-               command_print(cmd_ctx, "half-rate clocking %ssupported",
+               command_print(CMD_CTX, "half-rate clocking %ssupported",
                                (config & (1 << 3)) ? "" : "not ");
-               command_print(cmd_ctx, "full-rate clocking %ssupported",
+               command_print(CMD_CTX, "full-rate clocking %ssupported",
                                (config & (1 << 4)) ? "" : "not ");
-               command_print(cmd_ctx, "normal trace format %ssupported",
+               command_print(CMD_CTX, "normal trace format %ssupported",
                                (config & (1 << 5)) ? "" : "not ");
-               command_print(cmd_ctx, "multiplex trace format %ssupported",
+               command_print(CMD_CTX, "multiplex trace format %ssupported",
                                (config & (1 << 6)) ? "" : "not ");
-               command_print(cmd_ctx, "demultiplex trace format %ssupported",
+               command_print(CMD_CTX, "demultiplex trace format %ssupported",
                                (config & (1 << 7)) ? "" : "not ");
        } else {
                /* REVISIT show which size and format are selected ... */
-               command_print(cmd_ctx, "current port size %ssupported",
+               command_print(CMD_CTX, "current port size %ssupported",
                                (config & (1 << 10)) ? "" : "not ");
-               command_print(cmd_ctx, "current trace format %ssupported",
+               command_print(CMD_CTX, "current trace format %ssupported",
                                (config & (1 << 11)) ? "" : "not ");
        }
        if (etm->bcd_vers >= 0x21)
-               command_print(cmd_ctx, "fetch comparisons %ssupported",
+               command_print(CMD_CTX, "fetch comparisons %ssupported",
                                (config & (1 << 17)) ? "not " : "");
-       command_print(cmd_ctx, "FIFO full %ssupported",
+       command_print(CMD_CTX, "FIFO full %ssupported",
                        (config & (1 << 8)) ? "" : "not ");
 
        return ERROR_OK;
 }
 
-static int handle_etm_status_command(struct command_context_s *cmd_ctx,
-               char *cmd, char **args, int argc)
+COMMAND_HANDLER(handle_etm_status_command)
 {
-       target_t *target;
+       struct target *target;
        struct arm *arm;
-       etm_context_t *etm;
+       struct etm_context *etm;
        trace_status_t trace_status;
 
-       target = get_current_target(cmd_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");
+               command_print(CMD_CTX, "ETM: current target isn't an ARM");
                return ERROR_FAIL;
        }
 
        etm = arm->etm;
        if (!etm)
        {
-               command_print(cmd_ctx, "current target doesn't have an ETM configured");
+               command_print(CMD_CTX, "current target doesn't have an ETM configured");
                return ERROR_FAIL;
        }
 
        /* ETM status */
        if (etm->bcd_vers >= 0x11) {
-               reg_t *reg;
+               struct reg *reg;
 
                reg = etm_reg_lookup(etm, ETM_STATUS);
                if (!reg)
@@ -1688,7 +1677,7 @@ static int handle_etm_status_command(struct command_context_s *cmd_ctx,
                if (etm_get_reg(reg) == ERROR_OK) {
                        unsigned s = buf_get_u32(reg->value, 0, reg->size);
 
-                       command_print(cmd_ctx, "etm: %s%s%s%s",
+                       command_print(CMD_CTX, "etm: %s%s%s%s",
                                /* bit(1) == progbit */
                                (etm->bcd_vers >= 0x12)
                                        ? ((s & (1 << 1))
@@ -1707,7 +1696,7 @@ static int handle_etm_status_command(struct command_context_s *cmd_ctx,
        trace_status = etm->capture_driver->status(etm);
        if (trace_status == TRACE_IDLE)
        {
-               command_print(cmd_ctx, "%s: idle", etm->capture_driver->name);
+               command_print(CMD_CTX, "%s: idle", etm->capture_driver->name);
        }
        else
        {
@@ -1716,7 +1705,7 @@ static int handle_etm_status_command(struct command_context_s *cmd_ctx,
                static char *overflowed = ", overflowed";
                static char *triggered = ", triggered";
 
-               command_print(cmd_ctx, "%s: trace collection%s%s%s",
+               command_print(CMD_CTX, "%s: trace collection%s%s%s",
                        etm->capture_driver->name,
                        (trace_status & TRACE_RUNNING) ? running : completed,
                        (trace_status & TRACE_OVERFLOWED) ? overflowed : "",
@@ -1724,7 +1713,7 @@ static int handle_etm_status_command(struct command_context_s *cmd_ctx,
 
                if (etm->trace_depth > 0)
                {
-                       command_print(cmd_ctx, "%i frames of trace data read",
+                       command_print(CMD_CTX, "%i frames of trace data read",
                                        (int)(etm->trace_depth));
                }
        }
@@ -1732,31 +1721,30 @@ static int handle_etm_status_command(struct command_context_s *cmd_ctx,
        return ERROR_OK;
 }
 
-static int handle_etm_image_command(struct command_context_s *cmd_ctx,
-               char *cmd, char **args, int argc)
+COMMAND_HANDLER(handle_etm_image_command)
 {
-       target_t *target;
+       struct target *target;
        struct arm *arm;
-       etm_context_t *etm_ctx;
+       struct etm_context *etm_ctx;
 
-       if (argc < 1)
+       if (CMD_ARGC < 1)
        {
-               command_print(cmd_ctx, "usage: etm image <file> [base address] [type]");
+               command_print(CMD_CTX, "usage: etm image <file> [base address] [type]");
                return ERROR_FAIL;
        }
 
-       target = get_current_target(cmd_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");
+               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");
+               command_print(CMD_CTX, "current target doesn't have an ETM configured");
                return ERROR_FAIL;
        }
 
@@ -1764,25 +1752,25 @@ static int handle_etm_image_command(struct command_context_s *cmd_ctx,
        {
                image_close(etm_ctx->image);
                free(etm_ctx->image);
-               command_print(cmd_ctx, "previously loaded image found and closed");
+               command_print(CMD_CTX, "previously loaded image found and closed");
        }
 
-       etm_ctx->image = malloc(sizeof(image_t));
+       etm_ctx->image = malloc(sizeof(struct image));
        etm_ctx->image->base_address_set = 0;
        etm_ctx->image->start_address_set = 0;
 
        /* a base address isn't always necessary, default to 0x0 (i.e. don't relocate) */
-       if (argc >= 2)
+       if (CMD_ARGC >= 2)
        {
                etm_ctx->image->base_address_set = 1;
-               COMMAND_PARSE_NUMBER(int, args[1], etm_ctx->image->base_address);
+               COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], etm_ctx->image->base_address);
        }
        else
        {
                etm_ctx->image->base_address_set = 0;
        }
 
-       if (image_open(etm_ctx->image, args[0], (argc >= 3) ? args[2] : NULL) != ERROR_OK)
+       if (image_open(etm_ctx->image, CMD_ARGV[0], (CMD_ARGC >= 3) ? CMD_ARGV[2] : NULL) != ERROR_OK)
        {
                free(etm_ctx->image);
                etm_ctx->image = NULL;
@@ -1792,46 +1780,45 @@ static int handle_etm_image_command(struct command_context_s *cmd_ctx,
        return ERROR_OK;
 }
 
-static int handle_etm_dump_command(struct command_context_s *cmd_ctx,
-               char *cmd, char **args, int argc)
+COMMAND_HANDLER(handle_etm_dump_command)
 {
-       fileio_t file;
-       target_t *target;
+       struct fileio file;
+       struct target *target;
        struct arm *arm;
-       etm_context_t *etm_ctx;
+       struct etm_context *etm_ctx;
        uint32_t i;
 
-       if (argc != 1)
+       if (CMD_ARGC != 1)
        {
-               command_print(cmd_ctx, "usage: etm dump <file>");
+               command_print(CMD_CTX, "usage: etm dump <file>");
                return ERROR_FAIL;
        }
 
-       target = get_current_target(cmd_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");
+               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");
+               command_print(CMD_CTX, "current target doesn't have an ETM configured");
                return ERROR_FAIL;
        }
 
        if (etm_ctx->capture_driver->status == TRACE_IDLE)
        {
-               command_print(cmd_ctx, "trace capture wasn't enabled, no trace data captured");
+               command_print(CMD_CTX, "trace capture wasn't enabled, no trace data captured");
                return ERROR_OK;
        }
 
        if (etm_ctx->capture_driver->status(etm_ctx) & TRACE_RUNNING)
        {
                /* TODO: if on-the-fly capture is to be supported, this needs to be changed */
-               command_print(cmd_ctx, "trace capture not completed");
+               command_print(CMD_CTX, "trace capture not completed");
                return ERROR_FAIL;
        }
 
@@ -1839,14 +1826,13 @@ static int handle_etm_dump_command(struct command_context_s *cmd_ctx,
        if (etm_ctx->trace_depth == 0)
                etm_ctx->capture_driver->read_trace(etm_ctx);
 
-       if (fileio_open(&file, args[0], FILEIO_WRITE, FILEIO_BINARY) != ERROR_OK)
+       if (fileio_open(&file, CMD_ARGV[0], FILEIO_WRITE, FILEIO_BINARY) != ERROR_OK)
        {
                return ERROR_FAIL;
        }
 
        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++)
@@ -1861,50 +1847,49 @@ static int handle_etm_dump_command(struct command_context_s *cmd_ctx,
        return ERROR_OK;
 }
 
-static int handle_etm_load_command(struct command_context_s *cmd_ctx,
-               char *cmd, char **args, int argc)
+COMMAND_HANDLER(handle_etm_load_command)
 {
-       fileio_t file;
-       target_t *target;
+       struct fileio file;
+       struct target *target;
        struct arm *arm;
-       etm_context_t *etm_ctx;
+       struct etm_context *etm_ctx;
        uint32_t i;
 
-       if (argc != 1)
+       if (CMD_ARGC != 1)
        {
-               command_print(cmd_ctx, "usage: etm load <file>");
+               command_print(CMD_CTX, "usage: etm load <file>");
                return ERROR_FAIL;
        }
 
-       target = get_current_target(cmd_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");
+               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");
+               command_print(CMD_CTX, "current target doesn't have an ETM configured");
                return ERROR_FAIL;
        }
 
        if (etm_ctx->capture_driver->status(etm_ctx) & TRACE_RUNNING)
        {
-               command_print(cmd_ctx, "trace capture running, stop first");
+               command_print(CMD_CTX, "trace capture running, stop first");
                return ERROR_FAIL;
        }
 
-       if (fileio_open(&file, args[0], FILEIO_READ, FILEIO_BINARY) != ERROR_OK)
+       if (fileio_open(&file, CMD_ARGV[0], FILEIO_READ, FILEIO_BINARY) != ERROR_OK)
        {
                return ERROR_FAIL;
        }
 
        if (file.size % 4)
        {
-               command_print(cmd_ctx, "size isn't a multiple of 4, no valid trace data");
+               command_print(CMD_CTX, "size isn't a multiple of 4, no valid trace data");
                fileio_close(&file);
                return ERROR_FAIL;
        }
@@ -1918,14 +1903,13 @@ static int handle_etm_load_command(struct command_context_s *cmd_ctx,
        {
          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(etmv1_trace_data_t) * etm_ctx->trace_depth);
+       etm_ctx->trace_data = malloc(sizeof(struct etmv1_trace_data) * etm_ctx->trace_depth);
        if (etm_ctx->trace_data == NULL)
        {
-               command_print(cmd_ctx, "not enough memory to perform operation");
+               command_print(CMD_CTX, "not enough memory to perform operation");
                fileio_close(&file);
                return ERROR_FAIL;
        }
@@ -1946,68 +1930,25 @@ static int handle_etm_load_command(struct command_context_s *cmd_ctx,
        return ERROR_OK;
 }
 
-static int handle_etm_trigger_percent_command(struct command_context_s *cmd_ctx,
-               char *cmd, char **args, int argc)
-{
-       target_t *target;
-       struct arm *arm;
-       etm_context_t *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 (argc > 0)
-       {
-               uint32_t new_value;
-               COMMAND_PARSE_NUMBER(u32, args[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;
-}
-
-static int handle_etm_start_command(struct command_context_s *cmd_ctx,
-               char *cmd, char **args, int argc)
+COMMAND_HANDLER(handle_etm_start_command)
 {
-       target_t *target;
+       struct target *target;
        struct arm *arm;
-       etm_context_t *etm_ctx;
-       reg_t *etm_ctrl_reg;
+       struct etm_context *etm_ctx;
+       struct reg *etm_ctrl_reg;
 
-       target = get_current_target(cmd_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");
+               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");
+               command_print(CMD_CTX, "current target doesn't have an ETM configured");
                return ERROR_FAIL;
        }
 
@@ -2037,26 +1978,25 @@ static int handle_etm_start_command(struct command_context_s *cmd_ctx,
        return ERROR_OK;
 }
 
-static int handle_etm_stop_command(struct command_context_s *cmd_ctx,
-               char *cmd, char **args, int argc)
+COMMAND_HANDLER(handle_etm_stop_command)
 {
-       target_t *target;
+       struct target *target;
        struct arm *arm;
-       etm_context_t *etm_ctx;
-       reg_t *etm_ctrl_reg;
+       struct etm_context *etm_ctx;
+       struct reg *etm_ctrl_reg;
 
-       target = get_current_target(cmd_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");
+               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");
+               command_print(CMD_CTX, "current target doesn't have an ETM configured");
                return ERROR_FAIL;
        }
 
@@ -2077,89 +2017,187 @@ static int handle_etm_stop_command(struct command_context_s *cmd_ctx,
        return ERROR_OK;
 }
 
-static int handle_etm_analyze_command(struct command_context_s *cmd_ctx,
-               char *cmd, char **args, int argc)
+COMMAND_HANDLER(handle_etm_trigger_debug_command)
 {
-       target_t *target;
+       struct target *target;
        struct arm *arm;
-       etm_context_t *etm_ctx;
+       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;
+       struct arm *arm;
+       struct etm_context *etm_ctx;
        int retval;
 
-       target = get_current_target(cmd_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");
+               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");
+               command_print(CMD_CTX, "current target doesn't have an ETM configured");
                return ERROR_FAIL;
        }
 
-       if ((retval = etmv1_analyze_trace(etm_ctx, cmd_ctx)) != ERROR_OK)
+       if ((retval = etmv1_analyze_trace(etm_ctx, CMD_CTX)) != ERROR_OK)
        {
                switch (retval)
                {
                        case ERROR_ETM_ANALYSIS_FAILED:
-                               command_print(cmd_ctx, "further analysis failed (corrupted trace data or just end of data");
+                               command_print(CMD_CTX, "further analysis failed (corrupted trace data or just end of data");
                                break;
                        case ERROR_TRACE_INSTRUCTION_UNAVAILABLE:
-                               command_print(cmd_ctx, "no instruction for current address available, analysis aborted");
+                               command_print(CMD_CTX, "no instruction for current address available, analysis aborted");
                                break;
                        case ERROR_TRACE_IMAGE_UNAVAILABLE:
-                               command_print(cmd_ctx, "no image available for trace analysis");
+                               command_print(CMD_CTX, "no image available for trace analysis");
                                break;
                        default:
-                               command_print(cmd_ctx, "unknown error: %i", retval);
+                               command_print(CMD_CTX, "unknown error: %i", retval);
                }
        }
 
        return retval;
 }
 
-int etm_register_commands(struct command_context_s *cmd_ctx)
-{
-       etm_cmd = register_command(cmd_ctx, NULL, "etm", NULL, COMMAND_ANY, "Embedded Trace Macrocell");
-
-       register_command(cmd_ctx, etm_cmd, "config", handle_etm_config_command,
-               COMMAND_CONFIG, "etm config <target> <port_width> <port_mode> <clocking> <capture_driver>");
+static const struct command_registration etm_config_command_handlers[] = {
+       {
+               .name = "config",
+               .handler = &handle_etm_config_command,
+               .mode = COMMAND_CONFIG,
+               .usage = "<target> <port_width> <port_mode> "
+                       "<clocking> <capture_driver>",
+       },
+       COMMAND_REGISTRATION_DONE
+};
+const struct command_registration etm_command_handlers[] = {
+       {
+               .name = "etm",
+               .mode = COMMAND_ANY,
+               .help = "Emebdded Trace Macrocell command group",
+               .chain = etm_config_command_handlers,
+       },
+       COMMAND_REGISTRATION_DONE
+};
 
-       return ERROR_OK;
-}
+static const struct command_registration etm_exec_command_handlers[] = {
+       {
+               .name = "tracemode", handle_etm_tracemode_command,
+               .mode = COMMAND_EXEC,
+               .help = "configure/display trace mode",
+               .usage = "<none | data | address | all> "
+                       "<context_id_bits> <cycle_accurate> <branch_output>",
+       },
+       {
+               .name = "info",
+               .handler = &handle_etm_info_command,
+               .mode = COMMAND_EXEC,
+               .help = "display info about the current target's ETM",
+       },
+       {
+               .name = "status",
+               .handler = &handle_etm_status_command,
+               .mode = COMMAND_EXEC,
+               .help = "display current target's ETM status",
+       },
+       {
+               .name = "start",
+               .handler = &handle_etm_start_command,
+               .mode = COMMAND_EXEC,
+               .help = "start ETM trace collection",
+       },
+       {
+               .name = "stop",
+               .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,
+               .mode = COMMAND_EXEC,
+               .help = "analyze collected ETM trace",
+       },
+       {
+               .name = "image",
+               .handler = &handle_etm_image_command,
+               .mode = COMMAND_EXEC,
+               .help = "load image from <file> [base address]",
+       },
+       {
+               .name = "dump",
+               .handler = &handle_etm_dump_command,
+               .mode = COMMAND_EXEC,
+               .help = "dump captured trace data <file>",
+       },
+       {
+               .name = "load",
+               .handler = &handle_etm_load_command,
+               .mode = COMMAND_EXEC,
+               .help = "load trace data for analysis <file>",
+       },
+       COMMAND_REGISTRATION_DONE
+};
 
-static int etm_register_user_commands(struct command_context_s *cmd_ctx)
+static int etm_register_user_commands(struct command_context *cmd_ctx)
 {
-       register_command(cmd_ctx, etm_cmd, "tracemode", handle_etm_tracemode_command,
-               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,
-               COMMAND_EXEC, "display info about the current target's ETM");
-
-       register_command(cmd_ctx, etm_cmd, "trigger_percent", handle_etm_trigger_percent_command,
-               COMMAND_EXEC, "amount (<percent>) of trace buffer to be filled after the trigger occured");
-       register_command(cmd_ctx, etm_cmd, "status", handle_etm_status_command,
-               COMMAND_EXEC, "display current target's ETM status");
-       register_command(cmd_ctx, etm_cmd, "start", handle_etm_start_command,
-               COMMAND_EXEC, "start ETM trace collection");
-       register_command(cmd_ctx, etm_cmd, "stop", handle_etm_stop_command,
-               COMMAND_EXEC, "stop ETM trace collection");
-
-       register_command(cmd_ctx, etm_cmd, "analyze", handle_etm_analyze_command,
-               COMMAND_EXEC, "anaylze collected ETM trace");
-
-       register_command(cmd_ctx, etm_cmd, "image", handle_etm_image_command,
-               COMMAND_EXEC, "load image from <file> [base address]");
-
-       register_command(cmd_ctx, etm_cmd, "dump", handle_etm_dump_command,
-               COMMAND_EXEC, "dump captured trace data <file>");
-       register_command(cmd_ctx, etm_cmd, "load", handle_etm_load_command,
-               COMMAND_EXEC, "load trace data for analysis <file>");
-
-       return ERROR_OK;
+       struct command *etm_cmd = command_find_in_context(cmd_ctx, "etm");
+       return register_commands(cmd_ctx, etm_cmd, etm_exec_command_handlers);
 }

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)