From: OpenOCD-Gerrit <ope...@us...> - 2020-07-26 19:09:17
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Main OpenOCD repository". The branch, master has been updated via b2821b607460f8ce564b8b9d1cd968439058a108 (commit) via 8fea8460dbc6ca23e34a16898e86231daab0594d (commit) from 07df04b3b1eca3b920a9b4b411883d9d44fd06e5 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit b2821b607460f8ce564b8b9d1cd968439058a108 Author: Evgeniy Didin <di...@sy...> Date: Mon Jul 20 13:27:46 2020 +0300 Introduce tcl config files for Synopsys HSDK board With this commit we add tcl configure files for ARCv2 HS Development kit(HSDK). HSDK board has Quad-core ARC HS38 CPU with L1 and L2 caches. Change-Id: I372ef45428c7c7ca1421a6da3e5ed08b86f705e0 Signed-off-by: Evgeniy Didin <di...@sy...> Reviewed-on: http://openocd.zylin.com/5784 Tested-by: jenkins Reviewed-by: Antonio Borneo <bor...@gm...> diff --git a/tcl/board/snps_hsdk.cfg b/tcl/board/snps_hsdk.cfg new file mode 100644 index 000000000..fed7343de --- /dev/null +++ b/tcl/board/snps_hsdk.cfg @@ -0,0 +1,18 @@ +# Copyright (C) 2019, 2020 Synopsys, Inc. +# Anton Kolesov <ant...@sy...> +# Didin Evgeniy <di...@sy...> +# +# SPDX-License-Identifier: GPL-2.0-or-later + +# +# Synopsys DesignWare ARC HSDK Software Development Platform (HS38 cores) +# + +source [find interface/ftdi/snps_sdp.cfg] +adapter_khz 10000 + +# ARCs supports only JTAG. +transport select jtag + +# Configure SoC +source [find target/snps_hsdk.cfg] diff --git a/tcl/cpu/arc/hs.tcl b/tcl/cpu/arc/hs.tcl new file mode 100644 index 000000000..f39f2a7d0 --- /dev/null +++ b/tcl/cpu/arc/hs.tcl @@ -0,0 +1,58 @@ +# Copyright (C) 2015, 2020 Synopsys, Inc. +# Anton Kolesov <ant...@sy...> +# Didin Evgeniy <di...@sy...> +# +# SPDX-License-Identifier: GPL-2.0-or-later + +source [find cpu/arc/v2.tcl] + +proc arc_hs_examine_target { target } { + # Will set current target for us. + arc_v2_examine_target $target +} + +proc arc_hs_init_regs { } { + arc_v2_init_regs + + [target current] configure \ + -event examine-end "arc_hs_examine_target [target current]" +} + +# Scripts in "target" folder should call this function instead of direct +# invocation of arc_common_reset. +proc arc_hs_reset { {target ""} } { + arc_v2_reset $target + + # Invalidate L2 cache if there is one. + set l2_config [$target arc jtag get-aux-reg 0x901] + # Will return 0, if cache is not present and register doesn't exist. + set l2_ctrl [$target arc jtag get-aux-reg 0x903] + if { ($l2_config != 0) && (($l2_ctrl & 1) == 0) } { + puts "L2 cache is present and not disabled" + + # Wait until BUSY bit is 0. + puts "Invalidating L2 cache..." + $target arc jtag set-aux-reg 0x905 1 + # Dummy read of SLC_AUX_CACHE_CTRL bit, as described in: + # https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git/commit/arch/arc?id=c70c473396cbdec1168a6eff60e13029c0916854 + set l2_ctrl [$target arc jtag get-aux-reg 0x903] + set l2_ctrl [$target arc jtag get-aux-reg 0x903] + while { ($l2_ctrl & 0x100) != 0 } { + set l2_ctrl [$target arc jtag get-aux-reg 0x903] + } + + # Flush cache if needed. If SLC_AUX_CACHE_CTRL.IM is 1, then invalidate + # operation already flushed everything. + if { ($l2_ctrl & 0x40) == 0 } { + puts "Flushing L2 cache..." + $target arc jtag set-aux-reg 0x904 1 + set l2_ctrl [$target arc jtag get-aux-reg 0x903] + set l2_ctrl [$target arc jtag get-aux-reg 0x903] + while { [expr $l2_ctrl & 0x100] != 0 } { + set l2_ctrl [$target arc jtag get-aux-reg 0x903] + } + } + + puts "L2 cache has been flushed and invalidated." + } +} diff --git a/tcl/interface/ftdi/snps_sdp.cfg b/tcl/interface/ftdi/snps_sdp.cfg new file mode 100644 index 000000000..8d91c6d3c --- /dev/null +++ b/tcl/interface/ftdi/snps_sdp.cfg @@ -0,0 +1,18 @@ +# Copyright (C) 2020 Synopsys, Inc. +# Anton Kolesov <ant...@sy...> +# Didin Evgeniy <di...@sy...> +# +# SPDX-License-Identifier: GPL-2.0-or-later + +# +# Synopsys SDP Mainboard has embdded FT2232 chip, which is similiar to Digilent +# HS-1, except that it uses channel B for JTAG communication, instead of +# channel A. +# + +adapter driver ftdi +ftdi_vid_pid 0x0403 0x6010 +ftdi_layout_init 0x0088 0x008b +ftdi_channel 1 + + diff --git a/tcl/target/snps_hsdk.cfg b/tcl/target/snps_hsdk.cfg new file mode 100644 index 000000000..634e07adc --- /dev/null +++ b/tcl/target/snps_hsdk.cfg @@ -0,0 +1,86 @@ +# Copyright (C) 2019,2020 Synopsys, Inc. +# Anton Kolesov <ant...@sy...> +# Didin Evgeniy <di...@sy...> +# +# SPDX-License-Identifier: GPL-2.0-or-later + +# +# HS Development Kit SoC. +# +# Contains quad-core ARC HS38. +# + +source [find cpu/arc/hs.tcl] + +set _coreid 0 +set _dbgbase [expr ($_coreid << 13)] + +# CHIPNAME will be used to choose core family (600, 700 or EM). As far as +# OpenOCD is concerned EM and HS are identical. +set _CHIPNAME arc-em + +# OpenOCD discovers JTAG TAPs in reverse order. + +# ARC HS38 core 4 +set _TARGETNAME $_CHIPNAME.cpu4 +jtag newtap $_CHIPNAME cpu4 -irlen 4 -ircapture 0x1 -expected-id 0x200c24b1 + +target create $_TARGETNAME arcv2 -chain-position $_TARGETNAME +$_TARGETNAME configure -coreid $_coreid +$_TARGETNAME configure -dbgbase $_dbgbase +# Flush L2$. +$_TARGETNAME configure -event reset-assert "arc_hs_reset $_TARGETNAME" +set _coreid [expr $_coreid + 1] +set _dbgbase [expr ($_coreid << 13)] + +arc_hs_init_regs + +# Enable L2 cache support for core 4. +$_TARGETNAME arc cache l2 auto 1 + +# ARC HS38 core 3 +set _TARGETNAME $_CHIPNAME.cpu3 +jtag newtap $_CHIPNAME cpu3 -irlen 4 -ircapture 0x1 -expected-id 0x200824b1 + +target create $_TARGETNAME arcv2 -chain-position $_TARGETNAME +$_TARGETNAME configure -coreid $_coreid +$_TARGETNAME configure -dbgbase $_dbgbase +$_TARGETNAME configure -event reset-assert "arc_common_reset $_TARGETNAME" +set _coreid [expr $_coreid + 1] +set _dbgbase [expr ($_coreid << 13)] + +arc_hs_init_regs + +# Enable L2 cache support for core 3. +$_TARGETNAME arc cache l2 auto 1 + +# ARC HS38 core 2 +set _TARGETNAME $_CHIPNAME.cpu2 +jtag newtap $_CHIPNAME cpu2 -irlen 4 -ircapture 0x1 -expected-id 0x200424b1 + +target create $_TARGETNAME arcv2 -chain-position $_TARGETNAME +$_TARGETNAME configure -coreid $_coreid +$_TARGETNAME configure -dbgbase $_dbgbase +$_TARGETNAME configure -event reset-assert "arc_common_reset $_TARGETNAME" +set _coreid [expr $_coreid + 1] +set _dbgbase [expr ($_coreid << 13)] + +arc_hs_init_regs + +# Enable L2 cache support for core 2. +$_TARGETNAME arc cache l2 auto 1 + +# ARC HS38 core 1 +set _TARGETNAME $_CHIPNAME.cpu1 +jtag newtap $_CHIPNAME cpu1 -irlen 4 -ircapture 0x1 -expected-id 0x200024b1 + +target create $_TARGETNAME arcv2 -chain-position $_TARGETNAME +$_TARGETNAME configure -coreid $_coreid +$_TARGETNAME configure -dbgbase $_dbgbase +$_TARGETNAME configure -event reset-assert "arc_common_reset $_TARGETNAME" +set _coreid [expr $_coreid + 1] +set _dbgbase [expr 0x00000000 | ($_coreid << 13)] +arc_hs_init_regs + +# Enable L2 cache support for core 1. +$_TARGETNAME arc cache l2 auto 1 commit 8fea8460dbc6ca23e34a16898e86231daab0594d Author: Evgeniy Didin <di...@sy...> Date: Fri Jul 10 14:52:35 2020 +0300 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 <di...@sy...> Reviewed-on: http://openocd.zylin.com/5763 Tested-by: jenkins Reviewed-by: Antonio Borneo <bor...@gm...> diff --git a/src/target/arc.c b/src/target/arc.c index 1ac4a4335..db338031f 100644 --- a/src/target/arc.c +++ b/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) diff --git a/src/target/arc.h b/src/target/arc.h index 664141159..f9ee5b45e 100644 --- a/src/target/arc.h +++ b/src/target/arc.h @@ -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 */ diff --git a/src/target/arc_cmd.c b/src/target/arc_cmd.c index 59e1645d6..a1d5a0936 100644 --- a/src/target/arc_cmd.c +++ b/src/target/arc_cmd.c @@ -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 }; diff --git a/tcl/cpu/arc/v2.tcl b/tcl/cpu/arc/v2.tcl index ad55361a5..a3172c220 100644 --- a/tcl/cpu/arc/v2.tcl +++ b/tcl/cpu/arc/v2.tcl @@ -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 + } } ----------------------------------------------------------------------- Summary of changes: src/target/arc.c | 284 +++++++++++++++++++++++++++++++++++++++- src/target/arc.h | 34 ++++- src/target/arc_cmd.c | 51 ++++++++ tcl/board/snps_hsdk.cfg | 18 +++ tcl/cpu/arc/hs.tcl | 58 ++++++++ tcl/cpu/arc/v2.tcl | 58 ++++++++ tcl/interface/ftdi/snps_sdp.cfg | 18 +++ tcl/target/snps_hsdk.cfg | 86 ++++++++++++ 8 files changed, 598 insertions(+), 9 deletions(-) create mode 100644 tcl/board/snps_hsdk.cfg create mode 100644 tcl/cpu/arc/hs.tcl create mode 100644 tcl/interface/ftdi/snps_sdp.cfg create mode 100644 tcl/target/snps_hsdk.cfg hooks/post-receive -- Main OpenOCD repository |