- fixed endianness helper macros (thanks to obilix and wiml for finding and fixing...
authordrath <drath@b42882b7-edfa-0310-969c-e2dbd0fdcd60>
Thu, 28 Jun 2007 10:32:58 +0000 (10:32 +0000)
committerdrath <drath@b42882b7-edfa-0310-969c-e2dbd0fdcd60>
Thu, 28 Jun 2007 10:32:58 +0000 (10:32 +0000)
- added declarations for 32bit fileio access functions (network byte order)
- fixed bug in etm trace dump file handling
- added XScale trace buffer decoding
- fixed arm_simulator ERROR numbers (-7xx used twice)
- fixed minor bug in debug output in stellaris.c

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

src/flash/stellaris.c
src/helper/fileio.h
src/helper/types.h
src/openocd.c
src/target/arm_simulator.h
src/target/etm.c
src/target/xscale.c
src/target/xscale.h

index ec5dc3a429da40d02b70df10886d19e253264f7f..376a80fd84b05a83041dc2f2ccfdc3b57bb67e30 100644 (file)
@@ -148,7 +148,7 @@ int stellaris_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, c
        stellaris_info->target = get_target_by_num(strtoul(args[5], NULL, 0));
        if (!stellaris_info->target)
        {
-               ERROR("no target '%i' configured", args[5]);
+               ERROR("no target '%s' configured", args[5]);
                exit(-1);
        }
        
index 55e6f32313aa1504517bc7d2feae0a2ff00dc202..5c0a88dae4146a502b0862e0f445bedf06c745fb 100644 (file)
@@ -82,6 +82,8 @@ extern int fileio_read(fileio_t *fileio, u32 size, u8 *buffer, u32 *size_read);
 extern int fileio_seek(fileio_t *fileio, u32 position);
 extern int fileio_close(fileio_t *fileio);
 extern int fileio_open(fileio_t *fileio, char *url, enum fileio_access access, enum fileio_type type);
+extern int fileio_read_u32(fileio_t *fileio, u32 *data);
+extern int fileio_write_u32(fileio_t *fileio, u32 data);
        
 #define ERROR_FILEIO_LOCATION_UNKNOWN  (-1200)
 #define ERROR_FILEIO_NOT_FOUND                 (-1201)
index 69cb16a28d704a648e074da0e6eaa077360df5a5..a68c301ee632946add2fbf64c4baf4d7a90fd992 100644 (file)
@@ -40,23 +40,23 @@ typedef unsigned long long u64;
 
 #ifdef WORDS_BIGENDIAN /* big endian host */
 
-#define le_to_h_u32(x) (u32)(x[0] | x[1] << 8 | x[2] << 16 | x[3] << 24)
-#define le_to_h_u16(x) (u16)(x[0] | x[1] << 8)
+#define le_to_h_u32(x) (u32)((x)[0] | (x)[1] << 8 | (x)[2] << 16 | (x)[3] << 24)
+#define le_to_h_u16(x) (u16)((x)[0] | (x)[1] << 8)
 #define be_to_h_u32(x) (*(u32*)(x))
 #define be_to_h_u16(x) (*(u16*)(x))
 
 #define h_u32_to_le(buf, val) \
        do { \
-               buf[3] = (val & 0xff000000) >> 24; \
-               buf[2] = (val & 0x00ff0000) >> 16; \
-               buf[1] = (val & 0x0000ff00) >> 8; \
-               buf[0] = (val & 0x000000ff); \
+               (buf)[3] = ((val) & 0xff000000) >> 24; \
+               (buf)[2] = ((val) & 0x00ff0000) >> 16; \
+               (buf)[1] = ((val) & 0x0000ff00) >> 8; \
+               (buf)[0] = ((val) & 0x000000ff); \
        } while (0)
 
 #define h_u16_to_le(buf, val)  \
        do { \
-               buf[0] = (val & 0xff000) >> 8; \
-               buf[1] = (val & 0x00ff); \
+               (buf)[0] = ((val) & 0xff000) >> 8; \
+               (buf)[1] = ((val) & 0x00ff); \
        } while (0)
 
 #define h_u32_to_be(buf, val) do { *(u32*)(buf) = (val); } while (0)
@@ -73,16 +73,16 @@ typedef unsigned long long u64;
 
 #define h_u32_to_be(buf, val) \
        do { \
-               buf[0] = (val & 0xff000000) >> 24; \
-               buf[1] = (val & 0x00ff0000) >> 16; \
-               buf[2] = (val & 0x0000ff00) >> 8; \
-               buf[3] = (val & 0x000000ff); \
+               (buf)[0] = ((val) & 0xff000000) >> 24; \
+               (buf)[1] = ((val) & 0x00ff0000) >> 16; \
+               (buf)[2] = ((val) & 0x0000ff00) >> 8; \
+               (buf)[3] = ((val) & 0x000000ff); \
        } while (0)
 
 #define h_u16_to_be(buf, val) \
        do { \
-               buf[0] = (val & 0xff000) >> 8; \
-               buf[1] = (val & 0x00ff); \
+               (buf)[0] = ((val) & 0xff000) >> 8; \
+               (buf)[1] = ((val) & 0x00ff); \
        } while (0)
 #endif
 
index 76cc3d8d6d7ce8ff247196e333cf7680d66eadb5..035c166a0aa4cd51afa8db4c838fe28635a81d26 100644 (file)
@@ -18,7 +18,7 @@
  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
  ***************************************************************************/
 
-#define OPENOCD_VERSION "Open On-Chip Debugger (2007-06-15 16:00 CEST)"
+#define OPENOCD_VERSION "Open On-Chip Debugger (2007-06-28 12:30 CEST)"
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
index 9c28a086b19d94e5255082b9be83b0359b23f337..7894873043a75184ddf407f84d2ff3f134c9c6a6 100644 (file)
@@ -26,6 +26,6 @@
 extern int arm_simulate_step(target_t *target, u32 *dry_run_pc);
 
 
-#define ERROR_ARM_SIMULATOR_NOT_IMPLEMENTED    (-1000)
+#define ERROR_ARM_SIMULATOR_NOT_IMPLEMENTED    (-700)
 
 #endif /* ARM_SIMULATOR_H */
index b4c20750bced8903759d83da31f42762996fa8ea..367eafffabe38ab00dc6bfb2faed8301670fd00b 100644 (file)
@@ -1502,9 +1502,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);
index 2cfc23e71d2f73bf0d0026a446df0a0fabe844af..e7661aaa9f05f062aeb33cd151026243fe25ca28 100644 (file)
@@ -29,6 +29,7 @@
 #include "target.h"
 #include "armv4_5.h"
 #include "arm_simulator.h"
