- add missing svn props
[fw/openocd] / src / target / etm.c
index dd6e6025d2f9075dc27568d39f443da34026cf79..8e39a4f634d6af8eb05785973375756ca68c1c99 100644 (file)
@@ -223,7 +223,6 @@ reg_cache_t* etm_build_reg_cache(target_t *target, arm_jtag_t *jtag_info, etm_co
        etm_reg_t *arch_info = NULL;
        int num_regs = sizeof(etm_reg_arch_info)/sizeof(int);
        int i;
-       u32 etm_ctrl_value;
        
        /* register a register arch-type for etm registers only once */
        if (etm_reg_arch_type == -1)
@@ -256,21 +255,6 @@ reg_cache_t* etm_build_reg_cache(target_t *target, arm_jtag_t *jtag_info, etm_co
                arch_info[i].jtag_info = jtag_info;
        }
 
-       /* initialize some ETM control register settings */     
-       etm_get_reg(&reg_list[ETM_CTRL]);
-       etm_ctrl_value = buf_get_u32(reg_list[ETM_CTRL].value, 0, reg_list[ETM_CTRL].size);
-       
-       /* clear the ETM powerdown bit (0) */
-       etm_ctrl_value &= ~0x1;
-               
-       /* configure port width (6:4), mode (17:16) and clocking (13) */
-       etm_ctrl_value = (etm_ctrl_value & 
-               ~ETM_PORT_WIDTH_MASK & ~ETM_PORT_MODE_MASK & ~ETM_PORT_CLOCK_MASK)
-               | etm_ctx->portmode;
-       
-       buf_set_u32(reg_list[ETM_CTRL].value, 0, reg_list[ETM_CTRL].size, etm_ctrl_value);
-       etm_store_reg(&reg_list[ETM_CTRL]);
-       
        /* the ETM might have an ETB connected */
        if (strcmp(etm_ctx->capture_driver->name, "etb") == 0)
        {
@@ -278,35 +262,64 @@ reg_cache_t* etm_build_reg_cache(target_t *target, arm_jtag_t *jtag_info, etm_co
                
                if (!etb)
                {
-                       ERROR("etb selected as etm capture driver, but no ETB configured");
+                       LOG_ERROR("etb selected as etm capture driver, but no ETB configured");
                        return ERROR_OK;
                }
                
                reg_cache->next = etb_build_reg_cache(etb);
                
                etb->reg_cache = reg_cache->next;
-               
-               if (etm_ctx->capture_driver->init(etm_ctx) != ERROR_OK)
-               {
-                       ERROR("ETM capture driver initialization failed");
-                       exit(-1);
-               }
        }
        
+       
        return reg_cache;
 }
 
+int etm_setup(target_t *target)
+{
+       int retval;
+       u32 etm_ctrl_value;
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+       etm_context_t *etm_ctx = arm7_9->etm_ctx;
+       reg_t *etm_ctrl_reg = &arm7_9->etm_ctx->reg_cache->reg_list[ETM_CTRL];
+       /* 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);
+       
+       /* clear the ETM powerdown bit (0) */
+       etm_ctrl_value &= ~0x1;
+               
+       /* configure port width (6:4), mode (17:16) and clocking (13) */
+       etm_ctrl_value = (etm_ctrl_value & 
+               ~ETM_PORT_WIDTH_MASK & ~ETM_PORT_MODE_MASK & ~ETM_PORT_CLOCK_MASK)
+               | etm_ctx->portmode;
+       
+       buf_set_u32(etm_ctrl_reg->value, 0, etm_ctrl_reg->size, etm_ctrl_value);
+       etm_store_reg(etm_ctrl_reg);
+       
+       if ((retval=jtag_execute_queue())!=ERROR_OK)
+               return retval;
+       
+       if ((retval=etm_ctx->capture_driver->init(etm_ctx)) != ERROR_OK)
+       {
+               LOG_ERROR("ETM capture driver initialization failed");
+               return retval;
+       }
+       return ERROR_OK;
+}
+
 int etm_get_reg(reg_t *reg)
 {
        if (etm_read_reg(reg) != ERROR_OK)
        {
-               ERROR("BUG: error scheduling etm register read");
+               LOG_ERROR("BUG: error scheduling etm register read");
                exit(-1);
        }
        
        if (jtag_execute_queue() != ERROR_OK)
        {
-               ERROR("register read failed");
+               LOG_ERROR("register read failed");
        }
        
        return ERROR_OK;
@@ -318,7 +331,7 @@ int etm_read_reg_w_check(reg_t *reg, u8* check_value, u8* check_mask)
        u8 reg_addr = etm_reg->addr & 0x7f;
        scan_field_t fields[3];
        
-       DEBUG("%i", etm_reg->addr);
+       LOG_DEBUG("%i", etm_reg->addr);
 
        jtag_add_end_state(TAP_RTI);
        arm_jtag_scann(etm_reg->jtag_info, 0x6);
@@ -356,13 +369,12 @@ int etm_read_reg_w_check(reg_t *reg, u8* check_value, u8* check_mask)
        fields[2].in_handler = NULL;
        fields[2].in_handler_priv = NULL;
        
-       jtag_add_dr_scan(3, fields, -1, NULL);
+       jtag_add_dr_scan(3, fields, -1);
        
        fields[0].in_value = reg->value;
-       fields[0].in_check_value = check_value;
-       fields[0].in_check_mask = check_mask;
+       jtag_set_check_value(fields+0, check_value, check_mask, NULL);  
                
-       jtag_add_dr_scan(3, fields, -1, NULL);
+       jtag_add_dr_scan(3, fields, -1);
 
        free(fields[1].out_value);
        free(fields[2].out_value);
@@ -379,7 +391,7 @@ int etm_set_reg(reg_t *reg, u32 value)
 {
        if (etm_write_reg(reg, value) != ERROR_OK)
        {
-               ERROR("BUG: error scheduling etm register write");
+               LOG_ERROR("BUG: error scheduling etm register write");
                exit(-1);
        }
        
@@ -396,7 +408,7 @@ int etm_set_reg_w_exec(reg_t *reg, u8 *buf)
        
        if (jtag_execute_queue() != ERROR_OK)
        {
-               ERROR("register write failed");
+               LOG_ERROR("register write failed");
                exit(-1);
        }
        return ERROR_OK;
@@ -408,7 +420,7 @@ int etm_write_reg(reg_t *reg, u32 value)
        u8 reg_addr = etm_reg->addr & 0x7f;
        scan_field_t fields[3];
        
-       DEBUG("%i: 0x%8.8x", etm_reg->addr, value);
+       LOG_DEBUG("%i: 0x%8.8x", etm_reg->addr, value);
        
        jtag_add_end_state(TAP_RTI);
        arm_jtag_scann(etm_reg->jtag_info, 0x6);
@@ -447,7 +459,7 @@ int etm_write_reg(reg_t *reg, u32 value)
        fields[2].in_handler = NULL;
        fields[2].in_handler_priv = NULL;
        
-       jtag_add_dr_scan(3, fields, -1, NULL);
+       jtag_add_dr_scan(3, fields, -1);
        
        free(fields[0].out_value);
        free(fields[1].out_value);
@@ -465,10 +477,18 @@ int etm_store_reg(reg_t *reg)
  * 
  */
 extern etm_capture_driver_t etb_capture_driver;
+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_capture_driver_t *etm_capture_drivers[] = 
 {
        &etb_capture_driver,
+       &etm_dummy_capture_driver,
+#if BUILD_OOCD_TRACE == 1
+       &oocd_trace_capture_driver,
+#endif
        NULL
 };
 
@@ -519,7 +539,7 @@ int etm_read_instruction(etm_context_t *ctx, arm_instruction_t *instruction)
                        ctx->current_pc - ctx->image->sections[section].base_address,
                        4, buf, &size_read)) != ERROR_OK)
                {
-                       ERROR("error while reading instruction: %i", retval);
+                       LOG_ERROR("error while reading instruction: %i", retval);
                        return ERROR_TRACE_INSTRUCTION_UNAVAILABLE;
                }
                opcode = target_buffer_get_u32(ctx->target, buf);
