- added manpage for OpenOCD (thanks to Uwe Hermann)
authordrath <drath@b42882b7-edfa-0310-969c-e2dbd0fdcd60>
Thu, 14 Jun 2007 09:47:00 +0000 (09:47 +0000)
committerdrath <drath@b42882b7-edfa-0310-969c-e2dbd0fdcd60>
Thu, 14 Jun 2007 09:47:00 +0000 (09:47 +0000)
- fixed bug in ARM926EJ-S cache handling that caused cache linefills to be disabled after first debug entry
- added support for auto image type detection (thanks to Vincent Palatin)
- further work on ETM trace decoding (tested with a ETB interface using an ETM in normal 16-bit port mode, still experimental)

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

16 files changed:
README
configure.in
doc/openocd.1 [new file with mode: 0644]
src/flash/flash.c
src/helper/fileio.c
src/openocd.c
src/target/arm926ejs.c
src/target/arm_disassembler.c
src/target/arm_disassembler.h
src/target/etb.c
src/target/etm.c
src/target/etm.h
src/target/image.c
src/target/image.h
src/target/target.c
src/target/trace.h

diff --git a/README b/README
index 3dc5865c705705f0ebe615b62089ef5a514e7a8c..2defb5d1ec6bbd5197b3a2fa6a4c70881534bbb3 100644 (file)
--- a/README
+++ b/README
@@ -2,7 +2,7 @@
 
                         Free and Open On-Chip Debugging, In-System Programming 
                                                   and Boundary-Scan Testing
 
                         Free and Open On-Chip Debugging, In-System Programming 
                                                   and Boundary-Scan Testing
-                                 Copyright (c) 2004, 2005, 2006 Dominic Rath
+                                 Copyright (c) 2004-2007 Dominic Rath
 
 The debugger uses an IEEE 1149-1 compliant JTAG TAP bus master to access on-chip
 debug functionality available on ARM7 and ARM9 based microcontrollers /
 
 The debugger uses an IEEE 1149-1 compliant JTAG TAP bus master to access on-chip
 debug functionality available on ARM7 and ARM9 based microcontrollers /
@@ -67,22 +67,28 @@ with many Linux distributions.
 
 2. Supported cores
 
 
 2. Supported cores
 
-This version of openocd supports the following cores:
+This version of openocd supports the following ARM7/9 cores:
 
 - ARM7TDMI(-s)
 - ARM9TDMI
 - ARM920t
 - ARM922t
 
 - ARM7TDMI(-s)
 - ARM9TDMI
 - ARM920t
 - ARM922t
+- ARM926ej-s
 - ARM966e
 
 - ARM966e
 
-Support for Intel XScale CPUs (PXA25x, PXA27x and IXP4xx) is currently being
-developed.
+Support for Intel XScale CPUs is also included:
 
 
+- PXA25x
+- IXP42x
+
+PXA27x debugging should be similar to the PXA25x but fails in the current
+version of OpenOCD.
 3. Host platforms
 
 OpenOCD was originally developed on x86-Linux, but has since then been ported
 to run on Windows/Cygwin, native Windows with MinGW, FreeBSD, x86-64-Linux and
 3. Host platforms
 
 OpenOCD was originally developed on x86-Linux, but has since then been ported
 to run on Windows/Cygwin, native Windows with MinGW, FreeBSD, x86-64-Linux and
-(though it's not fully working yet) PowerPC OS-X.
+PowerPC OS-X.
 
 4. Documentation
 
 
 4. Documentation
 
index cdee2b853a1e6824bb1412f19733d78966f52c01..69b1510ef6d6412a82d24ff10857014532225629 100644 (file)
@@ -4,6 +4,8 @@ AC_SEARCH_LIBS([ioperm], [ioperm])
 
 AC_CANONICAL_HOST
 
 
 AC_CANONICAL_HOST
 
+AC_CHECK_HEADERS(sys/param.h)
+
 AC_C_BIGENDIAN
 
 AC_CHECK_FUNCS(strndup)
 AC_C_BIGENDIAN
 
 AC_CHECK_FUNCS(strndup)
diff --git a/doc/openocd.1 b/doc/openocd.1
new file mode 100644 (file)
index 0000000..d313530
--- /dev/null
@@ -0,0 +1,103 @@
+.TH "OPENOCD" "1" "May 03, 2007" "" ""
+.SH "NAME"
+openocd \- A free and open on\-chip debugging, in\-system programming and
+boundary\-scan testing tool for ARM systems (currently ARM7/9 and XScale, Cortex\-M3 support to be merged)
+.SH "SYNOPSIS"
+.B openocd \fR[\fB\-fdlh\fR] [\fB\-\-file\fR <filename>] [\fB\-\-debug\fR <debuglevel>] [\fB\-\-log_output\fR <filename>] [\fB\-\-help]
+.SH "DESCRIPTION"
+.B OpenOCD
+is an on\-chip debugging, in\-system programming and boundary\-scan
+testing tool for ARM systems.
+.PP 
+The debugger uses an IEEE 1149\-1 compliant JTAG TAP bus master to access
+on\-chip debug functionality available on ARM7/9 and XScale based
+microcontrollers / system\-on\-chip solutions.
+.PP 
+User interaction is realized through a telnet command line interface and
+a gdb (the GNU debugger) remote protocol server.
+.PP 
+OpenOCD supports various different types of JTAG interfaces/programmers:
+  * Parallel port wigglers
+  * Amontec JTAG Accelerator
+  * FTDI FT2232 based USB devices
+  * USBJTAG
+  * OOCD\-Link
+  * Amontec JTAGkey
+  * Amontec JTAGkey\-Tiny
+  * Olimex ARM\-USB\-OCD
+  * eVerve Signalyzer
+  * ... other FT2232 based dongles
+.PP 
+It also supports a number of different ARM7/9 cores:
+  * ARM7TDMI(\-s)
+  * ARM720t
+  * ARM9TDMI
+  * ARM920t
+  * ARM922t
+  * ARM926ej\-s
+  * ARM966e
+.PP 
+Support for Intel XScale CPUs is also included:
+  * PXA25x
+  * IXP42x
+
+PXA27x debugging should be similar to the PXA25x but fails in the current
+version of OpenOCD.
+.SH "OPTIONS"
+.TP 
+.B "\-f, \-\-file <filename>"
+Use configuration file
+.BR <filename> .
+If this option is omitted, the config file
+.B openocd.cfg
+in the current working directory will be used.
+.TP 
+.B "\-d, \-\-debug <debuglevel>"
+Set debug level. Possible values are:
+.br 
+.RB "  * " 0 " (errors)"
+.br 
+.RB "  * " 1 " (warnings)"
+.br 
+.RB "  * " 2 " (informational messages)"
+.br 
+.RB "  * " 3 " (debug messages)"
+.br 
+The default level is
+.BR 2 .
+.TP 
+.B "\-l, \-\-log_output <filename>"
+Redirect log output to the file
+.BR <filename> .
+Per default the log output is printed on
+.BR stderr .
+.TP 
+.B "\-h, \-\-help"
+Show a help text and exit.
+.\".TP 
+.\".B "\-v, \-\-version"
+.\"Show version information and exit.
+.SH "BUGS"
+Please report any bugs at
+.B http://developer.berlios.de/bugs/?group_id=4148
+or on the mailing list
+.BR openocd\-development@lists.berlios.de .
+.SH "LICENCE"
+.B OpenOCD
+is covered by the GNU General Public License (GPL), version 2 or later.
+.\"
+.SH "SEE ALSO"
+
+.SH "AUTHORS"
+Dominic Rath <Dominic.Rath@gmx.de>
+.br 
+Magnus Lundin <lundin@mlu.mine.nu>
+.br 
+Michael Fischer <fischermi@t\-online.de>
+.br 
+Spencer Oliver <spen@spen\-soft.co.uk>
+.br 
+and others
+.PP 
+This manual page was written by Uwe Hermann <uwe@hermann\-uwe.de>.
+It is licensed under the terms of the GNU GPL (v2 or later).
index 58a467d2b30b66e53186d2dc658e7abb8473f67d..fecb89b72d3d23c749c341bf3c0fc40b0bea92eb 100644 (file)
@@ -511,8 +511,6 @@ int handle_flash_write_command(struct command_context_s *cmd_ctx, char *cmd, cha
        
        duration_start_measure(&duration);
        
        
        duration_start_measure(&duration);
        
-       identify_image_type(&image.type, (argc == 4) ? args[3] : NULL);
-
        image.base_address_set = 1;
        image.base_address = strtoul(args[1], NULL, 0);
        
        image.base_address_set = 1;
        image.base_address = strtoul(args[1], NULL, 0);
        
@@ -526,7 +524,7 @@ int handle_flash_write_command(struct command_context_s *cmd_ctx, char *cmd, cha
                return ERROR_OK;
        }
        
                return ERROR_OK;
        }
        
-       if (image_open(&image, args[1], FILEIO_READ) != ERROR_OK)
+       if (image_open(&image, args[1], (argc == 4) ? args[3] : NULL) != ERROR_OK)
        {
                command_print(cmd_ctx, "flash write error: %s", image.error_str);
                return ERROR_OK;
        {
                command_print(cmd_ctx, "flash write error: %s", image.error_str);
                return ERROR_OK;
index 3a760cd82f8ba042c51e931fd35d9ed6a52a9d8c..7075fc160ba30f9dd0e49414689e0cad498e975b 100644 (file)
@@ -258,6 +258,27 @@ int fileio_read(fileio_t *fileio, u32 size, u8 *buffer, u32 *size_read)
        }
 }
 
        }
 }
 
