- 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-e2dbd0fdcd60tags/v0.1.0
@@ -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) | |||
{ | |||
@@ -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 | |||
{ | |||
@@ -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_start<word_end)) | |||
word_start++; | |||
while (isspace(*(word_end-1))&&(word_start<word_end)) | |||
word_end--; | |||
len = word_end - word_start; | |||
if (len>0) | |||
{ | |||
/* 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; | |||
@@ -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; | |||
@@ -25,7 +25,7 @@ | |||
#include "command.h" | |||
#if 0 | |||
#if 1 | |||
#define _DEBUG_JTAG_IO_ | |||
#endif | |||
@@ -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; | |||
@@ -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; | |||
@@ -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; | |||
} | |||
@@ -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; | |||
@@ -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; | |||
} | |||
@@ -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; | |||
} | |||
@@ -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 */ |
@@ -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; | |||
} | |||
@@ -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; | |||
@@ -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; | |||
@@ -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); | |||
@@ -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; | |||