From: drath Date: Fri, 10 Aug 2007 19:44:06 +0000 (+0000) Subject: - renamed M5960 USB JTAG to "flyswatter" X-Git-Tag: v0.1.0~1089 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=20e4e77cdf366dedac21ff5670c54291feadfc05;p=openocd - 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 --- diff --git a/README b/README index f5db0218..3c93424e 100644 --- a/README +++ b/README @@ -69,7 +69,7 @@ features and additional RS232 UART. The Signalyzer offers support for a wide variety of target voltages from 1.2V to 5.5V. A second connector provides access to a TTL level UART. -* American Microsystem M5960 USB JTAG programmer. +* TinCanTools 'Flyswatter' USB JTAG programmer. * Turtelizer 2: http://www.ethernut.de/en/hardware/turtelizer/index.html Another USB JTAG programmer, with freely available schematics. It supports diff --git a/configure.in b/configure.in index 20d3c02e..5e7f9094 100644 --- a/configure.in +++ b/configure.in @@ -47,13 +47,22 @@ AC_ARG_ENABLE(amtjtagaccel, AS_HELP_STRING([--enable-amtjtagaccel], [Enable building the Amontec JTAG-Accelerator driver]), [build_amtjtagaccel=$enableval], [build_amtjtagaccel=no]) -AC_ARG_ENABLE(ep93xx, - AS_HELP_STRING([--enable-ep93xx], [Enable building support for EP93xx based SBCs]), - [build_ep93xx=$enableval], [build_ep93xx=no]) - -AC_ARG_ENABLE(at91rm9200, - AS_HELP_STRING([--enable-at91rm9200], [Enable building support for AT91RM9200 based SBCs]), - [build_at91rm9200=$enableval], [build_at91rm9200=no]) +case "${host_cpu}" in + arm*) + AC_ARG_ENABLE(ep93xx, + AS_HELP_STRING([--enable-ep93xx], [Enable building support for EP93xx based SBCs]), + [build_ep93xx=$enableval], [build_ep93xx=no]) + + AC_ARG_ENABLE(at91rm9200, + AS_HELP_STRING([--enable-at91rm9200], [Enable building support for AT91RM9200 based SBCs]), + [build_at91rm9200=$enableval], [build_at91rm9200=no]) + ;; + + *) + build_ep93xx=no + build_at91rm9200=no + ;; +esac AC_ARG_ENABLE(gw16012, AS_HELP_STRING([--enable-gw16012], [Enable building support for the Gateworks GW16012 JTAG Programmer]), diff --git a/doc/openocd.1 b/doc/openocd.1 index b747c6d0..dc5ceae9 100644 --- a/doc/openocd.1 +++ b/doc/openocd.1 @@ -32,7 +32,7 @@ OpenOCD supports various different types of JTAG interfaces/programmers: * Amontec JTAGkey\-Tiny * Olimex ARM\-USB\-OCD * eVerve Signalyzer - * American Microsystem M5960 + * TinCanTools 'Flyswatter' * Turtelizer 2 * Hitex STR9-comSTICK * Luminary Micro evb_lm3s811 diff --git a/src/flash/at91sam7.c b/src/flash/at91sam7.c index 0d97c34c..fdc1c51a 100644 --- a/src/flash/at91sam7.c +++ b/src/flash/at91sam7.c @@ -131,8 +131,7 @@ int at91sam7_register_commands(struct command_context_s *cmd_ctx) u32 at91sam7_get_flash_status(flash_bank_t *bank) { - at91sam7_flash_bank_t *at91sam7_info = bank->driver_priv; - target_t *target = at91sam7_info->target; + target_t *target = bank->target; u32 fsr; target_read_u32(target, MC_FSR, &fsr); @@ -144,7 +143,7 @@ u32 at91sam7_get_flash_status(flash_bank_t *bank) void at91sam7_read_clock_info(flash_bank_t *bank) { at91sam7_flash_bank_t *at91sam7_info = bank->driver_priv; - target_t *target = at91sam7_info->target; + target_t *target = bank->target; u32 mckr, mcfr, pllr; unsigned long tmp = 0, mainfreq; @@ -203,7 +202,7 @@ void at91sam7_set_flash_mode(flash_bank_t *bank,int mode) { u32 fmr, fmcn = 0, fws = 0; at91sam7_flash_bank_t *at91sam7_info = bank->driver_priv; - target_t *target = at91sam7_info->target; + target_t *target = bank->target; if (mode && (mode != at91sam7_info->flashmode)) { @@ -272,7 +271,7 @@ int at91sam7_flash_command(struct flash_bank_s *bank,u8 cmd,u16 pagen) { u32 fcr; at91sam7_flash_bank_t *at91sam7_info = bank->driver_priv; - target_t *target = at91sam7_info->target; + target_t *target = bank->target; fcr = (0x5A<<24) | (pagen<<8) | cmd; target_write_u32(target, MC_FCR, fcr); @@ -299,10 +298,10 @@ int at91sam7_flash_command(struct flash_bank_s *bank,u8 cmd,u16 pagen) int at91sam7_read_part_info(struct flash_bank_s *bank) { at91sam7_flash_bank_t *at91sam7_info = bank->driver_priv; - target_t *target = at91sam7_info->target; + target_t *target = bank->target; u32 cidr, status; - if (at91sam7_info->target->state != TARGET_HALTED) + if (bank->target->state != TARGET_HALTED) { return ERROR_TARGET_NOT_HALTED; } @@ -525,6 +524,8 @@ int at91sam7_protect_check(struct flash_bank_s *bank) return ERROR_OK; } +/* flash_bank at91sam7 0 0 0 0 + */ int at91sam7_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank) { at91sam7_flash_bank_t *at91sam7_info; @@ -538,13 +539,6 @@ int at91sam7_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, ch at91sam7_info = malloc(sizeof(at91sam7_flash_bank_t)); bank->driver_priv = at91sam7_info; - at91sam7_info->target = get_target_by_num(strtoul(args[5], NULL, 0)); - if (!at91sam7_info->target) - { - ERROR("no target '%s' configured", args[5]); - exit(-1); - } - /* part wasn't probed for info yet */ at91sam7_info->cidr = 0; @@ -555,7 +549,7 @@ int at91sam7_erase(struct flash_bank_s *bank, int first, int last) { at91sam7_flash_bank_t *at91sam7_info = bank->driver_priv; - if (at91sam7_info->target->state != TARGET_HALTED) + if (bank->target->state != TARGET_HALTED) { return ERROR_TARGET_NOT_HALTED; } @@ -596,7 +590,7 @@ int at91sam7_protect(struct flash_bank_s *bank, int set, int first, int last) at91sam7_flash_bank_t *at91sam7_info = bank->driver_priv; - if (at91sam7_info->target->state != TARGET_HALTED) + if (bank->target->state != TARGET_HALTED) { return ERROR_TARGET_NOT_HALTED; } @@ -644,11 +638,11 @@ int at91sam7_protect(struct flash_bank_s *bank, int set, int first, int last) int at91sam7_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count) { at91sam7_flash_bank_t *at91sam7_info = bank->driver_priv; - target_t *target = at91sam7_info->target; + target_t *target = bank->target; u32 dst_min_alignment, wcount, bytes_remaining = count; u32 first_page, last_page, pagen, buffer_pos; - if (at91sam7_info->target->state != TARGET_HALTED) + if (bank->target->state != TARGET_HALTED) { return ERROR_TARGET_NOT_HALTED; } @@ -809,7 +803,7 @@ int at91sam7_handle_gpnvm_command(struct command_context_s *cmd_ctx, char *cmd, at91sam7_info = bank->driver_priv; - if (at91sam7_info->target->state != TARGET_HALTED) + if (bank->target->state != TARGET_HALTED) { return ERROR_TARGET_NOT_HALTED; } diff --git a/src/flash/at91sam7.h b/src/flash/at91sam7.h index 0bb8f439..317af710 100644 --- a/src/flash/at91sam7.h +++ b/src/flash/at91sam7.h @@ -25,7 +25,6 @@ typedef struct at91sam7_flash_bank_s { - struct target_s *target; u32 working_area; u32 working_area_size; diff --git a/src/flash/cfi.c b/src/flash/cfi.c index 69494b5f..4f2375de 100644 --- a/src/flash/cfi.c +++ b/src/flash/cfi.c @@ -84,6 +84,10 @@ cfi_fixup_t cfi_jedec_fixups[] = { {CFI_MFR_SST, 0x00D5, cfi_fixup_non_cfi, NULL}, {CFI_MFR_SST, 0x00D6, cfi_fixup_non_cfi, NULL}, {CFI_MFR_SST, 0x00D7, cfi_fixup_non_cfi, NULL}, + {CFI_MFR_ST, 0x00D5, cfi_fixup_non_cfi, NULL}, + {CFI_MFR_ST, 0x00D6, cfi_fixup_non_cfi, NULL}, + {CFI_MFR_AMD, 0x2223, cfi_fixup_non_cfi, NULL}, + {CFI_MFR_AMD, 0x22ab, cfi_fixup_non_cfi, NULL}, {0, 0, NULL, NULL} }; @@ -137,7 +141,6 @@ inline u32 flash_address(flash_bank_t *bank, int sector, u32 offset) void cfi_command(flash_bank_t *bank, u8 cmd, u8 *cmd_buf) { - cfi_flash_bank_t *cfi_info = bank->driver_priv; int i; /* clear whole buffer, to ensure bits that exceed the bus_width @@ -146,7 +149,7 @@ void cfi_command(flash_bank_t *bank, u8 cmd, u8 *cmd_buf) for (i = 0; i < CFI_MAX_BUS_WIDTH; i++) cmd_buf[i] = 0; - if (cfi_info->target->endianness == TARGET_LITTLE_ENDIAN) + if (bank->target->endianness == TARGET_LITTLE_ENDIAN) { for (i = bank->bus_width; i > 0; i--) { @@ -168,13 +171,12 @@ void cfi_command(flash_bank_t *bank, u8 cmd, u8 *cmd_buf) */ u8 cfi_query_u8(flash_bank_t *bank, int sector, u32 offset) { - cfi_flash_bank_t *cfi_info = bank->driver_priv; - target_t *target = cfi_info->target; + target_t *target = bank->target; u8 data[CFI_MAX_BUS_WIDTH]; target->type->read_memory(target, flash_address(bank, sector, offset), bank->bus_width, 1, data); - if (cfi_info->target->endianness == TARGET_LITTLE_ENDIAN) + if (bank->target->endianness == TARGET_LITTLE_ENDIAN) return data[0]; else return data[bank->bus_width - 1]; @@ -186,14 +188,13 @@ u8 cfi_query_u8(flash_bank_t *bank, int sector, u32 offset) */ u8 cfi_get_u8(flash_bank_t *bank, int sector, u32 offset) { - cfi_flash_bank_t *cfi_info = bank->driver_priv; - target_t *target = cfi_info->target; + target_t *target = bank->target; u8 data[CFI_MAX_BUS_WIDTH]; int i; target->type->read_memory(target, flash_address(bank, sector, offset), bank->bus_width, 1, data); - if (cfi_info->target->endianness == TARGET_LITTLE_ENDIAN) + if (bank->target->endianness == TARGET_LITTLE_ENDIAN) { for (i = 0; i < bank->bus_width / bank->chip_width; i++) data[0] |= data[i]; @@ -212,13 +213,12 @@ u8 cfi_get_u8(flash_bank_t *bank, int sector, u32 offset) u16 cfi_query_u16(flash_bank_t *bank, int sector, u32 offset) { - cfi_flash_bank_t *cfi_info = bank->driver_priv; - target_t *target = cfi_info->target; + target_t *target = bank->target; u8 data[CFI_MAX_BUS_WIDTH * 2]; target->type->read_memory(target, flash_address(bank, sector, offset), bank->bus_width, 2, data); - if (cfi_info->target->endianness == TARGET_LITTLE_ENDIAN) + if (bank->target->endianness == TARGET_LITTLE_ENDIAN) return data[0] | data[bank->bus_width] << 8; else return data[bank->bus_width - 1] | data[(2 * bank->bus_width) - 1] << 8; @@ -226,13 +226,12 @@ u16 cfi_query_u16(flash_bank_t *bank, int sector, u32 offset) u32 cfi_query_u32(flash_bank_t *bank, int sector, u32 offset) { - cfi_flash_bank_t *cfi_info = bank->driver_priv; - target_t *target = cfi_info->target; + target_t *target = bank->target; u8 data[CFI_MAX_BUS_WIDTH * 4]; target->type->read_memory(target, flash_address(bank, sector, offset), bank->bus_width, 4, data); - if (cfi_info->target->endianness == TARGET_LITTLE_ENDIAN) + if (bank->target->endianness == TARGET_LITTLE_ENDIAN) return data[0] | data[bank->bus_width] << 8 | data[bank->bus_width * 2] << 16 | data[bank->bus_width * 3] << 24; else return data[bank->bus_width - 1] | data[(2* bank->bus_width) - 1] << 8 | @@ -241,8 +240,7 @@ u32 cfi_query_u32(flash_bank_t *bank, int sector, u32 offset) void cfi_intel_clear_status_register(flash_bank_t *bank) { - cfi_flash_bank_t *cfi_info = bank->driver_priv; - target_t *target = cfi_info->target; + target_t *target = bank->target; u8 command[8]; if (target->state != TARGET_HALTED) @@ -334,7 +332,7 @@ int cfi_read_intel_pri_ext(flash_bank_t *bank) { cfi_flash_bank_t *cfi_info = bank->driver_priv; cfi_intel_pri_ext_t *pri_ext = malloc(sizeof(cfi_intel_pri_ext_t)); - target_t *target = cfi_info->target; + target_t *target = bank->target; u8 command[8]; cfi_info->pri_ext = pri_ext; @@ -389,7 +387,7 @@ int cfi_read_spansion_pri_ext(flash_bank_t *bank) { cfi_flash_bank_t *cfi_info = bank->driver_priv; cfi_spansion_pri_ext_t *pri_ext = malloc(sizeof(cfi_spansion_pri_ext_t)); - target_t *target = cfi_info->target; + target_t *target = bank->target; u8 command[8]; cfi_info->pri_ext = pri_ext; @@ -450,7 +448,7 @@ int cfi_read_atmel_pri_ext(flash_bank_t *bank) cfi_atmel_pri_ext_t atmel_pri_ext; cfi_flash_bank_t *cfi_info = bank->driver_priv; cfi_spansion_pri_ext_t *pri_ext = malloc(sizeof(cfi_spansion_pri_ext_t)); - target_t *target = cfi_info->target; + target_t *target = bank->target; u8 command[8]; /* ATMEL devices use the same CFI primary command set (0x2) as AMD/Spansion, @@ -619,13 +617,6 @@ int cfi_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char ** cfi_info->jedec_probe = 0; cfi_info->not_cfi = 0; - cfi_info->target = get_target_by_num(strtoul(args[5], NULL, 0)); - if (!cfi_info->target) - { - ERROR("no target '%s' configured", args[5]); - exit(-1); - } - for (i = 6; i < argc; i++) { if (strcmp(args[i], "x16_as_x8") == 0) @@ -649,7 +640,7 @@ int cfi_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char ** int cfi_intel_erase(struct flash_bank_s *bank, int first, int last) { cfi_flash_bank_t *cfi_info = bank->driver_priv; - target_t *target = cfi_info->target; + target_t *target = bank->target; u8 command[8]; int i; @@ -685,7 +676,7 @@ int cfi_spansion_erase(struct flash_bank_s *bank, int first, int last) { cfi_flash_bank_t *cfi_info = bank->driver_priv; cfi_spansion_pri_ext_t *pri_ext = cfi_info->pri_ext; - target_t *target = cfi_info->target; + target_t *target = bank->target; u8 command[8]; int i; @@ -731,7 +722,7 @@ int cfi_erase(struct flash_bank_s *bank, int first, int last) { cfi_flash_bank_t *cfi_info = bank->driver_priv; - if (cfi_info->target->state != TARGET_HALTED) + if (bank->target->state != TARGET_HALTED) { return ERROR_TARGET_NOT_HALTED; } @@ -765,7 +756,7 @@ int cfi_intel_protect(struct flash_bank_s *bank, int set, int first, int last) { cfi_flash_bank_t *cfi_info = bank->driver_priv; cfi_intel_pri_ext_t *pri_ext = cfi_info->pri_ext; - target_t *target = cfi_info->target; + target_t *target = bank->target; u8 command[8]; int retry = 0; int i; @@ -860,7 +851,7 @@ int cfi_protect(struct flash_bank_s *bank, int set, int first, int last) { cfi_flash_bank_t *cfi_info = bank->driver_priv; - if (cfi_info->target->state != TARGET_HALTED) + if (bank->target->state != TARGET_HALTED) { return ERROR_TARGET_NOT_HALTED; } @@ -889,8 +880,7 @@ int cfi_protect(struct flash_bank_s *bank, int set, int first, int last) void cfi_add_byte(struct flash_bank_s *bank, u8 *word, u8 byte) { - cfi_flash_bank_t *cfi_info = bank->driver_priv; - target_t *target = cfi_info->target; + target_t *target = bank->target; int i; @@ -913,7 +903,7 @@ void cfi_add_byte(struct flash_bank_s *bank, u8 *word, u8 byte) int cfi_intel_write_block(struct flash_bank_s *bank, u8 *buffer, u32 address, u32 count) { cfi_flash_bank_t *cfi_info = bank->driver_priv; - target_t *target = cfi_info->target; + target_t *target = bank->target; reg_param_t reg_params[7]; armv4_5_algorithm_t armv4_5_info; working_area_t *source; @@ -1122,7 +1112,7 @@ int cfi_spansion_write_block(struct flash_bank_s *bank, u8 *buffer, u32 address, { cfi_flash_bank_t *cfi_info = bank->driver_priv; cfi_spansion_pri_ext_t *pri_ext = cfi_info->pri_ext; - target_t *target = cfi_info->target; + target_t *target = bank->target; reg_param_t reg_params[10]; armv4_5_algorithm_t armv4_5_info; working_area_t *source; @@ -1383,7 +1373,7 @@ int cfi_spansion_write_block(struct flash_bank_s *bank, u8 *buffer, u32 address, int cfi_intel_write_word(struct flash_bank_s *bank, u8 *word, u32 address) { cfi_flash_bank_t *cfi_info = bank->driver_priv; - target_t *target = cfi_info->target; + target_t *target = bank->target; u8 command[8]; cfi_intel_clear_status_register(bank); @@ -1408,7 +1398,7 @@ int cfi_spansion_write_word(struct flash_bank_s *bank, u8 *word, u32 address) { cfi_flash_bank_t *cfi_info = bank->driver_priv; cfi_spansion_pri_ext_t *pri_ext = cfi_info->pri_ext; - target_t *target = cfi_info->target; + target_t *target = bank->target; u8 command[8]; cfi_command(bank, 0xaa, command); @@ -1458,7 +1448,7 @@ int cfi_write_word(struct flash_bank_s *bank, u8 *word, u32 address) int cfi_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count) { cfi_flash_bank_t *cfi_info = bank->driver_priv; - target_t *target = cfi_info->target; + target_t *target = bank->target; u32 address = bank->base + offset; /* address of first byte to be programmed */ u32 write_p, copy_p; int align; /* number of unaligned bytes */ @@ -1466,7 +1456,7 @@ int cfi_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count) int i; int retval; - if (cfi_info->target->state != TARGET_HALTED) + if (bank->target->state != TARGET_HALTED) { return ERROR_TARGET_NOT_HALTED; } @@ -1632,7 +1622,7 @@ void cfi_fixup_0002_unlock_addresses(flash_bank_t *bank, void *param) int cfi_probe(struct flash_bank_s *bank) { cfi_flash_bank_t *cfi_info = bank->driver_priv; - target_t *target = cfi_info->target; + target_t *target = bank->target; u8 command[8]; int num_sectors = 0; int i; @@ -1855,7 +1845,7 @@ int cfi_probe(struct flash_bank_s *bank) int cfi_erase_check(struct flash_bank_s *bank) { cfi_flash_bank_t *cfi_info = bank->driver_priv; - target_t *target = cfi_info->target; + target_t *target = bank->target; int i; int retval; @@ -1967,7 +1957,7 @@ int cfi_intel_protect_check(struct flash_bank_s *bank) { cfi_flash_bank_t *cfi_info = bank->driver_priv; cfi_intel_pri_ext_t *pri_ext = cfi_info->pri_ext; - target_t *target = cfi_info->target; + target_t *target = bank->target; u8 command[CFI_MAX_BUS_WIDTH]; int i; @@ -1998,7 +1988,7 @@ int cfi_spansion_protect_check(struct flash_bank_s *bank) { cfi_flash_bank_t *cfi_info = bank->driver_priv; cfi_spansion_pri_ext_t *pri_ext = cfi_info->pri_ext; - target_t *target = cfi_info->target; + target_t *target = bank->target; u8 command[8]; int i; diff --git a/src/flash/cfi.h b/src/flash/cfi.h index b4e3ab22..bf58522b 100644 --- a/src/flash/cfi.h +++ b/src/flash/cfi.h @@ -25,7 +25,6 @@ typedef struct cfi_flash_bank_s { - struct target_s *target; working_area_t *write_algorithm; working_area_t *erase_check_algorithm; diff --git a/src/flash/flash.c b/src/flash/flash.c index 1e091d26..e3389b19 100644 --- a/src/flash/flash.c +++ b/src/flash/flash.c @@ -25,6 +25,9 @@ #include "command.h" #include "target.h" #include "time_support.h" +#include "fileio.h" +#include "image.h" +#include "log.h" #include #include @@ -32,10 +35,7 @@ #include #include #include - -#include -#include -#include "log.h" +#include /* command handlers */ int handle_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); @@ -46,6 +46,8 @@ int handle_flash_erase_check_command(struct command_context_s *cmd_ctx, char *cm int handle_flash_protect_check_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); int handle_flash_erase_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); int handle_flash_write_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); +int handle_flash_write_binary_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); +int handle_flash_write_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); int handle_flash_protect_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); /* flash drivers @@ -100,8 +102,12 @@ int flash_init(struct command_context_s *cmd_ctx) "check protection state of sectors in flash bank "); register_command(cmd_ctx, flash_cmd, "erase", handle_flash_erase_command, COMMAND_EXEC, "erase sectors at "); - register_command(cmd_ctx, flash_cmd, "write", handle_flash_write_command, COMMAND_EXEC, + register_command(cmd_ctx, flash_cmd, "write", handle_flash_write_binary_command, COMMAND_EXEC, + "DEPRECATED, use 'write_binary' or 'write_image' instead"); + register_command(cmd_ctx, flash_cmd, "write_binary", handle_flash_write_binary_command, COMMAND_EXEC, "write binary "); + register_command(cmd_ctx, flash_cmd, "write_image", handle_flash_write_image_command, COMMAND_EXEC, + "write image [offset] [type]"); register_command(cmd_ctx, flash_cmd, "protect", handle_flash_protect_command, COMMAND_EXEC, "set protection of sectors at "); } @@ -125,16 +131,24 @@ flash_bank_t *get_flash_bank_by_num(int num) return NULL; } -/* flash_bank [driver_options ...] +/* flash_bank [driver_options ...] */ int handle_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) { int i; int found = 0; + target_t *target; - if (argc < 5) + if (argc < 6) { WARNING("incomplete flash_bank configuration"); + WARNING("flash_bank [driver_options ...]"); + return ERROR_OK; + } + + if ((target = get_target_by_num(strtoul(args[5], NULL, 0))) == NULL) + { + ERROR("target %lu not defined", strtoul(args[5], NULL, 0)); return ERROR_OK; } @@ -152,6 +166,7 @@ int handle_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char } c = malloc(sizeof(flash_bank_t)); + c->target = target; c->driver = flash_drivers[i]; c->driver_priv = NULL; c->base = strtoul(args[1], NULL, 0); @@ -226,9 +241,9 @@ int handle_flash_info_command(struct command_context_s *cmd_ctx, char *cmd, char return ERROR_OK; } - for (p = flash_banks; p; p = p->next) + for (p = flash_banks; p; p = p->next, i++) { - if (i++ == strtoul(args[0], NULL, 0)) + if (i == strtoul(args[0], NULL, 0)) { char buf[1024]; @@ -494,15 +509,96 @@ int handle_flash_protect_command(struct command_context_s *cmd_ctx, char *cmd, c return ERROR_OK; } -int handle_flash_write_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) +int handle_flash_write_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) +{ + target_t *target = get_current_target(cmd_ctx); + + image_t image; + u32 image_size; + char *error_str; + u32 *failed; + + int i; + + duration_t duration; + char *duration_text; + + int retval; + + if (!strcmp(cmd, "write")) + { + command_print(cmd_ctx, "'flash write' has been deprecated in favor of 'flash write_binary' and 'flash write_image'"); + DEBUG("'flash write' has been deprecated in favor of 'flash write_binary' and 'flash write_image'"); + } + + if (argc < 1) + { + command_print(cmd_ctx, "usage: flash write [offset] [type]"); + return ERROR_OK; + } + + if (!target) + { + ERROR("no target selected"); + return ERROR_OK; + } + + duration_start_measure(&duration); + + if (argc >= 2) + { + image.base_address_set = 1; + image.base_address = strtoul(args[1], NULL, 0); + } + else + { + image.base_address_set = 0; + image.base_address = 0x0; + } + + image.start_address_set = 0; + + if (image_open(&image, args[0], (argc == 4) ? args[2] : NULL) != ERROR_OK) + { + command_print(cmd_ctx, "flash write error: %s", image.error_str); + return ERROR_OK; + } + + failed = malloc(sizeof(u32) * image.num_sections); + + if ((retval = flash_write(target, &image, &image_size, &error_str, failed)) != ERROR_OK) + { + command_print(cmd_ctx, "failed writing image %s: %s", args[0], error_str); + free(error_str); + } + + for (i = 0; i < image.num_sections; i++) + { + if (failed[i]) + { + command_print(cmd_ctx, "didn't write section at 0x%8.8x, size 0x%8.8x", + image.sections[i].base_address, image.sections[i].size); + } + } + + duration_stop_measure(&duration, &duration_text); + command_print(cmd_ctx, "wrote %u byte from file %s in %s (%f kb/s)", + image_size, args[0], duration_text, + (float)image_size / 1024.0 / ((float)duration.duration.tv_sec + ((float)duration.duration.tv_usec / 1000000.0))); + free(duration_text); + + image_close(&image); + + return ERROR_OK; +} + +int handle_flash_write_binary_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) { u32 offset; u8 *buffer; u32 buf_cnt; - u32 image_size; - int i; - image_t image; + fileio_t fileio; duration_t duration; char *duration_text; @@ -512,17 +608,12 @@ int handle_flash_write_command(struct command_context_s *cmd_ctx, char *cmd, cha if (argc < 3) { - command_print(cmd_ctx, "usage: flash write [type]"); + command_print(cmd_ctx, "usage: flash write "); return ERROR_OK; } duration_start_measure(&duration); - image.base_address_set = 1; - image.base_address = strtoul(args[1], NULL, 0); - - image.start_address_set = 0; - offset = strtoul(args[2], NULL, 0); p = get_flash_bank_by_num(strtoul(args[0], NULL, 0)); if (!p) @@ -531,69 +622,208 @@ int handle_flash_write_command(struct command_context_s *cmd_ctx, char *cmd, cha return ERROR_OK; } - if (image_open(&image, args[1], (argc == 4) ? args[3] : NULL) != ERROR_OK) + if (fileio_open(&fileio, args[1], FILEIO_READ, FILEIO_BINARY) != ERROR_OK) { - command_print(cmd_ctx, "flash write error: %s", image.error_str); + command_print(cmd_ctx, "flash write error: %s", fileio.error_str); return ERROR_OK; } - image_size = 0x0; - for (i = 0; i < image.num_sections; i++) + buffer = malloc(fileio.size); + if (fileio_read(&fileio, fileio.size, buffer, &buf_cnt) != ERROR_OK) { - buffer = malloc(image.sections[i].size); - if ((retval = image_read_section(&image, i, 0x0, image.sections[i].size, buffer, &buf_cnt)) != ERROR_OK) - { - ERROR("image_read_section failed with error code: %i", retval); - command_print(cmd_ctx, "image reading failed, flash write aborted"); - free(buffer); - image_close(&image); - return ERROR_OK; - } - - if ((retval = p->driver->write(p, buffer, offset, buf_cnt)) != ERROR_OK) + command_print(cmd_ctx, "flash write error: %s", fileio.error_str); + return ERROR_OK; + } + + if ((retval = p->driver->write(p, buffer, offset, buf_cnt)) != ERROR_OK) + { + command_print(cmd_ctx, "failed writing file %s to flash bank %i at offset 0x%8.8x", + args[1], strtoul(args[0], NULL, 0), strtoul(args[2], NULL, 0)); + switch (retval) { - command_print(cmd_ctx, "failed writing file %s to flash bank %i at offset 0x%8.8x", - args[1], strtoul(args[0], NULL, 0), strtoul(args[2], NULL, 0)); - switch (retval) - { - case ERROR_TARGET_NOT_HALTED: - command_print(cmd_ctx, "can't work with this flash while target is running"); - break; - case ERROR_INVALID_ARGUMENTS: - command_print(cmd_ctx, "usage: flash write "); - break; - case ERROR_FLASH_BANK_INVALID: - command_print(cmd_ctx, "no '%s' flash found at 0x%8.8x", p->driver->name, p->base); - break; - case ERROR_FLASH_OPERATION_FAILED: - command_print(cmd_ctx, "flash program error"); - break; - case ERROR_FLASH_DST_BREAKS_ALIGNMENT: - command_print(cmd_ctx, "offset breaks required alignment"); - break; - case ERROR_FLASH_DST_OUT_OF_BANK: - command_print(cmd_ctx, "destination is out of flash bank (offset and/or file too large)"); - break; - case ERROR_FLASH_SECTOR_NOT_ERASED: - command_print(cmd_ctx, "destination sector(s) not erased"); - break; - default: - command_print(cmd_ctx, "unknown error"); - } + case ERROR_TARGET_NOT_HALTED: + command_print(cmd_ctx, "can't work with this flash while target is running"); + break; + case ERROR_INVALID_ARGUMENTS: + command_print(cmd_ctx, "usage: flash write "); + break; + case ERROR_FLASH_BANK_INVALID: + command_print(cmd_ctx, "no '%s' flash found at 0x%8.8x", p->driver->name, p->base); + break; + case ERROR_FLASH_OPERATION_FAILED: + command_print(cmd_ctx, "flash program error"); + break; + case ERROR_FLASH_DST_BREAKS_ALIGNMENT: + command_print(cmd_ctx, "offset breaks required alignment"); + break; + case ERROR_FLASH_DST_OUT_OF_BANK: + command_print(cmd_ctx, "destination is out of flash bank (offset and/or file too large)"); + break; + case ERROR_FLASH_SECTOR_NOT_ERASED: + command_print(cmd_ctx, "destination sector(s) not erased"); + break; + default: + command_print(cmd_ctx, "unknown error"); } - image_size += buf_cnt; - - free(buffer); } + free(buffer); duration_stop_measure(&duration, &duration_text); - command_print(cmd_ctx, "wrote %u byte from file %s to flash bank %i at offset 0x%8.8x in %s (%f kb/s)", - image_size, args[1], strtoul(args[0], NULL, 0), offset, duration_text, - (float)image_size / 1024.0 / ((float)duration.duration.tv_sec + ((float)duration.duration.tv_usec / 1000000.0))); + command_print(cmd_ctx, "wrote %"PRIi64" byte from file %s to flash bank %i at offset 0x%8.8x in %s (%f kb/s)", + fileio.size, args[1], strtoul(args[0], NULL, 0), offset, duration_text, + (float)fileio.size / 1024.0 / ((float)duration.duration.tv_sec + ((float)duration.duration.tv_usec / 1000000.0))); free(duration_text); - image_close(&image); + fileio_close(&fileio); + + return ERROR_OK; +} + +/* lookup flash bank by address */ +flash_bank_t *get_flash_bank_by_addr(target_t *target, u32 addr) +{ + flash_bank_t *c; + + /* cycle through bank list */ + for (c = flash_banks; c; c = c->next) + { + /* check whether address belongs to this flash bank */ + if ((addr >= c->base) && (addr < c->base + c->size) && target == c->target) + return c; + } + + return NULL; +} + +/* erase given flash region, selects proper bank according to target and address */ +int flash_erase(target_t *target, u32 addr, u32 length) +{ + flash_bank_t *c; + unsigned long sector_size; + int first; + int last; + + if ((c = get_flash_bank_by_addr(target, addr)) == NULL) + return ERROR_FLASH_DST_OUT_OF_BANK; /* no corresponding bank found */ + + /* sanity checks */ + if (c->size == 0 || c->num_sectors == 0 || c->size % c->num_sectors) + return ERROR_FLASH_BANK_INVALID; + + if (length == 0) + { + /* special case, erase whole bank when length is zero */ + if (addr != c->base) + return ERROR_FLASH_DST_BREAKS_ALIGNMENT; + + return c->driver->erase(c, 0, c->num_sectors - 1); + } + + /* check whether it fits */ + if (addr + length > c->base + c->size) + return ERROR_FLASH_DST_BREAKS_ALIGNMENT; + + /* calculate sector size */ + sector_size = c->size / c->num_sectors; + + /* check alignment */ + if ((addr - c->base) % sector_size || length % sector_size) + return ERROR_FLASH_DST_BREAKS_ALIGNMENT; + + first = (addr - c->base) / sector_size; + last = first + length / sector_size - 1; + return c->driver->erase(c, first, last); +} + +int flash_write(target_t *target, image_t *image, u32 *image_size, char **error_str, u32 *failed) +{ + int section; + int retval; + + *image_size = 0; + + /* for each section in the image */ + for (section = 0; section < image->num_sections; section++) + { + u32 offset = 0; + u32 address = image->sections[section].base_address; + u32 size = image->sections[section].size; + + failed[section] = 0; + + while (size != 0) + { + flash_bank_t *c; + u32 thisrun_size = size; + u32 size_read; + u8 *buffer; + + /* find the corresponding flash bank */ + if ((c = get_flash_bank_by_addr(target, address)) == NULL) + { + /* mark as failed, and skip the current section */ + failed[section] = 1; + break; + } + + /* check whether it fits, split into multiple runs if not */ + if ((address + size) > (c->base + c->size)) + thisrun_size = c->base + c->size - address; + + buffer = malloc(thisrun_size); + if (((retval = image_read_section(image, section, offset, size, buffer, &size_read)) != ERROR_OK) + || (thisrun_size != size_read)) + { + *error_str = malloc(FLASH_MAX_ERROR_STR); + snprintf(*error_str, FLASH_MAX_ERROR_STR, "error reading from image"); + return ERROR_IMAGE_TEMPORARILY_UNAVAILABLE; + } + + if ((retval = c->driver->write(c, buffer, address - c->base, thisrun_size)) != ERROR_OK) + { + /* mark the current section as failed */ + failed[section] = 1; + *error_str = malloc(FLASH_MAX_ERROR_STR); + switch (retval) + { + case ERROR_TARGET_NOT_HALTED: + snprintf(*error_str, FLASH_MAX_ERROR_STR, "can't flash image while target is running"); + break; + case ERROR_INVALID_ARGUMENTS: + snprintf(*error_str, FLASH_MAX_ERROR_STR, "flash driver can't fulfill request"); + break; + case ERROR_FLASH_OPERATION_FAILED: + snprintf(*error_str, FLASH_MAX_ERROR_STR, "flash program error"); + break; + case ERROR_FLASH_DST_BREAKS_ALIGNMENT: + snprintf(*error_str, FLASH_MAX_ERROR_STR, "offset breaks required alignment"); + break; + case ERROR_FLASH_DST_OUT_OF_BANK: + snprintf(*error_str, FLASH_MAX_ERROR_STR, "no flash mapped at requested address"); + break; + case ERROR_FLASH_SECTOR_NOT_ERASED: + snprintf(*error_str, FLASH_MAX_ERROR_STR, "destination sector(s) not erased"); + break; + default: + snprintf(*error_str, FLASH_MAX_ERROR_STR, "unknown error: %i", retval); + } + + free(buffer); + + /* abort operation */ + return retval; + } + + free(buffer); + + offset += thisrun_size; + address += thisrun_size; + size -= thisrun_size; + } + + *image_size += image->sections[section].size; + } return ERROR_OK; } diff --git a/src/flash/flash.h b/src/flash/flash.h index a8cc1869..513ede81 100644 --- a/src/flash/flash.h +++ b/src/flash/flash.h @@ -21,6 +21,9 @@ #define FLASH_H #include "target.h" +#include "image.h" + +#define FLASH_MAX_ERROR_STR (128) typedef struct flash_sector_s { @@ -48,6 +51,7 @@ typedef struct flash_driver_s typedef struct flash_bank_s { + target_t *target; flash_driver_t *driver; void *driver_priv; u32 base; @@ -62,7 +66,11 @@ typedef struct flash_bank_s extern int flash_register_commands(struct command_context_s *cmd_ctx); extern int flash_init(struct command_context_s *cmd_ctx); +extern int flash_erase(target_t *target, u32 addr, u32 length); +extern int flash_write(target_t *target, image_t *image, u32 *image_size, char **error, u32 *failed); + extern flash_bank_t *get_flash_bank_by_num(int num); +extern flash_bank_t *get_flash_bank_by_addr(target_t *target, u32 addr); #define ERROR_FLASH_BANK_INVALID (-900) #define ERROR_FLASH_SECTOR_INVALID (-901) diff --git a/src/flash/lpc2000.c b/src/flash/lpc2000.c index e3c7e742..2252ca42 100644 --- a/src/flash/lpc2000.c +++ b/src/flash/lpc2000.c @@ -233,7 +233,7 @@ int lpc2000_build_sector_list(struct flash_bank_s *bank) int lpc2000_iap_call(flash_bank_t *bank, int code, u32 param_table[5], u32 result_table[2]) { lpc2000_flash_bank_t *lpc2000_info = bank->driver_priv; - target_t *target = lpc2000_info->target; + target_t *target = bank->target; mem_param_t mem_params[2]; reg_param_t reg_params[5]; armv4_5_algorithm_t armv4_5_info; @@ -350,7 +350,7 @@ int lpc2000_iap_blank_check(struct flash_bank_s *bank, int first, int last) return ERROR_OK; } -/* flash bank lpc2000 0 0 [calc_checksum] +/* flash bank lpc2000 0 0 [calc_checksum] */ int lpc2000_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank) { @@ -365,14 +365,14 @@ int lpc2000_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, cha lpc2000_info = malloc(sizeof(lpc2000_flash_bank_t)); bank->driver_priv = lpc2000_info; - if (strcmp(args[5], "lpc2000_v1") == 0) + if (strcmp(args[6], "lpc2000_v1") == 0) { lpc2000_info->variant = 1; lpc2000_info->cmd51_dst_boundary = 512; lpc2000_info->cmd51_can_256b = 0; lpc2000_info->cmd51_can_8192b = 1; } - else if (strcmp(args[5], "lpc2000_v2") == 0) + else if (strcmp(args[6], "lpc2000_v2") == 0) { lpc2000_info->variant = 2; lpc2000_info->cmd51_dst_boundary = 256; @@ -386,18 +386,11 @@ int lpc2000_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, cha return ERROR_FLASH_BANK_INVALID; } - lpc2000_info->target = get_target_by_num(strtoul(args[6], NULL, 0)); - if (!lpc2000_info->target) - { - ERROR("no target '%s' configured", args[6]); - exit(-1); - } lpc2000_info->iap_working_area = NULL; lpc2000_info->cclk = strtoul(args[7], NULL, 0); lpc2000_info->calc_checksum = 0; lpc2000_build_sector_list(bank); - - + if (argc >= 9) { if (strcmp(args[8], "calc_checksum") == 0) @@ -414,7 +407,7 @@ int lpc2000_erase(struct flash_bank_s *bank, int first, int last) u32 result_table[2]; int status_code; - if (lpc2000_info->target->state != TARGET_HALTED) + if (bank->target->state != TARGET_HALTED) { return ERROR_TARGET_NOT_HALTED; } @@ -472,7 +465,7 @@ int lpc2000_protect(struct flash_bank_s *bank, int set, int first, int last) int lpc2000_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count) { lpc2000_flash_bank_t *lpc2000_info = bank->driver_priv; - target_t *target = lpc2000_info->target; + target_t *target = bank->target; u32 dst_min_alignment; u32 bytes_remaining = count; u32 bytes_written = 0; @@ -484,7 +477,7 @@ int lpc2000_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count) int i; working_area_t *download_area; - if (lpc2000_info->target->state != TARGET_HALTED) + if (bank->target->state != TARGET_HALTED) { return ERROR_TARGET_NOT_HALTED; } @@ -568,7 +561,7 @@ int lpc2000_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count) if (bytes_remaining >= thisrun_bytes) { - if (target_write_buffer(lpc2000_info->target, download_area->address, thisrun_bytes, buffer + bytes_written) != ERROR_OK) + if (target_write_buffer(bank->target, download_area->address, thisrun_bytes, buffer + bytes_written) != ERROR_OK) { target_free_working_area(target, download_area); return ERROR_FLASH_OPERATION_FAILED; @@ -581,7 +574,7 @@ int lpc2000_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count) memcpy(last_buffer, buffer + bytes_written, bytes_remaining); for (i = bytes_remaining; i < thisrun_bytes; i++) last_buffer[i] = 0xff; - target_write_buffer(lpc2000_info->target, download_area->address, thisrun_bytes, last_buffer); + target_write_buffer(bank->target, download_area->address, thisrun_bytes, last_buffer); free(last_buffer); } @@ -629,9 +622,7 @@ int lpc2000_probe(struct flash_bank_s *bank) int lpc2000_erase_check(struct flash_bank_s *bank) { - lpc2000_flash_bank_t *lpc2000_info = bank->driver_priv; - - if (lpc2000_info->target->state != TARGET_HALTED) + if (bank->target->state != TARGET_HALTED) { return ERROR_TARGET_NOT_HALTED; } @@ -676,7 +667,7 @@ int lpc2000_handle_part_id_command(struct command_context_s *cmd_ctx, char *cmd, } lpc2000_info = bank->driver_priv; - if (lpc2000_info->target->state != TARGET_HALTED) + if (bank->target->state != TARGET_HALTED) { return ERROR_TARGET_NOT_HALTED; } diff --git a/src/flash/lpc2000.h b/src/flash/lpc2000.h index dbbe4b6a..bf7358f6 100644 --- a/src/flash/lpc2000.h +++ b/src/flash/lpc2000.h @@ -26,7 +26,6 @@ typedef struct lpc2000_flash_bank_s { int variant; - struct target_s *target; struct working_area_s *iap_working_area; u32 cclk; int cmd51_dst_boundary; diff --git a/src/flash/non_cfi.c b/src/flash/non_cfi.c index 3a74ff92..d80f3784 100644 --- a/src/flash/non_cfi.c +++ b/src/flash/non_cfi.c @@ -35,13 +35,13 @@ non_cfi_t non_cfi_flashes[] = { .mfr = CFI_MFR_SST, .id = 0xd4, .pri_id = 0x02, - .dev_size = 0x10, - .interface_desc = 0x0, + .dev_size = 0x10, /* 2^16 = 64KB */ + .interface_desc = 0x0, /* x8 only device */ .max_buf_write_size = 0x0, .num_erase_regions = 1, .erase_region_info = { - 0x0010000f, + 0x0010000f, /* 16x 4KB */ 0x00000000 } }, @@ -49,8 +49,8 @@ non_cfi_t non_cfi_flashes[] = { .mfr = CFI_MFR_SST, .id = 0xd5, .pri_id = 0x02, - .dev_size = 0x11, - .interface_desc = 0x0, + .dev_size = 0x11, /* 2^17 = 128KB */ + .interface_desc = 0x0, /* x8 only device */ .max_buf_write_size = 0x0, .num_erase_regions = 1, .erase_region_info = @@ -63,8 +63,8 @@ non_cfi_t non_cfi_flashes[] = { .mfr = CFI_MFR_SST, .id = 0xd6, .pri_id = 0x02, - .dev_size = 0x12, - .interface_desc = 0x0, + .dev_size = 0x12, /* 2^18 = 256KB */ + .interface_desc = 0x0, /* x8 only device */ .max_buf_write_size = 0x0, .num_erase_regions = 1, .erase_region_info = @@ -77,8 +77,8 @@ non_cfi_t non_cfi_flashes[] = { .mfr = CFI_MFR_SST, .id = 0xd7, .pri_id = 0x02, - .dev_size = 0x13, - .interface_desc = 0x0, + .dev_size = 0x13, /* 2^19 = 512KB */ + .interface_desc = 0x0, /* x8 only device */ .max_buf_write_size = 0x0, .num_erase_regions = 1, .erase_region_info = @@ -87,6 +87,74 @@ non_cfi_t non_cfi_flashes[] = { 0x00000000 } }, + { + .mfr = CFI_MFR_ST, + .id = 0xd6, /* ST29F400BB */ + .pri_id = 0x02, + .dev_size = 0x13, /* 2^19 = 512KB */ + .interface_desc = 0x2, /* x8 or x16 device with nBYTE */ + .max_buf_write_size = 0x0, + .num_erase_regions = 4, + .erase_region_info = + { + 0x00400000, /* 1x 16KB */ + 0x00200001, /* 2x 8KB */ + 0x00800000, /* 1x 32KB */ + 0x01000006, /* 7x 64KB */ + 0x00000000 + } + }, + { + .mfr = CFI_MFR_ST, + .id = 0xd5, /* ST29F400BT */ + .pri_id = 0x02, + .dev_size = 0x13, /* 2^19 = 512KB */ + .interface_desc = 0x2, /* x8 or x16 device with nBYTE */ + .max_buf_write_size = 0x0, + .num_erase_regions = 4, + .erase_region_info = + { + 0x01000006, /* 7x 64KB */ + 0x00800000, /* 1x 32KB */ + 0x00200001, /* 2x 8KB */ + 0x00400000, /* 1x 16KB */ + 0x00000000 + } + }, + { + .mfr = CFI_MFR_AMD, + .id = 0x22ab, /* AM29F400BB */ + .pri_id = 0x02, + .dev_size = 0x13, /* 2^19 = 512KB */ + .interface_desc = 0x2, /* x8 or x16 device with nBYTE */ + .max_buf_write_size = 0x0, + .num_erase_regions = 4, + .erase_region_info = + { + 0x00400000, /* 1x 16KB */ + 0x00200001, /* 2x 8KB */ + 0x00800000, /* 1x 32KB */ + 0x01000006, /* 7x 64KB */ + 0x00000000 + } + }, + { + .mfr = CFI_MFR_AMD, + .id = 0x2223, /* AM29F400BT */ + .pri_id = 0x02, + .dev_size = 0x13, /* 2^19 = 512KB */ + .interface_desc = 0x2, /* x8 or x16 device with nBYTE */ + .max_buf_write_size = 0x0, + .num_erase_regions = 4, + .erase_region_info = + { + 0x01000006, /* 7x 64KB */ + 0x00800000, /* 1x 32KB */ + 0x00200001, /* 2x 8KB */ + 0x00400000, /* 1x 16KB */ + 0x00000000 + } + }, { .mfr = 0, .id = 0, diff --git a/src/flash/stellaris.c b/src/flash/stellaris.c index 376a80fd..490b02cc 100644 --- a/src/flash/stellaris.c +++ b/src/flash/stellaris.c @@ -57,6 +57,8 @@ u32 stellaris_get_flash_status(flash_bank_t *bank); void stellaris_set_flash_mode(flash_bank_t *bank,int mode); u32 stellaris_wait_status_busy(flash_bank_t *bank, u32 waitbits, int timeout); +int stellaris_read_part_info(struct flash_bank_s *bank); + flash_driver_t stellaris_flash = { .name = "stellaris", @@ -130,6 +132,8 @@ struct { * openocd command interface * ***************************************************************************/ +/* flash_bank stellaris 0 0 + */ int stellaris_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank) { stellaris_flash_bank_t *stellaris_info; @@ -144,13 +148,7 @@ int stellaris_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, c bank->base = 0x0; bank->driver_priv = stellaris_info; - stellaris_info->target_name ="Unknown target"; - stellaris_info->target = get_target_by_num(strtoul(args[5], NULL, 0)); - if (!stellaris_info->target) - { - ERROR("no target '%s' configured", args[5]); - exit(-1); - } + stellaris_info->target_name = "Unknown target"; /* part wasn't probed for info yet */ stellaris_info->did1 = 0; @@ -214,7 +212,7 @@ int stellaris_info(struct flash_bank_s *bank, char *buf, int buf_size) u32 stellaris_get_flash_status(flash_bank_t *bank) { stellaris_flash_bank_t *stellaris_info = bank->driver_priv; - target_t *target = stellaris_info->target; + target_t *target = bank->target; u32 fmc; target_read_u32(target, FLASH_CONTROL_BASE|FLASH_FMC, &fmc); @@ -227,7 +225,7 @@ u32 stellaris_get_flash_status(flash_bank_t *bank) void stellaris_read_clock_info(flash_bank_t *bank) { stellaris_flash_bank_t *stellaris_info = bank->driver_priv; - target_t *target = stellaris_info->target; + target_t *target = bank->target; u32 rcc, pllcfg, sysdiv, usesysdiv, bypass, oscsrc; unsigned long tmp, mainfreq; @@ -275,7 +273,7 @@ void stellaris_read_clock_info(flash_bank_t *bank) void stellaris_set_flash_mode(flash_bank_t *bank,int mode) { stellaris_flash_bank_t *stellaris_info = bank->driver_priv; - target_t *target = stellaris_info->target; + target_t *target = bank->target; u32 usecrl = (stellaris_info->mck_freq/1000000ul-1); DEBUG("usecrl = %i",usecrl); @@ -305,7 +303,7 @@ int stellaris_flash_command(struct flash_bank_s *bank,u8 cmd,u16 pagen) { u32 fmc; stellaris_flash_bank_t *stellaris_info = bank->driver_priv; - target_t *target = stellaris_info->target; + target_t *target = bank->target; fmc = FMC_WRKEY | cmd; target_write_u32(target, FLASH_CONTROL_BASE|FLASH_FMC, fmc); @@ -323,7 +321,7 @@ int stellaris_flash_command(struct flash_bank_s *bank,u8 cmd,u16 pagen) int stellaris_read_part_info(struct flash_bank_s *bank) { stellaris_flash_bank_t *stellaris_info = bank->driver_priv; - target_t *target = stellaris_info->target; + target_t *target = bank->target; u32 did0,did1, ver, fam, status; int i; @@ -390,7 +388,7 @@ int stellaris_read_part_info(struct flash_bank_s *bank) int stellaris_erase_check(struct flash_bank_s *bank) { stellaris_flash_bank_t *stellaris_info = bank->driver_priv; - target_t *target = stellaris_info->target; + target_t *target = bank->target; int i; /* */ @@ -403,7 +401,7 @@ int stellaris_protect_check(struct flash_bank_s *bank) u32 status; stellaris_flash_bank_t *stellaris_info = bank->driver_priv; - target_t *target = stellaris_info->target; + target_t *target = bank->target; if (stellaris_info->did1 == 0) { @@ -427,9 +425,9 @@ int stellaris_erase(struct flash_bank_s *bank, int first, int last) int banknr; u32 flash_fmc, flash_cris; stellaris_flash_bank_t *stellaris_info = bank->driver_priv; - target_t *target = stellaris_info->target; + target_t *target = bank->target; - if (stellaris_info->target->state != TARGET_HALTED) + if (bank->target->state != TARGET_HALTED) { return ERROR_TARGET_NOT_HALTED; } @@ -517,9 +515,9 @@ int stellaris_protect(struct flash_bank_s *bank, int set, int first, int last) int lockregion; stellaris_flash_bank_t *stellaris_info = bank->driver_priv; - target_t *target = stellaris_info->target; + target_t *target = bank->target; - if (stellaris_info->target->state != TARGET_HALTED) + if (bank->target->state != TARGET_HALTED) { return ERROR_TARGET_NOT_HALTED; } @@ -625,7 +623,7 @@ u8 stellaris_write_code[] = int stellaris_write_block(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 wcount) { stellaris_flash_bank_t *stellaris_info = bank->driver_priv; - target_t *target = stellaris_info->target; + target_t *target = bank->target; u32 buffer_size = 8192; working_area_t *source; working_area_t *write_algorithm; @@ -721,7 +719,7 @@ int stellaris_write_block(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 int stellaris_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count) { stellaris_flash_bank_t *stellaris_info = bank->driver_priv; - target_t *target = stellaris_info->target; + target_t *target = bank->target; u32 dst_min_alignment, wcount, bytes_remaining = count; u32 address = offset; u32 fcr,flash_cris,flash_fmc; @@ -730,7 +728,7 @@ int stellaris_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count DEBUG("(bank=%08X buffer=%08X offset=%08X count=%08X)", bank, buffer, offset, count); - if (stellaris_info->target->state != TARGET_HALTED) + if (bank->target->state != TARGET_HALTED) { return ERROR_TARGET_NOT_HALTED; } diff --git a/src/flash/stellaris.h b/src/flash/stellaris.h index e899b30f..8024258e 100644 --- a/src/flash/stellaris.h +++ b/src/flash/stellaris.h @@ -25,8 +25,6 @@ typedef struct stellaris_flash_bank_s { - struct target_s *target; - /* chip id register */ u32 did0; u32 did1; diff --git a/src/flash/stm32x.c b/src/flash/stm32x.c index a09fa40d..15cbb74c 100644 --- a/src/flash/stm32x.c +++ b/src/flash/stm32x.c @@ -137,13 +137,6 @@ int stm32x_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char WARNING("overriding flash base address for STM32x device with 0x08000000"); bank->base = 0x08000000; } - - stm32x_info->target = get_target_by_num(strtoul(args[5], NULL, 0)); - if (!stm32x_info->target) - { - ERROR("no target '%s' configured", args[5]); - exit(-1); - } stm32x_build_block_list(bank); @@ -154,8 +147,7 @@ int stm32x_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char u32 stm32x_get_flash_status(flash_bank_t *bank) { - stm32x_flash_bank_t *stm32x_info = bank->driver_priv; - target_t *target = stm32x_info->target; + target_t *target = bank->target; u32 status; target_read_u32(target, STM32_FLASH_SR, &status); @@ -179,8 +171,7 @@ u32 stm32x_wait_status_busy(flash_bank_t *bank, int timeout) int stm32x_blank_check(struct flash_bank_s *bank, int first, int last) { - stm32x_flash_bank_t *stm32x_info = bank->driver_priv; - target_t *target = stm32x_info->target; + target_t *target = bank->target; u8 *buffer; int i; int nBytes; @@ -218,8 +209,7 @@ int stm32x_blank_check(struct flash_bank_s *bank, int first, int last) int stm32x_protect_check(struct flash_bank_s *bank) { - stm32x_flash_bank_t *stm32x_info = bank->driver_priv; - target_t *target = stm32x_info->target; + target_t *target = bank->target; u32 protection; int i, s; @@ -248,8 +238,7 @@ int stm32x_protect_check(struct flash_bank_s *bank) int stm32x_erase(struct flash_bank_s *bank, int first, int last) { - stm32x_flash_bank_t *stm32x_info = bank->driver_priv; - target_t *target = stm32x_info->target; + target_t *target = bank->target; int i; u32 status; @@ -285,8 +274,7 @@ int stm32x_erase(struct flash_bank_s *bank, int first, int last) int stm32x_protect(struct flash_bank_s *bank, int set, int first, int last) { - stm32x_flash_bank_t *stm32x_info = bank->driver_priv; - target_t *target = stm32x_info->target; + target_t *target = bank->target; if (target->state != TARGET_HALTED) { @@ -299,7 +287,7 @@ int stm32x_protect(struct flash_bank_s *bank, int set, int first, int last) int stm32x_write_block(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count) { stm32x_flash_bank_t *stm32x_info = bank->driver_priv; - target_t *target = stm32x_info->target; + target_t *target = bank->target; u32 buffer_size = 8192; working_area_t *source; u32 address = bank->base + offset; @@ -409,8 +397,7 @@ int stm32x_write_block(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 co int stm32x_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count) { - stm32x_flash_bank_t *stm32x_info = bank->driver_priv; - target_t *target = stm32x_info->target; + target_t *target = bank->target; u32 words_remaining = (count / 2); u32 bytes_remaining = (count & 0x00000001); u32 address = bank->base + offset; @@ -547,7 +534,7 @@ int stm32x_handle_lock_command(struct command_context_s *cmd_ctx, char *cmd, cha stm32x_info = bank->driver_priv; - target = stm32x_info->target; + target = bank->target; if (target->state != TARGET_HALTED) { @@ -614,7 +601,7 @@ int stm32x_handle_unlock_command(struct command_context_s *cmd_ctx, char *cmd, c stm32x_info = bank->driver_priv; - target = stm32x_info->target; + target = bank->target; if (target->state != TARGET_HALTED) { @@ -681,7 +668,7 @@ int stm32x_handle_options_read_command(struct command_context_s *cmd_ctx, char * stm32x_info = bank->driver_priv; - target = stm32x_info->target; + target = bank->target; if (target->state != TARGET_HALTED) { @@ -749,7 +736,7 @@ int stm32x_handle_options_write_command(struct command_context_s *cmd_ctx, char stm32x_info = bank->driver_priv; - target = stm32x_info->target; + target = bank->target; if (target->state != TARGET_HALTED) { @@ -831,7 +818,7 @@ int stm32x_handle_mass_erase_command(struct command_context_s *cmd_ctx, char *cm stm32x_info = bank->driver_priv; - target = stm32x_info->target; + target = bank->target; if (target->state != TARGET_HALTED) { diff --git a/src/flash/stm32x.h b/src/flash/stm32x.h index ad189ac4..59fcb04b 100644 --- a/src/flash/stm32x.h +++ b/src/flash/stm32x.h @@ -25,7 +25,6 @@ typedef struct stm32x_flash_bank_s { - struct target_s *target; working_area_t *write_algorithm; } stm32x_flash_bank_t; diff --git a/src/flash/str7x.c b/src/flash/str7x.c index 0fa2f6ce..6771506a 100644 --- a/src/flash/str7x.c +++ b/src/flash/str7x.c @@ -150,7 +150,7 @@ int str7x_build_block_list(struct flash_bank_s *bank) return ERROR_OK; } -/* flash bank str7x 0 0 +/* flash bank str7x 0 0 */ int str7x_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank) { @@ -165,7 +165,7 @@ int str7x_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char str7x_info = malloc(sizeof(str7x_flash_bank_t)); bank->driver_priv = str7x_info; - if (strcmp(args[5], "STR71x") == 0) + if (strcmp(args[6], "STR71x") == 0) { str7x_info->bank1 = 1; if (bank->base != 0x40000000) @@ -174,7 +174,7 @@ int str7x_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char bank->base = 0x40000000; } } - else if (strcmp(args[5], "STR73x") == 0) + else if (strcmp(args[6], "STR73x") == 0) { str7x_info->bank1 = 0; if (bank->base != 0x80000000) @@ -183,7 +183,7 @@ int str7x_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char bank->base = 0x80000000; } } - else if (strcmp(args[5], "STR75x") == 0) + else if (strcmp(args[6], "STR75x") == 0) { str7x_info->bank1 = 1; if (bank->base != 0x20000000) @@ -194,17 +194,10 @@ int str7x_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char } else { - ERROR("unknown STR7x variant"); + ERROR("unknown STR7x variant: '%s'", args[6]); free(str7x_info); return ERROR_FLASH_BANK_INVALID; } - - str7x_info->target = get_target_by_num(strtoul(args[6], NULL, 0)); - if (!str7x_info->target) - { - ERROR("no target '%s' configured", args[6]); - exit(-1); - } str7x_build_block_list(bank); @@ -215,8 +208,7 @@ int str7x_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char u32 str7x_status(struct flash_bank_s *bank) { - str7x_flash_bank_t *str7x_info = bank->driver_priv; - target_t *target = str7x_info->target; + target_t *target = bank->target; u32 retval; target_read_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), &retval); @@ -226,8 +218,7 @@ u32 str7x_status(struct flash_bank_s *bank) u32 str7x_result(struct flash_bank_s *bank) { - str7x_flash_bank_t *str7x_info = bank->driver_priv; - target_t *target = str7x_info->target; + target_t *target = bank->target; u32 retval; target_read_u32(target, str7x_get_flash_adr(bank, FLASH_ER), &retval); @@ -237,8 +228,7 @@ u32 str7x_result(struct flash_bank_s *bank) int str7x_blank_check(struct flash_bank_s *bank, int first, int last) { - str7x_flash_bank_t *str7x_info = bank->driver_priv; - target_t *target = str7x_info->target; + target_t *target = bank->target; u8 *buffer; int i; int nBytes; @@ -246,7 +236,7 @@ int str7x_blank_check(struct flash_bank_s *bank, int first, int last) if ((first < 0) || (last > bank->num_sectors)) return ERROR_FLASH_SECTOR_INVALID; - if (str7x_info->target->state != TARGET_HALTED) + if (bank->target->state != TARGET_HALTED) { return ERROR_TARGET_NOT_HALTED; } @@ -277,12 +267,12 @@ int str7x_blank_check(struct flash_bank_s *bank, int first, int last) int str7x_protect_check(struct flash_bank_s *bank) { str7x_flash_bank_t *str7x_info = bank->driver_priv; - target_t *target = str7x_info->target; + target_t *target = bank->target; int i; u32 retval; - if (str7x_info->target->state != TARGET_HALTED) + if (bank->target->state != TARGET_HALTED) { return ERROR_TARGET_NOT_HALTED; } @@ -303,14 +293,14 @@ int str7x_protect_check(struct flash_bank_s *bank) int str7x_erase(struct flash_bank_s *bank, int first, int last) { str7x_flash_bank_t *str7x_info = bank->driver_priv; - target_t *target = str7x_info->target; + target_t *target = bank->target; int i; u32 cmd; u32 retval; u32 b0_sectors = 0, b1_sectors = 0; - if (str7x_info->target->state != TARGET_HALTED) + if (bank->target->state != TARGET_HALTED) { return ERROR_TARGET_NOT_HALTED; } @@ -392,13 +382,13 @@ int str7x_erase(struct flash_bank_s *bank, int first, int last) int str7x_protect(struct flash_bank_s *bank, int set, int first, int last) { str7x_flash_bank_t *str7x_info = bank->driver_priv; - target_t *target = str7x_info->target; + target_t *target = bank->target; int i; u32 cmd; u32 retval; u32 protect_blocks; - if (str7x_info->target->state != TARGET_HALTED) + if (bank->target->state != TARGET_HALTED) { return ERROR_TARGET_NOT_HALTED; } @@ -445,7 +435,7 @@ int str7x_protect(struct flash_bank_s *bank, int set, int first, int last) int str7x_write_block(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count) { str7x_flash_bank_t *str7x_info = bank->driver_priv; - target_t *target = str7x_info->target; + target_t *target = bank->target; u32 buffer_size = 8192; working_area_t *source; u32 address = bank->base + offset; @@ -564,8 +554,7 @@ int str7x_write_block(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 cou int str7x_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count) { - str7x_flash_bank_t *str7x_info = bank->driver_priv; - target_t *target = str7x_info->target; + target_t *target = bank->target; u32 dwords_remaining = (count / 8); u32 bytes_remaining = (count & 0x00000007); u32 address = bank->base + offset; @@ -575,7 +564,7 @@ int str7x_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count) u32 check_address = offset; int i; - if (str7x_info->target->state != TARGET_HALTED) + if (bank->target->state != TARGET_HALTED) { return ERROR_TARGET_NOT_HALTED; } diff --git a/src/flash/str7x.h b/src/flash/str7x.h index ecf64322..a823bb80 100644 --- a/src/flash/str7x.h +++ b/src/flash/str7x.h @@ -26,7 +26,6 @@ typedef struct str7x_flash_bank_s { int bank1; - struct target_s *target; u32 *sector_bank; u32 *sector_bits; working_area_t *write_algorithm; diff --git a/src/flash/str9x.c b/src/flash/str9x.c index b47758d2..66b27036 100644 --- a/src/flash/str9x.c +++ b/src/flash/str9x.c @@ -156,13 +156,6 @@ int str9x_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char WARNING("overriding flash base address for STR91x device with 0x00000000"); bank->base = 0x00000000; } - - str9x_info->target = get_target_by_num(strtoul(args[5], NULL, 0)); - if (!str9x_info->target) - { - ERROR("no target '%s' configured", args[5]); - exit(-1); - } str9x_build_block_list(bank); @@ -173,8 +166,7 @@ int str9x_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char int str9x_blank_check(struct flash_bank_s *bank, int first, int last) { - str9x_flash_bank_t *str9x_info = bank->driver_priv; - target_t *target = str9x_info->target; + target_t *target = bank->target; u8 *buffer; int i; int nBytes; @@ -182,7 +174,7 @@ int str9x_blank_check(struct flash_bank_s *bank, int first, int last) if ((first < 0) || (last > bank->num_sectors)) return ERROR_FLASH_SECTOR_INVALID; - if (str9x_info->target->state != TARGET_HALTED) + if (bank->target->state != TARGET_HALTED) { return ERROR_TARGET_NOT_HALTED; } @@ -213,13 +205,13 @@ int str9x_blank_check(struct flash_bank_s *bank, int first, int last) int str9x_protect_check(struct flash_bank_s *bank) { str9x_flash_bank_t *str9x_info = bank->driver_priv; - target_t *target = str9x_info->target; + target_t *target = bank->target; int i; u32 adr; u16 status; - if (str9x_info->target->state != TARGET_HALTED) + if (bank->target->state != TARGET_HALTED) { return ERROR_TARGET_NOT_HALTED; } @@ -245,13 +237,12 @@ int str9x_protect_check(struct flash_bank_s *bank) int str9x_erase(struct flash_bank_s *bank, int first, int last) { - str9x_flash_bank_t *str9x_info = bank->driver_priv; - target_t *target = str9x_info->target; + target_t *target = bank->target; int i; u32 adr; u8 status; - if (str9x_info->target->state != TARGET_HALTED) + if (bank->target->state != TARGET_HALTED) { return ERROR_TARGET_NOT_HALTED; } @@ -295,13 +286,12 @@ int str9x_erase(struct flash_bank_s *bank, int first, int last) int str9x_protect(struct flash_bank_s *bank, int set, int first, int last) { - str9x_flash_bank_t *str9x_info = bank->driver_priv; - target_t *target = str9x_info->target; + target_t *target = bank->target; int i; u32 adr; u8 status; - if (str9x_info->target->state != TARGET_HALTED) + if (bank->target->state != TARGET_HALTED) { return ERROR_TARGET_NOT_HALTED; } @@ -328,7 +318,7 @@ int str9x_protect(struct flash_bank_s *bank, int set, int first, int last) int str9x_write_block(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count) { str9x_flash_bank_t *str9x_info = bank->driver_priv; - target_t *target = str9x_info->target; + target_t *target = bank->target; u32 buffer_size = 8192; working_area_t *source; u32 address = bank->base + offset; @@ -440,8 +430,7 @@ int str9x_write_block(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 cou int str9x_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count) { - str9x_flash_bank_t *str9x_info = bank->driver_priv; - target_t *target = str9x_info->target; + target_t *target = bank->target; u32 words_remaining = (count / 2); u32 bytes_remaining = (count & 0x00000001); u32 address = bank->base + offset; @@ -452,7 +441,7 @@ int str9x_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count) u32 bank_adr; int i; - if (str9x_info->target->state != TARGET_HALTED) + if (bank->target->state != TARGET_HALTED) { return ERROR_TARGET_NOT_HALTED; } @@ -616,9 +605,9 @@ int str9x_handle_flash_config_command(struct command_context_s *cmd_ctx, char *c bank = get_flash_bank_by_num(0); str9x_info = bank->driver_priv; - target = str9x_info->target; + target = bank->target; - if (str9x_info->target->state != TARGET_HALTED) + if (bank->target->state != TARGET_HALTED) { return ERROR_TARGET_NOT_HALTED; } diff --git a/src/flash/str9x.h b/src/flash/str9x.h index 0cd1f196..e65e3730 100644 --- a/src/flash/str9x.h +++ b/src/flash/str9x.h @@ -25,7 +25,6 @@ typedef struct str9x_flash_bank_s { - struct target_s *target; u32 *sector_bits; working_area_t *write_algorithm; } str9x_flash_bank_t; diff --git a/src/flash/str9xpec.c b/src/flash/str9xpec.c index e8830314..7a8fb2fe 100644 --- a/src/flash/str9xpec.c +++ b/src/flash/str9xpec.c @@ -336,18 +336,11 @@ int str9xpec_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, ch WARNING("overriding flash base address for STR91x device with 0x00000000"); bank->base = 0x00000000; } - - str9xpec_info->target = get_target_by_num(strtoul(args[5], NULL, 0)); - if (!str9xpec_info->target) - { - ERROR("no target '%s' configured", args[5]); - exit(-1); - } /* find out jtag position of flash controller * it is always after the arm966 core */ - armv4_5 = str9xpec_info->target->arch_info; + armv4_5 = bank->target->arch_info; arm7_9 = armv4_5->arch_info; jtag_info = &arm7_9->jtag_info; diff --git a/src/flash/str9xpec.h b/src/flash/str9xpec.h index 3d1b0068..52340a54 100644 --- a/src/flash/str9xpec.h +++ b/src/flash/str9xpec.h @@ -26,7 +26,6 @@ typedef struct str9xpec_flash_controller_s { - struct target_s *target; u32 *sector_bits; int chain_pos; int isc_enable; diff --git a/src/helper/replacements.h b/src/helper/replacements.h index ca042d60..99aaba43 100644 --- a/src/helper/replacements.h +++ b/src/helper/replacements.h @@ -187,14 +187,14 @@ typedef struct typedef struct { - u32 p_type; /* Segment type */ - u32 p_offset; /* Segment file offset */ - u32 p_vaddr; /* Segment virtual address */ - u32 p_paddr; /* Segment physical address */ - u32 p_filesz; /* Segment size in file */ - u32 p_memsz; /* Segment size in memory */ - u32 p_flags; /* Segment flags */ - u32 p_align; /* Segment alignment */ + u32 p_type; /* Segment type */ + u32 p_offset; /* Segment file offset */ + u32 p_vaddr; /* Segment virtual address */ + u32 p_paddr; /* Segment physical address */ + u32 p_filesz; /* Segment size in file */ + u32 p_memsz; /* Segment size in memory */ + u32 p_flags; /* Segment flags */ + u32 p_align; /* Segment alignment */ } Elf32_Phdr; #define PT_LOAD 1 /* Loadable program segment */ diff --git a/src/jtag/at91rm9200.c b/src/jtag/at91rm9200.c index 5497b561..d532e3e7 100644 --- a/src/jtag/at91rm9200.c +++ b/src/jtag/at91rm9200.c @@ -26,7 +26,6 @@ #include "bitbang.h" /* system includes */ -#include #include #include #include @@ -217,7 +216,6 @@ int at91rm9200_register_commands(struct command_context_s *cmd_ctx) int at91rm9200_init(void) { - int ret; struct device_t *cur_device; cur_device = devices; diff --git a/src/jtag/bitq.c b/src/jtag/bitq.c index 05f4c925..9d1f43dc 100644 --- a/src/jtag/bitq.c +++ b/src/jtag/bitq.c @@ -61,8 +61,6 @@ void bitq_in_proc(void) scan_field_t *field; int tdo; - int result; - /* loop through the queue */ while (bitq_in_state.cmd) { /* only JTAG_SCAN command may return data */ diff --git a/src/jtag/ep93xx.c b/src/jtag/ep93xx.c index 38763d2e..88ed50c1 100644 --- a/src/jtag/ep93xx.c +++ b/src/jtag/ep93xx.c @@ -34,7 +34,6 @@ #define VCC_BIT 64 /* system includes */ -#include #include #include #include @@ -211,8 +210,8 @@ int ep93xx_init(void) gpio_data_register = gpio_controller + 0x08; gpio_data_direction_register = gpio_controller + 0x18; - printf("gpio_data_register = %08x\n", gpio_data_register); - printf("gpio_data_direction_reg = %08x\n", gpio_data_direction_register); + printf("gpio_data_register = %p\n", gpio_data_register); + printf("gpio_data_direction_reg = %p\n", gpio_data_direction_register); /* * Configure bit 0 (TDO) as an input, and bits 1-5 (TDI, TCK * TMS, TRST, SRST) as outputs. Drive TDI and TCK low, and diff --git a/src/jtag/ft2232.c b/src/jtag/ft2232.c index 44b0e6a8..339e77da 100644 --- a/src/jtag/ft2232.c +++ b/src/jtag/ft2232.c @@ -95,7 +95,7 @@ typedef struct ft2232_layout_s int usbjtag_init(void); int jtagkey_init(void); int olimex_jtag_init(void); -int m5960_init(void); +int flyswatter_init(void); int turtle_init(void); int comstick_init(void); @@ -103,7 +103,7 @@ int comstick_init(void); void usbjtag_reset(int trst, int srst); void jtagkey_reset(int trst, int srst); void olimex_jtag_reset(int trst, int srst); -void m5960_reset(int trst, int srst); +void flyswatter_reset(int trst, int srst); void turtle_reset(int trst, int srst); void comstick_reset(int trst, int srst); @@ -120,7 +120,7 @@ ft2232_layout_t ft2232_layouts[] = {"signalyzer", usbjtag_init, usbjtag_reset, NULL}, {"evb_lm3s811", usbjtag_init, usbjtag_reset, NULL}, {"olimex-jtag", olimex_jtag_init, olimex_jtag_reset, olimex_jtag_blink}, - {"m5960", m5960_init, m5960_reset, NULL}, + {"flyswatter", flyswatter_init, flyswatter_reset, NULL}, {"turtelizer2", turtle_init, turtle_reset, turtle_jtag_blink}, {"comstick", comstick_init, comstick_reset, NULL}, {NULL, NULL, NULL}, @@ -991,7 +991,7 @@ void olimex_jtag_reset(int trst, int srst) DEBUG("trst: %i, srst: %i, high_output: 0x%2.2x, high_direction: 0x%2.2x", trst, srst, high_output, high_direction); } -void m5960_reset(int trst, int srst) +void flyswatter_reset(int trst, int srst) { if (trst == 1) { @@ -1781,7 +1781,7 @@ int olimex_jtag_init(void) return ERROR_OK; } -int m5960_init(void) +int flyswatter_init(void) { u8 buf[3]; u32 bytes_written; @@ -1797,7 +1797,7 @@ int m5960_init(void) if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3)) { - ERROR("couldn't initialize FT2232 with 'm5960' layout"); + ERROR("couldn't initialize FT2232 with 'flyswatter' layout"); return ERROR_JTAG_INIT_FAILED; } @@ -1820,7 +1820,7 @@ int m5960_init(void) if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3)) { - ERROR("couldn't initialize FT2232 with 'm5960' layout"); + ERROR("couldn't initialize FT2232 with 'flyswatter' layout"); return ERROR_JTAG_INIT_FAILED; } diff --git a/src/jtag/gw16012.c b/src/jtag/gw16012.c index 8060d7d6..0d5c3f66 100644 --- a/src/jtag/gw16012.c +++ b/src/jtag/gw16012.c @@ -29,11 +29,9 @@ #define _DEBUG_GW16012_IO_ #endif -/* system includes */ - /* system includes */ // -ino: 060521-1036 -#ifdef __FreeBSD__ +#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) #include #include @@ -47,7 +45,7 @@ #include "errno.h" #endif /* _WIN32 */ -#endif /* __FreeBSD__ */ +#endif /* __FreeBSD__, __FreeBSD_kernel__ */ #include #include @@ -56,7 +54,7 @@ #include #if PARPORT_USE_PPDEV == 1 -#ifdef __FreeBSD__ +#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) #include #include #define PPRSTATUS PPIGSTATUS @@ -137,7 +135,7 @@ void gw16012_data(u8 value) #if PARPORT_USE_PPDEV == 1 ioctl(device_handle, PPWDATA, &value); #else - #ifdef __FreeBSD__ + #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) outb(gw16012_port, value); #else outb(value, gw16012_port); @@ -158,7 +156,7 @@ void gw16012_control(u8 value) #if PARPORT_USE_PPDEV == 1 ioctl(device_handle, PPWCONTROL, &gw16012_control_value); #else - #ifdef __FreeBSD__ + #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) outb(gw16012_port + 2, gw16012_control_value); #else outb(gw16012_control_value, gw16012_port + 2); @@ -485,7 +483,7 @@ int gw16012_init(void) return ERROR_JTAG_INIT_FAILED; } -#ifdef __FreeBSD__ +#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) DEBUG("opening /dev/ppi%d...", gw16012_port); snprintf(buffer, 256, "/dev/ppi%d", gw16012_port); @@ -504,7 +502,7 @@ int gw16012_init(void) DEBUG("...open"); -#ifndef __FreeBSD__ +#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) i=ioctl(device_handle, PPCLAIM); if (i<0) { @@ -548,7 +546,7 @@ int gw16012_init(void) DEBUG("...privileges granted"); /* make sure parallel port is in right mode (clear tristate and interrupt */ -#ifdef __FreeBSD__ +#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) outb(gw16012_port + 2, 0x0); #else outb(0x0, gw16012_port + 2); diff --git a/src/jtag/jtag.c b/src/jtag/jtag.c index c1c52fe4..bac1b39e 100644 --- a/src/jtag/jtag.c +++ b/src/jtag/jtag.c @@ -1251,7 +1251,7 @@ int jtag_examine_chain() if ((zero_check == 0x00) || (one_check == 0xff)) { ERROR("JTAG communication failure, check connection, JTAG interface, target power etc."); - exit(-1); + return ERROR_JTAG_INIT_FAILED; } for (bit_count = 0; bit_count < (JTAG_MAX_CHAIN_SIZE * 32) - 31;) @@ -1300,7 +1300,7 @@ int jtag_examine_chain() ERROR("number of discovered devices in JTAG chain (%i) doesn't match configuration (%i)", device_count, jtag_num_devices); ERROR("check the config file and ensure proper JTAG communication (connections, speed, ...)"); - exit(-1); + return ERROR_JTAG_INIT_FAILED; } return ERROR_OK; @@ -1434,6 +1434,12 @@ int jtag_init(struct command_context_s *cmd_ctx) jtag_add_statemove(TAP_TLR); jtag_execute_queue(); + /* examine chain first, as this could discover the real chain layout */ + if (jtag_examine_chain() != ERROR_OK) + { + ERROR("trying to validate configured JTAG chain anyway..."); + } + while (jtag_validate_chain() != ERROR_OK) { validate_tries++; @@ -1445,8 +1451,6 @@ int jtag_init(struct command_context_s *cmd_ctx) usleep(10000); } - jtag_examine_chain(); - return ERROR_OK; } } diff --git a/src/jtag/parport.c b/src/jtag/parport.c index bc95c3d0..b9087d9f 100644 --- a/src/jtag/parport.c +++ b/src/jtag/parport.c @@ -28,7 +28,7 @@ /* system includes */ // -ino: 060521-1036 -#ifdef __FreeBSD__ +#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) #include #include @@ -49,7 +49,7 @@ #include #if PARPORT_USE_PPDEV == 1 -#ifdef __FreeBSD__ +#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) #include #include #define PPRSTATUS PPIGSTATUS @@ -200,7 +200,7 @@ void parport_write(int tck, int tms, int tdi) #if PARPORT_USE_PPDEV == 1 ioctl(device_handle, PPWDATA, &output); #else -#ifdef __FreeBSD__ +#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) outb(dataport, output); #else outb(output, dataport); @@ -229,7 +229,7 @@ void parport_reset(int trst, int srst) #if PARPORT_USE_PPDEV == 1 ioctl(device_handle, PPWDATA, &output); #else -#ifdef __FreeBSD__ +#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) outb(dataport, output); #else outb(output, dataport); @@ -322,17 +322,17 @@ int parport_init(void) return ERROR_JTAG_INIT_FAILED; } -#ifdef __FreeBSD__ +#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) DEBUG("opening /dev/ppi%d...", parport_port); snprintf(buffer, 256, "/dev/ppi%d", parport_port); device_handle = open(buffer, O_WRONLY); -#else /* not __Free_BSD */ +#else /* not __FreeBSD__, __FreeBSD_kernel__ */ DEBUG("opening /dev/parport%d...", parport_port); snprintf(buffer, 256, "/dev/parport%d", parport_port); device_handle = open(buffer, O_WRONLY); -#endif /* __FreeBSD__ */ +#endif /* __FreeBSD__, __FreeBSD_kernel__ */ if (device_handle < 0) { @@ -342,7 +342,7 @@ int parport_init(void) DEBUG("...open"); -#ifndef __FreeBSD__ +#if !defined(__FreeBSD__) && !defined(__FreeBSD_kernel__) i=ioctl(device_handle, PPCLAIM); if (i<0) { @@ -365,7 +365,7 @@ int parport_init(void) ERROR("cannot set compatible 1284 mode to device"); return ERROR_JTAG_INIT_FAILED; } -#endif /* not __Free_BSD__ */ +#endif /* not __FreeBSD__, __FreeBSD_kernel__ */ #else /* not PARPORT_USE_PPDEV */ if (parport_port == 0) @@ -390,7 +390,7 @@ int parport_init(void) DEBUG("...privileges granted"); /* make sure parallel port is in right mode (clear tristate and interrupt */ - #ifdef __FreeBSD__ + #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) outb(parport_port + 2, 0x0); #else outb(0x0, parport_port + 2); diff --git a/src/jtag/presto.c b/src/jtag/presto.c index fe54b131..95c59303 100644 --- a/src/jtag/presto.c +++ b/src/jtag/presto.c @@ -135,7 +135,6 @@ BYTE presto_init_seq[] = int presto_open(char *req_serial) { int i; - int result; DWORD numdevs; DWORD vidpid; char devname[FT_DEVICE_NAME_LEN]; @@ -144,7 +143,7 @@ int presto_open(char *req_serial) BYTE presto_data; unsigned long ftbytes; - presto->handle=INVALID_HANDLE_VALUE; + presto->handle = (FT_HANDLE)INVALID_HANDLE_VALUE; presto->buff_out_pos=0; presto->buff_in_pos=0; @@ -169,10 +168,10 @@ int presto_open(char *req_serial) break; } FT_Close(presto->handle); - presto->handle=INVALID_HANDLE_VALUE; + presto->handle = (FT_HANDLE)INVALID_HANDLE_VALUE; } - if (presto->handle==INVALID_HANDLE_VALUE) return PRST_ERR; + if (presto->handle == (FT_HANDLE)INVALID_HANDLE_VALUE) return PRST_ERR; if ((presto->status=FT_SetLatencyTimer(presto->handle,1))!=FT_OK) return PRST_ERR; if ((presto->status=FT_SetTimeouts(presto->handle,100,0))!=FT_OK) return PRST_ERR; @@ -219,7 +218,7 @@ int presto_close(void) int result=PRST_OK; - if (presto->handle==INVALID_HANDLE_VALUE) return result; + if (presto->handle == (FT_HANDLE)INVALID_HANDLE_VALUE) return result; presto->status=FT_Write(presto->handle,&presto_init_seq,sizeof(presto_init_seq),&ftbytes); if (presto->status!=FT_OK) result=PRST_ERR; @@ -228,7 +227,7 @@ int presto_close(void) if ((presto->status=FT_SetLatencyTimer(presto->handle,16))!=FT_OK) result=PRST_ERR; if ((presto->status=FT_Close(presto->handle))!=FT_OK) result=PRST_ERR; - else presto->handle=INVALID_HANDLE_VALUE; + else presto->handle = (FT_HANDLE)INVALID_HANDLE_VALUE; return result; } diff --git a/src/jtag/usbprog.c b/src/jtag/usbprog.c index cdf32704..4c39a8ff 100644 --- a/src/jtag/usbprog.c +++ b/src/jtag/usbprog.c @@ -129,83 +129,83 @@ int usbprog_register_commands(struct command_context_s *cmd_ctx) int usbprog_execute_queue(void) { - jtag_command_t *cmd = jtag_command_queue; /* currently processed command */ - int scan_size; - enum scan_type type; - u8 *buffer; - - while (cmd) - { - switch (cmd->type) - { - case JTAG_END_STATE: + jtag_command_t *cmd = jtag_command_queue; /* currently processed command */ + int scan_size; + enum scan_type type; + u8 *buffer; + + while (cmd) + { + switch (cmd->type) + { + case JTAG_END_STATE: #ifdef _DEBUG_JTAG_IO_ - DEBUG("end_state: %i", cmd->cmd.end_state->end_state); +DEBUG("end_state: %i", cmd->cmd.end_state->end_state); #endif - if (cmd->cmd.end_state->end_state != -1) - usbprog_end_state(cmd->cmd.end_state->end_state); - break; - case JTAG_RESET: +if (cmd->cmd.end_state->end_state != -1) + usbprog_end_state(cmd->cmd.end_state->end_state); +break; + case JTAG_RESET: #ifdef _DEBUG_JTAG_IO_ - DEBUG("reset trst: %i srst %i", cmd->cmd.reset->trst, cmd->cmd.reset->srst); + DEBUG("reset trst: %i srst %i", cmd->cmd.reset->trst, cmd->cmd.reset->srst); #endif - if (cmd->cmd.reset->trst == 1) - { - cur_state = TAP_TLR; - } - usbprog_reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst); - break; - case JTAG_RUNTEST: + if (cmd->cmd.reset->trst == 1) + { + cur_state = TAP_TLR; + } + usbprog_reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst); + break; + case JTAG_RUNTEST: #ifdef _DEBUG_JTAG_IO_ - DEBUG("runtest %i cycles, end in %i", cmd->cmd.runtest->num_cycles, cmd->cmd.runtest->end_state); + DEBUG("runtest %i cycles, end in %i", cmd->cmd.runtest->num_cycles, cmd->cmd.runtest->end_state); #endif - if (cmd->cmd.runtest->end_state != -1) - usbprog_end_state(cmd->cmd.runtest->end_state); - usbprog_runtest(cmd->cmd.runtest->num_cycles); - break; - case JTAG_STATEMOVE: + if (cmd->cmd.runtest->end_state != -1) + usbprog_end_state(cmd->cmd.runtest->end_state); + usbprog_runtest(cmd->cmd.runtest->num_cycles); + break; + case JTAG_STATEMOVE: #ifdef _DEBUG_JTAG_IO_ - DEBUG("statemove end in %i", cmd->cmd.statemove->end_state); + DEBUG("statemove end in %i", cmd->cmd.statemove->end_state); #endif - if (cmd->cmd.statemove->end_state != -1) - usbprog_end_state(cmd->cmd.statemove->end_state); - usbprog_state_move(); - break; - case JTAG_PATHMOVE: + if (cmd->cmd.statemove->end_state != -1) + usbprog_end_state(cmd->cmd.statemove->end_state); + usbprog_state_move(); + break; + case JTAG_PATHMOVE: #ifdef _DEBUG_JTAG_IO_ - DEBUG("pathmove: %i states, end in %i", cmd->cmd.pathmove->num_states, - cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]); + DEBUG("pathmove: %i states, end in %i", cmd->cmd.pathmove->num_states, + cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]); #endif - usbprog_path_move(cmd->cmd.pathmove); - break; - case JTAG_SCAN: + usbprog_path_move(cmd->cmd.pathmove); + break; + case JTAG_SCAN: #ifdef _DEBUG_JTAG_IO_ - DEBUG("scan end in %i", cmd->cmd.scan->end_state); + DEBUG("scan end in %i", cmd->cmd.scan->end_state); #endif - if (cmd->cmd.scan->end_state != -1) - usbprog_end_state(cmd->cmd.scan->end_state); - scan_size = jtag_build_buffer(cmd->cmd.scan, &buffer); - type = jtag_scan_type(cmd->cmd.scan); - usbprog_scan(cmd->cmd.scan->ir_scan, type, buffer, scan_size); - if (jtag_read_buffer(buffer, cmd->cmd.scan) != ERROR_OK) - return ERROR_JTAG_QUEUE_FAILED; - if (buffer) - free(buffer); - break; - case JTAG_SLEEP: + if (cmd->cmd.scan->end_state != -1) + usbprog_end_state(cmd->cmd.scan->end_state); + scan_size = jtag_build_buffer(cmd->cmd.scan, &buffer); + type = jtag_scan_type(cmd->cmd.scan); + usbprog_scan(cmd->cmd.scan->ir_scan, type, buffer, scan_size); + if (jtag_read_buffer(buffer, cmd->cmd.scan) != ERROR_OK) + return ERROR_JTAG_QUEUE_FAILED; + if (buffer) + free(buffer); + break; + case JTAG_SLEEP: #ifdef _DEBUG_JTAG_IO_ - DEBUG("sleep %i", cmd->cmd.sleep->us); + DEBUG("sleep %i", cmd->cmd.sleep->us); #endif - jtag_sleep(cmd->cmd.sleep->us); - break; - default: - ERROR("BUG: unknown JTAG command type encountered"); - exit(-1); - } - cmd = cmd->next; - } - - return ERROR_OK; + jtag_sleep(cmd->cmd.sleep->us); + break; + default: + ERROR("BUG: unknown JTAG command type encountered"); + exit(-1); + } + cmd = cmd->next; + } + + return ERROR_OK; } @@ -218,9 +218,9 @@ int usbprog_init(void) ERROR("Can't find USB JTAG Interface! Please check connection and permissions."); return ERROR_JTAG_INIT_FAILED; } - + INFO("USB JTAG Interface ready!"); - + usbprog_jtag_init(usbprog_jtag_handle); usbprog_reset(0, 0); usbprog_write(0, 0, 0); @@ -230,7 +230,7 @@ int usbprog_init(void) int usbprog_quit(void) { - + return ERROR_OK; } @@ -249,69 +249,70 @@ void usbprog_end_state(enum tap_state state) void usbprog_state_move(void) { - int i=0, tms=0; - u8 tms_scan = TAP_MOVE(cur_state, end_state); + int i=0, tms=0; + u8 tms_scan = TAP_MOVE(cur_state, end_state); - usbprog_jtag_write_tms(usbprog_jtag_handle,(char)tms_scan); - for (i = 0; i < 7; i++) - { - tms = (tms_scan >> i) & 1; - } - - cur_state = end_state; + usbprog_jtag_write_tms(usbprog_jtag_handle,(char)tms_scan); + for (i = 0; i < 7; i++) + { + tms = (tms_scan >> i) & 1; + } + + cur_state = end_state; } void usbprog_path_move(pathmove_command_t *cmd) { - int num_states = cmd->num_states; - int state_count; - - state_count = 0; - while (num_states) - { - if (tap_transitions[cur_state].low == cmd->path[state_count]) - { + int num_states = cmd->num_states; + int state_count; + + state_count = 0; + while (num_states) + { + if (tap_transitions[cur_state].low == cmd->path[state_count]) + { INFO("1"); - usbprog_write(0, 0, 0); - usbprog_write(1, 0, 0); - } - else if (tap_transitions[cur_state].high == cmd->path[state_count]) - { + usbprog_write(0, 0, 0); + usbprog_write(1, 0, 0); + } + else if (tap_transitions[cur_state].high == cmd->path[state_count]) + { INFO("2"); - usbprog_write(0, 1, 0); - usbprog_write(1, 1, 0); - } - else - { - ERROR("BUG: %s -> %s isn't a valid TAP transition", tap_state_strings[cur_state], tap_state_strings[cmd->path[state_count]]); - exit(-1); - } - - cur_state = cmd->path[state_count]; - state_count++; - num_states--; - } - - end_state = cur_state; + usbprog_write(0, 1, 0); + usbprog_write(1, 1, 0); + } + else + { + ERROR("BUG: %s -> %s isn't a valid TAP transition", tap_state_strings[cur_state], tap_state_strings[cmd->path[state_count]]); + exit(-1); + } + + cur_state = cmd->path[state_count]; + state_count++; + num_states--; + } + + end_state = cur_state; } void usbprog_runtest(int num_cycles) { - int i; + int i; - enum tap_state saved_end_state = end_state; + /* + enum tap_state saved_end_state = end_state; + */ - /* only do a state_move when we're not already in RTI */ - if (cur_state != TAP_RTI) - { - usbprog_end_state(TAP_RTI); - usbprog_state_move(); - } + if (cur_state != TAP_RTI) + { + usbprog_end_state(TAP_RTI); + usbprog_state_move(); + } - /* execute num_cycles */ + /* execute num_cycles */ if(num_cycles>0) { usbprog_write(0, 0, 0); @@ -320,86 +321,85 @@ void usbprog_runtest(int num_cycles) usbprog_jtag_tms_send(usbprog_jtag_handle); } - for (i = 0; i < num_cycles; i++) - { - usbprog_write(1, 0, 0); - usbprog_write(0, 0, 0); - } + for (i = 0; i < num_cycles; i++) + { + usbprog_write(1, 0, 0); + usbprog_write(0, 0, 0); + } - /* finish in end_state */ + /* finish in end_state */ /* usbprog_end_state(saved_end_state); if (cur_state != end_state) usbprog_state_move(); - */ + */ } void usbprog_scan(int ir_scan, enum scan_type type, u8 *buffer, int scan_size) { - enum tap_state saved_end_state = end_state; - int bit_cnt; + enum tap_state saved_end_state = end_state; - if (ir_scan) - usbprog_end_state(TAP_SI); - else - usbprog_end_state(TAP_SD); + if (ir_scan) + usbprog_end_state(TAP_SI); + else + usbprog_end_state(TAP_SD); - usbprog_state_move(); - usbprog_end_state(saved_end_state); + usbprog_state_move(); + usbprog_end_state(saved_end_state); usbprog_jtag_tms_send(usbprog_jtag_handle); - if (type == SCAN_OUT) { - usbprog_jtag_write_tdi(usbprog_jtag_handle,buffer, scan_size); - } - if (type == SCAN_IN) { - usbprog_jtag_read_tdo(usbprog_jtag_handle,buffer, scan_size); - } - if (type == SCAN_IO) { - usbprog_jtag_write_and_read(usbprog_jtag_handle,buffer, scan_size); - } - - if (ir_scan) - cur_state = TAP_PI; - else - cur_state = TAP_PD; + if (type == SCAN_OUT) { + usbprog_jtag_write_tdi(usbprog_jtag_handle, (char*)buffer, scan_size); + } + if (type == SCAN_IN) { + usbprog_jtag_read_tdo(usbprog_jtag_handle, (char*)buffer, scan_size); + } + if (type == SCAN_IO) { + usbprog_jtag_write_and_read(usbprog_jtag_handle, (char*)buffer, scan_size); + } + + if (ir_scan) + cur_state = TAP_PI; + else + cur_state = TAP_PD; - if (cur_state != end_state) - usbprog_state_move(); + if (cur_state != end_state) + usbprog_state_move(); } /*************** jtag wrapper functions *********************/ void usbprog_write(int tck, int tms, int tdi) { - unsigned char output_value=0x00; + unsigned char output_value=0x00; - if (tms) - output_value |= (1< 0) { if(size > 488) { send_bits = 488; @@ -501,9 +500,9 @@ void usbprog_jtag_write_and_read(struct usbprog_jtag *usbprog_jtag, char * buffe tmp[3+i]=buffer[bufindex]; bufindex++; } - + usb_bulk_write(usbprog_jtag->usb_handle,3,tmp,64,1000); - + while(usb_bulk_read(usbprog_jtag->usb_handle,0x82, tmp, 64, 1000) < 1); for(i=0;i 0) { if(size > 488) { send_bits = 488; @@ -536,9 +535,9 @@ void usbprog_jtag_read_tdo(struct usbprog_jtag *usbprog_jtag, char * buffer, int tmp[0] = WRITE_AND_READ; tmp[1] = (char)(send_bits>>8); // high tmp[2] = (char)(send_bits); // low - + usb_bulk_write(usbprog_jtag->usb_handle,3,tmp,3,1000); - + while(usb_bulk_read(usbprog_jtag->usb_handle,0x82, tmp, 64, 10) < 1); for(i=0;i 0) { if(size > 488) { send_bits = 488; @@ -562,13 +561,13 @@ void usbprog_jtag_write_tdi(struct usbprog_jtag *usbprog_jtag, char * buffer, in } else { send_bits = size; loops = size/8; - //if(loops==0) + /*if(loops==0)*/ loops++; size = 0; } tmp[0] = WRITE_TDI; - tmp[1] = (char)(send_bits>>8); // high - tmp[2] = (char)(send_bits); // low + tmp[1] = (char)(send_bits>>8); /* high */ + tmp[2] = (char)(send_bits); /* low */ i=0; for(i=0;i < loops ;i++) { diff --git a/src/server/Makefile.am b/src/server/Makefile.am index 2397a7f0..a41e9320 100644 --- a/src/server/Makefile.am +++ b/src/server/Makefile.am @@ -1,4 +1,4 @@ -INCLUDES = -I$(top_srcdir)/src/helper -I$(top_srcdir)/src/target $(all_includes) +INCLUDES = -I$(top_srcdir)/src/helper -I$(top_srcdir)/src/target -I$(top_srcdir)/src/flash $(all_includes) METASOURCES = AUTO noinst_LIBRARIES = libserver.a noinst_HEADERS = server.h telnet_server.h gdb_server.h diff --git a/src/server/gdb_server.c b/src/server/gdb_server.c index 19c6a233..3481625e 100644 --- a/src/server/gdb_server.c +++ b/src/server/gdb_server.c @@ -29,6 +29,8 @@ #include "log.h" #include "binarybuffer.h" #include "breakpoints.h" +#include "flash.h" +#include "target_request.h" #define __USE_GNU #include @@ -66,7 +68,7 @@ int gdb_get_char(connection_t *connection, int* next_char) { gdb_connection_t *gdb_con = connection->priv; char *debug_buffer; - + if (gdb_con->buf_cnt-- > 0) { *next_char = *(gdb_con->buf_p++); @@ -74,11 +76,11 @@ int gdb_get_char(connection_t *connection, int* next_char) connection->input_pending = 1; else connection->input_pending = 0; - + #ifdef _DEBUG_GDB_IO_ DEBUG("returned char '%c' (0x%2.2x)", *next_char, *next_char); #endif - + return ERROR_OK; } @@ -86,7 +88,7 @@ int gdb_get_char(connection_t *connection, int* next_char) { if (gdb_con->buf_cnt == 0) return ERROR_SERVER_REMOTE_CLOSED; - + #ifdef _WIN32 errno = WSAGetLastError(); @@ -117,7 +119,7 @@ int gdb_get_char(connection_t *connection, int* next_char) } #endif } - + debug_buffer = malloc(gdb_con->buf_cnt + 1); memcpy(debug_buffer, gdb_con->buffer, gdb_con->buf_cnt); debug_buffer[gdb_con->buf_cnt] = 0; @@ -132,16 +134,16 @@ int gdb_get_char(connection_t *connection, int* next_char) else connection->input_pending = 0; #ifdef _DEBUG_GDB_IO_ - DEBUG("returned char '%c' (0x%2.2x)", *next_char, *next_char); + DEBUG("returned char '%c' (0x%2.2x)", *next_char, *next_char); #endif - + return ERROR_OK; } int gdb_putback_char(connection_t *connection, int last_char) { gdb_connection_t *gdb_con = connection->priv; - + if (gdb_con->buf_p > gdb_con->buffer) { *(--gdb_con->buf_p) = last_char; @@ -151,7 +153,7 @@ int gdb_putback_char(connection_t *connection, int last_char) { ERROR("BUG: couldn't put character back"); } - + return ERROR_OK; } @@ -167,23 +169,23 @@ int gdb_put_packet(connection_t *connection, char *buffer, int len) for (i = 0; i < len; i++) my_checksum += buffer[i]; - + while (1) { - + debug_buffer = malloc(len + 1); memcpy(debug_buffer, buffer, len); debug_buffer[len] = 0; DEBUG("sending packet '$%s#%2.2x'", debug_buffer, my_checksum); free(debug_buffer); - + write_socket(connection->fd, "$", 1); if (len > 0) write_socket(connection->fd, buffer, len); write_socket(connection->fd, "#", 1); - + snprintf(checksum, 3, "%2.2x", my_checksum); - + write_socket(connection->fd, checksum, 2); if ((retval = gdb_get_char(connection, &reply)) != ERROR_OK) @@ -214,7 +216,7 @@ int gdb_put_packet(connection_t *connection, char *buffer, int len) return ERROR_SERVER_REMOTE_CLOSED; } } - + return ERROR_OK; } @@ -223,8 +225,6 @@ int gdb_get_packet(connection_t *connection, char *buffer, int *len) int character; int count = 0; int retval; - int first_char = 0; - int packet_type = '\0'; char checksum[3]; unsigned char my_checksum = 0; gdb_connection_t *gdb_con = connection->priv; @@ -259,18 +259,18 @@ int gdb_get_packet(connection_t *connection, char *buffer, int *len) } while (character != '$'); my_checksum = 0; - + do { if ((retval = gdb_get_char(connection, &character)) != ERROR_OK) return retval; - + if (character == '#') break; if (character == '}') { /* data transmitted in binary mode (X packet) - * uses 0x7d as escape character */ + * uses 0x7d as escape character */ my_checksum += character & 0xff; if ((retval = gdb_get_char(connection, &character)) != ERROR_OK) return retval; @@ -291,7 +291,7 @@ int gdb_get_packet(connection_t *connection, char *buffer, int *len) } while (1); *len = count; - + if ((retval = gdb_get_char(connection, &character)) != ERROR_OK) return retval; checksum[0] = character; @@ -299,7 +299,7 @@ int gdb_get_packet(connection_t *connection, char *buffer, int *len) return retval; checksum[1] = character; checksum[2] = 0; - + if (my_checksum == strtoul(checksum, NULL, 16)) { write_socket(connection->fd, "+", 1); @@ -320,7 +320,7 @@ int gdb_output(struct command_context_s *context, char* line) int i, bin_size; bin_size = strlen(line); - + hex_buffer = malloc(bin_size*2 + 4); hex_buffer[0] = 'O'; @@ -342,7 +342,7 @@ int gdb_target_callback_event_handler(struct target_s *target, enum target_event gdb_connection_t *gdb_connection = connection->priv; char sig_reply[4]; int signal; - + switch (event) { case TARGET_EVENT_HALTED: @@ -357,7 +357,7 @@ int gdb_target_callback_event_handler(struct target_s *target, enum target_event { signal = gdb_last_signal(target); } - + snprintf(sig_reply, 4, "T%2.2x", signal); gdb_put_packet(connection, sig_reply, 3); gdb_connection->frontend_state = TARGET_HALTED; @@ -382,51 +382,66 @@ int gdb_new_connection(connection_t *connection) gdb_service_t *gdb_service = connection->service->priv; int retval; int initial_ack; - + connection->priv = gdb_connection; - + /* initialize gdb connection information */ gdb_connection->buf_p = gdb_connection->buffer; gdb_connection->buf_cnt = 0; gdb_connection->ctrl_c = 0; gdb_connection->frontend_state = TARGET_HALTED; - + gdb_connection->vflash_image = NULL; + /* output goes through gdb connection */ command_set_output_handler(connection->cmd_ctx, gdb_output, connection); - + /* register callback to be informed about target events */ target_register_event_callback(gdb_target_callback_event_handler, connection); - + /* a gdb session just attached, put the target in halt mode */ if (((retval = gdb_service->target->type->halt(gdb_service->target)) != ERROR_OK) && - (retval != ERROR_TARGET_ALREADY_HALTED)) + (retval != ERROR_TARGET_ALREADY_HALTED)) { ERROR("error when trying to halt target"); exit(-1); } - + while (gdb_service->target->state != TARGET_HALTED) { gdb_service->target->type->poll(gdb_service->target); } - + /* remove the initial ACK from the incoming buffer */ if ((retval = gdb_get_char(connection, &initial_ack)) != ERROR_OK) return retval; - + if (initial_ack != '+') gdb_putback_char(connection, initial_ack); - + return ERROR_OK; } int gdb_connection_closed(connection_t *connection) { + gdb_service_t *gdb_service = connection->service->priv; + gdb_connection_t *gdb_connection = connection->priv; + + /* see if an image built with vFlash commands is left */ + if (gdb_connection->vflash_image) + { + image_close(gdb_connection->vflash_image); + free(gdb_connection->vflash_image); + gdb_connection->vflash_image = NULL; + } + + /* if this connection registered a debug-message receiver delete it */ + delete_debug_msg_receiver(connection->cmd_ctx, gdb_service->target); + if (connection->priv) free(connection->priv); else ERROR("BUG: connection->priv == NULL"); - + target_unregister_event_callback(gdb_target_callback_event_handler, connection); return ERROR_OK; @@ -434,21 +449,21 @@ int gdb_connection_closed(connection_t *connection) void gdb_send_error(connection_t *connection, u8 the_error) { - char err[4]; - snprintf(err, 4, "E%2.2X", the_error ); - gdb_put_packet(connection, err, 3); + char err[4]; + snprintf(err, 4, "E%2.2X", the_error ); + gdb_put_packet(connection, err, 3); } int gdb_last_signal_packet(connection_t *connection, target_t *target, char* packet, int packet_size) { char sig_reply[4]; int signal; - + signal = gdb_last_signal(target); snprintf(sig_reply, 4, "S%2.2x", signal); gdb_put_packet(connection, sig_reply, 3); - + return ERROR_OK; } @@ -456,13 +471,13 @@ void gdb_str_to_target(target_t *target, char *str, char *tstr) { int str_len = strlen(str); int i; - + if (str_len % 2) { ERROR("BUG: gdb value with uneven number of characters encountered: %s", str); exit(-1); } - + if (target->endianness == TARGET_LITTLE_ENDIAN) { for (i = 0; i < str_len; i+=2) @@ -490,7 +505,7 @@ void gdb_target_to_str(target_t *target, char *tstr, char *str) ERROR("BUG: gdb value with uneven number of characters encountered"); exit(-1); } - + if (target->endianness == TARGET_LITTLE_ENDIAN) { for (i = 0; i < str_len; i+=2) @@ -517,7 +532,7 @@ int gdb_get_registers_packet(connection_t *connection, target_t *target, char* p char *reg_packet; char *reg_packet_p; int i; - + DEBUG("-"); if ((retval = target->type->get_gdb_reg_list(target, ®_list, ®_list_size)) != ERROR_OK) @@ -538,10 +553,10 @@ int gdb_get_registers_packet(connection_t *connection, target_t *target, char* p { reg_packet_size += reg_list[i]->size; } - + reg_packet = malloc(CEIL(reg_packet_size, 8) * 2); reg_packet_p = reg_packet; - + for (i = 0; i < reg_list_size; i++) { char *hex_buf = buf_to_str(reg_list[i]->value, reg_list[i]->size, 16); @@ -554,12 +569,12 @@ int gdb_get_registers_packet(connection_t *connection, target_t *target, char* p reg_packet_p = strndup(reg_packet, CEIL(reg_packet_size, 8) * 2); DEBUG("reg_packet: %s", reg_packet_p); free(reg_packet_p); - + gdb_put_packet(connection, reg_packet, CEIL(reg_packet_size, 8) * 2); free(reg_packet); - + free(reg_list); - + return ERROR_OK; } @@ -570,7 +585,7 @@ int gdb_set_registers_packet(connection_t *connection, target_t *target, char *p int reg_list_size; int retval; char *packet_p; - + DEBUG("-"); /* skip command character */ @@ -603,11 +618,11 @@ int gdb_set_registers_packet(connection_t *connection, target_t *target, char *p u8 *bin_buf; char *hex_buf; reg_arch_type_t *arch_type; - + /* convert from GDB-string (target-endian) to hex-string (big-endian) */ hex_buf = malloc(CEIL(reg_list[i]->size, 8) * 2); gdb_target_to_str(target, packet_p, hex_buf); - + /* convert hex-string to binary buffer */ bin_buf = malloc(CEIL(reg_list[i]->size, 8)); str_to_buf(hex_buf, CEIL(reg_list[i]->size, 8) * 2, bin_buf, reg_list[i]->size, 16); @@ -623,16 +638,16 @@ int gdb_set_registers_packet(connection_t *connection, target_t *target, char *p /* advance packet pointer */ packet_p += (CEIL(reg_list[i]->size, 8) * 2); - + free(bin_buf); free(hex_buf); } - + /* free reg_t *reg_list[] array allocated by get_gdb_reg_list */ free(reg_list); gdb_put_packet(connection, "OK", 2); - + return ERROR_OK; } @@ -644,9 +659,9 @@ int gdb_get_register_packet(connection_t *connection, target_t *target, char *pa int reg_list_size; int retval; char *hex_buf; - + DEBUG("-"); - + if ((retval = target->type->get_gdb_reg_list(target, ®_list, ®_list_size)) != ERROR_OK) { switch (retval) @@ -660,7 +675,7 @@ int gdb_get_register_packet(connection_t *connection, target_t *target, char *pa exit(-1); } } - + if (reg_list_size <= reg_num) { ERROR("gdb requested a non-existing register"); @@ -670,15 +685,15 @@ int gdb_get_register_packet(connection_t *connection, target_t *target, char *pa reg_packet = malloc(CEIL(reg_list[reg_num]->size, 8) * 2); hex_buf = buf_to_str(reg_list[reg_num]->value, reg_list[reg_num]->size, 16); - + gdb_str_to_target(target, hex_buf, reg_packet); - + gdb_put_packet(connection, reg_packet, CEIL(reg_list[reg_num]->size, 8) * 2); - + free(reg_list); free(reg_packet); free(hex_buf); - + return ERROR_OK; } @@ -692,9 +707,9 @@ int gdb_set_register_packet(connection_t *connection, target_t *target, char *pa int reg_list_size; int retval; reg_arch_type_t *arch_type; - + DEBUG("-"); - + if ((retval = target->type->get_gdb_reg_list(target, ®_list, ®_list_size)) != ERROR_OK) { switch (retval) @@ -708,7 +723,7 @@ int gdb_set_register_packet(connection_t *connection, target_t *target, char *pa exit(-1); } } - + if (reg_list_size < reg_num) { ERROR("gdb requested a non-existing register"); @@ -720,11 +735,11 @@ int gdb_set_register_packet(connection_t *connection, target_t *target, char *pa ERROR("GDB 'set register packet', but no '=' following the register number"); return ERROR_SERVER_REMOTE_CLOSED; } - + /* convert from GDB-string (target-endian) to hex-string (big-endian) */ hex_buf = malloc(CEIL(reg_list[reg_num]->size, 8) * 2); gdb_target_to_str(target, separator + 1, hex_buf); - + /* convert hex-string to binary buffer */ bin_buf = malloc(CEIL(reg_list[reg_num]->size, 8)); str_to_buf(hex_buf, CEIL(reg_list[reg_num]->size, 8) * 2, bin_buf, reg_list[reg_num]->size, 16); @@ -768,7 +783,7 @@ int gdb_memory_packet_error(connection_t *connection, int retval) ERROR("BUG: unexpected error %i", retval); exit(-1); } - + return ERROR_OK; } @@ -788,7 +803,7 @@ int gdb_read_memory_packet(connection_t *connection, target_t *target, char *pac packet++; addr = strtoul(packet, &separator, 16); - + if (*separator != ',') { ERROR("incomplete read memory packet received, dropping connection"); @@ -825,12 +840,12 @@ int gdb_read_memory_packet(connection_t *connection, target_t *target, char *pac if (retval == ERROR_OK) { hex_buffer = malloc(len * 2 + 1); - + for (i=0; itype->write_memory(target, addr, 1, len, buffer); break; - /* handle bulk writes */ + /* handle bulk writes */ default: retval = target_write_buffer(target, addr, len, buffer); break; @@ -920,9 +935,9 @@ int gdb_write_memory_packet(connection_t *connection, target_t *target, char *pa if ((retval = gdb_memory_packet_error(connection, retval)) != ERROR_OK) return retval; } - + free(buffer); - + return ERROR_OK; } @@ -939,7 +954,7 @@ int gdb_write_memory_binary_packet(connection_t *connection, target_t *target, c packet++; addr = strtoul(packet, &separator, 16); - + if (*separator != ',') { ERROR("incomplete write memory binary packet received, dropping connection"); @@ -956,13 +971,13 @@ int gdb_write_memory_binary_packet(connection_t *connection, target_t *target, c retval = ERROR_OK; if( len ) { - + buffer = malloc(len); - + DEBUG("addr: 0x%8.8x, len: 0x%8.8x", addr, len); - + memcpy( buffer, separator, len ); - + switch (len) { case 4: @@ -985,7 +1000,7 @@ int gdb_write_memory_binary_packet(connection_t *connection, target_t *target, c retval = target_write_buffer(target, addr, len, buffer); break; } - + free(buffer); } @@ -998,7 +1013,7 @@ int gdb_write_memory_binary_packet(connection_t *connection, target_t *target, c if ((retval = gdb_memory_packet_error(connection, retval)) != ERROR_OK) return retval; } - + return ERROR_OK; } @@ -1046,7 +1061,7 @@ int gdb_bp_wp_packet_error(connection_t *connection, int retval) ERROR("BUG: unexpected error %i", retval); exit(-1); } - + return ERROR_OK; } @@ -1063,7 +1078,7 @@ int gdb_breakpoint_watchpoint_packet(connection_t *connection, target_t *target, DEBUG("-"); type = strtoul(packet + 1, &separator, 16); - + if (type == 0) /* memory breakpoint */ bp_type = BKPT_SOFT; else if (type == 1) /* hardware breakpoint */ @@ -1074,7 +1089,7 @@ int gdb_breakpoint_watchpoint_packet(connection_t *connection, target_t *target, wp_type = WPT_READ; else if (type == 4) /* access watchpoint */ wp_type = WPT_ACCESS; - + if (*separator != ',') { ERROR("incomplete breakpoint/watchpoint packet received, dropping connection"); @@ -1167,8 +1182,126 @@ void gdb_query_packet(connection_t *connection, char *packet, int packet_size) gdb_put_packet(connection, "OK", 2); return; } - + + gdb_put_packet(connection, "", 0); +} + +int gdb_v_packet(connection_t *connection, target_t *target, char *packet, int packet_size) +{ + gdb_connection_t *gdb_connection = connection->priv; + gdb_service_t *gdb_service = connection->service->priv; + int result; + + if (strstr(packet, "vFlashErase:")) + { + unsigned long addr; + unsigned long length; + char *parse = packet + 12; + if (*parse == '\0') + { + ERROR("incomplete vFlashErase packet received, dropping connection"); + return ERROR_SERVER_REMOTE_CLOSED; + } + + addr = strtoul(parse, &parse, 16); + + if (*(parse++) != ',' || *parse == '\0') + { + ERROR("incomplete vFlashErase packet received, dropping connection"); + return ERROR_SERVER_REMOTE_CLOSED; + } + + length = strtoul(parse, &parse, 16); + + if (*parse != '\0') + { + ERROR("incomplete vFlashErase packet received, dropping connection"); + return ERROR_SERVER_REMOTE_CLOSED; + } + + /* perform erase */ + if ((result = flash_erase(gdb_service->target, addr, length)) != ERROR_OK) + { + /* GDB doesn't evaluate the actual error number returned, + * treat a failed erase as an I/O error + */ + gdb_send_error(connection, EIO); + ERROR("flash_erase returned %i", result); + } + else + gdb_put_packet(connection, "OK", 2); + + return ERROR_OK; + } + + if (strstr(packet, "vFlashWrite:")) + { + unsigned long addr; + unsigned long length; + char *parse = packet + 12; + + if (*parse == '\0') + { + ERROR("incomplete vFlashErase packet received, dropping connection"); + return ERROR_SERVER_REMOTE_CLOSED; + } + addr = strtoul(parse, &parse, 16); + if (*(parse++) != ':') + { + ERROR("incomplete vFlashErase packet received, dropping connection"); + return ERROR_SERVER_REMOTE_CLOSED; + } + length = packet_size - (parse - packet); + + /* create a new image if there isn't already one */ + if (gdb_connection->vflash_image == NULL) + { + gdb_connection->vflash_image = malloc(sizeof(image_t)); + image_open(gdb_connection->vflash_image, "", "build"); + } + + /* create new section with content from packet buffer */ + image_add_section(gdb_connection->vflash_image, addr, length, 0x0, (u8*)parse); + + gdb_put_packet(connection, "OK", 2); + + return ERROR_OK; + } + + if (!strcmp(packet, "vFlashDone")) + { + u32 image_size; + char *error_str; + u32 *failed = malloc(sizeof(u32) * gdb_connection->vflash_image->num_sections); + + /* process the flashing buffer */ + if ((result = flash_write(gdb_service->target, gdb_connection->vflash_image, &image_size, &error_str, failed)) != ERROR_OK) + { + if (result == ERROR_FLASH_DST_OUT_OF_BANK) + gdb_put_packet(connection, "E.memtype", 9); + else + gdb_send_error(connection, EIO); + + ERROR("flash writing failed: %s", error_str); + free(error_str); + } + else + { + DEBUG("wrote %u bytes from vFlash image to flash", image_size); + gdb_put_packet(connection, "OK", 2); + } + + free(failed); + + image_close(gdb_connection->vflash_image); + free(gdb_connection->vflash_image); + gdb_connection->vflash_image = NULL; + + return ERROR_OK; + } + gdb_put_packet(connection, "", 0); + return ERROR_OK; } int gdb_input(connection_t *connection) @@ -1198,12 +1331,12 @@ int gdb_input(connection_t *connection) exit(-1); } } - + /* terminate with zero */ packet[packet_size] = 0; - + DEBUG("recevied packet: '%s'", packet); - + if (packet_size > 0) { retval = ERROR_OK; @@ -1211,7 +1344,7 @@ int gdb_input(connection_t *connection) { case 'H': /* Hct... -- set thread - * we don't have threads, send empty reply */ + * we don't have threads, send empty reply */ gdb_put_packet(connection, NULL, 0); break; case 'q': @@ -1241,11 +1374,14 @@ int gdb_input(connection_t *connection) break; case '?': gdb_last_signal_packet(connection, target, packet, packet_size); - break; + break; case 'c': case 's': gdb_step_continue_packet(connection, target, packet, packet_size); break; + case 'v': + retval = gdb_v_packet(connection, target, packet, packet_size); + break; case 'D': target->type->resume(target, 1, 0, 1, 0); gdb_put_packet(connection, "OK", 2); @@ -1263,12 +1399,12 @@ int gdb_input(connection_t *connection) gdb_put_packet(connection, NULL, 0); break; } - + /* if a packet handler returned an error, exit input loop */ if (retval != ERROR_OK) return retval; } - + if (gdb_con->ctrl_c) { if (target->state == TARGET_RUNNING) @@ -1277,7 +1413,7 @@ int gdb_input(connection_t *connection) gdb_con->ctrl_c = 0; } } - + } while (gdb_con->buf_cnt > 0); return ERROR_OK; @@ -1288,36 +1424,36 @@ int gdb_init() gdb_service_t *gdb_service; target_t *target = targets; int i = 0; - + if (!target) { WARNING("no gdb ports allocated as no target has been specified"); return ERROR_OK; } - + if (gdb_port == 0) { WARNING("no gdb port specified, using default port 3333"); gdb_port = 3333; } - + while (target) { char service_name[8]; - + snprintf(service_name, 8, "gdb-%2.2i", i); - + gdb_service = malloc(sizeof(gdb_service_t)); gdb_service->target = target; - + add_service("gdb", CONNECTION_GDB, gdb_port + i, 1, gdb_new_connection, gdb_input, gdb_connection_closed, gdb_service); - + DEBUG("gdb service for target %s at port %i", target->type->name, gdb_port + i); - + i++; target = target->next; } - + return ERROR_OK; } @@ -1337,7 +1473,7 @@ int handle_gdb_port_command(struct command_context_s *cmd_ctx, char *cmd, char * int gdb_register_commands(command_context_t *command_context) { register_command(command_context, NULL, "gdb_port", handle_gdb_port_command, - COMMAND_CONFIG, ""); - + COMMAND_CONFIG, ""); + return ERROR_OK; } diff --git a/src/server/gdb_server.h b/src/server/gdb_server.h index 860b29ca..cd00ce29 100644 --- a/src/server/gdb_server.h +++ b/src/server/gdb_server.h @@ -22,6 +22,7 @@ #include "target.h" #include "server.h" +#include "image.h" #define GDB_BUFFER_SIZE 2048 @@ -32,6 +33,7 @@ typedef struct gdb_connection_s int buf_cnt; int ctrl_c; enum target_state frontend_state; + image_t *vflash_image; } gdb_connection_t; typedef struct gdb_service_s diff --git a/src/server/server.c b/src/server/server.c index 3ad6f377..98b1fb1d 100644 --- a/src/server/server.c +++ b/src/server/server.c @@ -323,13 +323,6 @@ int server_loop(command_context_t *command_context) /* do regular tasks after at most 100ms */ tv.tv_sec = 0; tv.tv_usec = 10000; - -#if 0 - if (shutdown_openocd) - return ERROR_COMMAND_CLOSE_CONNECTION; - - handle_target(); -#endif } for (service = services; service; service = service->next) diff --git a/src/server/telnet_server.c b/src/server/telnet_server.c index b573ec5c..eeb2cc82 100644 --- a/src/server/telnet_server.c +++ b/src/server/telnet_server.c @@ -29,6 +29,7 @@ #include "log.h" #include "command.h" #include "target.h" +#include "target_request.h" #include #include @@ -513,6 +514,9 @@ int telnet_connection_closed(connection_t *connection) free(t_con->history[i]); } + /* if this connection registered a debug-message receiver delete it */ + delete_debug_msg_receiver(connection->cmd_ctx, NULL); + if (connection->priv) free(connection->priv); else 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 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 #include @@ -34,6 +35,7 @@ #include "register.h" #include "jtag.h" #include "arm7_9_common.h" +#include "replacements.h" #include @@ -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
"); register_command(cmd_ctx, NULL, "dump_binary", handle_dump_image_command, COMMAND_EXEC, "[DEPRECATED] dump_binary
"); + 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 +#include + +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 + +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,