@@ -532,7 +552,7 @@ int etm_read_instruction(etm_context_t *ctx, arm_instruction_t *instruction)
                        ctx->current_pc - ctx->image->sections[section].base_address,
                        2, buf, &size_read)) != ERROR_OK)
                {
-                       ERROR("error while reading instruction: %i", retval);
+                       LOG_ERROR("error while reading instruction: %i", retval);
                        return ERROR_TRACE_INSTRUCTION_UNAVAILABLE;
                }
                opcode = target_buffer_get_u16(ctx->target, buf);
@@ -540,12 +560,12 @@ int etm_read_instruction(etm_context_t *ctx, arm_instruction_t *instruction)
        }
        else if (ctx->core_state == ARMV4_5_STATE_JAZELLE)
        {
-               ERROR("BUG: tracing of jazelle code not supported");
+               LOG_ERROR("BUG: tracing of jazelle code not supported");
                exit(-1);
        }
        else
        {
-               ERROR("BUG: unknown core state encountered");
+               LOG_ERROR("BUG: unknown core state encountered");
                exit(-1);
        }
        
@@ -716,13 +736,18 @@ int etmv1_data(etm_context_t *ctx, int size, u32 *data)
        }
        
        if (size == 8)
-               ERROR("TODO: add support for 64-bit values");
+       {
+               LOG_ERROR("TODO: add support for 64-bit values");
+               return -1;
+       }
        else if (size == 4)
                *data = target_buffer_get_u32(ctx->target, buf);
        else if (size == 2)
                *data = target_buffer_get_u16(ctx->target, buf);
        else if (size == 1)
                *data = buf[0];
