target/arc: Introduce Actionpoints support
Actionpoint mechanism allows to setup HW breakpoints and watchpoints on Synopsys ARC CPUs. This mechanism is controlled by DEBUG register and by a set of auxilary registers. Each actionpoint is controlled by 3 aux registers: Actionpoint(AP) match mask(AP_AMM), AP match value(AP_AMV) and AP control(AC). Note: some fields of actionpoint_t structure will be used in further support of watchpoints. Change-Id: I4efb24675f247cc19d9122501c9e63c3126fcab4 Signed-off-by: Evgeniy Didin <didin@synopsys.com> Reviewed-on: http://openocd.zylin.com/5763 Tested-by: jenkins Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
This commit is contained in:
parent
07df04b3b1
commit
8fea8460db
284
src/target/arc.c
284
src/target/arc.c
|
@ -603,6 +603,27 @@ static int arc_get_register_value(struct target *target, const char *reg_name,
|
|||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int arc_set_register_value(struct target *target, const char *reg_name,
|
||||
uint32_t value)
|
||||
{
|
||||
LOG_DEBUG("reg_name=%s value=0x%08" PRIx32, reg_name, value);
|
||||
|
||||
if (!(target && reg_name)) {
|
||||
LOG_ERROR("Arguments cannot be NULL.");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
struct reg *reg = arc_reg_get_by_name(target->reg_cache, reg_name, true);
|
||||
|
||||
if (!reg)
|
||||
return ERROR_ARC_REGISTER_NOT_FOUND;
|
||||
|
||||
uint8_t value_buf[4];
|
||||
buf_set_u32(value_buf, 0, 32, value);
|
||||
CHECK_RETVAL(reg->type->set(reg, value_buf));
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
/* Configure DCCM's */
|
||||
static int arc_configure_dccm(struct target *target)
|
||||
|
@ -897,6 +918,44 @@ exit:
|
|||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds an actionpoint that triggered last actionpoint event, as specified by
|
||||
* DEBUG.ASR.
|
||||
*
|
||||
* @param actionpoint Pointer to be set to last active actionpoint. Pointer
|
||||
* will be set to NULL if DEBUG.AH is 0.
|
||||
*/
|
||||
static int get_current_actionpoint(struct target *target,
|
||||
struct arc_actionpoint **actionpoint)
|
||||
{
|
||||
assert(target != NULL);
|
||||
assert(actionpoint != NULL);
|
||||
|
||||
uint32_t debug_ah;
|
||||
/* Check if actionpoint caused halt */
|
||||
CHECK_RETVAL(arc_reg_get_field(target, "debug", "ah",
|
||||
&debug_ah));
|
||||
|
||||
if (debug_ah) {
|
||||
struct arc_common *arc = target_to_arc(target);
|
||||
unsigned int ap;
|
||||
uint32_t debug_asr;
|
||||
CHECK_RETVAL(arc_reg_get_field(target, "debug",
|
||||
"asr", &debug_asr));
|
||||
|
||||
for (ap = 0; debug_asr > 1; debug_asr >>= 1)
|
||||
ap += 1;
|
||||
|
||||
assert(ap < arc->actionpoints_num);
|
||||
|
||||
*actionpoint = &(arc->actionpoints_list[ap]);
|
||||
} else {
|
||||
*actionpoint = NULL;
|
||||
}
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int arc_examine_debug_reason(struct target *target)
|
||||
{
|
||||
uint32_t debug_bh;
|
||||
|
@ -916,8 +975,20 @@ static int arc_examine_debug_reason(struct target *target)
|
|||
/* DEBUG.BH is set if core halted due to BRK instruction. */
|
||||
target->debug_reason = DBG_REASON_BREAKPOINT;
|
||||
} else {
|
||||
/* TODO: Add Actionpoint check when AP support will be introduced*/
|
||||
LOG_WARNING("Unknown debug reason");
|
||||
struct arc_actionpoint *actionpoint = NULL;
|
||||
CHECK_RETVAL(get_current_actionpoint(target, &actionpoint));
|
||||
|
||||
if (actionpoint != NULL) {
|
||||
if (!actionpoint->used)
|
||||
LOG_WARNING("Target halted by an unused actionpoint.");
|
||||
|
||||
if (actionpoint->type == ARC_AP_BREAKPOINT)
|
||||
target->debug_reason = DBG_REASON_BREAKPOINT;
|
||||
else if (actionpoint->type == ARC_AP_WATCHPOINT)
|
||||
target->debug_reason = DBG_REASON_WATCHPOINT;
|
||||
else
|
||||
LOG_WARNING("Unknown type of actionpoint.");
|
||||
}
|
||||
}
|
||||
|
||||
return ERROR_OK;
|
||||
|
@ -1301,6 +1372,7 @@ static void arc_deinit_target(struct target *target)
|
|||
list_for_each_entry_safe(desc, k, &arc->bcr_reg_descriptions, list)
|
||||
free_reg_desc(desc);
|
||||
|
||||
free(arc->actionpoints_list);
|
||||
free(arc);
|
||||
}
|
||||
|
||||
|
@ -1377,10 +1449,54 @@ int arc_read_instruction_u32(struct target *target, uint32_t address,
|
|||
return ERROR_OK;
|
||||
}
|
||||
|
||||
/* Actionpoint mechanism allows to setup HW breakpoints
|
||||
* and watchpoints. Each actionpoint is controlled by
|
||||
* 3 aux registers: Actionpoint(AP) match mask(AP_AMM), AP match value(AP_AMV)
|
||||
* and AP control(AC).
|
||||
* This function is for setting/unsetting actionpoints:
|
||||
* at - actionpoint target: trigger on mem/reg access
|
||||
* tt - transaction type : trigger on r/w. */
|
||||
static int arc_configure_actionpoint(struct target *target, uint32_t ap_num,
|
||||
uint32_t match_value, uint32_t control_tt, uint32_t control_at)
|
||||
{
|
||||
struct arc_common *arc = target_to_arc(target);
|
||||
|
||||
if (control_tt != AP_AC_TT_DISABLE) {
|
||||
|
||||
if (arc->actionpoints_num_avail < 1) {
|
||||
LOG_ERROR("No free actionpoints, maximim amount is %" PRIu32,
|
||||
arc->actionpoints_num);
|
||||
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
/* Names of register to set - 24 chars should be enough. Looks a little
|
||||
* bit out-of-place for C code, but makes it aligned to the bigger
|
||||
* concept of "ARC registers are defined in TCL" as far as possible.
|
||||
*/
|
||||
char ap_amv_reg_name[24], ap_amm_reg_name[24], ap_ac_reg_name[24];
|
||||
snprintf(ap_amv_reg_name, 24, "ap_amv%" PRIu32, ap_num);
|
||||
snprintf(ap_amm_reg_name, 24, "ap_amm%" PRIu32, ap_num);
|
||||
snprintf(ap_ac_reg_name, 24, "ap_ac%" PRIu32, ap_num);
|
||||
CHECK_RETVAL(arc_set_register_value(target, ap_amv_reg_name,
|
||||
match_value));
|
||||
CHECK_RETVAL(arc_set_register_value(target, ap_amm_reg_name, 0));
|
||||
CHECK_RETVAL(arc_set_register_value(target, ap_ac_reg_name,
|
||||
control_tt | control_at));
|
||||
arc->actionpoints_num_avail--;
|
||||
} else {
|
||||
char ap_ac_reg_name[24];
|
||||
snprintf(ap_ac_reg_name, 24, "ap_ac%" PRIu32, ap_num);
|
||||
CHECK_RETVAL(arc_set_register_value(target, ap_ac_reg_name,
|
||||
AP_AC_TT_DISABLE));
|
||||
arc->actionpoints_num_avail++;
|
||||
}
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int arc_set_breakpoint(struct target *target,
|
||||
struct breakpoint *breakpoint)
|
||||
{
|
||||
|
||||
if (breakpoint->set) {
|
||||
LOG_WARNING("breakpoint already set");
|
||||
return ERROR_OK;
|
||||
|
@ -1425,8 +1541,34 @@ static int arc_set_breakpoint(struct target *target,
|
|||
|
||||
breakpoint->set = 64; /* Any nice value but 0 */
|
||||
} else if (breakpoint->type == BKPT_HARD) {
|
||||
LOG_DEBUG("Hardware breakpoints are not supported yet!");
|
||||
return ERROR_FAIL;
|
||||
struct arc_common *arc = target_to_arc(target);
|
||||
struct arc_actionpoint *ap_list = arc->actionpoints_list;
|
||||
unsigned int bp_num;
|
||||
|
||||
for (bp_num = 0; bp_num < arc->actionpoints_num; bp_num++) {
|
||||
if (!ap_list[bp_num].used)
|
||||
break;
|
||||
}
|
||||
|
||||
if (bp_num >= arc->actionpoints_num) {
|
||||
LOG_ERROR("No free actionpoints, maximum amount is %" PRIu32,
|
||||
arc->actionpoints_num);
|
||||
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
int retval = arc_configure_actionpoint(target, bp_num,
|
||||
breakpoint->address, AP_AC_TT_READWRITE, AP_AC_AT_INST_ADDR);
|
||||
|
||||
if (retval == ERROR_OK) {
|
||||
breakpoint->set = bp_num + 1;
|
||||
ap_list[bp_num].used = 1;
|
||||
ap_list[bp_num].bp_value = breakpoint->address;
|
||||
ap_list[bp_num].type = ARC_AP_BREAKPOINT;
|
||||
|
||||
LOG_DEBUG("bpid: %" PRIu32 ", bp_num %u bp_value 0x%" PRIx32,
|
||||
breakpoint->unique_id, bp_num, ap_list[bp_num].bp_value);
|
||||
}
|
||||
|
||||
} else {
|
||||
LOG_DEBUG("ERROR: setting unknown breakpoint type");
|
||||
return ERROR_FAIL;
|
||||
|
@ -1491,8 +1633,27 @@ static int arc_unset_breakpoint(struct target *target,
|
|||
breakpoint->set = 0;
|
||||
|
||||
} else if (breakpoint->type == BKPT_HARD) {
|
||||
LOG_WARNING("Hardware breakpoints are not supported yet!");
|
||||
return ERROR_FAIL;
|
||||
struct arc_common *arc = target_to_arc(target);
|
||||
struct arc_actionpoint *ap_list = arc->actionpoints_list;
|
||||
unsigned int bp_num = breakpoint->set - 1;
|
||||
|
||||
if ((breakpoint->set == 0) || (bp_num >= arc->actionpoints_num)) {
|
||||
LOG_DEBUG("Invalid actionpoint ID: %u in breakpoint: %" PRIu32,
|
||||
bp_num, breakpoint->unique_id);
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
retval = arc_configure_actionpoint(target, bp_num,
|
||||
breakpoint->address, AP_AC_TT_DISABLE, AP_AC_AT_INST_ADDR);
|
||||
|
||||
if (retval == ERROR_OK) {
|
||||
breakpoint->set = 0;
|
||||
ap_list[bp_num].used = 0;
|
||||
ap_list[bp_num].bp_value = 0;
|
||||
|
||||
LOG_DEBUG("bpid: %" PRIu32 " - released actionpoint ID: %i",
|
||||
breakpoint->unique_id, bp_num);
|
||||
}
|
||||
} else {
|
||||
LOG_DEBUG("ERROR: unsetting unknown breakpoint type");
|
||||
return ERROR_FAIL;
|
||||
|
@ -1530,6 +1691,115 @@ static int arc_remove_breakpoint(struct target *target,
|
|||
return ERROR_OK;
|
||||
}
|
||||
|
||||
void arc_reset_actionpoints(struct target *target)
|
||||
{
|
||||
struct arc_common *arc = target_to_arc(target);
|
||||
struct arc_actionpoint *ap_list = arc->actionpoints_list;
|
||||
struct breakpoint *next_b;
|
||||
|
||||
while (target->breakpoints) {
|
||||
next_b = target->breakpoints->next;
|
||||
arc_remove_breakpoint(target, target->breakpoints);
|
||||
free(target->breakpoints->orig_instr);
|
||||
free(target->breakpoints);
|
||||
target->breakpoints = next_b;
|
||||
}
|
||||
for (unsigned int i = 0; i < arc->actionpoints_num; i++) {
|
||||
if ((ap_list[i].used) && (ap_list[i].reg_address))
|
||||
arc_remove_auxreg_actionpoint(target, ap_list[i].reg_address);
|
||||
}
|
||||
}
|
||||
|
||||
int arc_set_actionpoints_num(struct target *target, uint32_t ap_num)
|
||||
{
|
||||
LOG_DEBUG("target=%s actionpoints=%" PRIu32, target_name(target), ap_num);
|
||||
struct arc_common *arc = target_to_arc(target);
|
||||
|
||||
/* Make sure that there are no enabled actionpoints in target. */
|
||||
arc_reset_actionpoints(target);
|
||||
|
||||
/* Assume that all points have been removed from target. */
|
||||
free(arc->actionpoints_list);
|
||||
|
||||
arc->actionpoints_num_avail = ap_num;
|
||||
arc->actionpoints_num = ap_num;
|
||||
/* calloc can be safely called when ncount == 0. */
|
||||
arc->actionpoints_list = calloc(ap_num, sizeof(struct arc_actionpoint));
|
||||
|
||||
if (!arc->actionpoints_list) {
|
||||
LOG_ERROR("Unable to allocate memory");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
|
||||
int arc_add_auxreg_actionpoint(struct target *target,
|
||||
uint32_t auxreg_addr, uint32_t transaction)
|
||||
{
|
||||
unsigned int ap_num = 0;
|
||||
int retval = ERROR_OK;
|
||||
|
||||
if (target->state != TARGET_HALTED)
|
||||
return ERROR_TARGET_NOT_HALTED;
|
||||
|
||||
struct arc_common *arc = target_to_arc(target);
|
||||
struct arc_actionpoint *ap_list = arc->actionpoints_list;
|
||||
|
||||
while (ap_list[ap_num].used)
|
||||
ap_num++;
|
||||
|
||||
if (ap_num >= arc->actionpoints_num) {
|
||||
LOG_ERROR("No actionpoint free, maximum amount is %u",
|
||||
arc->actionpoints_num);
|
||||
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
retval = arc_configure_actionpoint(target, ap_num,
|
||||
auxreg_addr, transaction, AP_AC_AT_AUXREG_ADDR);
|
||||
|
||||
if (retval == ERROR_OK) {
|
||||
ap_list[ap_num].used = 1;
|
||||
ap_list[ap_num].reg_address = auxreg_addr;
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
int arc_remove_auxreg_actionpoint(struct target *target, uint32_t auxreg_addr)
|
||||
{
|
||||
int retval = ERROR_OK;
|
||||
bool ap_found = false;
|
||||
unsigned int ap_num = 0;
|
||||
|
||||
if (target->state != TARGET_HALTED)
|
||||
return ERROR_TARGET_NOT_HALTED;
|
||||
|
||||
struct arc_common *arc = target_to_arc(target);
|
||||
struct arc_actionpoint *ap_list = arc->actionpoints_list;
|
||||
|
||||
while ((ap_list[ap_num].used) && (ap_num < arc->actionpoints_num)) {
|
||||
if (ap_list[ap_num].reg_address == auxreg_addr) {
|
||||
ap_found = true;
|
||||
break;
|
||||
}
|
||||
ap_num++;
|
||||
}
|
||||
|
||||
if (ap_found) {
|
||||
retval = arc_configure_actionpoint(target, ap_num,
|
||||
auxreg_addr, AP_AC_TT_DISABLE, AP_AC_AT_AUXREG_ADDR);
|
||||
|
||||
if (retval == ERROR_OK) {
|
||||
ap_list[ap_num].used = 0;
|
||||
ap_list[ap_num].bp_value = 0;
|
||||
}
|
||||
} else {
|
||||
LOG_ERROR("Register actionpoint not found");
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* Helper function which swiches core to single_step mode by
|
||||
* doing aux r/w operations. */
|
||||
int arc_config_step(struct target *target, int enable_step)
|
||||
|
|
|
@ -78,6 +78,16 @@
|
|||
#define SLC_AUX_CACHE_INV 0x905
|
||||
#define L2_INV_IV BIT(0)
|
||||
|
||||
/* Action Point */
|
||||
#define AP_AC_AT_INST_ADDR 0x0
|
||||
#define AP_AC_AT_MEMORY_ADDR 0x2
|
||||
#define AP_AC_AT_AUXREG_ADDR 0x4
|
||||
|
||||
#define AP_AC_TT_DISABLE 0x00
|
||||
#define AP_AC_TT_WRITE 0x10
|
||||
#define AP_AC_TT_READ 0x20
|
||||
#define AP_AC_TT_READWRITE 0x30
|
||||
|
||||
struct arc_reg_bitfield {
|
||||
struct reg_data_type_bitfield bitfield;
|
||||
char name[REG_TYPE_MAX_NAME_LENGTH];
|
||||
|
@ -96,8 +106,6 @@ struct arc_reg_data_type {
|
|||
};
|
||||
};
|
||||
|
||||
|
||||
|
||||
/* Standard GDB register types */
|
||||
static const struct reg_data_type standard_gdb_types[] = {
|
||||
{ .type = REG_TYPE_INT, .id = "int" },
|
||||
|
@ -118,6 +126,18 @@ static const struct reg_data_type standard_gdb_types[] = {
|
|||
{ .type = REG_TYPE_IEEE_DOUBLE, .id = "ieee_double" },
|
||||
};
|
||||
|
||||
enum arc_actionpointype {
|
||||
ARC_AP_BREAKPOINT,
|
||||
ARC_AP_WATCHPOINT,
|
||||
};
|
||||
|
||||
/* Actionpoint related fields */
|
||||
struct arc_actionpoint {
|
||||
int used;
|
||||
uint32_t bp_value;
|
||||
uint32_t reg_address;
|
||||
enum arc_actionpointype type;
|
||||
};
|
||||
|
||||
struct arc_common {
|
||||
uint32_t common_magic;
|
||||
|
@ -172,6 +192,11 @@ struct arc_common {
|
|||
unsigned long pc_index_in_cache;
|
||||
/* DEBUG register location in register cache. */
|
||||
unsigned long debug_index_in_cache;
|
||||
|
||||
/* Actionpoints */
|
||||
unsigned int actionpoints_num;
|
||||
unsigned int actionpoints_num_avail;
|
||||
struct arc_actionpoint *actionpoints_list;
|
||||
};
|
||||
|
||||
/* Borrowed from nds32.h */
|
||||
|
@ -284,4 +309,9 @@ int arc_reg_get_field(struct target *target, const char *reg_name,
|
|||
int arc_cache_flush(struct target *target);
|
||||
int arc_cache_invalidate(struct target *target);
|
||||
|
||||
int arc_add_auxreg_actionpoint(struct target *target,
|
||||
uint32_t auxreg_addr, uint32_t transaction);
|
||||
int arc_remove_auxreg_actionpoint(struct target *target, uint32_t auxreg_addr);
|
||||
int arc_set_actionpoints_num(struct target *target, uint32_t ap_num);
|
||||
|
||||
#endif /* OPENOCD_TARGET_ARC_H */
|
||||
|
|
|
@ -929,6 +929,50 @@ COMMAND_HANDLER(arc_l2_cache_disable_auto_cmd)
|
|||
&arc->has_l2cache, "target has l2 cache enabled");
|
||||
}
|
||||
|
||||
static int jim_handle_actionpoints_num(Jim_Interp *interp, int argc,
|
||||
Jim_Obj * const *argv)
|
||||
{
|
||||
Jim_GetOptInfo goi;
|
||||
Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1);
|
||||
|
||||
LOG_DEBUG("-");
|
||||
|
||||
if (goi.argc >= 2) {
|
||||
Jim_WrongNumArgs(interp, goi.argc, goi.argv, "[<unsigned integer>]");
|
||||
return JIM_ERR;
|
||||
}
|
||||
|
||||
struct command_context *context = current_command_context(interp);
|
||||
assert(context);
|
||||
|
||||
struct target *target = get_current_target(context);
|
||||
|
||||
if (!target) {
|
||||
Jim_SetResultFormatted(goi.interp, "No current target");
|
||||
return JIM_ERR;
|
||||
}
|
||||
|
||||
struct arc_common *arc = target_to_arc(target);
|
||||
/* It is not possible to pass &arc->actionpoints_num directly to
|
||||
* handle_command_parse_uint, because this value should be valid during
|
||||
* "actionpoint reset, initiated by arc_set_actionpoints_num. */
|
||||
uint32_t ap_num = arc->actionpoints_num;
|
||||
|
||||
if (goi.argc == 1) {
|
||||
JIM_CHECK_RETVAL(arc_cmd_jim_get_uint32(&goi, &ap_num));
|
||||
int e = arc_set_actionpoints_num(target, ap_num);
|
||||
if (e != ERROR_OK) {
|
||||
Jim_SetResultFormatted(goi.interp,
|
||||
"Failed to set number of actionpoints");
|
||||
return JIM_ERR;
|
||||
}
|
||||
}
|
||||
|
||||
Jim_SetResultInt(interp, ap_num);
|
||||
|
||||
return JIM_OK;
|
||||
}
|
||||
|
||||
/* ----- Exported target commands ------------------------------------------ */
|
||||
|
||||
const struct command_registration arc_l2_cache_group_handlers[] = {
|
||||
|
@ -1024,6 +1068,13 @@ static const struct command_registration arc_core_command_handlers[] = {
|
|||
.usage = "",
|
||||
.chain = arc_cache_group_handlers,
|
||||
},
|
||||
{
|
||||
.name = "num-actionpoints",
|
||||
.jim_handler = jim_handle_actionpoints_num,
|
||||
.mode = COMMAND_ANY,
|
||||
.usage = "[<unsigned integer>]",
|
||||
.help = "Prints or sets amount of actionpoints in the processor.",
|
||||
},
|
||||
COMMAND_REGISTRATION_DONE
|
||||
};
|
||||
|
||||
|
|
|
@ -30,6 +30,32 @@ proc arc_v2_examine_target { {target ""} } {
|
|||
r13 r14 r15 r16 r17 r18 r19 r20 r21 r22 r23 r24 r25 \
|
||||
gp fp sp ilink r30 blink lp_count pcl
|
||||
|
||||
# Actionpoints
|
||||
if { [arc get-reg-field ap_build version] == 5 } {
|
||||
set ap_build_type [arc get-reg-field ap_build type]
|
||||
# AP_BUILD.TYPE > 0b0110 is reserved in current ISA.
|
||||
# Current ISA supports up to 8 actionpoints.
|
||||
if { $ap_build_type < 8 } {
|
||||
# Two LSB bits of AP_BUILD.TYPE define amount of actionpoints:
|
||||
# 0b00 - 2 actionpoints
|
||||
# 0b01 - 4 actionpoints
|
||||
# 0b10 - 8 actionpoints
|
||||
# 0b11 - reserved.
|
||||
set ap_num [expr 0x2 << ($ap_build_type & 3)]
|
||||
# Expression on top may produce 16 action points - which is a
|
||||
# reserved value for now.
|
||||
if { $ap_num < 16 } {
|
||||
# Enable actionpoint registers
|
||||
for {set i 0} {$i < $ap_num} {incr i} {
|
||||
arc set-reg-exists ap_amv$i ap_amm$i ap_ac$i
|
||||
}
|
||||
|
||||
# Set amount of actionpoints
|
||||
arc num-actionpoints $ap_num
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# DCCM
|
||||
set dccm_version [arc get-reg-field dccm_build version]
|
||||
if { $dccm_version == 3 || $dccm_version == 4 } {
|
||||
|
@ -213,6 +239,30 @@ proc arc_v2_init_regs { } {
|
|||
0x018 aux_dccm int
|
||||
0x208 aux_iccm int
|
||||
|
||||
0x220 ap_amv0 uint32
|
||||
0x221 ap_amm0 uint32
|
||||
0x222 ap_ac0 ap_control_t
|
||||
0x223 ap_amv1 uint32
|
||||
0x224 ap_amm1 uint32
|
||||
0x225 ap_ac1 ap_control_t
|
||||
0x226 ap_amv2 uint32
|
||||
0x227 ap_amm2 uint32
|
||||
0x228 ap_ac2 ap_control_t
|
||||
0x229 ap_amv3 uint32
|
||||
0x22A ap_amm3 uint32
|
||||
0x22B ap_ac3 ap_control_t
|
||||
0x22C ap_amv4 uint32
|
||||
0x22D ap_amm4 uint32
|
||||
0x22E ap_ac4 ap_control_t
|
||||
0x22F ap_amv5 uint32
|
||||
0x230 ap_amm5 uint32
|
||||
0x231 ap_ac5 ap_control_t
|
||||
0x232 ap_amv6 uint32
|
||||
0x233 ap_amm6 uint32
|
||||
0x234 ap_ac6 ap_control_t
|
||||
0x235 ap_amv7 uint32
|
||||
0x236 ap_amm7 uint32
|
||||
0x237 ap_ac7 ap_control_t
|
||||
|
||||
0x400 eret code_ptr
|
||||
0x401 erbta code_ptr
|
||||
|
@ -285,4 +335,12 @@ proc arc_v2_init_regs { } {
|
|||
|
||||
proc arc_v2_reset { {target ""} } {
|
||||
arc_common_reset $target
|
||||
|
||||
# Disable all actionpoints. Cannot write via regcache yet, because it will
|
||||
# not be flushed and all changes to registers will get lost. Therefore has
|
||||
# to write directly via JTAG layer...
|
||||
set num_ap [arc num-actionpoints]
|
||||
for {set i 0} {$i < $num_ap} {incr i} {
|
||||
arc jtag set-aux-reg [expr 0x222 + $i * 3] 0
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue