aboutsummaryrefslogtreecommitdiff
path: root/src/target
diff options
context:
space:
mode:
authorntfreak <ntfreak@b42882b7-edfa-0310-969c-e2dbd0fdcd60>2008-02-19 19:26:17 +0000
committerntfreak <ntfreak@b42882b7-edfa-0310-969c-e2dbd0fdcd60>2008-02-19 19:26:17 +0000
commit5c0e8efa051f4e266add8b3685020970fe394a4c (patch)
tree261d72e1ce7002f3b331b93ee6d8fa8e01de545c /src/target
parentb02d64a1bff5bbbb56c3119e336e1530888c04bd (diff)
downloadriscv-openocd-5c0e8efa051f4e266add8b3685020970fe394a4c.zip
riscv-openocd-5c0e8efa051f4e266add8b3685020970fe394a4c.tar.gz
riscv-openocd-5c0e8efa051f4e266add8b3685020970fe394a4c.tar.bz2
- Fixed bug in pathmove for XScale
- added virtual address to working_area. - Improved error messages in a number of places - Added ERROR_COMMAND_SYNTAX_ERROR that commands can return to have syntax printed - Added help for some config commands - Added verification of sw breakpoints with ERROR() message - Removed a couple of exit()'s and replaced with error message - cosmetic fix to armv4_5.c, easier to read - added polymorphic(with default) virt2phys and mmu enable query function to target.h - added virt2phys command that uses target->type->virt2phys() fn Thanks to Øyvind Harboe git-svn-id: svn://svn.berlios.de/openocd/trunk@310 b42882b7-edfa-0310-969c-e2dbd0fdcd60
Diffstat (limited to 'src/target')
-rw-r--r--src/target/arm7_9_common.c22
-rw-r--r--src/target/armv4_5.c16
-rw-r--r--src/target/armv4_5_mmu.c4
-rw-r--r--src/target/target.c89
-rw-r--r--src/target/target.h9
-rw-r--r--src/target/xscale.c70
6 files changed, 164 insertions, 46 deletions
diff --git a/src/target/arm7_9_common.c b/src/target/arm7_9_common.c
index 825f7fa..45411c1 100644
--- a/src/target/arm7_9_common.c
+++ b/src/target/arm7_9_common.c
@@ -186,17 +186,33 @@ int arm7_9_set_breakpoint(struct target_s *target, breakpoint_t *breakpoint)
{
if (breakpoint->length == 4)
{
+ u32 verify = 0xffffffff;
/* keep the original instruction in target endianness */
target->type->read_memory(target, breakpoint->address, 4, 1, breakpoint->orig_instr);
/* write the breakpoint instruction in target endianness (arm7_9->arm_bkpt is host endian) */
target_write_u32(target, breakpoint->address, arm7_9->arm_bkpt);
+
+ target->type->read_memory(target, breakpoint->address, 4, 1, (u8 *)&verify);
+ if (verify != arm7_9->arm_bkpt)
+ {
+ ERROR("Unable to set 32 bit software breakpoint at address %08x", breakpoint->address);
+ return ERROR_OK;
+ }
}
else
{
+ u16 verify = 0xffff;
/* keep the original instruction in target endianness */
target->type->read_memory(target, breakpoint->address, 2, 1, breakpoint->orig_instr);
/* write the breakpoint instruction in target endianness (arm7_9->thumb_bkpt is host endian) */
target_write_u16(target, breakpoint->address, arm7_9->thumb_bkpt);
+
+ target->type->read_memory(target, breakpoint->address, 2, 1, (u8 *)&verify);
+ if (verify != arm7_9->thumb_bkpt)
+ {
+ ERROR("Unable to set thumb software breakpoint at address %08x", breakpoint->address);
+ return ERROR_OK;
+ }
}
breakpoint->set = 1;
}
@@ -1914,7 +1930,7 @@ int arm7_9_read_memory(struct target_s *target, u32 address, u32 size, u32 count
if ((retval = jtag_execute_queue()) != ERROR_OK)
{
ERROR("JTAG error while reading cpsr");
- exit(-1);
+ return ERROR_TARGET_DATA_ABORT;
}
if (((cpsr & 0x1f) == ARMV4_5_MODE_ABT) && (armv4_5->core_mode != ARMV4_5_MODE_ABT))
@@ -1943,7 +1959,9 @@ int arm7_9_write_memory(struct target_s *target, u32 address, u32 size, u32 coun
int retval;
int last_reg = 0;
+#ifdef _DEBUG_ARM7_9_
DEBUG("address: 0x%8.8x, size: 0x%8.8x, count: 0x%8.8x", address, size, count);
+#endif
if (target->state != TARGET_HALTED)
{
@@ -2079,7 +2097,7 @@ int arm7_9_write_memory(struct target_s *target, u32 address, u32 size, u32 coun
if ((retval = jtag_execute_queue()) != ERROR_OK)
{
ERROR("JTAG error while reading cpsr");
- exit(-1);
+ return ERROR_TARGET_DATA_ABORT;
}
if (((cpsr & 0x1f) == ARMV4_5_MODE_ABT) && (armv4_5->core_mode != ARMV4_5_MODE_ABT))
diff --git a/src/target/armv4_5.c b/src/target/armv4_5.c
index 2d73a53..02a731c 100644
--- a/src/target/armv4_5.c
+++ b/src/target/armv4_5.c
@@ -174,14 +174,14 @@ int armv4_5_mode_to_number(enum armv4_5_mode mode)
{
switch (mode)
{
- case 16: return 0; break;
- case 17: return 1; break;
- case 18: return 2; break;
- case 19: return 3; break;
- case 23: return 4; break;
- case 27: return 5; break;
- case 31: return 6; break;
- case -1: return 0; break; /* map MODE_ANY to user mode */
+ case ARMV4_5_MODE_USR: return 0; break;
+ case ARMV4_5_MODE_FIQ: return 1; break;
+ case ARMV4_5_MODE_IRQ: return 2; break;
+ case ARMV4_5_MODE_SVC: return 3; break;
+ case ARMV4_5_MODE_ABT: return 4; break;
+ case ARMV4_5_MODE_UND: return 5; break;
+ case ARMV4_5_MODE_SYS: return 6; break;
+ case ARMV4_5_MODE_ANY: return 0; break; /* map MODE_ANY to user mode */
default:
ERROR("invalid mode value encountered");
return -1;
diff --git a/src/target/armv4_5_mmu.c b/src/target/armv4_5_mmu.c
index b888933..9c6d12e 100644
--- a/src/target/armv4_5_mmu.c
+++ b/src/target/armv4_5_mmu.c
@@ -54,12 +54,14 @@ u32 armv4_5_mmu_translate_va(target_t *target, armv4_5_mmu_common_t *armv4_5_mmu
if ((first_lvl_descriptor & 0x3) == 0)
{
*type = -1;
+ ERROR("Address translation failure");
return ERROR_TARGET_TRANSLATION_FAULT;
}
if (!armv4_5_mmu->has_tiny_pages && ((first_lvl_descriptor & 0x3) == 3))
{
*type = -1;
+ ERROR("Address translation failure");
return ERROR_TARGET_TRANSLATION_FAULT;
}
@@ -97,6 +99,7 @@ u32 armv4_5_mmu_translate_va(target_t *target, armv4_5_mmu_common_t *armv4_5_mmu
if ((second_lvl_descriptor & 0x3) == 0)
{
*type = -1;
+ ERROR("Address translation failure");
return ERROR_TARGET_TRANSLATION_FAULT;
}
@@ -129,6 +132,7 @@ u32 armv4_5_mmu_translate_va(target_t *target, armv4_5_mmu_common_t *armv4_5_mmu
/* should not happen */
*type = -1;
+ ERROR("Address translation failure");
return ERROR_TARGET_TRANSLATION_FAULT;
}
diff --git a/src/target/target.c b/src/target/target.c
index a606376..4d6ffe3 100644
--- a/src/target/target.c
+++ b/src/target/target.c
@@ -74,6 +74,7 @@ int handle_bp_command(struct command_context_s *cmd_ctx, char *cmd, char **args,
int handle_rbp_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
int handle_wp_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
int handle_rwp_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int handle_virt2phys_command(command_context_t *cmd_ctx, char *cmd, char **args, int argc);
/* targets
*/
@@ -376,6 +377,19 @@ int target_process_reset(struct command_context_s *cmd_ctx)
return retval;
}
+static int default_virt2phys(struct target_s *target, u32 virtual, u32 *physical)
+{
+ *physical = virtual;
+ return ERROR_OK;
+}
+
+static int default_mmu(struct target_s *target, int *enabled)
+{
+ USER("No MMU present");
+ *enabled = 0;
+ return ERROR_OK;
+}
+
int target_init(struct command_context_s *cmd_ctx)
{
target_t *target = targets;
@@ -387,6 +401,16 @@ int target_init(struct command_context_s *cmd_ctx)
ERROR("target '%s' init failed", target->type->name);
exit(-1);
}
+
+ /* Set up default functions if none are provided by target */
+ if (target->type->virt2phys == NULL)
+ {
+ target->type->virt2phys = default_virt2phys;
+ }
+ if (target->type->mmu == NULL)
+ {
+ target->type->mmu = default_mmu;
+ }
target = target->next;
}
@@ -583,6 +607,26 @@ int target_alloc_working_area(struct target_s *target, u32 size, working_area_t
working_area_t *c = target->working_areas;
working_area_t *new_wa = NULL;
+ /* Reevaluate working area address based on MMU state*/
+ if (target->working_areas == NULL)
+ {
+ int retval;
+ int enabled;
+ retval = target->type->mmu(target, &enabled);
+ if (retval != ERROR_OK)
+ {
+ return retval;
+ }
+ if (enabled)
+ {
+ target->working_area = target->working_area_virt;
+ }
+ else
+ {
+ target->working_area = target->working_area_phys;
+ }
+ }
+
/* only allocate multiples of 4 byte */
if (size % 4)
{
@@ -621,7 +665,7 @@ int target_alloc_working_area(struct target_s *target, u32 size, working_area_t
if (free_size < size)
{
- WARNING("not enough working area available");
+ WARNING("not enough working area available(requested %d, free %d)", size, free_size);
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
}
@@ -700,7 +744,8 @@ int target_register_commands(struct command_context_s *cmd_ctx)
register_command(cmd_ctx, NULL, "daemon_startup", handle_daemon_startup_command, COMMAND_CONFIG, NULL);
register_command(cmd_ctx, NULL, "target_script", handle_target_script_command, COMMAND_CONFIG, NULL);
register_command(cmd_ctx, NULL, "run_and_halt_time", handle_run_and_halt_time_command, COMMAND_CONFIG, NULL);
- register_command(cmd_ctx, NULL, "working_area", handle_working_area_command, COMMAND_ANY, NULL);
+ register_command(cmd_ctx, NULL, "working_area", handle_working_area_command, COMMAND_ANY, "working_area <target#> <address> <size> <'backup'|'nobackup'> [virtual address]");
+ register_command(cmd_ctx, NULL, "virt2phys", handle_virt2phys_command, COMMAND_ANY, "virt2phys <virtual address>");
return ERROR_OK;
}
@@ -1221,10 +1266,9 @@ int handle_working_area_command(struct command_context_s *cmd_ctx, char *cmd, ch
{
target_t *target = NULL;
- if (argc < 4)
+ if ((argc < 4) || (argc > 5))
{
- ERROR("incomplete working_area command. usage: working_area <target#> <address> <size> <'backup'|'nobackup'>");
- exit(-1);
+ return ERROR_COMMAND_SYNTAX_ERROR;
}
target = get_target_by_num(strtoul(args[0], NULL, 0));
@@ -1236,7 +1280,11 @@ int handle_working_area_command(struct command_context_s *cmd_ctx, char *cmd, ch
}
target_free_all_working_areas(target);
- target->working_area = strtoul(args[1], NULL, 0);
+ target->working_area_phys = target->working_area_virt = strtoul(args[1], NULL, 0);
+ if (argc == 5)
+ {
+ target->working_area_virt = strtoul(args[4], NULL, 0);
+ }
target->working_area_size = strtoul(args[2], NULL, 0);
if (strcmp(args[3], "backup") == 0)
@@ -1250,7 +1298,7 @@ int handle_working_area_command(struct command_context_s *cmd_ctx, char *cmd, ch
else
{
ERROR("unrecognized <backup|nobackup> argument (%s)", args[3]);
- exit(-1);
+ return ERROR_COMMAND_SYNTAX_ERROR;
}
return ERROR_OK;
@@ -2247,3 +2295,30 @@ int handle_rwp_command(struct command_context_s *cmd_ctx, char *cmd, char **args
return ERROR_OK;
}
+
+int handle_virt2phys_command(command_context_t *cmd_ctx, char *cmd, char **args, int argc)
+{
+ int retval;
+ target_t *target = get_current_target(cmd_ctx);
+ u32 va;
+ u32 pa;
+
+ if (argc != 1)
+ {
+ return ERROR_COMMAND_SYNTAX_ERROR;
+ }
+ va = strtoul(args[0], NULL, 0);
+
+ retval = target->type->virt2phys(target, va, &pa);
+ if (retval == ERROR_OK)
+ {
+ command_print(cmd_ctx, "Physical address 0x%08x", pa);
+ }
+ else
+ {
+ /* lower levels will have logged a detailed error which is
+ * forwarded to telnet/GDB session.
+ */
+ }
+ return retval;
+}
diff --git a/src/target/target.h b/src/target/target.h
index 46ae505..29de1e9 100644
--- a/src/target/target.h
+++ b/src/target/target.h
@@ -147,6 +147,9 @@ typedef struct target_type_s
int (*init_target)(struct command_context_s *cmd_ctx, struct target_s *target);
int (*quit)(void);
+ int (*virt2phys)(struct target_s *target, u32 address, u32 *physical);
+ int (*mmu)(struct target_s *target, int *enabled);
+
} target_type_t;
typedef struct target_s
@@ -158,7 +161,11 @@ typedef struct target_s
char *post_halt_script; /* script file to execute after the target halted */
char *pre_resume_script; /* script file to execute before the target resumed */
char *gdb_program_script; /* script file to execute before programming vis gdb */
- u32 working_area; /* working area (initialized RAM) */
+ u32 working_area; /* working area (initialized RAM). Evaluated
+ upon first allocation from virtual/physical address.
+ */
+ u32 working_area_virt; /* virtual address */
+ u32 working_area_phys; /* physical address */
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 */
diff --git a/src/target/xscale.c b/src/target/xscale.c
index 03b922d..6a5aabb 100644
--- a/src/target/xscale.c
+++ b/src/target/xscale.c
@@ -84,6 +84,8 @@ int xscale_add_watchpoint(struct target_s *target, watchpoint_t *watchpoint);
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);
+static int xscale_virt2phys(struct target_s *target, u32 virtual, u32 *physical);
+static int xscale_mmu(struct target_s *target, int *enabled);
int xscale_read_trace(target_t *target);
@@ -122,7 +124,10 @@ target_type_t xscale_target =
.register_commands = xscale_register_commands,
.target_command = xscale_target_command,
.init_target = xscale_init_target,
- .quit = xscale_quit
+ .quit = xscale_quit,
+
+ .virt2phys = xscale_virt2phys,
+ .mmu = xscale_mmu
};
char* xscale_reg_list[] =
@@ -189,11 +194,13 @@ int xscale_get_arch_pointers(target_t *target, armv4_5_common_t **armv4_5_p, xsc
if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)
{
+ ERROR("target isn't an XScale target");
return -1;
}
if (xscale->common_magic != XSCALE_COMMON_MAGIC)
{
+ ERROR("target isn't an XScale target");
return -1;
}
@@ -436,7 +443,7 @@ int xscale_read_tx(target_t *target, int consume)
armv4_5_common_t *armv4_5 = target->arch_info;
xscale_common_t *xscale = armv4_5->arch_info;
enum tap_state path[3];
- enum tap_state noconsume_path[7];
+ enum tap_state noconsume_path[9];
int retval;
struct timeval timeout, now;
@@ -461,8 +468,10 @@ int xscale_read_tx(target_t *target, int consume)
noconsume_path[2] = TAP_E1D;
noconsume_path[3] = TAP_PD;
noconsume_path[4] = TAP_E2D;
- noconsume_path[5] = TAP_CD;
- noconsume_path[6] = TAP_SD;
+ noconsume_path[5] = TAP_UD;
+ noconsume_path[6] = TAP_SDS;
+ noconsume_path[7] = TAP_CD;
+ noconsume_path[8] = TAP_SD;
fields[0].device = xscale->jtag_info.chain_pos;
fields[0].num_bits = 3;
@@ -502,7 +511,7 @@ int xscale_read_tx(target_t *target, int consume)
if (consume)
jtag_add_pathmove(3, path);
else
- jtag_add_pathmove(7, noconsume_path);
+ jtag_add_pathmove(sizeof(noconsume_path)/sizeof(*noconsume_path), noconsume_path);
jtag_add_dr_scan(3, fields, TAP_RTI, NULL);
@@ -3142,7 +3151,6 @@ int xscale_handle_debug_handler_command(struct command_context_s *cmd_ctx, char
if (xscale_get_arch_pointers(target, &armv4_5, &xscale) != ERROR_OK)
{
- command_print(cmd_ctx, "target isn't an ARM920t target");
return ERROR_OK;
}
@@ -3183,7 +3191,6 @@ int xscale_handle_cache_clean_address_command(struct command_context_s *cmd_ctx,
if (xscale_get_arch_pointers(target, &armv4_5, &xscale) != ERROR_OK)
{
- command_print(cmd_ctx, "target isn't an XScale target");
return ERROR_OK;
}
@@ -3209,32 +3216,49 @@ int xscale_handle_cache_info_command(struct command_context_s *cmd_ctx, char *cm
if (xscale_get_arch_pointers(target, &armv4_5, &xscale) != ERROR_OK)
{
- command_print(cmd_ctx, "target isn't an XScale target");
return ERROR_OK;
}
return armv4_5_handle_cache_info_command(cmd_ctx, &xscale->armv4_5_mmu.armv4_5_cache);
}
-int xscale_handle_virt2phys_command(command_context_t *cmd_ctx, char *cmd, char **args, int argc)
+static int xscale_virt2phys(struct target_s *target, u32 virtual, u32 *physical)
{
- target_t *target = get_current_target(cmd_ctx);
armv4_5_common_t *armv4_5;
xscale_common_t *xscale;
-
- if (xscale_get_arch_pointers(target, &armv4_5, &xscale) != ERROR_OK)
+ int retval;
+ int type;
+ u32 cb;
+ int domain;
+ u32 ap;
+
+ if ((retval = xscale_get_arch_pointers(target, &armv4_5, &xscale)) != ERROR_OK)
{
- command_print(cmd_ctx, "target isn't an XScale target");
- return ERROR_OK;
+ return retval;
+ }
+ u32 ret = armv4_5_mmu_translate_va(target, &xscale->armv4_5_mmu, virtual, &type, &cb, &domain, &ap);
+ if (type == -1)
+ {
+ return ret;
}
+
+ *physical = ret;
+ return ERROR_OK;
+}
+
+static int xscale_mmu(struct target_s *target, int *enabled)
+{
+ armv4_5_common_t *armv4_5 = target->arch_info;
+ xscale_common_t *xscale = armv4_5->arch_info;
if (target->state != TARGET_HALTED)
{
- command_print(cmd_ctx, "target must be stopped for \"%s\" command", cmd);
- return ERROR_OK;
+ ERROR("Target not halted");
+ return ERROR_TARGET_INVALID;
}
-
- return armv4_5_mmu_handle_virt2phys_command(cmd_ctx, cmd, args, argc, target, &xscale->armv4_5_mmu);
+
+ *enabled = xscale->armv4_5_mmu.mmu_enabled;
+ return ERROR_OK;
}
int xscale_handle_mmu_command(command_context_t *cmd_ctx, char *cmd, char **args, int argc)
@@ -3245,7 +3269,6 @@ int xscale_handle_mmu_command(command_context_t *cmd_ctx, char *cmd, char **args
if (xscale_get_arch_pointers(target, &armv4_5, &xscale) != ERROR_OK)
{
- command_print(cmd_ctx, "target isn't an XScale target");
return ERROR_OK;
}
@@ -3283,7 +3306,6 @@ int xscale_handle_idcache_command(command_context_t *cmd_ctx, char *cmd, char **
if (xscale_get_arch_pointers(target, &armv4_5, &xscale) != ERROR_OK)
{
- command_print(cmd_ctx, "target isn't an XScale target");
return ERROR_OK;
}
@@ -3337,7 +3359,6 @@ int xscale_handle_vector_catch_command(command_context_t *cmd_ctx, char *cmd, ch
if (xscale_get_arch_pointers(target, &armv4_5, &xscale) != ERROR_OK)
{
- command_print(cmd_ctx, "target isn't an XScale target");
return ERROR_OK;
}
@@ -3365,7 +3386,6 @@ int xscale_handle_force_hw_bkpts_command(struct command_context_s *cmd_ctx, char
if (xscale_get_arch_pointers(target, &armv4_5, &xscale) != ERROR_OK)
{
- command_print(cmd_ctx, "target isn't an XScale target");
return ERROR_OK;
}
@@ -3396,7 +3416,6 @@ int xscale_handle_trace_buffer_command(struct command_context_s *cmd_ctx, char *
if (xscale_get_arch_pointers(target, &armv4_5, &xscale) != ERROR_OK)
{
- command_print(cmd_ctx, "target isn't an XScale target");
return ERROR_OK;
}
@@ -3483,7 +3502,6 @@ int xscale_handle_trace_image_command(struct command_context_s *cmd_ctx, char *c
if (xscale_get_arch_pointers(target, &armv4_5, &xscale) != ERROR_OK)
{
- command_print(cmd_ctx, "target isn't an XScale target");
return ERROR_OK;
}
@@ -3530,7 +3548,6 @@ int xscale_handle_dump_trace_command(struct command_context_s *cmd_ctx, char *cm
if (xscale_get_arch_pointers(target, &armv4_5, &xscale) != ERROR_OK)
{
- command_print(cmd_ctx, "target isn't an XScale target");
return ERROR_OK;
}
@@ -3588,7 +3605,6 @@ int xscale_handle_analyze_trace_buffer_command(struct command_context_s *cmd_ctx
if (xscale_get_arch_pointers(target, &armv4_5, &xscale) != ERROR_OK)
{
- command_print(cmd_ctx, "target isn't an XScale target");
return ERROR_OK;
}
@@ -3605,7 +3621,6 @@ int xscale_handle_cp15(command_context_t *cmd_ctx, char *cmd, char **args, int a
if (xscale_get_arch_pointers(target, &armv4_5, &xscale) != ERROR_OK)
{
- command_print(cmd_ctx, "target isn't an XScale target");
return ERROR_OK;
}
@@ -3697,7 +3712,6 @@ int xscale_register_commands(struct command_context_s *cmd_ctx)
register_command(cmd_ctx, xscale_cmd, "cache_clean_address", xscale_handle_cache_clean_address_command, COMMAND_ANY, NULL);
register_command(cmd_ctx, xscale_cmd, "cache_info", xscale_handle_cache_info_command, COMMAND_EXEC, NULL);
- register_command(cmd_ctx, xscale_cmd, "virt2phys", xscale_handle_virt2phys_command, COMMAND_EXEC, NULL);
register_command(cmd_ctx, xscale_cmd, "mmu", xscale_handle_mmu_command, COMMAND_EXEC, "['enable'|'disable'] the MMU");
register_command(cmd_ctx, xscale_cmd, "icache", xscale_handle_idcache_command, COMMAND_EXEC, "['enable'|'disable'] the ICache");
register_command(cmd_ctx, xscale_cmd, "dcache", xscale_handle_idcache_command, COMMAND_EXEC, "['enable'|'disable'] the DCache");