summaryrefslogtreecommitdiff
path: root/src/target
diff options
context:
space:
mode:
authordrath <drath@b42882b7-edfa-0310-969c-e2dbd0fdcd60>2007-08-10 19:44:06 +0000
committerdrath <drath@b42882b7-edfa-0310-969c-e2dbd0fdcd60>2007-08-10 19:44:06 +0000
commit20e4e77cdf366dedac21ff5670c54291feadfc05 (patch)
tree95363c4dc5940d7e0e94be81ba76b73e92ff1cf3 /src/target
parent835e6440b8d1d26b4e041be7edab200ab2c572ee (diff)
downloadopenocd+libswd-20e4e77cdf366dedac21ff5670c54291feadfc05.tar.gz
openocd+libswd-20e4e77cdf366dedac21ff5670c54291feadfc05.tar.bz2
openocd+libswd-20e4e77cdf366dedac21ff5670c54291feadfc05.tar.xz
openocd+libswd-20e4e77cdf366dedac21ff5670c54291feadfc05.zip
- renamed M5960 USB JTAG to "flyswatter"
- make ep93xx and at91rm9200 bitbang JTAG interfaces dependant on ARM host (thanks to Vincent Palatin) - various whitespace fixes - removed various warnings - add support for Debian GNU/kFreeBSD (thanks to Uwe Hermann) - fix OpenOCD compilation for various platforms (thanks to Uwe Hermann and Vincent Palatin) - switched order of JTAG chain examination and validation (examine first, then multiple validation tries even if examination failed) - added target_request subsystem to handle requests from the target (debug messages and tracepoints implemented, future enhancements might include semihosting, all ARM7/9 only for now) - added support for GDB vFlashXXX packets (thanks to Pavel Chromy) - added support for receiving data via ARM7/9 DCC - reworked flash writing. the 'flash write' command is now deprecated and replaced by 'flash write_binary' (old syntax and behaviour) and 'flash write_image' (write image files (bin, hex, elf, s19) to a target). - added support for AMD/ST/SST 29F400B non-cfi flashes git-svn-id: svn://svn.berlios.de/openocd/trunk@190 b42882b7-edfa-0310-969c-e2dbd0fdcd60
Diffstat (limited to 'src/target')
-rw-r--r--src/target/Makefile.am4
-rw-r--r--src/target/arm7_9_common.c52
-rw-r--r--src/target/arm7_9_common.h2
-rw-r--r--src/target/arm7tdmi.c2
-rw-r--r--src/target/arm920t.c2
-rw-r--r--src/target/arm926ejs.c2
-rw-r--r--src/target/arm966e.c2
-rw-r--r--src/target/arm9tdmi.c2
-rw-r--r--src/target/cortex_m3.c2
-rw-r--r--src/target/embeddedice.c69
-rw-r--r--src/target/embeddedice.h1
-rw-r--r--src/target/image.c72
-rw-r--r--src/target/image.h4
-rw-r--r--src/target/oocd_trace.c6
-rw-r--r--src/target/target.c10
-rw-r--r--src/target/target.h8
-rw-r--r--src/target/target_request.c270
-rw-r--r--src/target/target_request.h42
-rw-r--r--src/target/trace.c69
-rw-r--r--src/target/trace.h14
-rw-r--r--src/target/xscale.c4
21 files changed, 627 insertions, 12 deletions
diff --git a/src/target/Makefile.am b/src/target/Makefile.am
index c2aa65b4..39486427 100644
--- a/src/target/Makefile.am
+++ b/src/target/Makefile.am
@@ -11,8 +11,8 @@ noinst_LIBRARIES = libtarget.a
libtarget_a_SOURCES = target.c register.c breakpoints.c armv4_5.c embeddedice.c etm.c arm7tdmi.c arm9tdmi.c \
arm_jtag.c arm7_9_common.c algorithm.c arm920t.c arm720t.c armv4_5_mmu.c armv4_5_cache.c arm_disassembler.c \
arm966e.c arm926ejs.c etb.c xscale.c arm_simulator.c image.c armv7m.c cortex_m3.c cortex_swjdp.c \
- etm_dummy.c $(OOCD_TRACE_FILES)
+ etm_dummy.c $(OOCD_TRACE_FILES) target_request.c trace.c
noinst_HEADERS = target.h register.h armv4_5.h embeddedice.h etm.h arm7tdmi.h arm9tdmi.h \
arm_jtag.h arm7_9_common.h arm920t.h arm720t.h armv4_5_mmu.h armv4_5_cache.h breakpoints.h algorithm.h \
arm_disassembler.h arm966e.h arm926ejs.h etb.h xscale.h arm_simulator.h image.h armv7m.h cortex_m3.h cortex_swjdp.h \
- etm_dummy.h oocd_trace.h
+ etm_dummy.h oocd_trace.h target_request.h trace.h
diff --git a/src/target/arm7_9_common.c b/src/target/arm7_9_common.c
index cda99d84..35cbe6e5 100644
--- a/src/target/arm7_9_common.c
+++ b/src/target/arm7_9_common.c
@@ -25,6 +25,7 @@
#include "embeddedice.h"
#include "target.h"
+#include "target_request.h"
#include "armv4_5.h"
#include "arm_jtag.h"
#include "jtag.h"
@@ -589,6 +590,55 @@ int arm7_9_execute_fast_sys_speed(struct target_s *target)
return ERROR_OK;
}
+int arm7_9_target_request_data(target_t *target, u32 size, u8 *buffer)
+{
+ armv4_5_common_t *armv4_5 = target->arch_info;
+ arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+ arm_jtag_t *jtag_info = &arm7_9->jtag_info;
+ u32 *data;
+ int i;
+
+ data = malloc(size * (sizeof(u32)));
+
+ embeddedice_receive(jtag_info, data, size);
+
+ for (i = 0; i < size; i++)
+ {
+ h_u32_to_le(buffer + (i * 4), data[i]);
+ }
+
+ free(data);
+
+ return ERROR_OK;
+}
+
+int arm7_9_handle_target_request(void *priv)
+{
+ target_t *target = priv;
+ armv4_5_common_t *armv4_5 = target->arch_info;
+ arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+ arm_jtag_t *jtag_info = &arm7_9->jtag_info;
+ reg_t *dcc_control = &arm7_9->eice_cache->reg_list[EICE_COMMS_CTRL];
+
+ if (target->state == TARGET_RUNNING)
+ {
+ /* read DCC control register */
+ embeddedice_read_reg(dcc_control);
+ jtag_execute_queue();
+
+ /* check W bit */
+ if (buf_get_u32(dcc_control->value, 1, 1) == 1)
+ {
+ u32 request;
+
+ embeddedice_receive(jtag_info, &request, 1);
+ target_request(target, request);
+ }
+ }
+
+ return ERROR_OK;
+}
+
enum target_state arm7_9_poll(target_t *target)
{
int retval;
@@ -2467,5 +2517,7 @@ int arm7_9_init_arch_info(target_t *target, arm7_9_common_t *arm7_9)
armv4_5_init_arch_info(target, armv4_5);
+ target_register_timer_callback(arm7_9_handle_target_request, 1, 1, target);
+
return ERROR_OK;
}
diff --git a/src/target/arm7_9_common.h b/src/target/arm7_9_common.h
index fbcb920d..53a0ce9f 100644
--- a/src/target/arm7_9_common.h
+++ b/src/target/arm7_9_common.h
@@ -103,6 +103,8 @@ int arm7_9_register_commands(struct command_context_s *cmd_ctx);
enum target_state arm7_9_poll(target_t *target);
+int arm7_9_target_request_data(target_t *target, u32 size, u8 *buffer);
+
int arm7_9_assert_reset(target_t *target);
int arm7_9_deassert_reset(target_t *target);
int arm7_9_reset_request_halt(target_t *target);
diff --git a/src/target/arm7tdmi.c b/src/target/arm7tdmi.c
index 7c6b937f..ae51e3ae 100644
--- a/src/target/arm7tdmi.c
+++ b/src/target/arm7tdmi.c
@@ -59,6 +59,8 @@ target_type_t arm7tdmi_target =
.poll = arm7_9_poll,
.arch_state = armv4_5_arch_state,
+ .target_request_data = arm7_9_target_request_data,
+
.halt = arm7_9_halt,
.resume = arm7_9_resume,
.step = arm7_9_step,
diff --git a/src/target/arm920t.c b/src/target/arm920t.c
index 1bcca0ad..0dff2506 100644
--- a/src/target/arm920t.c
+++ b/src/target/arm920t.c
@@ -63,6 +63,8 @@ target_type_t arm920t_target =
.poll = arm7_9_poll,
.arch_state = arm920t_arch_state,
+ .target_request_data = arm7_9_target_request_data,
+
.halt = arm7_9_halt,
.resume = arm7_9_resume,
.step = arm7_9_step,
diff --git a/src/target/arm926ejs.c b/src/target/arm926ejs.c
index b62bc493..7d8f371b 100644
--- a/src/target/arm926ejs.c
+++ b/src/target/arm926ejs.c
@@ -63,6 +63,8 @@ target_type_t arm926ejs_target =
.poll = arm7_9_poll,
.arch_state = arm926ejs_arch_state,
+ .target_request_data = arm7_9_target_request_data,
+
.halt = arm7_9_halt,
.resume = arm7_9_resume,
.step = arm7_9_step,
diff --git a/src/target/arm966e.c b/src/target/arm966e.c
index 616fb946..80ccd614 100644
--- a/src/target/arm966e.c
+++ b/src/target/arm966e.c
@@ -54,6 +54,8 @@ target_type_t arm966e_target =
.poll = arm7_9_poll,
.arch_state = armv4_5_arch_state,
+ .target_request_data = arm7_9_target_request_data,
+
.halt = arm7_9_halt,
.resume = arm7_9_resume,
.step = arm7_9_step,
diff --git a/src/target/arm9tdmi.c b/src/target/arm9tdmi.c
index 3b06b0e4..b9b1f953 100644
--- a/src/target/arm9tdmi.c
+++ b/src/target/arm9tdmi.c
@@ -57,6 +57,8 @@ target_type_t arm9tdmi_target =
.poll = arm7_9_poll,
.arch_state = armv4_5_arch_state,
+ .target_request_data = arm7_9_target_request_data,
+
.halt = arm7_9_halt,
.resume = arm7_9_resume,
.step = arm7_9_step,
diff --git a/src/target/cortex_m3.c b/src/target/cortex_m3.c
index 852326a7..bdc8b717 100644
--- a/src/target/cortex_m3.c
+++ b/src/target/cortex_m3.c
@@ -60,6 +60,8 @@ target_type_t cortexm3_target =
.poll = cortex_m3_poll,
.arch_state = armv7m_arch_state,
+ .target_request_data = NULL,
+
.halt = cortex_m3_halt,
.resume = cortex_m3_resume,
.step = cortex_m3_step,
diff --git a/src/target/embeddedice.c b/src/target/embeddedice.c
index f601c1eb..e86a81cd 100644
--- a/src/target/embeddedice.c
+++ b/src/target/embeddedice.c
@@ -274,6 +274,75 @@ int embeddedice_read_reg_w_check(reg_t *reg, u8* check_value, u8* check_mask)
return ERROR_OK;
}
+/* receive <size> words of 32 bit from the DCC
+ * we pretend the target is always going to be fast enough
+ * (relative to the JTAG clock), so we don't need to handshake
+ */
+int embeddedice_receive(arm_jtag_t *jtag_info, u32 *data, u32 size)
+{
+ u8 reg_addr = 0x5;
+ scan_field_t fields[3];
+
+ jtag_add_end_state(TAP_RTI);
+ arm_jtag_scann(jtag_info, 0x2);
+ arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL);
+
+ fields[0].device = jtag_info->chain_pos;
+ fields[0].num_bits = 32;
+ fields[0].out_value = NULL;
+ fields[0].out_mask = NULL;
+ fields[0].in_value = NULL;
+ fields[0].in_check_value = NULL;
+ fields[0].in_check_mask = NULL;
+ fields[0].in_handler = NULL;
+ fields[0].in_handler_priv = NULL;
+
+ fields[1].device = jtag_info->chain_pos;
+ fields[1].num_bits = 5;
+ fields[1].out_value = malloc(1);
+ buf_set_u32(fields[1].out_value, 0, 5, reg_addr);
+ fields[1].out_mask = NULL;
+ fields[1].in_value = NULL;
+ fields[1].in_check_value = NULL;
+ fields[1].in_check_mask = NULL;
+ fields[1].in_handler = NULL;
+ fields[1].in_handler_priv = NULL;
+
+ fields[2].device = jtag_info->chain_pos;
+ fields[2].num_bits = 1;
+ fields[2].out_value = malloc(1);
+ buf_set_u32(fields[2].out_value, 0, 1, 0);
+ fields[2].out_mask = NULL;
+ fields[2].in_value = NULL;
+ fields[2].in_check_value = NULL;
+ fields[2].in_check_mask = NULL;
+ fields[2].in_handler = NULL;
+ fields[2].in_handler_priv = NULL;
+
+ jtag_add_dr_scan(3, fields, -1, NULL);
+
+ while (size > 0)
+ {
+ /* when reading the last item, set the register address to the DCC control reg,
+ * to avoid reading additional data from the DCC data reg
+ */
+ if (size == 1)
+ buf_set_u32(fields[1].out_value, 0, 5, embeddedice_reg_arch_info[EICE_COMMS_CTRL]);
+
+ fields[0].in_handler = arm_jtag_buf_to_u32;
+ fields[0].in_handler_priv = data;
+ jtag_add_dr_scan(3, fields, -1, NULL);
+
+ data++;
+ size--;
+ }
+
+ free(fields[1].out_value);
+ free(fields[2].out_value);
+
+ return jtag_execute_queue();
+}
+
int embeddedice_read_reg(reg_t *reg)
{
return embeddedice_read_reg_w_check(reg, NULL, NULL);
diff --git a/src/target/embeddedice.h b/src/target/embeddedice.h
index a50ea221..466854f9 100644
--- a/src/target/embeddedice.h
+++ b/src/target/embeddedice.h
@@ -97,5 +97,6 @@ extern int embeddedice_read_reg_w_check(reg_t *reg, u8* check_value, u8* check_m
extern int embeddedice_store_reg(reg_t *reg);
extern int embeddedice_set_reg(reg_t *reg, u32 value);
extern int embeddedice_set_reg_w_exec(reg_t *reg, u8 *buf);
+extern int embeddedice_receive(arm_jtag_t *jtag_info, u32 *data, u32 size);
#endif /* EMBEDDED_ICE_H */
diff --git a/src/target/image.c b/src/target/image.c
index f849fe93..c85f387d 100644
--- a/src/target/image.c
+++ b/src/target/image.c
@@ -133,6 +133,10 @@ int identify_image_type(image_t *image, char *type_string, char *url)
{
image->type = IMAGE_SRECORD;
}
+ else if (!strcmp(type_string, "build"))
+ {
+ image->type = IMAGE_BUILDER;
+ }
else
{
return ERROR_IMAGE_TYPE_UNKNOWN;
@@ -395,7 +399,7 @@ int image_elf_read_headers(image_t *image)
if ((field32(elf, elf->segments[i].p_type) == PT_LOAD) && (field32(elf, elf->segments[i].p_filesz) != 0))
{
image->sections[j].size = field32(elf,elf->segments[i].p_memsz);
- image->sections[j].base_address = field32(elf,elf->segments[i].p_vaddr);
+ image->sections[j].base_address = field32(elf,elf->segments[i].p_paddr);
image->sections[j].private = &elf->segments[i];
image->sections[j].flags = field32(elf,elf->segments[i].p_flags);
j++;
@@ -758,6 +762,12 @@ int image_open(image_t *image, char *url, char *type_string)
return retval;
}
}
+ else if (image->type == IMAGE_BUILDER)
+ {
+ image->num_sections = 0;
+ image->sections = NULL;
+ image->type_private = NULL;
+ }
return retval;
};
@@ -765,7 +775,15 @@ int image_open(image_t *image, char *url, char *type_string)
int image_read_section(image_t *image, int section, u32 offset, u32 size, u8 *buffer, u32 *size_read)
{
int retval;
-
+
+ /* don't read past the end of a section */
+ if (offset + size > image->sections[section].size)
+ {
+ DEBUG("read past end of section: 0x%8.8x + 0x%8.8x > 0x%8.8x",
+ offset, size, image->sections[section].size);
+ return ERROR_INVALID_ARGUMENTS;
+ }
+
if (image->type == IMAGE_BINARY)
{
image_binary_t *image_binary = image->type_private;
@@ -774,9 +792,6 @@ int image_read_section(image_t *image, int section, u32 offset, u32 size, u8 *bu
if (section != 0)
return ERROR_INVALID_ARGUMENTS;
- if ((offset > image->sections[0].size) || (offset + size > image->sections[0].size))
- return ERROR_INVALID_ARGUMENTS;
-
/* seek to offset */
if ((retval = fileio_seek(&image_binary->fileio, offset)) != ERROR_OK)
{
@@ -849,6 +864,44 @@ int image_read_section(image_t *image, int section, u32 offset, u32 size, u8 *bu
return ERROR_OK;
}
+ else if (image->type == IMAGE_BUILDER)
+ {
+ memcpy(buffer, (u8*)image->sections[section].private + offset, size);
+ *size_read = size;
+ image->error_str[0] = '\0';
+
+ return ERROR_OK;
+ }
+
+ return ERROR_OK;
+}
+
+int image_add_section(image_t *image, u32 base, u32 size, int flags, u8 *data)
+{
+ /* only image builder supports adding sections */
+ if (image->type != IMAGE_BUILDER)
+ return ERROR_INVALID_ARGUMENTS;
+
+ /* see if it's enough to extend an existing section */
+ if (((image->sections[image->num_sections - 1].base_address + image->sections[image->num_sections - 1].size) == base)
+ && (image->sections[image->num_sections - 1].flags == flags))
+ {
+ u32 old_size = image->sections[image->num_sections - 1].size;
+ image->sections[image->num_sections - 1].size += size;
+ image->sections[image->num_sections - 1].private = realloc(image->sections[image->num_sections - 1].private, image->sections[image->num_sections - 1].size);
+ memcpy((u8*)image->sections[image->num_sections - 1].private + old_size, data, size);
+
+ return ERROR_OK;
+ }
+
+ /* allocate new section */
+ image->num_sections++;
+ image->sections = realloc(image->sections, sizeof(image_section_t) * image->num_sections);
+ image->sections[image->num_sections - 1].base_address = base;
+ image->sections[image->num_sections - 1].size = size;
+ image->sections[image->num_sections - 1].flags = flags;
+ image->sections[image->num_sections - 1].private = malloc(sizeof(u8) * size);
+ memcpy((u8*)image->sections[image->num_sections - 1].private, data, size);
return ERROR_OK;
}
@@ -898,6 +951,15 @@ int image_close(image_t *image)
if (image_mot->buffer)
free(image_mot->buffer);
}
+ else if (image->type == IMAGE_BUILDER)
+ {
+ int i;
+
+ for (i = 0; i < image->num_sections; i++)
+ {
+ free(image->sections[i].private);
+ }
+ }
if (image->type_private)
free(image->type_private);
diff --git a/src/target/image.h b/src/target/image.h
index 2e4ef968..ec52acb4 100644
--- a/src/target/image.h
+++ b/src/target/image.h
@@ -42,7 +42,8 @@ typedef enum image_type
IMAGE_IHEX, /* intel hex-record format */
IMAGE_MEMORY, /* target-memory pseudo-image */
IMAGE_ELF, /* ELF binary */
- IMAGE_SRECORD /* motorola s19 */
+ IMAGE_SRECORD, /* motorola s19 */
+ IMAGE_BUILDER, /* when building a new image */
} image_type_t;
typedef struct image_section_s
@@ -102,6 +103,7 @@ typedef struct image_mot_s
extern int image_open(image_t *image, char *url, 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_add_section(image_t *image, u32 base, u32 size, int flags, u8 *data);
#define ERROR_IMAGE_FORMAT_ERROR (-1400)
#define ERROR_IMAGE_TYPE_UNKNOWN (-1401)
diff --git a/src/target/oocd_trace.c b/src/target/oocd_trace.c
index ff63820a..b96116f3 100644
--- a/src/target/oocd_trace.c
+++ b/src/target/oocd_trace.c
@@ -21,6 +21,7 @@
#include "config.h"
#endif
+#define _GNU_SOURCE
#include <string.h>
#include <errno.h>
@@ -34,6 +35,7 @@
#include "register.h"
#include "jtag.h"
#include "arm7_9_common.h"
+#include "replacements.h"
#include <stdlib.h>
@@ -78,7 +80,6 @@ int oocd_trace_read_memory(oocd_trace_t *oocd_trace, u8 *data, u32 address, u32
{
size_t bytes_written, bytes_read, bytes_to_read;
u8 cmd;
- int i;
oocd_trace_write_reg(oocd_trace, OOCD_TRACE_ADDRESS, address);
oocd_trace_write_reg(oocd_trace, OOCD_TRACE_SDRAM_COUNTER, size);
@@ -105,7 +106,7 @@ int oocd_trace_init(etm_context_t *etm_ctx)
{
u8 trash[256];
oocd_trace_t *oocd_trace = etm_ctx->capture_driver_priv;
- size_t bytes_written, bytes_read, bytes_to_read;
+ size_t bytes_read;
oocd_trace->tty_fd = open(oocd_trace->tty, O_RDWR | O_NOCTTY | O_NONBLOCK);
@@ -378,7 +379,6 @@ int handle_oocd_trace_resync_command(struct command_context_s *cmd_ctx, char *cm
armv4_5_common_t *armv4_5;
arm7_9_common_t *arm7_9;
oocd_trace_t *oocd_trace;
- u32 status;
size_t bytes_written;
u8 cmd_array[1];
diff --git a/src/target/target.c b/src/target/target.c
index 520adf15..905b1074 100644
--- a/src/target/target.c
+++ b/src/target/target.c
@@ -23,6 +23,7 @@
#include "replacements.h"
#include "target.h"
+#include "target_request.h"
#include "log.h"
#include "configuration.h"
@@ -883,6 +884,8 @@ int target_register_user_commands(struct command_context_s *cmd_ctx)
register_command(cmd_ctx, NULL, "load_binary", handle_load_image_command, COMMAND_EXEC, "[DEPRECATED] load_binary <file> <address>");
register_command(cmd_ctx, NULL, "dump_binary", handle_dump_image_command, COMMAND_EXEC, "[DEPRECATED] dump_binary <file> <address> <size>");
+ target_request_register_commands(cmd_ctx);
+
return ERROR_OK;
}
@@ -1000,6 +1003,13 @@ int handle_target_command(struct command_context_s *cmd_ctx, char *cmd, char **a
(*last_target_p)->next = NULL;
(*last_target_p)->arch_info = NULL;
+ /* initialize trace information */
+ (*last_target_p)->trace_info = malloc(sizeof(trace_t));
+ (*last_target_p)->trace_info->num_trace_points = 0;
+ (*last_target_p)->trace_info->trace_points = NULL;
+ (*last_target_p)->trace_info->trace_history_size = 0;
+ (*last_target_p)->trace_info->trace_history = NULL;
+
(*last_target_p)->type->target_command(cmd_ctx, cmd, args, argc, *last_target_p);
found = 1;
diff --git a/src/target/target.h b/src/target/target.h
index 9ab3d19a..f6c09c09 100644
--- a/src/target/target.h
+++ b/src/target/target.h
@@ -23,6 +23,7 @@
#include "register.h"
#include "breakpoints.h"
#include "algorithm.h"
+#include "trace.h"
#include "command.h"
#include "types.h"
@@ -101,6 +102,9 @@ typedef struct target_type_s
/* architecture specific status reply */
int (*arch_state)(struct target_s *target, char *buf, int buf_size);
+ /* target request support */
+ int (*target_request_data)(struct target_s *target, u32 size, u8 *buffer);
+
/* target execution control */
int (*halt)(struct target_s *target);
int (*resume)(struct target_s *target, int current, u32 address, int handle_breakpoints, int debug_execution);
@@ -155,12 +159,14 @@ typedef struct target_s
u32 working_area_size; /* size in bytes */
u32 backup_working_area; /* whether the content of the working area has to be preserved */
struct working_area_s *working_areas;/* list of allocated working areas */
- enum target_debug_reason debug_reason; /* reason why the target entered debug state */
+ enum target_debug_reason debug_reason;/* reason why the target entered debug state */
enum target_endianess endianness; /* target endianess */
enum target_state state; /* the current backend-state (running, halted, ...) */
struct reg_cache_s *reg_cache; /* the first register cache of the target (core regs) */
struct breakpoint_s *breakpoints; /* list of breakpoints */
struct watchpoint_s *watchpoints; /* list of watchpoints */
+ struct trace_s *trace_info; /* generic trace information */
+ struct debug_msg_receiver_s *dbgmsg;/* list of debug message receivers */
void *arch_info; /* architecture specific information */
struct target_s *next; /* next target in list */
} target_t;
diff --git a/src/target/target_request.c b/src/target/target_request.c
new file mode 100644
index 00000000..e8409020
--- /dev/null
+++ b/src/target/target_request.c
@@ -0,0 +1,270 @@
+/***************************************************************************
+ * Copyright (C) 2007 by Dominic Rath *
+ * Dominic.Rath@gmx.de *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "replacements.h"
+#include "log.h"
+#include "target.h"
+#include "target_request.h"
+#include "binarybuffer.h"
+#include "command.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+command_t *target_request_cmd = NULL;
+
+int target_asciimsg(target_t *target, u32 length)
+{
+ char *msg = malloc(CEIL(length + 1, 4) * 4);
+ debug_msg_receiver_t *c = target->dbgmsg;
+
+ target->type->target_request_data(target, CEIL(length, 4), (u8*)msg);
+ msg[length] = 0;
+
+ DEBUG("%s", msg);
+
+ while (c)
+ {
+ command_print(c->cmd_ctx, "%s", msg);
+ c = c->next;
+ }
+
+ return ERROR_OK;
+}
+
+int target_hexmsg(target_t *target, int size, u32 length)
+{
+ if (size == 1)
+ {
+ u8 *data = malloc(CEIL(length * sizeof(u8), 4) * 4);
+
+ target->type->target_request_data(target, CEIL(length * sizeof(u8), 4), (u8*)data);
+
+ free(data);
+ }
+ else if (size == 2)
+ {
+ u16 *data = malloc(CEIL(length * sizeof(u16), 4) * 4);
+
+ target->type->target_request_data(target, CEIL(length * sizeof(u16), 4), (u8*)data);
+
+ free(data);
+ }
+ else if (size == 4)
+ {
+ u32 *data = malloc(CEIL(length * sizeof(u32), 4) * 4);
+
+ target->type->target_request_data(target, CEIL(length * sizeof(u32), 4), (u8*)data);
+
+ free(data);
+ }
+ else
+ {
+ ERROR("invalid debug message type");
+ }
+
+ return ERROR_OK;
+}
+
+/* handle requests from the target received by a target specific
+ * side-band channel (e.g. ARM7/9 DCC)
+ */
+int target_request(target_t *target, u32 request)
+{
+ target_req_cmd_t target_req_cmd = request & 0xff;
+
+ switch (target_req_cmd)
+ {
+ case TARGET_REQ_TRACEMSG:
+ DEBUG("tracepoint: %i", (request & 0xffffff00) >> 8);
+ break;
+ case TARGET_REQ_DEBUGMSG:
+ if (((request & 0xff00) >> 8) == 0)
+ {
+ target_asciimsg(target, (request & 0xffff0000) >> 16);
+ }
+ else
+ {
+ target_hexmsg(target, (request & 0xff00) >> 8, (request & 0xffff0000) >> 16);
+ }
+ break;
+/* case TARGET_REQ_SEMIHOSTING:
+ * break;
+ */
+ default:
+ ERROR("unknown target request: %2.2x", target_req_cmd);
+ break;
+ }
+
+ return ERROR_OK;
+}
+
+int add_debug_msg_receiver(struct command_context_s *cmd_ctx, target_t *target)
+{
+ debug_msg_receiver_t **p = &target->dbgmsg;
+
+ if (target == NULL)
+ return ERROR_INVALID_ARGUMENTS;
+
+ /* see if there's already a list */
+ if (*p)
+ {
+ /* find end of linked list */
+ p = &target->dbgmsg;
+ while ((*p)->next)
+ p = &((*p)->next);
+ p = &((*p)->next);
+ }
+
+ /* add new debug message receiver */
+ (*p) = malloc(sizeof(debug_msg_receiver_t));
+ (*p)->cmd_ctx = cmd_ctx;
+ (*p)->next = NULL;
+
+ return ERROR_OK;
+}
+
+debug_msg_receiver_t* find_debug_msg_receiver(struct command_context_s *cmd_ctx, target_t *target)
+{
+ int all_targets = 0;
+ debug_msg_receiver_t **p = &target->dbgmsg;
+
+ /* if no target has been specified search all of them */
+ if (target == NULL)
+ {
+ /* if no targets haven been specified */
+ if (targets == NULL)
+ return NULL;
+
+ target = targets;
+ all_targets = 1;
+ }
+
+ do
+ {
+ while (*p)
+ {
+ if ((*p)->cmd_ctx == cmd_ctx)
+ {
+ return *p;
+ }
+ p = &((*p)->next);
+ }
+
+ target = target->next;
+ } while (target && all_targets);
+
+ return NULL;
+}
+
+int delete_debug_msg_receiver(struct command_context_s *cmd_ctx, target_t *target)
+{
+ debug_msg_receiver_t **p;
+ debug_msg_receiver_t *c;
+ int all_targets = 0;
+
+ /* if no target has been specified search all of them */
+ if (target == NULL)
+ {
+ /* if no targets haven been specified */
+ if (targets == NULL)
+ return ERROR_OK;
+
+ target = targets;
+ all_targets = 1;
+ }
+
+ do
+ {
+ while (c)
+ {
+ debug_msg_receiver_t *next = c->next;
+ if (c->cmd_ctx == cmd_ctx)
+ {
+ *p = next;
+ free(c);
+ return ERROR_OK;
+ }
+ else
+ p = &(c->next);
+ c = next;
+ }
+
+ target = target->next;
+ } while (target && all_targets);
+
+ return ERROR_OK;
+}
+
+int handle_target_request_debugmsgs_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+ target_t *target = get_current_target(cmd_ctx);
+
+ int receiving = 0;
+
+ /* see if reciever is already registered */
+ if (find_debug_msg_receiver(cmd_ctx, target) != NULL)
+ receiving = 1;
+
+ if (argc > 0)
+ {
+ if (!strcmp(args[0], "enable"))
+ {
+ /* don't register if this command context is already receiving */
+ if (!receiving)
+ {
+ receiving = 1;
+ add_debug_msg_receiver(cmd_ctx, target);
+ }
+ }
+ else if (!strcmp(args[0], "disable"))
+ {
+ /* no need to delete a receiver if none is registered */
+ if (receiving)
+ {
+ receiving = 0;
+ delete_debug_msg_receiver(cmd_ctx, target);
+ }
+ }
+ else
+ {
+ command_print(cmd_ctx, "usage: target_request debugmsgs ['enable'|'disable']");
+ }
+ }
+
+ command_print(cmd_ctx, "receiving debug messages from current target %s",
+ (receiving) ? "enabled" : "disabled");
+
+ return ERROR_OK;
+}
+
+int target_request_register_commands(struct command_context_s *cmd_ctx)
+{
+ target_request_cmd =
+ register_command(cmd_ctx, NULL, "target_request", NULL, COMMAND_ANY, "target_request commands");
+
+ register_command(cmd_ctx, target_request_cmd, "debugmsgs", handle_target_request_debugmsgs_command,
+ COMMAND_EXEC, "enable/disable reception of debug messgages from target");
+
+ return ERROR_OK;
+}
diff --git a/src/target/target_request.h b/src/target/target_request.h
new file mode 100644
index 00000000..6aacaed7
--- /dev/null
+++ b/src/target/target_request.h
@@ -0,0 +1,42 @@
+/***************************************************************************
+ * Copyright (C) 2007 by Dominic Rath *
+ * Dominic.Rath@gmx.de *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+#ifndef TARGET_REQUEST_H
+#define TARGET_REQUEST_H
+
+#include "command.h"
+
+typedef enum target_req_cmd
+{
+ TARGET_REQ_TRACEMSG,
+ TARGET_REQ_DEBUGMSG,
+/* TARGET_REQ_SEMIHOSTING, */
+} target_req_cmd_t;
+
+typedef struct debug_msg_receiver_s
+{
+ command_context_t *cmd_ctx;
+ struct debug_msg_receiver_s *next;
+} debug_msg_receiver_t;
+
+extern int target_request(target_t *target, u32 request);
+extern int delete_debug_msg_receiver(struct command_context_s *cmd_ctx, target_t *target);
+extern int target_request_register_commands(struct command_context_s *cmd_ctx);
+
+#endif /* TARGET_REQUEST_H */
diff --git a/src/target/trace.c b/src/target/trace.c
new file mode 100644
index 00000000..3eec3d83
--- /dev/null
+++ b/src/target/trace.c
@@ -0,0 +1,69 @@
+/***************************************************************************
+ * Copyright (C) 2005, 2007 by Dominic Rath *
+ * Dominic.Rath@gmx.de *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "replacements.h"
+#include "log.h"
+#include "trace.h"
+#include "target.h"
+
+#include <stdlib.h>
+
+int handle_trace_history_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+ target_t *target = get_current_target(cmd_ctx);
+ trace_t *trace = target->trace_info;
+
+ if (argc > 0)
+ {
+ if (trace->trace_history)
+ free(trace->trace_history);
+
+ trace->trace_history_size = strtoul(args[0], NULL, 0);
+ trace->trace_history = malloc(sizeof(u32) * trace->trace_history_size);
+
+ command_print(cmd_ctx, "new trace history size: %i", trace->trace_history_size);
+ }
+ else
+ {
+ int i;
+
+ for (i = 0; i < trace->trace_history_size; i++)
+ {
+ if (trace->trace_history[i] < trace->num_trace_points)
+ {
+ u32 address;
+ address = trace->trace_points[trace->trace_history[i]].address;
+ command_print(cmd_ctx, "trace point %i: 0x%8.8x",
+ trace->trace_history[i],
+ address);
+ }
+
+ else
+ {
+ command_print(cmd_ctx, "trace point %i: -not defined-", trace->trace_history[i]);
+ }
+ }
+ }
+
+ return ERROR_OK;
+}
diff --git a/src/target/trace.h b/src/target/trace.h
index ec4a4c38..7267cd38 100644
--- a/src/target/trace.h
+++ b/src/target/trace.h
@@ -22,6 +22,20 @@
#include "target.h"
+typedef struct trace_point_s
+{
+ u32 address;
+ u64 hit_counter;
+} trace_point_t;
+
+typedef struct trace_s
+{
+ int num_trace_points;
+ trace_point_t *trace_points;
+ int trace_history_size;
+ u32 *trace_history;
+} trace_t;
+
typedef enum trace_status
{
TRACE_IDLE = 0x0,
diff --git a/src/target/xscale.c b/src/target/xscale.c
index e7661aaa..91078927 100644
--- a/src/target/xscale.c
+++ b/src/target/xscale.c
@@ -84,6 +84,8 @@ int xscale_remove_watchpoint(struct target_s *target, watchpoint_t *watchpoint);
void xscale_enable_watchpoints(struct target_s *target);
void xscale_enable_breakpoints(struct target_s *target);
+int xscale_read_trace(target_t *target);
+
target_type_t xscale_target =
{
.name = "xscale",
@@ -91,6 +93,8 @@ target_type_t xscale_target =
.poll = xscale_poll,
.arch_state = xscale_arch_state,
+ .target_request_data = NULL,
+
.halt = xscale_halt,
.resume = xscale_resume,
.step = xscale_step,