- further work on ETB decoding (not yet functional)
authordrath <drath@b42882b7-edfa-0310-969c-e2dbd0fdcd60>
Sat, 5 May 2007 11:02:03 +0000 (11:02 +0000)
committerdrath <drath@b42882b7-edfa-0310-969c-e2dbd0fdcd60>
Sat, 5 May 2007 11:02:03 +0000 (11:02 +0000)
- fixed several uses of uninitialized bits (Thanks to Vincent Palatin for finding and fixing these bugs)

git-svn-id: svn://svn.berlios.de/openocd/trunk@145 b42882b7-edfa-0310-969c-e2dbd0fdcd60

src/helper/binarybuffer.c
src/jtag/jtag.c
src/target/arm7_9_common.c
src/target/etb.c

index acc8237eb08323fcdfab29fbb3623b0a2a061025..7d97891533755ed9bbc2bc5ad41524ddae6ba2be 100644 (file)
@@ -354,7 +354,12 @@ int str_to_buf(char* str, int str_len, u8 *buf, int buf_len, int radix)
        }
        
        for (j = 0; j < CEIL(buf_len, 8); j++)
-               buf[j] = b256_buf[j];
+       {
+               if (j < b256_len)
+                       buf[j] = b256_buf[j];
+               else
+                       buf[j] = 0;
+       }
 
        /* mask out bits that don't belong to the buffer */
        if (buf_len % 8)