+       else
+               return -1;
                
        return 0;
 }
@@ -751,11 +776,19 @@ int etmv1_analyze_trace(etm_context_t *ctx, struct command_context_s *cmd_ctx)
                u32 next_pc = ctx->current_pc;
                u32 old_data_index = ctx->data_index;
                u32 old_data_half = ctx->data_half;
+               u32 old_index = ctx->pipe_index;
+               u32 last_instruction = ctx->last_instruction;
+               u32 cycles = 0;
+               int current_pc_ok = ctx->pc_ok;
                
                if (ctx->trace_data[ctx->pipe_index].flags & ETMV1_TRIGGER_CYCLE)
                {
                        command_print(cmd_ctx, "--- trigger ---");
                }
+
+               /* instructions execute in IE/D or BE/D cycles */
+               if ((pipestat == STAT_IE) || (pipestat == STAT_ID))
+                       ctx->last_instruction = ctx->pipe_index;
                
                /* if we don't have a valid pc skip until we reach an indirect branch */
                if ((!ctx->pc_ok) && (pipestat != STAT_BE))
@@ -775,6 +808,8 @@ int etmv1_analyze_trace(etm_context_t *ctx, struct command_context_s *cmd_ctx)
                         */
                        old_data_index = ctx->data_index;
                        old_data_half = ctx->data_half;
+
+                       ctx->last_instruction = ctx->pipe_index;
                        
                        if ((retval = etmv1_branch_address(ctx)) != 0)
                        {
@@ -786,7 +821,7 @@ int etmv1_analyze_trace(etm_context_t *ctx, struct command_context_s *cmd_ctx)
                                /* a positive return values means the current branch was abandoned,
                                 * and a new branch was encountered in cycle ctx->pipe_index + retval;
                                 */
-                               WARNING("abandoned branch encountered, correctnes of analysis uncertain");
+                               LOG_WARNING("abandoned branch encountered, correctnes of analysis uncertain");
                                ctx->pipe_index += retval;
                                continue;
                        }
@@ -819,9 +854,19 @@ int etmv1_analyze_trace(etm_context_t *ctx, struct command_context_s *cmd_ctx)
                                        break;
                                case 0x4:       /* periodic synchronization point */
                                        next_pc = ctx->last_branch;
+                                       /* if we had no valid PC prior to this synchronization point,
+                                        * we have to move on with the next trace cycle
+                                        */
+                                       if (!current_pc_ok)
+                                       {
+                                               command_print(cmd_ctx, "--- periodic synchronization point at 0x%8.8x ---", next_pc);
+                                               ctx->current_pc = next_pc;
+                                               ctx->pipe_index++;
+                                               continue;
+                                       }
                                        break;
                                default:        /* reserved */
