]> git.sur5r.net Git - openocd/blobdiff - src/target/etm.c
- fixed ETM configuration register decoding
[openocd] / src / target / etm.c
index 52e4b3d6223716d38da62c51475c44602dcbd7dd..1a20d862864d3c654cbcbae3463ea7a52c3b890a 100644 (file)
@@ -760,18 +760,22 @@ int etmv1_analyze_trace(etm_context_t *ctx, struct command_context_s *cmd_ctx)
                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))
                {
-                       if (pipestat == STAT_IE)
-                               ctx->last_instruction = ctx->pipe_index;
                        ctx->pipe_index++;
                        continue;
                }
@@ -787,6 +791,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)
                        {
@@ -810,32 +816,37 @@ int etmv1_analyze_trace(etm_context_t *ctx, struct command_context_s *cmd_ctx)
                        {
                                case 0x0:       /* normal PC change */
                                        next_pc = ctx->last_branch;
-                                       ctx->last_instruction = old_index;
                                        break;
                                case 0x1:       /* tracing enabled */
                                        command_print(cmd_ctx, "--- tracing enabled at 0x%8.8x ---", ctx->last_branch);
                                        ctx->current_pc = ctx->last_branch;
                                        ctx->pipe_index++;
-                                       ctx->last_instruction = old_index;
                                        continue;
                                        break;
                                case 0x2:       /* trace restarted after FIFO overflow */
                                        command_print(cmd_ctx, "--- trace restarted after FIFO overflow at 0x%8.8x ---", ctx->last_branch);
                                        ctx->current_pc = ctx->last_branch;
                                        ctx->pipe_index++;
-                                       ctx->last_instruction = old_index;
                                        continue;
                                        break;
                                case 0x3:       /* exit from debug state */
                                        command_print(cmd_ctx, "--- exit from debug state at 0x%8.8x ---", ctx->last_branch);
                                        ctx->current_pc = ctx->last_branch;
                                        ctx->pipe_index++;
-                                       ctx->last_instruction = old_index;
                                        continue;
                                        break;
                                case 0x4:       /* periodic synchronization point */
                                        next_pc = ctx->last_branch;
-                                       ctx->last_instruction = old_index;
+                                       /* 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);             
@@ -854,8 +865,6 @@ int etmv1_analyze_trace(etm_context_t *ctx, struct command_context_s *cmd_ctx)
                        if (((ctx->last_branch >= 0x0) && (ctx->last_branch <= 0x20))
                                || ((ctx->last_branch >= 0xffff0000) && (ctx->last_branch <= 0xffff0020)))
                        {
-                               ctx->last_instruction = old_index;
-                               
                                if ((ctx->last_branch & 0xff) == 0x10)
                                {
                                        command_print(cmd_ctx, "data abort");
@@ -885,12 +894,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 - ctx->last_instruction;
-                       ctx->last_instruction = old_index;
+                       cycles = old_index - last_instruction;
                }
                
                if ((pipestat == STAT_ID) || (pipestat == STAT_BD))
@@ -913,7 +923,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;
@@ -939,7 +949,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);
                                                }
                                        }
@@ -948,7 +958,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);
                                }
                        }
@@ -1354,8 +1364,8 @@ int handle_etm_info_command(struct command_context_s *cmd_ctx, char *cmd, char *
        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, 4));
-       command_print(cmd_ctx, "number of counters: %i", buf_get_u32(etm_config_reg->value, 12, 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));
@@ -1774,6 +1784,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);
        
@@ -1789,7 +1800,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;
 }