X-Git-Url: https://review.openocd.org/gitweb?a=blobdiff_plain;f=src%2Ftarget%2Farc.c;h=471f16a9898d7080c58278b1e175c4174a9b1dd5;hb=2053120ba10d68339c61cd2b247bde01bda41ab7;hp=db338031f704d03a23102b66cf217f0968045fbe;hpb=8fea8460dbc6ca23e34a16898e86231daab0594d;p=openocd.git diff --git a/src/target/arc.c b/src/target/arc.c index db338031f7..471f16a989 100644 --- a/src/target/arc.c +++ b/src/target/arc.c @@ -33,7 +33,7 @@ * unexisting register is safe RAZ, rather then an error. * Note, core registers cannot be BCR. * - * In arc/cpu/ tcl files all regiters are defined as core, non-BCR aux + * In arc/cpu/ tcl files all registers are defined as core, non-BCR aux * and BCR aux, in "add-reg" command they are passed to three lists * respectively: core_reg_descriptions, aux_reg_descriptions, * bcr_reg_descriptions. @@ -48,6 +48,8 @@ */ +static int arc_remove_watchpoint(struct target *target, + struct watchpoint *watchpoint); void arc_reg_data_type_add(struct target *target, struct arc_reg_data_type *data_type) @@ -197,7 +199,7 @@ int arc_reg_add(struct target *target, struct arc_reg_desc *arc_reg, arc->num_regs += 1; LOG_DEBUG( - "added register {name=%s, num=0x%x, type=%s%s%s%s}", + "added register {name=%s, num=0x%" PRIx32 ", type=%s%s%s%s}", arc_reg->name, arc_reg->arch_num, arc_reg->data_type->id, arc_reg->is_core ? ", core" : "", arc_reg->is_bcr ? ", bcr" : "", arc_reg->is_general ? ", general" : "" @@ -225,7 +227,7 @@ static int arc_get_register(struct reg *reg) if (desc->is_core) { /* Accessing to R61/R62 registers causes Jtag hang */ - if (desc->arch_num == CORE_R61_NUM || desc->arch_num == CORE_R62_NUM) { + if (desc->arch_num == ARC_R61 || desc->arch_num == ARC_R62) { LOG_ERROR("It is forbidden to read core registers 61 and 62."); return ERROR_FAIL; } @@ -265,8 +267,8 @@ static int arc_set_register(struct reg *reg, uint8_t *buf) return ERROR_TARGET_NOT_HALTED; /* Accessing to R61/R62 registers causes Jtag hang */ - if (desc->is_core && (desc->arch_num == CORE_R61_NUM || - desc->arch_num == CORE_R62_NUM)) { + if (desc->is_core && (desc->arch_num == ARC_R61 || + desc->arch_num == ARC_R62)) { LOG_ERROR("It is forbidden to write core registers 61 and 62."); return ERROR_FAIL; } @@ -286,7 +288,7 @@ const struct reg_arch_type arc_reg_type = { .set = arc_set_register, }; -/* GDB register groups. For now we suport only general and "empty" */ +/* GDB register groups. For now we support only general and "empty" */ static const char * const reg_group_general = "general"; static const char * const reg_group_other = ""; @@ -303,7 +305,7 @@ static int arc_init_reg(struct target *target, struct reg *reg, /* Initialize struct reg */ reg->name = reg_desc->name; reg->size = 32; /* All register in ARC are 32-bit */ - reg->value = ®_desc->reg_value; + reg->value = reg_desc->reg_value; reg->type = &arc_reg_type; reg->arch_info = reg_desc; reg->caller_save = true; /* @todo should be configurable. */ @@ -548,7 +550,7 @@ int arc_reg_get_field(struct target *target, const char *reg_name, struct reg *reg = arc_reg_get_by_name(target->reg_cache, reg_name, true); if (!reg) { - LOG_ERROR("Requested register `%s' doens't exist.", reg_name); + LOG_ERROR("Requested register `%s' doesn't exist.", reg_name); return ERROR_ARC_REGISTER_NOT_FOUND; } @@ -575,7 +577,7 @@ int arc_reg_get_field(struct target *target, const char *reg_name, if (!reg->valid) CHECK_RETVAL(reg->type->get(reg)); - /* First do endiannes-safe read of register value + /* First do endianness-safe read of register value * then convert it to binary buffer for further * field extraction */ @@ -864,7 +866,7 @@ static int arc_save_context(struct target *target) /* Read data from target. */ if (core_cnt > 0) { retval = arc_jtag_read_core_reg(&arc->jtag_info, core_addrs, core_cnt, core_values); - if (ERROR_OK != retval) { + if (retval != ERROR_OK) { LOG_ERROR("Attempt to read core registers failed."); retval = ERROR_FAIL; goto exit; @@ -872,7 +874,7 @@ static int arc_save_context(struct target *target) } if (aux_cnt > 0) { retval = arc_jtag_read_aux_reg(&arc->jtag_info, aux_addrs, aux_cnt, aux_values); - if (ERROR_OK != retval) { + if (retval != ERROR_OK) { LOG_ERROR("Attempt to read aux registers failed."); retval = ERROR_FAIL; goto exit; @@ -889,7 +891,7 @@ static int arc_save_context(struct target *target) core_cnt += 1; reg->valid = true; reg->dirty = false; - LOG_DEBUG("Get core register regnum=%" PRIu32 ", name=%s, value=0x%08" PRIx32, + LOG_DEBUG("Get core register regnum=%u, name=%s, value=0x%08" PRIx32, i, arc_reg->name, core_values[core_cnt]); } } @@ -904,7 +906,7 @@ static int arc_save_context(struct target *target) aux_cnt += 1; reg->valid = true; reg->dirty = false; - LOG_DEBUG("Get aux register regnum=%" PRIu32 ", name=%s, value=0x%08" PRIx32, + LOG_DEBUG("Get aux register regnum=%u, name=%s, value=0x%08" PRIx32, i, arc_reg->name, aux_values[aux_cnt]); } } @@ -922,14 +924,15 @@ exit: * Finds an actionpoint that triggered last actionpoint event, as specified by * DEBUG.ASR. * + * @param target * @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); + assert(target); + assert(actionpoint); uint32_t debug_ah; /* Check if actionpoint caused halt */ @@ -978,7 +981,7 @@ static int arc_examine_debug_reason(struct target *target) struct arc_actionpoint *actionpoint = NULL; CHECK_RETVAL(get_current_actionpoint(target, &actionpoint)); - if (actionpoint != NULL) { + if (actionpoint) { if (!actionpoint->used) LOG_WARNING("Target halted by an unused actionpoint."); @@ -1194,7 +1197,7 @@ static int arc_restore_context(struct target *target) * Check before write, if aux and core count is greater than 0. */ if (core_cnt > 0) { retval = arc_jtag_write_core_reg(&arc->jtag_info, core_addrs, core_cnt, core_values); - if (ERROR_OK != retval) { + if (retval != ERROR_OK) { LOG_ERROR("Attempt to write to core registers failed."); retval = ERROR_FAIL; goto exit; @@ -1203,7 +1206,7 @@ static int arc_restore_context(struct target *target) if (aux_cnt > 0) { retval = arc_jtag_write_aux_reg(&arc->jtag_info, aux_addrs, aux_cnt, aux_values); - if (ERROR_OK != retval) { + if (retval != ERROR_OK) { LOG_ERROR("Attempt to write to aux registers failed."); retval = ERROR_FAIL; goto exit; @@ -1396,7 +1399,7 @@ static int arc_target_create(struct target *target, Jim_Interp *interp) * Write 4-byte instruction to memory. This is like target_write_u32, however * in case of little endian ARC instructions are in middle endian format, not * little endian, so different type of conversion should be done. - * Middle endinan: instruction "aabbccdd", stored as "bbaaddcc" + * Middle endian: instruction "aabbccdd", stored as "bbaaddcc" */ int arc_write_instruction_u32(struct target *target, uint32_t address, uint32_t instr) @@ -1464,7 +1467,7 @@ static int arc_configure_actionpoint(struct target *target, uint32_t ap_num, if (control_tt != AP_AC_TT_DISABLE) { if (arc->actionpoints_num_avail < 1) { - LOG_ERROR("No free actionpoints, maximim amount is %" PRIu32, + LOG_ERROR("No free actionpoints, maximum amount is %u", arc->actionpoints_num); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } @@ -1497,7 +1500,7 @@ static int arc_configure_actionpoint(struct target *target, uint32_t ap_num, static int arc_set_breakpoint(struct target *target, struct breakpoint *breakpoint) { - if (breakpoint->set) { + if (breakpoint->is_set) { LOG_WARNING("breakpoint already set"); return ERROR_OK; } @@ -1539,7 +1542,7 @@ static int arc_set_breakpoint(struct target *target, return ERROR_COMMAND_ARGUMENT_INVALID; } - breakpoint->set = 64; /* Any nice value but 0 */ + breakpoint->is_set = true; } else if (breakpoint->type == BKPT_HARD) { struct arc_common *arc = target_to_arc(target); struct arc_actionpoint *ap_list = arc->actionpoints_list; @@ -1551,7 +1554,7 @@ static int arc_set_breakpoint(struct target *target, } if (bp_num >= arc->actionpoints_num) { - LOG_ERROR("No free actionpoints, maximum amount is %" PRIu32, + LOG_ERROR("No free actionpoints, maximum amount is %u", arc->actionpoints_num); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } @@ -1560,7 +1563,7 @@ static int arc_set_breakpoint(struct target *target, breakpoint->address, AP_AC_TT_READWRITE, AP_AC_AT_INST_ADDR); if (retval == ERROR_OK) { - breakpoint->set = bp_num + 1; + breakpoint_hw_set(breakpoint, bp_num); ap_list[bp_num].used = 1; ap_list[bp_num].bp_value = breakpoint->address; ap_list[bp_num].type = ARC_AP_BREAKPOINT; @@ -1585,7 +1588,7 @@ static int arc_unset_breakpoint(struct target *target, { int retval = ERROR_OK; - if (!breakpoint->set) { + if (!breakpoint->is_set) { LOG_WARNING("breakpoint not set"); return ERROR_OK; } @@ -1607,7 +1610,7 @@ static int arc_unset_breakpoint(struct target *target, } else { LOG_WARNING("Software breakpoint @0x%" TARGET_PRIxADDR " has been overwritten outside of debugger." - "Expected: @0x%" PRIx32 ", got: @0x%" PRIx32, + "Expected: @0x%x, got: @0x%" PRIx32, breakpoint->address, ARC_SDBBP_32, current_instr); } } else if (breakpoint->length == 2) { @@ -1630,14 +1633,14 @@ static int arc_unset_breakpoint(struct target *target, LOG_ERROR("Invalid breakpoint length: target supports only 2 or 4"); return ERROR_COMMAND_ARGUMENT_INVALID; } - breakpoint->set = 0; + breakpoint->is_set = false; } else if (breakpoint->type == BKPT_HARD) { struct arc_common *arc = target_to_arc(target); struct arc_actionpoint *ap_list = arc->actionpoints_list; - unsigned int bp_num = breakpoint->set - 1; + unsigned int bp_num = breakpoint->number; - if ((breakpoint->set == 0) || (bp_num >= arc->actionpoints_num)) { + if (bp_num >= arc->actionpoints_num) { LOG_DEBUG("Invalid actionpoint ID: %u in breakpoint: %" PRIu32, bp_num, breakpoint->unique_id); return ERROR_OK; @@ -1647,11 +1650,11 @@ static int arc_unset_breakpoint(struct target *target, breakpoint->address, AP_AC_TT_DISABLE, AP_AC_AT_INST_ADDR); if (retval == ERROR_OK) { - breakpoint->set = 0; + breakpoint->is_set = false; ap_list[bp_num].used = 0; ap_list[bp_num].bp_value = 0; - LOG_DEBUG("bpid: %" PRIu32 " - released actionpoint ID: %i", + LOG_DEBUG("bpid: %" PRIu32 " - released actionpoint ID: %u", breakpoint->unique_id, bp_num); } } else { @@ -1681,7 +1684,7 @@ static int arc_remove_breakpoint(struct target *target, struct breakpoint *breakpoint) { if (target->state == TARGET_HALTED) { - if (breakpoint->set) + if (breakpoint->is_set) CHECK_RETVAL(arc_unset_breakpoint(target, breakpoint)); } else { LOG_WARNING("target not halted"); @@ -1696,6 +1699,7 @@ 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; + struct watchpoint *next_w; while (target->breakpoints) { next_b = target->breakpoints->next; @@ -1704,6 +1708,12 @@ void arc_reset_actionpoints(struct target *target) free(target->breakpoints); target->breakpoints = next_b; } + while (target->watchpoints) { + next_w = target->watchpoints->next; + arc_remove_watchpoint(target, target->watchpoints); + free(target->watchpoints); + target->watchpoints = next_w; + } 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); @@ -1800,7 +1810,160 @@ int arc_remove_auxreg_actionpoint(struct target *target, uint32_t auxreg_addr) return retval; } -/* Helper function which swiches core to single_step mode by + +static int arc_set_watchpoint(struct target *target, + struct watchpoint *watchpoint) +{ + unsigned int wp_num; + struct arc_common *arc = target_to_arc(target); + struct arc_actionpoint *ap_list = arc->actionpoints_list; + + if (watchpoint->is_set) { + LOG_WARNING("watchpoint already set"); + return ERROR_OK; + } + + for (wp_num = 0; wp_num < arc->actionpoints_num; wp_num++) { + if (!ap_list[wp_num].used) + break; + } + + if (wp_num >= arc->actionpoints_num) { + LOG_ERROR("No free actionpoints, maximum amount is %u", + arc->actionpoints_num); + return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; + } + + if (watchpoint->length != 4) { + LOG_ERROR("Only watchpoints of length 4 are supported"); + return ERROR_TARGET_UNALIGNED_ACCESS; + } + + int enable = AP_AC_TT_DISABLE; + switch (watchpoint->rw) { + case WPT_READ: + enable = AP_AC_TT_READ; + break; + case WPT_WRITE: + enable = AP_AC_TT_WRITE; + break; + case WPT_ACCESS: + enable = AP_AC_TT_READWRITE; + break; + default: + LOG_ERROR("BUG: watchpoint->rw neither read, write nor access"); + return ERROR_FAIL; + } + + int retval = arc_configure_actionpoint(target, wp_num, + watchpoint->address, enable, AP_AC_AT_MEMORY_ADDR); + + if (retval == ERROR_OK) { + watchpoint_set(watchpoint, wp_num); + ap_list[wp_num].used = 1; + ap_list[wp_num].bp_value = watchpoint->address; + ap_list[wp_num].type = ARC_AP_WATCHPOINT; + + LOG_DEBUG("wpid: %" PRIu32 ", wp_num %u wp_value 0x%" PRIx32, + watchpoint->unique_id, wp_num, ap_list[wp_num].bp_value); + } + + return retval; +} + +static int arc_unset_watchpoint(struct target *target, + struct watchpoint *watchpoint) +{ + /* get pointers to arch-specific information */ + struct arc_common *arc = target_to_arc(target); + struct arc_actionpoint *ap_list = arc->actionpoints_list; + + if (!watchpoint->is_set) { + LOG_WARNING("watchpoint not set"); + return ERROR_OK; + } + + unsigned int wp_num = watchpoint->number; + if (wp_num >= arc->actionpoints_num) { + LOG_DEBUG("Invalid actionpoint ID: %u in watchpoint: %" PRIu32, + wp_num, watchpoint->unique_id); + return ERROR_OK; + } + + int retval = arc_configure_actionpoint(target, wp_num, + watchpoint->address, AP_AC_TT_DISABLE, AP_AC_AT_MEMORY_ADDR); + + if (retval == ERROR_OK) { + watchpoint->is_set = false; + ap_list[wp_num].used = 0; + ap_list[wp_num].bp_value = 0; + + LOG_DEBUG("wpid: %" PRIu32 " - releasing actionpoint ID: %u", + watchpoint->unique_id, wp_num); + } + + return retval; +} + +static int arc_add_watchpoint(struct target *target, + struct watchpoint *watchpoint) +{ + if (target->state != TARGET_HALTED) { + LOG_WARNING("target not halted"); + return ERROR_TARGET_NOT_HALTED; + } + + CHECK_RETVAL(arc_set_watchpoint(target, watchpoint)); + + return ERROR_OK; +} + +static int arc_remove_watchpoint(struct target *target, + struct watchpoint *watchpoint) +{ + if (target->state != TARGET_HALTED) { + LOG_WARNING("target not halted"); + return ERROR_TARGET_NOT_HALTED; + } + + if (watchpoint->is_set) + CHECK_RETVAL(arc_unset_watchpoint(target, watchpoint)); + + return ERROR_OK; +} + +static int arc_hit_watchpoint(struct target *target, struct watchpoint **hit_watchpoint) +{ + assert(target); + assert(hit_watchpoint); + + struct arc_actionpoint *actionpoint = NULL; + CHECK_RETVAL(get_current_actionpoint(target, &actionpoint)); + + if (actionpoint) { + if (!actionpoint->used) + LOG_WARNING("Target halted by unused actionpoint."); + + /* If this check fails - that is some sort of an error in OpenOCD. */ + if (actionpoint->type != ARC_AP_WATCHPOINT) + LOG_WARNING("Target halted by breakpoint, but is treated as a watchpoint."); + + for (struct watchpoint *watchpoint = target->watchpoints; + watchpoint; + watchpoint = watchpoint->next) { + if (actionpoint->bp_value == watchpoint->address) { + *hit_watchpoint = watchpoint; + LOG_DEBUG("Hit watchpoint, wpid: %" PRIu32 ", watchpoint num: %u", + watchpoint->unique_id, watchpoint->number); + return ERROR_OK; + } + } + } + + return ERROR_FAIL; +} + +/* Helper function which switches core to single_step mode by * doing aux r/w operations. */ int arc_config_step(struct target *target, int enable_step) { @@ -2081,7 +2244,7 @@ struct target_type arcv2_target = { .arch_state = arc_arch_state, - /* TODO That seems like something similiar to metaware hostlink, so perhaps + /* TODO That seems like something similar to metaware hostlink, so perhaps * we can exploit this in the future. */ .target_request_data = NULL, @@ -2106,9 +2269,9 @@ struct target_type arcv2_target = { .add_context_breakpoint = NULL, .add_hybrid_breakpoint = NULL, .remove_breakpoint = arc_remove_breakpoint, - .add_watchpoint = NULL, - .remove_watchpoint = NULL, - .hit_watchpoint = NULL, + .add_watchpoint = arc_add_watchpoint, + .remove_watchpoint = arc_remove_watchpoint, + .hit_watchpoint = arc_hit_watchpoint, .run_algorithm = NULL, .start_algorithm = NULL,