+int fileio_read_u32(fileio_t *fileio, u32 *data)
+{
+       u8 buf[4];
+       u32 size_read;
+       int retval;
+       
+       switch (fileio->location)
+       {
+               case FILEIO_LOCAL:
+                       if ((retval = fileio_local_read(fileio, 4, buf, &size_read)) != ERROR_OK)
+                               return retval;
+                       *data = be_to_h_u32(buf);
+                       break;
+               default:
+                       ERROR("BUG: should never get here");
+                       exit(-1);
+       }
+       
+       return ERROR_OK;
+}
+
 int fileio_local_write(fileio_t *fileio, u32 size, u8 *buffer, u32 *size_written)
 {
        fileio_local_t *fileio_local = fileio->location_private;
 int fileio_local_write(fileio_t *fileio, u32 size, u8 *buffer, u32 *size_written)
 {
        fileio_local_t *fileio_local = fileio->location_private;
@@ -280,3 +301,24 @@ int fileio_write(fileio_t *fileio, u32 size, u8 *buffer, u32 *size_written)
        
        return ERROR_OK;
 }
        
        return ERROR_OK;
 }
+
+int fileio_write_u32(fileio_t *fileio, u32 data)
+{
+       u8 buf[4];
+       u32 size_written;
+       int retval;
+       
+       h_u32_to_be(buf, data);
+       
+       switch (fileio->location)
+       {
+               case FILEIO_LOCAL:
+                       if ((retval = fileio_local_write(fileio, 4, buf, &size_written)) != ERROR_OK)
+                               return retval;
+                       break;
+               default:
+                       ERROR("BUG: should never get here");
+       }
+       
+       return ERROR_OK;
+}
index 9601b9ef1baf96969f39310d34e61a3b6709a3e1..ac8e2fea0d1122628544fe3426658555d7f399ba 100644 (file)
@@ -18,7 +18,7 @@
  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
  ***************************************************************************/
 
  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
  ***************************************************************************/
 
-#define OPENOCD_VERSION "Open On-Chip Debugger (2007-05-30 17:45 CEST)"
+#define OPENOCD_VERSION "Open On-Chip Debugger (2007-06-14 12:00 CEST)"
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
index 89fbfae3b05f52fc215e20dde4ac03df64f835ec..b62bc49399b5d3bf51ac54fb4bd2d6d517a824e0 100644 (file)
@@ -477,7 +477,7 @@ void arm926ejs_pre_restore_context(target_t *target)
        /* read-modify-write CP15 cache debug control register 
         * to reenable I/D-cache linefills and disable WT */
        arm926ejs_read_cp15(target, ARM926EJS_CP15_ADDR(7, 0, 15, 0), &cache_dbg_ctrl);
        /* read-modify-write CP15 cache debug control register 
         * to reenable I/D-cache linefills and disable WT */
        arm926ejs_read_cp15(target, ARM926EJS_CP15_ADDR(7, 0, 15, 0), &cache_dbg_ctrl);
-       cache_dbg_ctrl |= 0x7;
+       cache_dbg_ctrl &= ~0x7;
        arm926ejs_write_cp15(target, ARM926EJS_CP15_ADDR(7, 0, 15, 0), cache_dbg_ctrl);
 }
 
        arm926ejs_write_cp15(target, ARM926EJS_CP15_ADDR(7, 0, 15, 0), cache_dbg_ctrl);
 }
 
index 1c275f54645a897e70c4cbede7f8806264838e94..ed7fe655f8173bf143445262179b940e903688b8 100644 (file)
@@ -2080,3 +2080,37 @@ int thumb_evaluate_opcode(u16 opcode, u32 address, arm_instruction_t *instructio
        return -1;
 }
 
        return -1;
 }
 
+int arm_access_size(arm_instruction_t *instruction)
+{
+       if ((instruction->type == ARM_LDRB)
+               || (instruction->type == ARM_LDRBT)
+               || (instruction->type == ARM_LDRSB)
+               || (instruction->type == ARM_STRB)
+               || (instruction->type == ARM_STRBT))
+       {
+               return 1;
+       }
+       else if ((instruction->type == ARM_LDRH)
+               || (instruction->type == ARM_LDRSH)
+               || (instruction->type == ARM_STRH))
+       {
+               return 2;
+       }
+       else if ((instruction->type == ARM_LDR)
+               || (instruction->type == ARM_LDRT)
+               || (instruction->type == ARM_STR)
+               || (instruction->type == ARM_STRT))
+       {
+               return 4;
+       }
+       else if ((instruction->type == ARM_LDRD)
+               || (instruction->type == ARM_STRD))
+       {
+               return 8;
+       }
+       else
+       {
+               ERROR("BUG: instruction type %i isn't a load/store instruction", instruction->type);
+               return 0;
+       }
+}
index bdab113ddaa6e855a26a19aa0453dc8e7affaf49..d0fcabd863169886ff82bec582eac6487dab7b64 100644 (file)
@@ -196,6 +196,7 @@ typedef struct arm_instruction_s
 
 extern int arm_evaluate_opcode(u32 opcode, u32 address, arm_instruction_t *instruction);
 extern int thumb_evaluate_opcode(u16 opcode, u32 address, arm_instruction_t *instruction);
 
 extern int arm_evaluate_opcode(u32 opcode, u32 address, arm_instruction_t *instruction);
 extern int thumb_evaluate_opcode(u16 opcode, u32 address, arm_instruction_t *instruction);
+extern int arm_access_size(arm_instruction_t *instruction);
 
 #define COND(opcode) (arm_condition_strings[(opcode & 0xf0000000)>>28])
 
 
 #define COND(opcode) (arm_condition_strings[(opcode & 0xf0000000)>>28])
 
