Commit 4fc97d3f authored by drath's avatar drath
Browse files

- 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
parent adaed4c1
......@@ -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;