From 4fc97d3f2726efa147cfdb0c456eace51550e1e3 Mon Sep 17 00:00:00 2001 From: drath Date: Mon, 22 Jan 2007 14:47:00 +0000 Subject: [PATCH] - fix incorrect parsing of whitespace in command.c (thanks to Magnus Lundin) - fix infinite recursion in target_init_handler (thanks to jw and Magnus Lundin) - fix CFI flash handlign with buswidth < 32bit (thanks to Daniele Orio for reporting this) - add support for reading JTAG device id (currently only as debug output on startup) - cleaned up handling of EmbeddedICE registers. Supported functionality and register size now determined by EmbeddedICE version number. - small cleanups/fixes git-svn-id: svn://svn.berlios.de/openocd/trunk@124 b42882b7-edfa-0310-969c-e2dbd0fdcd60 --- src/flash/cfi.c | 57 ++++++++++++++++++---- src/flash/flash.c | 4 ++ src/helper/command.c | 25 +++++++--- src/jtag/jtag.c | 96 +++++++++++++++++++++++++++++++++++++- src/jtag/jtag.h | 2 +- src/target/arm7_9_common.c | 4 ++ src/target/arm7_9_common.h | 4 ++ src/target/arm7tdmi.c | 26 ++--------- src/target/arm7tdmi.h | 1 - src/target/arm920t.c | 2 +- src/target/arm966e.c | 42 ----------------- src/target/arm966e.h | 1 - src/target/arm9tdmi.c | 29 ++++-------- src/target/arm9tdmi.h | 2 - src/target/embeddedice.c | 67 ++++++++++++++++++++++---- src/target/embeddedice.h | 5 +- src/target/target.c | 4 +- 17 files changed, 252 insertions(+), 119 deletions(-) diff --git a/src/flash/cfi.c b/src/flash/cfi.c index e91fcc7ed..7f2313d82 100644 --- a/src/flash/cfi.c +++ b/src/flash/cfi.c @@ -88,6 +88,12 @@ 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 + * are set to zero + */ + for (i = 0; i < CFI_MAX_BUS_WIDTH; i++) + cmd_buf[i] = 0; + if (cfi_info->target->endianness == TARGET_LITTLE_ENDIAN) { for (i = bank->bus_width; i > 0; i--) @@ -206,7 +212,10 @@ u8 cfi_intel_wait_status_busy(flash_bank_t *bank, int timeout) DEBUG("status: 0x%x", status); usleep(1000); } - + + /* mask out bit 0 (reserved) */ + status = status & 0xfe; + DEBUG("status: 0x%x", status); if ((status & 0x80) != 0x80) @@ -438,6 +447,7 @@ int cfi_intel_protect(struct flash_bank_s *bank, int set, int first, int last) cfi_intel_pri_ext_t *pri_ext = cfi_info->pri_ext; target_t *target = cfi_info->target; u8 command[8]; + int retry = 0; int i; /* if the device supports neither legacy lock/unlock (bit 3) nor @@ -451,22 +461,53 @@ int cfi_intel_protect(struct flash_bank_s *bank, int set, int first, int last) for (i = first; i <= last; i++) { cfi_command(bank, 0x60, command); + DEBUG("address: 0x%4.4x, command: 0x%4.4x", flash_address(bank, i, 0x0), target_buffer_get_u32(target, command)); target->type->write_memory(target, flash_address(bank, i, 0x0), bank->bus_width, 1, command); if (set) { cfi_command(bank, 0x01, command); + DEBUG("address: 0x%4.4x, command: 0x%4.4x", flash_address(bank, i, 0x0), target_buffer_get_u32(target, command)); target->type->write_memory(target, flash_address(bank, i, 0x0), bank->bus_width, 1, command); bank->sectors[i].is_protected = 1; } else { cfi_command(bank, 0xd0, command); + DEBUG("address: 0x%4.4x, command: 0x%4.4x", flash_address(bank, i, 0x0), target_buffer_get_u32(target, command)); target->type->write_memory(target, flash_address(bank, i, 0x0), bank->bus_width, 1, command); bank->sectors[i].is_protected = 0; } - - /* Clear lock bits operation may take up to 1.4s */ - cfi_intel_wait_status_busy(bank, 1400); + + /* instant individual block locking doesn't require reading of the status register */ + if (!(pri_ext->feature_support & 0x20)) + { + /* Clear lock bits operation may take up to 1.4s */ + cfi_intel_wait_status_busy(bank, 1400); + } + else + { + u8 block_status; + /* read block lock bit, to verify status */ + cfi_command(bank, 0x90, command); + target->type->write_memory(target, flash_address(bank, 0, 0x55), bank->bus_width, 1, command); + block_status = cfi_get_u8(bank, i, 0x2); + + if ((block_status & 0x1) != set) + { + ERROR("couldn't change block lock status (set = %i, block_status = 0x%2.2x)", set, block_status); + cfi_command(bank, 0x70, command); + target->type->write_memory(target, flash_address(bank, 0, 0x55), bank->bus_width, 1, command); + cfi_intel_wait_status_busy(bank, 10); + + if (retry > 10) + return ERROR_FLASH_OPERATION_FAILED; + else + { + i--; + retry++; + } + } + } } /* if the device doesn't support individual block lock bits set/clear, @@ -683,7 +724,7 @@ int cfi_intel_write_block(struct flash_bank_s *bank, u8 *buffer, u32 address, u3 cfi_command(bank, 0x40, write_command); cfi_command(bank, 0x80, busy_pattern); - cfi_command(bank, 0x7f, error_pattern); + cfi_command(bank, 0x7e, error_pattern); while (count > 0) { @@ -694,9 +735,9 @@ int cfi_intel_write_block(struct flash_bank_s *bank, u8 *buffer, u32 address, u3 buf_set_u32(reg_params[0].value, 0, 32, source->address); buf_set_u32(reg_params[1].value, 0, 32, address); buf_set_u32(reg_params[2].value, 0, 32, thisrun_count / bank->bus_width); - buf_set_u32(reg_params[3].value, 0, 32, buf_get_u32(write_command, 0, 32)); - buf_set_u32(reg_params[5].value, 0, 32, buf_get_u32(busy_pattern, 0, 32)); - buf_set_u32(reg_params[6].value, 0, 32, buf_get_u32(error_pattern, 0, 32)); + buf_set_u32(reg_params[3].value, 0, 32, target_buffer_get_u32(target, write_command)); + buf_set_u32(reg_params[5].value, 0, 32, target_buffer_get_u32(target, busy_pattern)); + buf_set_u32(reg_params[6].value, 0, 32, target_buffer_get_u32(target, error_pattern)); if ((retval = target->type->run_algorithm(target, 0, NULL, 7, reg_params, cfi_info->write_algorithm->address, cfi_info->write_algorithm->address + (13 * 4), 10000, &armv4_5_info)) != ERROR_OK) { diff --git a/src/flash/flash.c b/src/flash/flash.c index 736d3fca1..0a6796468 100644 --- a/src/flash/flash.c +++ b/src/flash/flash.c @@ -471,6 +471,10 @@ int handle_flash_protect_command(struct command_context_s *cmd_ctx, char *cmd, c command_print(cmd_ctx, "unknown error"); } } + else + { + command_print(cmd_ctx, "%s protection for sectors %i through %i on flash bank %i", (set) ? "set" : "cleared", first, last, strtoul(args[0], 0, 0)); + } } else { diff --git a/src/helper/command.c b/src/helper/command.c index ca08535a4..dbf3f2aa1 100644 --- a/src/helper/command.c +++ b/src/helper/command.c @@ -200,12 +200,23 @@ int parse_line(char *line, char *words[], int max_words) /* we're inside a word or quote, and reached its end*/ if (word_start) { - int len = p - word_start; - - /* copy the word */ - memcpy(words[nwords] = malloc(len + 1), word_start, len); - /* add terminating NUL */ - words[nwords++][len] = 0; + int len; + char *word_end=p; + /* This will handle extra whitespace within quotes */ + while (isspace(*word_start)&&(word_start0) + { + /* copy the word */ + memcpy(words[nwords] = malloc(len + 1), word_start, len); + /* add terminating NUL */ + words[nwords++][len] = 0; + } } /* we're done parsing the line */ @@ -215,6 +226,8 @@ int parse_line(char *line, char *words[], int max_words) /* skip over trailing quote or whitespace*/ if (inquote || isspace(*p)) p++; + while (isspace(*p)) + p++; inquote = 0; word_start = 0; diff --git a/src/jtag/jtag.c b/src/jtag/jtag.c index 263eed1a9..cc9f8dc45 100644 --- a/src/jtag/jtag.c +++ b/src/jtag/jtag.c @@ -115,6 +115,10 @@ int jtag_verify_capture_ir = 1; int jtag_nsrst_delay = 0; /* default to no nSRST delay */ int jtag_ntrst_delay = 0; /* default to no nTRST delay */ +/* maximum number of JTAG devices expected in the chain + */ +#define JTAG_MAX_CHAIN_SIZE 20 + /* callbacks to inform high-level handlers about JTAG state changes */ jtag_event_callback_t *jtag_event_callbacks; @@ -597,8 +601,7 @@ int jtag_add_dr_scan(int num_fields, scan_field_t *fields, enum tap_state state) /* if a device is listed, the BYPASS register must not be selected */ if (jtag_get_device(i)->bypass) { - ERROR("BUG: scan data for a device in BYPASS"); - exit(-1); + WARNING("scan data for a device in BYPASS"); } } } @@ -1116,6 +1119,93 @@ void jtag_sleep(u32 us) usleep(us); } +/* Try to examine chain layout according to IEEE 1149.1 ยง12 + */ +int jtag_examine_chain() +{ + scan_field_t field; + u8 idcode_buffer[JTAG_MAX_CHAIN_SIZE * 4]; + int i; + int bit_count; + int device_count = 0; + u8 valid = 0x0; + + field.device = 0; + field.num_bits = sizeof(idcode_buffer) * 8; + field.out_value = idcode_buffer; + field.out_mask = NULL; + field.in_value = idcode_buffer; + field.in_check_value = NULL; + field.in_check_mask = NULL; + field.in_handler = NULL; + field.in_handler_priv = NULL; + + for (i = 0; i < JTAG_MAX_CHAIN_SIZE; i++) + { + buf_set_u32(idcode_buffer, 0, 32, 0x000000FF); + } + + jtag_add_plain_dr_scan(1, &field, TAP_TLR); + jtag_execute_queue(); + + for (i = 0; i < JTAG_MAX_CHAIN_SIZE * 4; i++) + { + valid |= idcode_buffer[i]; + } + + /* if there wasn't a single non-zero bit, the scan isn't valid */ + if (!valid) + { + ERROR("JTAG communication failure, check connection, JTAG interface, target power etc."); + exit(-1); + } + + for (bit_count = 0; bit_count < (JTAG_MAX_CHAIN_SIZE * 32) - 31;) + { + u32 idcode = buf_get_u32(idcode_buffer, bit_count, 32); + if ((idcode & 1) == 0) + { + /* LSB must not be 0, this indicates a device in bypass */ + device_count++; + + bit_count += 1; + } + else + { + u32 manufacturer; + u32 part; + u32 version; + + if (idcode == 0x000000FF) + { + /* End of chain (invalid manufacturer ID) */ + break; + } + + device_count++; + + manufacturer = (idcode & 0xffe) >> 1; + part = (idcode & 0xffff000) >> 12; + version = (idcode & 0xf0000000) >> 28; + + DEBUG("JTAG device found: 0x%8.8x (Manufacturer: 0x%3.3x, Part: 0x%4.4x, Version: 0x%1.1x", + idcode, manufacturer, part, version); + + bit_count += 32; + } + } + + /* see if number of discovered devices matches configuration */ + if (device_count != jtag_num_devices) + { + ERROR("number of discovered devices in JTAG chain (%i) doesn't match configuration (%i)", + device_count, jtag_num_devices); + exit(-1); + } + + return ERROR_OK; +} + int jtag_validate_chain() { jtag_device_t *device = jtag_devices; @@ -1244,6 +1334,8 @@ int jtag_init(struct command_context_s *cmd_ctx) jtag_add_statemove(TAP_TLR); jtag_execute_queue(); + jtag_examine_chain(); + jtag_validate_chain(); return ERROR_OK; diff --git a/src/jtag/jtag.h b/src/jtag/jtag.h index 7ad382780..19f81ce63 100644 --- a/src/jtag/jtag.h +++ b/src/jtag/jtag.h @@ -25,7 +25,7 @@ #include "command.h" -#if 0 +#if 1 #define _DEBUG_JTAG_IO_ #endif diff --git a/src/target/arm7_9_common.c b/src/target/arm7_9_common.c index cd7e7fe18..8e74dedab 100644 --- a/src/target/arm7_9_common.c +++ b/src/target/arm7_9_common.c @@ -2388,7 +2388,11 @@ int arm7_9_init_arch_info(target_t *target, arm7_9_common_t *arm7_9) arm7_9->wp1_used = 0; arm7_9->force_hw_bkpts = 0; arm7_9->use_dbgrq = 0; + arm7_9->has_etm = 0; + arm7_9->has_single_step = 0; + arm7_9->has_monitor_mode = 0; + arm7_9->has_vector_catch = 0; arm7_9->reinit_embeddedice = 0; diff --git a/src/target/arm7_9_common.h b/src/target/arm7_9_common.h index fc90c0591..25141a14c 100644 --- a/src/target/arm7_9_common.h +++ b/src/target/arm7_9_common.h @@ -45,7 +45,11 @@ typedef struct arm7_9_common_s int force_hw_bkpts; int dbgreq_adjust_pc; int use_dbgrq; + int has_etm; + int has_single_step; + int has_monitor_mode; + int has_vector_catch; int reinit_embeddedice; diff --git a/src/target/arm7tdmi.c b/src/target/arm7tdmi.c index a1fde037e..5d925e219 100644 --- a/src/target/arm7tdmi.c +++ b/src/target/arm7tdmi.c @@ -742,7 +742,7 @@ void arm7tdmi_build_reg_cache(target_t *target) (*cache_p) = armv4_5_build_reg_cache(target, armv4_5); armv4_5->core_cache = (*cache_p); - (*cache_p)->next = embeddedice_build_reg_cache(target, jtag_info, 0); + (*cache_p)->next = embeddedice_build_reg_cache(target, arm7_9); arm7_9->eice_cache = (*cache_p)->next; if (arm7_9->has_etm) @@ -750,14 +750,6 @@ void arm7tdmi_build_reg_cache(target_t *target) (*cache_p)->next->next = etm_build_reg_cache(target, jtag_info, 0); arm7_9->etm_cache = (*cache_p)->next->next; } - - if (arch_info->has_monitor_mode) - (*cache_p)->next->reg_list[EICE_DBG_CTRL].size = 6; - else - (*cache_p)->next->reg_list[EICE_DBG_CTRL].size = 3; - - (*cache_p)->next->reg_list[EICE_DBG_STAT].size = 5; - } int arm7tdmi_init_target(struct command_context_s *cmd_ctx, struct target_s *target) @@ -828,30 +820,20 @@ int arm7tdmi_init_arch_info(target_t *target, arm7tdmi_common_t *arm7tdmi, int c arm7_9->sw_bkpts_enabled = 0; arm7_9->dbgreq_adjust_pc = 2; arm7_9->arch_info = arm7tdmi; - - arm7tdmi->has_monitor_mode = 0; + arm7tdmi->arch_info = NULL; arm7tdmi->common_magic = ARM7TDMI_COMMON_MAGIC; if (variant) { - if (strcmp(variant, "arm7tdmi-s_r4") == 0) - arm7tdmi->has_monitor_mode = 1; - else if (strcmp(variant, "arm7tdmi_r4") == 0) - arm7tdmi->has_monitor_mode = 1; - else if (strcmp(variant, "lpc2000") == 0) - { - arm7tdmi->has_monitor_mode = 1; - has_etm = 1; - } arm7tdmi->variant = strdup(variant); } else + { arm7tdmi->variant = strdup(""); + } arm7_9_init_arch_info(target, arm7_9); - - arm7_9->has_etm = has_etm; return ERROR_OK; } diff --git a/src/target/arm7tdmi.h b/src/target/arm7tdmi.h index ca2df8b69..104d1e032 100644 --- a/src/target/arm7tdmi.h +++ b/src/target/arm7tdmi.h @@ -33,7 +33,6 @@ typedef struct arm7tdmi_common_s { int common_magic; char *variant; - int has_monitor_mode; void *arch_info; arm7_9_common_t arm7_9_common; } arm7tdmi_common_t; diff --git a/src/target/arm920t.c b/src/target/arm920t.c index 97a08811e..1dae23192 100644 --- a/src/target/arm920t.c +++ b/src/target/arm920t.c @@ -701,7 +701,7 @@ int arm920t_init_arch_info(target_t *target, arm920t_common_t *arm920t, int chai arm920t->preserve_cache = 0; /* override hw single-step capability from ARM9TDMI */ - arm9tdmi->has_single_step = 1; + arm7_9->has_single_step = 1; return ERROR_OK; } diff --git a/src/target/arm966e.c b/src/target/arm966e.c index f5f4a209f..4573844a7 100644 --- a/src/target/arm966e.c +++ b/src/target/arm966e.c @@ -91,9 +91,6 @@ int arm966e_assert_reset(target_t *target) arm966e_common_t *arm966e = arm9tdmi->arch_info; reg_t *dbg_ctrl = &arm7_9->eice_cache->reg_list[EICE_DBG_CTRL]; int retval; - int trst_asserted_with_srt = 0; - - arm966e->monitor_mode_set = 1; DEBUG("target->state: %s", target_state_strings[target->state]); @@ -121,7 +118,6 @@ int arm966e_assert_reset(target_t *target) { WARNING("srst resets test logic, too"); retval = jtag_add_reset(1, 1); - trst_asserted_with_srt = 1; } } } @@ -133,7 +129,6 @@ int arm966e_assert_reset(target_t *target) { WARNING("srst resets test logic, too"); retval = jtag_add_reset(1, 1); - trst_asserted_with_srt = 1; } if (retval == ERROR_JTAG_RESET_CANT_SRST) @@ -153,23 +148,6 @@ int arm966e_assert_reset(target_t *target) jtag_add_sleep(50000); armv4_5_invalidate_core_regs(target); - - if( trst_asserted_with_srt == 0 ) - { - DEBUG("monitor mode needs clearing"); - - /* arm9e monitor mode enabled at reset */ - embeddedice_read_reg(dbg_ctrl); - jtag_execute_queue(); - - if(buf_get_u32(dbg_ctrl->value, EICE_DBG_CONTROL_MONEN, 1)) - { - buf_set_u32(dbg_ctrl->value, EICE_DBG_CONTROL_MONEN, 1, 0); - embeddedice_store_reg(dbg_ctrl); - DEBUG("monitor mode disabled"); - } - arm966e->monitor_mode_set = 0; - } return ERROR_OK; } @@ -184,23 +162,6 @@ int arm966e_deassert_reset(target_t *target) arm7_9_deassert_reset( target ); - if( arm966e->monitor_mode_set == 1 ) - { - DEBUG("monitor mode needs clearing"); - - /* arm9e monitor mode enabled at reset */ - embeddedice_read_reg(dbg_ctrl); - jtag_execute_queue(); - - if(buf_get_u32(dbg_ctrl->value, EICE_DBG_CONTROL_MONEN, 1)) - { - buf_set_u32(dbg_ctrl->value, EICE_DBG_CONTROL_MONEN, 1, 0); - embeddedice_store_reg(dbg_ctrl); - arm966e->monitor_mode_set = 0; - DEBUG("monitor mode disabled"); - } - } - return ERROR_OK; } @@ -226,9 +187,6 @@ int arm966e_init_arch_info(target_t *target, arm966e_common_t *arm966e, int chai arm9tdmi->arch_info = arm966e; arm966e->common_magic = ARM966E_COMMON_MAGIC; - arm9tdmi->has_single_step = 0; - arm9tdmi->has_monitor_mode = 1; - return ERROR_OK; } diff --git a/src/target/arm966e.h b/src/target/arm966e.h index dee067652..d4624f6c6 100644 --- a/src/target/arm966e.h +++ b/src/target/arm966e.h @@ -33,7 +33,6 @@ typedef struct arm966e_common_s int common_magic; arm9tdmi_common_t arm9tdmi_common; u32 cp15_control_reg; - int monitor_mode_set; } arm966e_common_t; #endif /* ARM966E_H */ diff --git a/src/target/arm9tdmi.c b/src/target/arm9tdmi.c index ccd30312d..ef978956d 100644 --- a/src/target/arm9tdmi.c +++ b/src/target/arm9tdmi.c @@ -788,7 +788,7 @@ void arm9tdmi_enable_single_step(target_t *target) arm7_9_common_t *arm7_9 = armv4_5->arch_info; arm9tdmi_common_t *arm9 = arm7_9->arch_info; - if (arm9->has_single_step) + if (arm7_9->has_single_step) { buf_set_u32(arm7_9->eice_cache->reg_list[EICE_DBG_CTRL].value, 3, 1, 1); embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_DBG_CTRL]); @@ -806,7 +806,7 @@ void arm9tdmi_disable_single_step(target_t *target) arm7_9_common_t *arm7_9 = armv4_5->arch_info; arm9tdmi_common_t *arm9 = arm7_9->arch_info; - if (arm9->has_single_step) + if (arm7_9->has_single_step) { buf_set_u32(arm7_9->eice_cache->reg_list[EICE_DBG_CTRL].value, 3, 1, 0); embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_DBG_CTRL]); @@ -832,16 +832,10 @@ void arm9tdmi_build_reg_cache(target_t *target) armv4_5->core_cache = (*cache_p); /* one extra register (vector catch) */ - (*cache_p)->next = embeddedice_build_reg_cache(target, jtag_info, 1); + (*cache_p)->next = embeddedice_build_reg_cache(target, arm7_9); arm7_9->eice_cache = (*cache_p)->next; - - if (arm9tdmi->has_monitor_mode) - (*cache_p)->next->reg_list[EICE_DBG_CTRL].size = 6; - else - (*cache_p)->next->reg_list[EICE_DBG_CTRL].size = 4; - - (*cache_p)->next->reg_list[EICE_DBG_STAT].size = 5; +#if 0 (*cache_p)->next->reg_list[EICE_VEC_CATCH].name = "vector catch"; (*cache_p)->next->reg_list[EICE_VEC_CATCH].dirty = 0; (*cache_p)->next->reg_list[EICE_VEC_CATCH].valid = 0; @@ -851,7 +845,7 @@ void arm9tdmi_build_reg_cache(target_t *target) (*cache_p)->next->reg_list[EICE_VEC_CATCH].value = calloc(1, 4); vec_catch_arch_info = (*cache_p)->next->reg_list[EICE_VEC_CATCH].arch_info; vec_catch_arch_info->addr = 0x2; - +#endif } int arm9tdmi_init_target(struct command_context_s *cmd_ctx, struct target_s *target) @@ -923,27 +917,24 @@ int arm9tdmi_init_arch_info(target_t *target, arm9tdmi_common_t *arm9tdmi, int c arm7_9->arch_info = arm9tdmi; arm9tdmi->common_magic = ARM9TDMI_COMMON_MAGIC; - arm9tdmi->has_monitor_mode = 0; - arm9tdmi->has_single_step = 0; arm9tdmi->arch_info = NULL; if (variant) { - if (strcmp(variant, "arm920t") == 0) - arm9tdmi->has_single_step = 1; - else if (strcmp(variant, "arm922t") == 0) - arm9tdmi->has_single_step = 1; - else if (strcmp(variant, "arm940t") == 0) - arm9tdmi->has_single_step = 1; arm9tdmi->variant = strdup(variant); } else + { arm9tdmi->variant = strdup(""); + } arm7_9_init_arch_info(target, arm7_9); /* override use of DBGRQ, this is safe on ARM9TDMI */ arm7_9->use_dbgrq = 1; + + /* all ARM9s have the vector catch register */ + arm7_9->has_vector_catch = 1; return ERROR_OK; } diff --git a/src/target/arm9tdmi.h b/src/target/arm9tdmi.h index 7bbaac7c9..f888c3559 100644 --- a/src/target/arm9tdmi.h +++ b/src/target/arm9tdmi.h @@ -33,8 +33,6 @@ typedef struct arm9tdmi_common_s { int common_magic; char *variant; - int has_monitor_mode; - int has_single_step; void *arch_info; arm7_9_common_t arm7_9_common; } arm9tdmi_common_t; diff --git a/src/target/embeddedice.c b/src/target/embeddedice.c index b063bd2c3..6cf698161 100644 --- a/src/target/embeddedice.c +++ b/src/target/embeddedice.c @@ -48,7 +48,8 @@ int embeddedice_reg_arch_info[] = { 0x0, 0x1, 0x4, 0x5, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15 + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, + 0x2 }; char* embeddedice_reg_list[] = @@ -71,7 +72,9 @@ char* embeddedice_reg_list[] = "watch 1 data value", "watch 1 data mask", "watch 1 control value", - "watch 1 control mask" + "watch 1 control mask", + + "vector catch" }; int embeddedice_reg_arch_type = -1; @@ -83,18 +86,25 @@ int embeddedice_set_reg_w_exec(reg_t *reg, u8 *buf); int embeddedice_write_reg(reg_t *reg, u32 value); int embeddedice_read_reg(reg_t *reg); -reg_cache_t* embeddedice_build_reg_cache(target_t *target, arm_jtag_t *jtag_info, int extra_reg) +reg_cache_t* embeddedice_build_reg_cache(target_t *target, arm7_9_common_t *arm7_9) { reg_cache_t *reg_cache = malloc(sizeof(reg_cache_t)); reg_t *reg_list = NULL; embeddedice_reg_t *arch_info = NULL; - int num_regs = 16 + extra_reg; + arm_jtag_t *jtag_info = &arm7_9->jtag_info; + int num_regs; int i; + int eice_version = 0; /* register a register arch-type for EmbeddedICE registers only once */ if (embeddedice_reg_arch_type == -1) embeddedice_reg_arch_type = register_reg_arch_type(embeddedice_get_reg, embeddedice_set_reg_w_exec); + if (arm7_9->has_vector_catch) + num_regs = 17; + else + num_regs = 16; + /* the actual registers are kept in two arrays */ reg_list = calloc(num_regs, sizeof(reg_t)); arch_info = calloc(num_regs, sizeof(embeddedice_reg_t)); @@ -106,7 +116,7 @@ reg_cache_t* embeddedice_build_reg_cache(target_t *target, arm_jtag_t *jtag_info reg_cache->num_regs = num_regs; /* set up registers */ - for (i = 0; i < num_regs - extra_reg; i++) + for (i = 0; i < num_regs; i++) { reg_list[i].name = embeddedice_reg_list[i]; reg_list[i].size = 32; @@ -121,12 +131,49 @@ reg_cache_t* embeddedice_build_reg_cache(target_t *target, arm_jtag_t *jtag_info arch_info[i].jtag_info = jtag_info; } - /* there may be one extra reg (Abort status (ARM7 rev4) or Vector catch (ARM9)) */ - if (extra_reg) + /* identify EmbeddedICE version by reading DCC control register */ + embeddedice_read_reg(®_list[EICE_COMMS_CTRL]); + jtag_execute_queue(); + + eice_version = buf_get_u32(reg_list[EICE_COMMS_CTRL].value, 28, 4); + + switch (eice_version) { - reg_list[num_regs - 1].arch_info = &arch_info[num_regs - 1]; - reg_list[num_regs - 1].arch_type = embeddedice_reg_arch_type; - arch_info[num_regs - 1].jtag_info = jtag_info; + case 1: + reg_list[EICE_DBG_CTRL].size = 3; + reg_list[EICE_DBG_STAT].size = 5; + break; + case 2: + reg_list[EICE_DBG_CTRL].size = 4; + reg_list[EICE_DBG_STAT].size = 5; + arm7_9->has_single_step = 1; + break; + case 3: + ERROR("EmbeddedICE version 3 detected, EmbeddedICE handling might be broken"); + reg_list[EICE_DBG_CTRL].size = 6; + reg_list[EICE_DBG_STAT].size = 5; + arm7_9->has_single_step = 1; + arm7_9->has_monitor_mode = 1; + break; + case 4: + reg_list[EICE_DBG_CTRL].size = 6; + reg_list[EICE_DBG_STAT].size = 5; + arm7_9->has_monitor_mode = 1; + break; + case 5: + reg_list[EICE_DBG_CTRL].size = 6; + reg_list[EICE_DBG_STAT].size = 5; + arm7_9->has_single_step = 1; + arm7_9->has_monitor_mode = 1; + break; + case 6: + reg_list[EICE_DBG_CTRL].size = 6; + reg_list[EICE_DBG_STAT].size = 10; + arm7_9->has_single_step = 1; + arm7_9->has_monitor_mode = 1; + break; + default: + ERROR("unknown EmbeddedICE version (comms ctrl: 0x%4.4x)", buf_get_u32(reg_list[EICE_COMMS_CTRL].value, 0, 32)); } return reg_cache; diff --git a/src/target/embeddedice.h b/src/target/embeddedice.h index eedc21912..a50ea221f 100644 --- a/src/target/embeddedice.h +++ b/src/target/embeddedice.h @@ -23,6 +23,7 @@ #include "target.h" #include "register.h" #include "arm_jtag.h" +#include "arm7_9_common.h" enum { @@ -42,7 +43,6 @@ enum EICE_W1_DATA_MASK = 13, EICE_W1_CONTROL_VALUE = 14, EICE_W1_CONTROL_MASK = 15, - EICE_ABT_STATUS = 16, EICE_VEC_CATCH = 16 }; @@ -57,6 +57,7 @@ enum enum { + EICE_DBG_STATUS_IJBIT = 5, EICE_DBG_STATUS_ITBIT = 4, EICE_DBG_STATUS_SYSCOMP = 3, EICE_DBG_STATUS_IFEN = 2, @@ -89,7 +90,7 @@ typedef struct embeddedice_reg_s arm_jtag_t *jtag_info; } embeddedice_reg_t; -extern reg_cache_t* embeddedice_build_reg_cache(target_t *target, arm_jtag_t *jtag_info, int extra_reg); +extern reg_cache_t* embeddedice_build_reg_cache(target_t *target, arm7_9_common_t *arm7_9); extern int embeddedice_read_reg(reg_t *reg); extern int embeddedice_write_reg(reg_t *reg, u32 value); extern int embeddedice_read_reg_w_check(reg_t *reg, u8* check_value, u8* check_mask); diff --git a/src/target/target.c b/src/target/target.c index 732288880..8c6d97dfc 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -209,6 +209,8 @@ int target_init_handler(struct target_s *target, enum target_event event, void * if ((event == TARGET_EVENT_HALTED) && (target->reset_script)) { + target_unregister_event_callback(target_init_handler, priv); + script = fopen(target->reset_script, "r"); if (!script) { @@ -221,8 +223,6 @@ int target_init_handler(struct target_s *target, enum target_event event, void * fclose(script); jtag_execute_queue(); - - target_unregister_event_callback(target_init_handler, priv); } return ERROR_OK;