-                                       ERROR("BUG: branch reason code 0x%x is reserved", ctx->last_branch_reason);             
+                                       LOG_ERROR("BUG: branch reason code 0x%x is reserved", ctx->last_branch_reason);         
                                        exit(-1);
                                        break;
                        }
@@ -866,9 +911,13 @@ int etmv1_analyze_trace(etm_context_t *ctx, struct command_context_s *cmd_ctx)
                                }
                                else if (retval == ERROR_TRACE_INSTRUCTION_UNAVAILABLE)
                                {
-                                       /* TODO: handle incomplete images */
+                                       /* TODO: handle incomplete images 
+                                        * for now we just quit the analsysis*/
+                                       return retval;
                                }
                        }
+                       
+                       cycles = old_index - last_instruction;
                }
                
                if ((pipestat == STAT_ID) || (pipestat == STAT_BD))
@@ -891,7 +940,7 @@ int etmv1_analyze_trace(etm_context_t *ctx, struct command_context_s *cmd_ctx)
                                
                                do {
                                        if ((retval = etmv1_next_packet(ctx, &packet, 0)) != 0)
-                                               return -1;
+                                               return ERROR_ETM_ANALYSIS_FAILED;
                                        ctx->last_ptr &= ~(0x7f << shift);
                                        ctx->last_ptr |= (packet & 0x7f) << shift;
                                        shift += 7;
@@ -917,7 +966,7 @@ int etmv1_analyze_trace(etm_context_t *ctx, struct command_context_s *cmd_ctx)
                                                {
                                                        u32 data;
                                                        if (etmv1_data(ctx, 4, &data) != 0)
-                                                               return -1;
+                                                               return ERROR_ETM_ANALYSIS_FAILED;
                                                        command_print(cmd_ctx, "data: 0x%8.8x", data);
                                                }
                                        }
@@ -926,7 +975,7 @@ int etmv1_analyze_trace(etm_context_t *ctx, struct command_context_s *cmd_ctx)
                                {
                                        u32 data;
                                        if (etmv1_data(ctx, arm_access_size(&instruction), &data) != 0)
-                                               return -1;
+                                               return ERROR_ETM_ANALYSIS_FAILED;
                                        command_print(cmd_ctx, "data: 0x%8.8x", data);
                                }
                        }
