@@ -2,6 +2,9 @@ | |||
* Copyright (C) 2005 by Dominic Rath * | |||
* Dominic.Rath@gmx.de * | |||
* * | |||
* Copyright (C) 2009 by Øyvind Harboe * | |||
* oyvind.harboe@zylin.com * | |||
* * | |||
* This program is free software; you can redistribute it and/or modify * | |||
* it under the terms of the GNU General Public License as published by * | |||
* the Free Software Foundation; either version 2 of the License, or * | |||
@@ -46,6 +49,9 @@ int arm720t_read_phys_memory(struct target_s *target, uint32_t address, uint32_t | |||
int arm720t_write_phys_memory(struct target_s *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer); | |||
int arm720t_soft_reset_halt(struct target_s *target); | |||
static int arm720t_mrc(target_t *target, int cpnum, uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm, uint32_t *value); | |||
static int arm720t_mcr(target_t *target, int cpnum, uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm, uint32_t value); | |||
target_type_t arm720t_target = | |||
{ | |||
.name = "arm720t", | |||
@@ -82,7 +88,9 @@ target_type_t arm720t_target = | |||
.target_create = arm720t_target_create, | |||
.init_target = arm720t_init_target, | |||
.examine = arm7tdmi_examine, | |||
.quit = arm720t_quit | |||
.quit = arm720t_quit, | |||
.mrc = arm720t_mrc, | |||
.mcr = arm720t_mcr, | |||
}; | |||
@@ -574,3 +582,29 @@ int arm720t_handle_cp15_command(struct command_context_s *cmd_ctx, char *cmd, ch | |||
return ERROR_OK; | |||
} | |||
static int arm720t_mrc(target_t *target, int cpnum, uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm, uint32_t *value) | |||
{ | |||
if (cpnum!=15) | |||
{ | |||
LOG_ERROR("Only cp15 is supported"); | |||
return ERROR_FAIL; | |||
} | |||
return arm720t_read_cp15(target, mrc_opcode(cpnum, op1, op2, CRn, CRm), value); | |||
} | |||
static int arm720t_mcr(target_t *target, int cpnum, uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm, uint32_t value) | |||
{ | |||
if (cpnum!=15) | |||
{ | |||
LOG_ERROR("Only cp15 is supported"); | |||
return ERROR_FAIL; | |||
} | |||
return arm720t_write_cp15(target, mrc_opcode(cpnum, op1, op2, CRn, CRm), value); | |||
} | |||
@@ -2,7 +2,7 @@ | |||
* Copyright (C) 2007 by Dominic Rath * | |||
* Dominic.Rath@gmx.de * | |||
* * | |||
* Copyright (C) 2009 by Øyvind Harboe * | |||
* Copyright (C) 2007,2008,2009 by Øyvind Harboe * | |||
* oyvind.harboe@zylin.com * | |||
* * | |||
* This program is free software; you can redistribute it and/or modify * | |||
@@ -35,7 +35,6 @@ | |||
/* cli handling */ | |||
int arm926ejs_handle_cp15_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); | |||
int arm926ejs_handle_cp15i_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); | |||
int arm926ejs_handle_cache_info_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); | |||
int arm926ejs_handle_read_cache_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); | |||
@@ -52,6 +51,29 @@ int arm926ejs_write_phys_memory(struct target_s *target, uint32_t address, uint3 | |||
static int arm926ejs_virt2phys(struct target_s *target, uint32_t virtual, uint32_t *physical); | |||
static int arm926ejs_mmu(struct target_s *target, int *enabled); | |||
int arm926ejs_cp15_read(target_t *target, uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm, uint32_t *value); | |||
int arm926ejs_cp15_write(target_t *target, uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm, uint32_t value); | |||
static int arm926ejs_mrc(target_t *target, int cpnum, uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm, uint32_t *value) | |||
{ | |||
if (cpnum!=15) | |||
{ | |||
LOG_ERROR("Only cp15 is supported"); | |||
return ERROR_FAIL; | |||
} | |||
return arm926ejs_cp15_read(target, op1, op2, CRn, CRm, value); | |||
} | |||
static int arm926ejs_mcr(target_t *target, int cpnum, uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm, uint32_t value) | |||
{ | |||
if (cpnum!=15) | |||
{ | |||
LOG_ERROR("Only cp15 is supported"); | |||
return ERROR_FAIL; | |||
} | |||
return arm926ejs_cp15_write(target, op1, op2, CRn, CRm, value); | |||
} | |||
target_type_t arm926ejs_target = | |||
{ | |||
.name = "arm926ejs", | |||
@@ -94,6 +116,8 @@ target_type_t arm926ejs_target = | |||
.read_phys_memory = arm926ejs_read_phys_memory, | |||
.write_phys_memory = arm926ejs_write_phys_memory, | |||
.mrc = arm926ejs_mrc, | |||
.mcr = arm926ejs_mcr, | |||
}; | |||
int arm926ejs_catch_broken_irscan(uint8_t *captured, void *priv, scan_field_t *field) | |||
@@ -5,6 +5,9 @@ | |||
* Copyright (C) 2008 by Spencer Oliver * | |||
* spen@spen-soft.co.uk * | |||
* * | |||
* Copyright (C) 2009 by Øyvind Harboe * | |||
* oyvind.harboe@zylin.com * | |||
* * | |||
* This program is free software; you can redistribute it and/or modify * | |||
* it under the terms of the GNU General Public License as published by * | |||
* the Free Software Foundation; either version 2 of the License, or * | |||
@@ -315,4 +318,19 @@ extern int armv4_5_invalidate_core_regs(target_t *target); | |||
*/ | |||
#define ARMV5_T_BKPT(Im) ((0xbe00 | Im) | ((0xbe00 | Im) << 16)) | |||
/* build basic mrc/mcr opcode */ | |||
static inline uint32_t mrc_opcode(int cpnum, uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm) | |||
{ | |||
uint32_t t = 0; | |||
t|=op1<<21; | |||
t|=op2<<5; | |||
t|=CRn<<16; | |||
t|=CRm<<0; | |||
return t; | |||
} | |||
#endif /* ARMV4_5_H */ |
@@ -69,6 +69,7 @@ static int handle_fast_load_image_command(struct command_context_s *cmd_ctx, cha | |||
static int handle_fast_load_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); | |||
static int jim_array2mem(Jim_Interp *interp, int argc, Jim_Obj *const *argv); | |||
static int jim_mcrmrc(Jim_Interp *interp, int argc, Jim_Obj *const *argv); | |||
static int jim_mem2array(Jim_Interp *interp, int argc, Jim_Obj *const *argv); | |||
static int jim_target(Jim_Interp *interp, int argc, Jim_Obj *const *argv); | |||
@@ -687,6 +688,60 @@ void target_reset_examined(struct target_s *target) | |||
} | |||
static int default_mrc(struct target_s *target, int cpnum, uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm, uint32_t *value) | |||
{ | |||
LOG_ERROR("Not implemented"); | |||
return ERROR_FAIL; | |||
} | |||
static int default_mcr(struct target_s *target, int cpnum, uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm, uint32_t value) | |||
{ | |||
LOG_ERROR("Not implemented"); | |||
return ERROR_FAIL; | |||
} | |||
static int arm_cp_check(struct target_s *target, int cpnum, uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm) | |||
{ | |||
/* basic check */ | |||
if (!target_was_examined(target)) | |||
{ | |||
LOG_ERROR("Target not examined yet"); | |||
return ERROR_FAIL; | |||
} | |||
if ((cpnum <0) || (cpnum > 15)) | |||
{ | |||
LOG_ERROR("Illegal co-processor %d", cpnum); | |||
return ERROR_FAIL; | |||
} | |||
return ERROR_OK; | |||
} | |||
int target_mrc(struct target_s *target, int cpnum, uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm, uint32_t *value) | |||
{ | |||
int retval; | |||
retval = arm_cp_check(target, cpnum, op1, op2, CRn, CRm); | |||
if (retval != ERROR_OK) | |||
return retval; | |||
return target->type->mrc(target, cpnum, op1, op2, CRn, CRm, value); | |||
} | |||
int target_mcr(struct target_s *target, int cpnum, uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm, uint32_t value) | |||
{ | |||
int retval; | |||
retval = arm_cp_check(target, cpnum, op1, op2, CRn, CRm); | |||
if (retval != ERROR_OK) | |||
return retval; | |||
return target->type->mcr(target, cpnum, op1, op2, CRn, CRm, value); | |||
} | |||
int target_init(struct command_context_s *cmd_ctx) | |||
{ | |||
target_t *target = all_targets; | |||
@@ -722,6 +777,17 @@ int target_init(struct command_context_s *cmd_ctx) | |||
target->type->write_phys_memory = target->type->write_memory; | |||
} | |||
if (target->type->mcr == NULL) | |||
{ | |||
target->type->mcr = default_mcr; | |||
} | |||
if (target->type->mrc == NULL) | |||
{ | |||
target->type->mrc = default_mrc; | |||
} | |||
/* a non-invasive way(in terms of patches) to add some code that | |||
* runs before the type->write/read_memory implementation | |||
*/ | |||
@@ -1538,6 +1604,9 @@ int target_register_user_commands(struct command_context_s *cmd_ctx) | |||
register_jim(cmd_ctx, "ocd_mem2array", jim_mem2array, "read memory and return as a TCL array for script processing <ARRAYNAME> <WIDTH = 32/16/8> <ADDRESS> <COUNT>"); | |||
register_jim(cmd_ctx, "ocd_array2mem", jim_array2mem, "convert a TCL array to memory locations and write the values <ARRAYNAME> <WIDTH = 32/16/8> <ADDRESS> <COUNT>"); | |||
register_jim(cmd_ctx, "mrc", jim_mcrmrc, "read coprocessor <cpnum> <op1> <op2> <CRn> <CRm>"); | |||
register_jim(cmd_ctx, "mcr", jim_mcrmrc, "write coprocessor <cpnum> <op1> <op2> <CRn> <CRm> <value>"); | |||
register_command(cmd_ctx, NULL, "fast_load_image", handle_fast_load_image_command, COMMAND_ANY, | |||
"same args as load_image, image stored in memory - mainly for profiling purposes"); | |||
@@ -3355,7 +3424,6 @@ static int jim_array2mem(Jim_Interp *interp, int argc, Jim_Obj *const *argv) | |||
return target_array2mem(interp,target, argc-1, argv + 1); | |||
} | |||
static int target_array2mem(Jim_Interp *interp, target_t *target, int argc, Jim_Obj *const *argv) | |||
{ | |||
long l; | |||
@@ -4693,10 +4761,90 @@ static int handle_fast_load_command(struct command_context_s *cmd_ctx, char *cmd | |||
return retval; | |||
} | |||
static int jim_mcrmrc(Jim_Interp *interp, int argc, Jim_Obj *const *argv) | |||
{ | |||
command_context_t *context; | |||
target_t *target; | |||
int retval; | |||
/* | |||
* Local Variables: | |||
* c-basic-offset: 4 | |||
* tab-width: 4 | |||
* End: | |||
*/ | |||
context = Jim_GetAssocData(interp, "context"); | |||
if (context == NULL) { | |||
LOG_ERROR("array2mem: no command context"); | |||
return JIM_ERR; | |||
} | |||
target = get_current_target(context); | |||
if (target == NULL) { | |||
LOG_ERROR("array2mem: no current target"); | |||
return JIM_ERR; | |||
} | |||
if ((argc < 6) || (argc > 7)) | |||
{ | |||
return JIM_ERR; | |||
} | |||
int cpnum; | |||
uint32_t op1; | |||
uint32_t op2; | |||
uint32_t CRn; | |||
uint32_t CRm; | |||
uint32_t value; | |||
int e; | |||
long l; | |||
e = Jim_GetLong(interp, argv[1], &l); | |||
if (e != JIM_OK) { | |||
return e; | |||
} | |||
cpnum = l; | |||
e = Jim_GetLong(interp, argv[2], &l); | |||
if (e != JIM_OK) { | |||
return e; | |||
} | |||
op1 = l; | |||
e = Jim_GetLong(interp, argv[3], &l); | |||
if (e != JIM_OK) { | |||
return e; | |||
} | |||
op2 = l; | |||
e = Jim_GetLong(interp, argv[4], &l); | |||
if (e != JIM_OK) { | |||
return e; | |||
} | |||
CRn = l; | |||
e = Jim_GetLong(interp, argv[5], &l); | |||
if (e != JIM_OK) { | |||
return e; | |||
} | |||
CRm = l; | |||
value = 0; | |||
LOG_DEBUG("%d %d %d %d %d %d", cpnum, op1, op2, CRn, CRm, value); | |||
if (argc == 7) | |||
{ | |||
e = Jim_GetLong(interp, argv[6], &l); | |||
if (e != JIM_OK) { | |||
return e; | |||
} | |||
value = l; | |||
retval = target_mcr(target, cpnum, op1, op2, CRn, CRm, value); | |||
if (retval != ERROR_OK) | |||
return JIM_ERR; | |||
} else | |||
{ | |||
retval = target_mrc(target, cpnum, op1, op2, CRn, CRm, &value); | |||
if (retval != ERROR_OK) | |||
return JIM_ERR; | |||
Jim_SetResult(interp, Jim_NewIntObj(interp, value)); | |||
} | |||
return JIM_OK; | |||
} |
@@ -2,7 +2,7 @@ | |||
* Copyright (C) 2005 by Dominic Rath * | |||
* Dominic.Rath@gmx.de * | |||
* * | |||
* Copyright (C) 2007,2008 Øyvind Harboe * | |||
* Copyright (C) 2007,2008,2009 Øyvind Harboe * | |||
* oyvind.harboe@zylin.com * | |||
* * | |||
* Copyright (C) 2008 by Spencer Oliver * | |||
@@ -2,7 +2,7 @@ | |||
* Copyright (C) 2005 by Dominic Rath * | |||
* Dominic.Rath@gmx.de * | |||
* * | |||
* Copyright (C) 2007,2008 Øyvind Harboe * | |||
* Copyright (C) 2007,2008,2009 Øyvind Harboe * | |||
* oyvind.harboe@zylin.com * | |||
* * | |||
* Copyright (C) 2008 by Spencer Oliver * | |||
@@ -202,6 +202,11 @@ struct target_type_s | |||
int (*mmu)(struct target_s *target, int *enabled); | |||
/* Read coprocessor - arm specific. Default implementation returns error. */ | |||
int (*mrc)(struct target_s *target, int cpnum, uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm, uint32_t *value); | |||
/* Write coprocessor. Default implementation returns error. */ | |||
int (*mcr)(struct target_s *target, int cpnum, uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm, uint32_t value); | |||
}; | |||
#endif // TARGET_TYPE_H |