+#include "arm_disassembler.h"
 #include "log.h"
 #include "jtag.h"
 #include "binarybuffer.h"
@@ -995,21 +996,29 @@ enum target_state xscale_poll(target_t *target)
        {
                if ((retval = xscale_read_tx(target, 0)) == ERROR_OK)
                {
+                       enum target_state previous_state = target->state;
+                       
                        /* there's data to read from the tx register, we entered debug state */
                        xscale->handler_running = 1;
+
+                       target->state = TARGET_HALTED;
                        
                        /* process debug entry, fetching current mode regs */
                        if ((retval = xscale_debug_entry(target)) != ERROR_OK)
                                return retval;
                        
+                       /* debug_entry could have overwritten target state (i.e. immediate resume)
+                        * don't signal event handlers in that case
+                        */
+                       if (target->state != TARGET_HALTED)
+                               return target->state;
+                       
                        /* if target was running, signal that we halted
                         * otherwise we reentered from debug execution */
-                       if (target->state == TARGET_RUNNING)
+                       if (previous_state == TARGET_RUNNING)
                                target_call_event_callbacks(target, TARGET_EVENT_HALTED);
                        else
                                target_call_event_callbacks(target, TARGET_EVENT_DEBUG_HALTED);
-
-                       target->state = TARGET_HALTED;
                }
                else if (retval != ERROR_TARGET_RESOURCE_NOT_AVAILABLE)
                {
@@ -1174,6 +1183,24 @@ int xscale_debug_entry(target_t *target)
        xscale->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled = (xscale->cp15_control_reg & 0x4U) ? 1 : 0;
        xscale->armv4_5_mmu.armv4_5_cache.i_cache_enabled = (xscale->cp15_control_reg & 0x1000U) ? 1 : 0;
        
+       /* tracing enabled, read collected trace data */
+       if (xscale->trace.buffer_enabled)
+       {
+               xscale_read_trace(target);
+               xscale->trace.buffer_fill--;
+               
+               /* resume if we're still collecting trace data */
+               if ((xscale->arch_debug_reason == XSCALE_DBG_REASON_TB_FULL)
+                       && (xscale->trace.buffer_fill > 0))
+               {
+                       xscale_resume(target, 1, 0x0, 1, 0);
+               }
+               else
+               {
+                       xscale->trace.buffer_enabled = 0;
+               }
+       }
+       
        return ERROR_OK;
 }
 
@@ -1315,7 +1342,7 @@ int xscale_resume(struct target_s *target, int current, u32 address, int handle_
                        
                        /* send resume request (command 0x30 or 0x31)
                         * clean the trace buffer if it is to be enabled (0x62) */
-                       if (xscale->trace_buffer_enabled)
+                       if (xscale->trace.buffer_enabled)
                        {
                                xscale_send_u32(target, 0x62);
                                xscale_send_u32(target, 0x31);
@@ -1358,7 +1385,7 @@ int xscale_resume(struct target_s *target, int current, u32 address, int handle_
        
        /* send resume request (command 0x30 or 0x31)
         * clean the trace buffer if it is to be enabled (0x62) */
-       if (xscale->trace_buffer_enabled)
+       if (xscale->trace.buffer_enabled)
        {
                xscale_send_u32(target, 0x62);
                xscale_send_u32(target, 0x31);
@@ -1462,7 +1489,7 @@ int xscale_step(struct target_s *target, int current, u32 address, int handle_br
        
        /* send resume request (command 0x30 or 0x31)
         * clean the trace buffer if it is to be enabled (0x62) */
-       if (xscale->trace_buffer_enabled)
+       if (xscale->trace.buffer_enabled)
        {
                xscale_send_u32(target, 0x62);
                xscale_send_u32(target, 0x31);
@@ -2537,6 +2564,355 @@ int xscale_write_dcsr_sw(target_t *target, u32 value)
        return ERROR_OK;
 }
 
+int xscale_read_trace(target_t *target)
+{
+       /* get pointers to arch-specific information */
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       xscale_common_t *xscale = armv4_5->arch_info;
+       xscale_trace_data_t **trace_data_p;
+       
+       /* 258 words from debug handler
+        * 256 trace buffer entries
+        * 2 checkpoint addresses
+        */ 
+       u32 trace_buffer[258];
+       int is_address[256];
+       int i, j;
+       
+       if (target->state != TARGET_HALTED)
+       {
+               WARNING("target must be stopped to read trace data");
+               return ERROR_TARGET_NOT_HALTED;
+       }
+
+       /* send read trace buffer command (command 0x61) */
+       xscale_send_u32(target, 0x61);
+       
+       /* receive trace buffer content */
+       xscale_receive(target, trace_buffer, 258);
+       
+       /* parse buffer backwards to identify address entries */
+       for (i = 255; i >= 0; i--)
+       {
+               is_address[i] = 0;
+               if (((trace_buffer[i] & 0xf0) == 0x90) ||
+                       ((trace_buffer[i] & 0xf0) == 0xd0)) 
+               {
+                       if (i >= 3)
+                               is_address[--i] = 1;
+                       if (i >= 2)
+                               is_address[--i] = 1;
+                       if (i >= 1)
+                               is_address[--i] = 1;
+                       if (i >= 0)
+                               is_address[--i] = 1;
+               }
+       }
+
+       
+       /* search first non-zero entry */
+       for (j = 0; (j < 256) && (trace_buffer[j] == 0) && (!is_address[j]); j++)
+               ;
+
+       if (j == 256)
+       {
+               DEBUG("no trace data collected");
+               return ERROR_XSCALE_NO_TRACE_DATA;
+       }
+               
+       for (trace_data_p = &xscale->trace.data; *trace_data_p; trace_data_p = &(*trace_data_p)->next)
+               ;
+
+       *trace_data_p = malloc(sizeof(xscale_trace_data_t));
+       (*trace_data_p)->next = NULL;
+       (*trace_data_p)->chkpt0 = trace_buffer[256];
+       (*trace_data_p)->chkpt1 = trace_buffer[257];
+       (*trace_data_p)->last_instruction = buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32);
+       (*trace_data_p)->entries = malloc(sizeof(xscale_trace_entry_t) * (256 - j));
+       (*trace_data_p)->depth = 256 - j;
+               
+       for (i = j; i < 256; i++)
+       {
+               (*trace_data_p)->entries[i - j].data = trace_buffer[i];
+               if (is_address[i])
+                       (*trace_data_p)->entries[i - j].type = XSCALE_TRACE_ADDRESS;
+               else
+                       (*trace_data_p)->entries[i - j].type = XSCALE_TRACE_MESSAGE;
+       }
+       
+       return ERROR_OK;
+}
+
+int xscale_read_instruction(target_t *target, arm_instruction_t *instruction)
+{
+       /* get pointers to arch-specific information */
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       xscale_common_t *xscale = armv4_5->arch_info;
+       int i;
+       int section = -1;
+       u32 size_read;
+       u32 opcode;
+       int retval;
+       
+       if (!xscale->trace.image)
+               return ERROR_TRACE_IMAGE_UNAVAILABLE;
+       
+       /* search for the section the current instruction belongs to */ 
+       for (i = 0; i < xscale->trace.image->num_sections; i++)
+       {
+               if ((xscale->trace.image->sections[i].base_address <= xscale->trace.current_pc) &&
+                       (xscale->trace.image->sections[i].base_address + xscale->trace.image->sections[i].size > xscale->trace.current_pc))
+               {
+                       section = i;
+                       break;
+               }
+       }
+       
+       if (section == -1)
+       {
+               /* current instruction couldn't be found in the image */
+               return ERROR_TRACE_INSTRUCTION_UNAVAILABLE;
+       }
+       
+       if (xscale->trace.core_state == ARMV4_5_STATE_ARM)
+       {
+               u8 buf[4];
+               if ((retval = image_read_section(xscale->trace.image, section, 
+                       xscale->trace.current_pc - xscale->trace.image->sections[section].base_address,
+                       4, buf, &size_read)) != ERROR_OK)
+               {
+                       ERROR("error while reading instruction: %i", retval);
+                       return ERROR_TRACE_INSTRUCTION_UNAVAILABLE;
+               }
+               opcode = target_buffer_get_u32(target, buf);
+               arm_evaluate_opcode(opcode, xscale->trace.current_pc, instruction);
+       }
+       else if (xscale->trace.core_state == ARMV4_5_STATE_THUMB)
+       {
+               u8 buf[2];
+               if ((retval = image_read_section(xscale->trace.image, section, 
+                       xscale->trace.current_pc - xscale->trace.image->sections[section].base_address,
+                       2, buf, &size_read)) != ERROR_OK)
+               {
+                       ERROR("error while reading instruction: %i", retval);
+                       return ERROR_TRACE_INSTRUCTION_UNAVAILABLE;
+               }
+               opcode = target_buffer_get_u16(target, buf);
+               thumb_evaluate_opcode(opcode, xscale->trace.current_pc, instruction);
+       }
+       else
+       {
+               ERROR("BUG: unknown core state encountered");
+               exit(-1);
+       }
+       
+       return ERROR_OK;
+}
+
+int xscale_branch_address(xscale_trace_data_t *trace_data, int i, u32 *target)
+{
+       /* if there are less than four entries prior to the indirect branch message
+        * we can't extract the address */
+       if (i < 4)
+       {
+               return -1;
+       }
+       
+       *target = (trace_data->entries[i-1].data) | (trace_data->entries[i-2].data << 8) |
+                               (trace_data->entries[i-3].data << 16) | (trace_data->entries[i-4].data << 24);
+       
+       return 0;
+}
+
+int xscale_analyze_trace(target_t *target, command_context_t *cmd_ctx)
+{
+       /* get pointers to arch-specific information */
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       xscale_common_t *xscale = armv4_5->arch_info;
+       int next_pc_ok = 0;
+       u32 next_pc = 0x0;
+       xscale_trace_data_t *trace_data = xscale->trace.data;
+       int retval;
+       
+       while (trace_data)
+       {
+               int i, chkpt;
+               int rollover;
+               int branch;
+               int exception;
+               xscale->trace.core_state = ARMV4_5_STATE_ARM;
+
+               chkpt = 0;
+               rollover = 0;
+               
+               for (i = 0; i < trace_data->depth; i++)
+               {
+                       next_pc_ok = 0;
+                       branch = 0;
+                       exception = 0;
+                       
+                       if (trace_data->entries[i].type == XSCALE_TRACE_ADDRESS)
+                               continue;
+                       
+                       switch ((trace_data->entries[i].data & 0xf0) >> 4)
+                       {
+                               case 0:         /* Exceptions */
+                               case 1:
+                               case 2:
+                               case 3:
+                               case 4:
+                               case 5:
+                               case 6:
+                               case 7:
+                                       exception = (trace_data->entries[i].data & 0x70) >> 4;
+                                       next_pc_ok = 1;
+                                       next_pc = (trace_data->entries[i].data & 0xf0) >> 2;
+                                       command_print(cmd_ctx, "--- exception %i ---", (trace_data->entries[i].data & 0xf0) >> 4);
+                                       break;
+                               case 8:         /* Direct Branch */
+                                       branch = 1;
+                                       break;
+                               case 9:         /* Indirect Branch */
+                                       branch = 1;
+                                       if (xscale_branch_address(trace_data, i, &next_pc) == 0)
+                                       {
+                                               next_pc_ok = 1;
+                                       }
+                                       break;
+                               case 13:        /* Checkpointed Indirect Branch */
+                                       if (xscale_branch_address(trace_data, i, &next_pc) == 0)
+                                       {
+                                               next_pc_ok = 1;
+                                               if (((chkpt == 0) && (next_pc != trace_data->chkpt0))
+                                                       || ((chkpt == 1) && (next_pc != trace_data->chkpt1)))
+                                                       WARNING("checkpointed indirect branch target address doesn't match checkpoint");
+                                       }
+                                       /* explicit fall-through */
+                               case 12:        /* Checkpointed Direct Branch */
+                                       branch = 1;
+                                       if (chkpt == 0)
+                                       {
+                                               next_pc_ok = 1;
+                                               next_pc = trace_data->chkpt0;
+                                               chkpt++;
+                                       }
+                                       else if (chkpt == 1)
+                                       {
+                                               next_pc_ok = 1;
+                                               next_pc = trace_data->chkpt0;
+                                               chkpt++;
+                                       }
+                                       else
+                                       {
+                                               WARNING("more than two checkpointed branches encountered");
+                                       }
+                                       break;
+                               case 15:        /* Roll-over */
+                                       rollover++;
+                                       continue;
+                               default:        /* Reserved */
+                                       command_print(cmd_ctx, "--- reserved trace message ---");
+                                       ERROR("BUG: trace message %i is reserved", (trace_data->entries[i].data & 0xf0) >> 4);
+                                       return ERROR_OK;
+                       }
+                       
+                       if (xscale->trace.pc_ok)
+                       {
+                               int executed = (trace_data->entries[i].data & 0xf) + rollover * 16;
+                               arm_instruction_t instruction;
+                               
+                               if ((exception == 6) || (exception == 7))
+                               {
+                                       /* IRQ or FIQ exception, no instruction executed */ 
+                                       executed -= 1;
+                               }
+                               
+                               while (executed-- >= 0)
+                               {
+                                       if ((retval = xscale_read_instruction(target, &instruction)) != ERROR_OK)
+                                       {
+                                               /* can't continue tracing with no image available */
+                                               if (retval == ERROR_TRACE_IMAGE_UNAVAILABLE)
+                                               {
+                                                       return retval;
+                                               }
+                                               else if (retval == ERROR_TRACE_INSTRUCTION_UNAVAILABLE)
+                                               {
+                                                       /* TODO: handle incomplete images */
+                                               }
+                                       }
+                                       
+                                       /* a precise abort on a load to the PC is included in the incremental
+                                        * word count, other instructions causing data aborts are not included
+                                        */
+                                       if ((executed == 0) && (exception == 4)
+                                               && ((instruction.type >= ARM_LDR) && (instruction.type <= ARM_LDM)))
+                                       {
+                                               if ((instruction.type == ARM_LDM)
+                                                       && ((instruction.info.load_store_multiple.register_list & 0x8000) == 0))
+                                               {
+                                                       executed--;
+                                               }
+                                               else if (((instruction.type >= ARM_LDR) && (instruction.type <= ARM_LDRSH))
+                                                       && (instruction.info.load_store.Rd != 15))
+                                               {
+                                                       executed--;
+                                               }
+                                       }
+
+                                       /* only the last instruction executed
+                                        * (the one that caused the control flow change)
+                                        * could be a taken branch
+                                        */
+                                       if (((executed == -1) && (branch == 1)) &&
+                                               (((instruction.type == ARM_B) ||
+                                                       (instruction.type == ARM_BL) ||
+                                                       (instruction.type == ARM_BLX)) &&
+                                                       (instruction.info.b_bl_bx_blx.target_address != -1)))
+                                       {
+                                               xscale->trace.current_pc = instruction.info.b_bl_bx_blx.target_address;
+                                       }
+                                       else
+                                       {
+                                               xscale->trace.current_pc += (xscale->trace.core_state == ARMV4_5_STATE_ARM) ? 4 : 2;
+                                       }
+                                       command_print(cmd_ctx, "%s", instruction.text);
+                               }
+                               
+                               rollover = 0;
+                       }
+                       
+                       if (next_pc_ok)
+                       {
+                               xscale->trace.current_pc = next_pc;
+                               xscale->trace.pc_ok = 1;
+                       }
+               }
+               
+               for (; xscale->trace.current_pc < trace_data->last_instruction; xscale->trace.current_pc += (xscale->trace.core_state == ARMV4_5_STATE_ARM) ? 4 : 2)
+               {
+                       arm_instruction_t instruction;
+                       if ((retval = xscale_read_instruction(target, &instruction)) != ERROR_OK)
+                       {
+                               /* can't continue tracing with no image available */
+                               if (retval == ERROR_TRACE_IMAGE_UNAVAILABLE)
+                               {
+                                       return retval;
+                               }
+                               else if (retval == ERROR_TRACE_INSTRUCTION_UNAVAILABLE)
+                               {
+                                       /* TODO: handle incomplete images */
+                               }
+                       }
+                       command_print(cmd_ctx, "%s", instruction.text);
+               }
+               
+               trace_data = trace_data->next;
+       }
+       
+       return ERROR_OK;
+}
+
 void xscale_build_reg_cache(target_t *target)
 {
        /* get pointers to arch-specific information */
@@ -2592,7 +2968,9 @@ int xscale_init_target(struct command_context_s *cmd_ctx, struct target_s *targe
        
        /* assert TRST once during startup */
        jtag_add_reset(1, 0);
+       jtag_add_sleep(5000);
        jtag_add_reset(0, 0);
+       jtag_execute_queue();
        
        return ERROR_OK;
 }
@@ -2688,8 +3066,11 @@ int xscale_init_arch_info(target_t *target, xscale_common_t *xscale, int chain_p
        
        xscale->vector_catch = 0x1;
        
-       xscale->trace_buffer_enabled = 0;
-       xscale->trace_buffer_fill = 0;
+       xscale->trace.capture_status = TRACE_IDLE;
+       xscale->trace.data = NULL;
+       xscale->trace.image = NULL;
+       xscale->trace.buffer_enabled = 0;
+       xscale->trace.buffer_fill = 0;
        
        /* prepare ARMv4/5 specific information */
        armv4_5->arch_info = xscale;
@@ -3022,28 +3403,45 @@ int xscale_handle_trace_buffer_command(struct command_context_s *cmd_ctx, char *
        
        if ((argc >= 1) && (strcmp("enable", args[0]) == 0))
        {
-               xscale->trace_buffer_enabled = 1;
+               xscale_trace_data_t *td, *next_td;
+               xscale->trace.buffer_enabled = 1;
+               
+               /* free old trace data */
+               td = xscale->trace.data;
+               while (td)
+               {
+                       next_td = td->next;
+                       
+                       if (td->entries)
+                               free(td->entries);
+                       free(td);
+                       td = next_td;
+               }
+               xscale->trace.data = NULL;
        }
        else if ((argc >= 1) && (strcmp("disable", args[0]) == 0))
        {
-               xscale->trace_buffer_enabled = 0;
+               xscale->trace.buffer_enabled = 0;
        }
 
        if ((argc >= 2) && (strcmp("fill", args[1]) == 0))
        {
-               xscale->trace_buffer_fill = 1;
+               if (argc >= 3)
+                       xscale->trace.buffer_fill = strtoul(args[2], NULL, 0);
+               else
+                       xscale->trace.buffer_fill = 1;
        }
        else if ((argc >= 2) && (strcmp("wrap", args[1]) == 0))
        {
-               xscale->trace_buffer_fill = 0;
+               xscale->trace.buffer_fill = -1;
        }
        
        command_print(cmd_ctx, "trace buffer %s (%s)", 
-               (xscale->trace_buffer_enabled) ? "enabled" : "disabled",
-               (xscale->trace_buffer_fill) ? "fill" : "wrap");
+               (xscale->trace.buffer_enabled) ? "enabled" : "disabled",
+               (xscale->trace.buffer_fill > 0) ? "fill" : "wrap");
 
        dcsr_value = buf_get_u32(xscale->reg_cache->reg_list[XSCALE_DCSR].value, 0, 32);
-       if (xscale->trace_buffer_fill)
+       if (xscale->trace.buffer_fill >= 0)
                xscale_write_dcsr_sw(target, (dcsr_value & 0xfffffffc) | 2);
        else
                xscale_write_dcsr_sw(target, dcsr_value & 0xfffffffc);
@@ -3051,14 +3449,19 @@ int xscale_handle_trace_buffer_command(struct command_context_s *cmd_ctx, char *
        return ERROR_OK;
 }
 
-int xscale_handle_dump_trace_buffer_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+int xscale_handle_trace_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
 {
-       target_t *target = get_current_target(cmd_ctx);
+       target_t *target;
        armv4_5_common_t *armv4_5;
        xscale_common_t *xscale;
-       u32 trace_buffer[258];
-       int is_address[256];
-       int i;
+
+       if (argc < 1)
+       {
+               command_print(cmd_ctx, "usage: xscale trace_image <file> [base address] [type]");
+               return ERROR_OK;
+       }
+       
+       target = get_current_target(cmd_ctx);
        
        if (xscale_get_arch_pointers(target, &armv4_5, &xscale) != ERROR_OK)
        {
@@ -3066,107 +3469,68 @@ int xscale_handle_dump_trace_buffer_command(struct command_context_s *cmd_ctx, c
                return ERROR_OK;
        }
        
-       if (target->state != TARGET_HALTED)
+       if (xscale->trace.image)
        {
-               command_print(cmd_ctx, "target must be stopped for \"%s\" command", cmd);
-               return ERROR_OK;
+               image_close(xscale->trace.image);
+               free(xscale->trace.image);
+               command_print(cmd_ctx, "previously loaded image found and closed");
        }
-
-       /* send read trace buffer command (command 0x61) */
-       xscale_send_u32(target, 0x61);
        
-       /* receive trace buffer content */
-       xscale_receive(target, trace_buffer, 258);
+       xscale->trace.image = malloc(sizeof(image_t));
+       xscale->trace.image->base_address_set = 0;
+       xscale->trace.image->start_address_set = 0;
        
-       for (i = 255; i >= 0; i--)
+       /* a base address isn't always necessary, default to 0x0 (i.e. don't relocate) */
+       if (argc >= 2)
        {
-               is_address[i] = 0;
-               if (((trace_buffer[i] & 0xf0) == 0x90) ||
-                       ((trace_buffer[i] & 0xf0) == 0xd0)) 
-               {
-                       if (i >= 4)
-                               is_address[--i] = 1;
-                       if (i >= 3)
-                               is_address[--i] = 1;
-                       if (i >= 2)
-                               is_address[--i] = 1;
-                       if (i >= 1)
-                               is_address[--i] = 1;
-               }
+               xscale->trace.image->base_address_set = 1;
+               xscale->trace.image->base_address = strtoul(args[1], NULL, 0);
+       }
+       else
+       {
+               xscale->trace.image->base_address_set = 0;
+       }
+               
+       if (image_open(xscale->trace.image, args[0], (argc >= 3) ? args[2] : NULL) != ERROR_OK)
+       {
+               command_print(cmd_ctx, "image opening error: %s", xscale->trace.image->error_str);
+               free(xscale->trace.image);
+               xscale->trace.image = NULL;
+               return ERROR_OK;
        }
        
-       for (i = 0; i < 256; i++)
+       return ERROR_OK;
+}
+
+int xscale_handle_dump_trace_buffer_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       target_t *target = get_current_target(cmd_ctx);
+       armv4_5_common_t *armv4_5;
+       xscale_common_t *xscale;
+
+       if (xscale_get_arch_pointers(target, &armv4_5, &xscale) != ERROR_OK)
        {
-#if 0
-               command_print(cmd_ctx, "0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x",
-                       trace_buffer[i + 0], trace_buffer[i + 1], trace_buffer[i + 2], trace_buffer[i + 3],
-                       trace_buffer[i + 4], trace_buffer[i + 5], trace_buffer[i + 6], trace_buffer[i + 6]
-                       );
-               i += 8;
-#endif
-               if (is_address[i])
-               {
-                       command_print(cmd_ctx, "address: 0x%2.2x%2.2x%2.2x%2.2x", trace_buffer[i], trace_buffer[i+1], trace_buffer[i+2], trace_buffer[i+3]);
-                       i += 3; 
-               }
-               else
-               {
-                       switch ((trace_buffer[i] & 0xf0) >> 4)
-                       {
-                               case 0:
-                                       command_print(cmd_ctx, "0x%2.2x: reset exception", trace_buffer[i]);
-                                       break;
-                               case 1:
-                                       command_print(cmd_ctx, "0x%2.2x: undef exception", trace_buffer[i]);
-                                       break;
-                               case 2:
-                                       command_print(cmd_ctx, "0x%2.2x: swi exception", trace_buffer[i]);
-                                       break;
-                               case 3:
-                                       command_print(cmd_ctx, "0x%2.2x: pabort exception", trace_buffer[i]);
-                                       break;
-                               case 4:
-                                       command_print(cmd_ctx, "0x%2.2x: dabort exception", trace_buffer[i]);
-                                       break;
-                               case 5:
-                                       command_print(cmd_ctx, "0x%2.2x: invalid", trace_buffer[i]);
-                                       break;
-                               case 6:
-                                       command_print(cmd_ctx, "0x%2.2x: irq exception", trace_buffer[i]);
-                                       break;
-                               case 7:
-                                       command_print(cmd_ctx, "0x%2.2x: fiq exception", trace_buffer[i]);
-                                       break;
-                               case 0x8:
-                                       command_print(cmd_ctx, "0x%2.2x: direct branch", trace_buffer[i]);
-                                       break;
-                               case 0x9:
-                                       command_print(cmd_ctx, "0x%2.2x: indirect branch", trace_buffer[i]);
-                                       break;
-                               case 0xa:
-                                       command_print(cmd_ctx, "0x%2.2x: invalid", trace_buffer[i]);
-                                       break;
-                               case 0xb:
-                                       command_print(cmd_ctx, "0x%2.2x: invalid", trace_buffer[i]);
-                                       break;
-                               case 0xc:
-                                       command_print(cmd_ctx, "0x%2.2x: checkpointed direct branch", trace_buffer[i]);
-                                       break;
-                               case 0xd:
-                                       command_print(cmd_ctx, "0x%2.2x: checkpointed indirect branch", trace_buffer[i]);
-                                       break;
-                               case 0xe:
-                                       command_print(cmd_ctx, "0x%2.2x: invalid", trace_buffer[i]);
-                                       break;
-                               case 0xf:
-                                       command_print(cmd_ctx, "0x%2.2x: rollover", trace_buffer[i]);
-                                       break;
-                       } 
-               }
+               command_print(cmd_ctx, "target isn't an XScale target");
+               return ERROR_OK;
        }
        
-       command_print(cmd_ctx, "chkpt0: 0x%8.8x, chkpt1: 0x%8.8x", trace_buffer[256], trace_buffer[257]);
+       return ERROR_OK;        
+}
+
+int xscale_handle_analyze_trace_buffer_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       target_t *target = get_current_target(cmd_ctx);
+       armv4_5_common_t *armv4_5;
+       xscale_common_t *xscale;
 
+       if (xscale_get_arch_pointers(target, &armv4_5, &xscale) != ERROR_OK)
+       {
+               command_print(cmd_ctx, "target isn't an XScale target");
+               return ERROR_OK;
+       }
+       
+       xscale_analyze_trace(target, cmd_ctx);
+       
        return ERROR_OK;        
 }
 
@@ -3190,7 +3554,10 @@ int xscale_register_commands(struct command_context_s *cmd_ctx)
        register_command(cmd_ctx, xscale_cmd, "trace_buffer", xscale_handle_trace_buffer_command, COMMAND_EXEC, "<enable|disable> ['fill'|'wrap']");
 
        register_command(cmd_ctx, xscale_cmd, "dump_trace_buffer", xscale_handle_dump_trace_buffer_command, COMMAND_EXEC, "dump content of trace buffer");
-       
+       register_command(cmd_ctx, xscale_cmd, "analyze_trace", xscale_handle_analyze_trace_buffer_command, COMMAND_EXEC, "analyze content of trace buffer");
+       register_command(cmd_ctx, xscale_cmd, "trace_image", xscale_handle_trace_image_command,
+               COMMAND_EXEC, "load image from <file> [base address]");
+               
        armv4_5_register_commands(cmd_ctx);
        
        return ERROR_OK;
index 9fcb265e4721b3b5bf260a3494de7b826595b0f9..86acfbdee7a3f724bafd31345c2f92a60df10582 100644 (file)
@@ -24,6 +24,8 @@
 #include "register.h"
 #include "armv4_5.h"
 #include "armv4_5_mmu.h"
+#include "trace.h"
+#include "image.h"
 
 #define        XSCALE_COMMON_MAGIC 0x58534341
 
@@ -47,6 +49,40 @@ enum xscale_debug_reason
        XSCALE_DBG_REASON_TB_FULL,
 };
 
+enum xscale_trace_entry_type
+{
+       XSCALE_TRACE_MESSAGE,
+       XSCALE_TRACE_ADDRESS,
+};
+
+typedef struct xscale_trace_entry_s
+{
+       u8 data;
+       enum xscale_trace_entry_type type;
+} xscale_trace_entry_t;
+
+typedef struct xscale_trace_data_s
+{
+       xscale_trace_entry_t *entries;
+       int depth;
+       u32 chkpt0;
+       u32 chkpt1;
+       u32 last_instruction;
+       struct xscale_trace_data_s *next;
+} xscale_trace_data_t;
+
+typedef struct xscale_trace_s
+{
+       trace_status_t capture_status;  /* current state of capture run */
+       image_t *image;                                 /* source for target opcodes */
+       xscale_trace_data_t *data;              /* linked list of collected trace data */
+       int buffer_enabled;                             /* whether trace buffer is enabled */
+       int buffer_fill;                                /* maximum number of trace runs to read (-1 for wrap-around) */
+       int pc_ok;
+       u32 current_pc;
+       armv4_5_state_t core_state;             /* current core state (ARM, Thumb, Jazelle) */
+} xscale_trace_t;
+
 typedef struct xscale_common_s
 {
        int common_magic;
@@ -93,9 +129,8 @@ typedef struct xscale_common_s
        u16 thumb_bkpt;
        
        u8 vector_catch;
-       
-       int trace_buffer_enabled;
-       int trace_buffer_fill;
+
+       xscale_trace_t trace;
        
        int arch_debug_reason;
        
@@ -142,4 +177,6 @@ enum
        XSCALE_TXRXCTRL,
 };
 
+#define ERROR_XSCALE_NO_TRACE_DATA     (-1500)
+
 #endif /* XSCALE_H */

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)