index 7ea40edb0e190ff3c06c9dac849a9a1b8d0dfafa..073ce1f4553a429ef605301f5bddf7ca02fe6692 100644 (file)
@@ -1039,6 +1039,7 @@ int jtag_read_buffer(u8 *buffer, scan_command_t *cmd)
                {
                        int num_bits = cmd->fields[i].num_bits;
                        u8 *captured = buf_set_buf(buffer, bit_count, malloc(CEIL(num_bits, 8)), 0, num_bits);
+                       
                        #ifdef _DEBUG_JTAG_IO_
                                char *char_buf;
 
@@ -1217,7 +1218,7 @@ int jtag_examine_chain()
        
        for (i = 0; i < JTAG_MAX_CHAIN_SIZE; i++)
        {
-               buf_set_u32(idcode_buffer, 0, 32, 0x000000FF);
+               buf_set_u32(idcode_buffer, i * 32, 32, 0x000000FF);
        }
        
        jtag_add_plain_dr_scan(1, &field, TAP_TLR, NULL);
index 5569ad5bbb932515f5c1de7d18cdee98bcd86aa4..d28aca59f67ebb6d41356983757000c51630d83d 100644 (file)
@@ -2496,6 +2496,8 @@ int handle_arm7_9_etb_command(struct command_context_s *cmd_ctx, char *cmd, char
        arm7_9->etb->chain_pos = strtoul(args[1], NULL, 0);
        arm7_9->etb->cur_scan_chain = -1;
        arm7_9->etb->reg_cache = NULL;
+       arm7_9->etb->RAM_width = 0;
+       arm7_9->etb->RAM_depth = 0;
 
        return ERROR_OK;
 }
index e6c4a8510d5040fa41accf28d2253f0011217ab9..21f250aa7f3e3b34c419e236eaeacfd8b0e0e023 100644 (file)
@@ -58,6 +58,14 @@ int etb_read_reg(reg_t *reg);
 int handle_arm7_9_etb_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
 int handle_arm7_9_etb_dump_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
 
+char *etmv1_branch_reason_string[] =
+{
+       "normal pc change", "tracing enabled", "restart after FIFO overflow",
+       "exit from debug state", "peridoic synchronization point",
+       "reserved", "reserved", "reserved"
+};
+
+
 int etb_set_instr(etb_t *etb, u32 new_instr)
 {
        jtag_device_t *device = jtag_get_device(etb->chain_pos);
@@ -334,15 +342,74 @@ int etb_register_commands(struct command_context_s *cmd_ctx, command_t *arm7_9_c
        return ERROR_OK;
 }
 
+#define PIPESTAT(x) ((x) & 0x7)
+#define TRACEPKT(x) (((x) & 0x7fff8) >> 3)
+#define TRACESYNC(x) (((x) & 0x80000) >> 19)
+
+int etmv1_next_packet(int trace_depth, u32 *trace_data, int frame, int *port_half, int apo, u8 *packet)
+{
+       while (frame < trace_depth)
+       {
+               if (apo > 0)
+               {
+                       if (TRACESYNC(trace_data[frame]))
+                               apo--;
+               }
+               else
+               {
+                       /* we're looking for a branch address, skip if TRACESYNC isn't set */
+                       if ((apo == 0) && (!TRACESYNC(trace_data[frame])))
+                       {
+                               frame++;
+                               continue;
+                       }
+                               
+                       /* TRACEPKT is valid if this isn't a TD nor a TRIGGER cycle */
+                       if (((PIPESTAT(trace_data[frame]) != 0x7) && (PIPESTAT(trace_data[frame]) != 0x6))
+                               && !((apo == 0) && (!TRACESYNC(trace_data[frame]))))
+                       {
+                               if (*port_half == 0)
+                               {
+                                       *packet = TRACEPKT(trace_data[frame]) & 0xff;
+                                       *port_half = 1;
+                               }
+                               else
+                               {
+                                       *packet = (TRACEPKT(trace_data[frame]) & 0xff00) >> 8;
+                                       *port_half = 0;
+                                       frame++;
+                               }
+                               return frame;
+                       }
+               }
+               frame++;
+       }
+       
+       /* we reached the end of the trace without finding the packet we're looking for
+        * tracing is finished
+        */
+       return -1;
+}
+
 int handle_arm7_9_etb_dump_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
 {
        int retval;
        target_t *target = get_current_target(cmd_ctx);
        armv4_5_common_t *armv4_5;
        arm7_9_common_t *arm7_9;
-       int i;
+       int i, j, k;
        int first_frame = 0;
        int last_frame;
+       int addressbits_valid = 0;
+       u32 address = 0x0;
+       u32 *trace_data;
+       int port_half = 0;
+       int last_instruction = -1;
+       u8 branch_reason;
+       u8 packet;
+       char trace_output[256];
+       int trace_output_len;
+       u8 apo;
 
        if (arm7_9_get_arch_pointers(target, &armv4_5, &arm7_9) != ERROR_OK)
        {
@@ -367,29 +434,191 @@ int handle_arm7_9_etb_dump_command(struct command_context_s *cmd_ctx, char *cmd,
                arm7_9->etb->RAM_width = buf_get_u32(arm7_9->etb->reg_cache->reg_list[ETB_RAM_WIDTH].value, 0, 32);
        }
        
+       trace_data = malloc(sizeof(u32) * arm7_9->etb->RAM_depth);
+       
        etb_read_reg(&arm7_9->etb->reg_cache->reg_list[ETB_STATUS]);
        etb_read_reg(&arm7_9->etb->reg_cache->reg_list[ETB_RAM_WRITE_POINTER]);
+       jtag_execute_queue();
        
        /* check if we overflowed, and adjust first and last frame of the trace accordingly */
        if (buf_get_u32(arm7_9->etb->reg_cache->reg_list[ETB_STATUS].value, 1, 1))
        {
                first_frame = buf_get_u32(arm7_9->etb->reg_cache->reg_list[ETB_RAM_WRITE_POINTER].value, 0, 32);
-               last_frame = first_frame - 1;
-       }
-       else
-       {
-               last_frame = buf_get_u32(arm7_9->etb->reg_cache->reg_list[ETB_RAM_WRITE_POINTER].value, 0, 32) - 1;
        }
        
+       last_frame = buf_get_u32(arm7_9->etb->reg_cache->reg_list[ETB_RAM_WRITE_POINTER].value, 0, 32) - 1;
+       
        etb_write_reg(&arm7_9->etb->reg_cache->reg_list[ETB_RAM_READ_POINTER], first_frame);
-       for (i = first_frame; (i % arm7_9->etb->RAM_depth) != last_frame; i++)
-       {
-               u32 trace_data;
+
+       /* read trace data from ETB */
+       i = first_frame;
+       j = 0;
+       do {
                etb_read_reg(&arm7_9->etb->reg_cache->reg_list[ETB_RAM_DATA]);
                jtag_execute_queue();
-               trace_data = buf_get_u32(arm7_9->etb->reg_cache->reg_list[ETB_RAM_DATA].value, 0, 32);
-               command_print(cmd_ctx, "%8.8i: %i %2.2x %2.2x %2.2x (0x%8.8x)",
-                       i % 2048, (trace_data >> 19) & 1, (trace_data >> 11) & 0xff, (trace_data >> 3) & 0xff, trace_data & 0x7, trace_data);
+               trace_data[j++] = buf_get_u32(arm7_9->etb->reg_cache->reg_list[ETB_RAM_DATA].value, 0, 32);
+               i++;
+       } while ((i % arm7_9->etb->RAM_depth) != (first_frame % arm7_9->etb->RAM_depth));
+       
+       for (i = 0, j = 0; i < arm7_9->etb->RAM_depth; i++)
+       {
+               int trigger = 0;
+               
+               trace_output_len = 0;
+               
+               /* catch trigger, actual PIPESTAT is encoded in TRACEPKT[2:0] */
+               if (PIPESTAT(trace_data[i]) == 0x6)
+               {
+                       trigger = 1;
+                       trace_data[i] &= ~0x7;
+                       trace_data[i] |= TRACEPKT(trace_data[i]) & 0x7;
+               }
+       
+               if (addressbits_valid == 32)
+               {
+                       trace_output_len += snprintf(trace_output + trace_output_len, 256 - trace_output_len,
+                               "%i: 0x%8.8x %s", i, address, (trigger) ? "(TRIGGER) " : "");
+               }
+               else if (addressbits_valid != 0)
+               {
+                       trace_output_len += snprintf(trace_output + trace_output_len, 256 - trace_output_len,
+                               "%i: 0x...%x %s", i, address, (trigger) ? "(TRIGGER) " : "");
+               }
+               else
+               {
+                       trace_output_len += snprintf(trace_output + trace_output_len, 256 - trace_output_len,
+                               "%i: 0xUNK %s", i, (trigger) ? "(TRIGGER) " : "");
+               }
+               
+               switch (PIPESTAT(trace_data[i]))
+               {
+                       case 0x0:
+                               trace_output_len += snprintf(trace_output + trace_output_len, 256 - trace_output_len,
+                                       "IE");
+                               break;
+                       case 0x1:
+                               trace_output_len += snprintf(trace_output + trace_output_len, 256 - trace_output_len,
+                                       "ID");
+                               break;
+                       case 0x2:
+                               /* Instruction exectued - TRACEPKT might be valid, but belongs to another cycle */
+                               trace_output_len += snprintf(trace_output + trace_output_len, 256 - trace_output_len,
+                                       "IN");
+                               break;
+                       case 0x3:
+                               /* WAIT cycle - TRACEPKT is valid, but belongs to another cycle */
+                               trace_output_len += snprintf(trace_output + trace_output_len, 256 - trace_output_len,
+                                       "WT");
+                               break;
+                       case 0x4:
+                               /* following a branch two APO cycles are output on PIPESTAT[1:0]
+                                * but another BE/BD could overwrite the current branch,
+                                * or a trigger could cause the APO to be output on TRACEPKT[1:0]
+                                */
+                               if ((PIPESTAT(trace_data[i + 1]) == 0x4)
+                                       || (PIPESTAT(trace_data[i + 1]) == 0x5))
+                               {
+                                       /* another branch occured, we ignore this one */
+                                       j = (j < i + 1) ? i + 1 : j;
+                                       break;
+                               }
+                               else if (PIPESTAT(trace_data[i + 1]) == 0x6)
+                               {
+                                       apo = TRACEPKT(trace_data[i + 1]) & 0x3;
+                               }
+                               else
+                               {
+                                       apo = PIPESTAT(trace_data[i + 1]) & 0x3;
+                               }
+
+                               if ((PIPESTAT(trace_data[i + 2]) == 0x4)
+                                       || (PIPESTAT(trace_data[i + 2]) == 0x5))
+                               {
+                                       j = (j < i + 2) ? i + 1 : j;
+                                       i = i + 1;
+                                       break;
+                               }
+                               else if (PIPESTAT(trace_data[i + 2]) == 0x6)
+                               {
+                                       apo |= (TRACEPKT(trace_data[i + 2]) & 0x3) << 2;
+                               }
+                               else
+                               {
+                                       apo = (PIPESTAT(trace_data[i + 1]) & 0x3) << 2;
+                               }
+                               
+                               branch_reason = -1;
+                               k = 0;
+                               do
+                               {
+                                       if ((j = etmv1_next_packet(arm7_9->etb->RAM_depth, trace_data, j, &port_half, apo, &packet)) != -1)
+                                       {
+                                               address &= ~(0x7f << (k * 7));
+                                               address |= (packet & 0x7f) << (k * 7);
+                                       }
+                                       else
+                                       {
+                                               break;
+                                       }
+                                       k++;
+                               } while ((k < 5) && (packet & 0x80));
+                               
+                               if (addressbits_valid < ((k * 7 > 32) ? 32 : k * 7))
+                                       addressbits_valid = (k * 7 > 32) ? 32 : k * 7;
+                               
+                               if (k == 5)
+                               {
+                                       branch_reason = (packet & 0x7) >> 4;
+                                       trace_output_len += snprintf(trace_output + trace_output_len, 256 - trace_output_len,
+                                               "BE 0x%x (/%i) (%s)", address, addressbits_valid, etmv1_branch_reason_string[branch_reason]);
+                               }
+                               else
+                               {
+                                       trace_output_len += snprintf(trace_output + trace_output_len, 256 - trace_output_len,
+                                               "BE 0x%x (/%i)", address, addressbits_valid);
+                               }
+                               
+                               break;
+                       case 0x5:
+                               trace_output_len += snprintf(trace_output + trace_output_len, 256 - trace_output_len,
+                                       "BD");
+                               break;
+                       case 0x6:
+                               /* We catch the trigger event before we get here */
+                               ERROR("TR pipestat should have been caught earlier");
+                               trace_output_len += snprintf(trace_output + trace_output_len, 256 - trace_output_len,
+                                       "--");
+                               break;
+                       case 0x7:
+                               /* TRACE disabled - TRACEPKT = invalid */
+                               trace_output_len += snprintf(trace_output + trace_output_len, 256 - trace_output_len,
+                                       "TD");
+                               break;
+               }
+               
+               /* PIPESTAT other than WT (b011) and TD (b111) mean we executed an instruction */
+               if ((PIPESTAT(trace_data[i]) & 0x3) != 0x3)
+               {
+                       last_instruction = i;
+                       address += 4;
+               }
+
+               /* The group of packets for a particular instruction cannot start on or before any
+                * previous functional PIPESTAT (IE, IN, ID, BE, or BD)
+                */
+               if (j < last_instruction)
+               {
+                       j = last_instruction + 1;
+               }
+
+               /* restore trigger PIPESTAT to ensure TRACEPKT is ignored */            
+               if (trigger == 1)
+               {
+                       trace_data[i] &= ~0x7;
+                       trace_data[i] |= 0x6;   
+               }
+               
+               command_print(cmd_ctx, "%s (raw: 0x%8.8x)", trace_output, trace_data[i]);
        }
        
        return ERROR_OK;

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)