index 257c4b182a27c334b93f801415762c571ddfd55a..81e20af01c23b86e7015f0cc5a655dfbb572a2d6 100644 (file)
@@ -582,11 +582,29 @@ int etb_read_trace(etm_context_t *etm_ctx)
                {
                        etm_ctx->trace_data[j].pipestat = trace_data[i] & 0x7;
                        etm_ctx->trace_data[j].packet = (trace_data[i] & 0x7f8) >> 3;
                {
                        etm_ctx->trace_data[j].pipestat = trace_data[i] & 0x7;
                        etm_ctx->trace_data[j].packet = (trace_data[i] & 0x7f8) >> 3;
-                       etm_ctx->trace_data[j].tracesync = (trace_data[i] & 0x800) >> 11;
+                       etm_ctx->trace_data[j].flags = 0;
+                       if ((trace_data[i] & 0x800) >> 11)
+                       {
+                               etm_ctx->trace_data[j].flags |= ETMV1_TRACESYNC_CYCLE;
+                       }
+                       if (etm_ctx->trace_data[j].pipestat == STAT_TR)
+                       {
+                               etm_ctx->trace_data[j].pipestat = etm_ctx->trace_data[j].packet & 0x7;
+                               etm_ctx->trace_data[j].flags |= ETMV1_TRIGGER_CYCLE;
+                       }
 
                        etm_ctx->trace_data[j+1].pipestat = (trace_data[i] & 0x7000) >> 12;
                        etm_ctx->trace_data[j+1].packet = (trace_data[i] & 0x7f8000) >> 15;
 
                        etm_ctx->trace_data[j+1].pipestat = (trace_data[i] & 0x7000) >> 12;
                        etm_ctx->trace_data[j+1].packet = (trace_data[i] & 0x7f8000) >> 15;
-                       etm_ctx->trace_data[j+1].tracesync = (trace_data[i] & 0x800000) >> 23;
+                       etm_ctx->trace_data[j+1].flags = 0;
+                       if ((trace_data[i] & 0x800000) >> 23)
+                       {
+                               etm_ctx->trace_data[j+1].flags |= ETMV1_TRACESYNC_CYCLE;
+                       }
+                       if (etm_ctx->trace_data[j+1].pipestat == STAT_TR)
+                       {
+                               etm_ctx->trace_data[j+1].pipestat = etm_ctx->trace_data[j+1].packet & 0x7;
+                               etm_ctx->trace_data[j+1].flags |= ETMV1_TRIGGER_CYCLE;
+                       }
                        
                        j += 2;
                }
                        
                        j += 2;
                }
@@ -594,7 +612,16 @@ int etb_read_trace(etm_context_t *etm_ctx)
                {
                        etm_ctx->trace_data[j].pipestat = trace_data[i] & 0x7;
                        etm_ctx->trace_data[j].packet = (trace_data[i] & 0x7fff8) >> 3;
                {
                        etm_ctx->trace_data[j].pipestat = trace_data[i] & 0x7;
                        etm_ctx->trace_data[j].packet = (trace_data[i] & 0x7fff8) >> 3;
-                       etm_ctx->trace_data[j].tracesync = (trace_data[i] & 0x80000) >> 19;
+                       etm_ctx->trace_data[j].flags = 0;
+                       if ((trace_data[i] & 0x80000) >> 19)
+                       {
+                               etm_ctx->trace_data[j].flags |= ETMV1_TRACESYNC_CYCLE;
+                       }
+                       if (etm_ctx->trace_data[j].pipestat == STAT_TR)
+                       {
+                               etm_ctx->trace_data[j].pipestat = etm_ctx->trace_data[j].packet & 0x7;
+                               etm_ctx->trace_data[j].flags |= ETMV1_TRIGGER_CYCLE;
+                       }
                        
                        j += 1;
                }
                        
                        j += 1;
                }
index 02c33104a35c08285944102fc03669018ba6a4d1..a775bbd1f713abce1acd902f4144eee6588c431c 100644 (file)
@@ -28,6 +28,8 @@
 
 #include "armv4_5.h"
 #include "arm7_9_common.h"
 
 #include "armv4_5.h"
 #include "arm7_9_common.h"
+#include "arm_disassembler.h"
+#include "arm_simulator.h"
 
 #include "log.h"
 #include "arm_jtag.h"
 
 #include "log.h"
 #include "arm_jtag.h"
@@ -482,39 +484,499 @@ char *etmv1v1_branch_reason_strings[] =
        "reserved",
 };
 
        "reserved",
 };
 
