diff options
author | drath <drath@b42882b7-edfa-0310-969c-e2dbd0fdcd60> | 2007-08-10 19:44:06 +0000 |
---|---|---|
committer | drath <drath@b42882b7-edfa-0310-969c-e2dbd0fdcd60> | 2007-08-10 19:44:06 +0000 |
commit | 20e4e77cdf366dedac21ff5670c54291feadfc05 (patch) | |
tree | 95363c4dc5940d7e0e94be81ba76b73e92ff1cf3 /src/target | |
parent | 835e6440b8d1d26b4e041be7edab200ab2c572ee (diff) | |
download | riscv-openocd-20e4e77cdf366dedac21ff5670c54291feadfc05.zip riscv-openocd-20e4e77cdf366dedac21ff5670c54291feadfc05.tar.gz riscv-openocd-20e4e77cdf366dedac21ff5670c54291feadfc05.tar.bz2 |
- 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.am | 4 | ||||
-rw-r--r-- | src/target/arm7_9_common.c | 52 | ||||
-rw-r--r-- | src/target/arm7_9_common.h | 2 | ||||
-rw-r--r-- | src/target/arm7tdmi.c | 2 | ||||
-rw-r--r-- | src/target/arm920t.c | 2 | ||||
-rw-r--r-- | src/target/arm926ejs.c | 2 | ||||
-rw-r--r-- | src/target/arm966e.c | 2 | ||||
-rw-r--r-- | src/target/arm9tdmi.c | 2 | ||||
-rw-r--r-- | src/target/cortex_m3.c | 2 | ||||
-rw-r--r-- | src/target/embeddedice.c | 69 | ||||
-rw-r--r-- | src/target/embeddedice.h | 1 | ||||
-rw-r--r-- | src/target/image.c | 72 | ||||
-rw-r--r-- | src/target/image.h | 4 | ||||
-rw-r--r-- | src/target/oocd_trace.c | 6 | ||||
-rw-r--r-- | src/target/target.c | 10 | ||||
-rw-r--r-- | src/target/target.h | 8 | ||||
-rw-r--r-- | src/target/target_request.c | 270 | ||||
-rw-r--r-- | src/target/target_request.h | 42 | ||||
-rw-r--r-- | src/target/trace.c | 69 | ||||
-rw-r--r-- | src/target/trace.h | 14 | ||||
-rw-r--r-- | src/target/xscale.c | 4 |
21 files changed, 627 insertions, 12 deletions
diff --git a/src/target/Makefile.am b/src/target/Makefile.am index c2aa65b..3948642 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 cda99d8..35cbe6e 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 fbcb920..53a0ce9 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 7c6b937..ae51e3a 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 1bcca0a..0dff250 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 b62bc49..7d8f371 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 616fb94..80ccd61 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 3b06b0e..b9b1f95 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 852326a..bdc8b71 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 f601c1e..e86a81c 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 a50ea22..466854f 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 f849fe9..c85f387 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 2e4ef96..ec52acb 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 ff63820..b96116f 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 520adf1..905b107 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 9ab3d19..f6c09c0 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 0000000..e840902 --- /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 0000000..6aacaed --- /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 0000000..3eec3d8 --- /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 ec4a4c3..7267cd3 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 e7661aa..9107892 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, |