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--)
DEBUG("status: 0x%x", status);
usleep(1000);
}
-
+
+ /* mask out bit 0 (reserved) */
+ status = status & 0xfe;
+
DEBUG("status: 0x%x", status);
if ((status & 0x80) != 0x80)
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
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,
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)
{
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)
{
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
{
/* 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 */
/* skip over trailing quote or whitespace*/
if (inquote || isspace(*p))
p++;
+ while (isspace(*p))
+ p++;
inquote = 0;
word_start = 0;
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;
/* 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");
}
}
}
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;
jtag_add_statemove(TAP_TLR);
jtag_execute_queue();
+ jtag_examine_chain();
+
jtag_validate_chain();
return ERROR_OK;
#include "command.h"
-#if 0
+#if 1
#define _DEBUG_JTAG_IO_
#endif
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;
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;
(*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)
(*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)
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;
}
{
int common_magic;
char *variant;
- int has_monitor_mode;
void *arch_info;
arm7_9_common_t arm7_9_common;
} arm7tdmi_common_t;
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;
}
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]);
{
WARNING("srst resets test logic, too");
retval = jtag_add_reset(1, 1);
- trst_asserted_with_srt = 1;
}
}
}
{
WARNING("srst resets test logic, too");
retval = jtag_add_reset(1, 1);
- trst_asserted_with_srt = 1;
}
if (retval == ERROR_JTAG_RESET_CANT_SRST)
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;
}
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;
}
arm9tdmi->arch_info = arm966e;
arm966e->common_magic = ARM966E_COMMON_MAGIC;
- arm9tdmi->has_single_step = 0;
- arm9tdmi->has_monitor_mode = 1;
-
return ERROR_OK;
}
int common_magic;
arm9tdmi_common_t arm9tdmi_common;
u32 cp15_control_reg;
- int monitor_mode_set;
} arm966e_common_t;
#endif /* ARM966E_H */
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]);
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]);
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;
(*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)
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;
}
{
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;
{
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[] =
"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;
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));
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;
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;
#include "target.h"
#include "register.h"
#include "arm_jtag.h"
+#include "arm7_9_common.h"
enum
{
EICE_W1_DATA_MASK = 13,
EICE_W1_CONTROL_VALUE = 14,
EICE_W1_CONTROL_MASK = 15,
- EICE_ABT_STATUS = 16,
EICE_VEC_CATCH = 16
};
enum
{
+ EICE_DBG_STATUS_IJBIT = 5,
EICE_DBG_STATUS_ITBIT = 4,
EICE_DBG_STATUS_SYSCOMP = 3,
EICE_DBG_STATUS_IFEN = 2,
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);
if ((event == TARGET_EVENT_HALTED) && (target->reset_script))
{
+ target_unregister_event_callback(target_init_handler, priv);
+
script = fopen(target->reset_script, "r");
if (!script)
{
fclose(script);
jtag_execute_queue();
-
- target_unregister_event_callback(target_init_handler, priv);
}
return ERROR_OK;