-int etmv1_next_packet(etm_context_t *ctx, u8 *packet)
+int etm_read_instruction(etm_context_t *ctx, arm_instruction_t *instruction)
 {
 {
+       int i;
+       int section = -1;
+       u32 size_read;
+       u32 opcode;
+       int retval;
        
        
+       if (!ctx->image)
+               return ERROR_TRACE_IMAGE_UNAVAILABLE;
+       
+       /* search for the section the current instruction belongs to */ 
+       for (i = 0; i < ctx->image->num_sections; i++)
+       {
+               if ((ctx->image->sections[i].base_address <= ctx->current_pc) &&
+                       (ctx->image->sections[i].base_address + ctx->image->sections[i].size > ctx->current_pc))
+               {
+                       section = i;
+                       break;
+               }
+       }
+       
+       if (section == -1)
+       {
+               /* current instruction couldn't be found in the image */
+               return ERROR_TRACE_INSTRUCTION_UNAVAILABLE;
+       }
+       
+       if (ctx->core_state == ARMV4_5_STATE_ARM)
+       {
+               u8 buf[4];
+               if ((retval = image_read_section(ctx->image, section, 
+                       ctx->current_pc - ctx->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(ctx->target, buf);
+               arm_evaluate_opcode(opcode, ctx->current_pc, instruction);
+       }
+       else if (ctx->core_state == ARMV4_5_STATE_THUMB)
+       {
+               u8 buf[2];
+               if ((retval = image_read_section(ctx->image, section, 
+                       ctx->current_pc - ctx->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(ctx->target, buf);
+               thumb_evaluate_opcode(opcode, ctx->current_pc, instruction);
+       }
+       else if (ctx->core_state == ARMV4_5_STATE_JAZELLE)
+       {
+               ERROR("BUG: tracing of jazelle code not supported");
+               exit(-1);
+       }
+       else
+       {
+               ERROR("BUG: unknown core state encountered");
+               exit(-1);
+       }
        
        return ERROR_OK;
 }
 
        
        return ERROR_OK;
 }
 
-int etmv1_analyse_trace(etm_context_t *ctx)
+int etmv1_next_packet(etm_context_t *ctx, u8 *packet, int apo)
+{
+       while (ctx->data_index < ctx->trace_depth)
+       {
+               /* if the caller specified an address packet offset, skip until the
+                * we reach the n-th cycle marked with tracesync */
+               if (apo > 0)
+               {
+                       if (ctx->trace_data[ctx->data_index].flags & ETMV1_TRACESYNC_CYCLE)
+                               apo--;
+                       
+                       if (apo > 0)
+                       {
+                               ctx->data_index++;
+                               ctx->data_half = 0;
+                       }
+                       continue;
+               }
+               
+               /* no tracedata output during a TD cycle
+                * or in a trigger cycle */
+               if ((ctx->trace_data[ctx->data_index].pipestat == STAT_TD)
+                       || (ctx->trace_data[ctx->data_index].flags & ETMV1_TRIGGER_CYCLE))
+               {
+                       ctx->data_index++;
+                       ctx->data_half = 0;
+                       continue;
+               }
+               
+               if ((ctx->portmode & ETM_PORT_WIDTH_MASK) == ETM_PORT_16BIT)
+               {
+                       if (ctx->data_half == 0)
+                       {
+                               *packet = ctx->trace_data[ctx->data_index].packet & 0xff;
+                               ctx->data_half = 1;
+                       }
+                       else
+                       {
+                               *packet = (ctx->trace_data[ctx->data_index].packet & 0xff00) >> 8;
+                               ctx->data_half = 0;
+                               ctx->data_index++;
+                       }
+               }
+               else if ((ctx->portmode & ETM_PORT_WIDTH_MASK) == ETM_PORT_8BIT)
+               {
+                       *packet = ctx->trace_data[ctx->data_index].packet & 0xff;
+                       ctx->data_index++;
+               }
+               else
+               {
+                       /* on a 4-bit port, a packet will be output during two consecutive cycles */
+                       if (ctx->data_index > (ctx->trace_depth - 2))
+                               return -1;
+                       
+                       *packet = ctx->trace_data[ctx->data_index].packet & 0xf;
+                       *packet |= (ctx->trace_data[ctx->data_index + 1].packet & 0xf) << 4;
+                       ctx->data_index += 2;
+               }
+                                       
+               return 0;
+       }
+       
+       return -1;
+}
+
+int etmv1_branch_address(etm_context_t *ctx)
 {
 {
+       int retval;
+       u8 packet;
+       int shift = 0;
+       int apo;
+       int i;
+       
+       /* quit analysis if less than two cycles are left in the trace
+        * because we can't extract the APO */
+       if (ctx->data_index > (ctx->trace_depth - 2))
+               return -1;
+               
+       /* a BE could be output during an APO cycle, skip the current
+        * and continue with the new one */
+       if (ctx->trace_data[ctx->pipe_index + 1].pipestat & 0x4)
+               return 1;
+       if (ctx->trace_data[ctx->pipe_index + 2].pipestat & 0x4)
+               return 2;
+               
+       /* address packet offset encoded in the next two cycles' pipestat bits */
+       apo = ctx->trace_data[ctx->pipe_index + 1].pipestat & 0x3;
+       apo |= (ctx->trace_data[ctx->pipe_index + 2].pipestat & 0x3) << 2;
+       
+       /* count number of tracesync cycles between current pipe_index and data_index
+        * i.e. the number of tracesyncs that data_index already passed by
+        * to subtract them from the APO */
+       for (i = ctx->pipe_index; i < ctx->data_index; i++)
+       {
+               if (ctx->trace_data[ctx->pipe_index + 1].pipestat & ETMV1_TRACESYNC_CYCLE)
+                       apo--;
+       }
+       
+       /* extract up to four 7-bit packets */
+       do {
+               if ((retval = etmv1_next_packet(ctx, &packet, (shift == 0) ? apo + 1 : 0)) != 0)
+                       return -1;
+               ctx->last_branch &= ~(0x7f << shift);
+               ctx->last_branch |= (packet & 0x7f) << shift;
+               shift += 7;
+       } while ((packet & 0x80) && (shift < 28));
+       
+       /* one last packet holding 4 bits of the address, plus the branch reason code */
+       if ((shift == 28) && (packet & 0x80))
+       {
+               if ((retval = etmv1_next_packet(ctx, &packet, 0)) != 0)
+                       return -1;
+               ctx->last_branch &= 0x0fffffff;
+               ctx->last_branch |= (packet & 0x0f) << 28;
+               ctx->last_branch_reason = (packet & 0x70) >> 4;
+               shift += 4;
+       }
+       else
+       {
+               ctx->last_branch_reason = 0;
+       }
+       
+       if (shift == 32)
+       {
+               ctx->pc_ok = 1;
+       }
+       
+       /* if a full address was output, we might have branched into Jazelle state */
+       if ((shift == 32) && (packet & 0x80))
+       {
+               ctx->core_state = ARMV4_5_STATE_JAZELLE;
+       }
+       else
+       {
+               /* if we didn't branch into Jazelle state, the current processor state is
+                * encoded in bit 0 of the branch target address */
+               if (ctx->last_branch & 0x1)
+               {
+                       ctx->core_state = ARMV4_5_STATE_THUMB;
+                       ctx->last_branch &= ~0x1;
+               }
+               else
+               {
+                       ctx->core_state = ARMV4_5_STATE_ARM;
+                       ctx->last_branch &= ~0x3;
+               }
+       }
+       
+       return 0;
+}
+
+int etmv1_data(etm_context_t *ctx, int size, u32 *data)
+{
+       int j;
+       u8 buf[4];
+       int retval;
+       
+       for (j = 0; j < size; j++)
+       {
+               if ((retval = etmv1_next_packet(ctx, &buf[j], 0)) != 0)
+                       return -1;
+       }
+       
+       if (size == 8)
+               ERROR("TODO: add support for 64-bit values");
+       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];
+               
+       return 0;
+}
+
+int etmv1_analyze_trace(etm_context_t *ctx, struct command_context_s *cmd_ctx)
+{
+       int retval;
+       arm_instruction_t instruction;
+       
+       /* read the trace data if it wasn't read already */
+       if (ctx->trace_depth == 0)
+               ctx->capture_driver->read_trace(ctx);
+       
+       /* start at the beginning of the captured trace */
        ctx->pipe_index = 0;
        ctx->data_index = 0;
        ctx->pipe_index = 0;
        ctx->data_index = 0;
+       ctx->data_half = 0;
+
+       /* neither the PC nor the data pointer are valid */     
+       ctx->pc_ok = 0;
+       ctx->ptr_ok = 0;
        
        while (ctx->pipe_index < ctx->trace_depth)
        {
        
        while (ctx->pipe_index < ctx->trace_depth)
        {
-               switch (ctx->trace_data[ctx->pipe_index].pipestat)
+               u8 pipestat = ctx->trace_data[ctx->pipe_index].pipestat;
+               u32 next_pc = ctx->current_pc;
+               u32 old_data_index = ctx->data_index;
+               u32 old_data_half = ctx->data_half;
+               
+               if (ctx->trace_data[ctx->pipe_index].flags & ETMV1_TRIGGER_CYCLE)
                {
                {
-                       case STAT_IE:
-                       case STAT_ID:
-                               break;
-                       case STAT_IN:
-                               DEBUG("IN");
-                               break;
-                       case STAT_WT:
-                               DEBUG("WT");
-                               break;
-                       case STAT_BE:
-                       case STAT_BD:
-                               break;
-                       case STAT_TD:
-                               /* TODO: in cycle accurate trace, we have to count cycles */
-                               DEBUG("TD");
-                               break;
+                       command_print(cmd_ctx, "--- trigger ---");
                }
                }
+               
+               /* if we don't have a valid pc skip until we reach an indirect branch */
+               if ((!ctx->pc_ok) && (pipestat != STAT_BE))
+               {
+                       ctx->pipe_index++;
+                       continue;
+               }
+               
+               /* any indirect branch could have interrupted instruction flow
+                * - the branch reason code could indicate a trace discontinuity
+                * - a branch to the exception vectors indicates an exception
+                */
+               if ((pipestat == STAT_BE) || (pipestat == STAT_BD))
+               {
+                       /* backup current data index, to be able to consume the branch address
+                        * before examining data address and values
+                        */
+                       old_data_index = ctx->data_index;
+                       old_data_half = ctx->data_half;
+                       
+                       if ((retval = etmv1_branch_address(ctx)) != 0)
+                       {
+                               /* negative return value from etmv1_branch_address means we ran out of packets,
+                                * quit analysing the trace */
+                               if (retval < 0)
+                                       break;
+                               
+                               /* 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");
+                               ctx->pipe_index += retval;
+                               continue;
+                       }
+                       
+                       /* skip over APO cycles */
+                       ctx->pipe_index += 2;
+                       
+                       switch (ctx->last_branch_reason)
+                       {
+                               case 0x0:       /* normal PC change */
+                                       next_pc = ctx->last_branch;
+                                       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++;
+                                       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++;
+                                       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++;
+                                       continue;
+                                       break;
+                               case 0x4:       /* periodic synchronization point */
+                                       next_pc = ctx->last_branch;
+                                       break;
+                               default:        /* reserved */
+                                       ERROR("BUG: branch reason code 0x%x is reserved", ctx->last_branch_reason);             
+                                       exit(-1);
+                                       break;
+                       }
+                       
+                       /* if we got here the branch was a normal PC change
+                        * (or a periodic synchronization point, which means the same for that matter)
+                        * if we didn't accquire a complete PC continue with the next cycle
+                        */
+                       if (!ctx->pc_ok)
+                               continue;
+                       
+                       /* indirect branch to the exception vector means an exception occured */
+                       if (((ctx->last_branch >= 0x0) && (ctx->last_branch <= 0x20))
+                               || ((ctx->last_branch >= 0xffff0000) && (ctx->last_branch <= 0xffff0020)))
+                       {
+                               if ((ctx->last_branch & 0xff) == 0x10)
+                               {
+                                       command_print(cmd_ctx, "data abort");
+                               }
+                               else
+                               {
+                                       command_print(cmd_ctx, "exception vector 0x%2.2x", ctx->last_branch);
+                                       ctx->current_pc = ctx->last_branch;
+                                       ctx->pipe_index++;
+                                       continue;
+                               }
+                       }
+               }
+               
+               /* an instruction was executed (or not, depending on the condition flags)
+                * retrieve it from the image for displaying */
+               if (ctx->pc_ok && (pipestat != STAT_WT) && (pipestat != STAT_TD) &&
+                       !(((pipestat == STAT_BE) || (pipestat == STAT_BD)) &&
+                               ((ctx->last_branch_reason != 0x0) && (ctx->last_branch_reason != 0x4))))  
+               {
+                       if ((retval = etm_read_instruction(ctx, &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 */
+                               }
+                       }
+               }
+               
+               if ((pipestat == STAT_ID) || (pipestat == STAT_BD))
+               {
+                       u32 new_data_index = ctx->data_index;
+                       u32 new_data_half = ctx->data_half;
+                       
+                       /* in case of a branch with data, the branch target address was consumed before
+                        * we temporarily go back to the saved data index */
+                       if (pipestat == STAT_BD)
+                       {
+                               ctx->data_index = old_data_index;
+                               ctx->data_half = old_data_half;
+                       }
+                       
+                       if (ctx->tracemode & ETMV1_TRACE_ADDR)
+                       {                       
+                               u8 packet;
+                               int shift = 0;
+                               
+                               do {
+                                       if ((retval = etmv1_next_packet(ctx, &packet, 0)) != 0)
+                                               return -1;
+                                       ctx->last_ptr &= ~(0x7f << shift);
+                                       ctx->last_ptr |= (packet & 0x7f) << shift;
+                                       shift += 7;
+                               } while ((packet & 0x80) && (shift < 32));
+                               
+                               if (shift >= 32)
+                                       ctx->ptr_ok = 1;
+                               
+                               if (ctx->ptr_ok)
+                               {
+                                       command_print(cmd_ctx, "address: 0x%8.8x", ctx->last_ptr);
+                               }
+                       }
+                       
+                       if (ctx->tracemode & ETMV1_TRACE_DATA)
+                       {
+                               if ((instruction.type == ARM_LDM) || (instruction.type == ARM_STM))
+                               {
+                                       int i;
+                                       for (i = 0; i < 16; i++)
+                                       {
+                                               if (instruction.info.load_store_multiple.register_list & (1 << i))
+                                               {
+                                                       u32 data;
+                                                       if (etmv1_data(ctx, 4, &data) != 0)
+                                                               return -1;
+                                                       command_print(cmd_ctx, "data: 0x%8.8x", data);
+                                               }
+                                       }
+                               }
+                               else if ((instruction.type >= ARM_LDR) && (instruction.type <= ARM_STRH))
+                               {
+                                       u32 data;
+                                       if (etmv1_data(ctx, arm_access_size(&instruction), &data) != 0)
+                                               return -1;
+                                       command_print(cmd_ctx, "data: 0x%8.8x", data);
+                               }
+                       }
+                       
+                       /* restore data index after consuming BD address and data */
+                       if (pipestat == STAT_BD)
+                       {
+                               ctx->data_index = new_data_index;
+                               ctx->data_half = new_data_half;
+                       }
+               }
+               
+               /* adjust PC */
+               if ((pipestat == STAT_IE) || (pipestat == STAT_ID))
+               {
+                       if (((instruction.type == ARM_B) ||
+                               (instruction.type == ARM_BL) ||
+                               (instruction.type == ARM_BLX)) &&
+                               (instruction.info.b_bl_bx_blx.target_address != -1))
+                       {
+                               next_pc = instruction.info.b_bl_bx_blx.target_address;
+                       }
+                       else
+                       {
+                               next_pc += (ctx->core_state == ARMV4_5_STATE_ARM) ? 4 : 2;
+                       }
+               }
+               else if (pipestat == STAT_IN)
+               {
+                       next_pc += (ctx->core_state == ARMV4_5_STATE_ARM) ? 4 : 2;
+               }
+
+               if ((pipestat != STAT_TD) && (pipestat != STAT_WT))
+               {
+                       command_print(cmd_ctx, "%s%s",
+                               instruction.text, (pipestat == STAT_IN) ? " (not executed)" : "");
+
+                       ctx->current_pc = next_pc;
+                       
+                       /* packets for an instruction don't start on or before the preceding
+                        * functional pipestat (i.e. other than WT or TD)
+                        */
+                       if (ctx->data_index <= ctx->pipe_index)
+                       {
+                               ctx->data_index = ctx->pipe_index + 1;
+                               ctx->data_half = 0;
+                       }
+               }
+               
+               ctx->pipe_index += 1;
        }
        
        return ERROR_OK;
        }
        
        return ERROR_OK;
@@ -769,17 +1231,21 @@ int handle_etm_config_command(struct command_context_s *cmd_ctx, char *cmd, char
                }
        }
        
                }
        }
        
+       etm_ctx->target = target;
        etm_ctx->trace_data = NULL;
        etm_ctx->trace_depth = 0;
        etm_ctx->portmode = portmode;
        etm_ctx->tracemode = 0x0;
        etm_ctx->core_state = ARMV4_5_STATE_ARM;
        etm_ctx->trace_data = NULL;
        etm_ctx->trace_depth = 0;
        etm_ctx->portmode = portmode;
        etm_ctx->tracemode = 0x0;
        etm_ctx->core_state = ARMV4_5_STATE_ARM;
+       etm_ctx->image = NULL;
        etm_ctx->pipe_index = 0;
        etm_ctx->data_index = 0;
        etm_ctx->current_pc = 0x0;
        etm_ctx->pc_ok = 0;
        etm_ctx->last_branch = 0x0;
        etm_ctx->pipe_index = 0;
        etm_ctx->data_index = 0;
        etm_ctx->current_pc = 0x0;
        etm_ctx->pc_ok = 0;
        etm_ctx->last_branch = 0x0;
+       etm_ctx->last_branch_reason = 0x0;
        etm_ctx->last_ptr = 0x0;
        etm_ctx->last_ptr = 0x0;
+       etm_ctx->ptr_ok = 0x0;
        etm_ctx->context_id = 0x0;
        
        arm7_9->etm_ctx = etm_ctx;
        etm_ctx->context_id = 0x0;
        
        arm7_9->etm_ctx = etm_ctx;
@@ -837,6 +1303,67 @@ int handle_etm_status_command(struct command_context_s *cmd_ctx, char *cmd, char
        return ERROR_OK;
 }
 
        return ERROR_OK;
 }
 
+int handle_etm_image_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;
+       int i;
+
+       if (argc < 1)
+       {
+               command_print(cmd_ctx, "usage: etm image <file> ['bin'|'ihex'|'elf'] [base address]");
+               return ERROR_OK;
+       }
+       
+       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 (etm_ctx->image)
+       {
+               image_close(etm_ctx->image);
+               free(etm_ctx->image);
+               command_print(cmd_ctx, "previously loaded image found and closed");
+       }
+       
+       etm_ctx->image = malloc(sizeof(image_t));
+       etm_ctx->image->base_address_set = 0;
+       etm_ctx->image->start_address_set = 0;
+       
+       for (i = 1; i < argc; i++)
+       {
+               /* optional argument could be image type */
+               if (identify_image_type(&etm_ctx->image->type, args[i], args[0]) == ERROR_IMAGE_TYPE_UNKNOWN)
+               {
+                       /* if it wasn't a valid image type, treat it as the base address */
+                       etm_ctx->image->base_address_set = 1;
+                       etm_ctx->image->base_address = strtoul(args[i], NULL, 0);
+               }
+       }
+       
+       if (image_open(etm_ctx->image, args[0], FILEIO_READ) != 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;
+       }
+       
+       return ERROR_OK;
+}
+
 int handle_etm_dump_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
 {
        fileio_t file;
 int handle_etm_dump_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
 {
        fileio_t file;
@@ -844,7 +1371,7 @@ int handle_etm_dump_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;
        armv4_5_common_t *armv4_5;
        arm7_9_common_t *arm7_9;
        etm_context_t *etm_ctx;
-       u32 size_written;
+       int i;
        
        if (argc != 1)
        {
        
        if (argc != 1)
        {
@@ -889,7 +1416,17 @@ int handle_etm_dump_command(struct command_context_s *cmd_ctx, char *cmd, char *
                return ERROR_OK;
        }
        
                return ERROR_OK;
        }
        
-       //fileio_write(&file, etm_ctx->trace_depth * 4, (u8*)etm_ctx->trace_data, &size_written);
+       fileio_write_u32(&file, etm_ctx->capture_status);
+       fileio_write_u32(&file, etm_ctx->portmode);
+       fileio_write_u32(&file, etm_ctx->tracemode);
+       fileio_write_u32(&file, etm_ctx->trace_depth);
+       
+       for (i = 0; i < etm_ctx->trace_depth; i++)
+       {
+               fileio_write_u32(&file, etm_ctx->trace_data[i].pipestat);
+               fileio_write_u32(&file, etm_ctx->trace_data[i].packet);
+               fileio_write_u32(&file, etm_ctx->trace_data[i].flags);
+       }
        
        fileio_close(&file);
        
        
        fileio_close(&file);
        
@@ -903,7 +1440,7 @@ int handle_etm_load_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;
        armv4_5_common_t *armv4_5;
        arm7_9_common_t *arm7_9;
        etm_context_t *etm_ctx;
-       u32 size_read;
+       int i;
        
        if (argc != 1)
        {
        
        if (argc != 1)
        {
@@ -948,9 +1485,19 @@ int handle_etm_load_command(struct command_context_s *cmd_ctx, char *cmd, char *
                free(etm_ctx->trace_data);
        }
        
                free(etm_ctx->trace_data);
        }
        
-       //fileio_read(&file, file.size, (u8*)etm_ctx->trace_data, &size_read);
-       etm_ctx->trace_depth = file.size / 4;
-       etm_ctx->capture_status = TRACE_COMPLETED;
+       fileio_read_u32(&file, &etm_ctx->capture_status);
+       fileio_read_u32(&file, &etm_ctx->portmode);
+       fileio_read_u32(&file, &etm_ctx->tracemode);
+       fileio_read_u32(&file, &etm_ctx->trace_depth);
+       
+       etm_ctx->trace_data = malloc(sizeof(etmv1_trace_data_t) * etm_ctx->trace_depth);
+       
+       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);
+       }
        
        fileio_close(&file);
        
        
        fileio_close(&file);
        
@@ -1037,7 +1584,7 @@ int handle_etm_stop_command(struct command_context_s *cmd_ctx, char *cmd, char *
        return ERROR_OK;
 }
 
        return ERROR_OK;
 }
 
-int handle_etm_analyse_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+int handle_etm_analyze_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
 {
        target_t *target;
        armv4_5_common_t *armv4_5;
 {
        target_t *target;
        armv4_5_common_t *armv4_5;
@@ -1058,7 +1605,7 @@ int handle_etm_analyse_command(struct command_context_s *cmd_ctx, char *cmd, cha
                return ERROR_OK;
        }
        
                return ERROR_OK;
        }
        
-       etmv1_analyse_trace(etm_ctx);
+       etmv1_analyze_trace(etm_ctx, cmd_ctx);
        
        return ERROR_OK;
 }
        
        return ERROR_OK;
 }
@@ -1084,9 +1631,12 @@ int etm_register_user_commands(struct command_context_s *cmd_ctx)
        register_command(cmd_ctx, etm_cmd, "stop", handle_etm_stop_command,
                COMMAND_EXEC, "stop ETM trace collection");
 
        register_command(cmd_ctx, etm_cmd, "stop", handle_etm_stop_command,
                COMMAND_EXEC, "stop ETM trace collection");
 
-       register_command(cmd_ctx, etm_cmd, "analyze", handle_etm_stop_command,
+       register_command(cmd_ctx, etm_cmd, "analyze", handle_etm_analyze_command,
                COMMAND_EXEC, "anaylze collected ETM trace");
 
                COMMAND_EXEC, "anaylze collected ETM trace");
 
+       register_command(cmd_ctx, etm_cmd, "image", handle_etm_image_command,
+               COMMAND_EXEC, "load image from <file> [base address]");
+
        register_command(cmd_ctx, etm_cmd, "dump", handle_etm_dump_command,
                COMMAND_EXEC, "dump captured trace data <file>");
        register_command(cmd_ctx, etm_cmd, "load", handle_etm_load_command,
        register_command(cmd_ctx, etm_cmd, "dump", handle_etm_dump_command,
                COMMAND_EXEC, "dump captured trace data <file>");
        register_command(cmd_ctx, etm_cmd, "load", handle_etm_load_command,
index 65fd757c8d3971b117f11150d7250162d5cfefcd..0b7b05addb7b494dc5ba821fc76cc6daafe5c213 100644 (file)
@@ -120,11 +120,17 @@ typedef struct etm_capture_driver_s
        int (*stop_capture)(struct etm_context_s *etm_ctx);\r
 } etm_capture_driver_t;\r
 \r
        int (*stop_capture)(struct etm_context_s *etm_ctx);\r
 } etm_capture_driver_t;\r
 \r
+enum\r
+{\r
+       ETMV1_TRACESYNC_CYCLE = 0x1,\r
+       ETMV1_TRIGGER_CYCLE = 0x2,\r
+};\r
+\r
 typedef struct etmv1_trace_data_s\r
 {\r
 typedef struct etmv1_trace_data_s\r
 {\r
-       u8 pipestat;    /* pipeline cycle this packet belongs to */\r
-       u16 packet;     /* packet data (4, 8 or 16 bit) */\r
-       int tracesync;  /* 1 if tracesync was set on this packet */\r
+       u8 pipestat;    /* bits 0-2 pipeline status */\r
+       u16 packet;             /* packet data (4, 8 or 16 bit) */\r
+       int flags;              /* ETMV1_TRACESYNC_CYCLE, ETMV1_TRIGGER_CYCLE */\r
 } etmv1_trace_data_t;\r
 \r
 /* describe a trace context\r
 } etmv1_trace_data_t;\r
 \r
 /* describe a trace context\r
@@ -134,6 +140,7 @@ typedef struct etmv1_trace_data_s
  */\r
 typedef struct etm_context_s\r
 {\r
  */\r
 typedef struct etm_context_s\r
 {\r
+       target_t *target;                               /* target this ETM is connected to */\r
        reg_cache_t *reg_cache;                 /* ETM register cache */\r
        etm_capture_driver_t *capture_driver;   /* driver used to access ETM data */\r
        void *capture_driver_priv;              /* capture driver private data */\r
        reg_cache_t *reg_cache;                 /* ETM register cache */\r
        etm_capture_driver_t *capture_driver;   /* driver used to access ETM data */\r
        void *capture_driver_priv;              /* capture driver private data */\r
@@ -143,13 +150,16 @@ typedef struct etm_context_s
        etm_portmode_t portmode;                /* normal, multiplexed or demultiplexed */\r
        etmv1_tracemode_t tracemode;    /* type of information the trace contains (data, addres, contextID, ...) */ \r
        armv4_5_state_t core_state;             /* current core state (ARM, Thumb, Jazelle) */\r
        etm_portmode_t portmode;                /* normal, multiplexed or demultiplexed */\r
        etmv1_tracemode_t tracemode;    /* type of information the trace contains (data, addres, contextID, ...) */ \r
        armv4_5_state_t core_state;             /* current core state (ARM, Thumb, Jazelle) */\r
-       image_t image;                                  /* source for target opcodes */\r
+       image_t *image;                                 /* source for target opcodes */\r
        u32 pipe_index;                                 /* current trace cycle */\r
        u32 data_index;                                 /* cycle holding next data packet */\r
        u32 pipe_index;                                 /* current trace cycle */\r
        u32 data_index;                                 /* cycle holding next data packet */\r
+       int data_half;                                  /* port half on a 16 bit port */\r
        u32 current_pc;                                 /* current program counter */\r
        u32 pc_ok;                                              /* full PC has been acquired */\r
        u32 last_branch;                                /* last branch address output */ \r
        u32 current_pc;                                 /* current program counter */\r
        u32 pc_ok;                                              /* full PC has been acquired */\r
        u32 last_branch;                                /* last branch address output */ \r
+       u32 last_branch_reason;                 /* branch reason code for the last branch encountered */\r
        u32 last_ptr;                                   /* address of the last data access */\r
        u32 last_ptr;                                   /* address of the last data access */\r
+       u32 ptr_ok;                                             /* whether last_ptr is valid */ \r
        u32 context_id;                                 /* context ID of the code being traced */\r
 } etm_context_t;\r
 \r
        u32 context_id;                                 /* context ID of the code being traced */\r
 } etm_context_t;\r
 \r
index 1f65e3ffb2599105ac117a04ce0705c449fae272..0cac1c10aefa4e8f98e69ac314cb39a8f080af14 100644 (file)
        ((elf->endianness==ELFDATA2LSB)? \
                le_to_h_u32((u8*)&field):be_to_h_u32((u8*)&field)) 
 
        ((elf->endianness==ELFDATA2LSB)? \
                le_to_h_u32((u8*)&field):be_to_h_u32((u8*)&field)) 
 
+static int autodetect_image_type(image_t *image, char *url)
+{
+       int retval;
+       fileio_t fileio;
+       u32 read_bytes;
+       u8 buffer[9];
+       
+       /* read the first 4 bytes of image */
+       if ((retval = fileio_open(&fileio, url, FILEIO_READ, FILEIO_BINARY)) != ERROR_OK)
+       {
+               snprintf(image->error_str, IMAGE_MAX_ERROR_STRING, "cannot open image: %s", fileio.error_str); 
+               ERROR(image->error_str);
+               return retval;
+       }
+       if ((retval = fileio_read(&fileio, 9, buffer, &read_bytes)) != ERROR_OK)
+       {
+               snprintf(image->error_str, IMAGE_MAX_ERROR_STRING, "cannot read image header: %s", fileio.error_str);
+               ERROR(image->error_str);
+               return ERROR_FILEIO_OPERATION_FAILED;
+       }
+       if (read_bytes != 9)
+       {
+               snprintf(image->error_str, IMAGE_MAX_ERROR_STRING, "cannot read image, only partially read");
+               ERROR(image->error_str);
+               return ERROR_FILEIO_OPERATION_FAILED;
+       }
+       fileio_close(&fileio);
+
+       /* check header against known signatures */
+       if (strncmp((char*)buffer,ELFMAG,SELFMAG)==0)
+       {
+               DEBUG("ELF image detected.");
+               image->type = IMAGE_ELF;
+       }
+       else if  ((buffer[0]==':') /* record start byte */
+               &&(isxdigit(buffer[1]))
+               &&(isxdigit(buffer[2]))
+               &&(isxdigit(buffer[3]))
+               &&(isxdigit(buffer[4]))
+               &&(isxdigit(buffer[5]))
+               &&(isxdigit(buffer[6]))
+               &&(buffer[7]=='0') /* record type : 00 -> 05 */
+               &&(buffer[8]>='0')&&(buffer[8]<'6'))
+       {
+               DEBUG("IHEX image detected.");
+               image->type = IMAGE_IHEX;
+       }
+       else
+       {
+               image->type = IMAGE_BINARY;
+       }
+
+       return ERROR_OK;
+}
+
+int identify_image_type(image_t *image, char *type_string, char *url)
+{
+       if (type_string)
+       {
+               if (!strcmp(type_string, "bin"))
+               {
+                       image->type = IMAGE_BINARY;
+               }
+               else if (!strcmp(type_string, "ihex"))
+               {
+                       image->type = IMAGE_IHEX;
+               }
+               else if (!strcmp(type_string, "elf"))
+               {
+                       image->type = IMAGE_ELF;
+               }
+               else if (!strcmp(type_string, "mem"))
+               {
+                       image->type = IMAGE_MEMORY;
+               }
+               else
+               {
+                       return ERROR_IMAGE_TYPE_UNKNOWN;
+               }
+       }
+       else
+       {
+               return autodetect_image_type(image, url);
+       }
+       
+       return ERROR_OK;
+}
+
 int image_ihex_buffer_complete(image_t *image)
 {
        image_ihex_t *ihex = image->type_private;
 int image_ihex_buffer_complete(image_t *image)
 {
        image_ihex_t *ihex = image->type_private;
@@ -334,10 +422,15 @@ int image_elf_read_section(image_t *image, int section, u32 offset, u32 size, u8
        return ERROR_OK;
 }
 
        return ERROR_OK;
 }
 
-int image_open(image_t *image, void *source, enum fileio_access access)
+int image_open(image_t *image, void *source, char *type_string)
 {
        int retval = ERROR_OK;
        
 {
        int retval = ERROR_OK;
        
+       if ((retval = identify_image_type(image, type_string, source)) != ERROR_OK)
+       {
+               return retval;
+       } 
+       
        if (image->type == IMAGE_BINARY)
        {
                image_binary_t *image_binary;
        if (image->type == IMAGE_BINARY)
        {
                image_binary_t *image_binary;
@@ -345,7 +438,7 @@ int image_open(image_t *image, void *source, enum fileio_access access)
                
                image_binary = image->type_private = malloc(sizeof(image_binary_t));
                
                
                image_binary = image->type_private = malloc(sizeof(image_binary_t));
                
-               if ((retval = fileio_open(&image_binary->fileio, url, access, FILEIO_BINARY)) != ERROR_OK)
+               if ((retval = fileio_open(&image_binary->fileio, url, FILEIO_READ, FILEIO_BINARY)) != ERROR_OK)
                {
                        strncpy(image->error_str, image_binary->fileio.error_str, IMAGE_MAX_ERROR_STRING); 
                        ERROR(image->error_str);
                {
                        strncpy(image->error_str, image_binary->fileio.error_str, IMAGE_MAX_ERROR_STRING); 
                        ERROR(image->error_str);
@@ -368,14 +461,6 @@ int image_open(image_t *image, void *source, enum fileio_access access)
                image_ihex_t *image_ihex;
                char *url = source;
                
                image_ihex_t *image_ihex;
                char *url = source;
                
-               if (access != FILEIO_READ)
-               {
-                       snprintf(image->error_str, IMAGE_MAX_ERROR_STRING,
-                               "can't open IHEX file for writing");
-                       ERROR(image->error_str);
-                       return ERROR_FILEIO_ACCESS_NOT_SUPPORTED;
-               }
-               
                image_ihex = image->type_private = malloc(sizeof(image_ihex_t));
                
                if ((retval = fileio_open(&image_ihex->fileio, url, FILEIO_READ, FILEIO_TEXT)) != ERROR_OK)
                image_ihex = image->type_private = malloc(sizeof(image_ihex_t));
                
                if ((retval = fileio_open(&image_ihex->fileio, url, FILEIO_READ, FILEIO_TEXT)) != ERROR_OK)
@@ -493,9 +578,6 @@ int image_close(image_t *image)
                
                fileio_close(&image_ihex->fileio);
                
                
                fileio_close(&image_ihex->fileio);
                
-               if (image_ihex->section_pointer)
-                       free(image_ihex->section_pointer);
-               
                if (image_ihex->buffer)
                        free(image_ihex->buffer);
        }
                if (image_ihex->buffer)
                        free(image_ihex->buffer);
        }
@@ -524,32 +606,3 @@ int image_close(image_t *image)
        
        return ERROR_OK;
 }
        
        return ERROR_OK;
 }
-
-int identify_image_type(image_type_t *type, char *type_string)
-{
-       if (type_string)
-       {
-               if (!strcmp(type_string, "bin"))
-               {
-                       *type = IMAGE_BINARY;
-               }
-               else if (!strcmp(type_string, "ihex"))
-               {
-                       *type = IMAGE_IHEX;
-               }
-               else if (!strcmp(type_string, "elf"))
-               {
-                       *type = IMAGE_ELF;
-               }
-               else
-               {
-                       return ERROR_IMAGE_TYPE_UNKNOWN;
-               }
-       }
-       else
-       {
-               *type = IMAGE_BINARY;
-       }
-       
-       return ERROR_OK;
-}
index 38a2b772c7d2bbcdef8f07176da585c0927b68a6..074b906903627cfb55dcc6075ece9371b1265544 100644 (file)
@@ -24,7 +24,7 @@
 #include "fileio.h"
 #include "target.h"
 
 #include "fileio.h"
 #include "target.h"
 
-#define IMAGE_MAX_ERROR_STRING         (128)
+#define IMAGE_MAX_ERROR_STRING         (256)
 #define IMAGE_MAX_SECTIONS                     (128)
 
 typedef enum image_type
 #define IMAGE_MAX_SECTIONS                     (128)
 
 typedef enum image_type
@@ -69,7 +69,6 @@ typedef struct image_ihex_s
 {
        fileio_t fileio;
        u8 *buffer;
 {
        fileio_t fileio;
        u8 *buffer;
-       u8 **section_pointer;
 } image_ihex_t;
 
 typedef struct image_memory_s
 } image_ihex_t;
 
 typedef struct image_memory_s
@@ -86,10 +85,9 @@ typedef struct fileio_elf_s
        u8 endianness;
 } image_elf_t;
 
        u8 endianness;
 } image_elf_t;
 
-extern int image_open(image_t *image, void *source, enum fileio_access access);
+extern int image_open(image_t *image, void *source, char *type_string);
 extern int image_read_section(image_t *image, int section, u32 offset, u32 size, u8 *buffer, u32 *size_read);
 extern int image_close(image_t *image);
 extern int image_read_section(image_t *image, int section, u32 offset, u32 size, u8 *buffer, u32 *size_read);
 extern int image_close(image_t *image);
-extern int identify_image_type(image_type_t *type, char *type_string);
 
 #define ERROR_IMAGE_FORMAT_ERROR       (-1400)
 #define ERROR_IMAGE_TYPE_UNKNOWN       (-1401)
 
 #define ERROR_IMAGE_FORMAT_ERROR       (-1400)
 #define ERROR_IMAGE_TYPE_UNKNOWN       (-1401)
index fd8ffd7b92f2a6f768af07fa37bf807b2fa5b217..3797c3cffa01029bc7d36332d0be36d862addd0a 100644 (file)
@@ -1654,7 +1654,6 @@ int handle_mw_command(struct command_context_s *cmd_ctx, char *cmd, char **args,
 
 int handle_load_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
 {
 
 int handle_load_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
 {
-       u32 address;
        u8 *buffer;
        u32 buf_cnt;
        u32 image_size;
        u8 *buffer;
        u32 buf_cnt;
        u32 image_size;
@@ -1668,22 +1667,28 @@ int handle_load_image_command(struct command_context_s *cmd_ctx, char *cmd, char
        
        target_t *target = get_current_target(cmd_ctx);
 
        
        target_t *target = get_current_target(cmd_ctx);
 
-       if (argc < 2)
+       if (argc < 1)
        {
        {
-               command_print(cmd_ctx, "usage: load_image <filename> <address> [type]");
+               command_print(cmd_ctx, "usage: load_image <filename> [address] [type]");
                return ERROR_OK;
        }
        
                return ERROR_OK;
        }
        
-       identify_image_type(&image.type, (argc == 3) ? args[2] : NULL);
-
-       image.base_address_set = 1;
-       image.base_address = strtoul(args[1], NULL, 0);
+       /* a base address isn't always necessary, default to 0x0 (i.e. don't relocate) */
+       if (argc >= 2)
+       {
+               image.base_address_set = 1;
+               image.base_address = strtoul(args[1], NULL, 0);
+       }
+       else
+       {
+               image.base_address_set = 0;
+       }
        
        image.start_address_set = 0;
 
        duration_start_measure(&duration);
        
        
        image.start_address_set = 0;
 
        duration_start_measure(&duration);
        
-       if (image_open(&image, args[0], FILEIO_READ) != ERROR_OK)
+       if (image_open(&image, args[0], (argc >= 3) ? args[2] : NULL) != ERROR_OK)
        {
                command_print(cmd_ctx, "load_image error: %s", image.error_str);
                return ERROR_OK;
        {
                command_print(cmd_ctx, "load_image error: %s", image.error_str);
                return ERROR_OK;
index 2994f10e97c4aea03531ba90eb7046134496a015..ec4a4c38fc2df035feb1c1a55c44b06442a9b0af 100644 (file)
@@ -31,4 +31,7 @@ typedef enum trace_status
        TRACE_OVERFLOWED = 0x8,
 } trace_status_t;
 
        TRACE_OVERFLOWED = 0x8,
 } trace_status_t;
 
+#define ERROR_TRACE_IMAGE_UNAVAILABLE  -(1500)
+#define ERROR_TRACE_INSTRUCTION_UNAVAILABLE    -(1500)
+
 #endif /* TRACE_H */
 #endif /* TRACE_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)