X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=blobdiff_plain;f=src%2Ftarget%2Farm7_9_common.c;h=d1e7a93e10c016e9089200acca42c738c1c306ec;hp=19fe98d8d8a2747f4d0dab15be60f88c5c791440;hb=1d9fba8c1488c3774c8bde737c2d658b1f525d09;hpb=dd9894f481d127266c201d7075ecbdd34b034124 diff --git a/src/target/arm7_9_common.c b/src/target/arm7_9_common.c index 19fe98d8d8..d1e7a93e10 100644 --- a/src/target/arm7_9_common.c +++ b/src/target/arm7_9_common.c @@ -2,7 +2,7 @@ * Copyright (C) 2005 by Dominic Rath * * Dominic.Rath@gmx.de * * * - * Copyright (C) 2007,2008 Øyvind Harboe * + * Copyright (C) 2007-2009 Øyvind Harboe * * oyvind.harboe@zylin.com * * * * Copyright (C) 2008 by Spencer Oliver * @@ -11,6 +11,8 @@ * Copyright (C) 2008 by Hongtao Zheng * * hontor@126.com * * * + * Copyright (C) 2009 by David Brownell * + * * * 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 * @@ -34,10 +36,12 @@ #include "embeddedice.h" #include "target_request.h" #include "etm.h" -#include "time_support.h" +#include #include "arm_simulator.h" +#include "arm_semihosting.h" #include "algorithm.h" #include "register.h" +#include "armv4_5.h" /** @@ -426,12 +430,6 @@ int arm7_9_add_breakpoint(struct target *target, struct breakpoint *breakpoint) { struct arm7_9_common *arm7_9 = target_to_arm7_9(target); - if (target->state != TARGET_HALTED) - { - LOG_WARNING("target not halted"); - return ERROR_TARGET_NOT_HALTED; - } - if (arm7_9->breakpoint_count == 0) { /* make sure we don't have any dangling breakpoints. This is vital upon @@ -631,12 +629,6 @@ int arm7_9_add_watchpoint(struct target *target, struct watchpoint *watchpoint) { struct arm7_9_common *arm7_9 = target_to_arm7_9(target); - if (target->state != TARGET_HALTED) - { - LOG_WARNING("target not halted"); - return ERROR_TARGET_NOT_HALTED; - } - if (arm7_9->wp_available < 1) { return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; @@ -899,33 +891,13 @@ int arm7_9_poll(struct target *target) } if ((target->state == TARGET_RUNNING) || (target->state == TARGET_RESET)) { - int check_pc = 0; - if (target->state == TARGET_RESET) - { - if (target->reset_halt) - { - enum reset_types jtag_reset_config = jtag_get_reset_config(); - if ((jtag_reset_config & RESET_SRST_PULLS_TRST) == 0) - { - check_pc = 1; - } - } - } - target->state = TARGET_HALTED; if ((retval = arm7_9_debug_entry(target)) != ERROR_OK) return retval; - if (check_pc) - { - struct reg *reg = register_get_by_name(target->reg_cache, "pc", 1); - uint32_t t=*((uint32_t *)reg->value); - if (t != 0) - { - LOG_ERROR("PC was not 0. Does this target need srst_pulls_trst?"); - } - } + if (arm_semihosting(target, &retval) != 0) + return retval; if ((retval = target_call_event_callbacks(target, TARGET_EVENT_HALTED)) != ERROR_OK) { @@ -971,14 +943,16 @@ int arm7_9_poll(struct target *target) int arm7_9_assert_reset(struct target *target) { struct arm7_9_common *arm7_9 = target_to_arm7_9(target); + enum reset_types jtag_reset_config = jtag_get_reset_config(); + bool use_event = false; LOG_DEBUG("target->state: %s", target_state_name(target)); - enum reset_types jtag_reset_config = jtag_get_reset_config(); - if (!(jtag_reset_config & RESET_HAS_SRST)) - { - LOG_ERROR("Can't assert SRST"); + if (target_has_event_action(target, TARGET_EVENT_RESET_ASSERT)) + use_event = true; + else if (!(jtag_reset_config & RESET_HAS_SRST)) { + LOG_ERROR("%s: how to reset?", target_name(target)); return ERROR_FAIL; } @@ -993,7 +967,8 @@ int arm7_9_assert_reset(struct target *target) */ bool srst_asserted = false; - if (((jtag_reset_config & RESET_SRST_PULLS_TRST) == 0) + if (!use_event + && !(jtag_reset_config & RESET_SRST_PULLS_TRST) && (jtag_reset_config & RESET_SRST_NO_GATING)) { jtag_add_reset(0, 1); @@ -1003,48 +978,70 @@ int arm7_9_assert_reset(struct target *target) if (target->reset_halt) { /* - * Some targets do not support communication while SRST is asserted. We need to - * set up the reset vector catch here. + * For targets that don't support communication while SRST is + * asserted, we need to set up the reset vector catch first. * - * If TRST is asserted, then these settings will be reset anyway, so setting them - * here is harmless. + * When we use TRST+SRST and that's equivalent to a power-up + * reset, these settings may well be reset anyway; so setting + * them here won't matter. */ if (arm7_9->has_vector_catch) { - /* program vector catch register to catch reset vector */ - embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_VEC_CATCH], 0x1); + /* program vector catch register to catch reset */ + embeddedice_write_reg(&arm7_9->eice_cache + ->reg_list[EICE_VEC_CATCH], 0x1); - /* extra runtest added as issues were found with certain ARM9 cores (maybe more) - AT91SAM9260 and STR9 */ + /* extra runtest added as issues were found with + * certain ARM9 cores (maybe more) - AT91SAM9260 + * and STR9 + */ jtag_add_runtest(1, jtag_get_end_state()); } else { - /* program watchpoint unit to match on reset vector address */ - embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_VALUE], 0x0); - embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_MASK], 0x3); - embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_DATA_MASK], 0xffffffff); - embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_VALUE], EICE_W_CTRL_ENABLE); - embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_MASK], ~EICE_W_CTRL_nOPC & 0xff); + /* program watchpoint unit to match on reset vector + * address + */ + embeddedice_write_reg(&arm7_9->eice_cache + ->reg_list[EICE_W0_ADDR_VALUE], 0x0); + embeddedice_write_reg(&arm7_9->eice_cache + ->reg_list[EICE_W0_ADDR_MASK], 0x3); + embeddedice_write_reg(&arm7_9->eice_cache + ->reg_list[EICE_W0_DATA_MASK], + 0xffffffff); + embeddedice_write_reg(&arm7_9->eice_cache + ->reg_list[EICE_W0_CONTROL_VALUE], + EICE_W_CTRL_ENABLE); + embeddedice_write_reg(&arm7_9->eice_cache + ->reg_list[EICE_W0_CONTROL_MASK], + ~EICE_W_CTRL_nOPC & 0xff); } } - /* here we should issue an SRST only, but we may have to assert TRST as well */ - if (jtag_reset_config & RESET_SRST_PULLS_TRST) - { - jtag_add_reset(1, 1); - } else if (!srst_asserted) - { - jtag_add_reset(0, 1); + if (use_event) { + target_handle_event(target, TARGET_EVENT_RESET_ASSERT); + } else { + /* If we use SRST ... we'd like to issue just SRST, but the + * board or chip may be set up so we have to assert TRST as + * well. On some chips that combination is equivalent to a + * power-up reset, and generally clobbers EICE state. + */ + if (jtag_reset_config & RESET_SRST_PULLS_TRST) + jtag_add_reset(1, 1); + else if (!srst_asserted) + jtag_add_reset(0, 1); + jtag_add_sleep(50000); } target->state = TARGET_RESET; - jtag_add_sleep(50000); - register_cache_invalidate(arm7_9->armv4_5_common.core_cache); - if ((target->reset_halt) && ((jtag_reset_config & RESET_SRST_PULLS_TRST) == 0)) + /* REVISIT why isn't standard debug entry logic sufficient?? */ + if (target->reset_halt + && (!(jtag_reset_config & RESET_SRST_PULLS_TRST) + || use_event)) { - /* debug entry was already prepared in arm7_9_assert_reset() */ + /* debug entry was prepared above */ target->debug_reason = DBG_REASON_DBGRQ; } @@ -1160,7 +1157,7 @@ int arm7_9_clear_halt(struct target *target) int arm7_9_soft_reset_halt(struct target *target) { struct arm7_9_common *arm7_9 = target_to_arm7_9(target); - struct armv4_5_common_s *armv4_5 = &arm7_9->armv4_5_common; + struct arm *armv4_5 = &arm7_9->armv4_5_common; struct reg *dbg_stat = &arm7_9->eice_cache->reg_list[EICE_DBG_STAT]; struct reg *dbg_ctrl = &arm7_9->eice_cache->reg_list[EICE_DBG_CTRL]; int i; @@ -1219,7 +1216,7 @@ int arm7_9_soft_reset_halt(struct target *target) uint32_t r0_thumb, pc_thumb; LOG_DEBUG("target entered debug from Thumb state, changing to ARM"); /* Entered debug from Thumb mode */ - armv4_5->core_state = ARMV4_5_STATE_THUMB; + armv4_5->core_state = ARM_STATE_THUMB; arm7_9->change_to_arm(target, &r0_thumb, &pc_thumb); } @@ -1238,16 +1235,18 @@ int arm7_9_soft_reset_halt(struct target *target) armv4_5->cpsr->dirty = 1; /* start fetching from 0x0 */ - buf_set_u32(armv4_5->core_cache->reg_list[15].value, 0, 32, 0x0); - armv4_5->core_cache->reg_list[15].dirty = 1; - armv4_5->core_cache->reg_list[15].valid = 1; + buf_set_u32(armv4_5->pc->value, 0, 32, 0x0); + armv4_5->pc->dirty = 1; + armv4_5->pc->valid = 1; /* reset registers */ for (i = 0; i <= 14; i++) { - buf_set_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, i).value, 0, 32, 0xffffffff); - ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, i).dirty = 1; - ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, i).valid = 1; + struct reg *r = arm_reg_current(armv4_5, i); + + buf_set_u32(r->value, 0, 32, 0xffffffff); + r->dirty = 1; + r->valid = 1; } if ((retval = target_call_event_callbacks(target, TARGET_EVENT_HALTED)) != ERROR_OK) @@ -1338,7 +1337,7 @@ static int arm7_9_debug_entry(struct target *target) uint32_t cpsr, cpsr_mask = 0; int retval; struct arm7_9_common *arm7_9 = target_to_arm7_9(target); - struct armv4_5_common_s *armv4_5 = &arm7_9->armv4_5_common; + struct arm *armv4_5 = &arm7_9->armv4_5_common; struct reg *dbg_stat = &arm7_9->eice_cache->reg_list[EICE_DBG_STAT]; struct reg *dbg_ctrl = &arm7_9->eice_cache->reg_list[EICE_DBG_CTRL]; @@ -1379,7 +1378,7 @@ static int arm7_9_debug_entry(struct target *target) { LOG_DEBUG("target entered debug from Thumb state"); /* Entered debug from Thumb mode */ - armv4_5->core_state = ARMV4_5_STATE_THUMB; + armv4_5->core_state = ARM_STATE_THUMB; cpsr_mask = 1 << 5; arm7_9->change_to_arm(target, &r0_thumb, &pc_thumb); LOG_DEBUG("r0_thumb: 0x%8.8" PRIx32 @@ -1391,13 +1390,13 @@ static int arm7_9_debug_entry(struct target *target) * B.7.3 for the reverse. That'd be the bare minimum... */ LOG_DEBUG("target entered debug from Jazelle state"); - armv4_5->core_state = ARMV4_5_STATE_JAZELLE; + armv4_5->core_state = ARM_STATE_JAZELLE; cpsr_mask = 1 << 24; LOG_ERROR("Jazelle debug entry -- BROKEN!"); } else { LOG_DEBUG("target entered debug from ARM state"); /* Entered debug from ARM mode */ - armv4_5->core_state = ARMV4_5_STATE_ARM; + armv4_5->core_state = ARM_STATE_ARM; } for (i = 0; i < 16; i++) @@ -1425,50 +1424,49 @@ static int arm7_9_debug_entry(struct target *target) LOG_DEBUG("target entered debug state in %s mode", arm_mode_name(armv4_5->core_mode)); - if (armv4_5->core_state == ARMV4_5_STATE_THUMB) + if (armv4_5->core_state == ARM_STATE_THUMB) { LOG_DEBUG("thumb state, applying fixups"); context[0] = r0_thumb; context[15] = pc_thumb; - } else if (armv4_5->core_state == ARMV4_5_STATE_ARM) + } else if (armv4_5->core_state == ARM_STATE_ARM) { /* adjust value stored by STM */ context[15] -= 3 * 4; } if ((target->debug_reason != DBG_REASON_DBGRQ) || (!arm7_9->use_dbgrq)) - context[15] -= 3 * ((armv4_5->core_state == ARMV4_5_STATE_ARM) ? 4 : 2); + context[15] -= 3 * ((armv4_5->core_state == ARM_STATE_ARM) ? 4 : 2); else - context[15] -= arm7_9->dbgreq_adjust_pc * ((armv4_5->core_state == ARMV4_5_STATE_ARM) ? 4 : 2); + context[15] -= arm7_9->dbgreq_adjust_pc * ((armv4_5->core_state == ARM_STATE_ARM) ? 4 : 2); for (i = 0; i <= 15; i++) { + struct reg *r = arm_reg_current(armv4_5, i); + LOG_DEBUG("r%i: 0x%8.8" PRIx32 "", i, context[i]); - buf_set_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, i).value, 0, 32, context[i]); - ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, i).dirty = 0; - ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, i).valid = 1; + + buf_set_u32(r->value, 0, 32, context[i]); + /* r0 and r15 (pc) have to be restored later */ + r->dirty = (i == 0) || (i == 15); + r->valid = 1; } LOG_DEBUG("entered debug state at PC 0x%" PRIx32 "", context[15]); /* exceptions other than USR & SYS have a saved program status register */ - if ((armv4_5->core_mode != ARMV4_5_MODE_USR) && (armv4_5->core_mode != ARMV4_5_MODE_SYS)) - { + if (armv4_5->spsr) { uint32_t spsr; arm7_9->read_xpsr(target, &spsr, 1); if ((retval = jtag_execute_queue()) != ERROR_OK) { return retval; } - buf_set_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 16).value, 0, 32, spsr); - ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 16).dirty = 0; - ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 16).valid = 1; + buf_set_u32(armv4_5->spsr->value, 0, 32, spsr); + armv4_5->spsr->dirty = 0; + armv4_5->spsr->valid = 1; } - /* r0 and r15 (pc) have to be restored later */ - ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 0).dirty = ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 0).valid; - ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 15).dirty = ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 15).valid; - if ((retval = jtag_execute_queue()) != ERROR_OK) return retval; @@ -1492,7 +1490,7 @@ int arm7_9_full_context(struct target *target) int i; int retval; struct arm7_9_common *arm7_9 = target_to_arm7_9(target); - struct armv4_5_common_s *armv4_5 = &arm7_9->armv4_5_common; + struct arm *armv4_5 = &arm7_9->armv4_5_common; LOG_DEBUG("-"); @@ -1586,10 +1584,10 @@ int arm7_9_full_context(struct target *target) int arm7_9_restore_context(struct target *target) { struct arm7_9_common *arm7_9 = target_to_arm7_9(target); - struct armv4_5_common_s *armv4_5 = &arm7_9->armv4_5_common; + struct arm *armv4_5 = &arm7_9->armv4_5_common; struct reg *reg; struct arm_reg *reg_arch_info; - enum armv4_5_mode current_mode = armv4_5->core_mode; + enum arm_mode current_mode = armv4_5->core_mode; int i, j; int dirty; int mode_change; @@ -1629,10 +1627,10 @@ int arm7_9_restore_context(struct target *target) { dirty = 1; LOG_DEBUG("examining dirty reg: %s", reg->name); - if ((reg_arch_info->mode != ARMV4_5_MODE_ANY) + if ((reg_arch_info->mode != ARM_MODE_ANY) && (reg_arch_info->mode != current_mode) - && !((reg_arch_info->mode == ARMV4_5_MODE_USR) && (armv4_5->core_mode == ARMV4_5_MODE_SYS)) - && !((reg_arch_info->mode == ARMV4_5_MODE_SYS) && (armv4_5->core_mode == ARMV4_5_MODE_USR))) + && !((reg_arch_info->mode == ARM_MODE_USR) && (armv4_5->core_mode == ARM_MODE_SYS)) + && !((reg_arch_info->mode == ARM_MODE_SYS) && (armv4_5->core_mode == ARM_MODE_USR))) { mode_change = 1; LOG_DEBUG("require mode change"); @@ -1691,7 +1689,7 @@ int arm7_9_restore_context(struct target *target) reg = &ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_number_to_mode(i), 16); reg_arch_info = reg->arch_info; - if ((reg->dirty) && (reg_arch_info->mode != ARMV4_5_MODE_ANY)) + if ((reg->dirty) && (reg_arch_info->mode != ARM_MODE_ANY)) { LOG_DEBUG("writing SPSR of mode %i with value 0x%8.8" PRIx32 "", i, buf_get_u32(reg->value, 0, 32)); arm7_9->write_xpsr(target, buf_get_u32(reg->value, 0, 32), 1); @@ -1723,12 +1721,10 @@ int arm7_9_restore_context(struct target *target) } /* restore PC */ - LOG_DEBUG("writing PC with value 0x%8.8" PRIx32 "", buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32)); - arm7_9->write_pc(target, buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32)); - armv4_5->core_cache->reg_list[15].dirty = 0; - - if (arm7_9->post_restore_context) - arm7_9->post_restore_context(target); + LOG_DEBUG("writing PC with value 0x%8.8" PRIx32, + buf_get_u32(armv4_5->pc->value, 0, 32)); + arm7_9->write_pc(target, buf_get_u32(armv4_5->pc->value, 0, 32)); + armv4_5->pc->dirty = 0; return ERROR_OK; } @@ -1797,7 +1793,7 @@ void arm7_9_enable_breakpoints(struct target *target) int arm7_9_resume(struct target *target, int current, uint32_t address, int handle_breakpoints, int debug_execution) { struct arm7_9_common *arm7_9 = target_to_arm7_9(target); - struct armv4_5_common_s *armv4_5 = &arm7_9->armv4_5_common; + struct arm *armv4_5 = &arm7_9->armv4_5_common; struct breakpoint *breakpoint = target->breakpoints; struct reg *dbg_ctrl = &arm7_9->eice_cache->reg_list[EICE_DBG_CTRL]; int err, retval = ERROR_OK; @@ -1817,15 +1813,17 @@ int arm7_9_resume(struct target *target, int current, uint32_t address, int hand /* current = 1: continue on current pc, otherwise continue at
*/ if (!current) - buf_set_u32(armv4_5->core_cache->reg_list[15].value, 0, 32, address); + buf_set_u32(armv4_5->pc->value, 0, 32, address); uint32_t current_pc; - current_pc = buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32); + current_pc = buf_get_u32(armv4_5->pc->value, 0, 32); /* the front-end may request us not to handle breakpoints */ if (handle_breakpoints) { - if ((breakpoint = breakpoint_find(target, buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32)))) + breakpoint = breakpoint_find(target, + buf_get_u32(armv4_5->pc->value, 0, 32)); + if (breakpoint != NULL) { LOG_DEBUG("unset breakpoint at 0x%8.8" PRIx32 " (id: %d)", breakpoint->address, breakpoint->unique_id ); if ((retval = arm7_9_unset_breakpoint(target, breakpoint)) != ERROR_OK) @@ -1853,9 +1851,9 @@ int arm7_9_resume(struct target *target, int current, uint32_t address, int hand return retval; } - if (armv4_5->core_state == ARMV4_5_STATE_ARM) + if (armv4_5->core_state == ARM_STATE_ARM) arm7_9->branch_resume(target); - else if (armv4_5->core_state == ARMV4_5_STATE_THUMB) + else if (armv4_5->core_state == ARM_STATE_THUMB) { arm7_9->branch_resume_thumb(target); } @@ -1883,7 +1881,8 @@ int arm7_9_resume(struct target *target, int current, uint32_t address, int hand } arm7_9_debug_entry(target); - LOG_DEBUG("new PC after step: 0x%8.8" PRIx32 "", buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32)); + LOG_DEBUG("new PC after step: 0x%8.8" PRIx32, + buf_get_u32(armv4_5->pc->value, 0, 32)); LOG_DEBUG("set breakpoint at 0x%8.8" PRIx32 "", breakpoint->address); if ((retval = arm7_9_set_breakpoint(target, breakpoint)) != ERROR_OK) @@ -1902,11 +1901,11 @@ int arm7_9_resume(struct target *target, int current, uint32_t address, int hand return retval; } - if (armv4_5->core_state == ARMV4_5_STATE_ARM) + if (armv4_5->core_state == ARM_STATE_ARM) { arm7_9->branch_resume(target); } - else if (armv4_5->core_state == ARMV4_5_STATE_THUMB) + else if (armv4_5->core_state == ARM_STATE_THUMB) { arm7_9->branch_resume_thumb(target); } @@ -1957,9 +1956,9 @@ int arm7_9_resume(struct target *target, int current, uint32_t address, int hand void arm7_9_enable_eice_step(struct target *target, uint32_t next_pc) { struct arm7_9_common *arm7_9 = target_to_arm7_9(target); - struct armv4_5_common_s *armv4_5 = &arm7_9->armv4_5_common; + struct arm *armv4_5 = &arm7_9->armv4_5_common; uint32_t current_pc; - current_pc = buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32); + current_pc = buf_get_u32(armv4_5->pc->value, 0, 32); if (next_pc != current_pc) { @@ -2009,7 +2008,7 @@ void arm7_9_disable_eice_step(struct target *target) int arm7_9_step(struct target *target, int current, uint32_t address, int handle_breakpoints) { struct arm7_9_common *arm7_9 = target_to_arm7_9(target); - struct armv4_5_common_s *armv4_5 = &arm7_9->armv4_5_common; + struct arm *armv4_5 = &arm7_9->armv4_5_common; struct breakpoint *breakpoint = NULL; int err, retval; @@ -2021,18 +2020,18 @@ int arm7_9_step(struct target *target, int current, uint32_t address, int handle /* current = 1: continue on current pc, otherwise continue at
*/ if (!current) - buf_set_u32(armv4_5->core_cache->reg_list[15].value, 0, 32, address); + buf_set_u32(armv4_5->pc->value, 0, 32, address); - uint32_t current_pc; - current_pc = buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32); + uint32_t current_pc = buf_get_u32(armv4_5->pc->value, 0, 32); /* the front-end may request us not to handle breakpoints */ if (handle_breakpoints) - if ((breakpoint = breakpoint_find(target, buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32)))) - if ((retval = arm7_9_unset_breakpoint(target, breakpoint)) != ERROR_OK) - { - return retval; - } + breakpoint = breakpoint_find(target, current_pc); + if (breakpoint != NULL) { + retval = arm7_9_unset_breakpoint(target, breakpoint); + if (retval != ERROR_OK) + return retval; + } target->debug_reason = DBG_REASON_SINGLESTEP; @@ -2053,11 +2052,11 @@ int arm7_9_step(struct target *target, int current, uint32_t address, int handle arm7_9->enable_single_step(target, next_pc); - if (armv4_5->core_state == ARMV4_5_STATE_ARM) + if (armv4_5->core_state == ARM_STATE_ARM) { arm7_9->branch_resume(target); } - else if (armv4_5->core_state == ARMV4_5_STATE_THUMB) + else if (armv4_5->core_state == ARM_STATE_THUMB) { arm7_9->branch_resume_thumb(target); } @@ -2100,23 +2099,23 @@ int arm7_9_step(struct target *target, int current, uint32_t address, int handle } static int arm7_9_read_core_reg(struct target *target, struct reg *r, - int num, enum armv4_5_mode mode) + int num, enum arm_mode mode) { uint32_t* reg_p[16]; uint32_t value; int retval; struct arm_reg *areg = r->arch_info; struct arm7_9_common *arm7_9 = target_to_arm7_9(target); - struct armv4_5_common_s *armv4_5 = &arm7_9->armv4_5_common; + struct arm *armv4_5 = &arm7_9->armv4_5_common; if (!is_arm_mode(armv4_5->core_mode)) return ERROR_FAIL; if ((num < 0) || (num > 16)) return ERROR_INVALID_ARGUMENTS; - if ((mode != ARMV4_5_MODE_ANY) + if ((mode != ARM_MODE_ANY) && (mode != armv4_5->core_mode) - && (areg->mode != ARMV4_5_MODE_ANY)) + && (areg->mode != ARM_MODE_ANY)) { uint32_t tmp_cpsr; @@ -2139,7 +2138,7 @@ static int arm7_9_read_core_reg(struct target *target, struct reg *r, /* read a program status register * if the register mode is MODE_ANY, we read the cpsr, otherwise a spsr */ - arm7_9->read_xpsr(target, &value, areg->mode != ARMV4_5_MODE_ANY); + arm7_9->read_xpsr(target, &value, areg->mode != ARM_MODE_ANY); } if ((retval = jtag_execute_queue()) != ERROR_OK) @@ -2151,9 +2150,9 @@ static int arm7_9_read_core_reg(struct target *target, struct reg *r, r->dirty = 0; buf_set_u32(r->value, 0, 32, value); - if ((mode != ARMV4_5_MODE_ANY) + if ((mode != ARM_MODE_ANY) && (mode != armv4_5->core_mode) - && (areg->mode != ARMV4_5_MODE_ANY)) { + && (areg->mode != ARM_MODE_ANY)) { /* restore processor mode (mask T bit) */ arm7_9->write_xpsr_im8(target, buf_get_u32(armv4_5->cpsr->value, 0, 8) @@ -2164,21 +2163,21 @@ static int arm7_9_read_core_reg(struct target *target, struct reg *r, } static int arm7_9_write_core_reg(struct target *target, struct reg *r, - int num, enum armv4_5_mode mode, uint32_t value) + int num, enum arm_mode mode, uint32_t value) { uint32_t reg[16]; struct arm_reg *areg = r->arch_info; struct arm7_9_common *arm7_9 = target_to_arm7_9(target); - struct armv4_5_common_s *armv4_5 = &arm7_9->armv4_5_common; + struct arm *armv4_5 = &arm7_9->armv4_5_common; if (!is_arm_mode(armv4_5->core_mode)) return ERROR_FAIL; if ((num < 0) || (num > 16)) return ERROR_INVALID_ARGUMENTS; - if ((mode != ARMV4_5_MODE_ANY) + if ((mode != ARM_MODE_ANY) && (mode != armv4_5->core_mode) - && (areg->mode != ARMV4_5_MODE_ANY)) { + && (areg->mode != ARM_MODE_ANY)) { uint32_t tmp_cpsr; /* change processor mode (mask T bit) */ @@ -2200,7 +2199,7 @@ static int arm7_9_write_core_reg(struct target *target, struct reg *r, /* write a program status register * if the register mode is MODE_ANY, we write the cpsr, otherwise a spsr */ - int spsr = (areg->mode != ARMV4_5_MODE_ANY); + int spsr = (areg->mode != ARM_MODE_ANY); /* if we're writing the CPSR, mask the T bit */ if (!spsr) @@ -2212,9 +2211,9 @@ static int arm7_9_write_core_reg(struct target *target, struct reg *r, r->valid = 1; r->dirty = 0; - if ((mode != ARMV4_5_MODE_ANY) + if ((mode != ARM_MODE_ANY) && (mode != armv4_5->core_mode) - && (areg->mode != ARMV4_5_MODE_ANY)) { + && (areg->mode != ARM_MODE_ANY)) { /* restore processor mode (mask T bit) */ arm7_9->write_xpsr_im8(target, buf_get_u32(armv4_5->cpsr->value, 0, 8) @@ -2227,7 +2226,7 @@ static int arm7_9_write_core_reg(struct target *target, struct reg *r, int arm7_9_read_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer) { struct arm7_9_common *arm7_9 = target_to_arm7_9(target); - struct armv4_5_common_s *armv4_5 = &arm7_9->armv4_5_common; + struct arm *armv4_5 = &arm7_9->armv4_5_common; uint32_t reg[16]; uint32_t num_accesses = 0; int thisrun_accesses; @@ -2368,17 +2367,16 @@ int arm7_9_read_memory(struct target *target, uint32_t address, uint32_t size, u } } break; - default: - LOG_ERROR("BUG: we shouldn't get here"); - exit(-1); - break; } if (!is_arm_mode(armv4_5->core_mode)) return ERROR_FAIL; - for (i = 0; i <= last_reg; i++) - ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, i).dirty = ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, i).valid; + for (i = 0; i <= last_reg; i++) { + struct reg *r = arm_reg_current(armv4_5, i); + + r->dirty = r->valid; + } arm7_9->read_xpsr(target, &cpsr, 0); if ((retval = jtag_execute_queue()) != ERROR_OK) @@ -2387,7 +2385,7 @@ int arm7_9_read_memory(struct target *target, uint32_t address, uint32_t size, u return ERROR_TARGET_DATA_ABORT; } - if (((cpsr & 0x1f) == ARMV4_5_MODE_ABT) && (armv4_5->core_mode != ARMV4_5_MODE_ABT)) + if (((cpsr & 0x1f) == ARM_MODE_ABT) && (armv4_5->core_mode != ARM_MODE_ABT)) { LOG_WARNING("memory read caused data abort (address: 0x%8.8" PRIx32 ", size: 0x%" PRIx32 ", count: 0x%" PRIx32 ")", address, size, count); @@ -2404,7 +2402,7 @@ int arm7_9_read_memory(struct target *target, uint32_t address, uint32_t size, u int arm7_9_write_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer) { struct arm7_9_common *arm7_9 = target_to_arm7_9(target); - struct armv4_5_common_s *armv4_5 = &arm7_9->armv4_5_common; + struct arm *armv4_5 = &arm7_9->armv4_5_common; struct reg *dbg_ctrl = &arm7_9->eice_cache->reg_list[EICE_DBG_CTRL]; uint32_t reg[16]; @@ -2549,10 +2547,6 @@ int arm7_9_write_memory(struct target *target, uint32_t address, uint32_t size, num_accesses += thisrun_accesses; } break; - default: - LOG_ERROR("BUG: we shouldn't get here"); - exit(-1); - break; } /* Re-Set DBGACK */ @@ -2562,8 +2556,11 @@ int arm7_9_write_memory(struct target *target, uint32_t address, uint32_t size, if (!is_arm_mode(armv4_5->core_mode)) return ERROR_FAIL; - for (i = 0; i <= last_reg; i++) - ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, i).dirty = ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, i).valid; + for (i = 0; i <= last_reg; i++) { + struct reg *r = arm_reg_current(armv4_5, i); + + r->dirty = r->valid; + } arm7_9->read_xpsr(target, &cpsr, 0); if ((retval = jtag_execute_queue()) != ERROR_OK) @@ -2572,7 +2569,7 @@ int arm7_9_write_memory(struct target *target, uint32_t address, uint32_t size, return ERROR_TARGET_DATA_ABORT; } - if (((cpsr & 0x1f) == ARMV4_5_MODE_ABT) && (armv4_5->core_mode != ARMV4_5_MODE_ABT)) + if (((cpsr & 0x1f) == ARM_MODE_ABT) && (armv4_5->core_mode != ARM_MODE_ABT)) { LOG_WARNING("memory write caused data abort (address: 0x%8.8" PRIx32 ", size: 0x%" PRIx32 ", count: 0x%" PRIx32 ")", address, size, count); @@ -2652,8 +2649,6 @@ static const uint32_t dcc_code[] = 0xeafffff9 /* b w */ }; -int armv4_5_run_algorithm_inner(struct target *target, int num_mem_params, struct mem_param *mem_params, int num_reg_params, struct reg_param *reg_params, uint32_t entry_point, uint32_t exit_point, int timeout_ms, void *arch_info, int (*run_it)(struct target *target, uint32_t exit_point, int timeout_ms, void *arch_info)); - int arm7_9_bulk_write_memory(struct target *target, uint32_t address, uint32_t count, uint8_t *buffer) { int retval; @@ -2688,12 +2683,12 @@ int arm7_9_bulk_write_memory(struct target *target, uint32_t address, uint32_t c } } - struct armv4_5_algorithm armv4_5_info; + struct arm_algorithm armv4_5_info; struct reg_param reg_params[1]; - armv4_5_info.common_magic = ARMV4_5_COMMON_MAGIC; - armv4_5_info.core_mode = ARMV4_5_MODE_SVC; - armv4_5_info.core_state = ARMV4_5_STATE_ARM; + armv4_5_info.common_magic = ARM_COMMON_MAGIC; + armv4_5_info.core_mode = ARM_MODE_SVC; + armv4_5_info.core_state = ARM_STATE_ARM; init_reg_param(®_params[0], "r0", 32, PARAM_IN_OUT); @@ -2702,7 +2697,9 @@ int arm7_9_bulk_write_memory(struct target *target, uint32_t address, uint32_t c dcc_count = count; dcc_buffer = buffer; retval = armv4_5_run_algorithm_inner(target, 0, NULL, 1, reg_params, - arm7_9->dcc_working_area->address, arm7_9->dcc_working_area->address + 6*4, 20*1000, &armv4_5_info, arm7_9_dcc_completion); + arm7_9->dcc_working_area->address, + arm7_9->dcc_working_area->address + 6*4, + 20*1000, &armv4_5_info, arm7_9_dcc_completion); if (retval == ERROR_OK) { @@ -2754,6 +2751,29 @@ int arm7_9_examine(struct target *target) return retval; } + +int arm7_9_check_reset(struct target *target) +{ + struct arm7_9_common *arm7_9 = target_to_arm7_9(target); + + if (get_target_reset_nag() && !arm7_9->dcc_downloads) + { + LOG_WARNING("NOTE! DCC downloads have not been enabled, defaulting to slow memory writes. Type 'help dcc'."); + } + + if (get_target_reset_nag() && (target->working_area_size == 0)) + { + LOG_WARNING("NOTE! Severe performance degradation without working memory enabled."); + } + + if (get_target_reset_nag() && !arm7_9->fast_memory_access) + { + LOG_WARNING("NOTE! Severe performance degradation without fast memory access enabled. Type 'help fast'."); + } + + return ERROR_OK; +} + COMMAND_HANDLER(handle_arm7_9_dbgrq_command) { struct target *target = get_current_target(CMD_CTX); @@ -2811,6 +2831,35 @@ COMMAND_HANDLER(handle_arm7_9_dcc_downloads_command) return ERROR_OK; } +int arm7_9_setup_semihosting(struct target *target, int enable) +{ + struct arm7_9_common *arm7_9 = target_to_arm7_9(target); + + if (!is_arm7_9(arm7_9)) + { + LOG_USER("current target isn't an ARM7/ARM9 target"); + return ERROR_TARGET_INVALID; + } + + if (arm7_9->has_vector_catch) { + struct reg *vector_catch = &arm7_9->eice_cache + ->reg_list[EICE_VEC_CATCH]; + + if (!vector_catch->valid) + embeddedice_read_reg(vector_catch); + buf_set_u32(vector_catch->value, 2, 1, enable); + embeddedice_store_reg(vector_catch); + } else { + /* TODO: allow optional high vectors and/or BKPT_HARD */ + if (enable) + breakpoint_add(target, 8, 4, BKPT_SOFT); + else + breakpoint_remove(target, 8); + } + + return ERROR_OK; +} + int arm7_9_init_arch_info(struct target *target, struct arm7_9_common *arm7_9) { int retval = ERROR_OK; @@ -2832,36 +2881,54 @@ int arm7_9_init_arch_info(struct target *target, struct arm7_9_common *arm7_9) armv4_5->read_core_reg = arm7_9_read_core_reg; armv4_5->write_core_reg = arm7_9_write_core_reg; armv4_5->full_context = arm7_9_full_context; + armv4_5->setup_semihosting = arm7_9_setup_semihosting; - if ((retval = armv4_5_init_arch_info(target, armv4_5)) != ERROR_OK) + retval = arm_init_arch_info(target, armv4_5); + if (retval != ERROR_OK) return retval; return target_register_timer_callback(arm7_9_handle_target_request, 1, 1, target); } -int arm7_9_register_commands(struct command_context *cmd_ctx) -{ - struct command *arm7_9_cmd; - - arm7_9_cmd = register_command(cmd_ctx, NULL, "arm7_9", - NULL, COMMAND_ANY, "arm7/9 specific commands"); - - register_command(cmd_ctx, arm7_9_cmd, "dbgrq", - handle_arm7_9_dbgrq_command, COMMAND_ANY, - "use EmbeddedICE dbgrq instead of breakpoint " - "for target halt requests "); - register_command(cmd_ctx, arm7_9_cmd, "fast_memory_access", - handle_arm7_9_fast_memory_access_command, COMMAND_ANY, - "use fast memory accesses instead of slower " - "but potentially safer accesses "); - register_command(cmd_ctx, arm7_9_cmd, "dcc_downloads", - handle_arm7_9_dcc_downloads_command, COMMAND_ANY, - "use DCC downloads for larger memory writes "); - - armv4_5_register_commands(cmd_ctx); - - etm_register_commands(cmd_ctx); - - return ERROR_OK; -} +static const struct command_registration arm7_9_any_command_handlers[] = { + { + "dbgrq", + .handler = handle_arm7_9_dbgrq_command, + .mode = COMMAND_ANY, + .usage = "['enable'|'disable']", + .help = "use EmbeddedICE dbgrq instead of breakpoint " + "for target halt requests", + }, + { + "fast_memory_access", + .handler = handle_arm7_9_fast_memory_access_command, + .mode = COMMAND_ANY, + .usage = "['enable'|'disable']", + .help = "use fast memory accesses instead of slower " + "but potentially safer accesses", + }, + { + "dcc_downloads", + .handler = handle_arm7_9_dcc_downloads_command, + .mode = COMMAND_ANY, + .usage = "['enable'|'disable']", + .help = "use DCC downloads for larger memory writes", + }, + COMMAND_REGISTRATION_DONE +}; +const struct command_registration arm7_9_command_handlers[] = { + { + .chain = arm_command_handlers, + }, + { + .chain = etm_command_handlers, + }, + { + .name = "arm7_9", + .mode = COMMAND_ANY, + .help = "arm7/9 specific commands", + .chain = arm7_9_any_command_handlers, + }, + COMMAND_REGISTRATION_DONE +};