@@ -961,8 +1010,22 @@ int etmv1_analyze_trace(etm_context_t *ctx, struct command_context_s *cmd_ctx)
 
                if ((pipestat != STAT_TD) && (pipestat != STAT_WT))
                {
-                       command_print(cmd_ctx, "%s%s",
-                               instruction.text, (pipestat == STAT_IN) ? " (not executed)" : "");
+                       char cycles_text[32] = "";
+                       
+                       /* 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)
+                       {
+                               snprintf(cycles_text, 32, " (%i %s)",
+                                       cycles,
+                                       (cycles == 1) ? "cycle" : "cycles");
+                       }
+                       
+                       command_print(cmd_ctx, "%s%s%s",
+                               instruction.text,
+                               (pipestat == STAT_IN) ? " (not executed)" : "",
+                               cycles_text);
 
                        ctx->current_pc = next_pc;
                        
@@ -1005,7 +1068,7 @@ int handle_etm_tracemode_command(struct command_context_s *cmd_ctx, char *cmd, c
        
        tracemode = arm7_9->etm_ctx->tracemode;
 
-       if (argc == 3)
+       if (argc == 4)
        {
                if (strcmp(args[0], "none") == 0)
                {
@@ -1061,10 +1124,24 @@ int handle_etm_tracemode_command(struct command_context_s *cmd_ctx, char *cmd, c
                        command_print(cmd_ctx, "invalid option '%s'", args[2]);
                        return ERROR_OK;
                }
+               
+               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[2]);
+                       return ERROR_OK;
+               }
        }
        else if (argc != 0)
        {
-               command_print(cmd_ctx, "usage: configure trace mode <none|data|address|all> <context id bits> <enable|disable cycle accurate>");
+               command_print(cmd_ctx, "usage: configure trace mode <none|data|address|all> <context id bits> <cycle accurate> <branch output>");
                return ERROR_OK;
        }
        
@@ -1110,6 +1187,15 @@ int handle_etm_tracemode_command(struct command_context_s *cmd_ctx, char *cmd, c
        {
                command_print(cmd_ctx, "cycle-accurate tracing disabled");
        }
+
+       if (tracemode & ETMV1_BRANCH_OUTPUT)
+       {
+               command_print(cmd_ctx, "full branch address output enabled");
+       }
+       else
+       {
+               command_print(cmd_ctx, "full branch address output disabled");
+       }
        
        /* only update ETM_CTRL register if tracemode changed */
        if (arm7_9->etm_ctx->tracemode != tracemode)
@@ -1121,7 +1207,7 @@ int handle_etm_tracemode_command(struct command_context_s *cmd_ctx, char *cmd, c
                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);
                etm_store_reg(etm_ctrl_reg);
                
                arm7_9->etm_ctx->tracemode = tracemode;
@@ -1131,6 +1217,7 @@ int handle_etm_tracemode_command(struct command_context_s *cmd_ctx, char *cmd, c
                if (arm7_9->etm_ctx->trace_depth > 0)
                {
                        free(arm7_9->etm_ctx->trace_data);
+                       arm7_9->etm_ctx->trace_data = NULL;
                }
                arm7_9->etm_ctx->trace_depth = 0;
        }
@@ -1149,7 +1236,7 @@ int handle_etm_config_command(struct command_context_s *cmd_ctx, char *cmd, char
        
        if (argc != 5)
        {
-               ERROR("incomplete 'etm config <target> <port_width> <port_mode> <clocking> <capture_driver>' command");
+               LOG_ERROR("incomplete 'etm config <target> <port_width> <port_mode> <clocking> <capture_driver>' command");
                exit(-1);
        }
        
@@ -1157,7 +1244,7 @@ int handle_etm_config_command(struct command_context_s *cmd_ctx, char *cmd, char
        
        if (!target)
        {
-               ERROR("target number '%s' not defined", args[0]);
+               LOG_ERROR("target number '%s' not defined", args[0]);
                exit(-1);
        }
        
@@ -1231,7 +1318,16 @@ int handle_etm_config_command(struct command_context_s *cmd_ctx, char *cmd, char
                }
        }
        
+       if (!etm_capture_drivers[i])
+       {
+               /* no supported capture driver found, don't register an ETM */
+               free(etm_ctx);
+               LOG_ERROR("trace capture driver '%s' not found", args[4]);
+               return ERROR_OK;
+       }
+       
        etm_ctx->target = target;
+       etm_ctx->trigger_percent = 50;
        etm_ctx->trace_data = NULL;
        etm_ctx->trace_depth = 0;
        etm_ctx->portmode = portmode;
@@ -1247,6 +1343,7 @@ int handle_etm_config_command(struct command_context_s *cmd_ctx, char *cmd, char
        etm_ctx->last_ptr = 0x0;
        etm_ctx->ptr_ok = 0x0;
        etm_ctx->context_id = 0x0;
+       etm_ctx->last_instruction = 0;
        
        arm7_9->etm_ctx = etm_ctx;
        
@@ -1255,6 +1352,81 @@ int handle_etm_config_command(struct command_context_s *cmd_ctx, char *cmd, char
        return ERROR_OK;
 }
 
+int handle_etm_info_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       target_t *target;
+       armv4_5_common_t *armv4_5;
+       arm7_9_common_t *arm7_9;
+       reg_t *etm_config_reg;
+       reg_t *etm_sys_config_reg;
+       
+       int max_port_size;
+               
+       target = get_current_target(cmd_ctx);
+       
+       if (arm7_9_get_arch_pointers(target, &armv4_5, &arm7_9) != ERROR_OK)
+       {
+               command_print(cmd_ctx, "current target isn't an ARM7/ARM9 target");
+               return ERROR_OK;
+       }
+       
+       if (!arm7_9->etm_ctx)
+       {
+               command_print(cmd_ctx, "current target doesn't have an ETM configured");
+               return ERROR_OK;
+       }
+       
+       etm_config_reg = &arm7_9->etm_ctx->reg_cache->reg_list[ETM_CONFIG];
+       etm_sys_config_reg = &arm7_9->etm_ctx->reg_cache->reg_list[ETM_SYS_CONFIG];
+       
+       etm_get_reg(etm_config_reg);
+       command_print(cmd_ctx, "pairs of address comparators: %i", buf_get_u32(etm_config_reg->value, 0, 4));
+       command_print(cmd_ctx, "pairs of data comparators: %i", buf_get_u32(etm_config_reg->value, 4, 4));
+       command_print(cmd_ctx, "memory map decoders: %i", buf_get_u32(etm_config_reg->value, 8, 5));
+       command_print(cmd_ctx, "number of counters: %i", buf_get_u32(etm_config_reg->value, 13, 3));
+       command_print(cmd_ctx, "sequencer %spresent",
+                       (buf_get_u32(etm_config_reg->value, 16, 1) == 1) ? "" : "not ");
+       command_print(cmd_ctx, "number of ext. inputs: %i", buf_get_u32(etm_config_reg->value, 17, 3));
+       command_print(cmd_ctx, "number of ext. outputs: %i", buf_get_u32(etm_config_reg->value, 20, 3));
+       command_print(cmd_ctx, "FIFO full %spresent",
+                       (buf_get_u32(etm_config_reg->value, 23, 1) == 1) ? "" : "not ");
+       command_print(cmd_ctx, "protocol version: %i", buf_get_u32(etm_config_reg->value, 28, 3));
+       
+       etm_get_reg(etm_sys_config_reg);
+
+       switch (buf_get_u32(etm_sys_config_reg->value, 0, 3))
+       {
+               case 0:
+                       max_port_size = 4;
+                       break;
+               case 1:
+                       max_port_size = 8;
+                       break;
+               case 2:
+                       max_port_size = 16;
+                       break;
+               default:
+                       LOG_ERROR("Illegal max_port_size");
+                       exit(-1);
+       }
+       command_print(cmd_ctx, "max. port size: %i", max_port_size);
+       
+       command_print(cmd_ctx, "half-rate clocking %ssupported",
+                       (buf_get_u32(etm_sys_config_reg->value, 3, 1) == 1) ? "" : "not ");
+       command_print(cmd_ctx, "full-rate clocking %ssupported",
+                       (buf_get_u32(etm_sys_config_reg->value, 4, 1) == 1) ? "" : "not ");
+       command_print(cmd_ctx, "normal trace format %ssupported",
+                       (buf_get_u32(etm_sys_config_reg->value, 5, 1) == 1) ? "" : "not ");
+       command_print(cmd_ctx, "multiplex trace format %ssupported",
+                       (buf_get_u32(etm_sys_config_reg->value, 6, 1) == 1) ? "" : "not ");
+       command_print(cmd_ctx, "demultiplex trace format %ssupported",
+                       (buf_get_u32(etm_sys_config_reg->value, 7, 1) == 1) ? "" : "not ");
+       command_print(cmd_ctx, "FIFO full %ssupported",
+                       (buf_get_u32(etm_sys_config_reg->value, 8, 1) == 1) ? "" : "not ");
+       
+       return ERROR_OK;
+}
+
 int handle_etm_status_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
 {
        target_t *target;
@@ -1309,7 +1481,6 @@ int handle_etm_image_command(struct command_context_s *cmd_ctx, char *cmd, char
        armv4_5_common_t *armv4_5;
        arm7_9_common_t *arm7_9;
        etm_context_t *etm_ctx;
-       int i;
 
        if (argc < 1)
        {
@@ -1355,7 +1526,6 @@ int handle_etm_image_command(struct command_context_s *cmd_ctx, char *cmd, char
                
        if (image_open(etm_ctx->image, args[0], (argc >= 3) ? args[2] : NULL) != ERROR_OK)
        {
-               command_print(cmd_ctx, "image opening error: %s", etm_ctx->image->error_str);
                free(etm_ctx->image);
                etm_ctx->image = NULL;
                return ERROR_OK;
@@ -1412,7 +1582,6 @@ int handle_etm_dump_command(struct command_context_s *cmd_ctx, char *cmd, char *
        
        if (fileio_open(&file, args[0], FILEIO_WRITE, FILEIO_BINARY) != ERROR_OK)
        {
-               command_print(cmd_ctx, "file open error: %s", file.error_str);
                return ERROR_OK;
        }
        
@@ -1470,7 +1639,6 @@ int handle_etm_load_command(struct command_context_s *cmd_ctx, char *cmd, char *
        
        if (fileio_open(&file, args[0], FILEIO_READ, FILEIO_BINARY) != ERROR_OK)
        {
-               command_print(cmd_ctx, "file open error: %s", file.error_str);
                return ERROR_OK;
        }
        
@@ -1494,9 +1662,13 @@ int handle_etm_load_command(struct command_context_s *cmd_ctx, char *cmd, char *
        
        for (i = 0; i < etm_ctx->trace_depth; i++)
        {
-               fileio_read_u32(&file, &etm_ctx->trace_data[i].pipestat);
-               fileio_read_u32(&file, &etm_ctx->trace_data[i].packet);
-               fileio_read_u32(&file, &etm_ctx->trace_data[i].flags);
+               u32 pipestat, packet, flags;
+               fileio_read_u32(&file, &pipestat);
+               fileio_read_u32(&file, &packet);
+               fileio_read_u32(&file, &flags);
+               etm_ctx->trace_data[i].pipestat = pipestat & 0xff;
+               etm_ctx->trace_data[i].packet = packet & 0xffff;
+               etm_ctx->trace_data[i].flags = flags;
        }
        
        fileio_close(&file);
@@ -1504,6 +1676,46 @@ int handle_etm_load_command(struct command_context_s *cmd_ctx, char *cmd, char *
        return ERROR_OK;        
 }
 
+int handle_etm_trigger_percent_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       target_t *target;
+       armv4_5_common_t *armv4_5;
+       arm7_9_common_t *arm7_9;
+       etm_context_t *etm_ctx;
+       
+       target = get_current_target(cmd_ctx);
+       
+       if (arm7_9_get_arch_pointers(target, &armv4_5, &arm7_9) != ERROR_OK)
+       {
+               command_print(cmd_ctx, "current target isn't an ARM7/ARM9 target");
+               return ERROR_OK;
+       }
+       
+       if (!(etm_ctx = arm7_9->etm_ctx))
+       {
+               command_print(cmd_ctx, "current target doesn't have an ETM configured");
+               return ERROR_OK;
+       }
+       
+       if (argc > 0)
+       {
+               u32 new_value = strtoul(args[0], NULL, 0);
+               
+               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", etm_ctx->trigger_percent);
+
+       return ERROR_OK;
+}
+
 int handle_etm_start_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
 {
        target_t *target;
@@ -1531,6 +1743,7 @@ int handle_etm_start_command(struct command_context_s *cmd_ctx, char *cmd, char
        if (arm7_9->etm_ctx->trace_depth > 0)
        {
                free(arm7_9->etm_ctx->trace_data);
+               arm7_9->etm_ctx->trace_data = NULL;
        }
        arm7_9->etm_ctx->trace_depth = 0;
                
@@ -1590,6 +1803,7 @@ int handle_etm_analyze_command(struct command_context_s *cmd_ctx, char *cmd, cha
        armv4_5_common_t *armv4_5;
        arm7_9_common_t *arm7_9;
        etm_context_t *etm_ctx;
+       int retval;
 
        target = get_current_target(cmd_ctx);
        
@@ -1605,7 +1819,23 @@ int handle_etm_analyze_command(struct command_context_s *cmd_ctx, char *cmd, cha
                return ERROR_OK;
        }
        
-       etmv1_analyze_trace(etm_ctx, cmd_ctx);
+       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");
+                               break;
+                       case ERROR_TRACE_INSTRUCTION_UNAVAILABLE:
+                               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");
+                               break;
+                       default:
+                               command_print(cmd_ctx, "unknown error: %i", retval);
+               }
+       }
        
        return ERROR_OK;
 }
@@ -1622,8 +1852,13 @@ int etm_register_commands(struct command_context_s *cmd_ctx)
 int etm_register_user_commands(struct command_context_s *cmd_ctx)
 {
        register_command(cmd_ctx, etm_cmd, "tracemode", handle_etm_tracemode_command,
-               COMMAND_EXEC, "configure trace mode <none|data|address|all> <context id bits> <enable|disable cycle accurate>");
+               COMMAND_EXEC, "configure 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 <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,