+// SPDX-License-Identifier: GPL-2.0-or-later
+
/***************************************************************************
* Copyright (C) 2008 digenius technology GmbH. *
* Michael Bruck *
* Copyright (C) 2008 Georg Acher <acher@in.tum.de> *
* *
* Copyright (C) 2009 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 *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program; if not, write to the *
- * Free Software Foundation, Inc., *
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#ifdef HAVE_CONFIG_H
static int arm11_step(struct target *target, int current,
- uint32_t address, int handle_breakpoints);
+ target_addr_t address, int handle_breakpoints);
/** Check and if necessary take control of the system
*/
static int arm11_check_init(struct arm11_common *arm11)
{
- CHECK_RETVAL(arm11_read_DSCR(arm11));
+ CHECK_RETVAL(arm11_read_dscr(arm11));
if (!(arm11->dscr & DSCR_HALT_DBG_MODE)) {
LOG_DEBUG("DSCR %08x", (unsigned) arm11->dscr);
LOG_DEBUG("Bringing target into debug mode");
arm11->dscr |= DSCR_HALT_DBG_MODE;
- CHECK_RETVAL(arm11_write_DSCR(arm11, arm11->dscr));
+ CHECK_RETVAL(arm11_write_dscr(arm11, arm11->dscr));
/* add further reset initialization here */
/* maybe save wDTR (pending DCC write to debug SW, e.g. libdcc) */
arm11->is_wdtr_saved = !!(arm11->dscr & DSCR_DTR_TX_FULL);
if (arm11->is_wdtr_saved) {
- arm11_add_debug_SCAN_N(arm11, 0x05, ARM11_TAP_DEFAULT);
+ arm11_add_debug_scan_n(arm11, 0x05, ARM11_TAP_DEFAULT);
- arm11_add_IR(arm11, ARM11_INTEST, ARM11_TAP_DEFAULT);
+ arm11_add_ir(arm11, ARM11_INTEST, ARM11_TAP_DEFAULT);
struct scan_field chain5_fields[3];
* but not to issue ITRs(?). The ARMv7 arch spec says it's required
* for executing instructions via ITR.
*/
- CHECK_RETVAL(arm11_write_DSCR(arm11, DSCR_ITR_EN | arm11->dscr));
+ CHECK_RETVAL(arm11_write_dscr(arm11, DSCR_ITR_EN | arm11->dscr));
/* From the spec:
/* mcr 15, 0, r0, cr7, cr10, {4} */
arm11_run_instr_no_data1(arm11, 0xee070f9a);
- uint32_t dscr = arm11_read_DSCR(arm11);
+ uint32_t dscr = arm11_read_dscr(arm11);
LOG_DEBUG("DRAIN, DSCR %08x", dscr);
if (dscr & ARM11_DSCR_STICKY_IMPRECISE_DATA_ABORT) {
arm11_run_instr_no_data1(arm11, 0xe320f000);
- dscr = arm11_read_DSCR(arm11);
+ dscr = arm11_read_dscr(arm11);
LOG_DEBUG("DRAIN, DSCR %08x (DONE)", dscr);
/* spec says clear wDTR and rDTR; we assume they are clear as
otherwise our programming would be sloppy */
{
- CHECK_RETVAL(arm11_read_DSCR(arm11));
+ CHECK_RETVAL(arm11_read_dscr(arm11));
if (arm11->dscr & (DSCR_DTR_RX_FULL | DSCR_DTR_TX_FULL)) {
/*
register_cache_invalidate(arm11->arm.core_cache);
/* restore DSCR */
- CHECK_RETVAL(arm11_write_DSCR(arm11, arm11->dscr));
+ CHECK_RETVAL(arm11_write_dscr(arm11, arm11->dscr));
/* maybe restore rDTR */
if (arm11->is_rdtr_saved) {
- arm11_add_debug_SCAN_N(arm11, 0x05, ARM11_TAP_DEFAULT);
+ arm11_add_debug_scan_n(arm11, 0x05, ARM11_TAP_DEFAULT);
- arm11_add_IR(arm11, ARM11_EXTEST, ARM11_TAP_DEFAULT);
+ arm11_add_ir(arm11, ARM11_EXTEST, ARM11_TAP_DEFAULT);
struct scan_field chain5_fields[3];
- uint8_t Ready = 0; /* ignored */
- uint8_t Valid = 0; /* ignored */
+ uint8_t ready = 0; /* ignored */
+ uint8_t valid = 0; /* ignored */
arm11_setup_field(arm11, 32, &arm11->saved_rdtr,
NULL, chain5_fields + 0);
- arm11_setup_field(arm11, 1, &Ready, NULL, chain5_fields + 1);
- arm11_setup_field(arm11, 1, &Valid, NULL, chain5_fields + 2);
+ arm11_setup_field(arm11, 1, &ready, NULL, chain5_fields + 1);
+ arm11_setup_field(arm11, 1, &valid, NULL, chain5_fields + 2);
arm11_add_dr_scan_vc(arm11->arm.target->tap, ARRAY_SIZE(
chain5_fields), chain5_fields, TAP_DRPAUSE);
/* REVISIT also display ARM11-specific MMU and cache status ... */
if (target->debug_reason == DBG_REASON_WATCHPOINT)
- LOG_USER("Watchpoint triggered at PC %#08x",
- (unsigned) arm11->dpm.wp_pc);
+ LOG_USER("Watchpoint triggered at PC " TARGET_ADDR_FMT, arm11->dpm.wp_addr);
return retval;
}
-/* target request support */
-static int arm11_target_request_data(struct target *target,
- uint32_t size, uint8_t *buffer)
-{
- LOG_WARNING("Not implemented: %s", __func__);
-
- return ERROR_FAIL;
-}
-
/* target execution control */
static int arm11_halt(struct target *target)
{
return ERROR_OK;
}
- arm11_add_IR(arm11, ARM11_HALT, TAP_IDLE);
+ arm11_add_ir(arm11, ARM11_HALT, TAP_IDLE);
CHECK_RETVAL(jtag_execute_queue());
int i = 0;
while (1) {
- CHECK_RETVAL(arm11_read_DSCR(arm11));
+ CHECK_RETVAL(arm11_read_dscr(arm11));
if (arm11->dscr & DSCR_CORE_HALTED)
break;
- long long then = 0;
+ int64_t then = 0;
if (i == 1000)
then = timeval_ms();
if (i >= 1000) {
{
void *value = arm11->arm.pc->value;
- if (!current)
- buf_set_u32(value, 0, 32, address);
- else
+ /* use the current program counter */
+ if (current)
address = buf_get_u32(value, 0, 32);
+ /* Make sure that the gdb thumb fixup does not
+ * kill the return address
+ */
+ switch (arm11->arm.core_state) {
+ case ARM_STATE_ARM:
+ address &= 0xFFFFFFFC;
+ break;
+ case ARM_STATE_THUMB:
+ /* When the return address is loaded into PC
+ * bit 0 must be 1 to stay in Thumb state
+ */
+ address |= 0x1;
+ break;
+
+ /* catch-all for JAZELLE and THUMB_EE */
+ default:
+ break;
+ }
+
+ buf_set_u32(value, 0, 32, address);
+ arm11->arm.pc->dirty = true;
+ arm11->arm.pc->valid = true;
+
return address;
}
static int arm11_resume(struct target *target, int current,
- uint32_t address, int handle_breakpoints, int debug_execution)
+ target_addr_t address, int handle_breakpoints, int debug_execution)
{
/* LOG_DEBUG("current %d address %08x handle_breakpoints %d debug_execution %d", */
/* current, address, handle_breakpoints, debug_execution); */
if (target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
+ LOG_TARGET_ERROR(target, "not halted");
return ERROR_TARGET_NOT_HALTED;
}
address = arm11_nextpc(arm11, current, address);
- LOG_DEBUG("RESUME PC %08" PRIx32 "%s", address, !current ? "!" : "");
+ LOG_DEBUG("RESUME PC %08" TARGET_PRIxADDR "%s", address, !current ? "!" : "");
/* clear breakpoints/watchpoints and VCR*/
CHECK_RETVAL(arm11_sc7_clear_vbw(arm11));
for (bp = target->breakpoints; bp; bp = bp->next) {
if (bp->address == address) {
- LOG_DEBUG("must step over %08" PRIx32 "", bp->address);
+ LOG_DEBUG("must step over %08" TARGET_PRIxADDR "", bp->address);
arm11_step(target, 1, 0, 0);
break;
}
CHECK_RETVAL(arm11_sc7_run(arm11, brp, ARRAY_SIZE(brp)));
- LOG_DEBUG("Add BP %d at %08" PRIx32, brp_num,
+ LOG_DEBUG("Add BP %d at %08" TARGET_PRIxADDR, brp_num,
bp->address);
brp_num++;
/* activate all watchpoints and breakpoints */
CHECK_RETVAL(arm11_leave_debug_state(arm11, true));
- arm11_add_IR(arm11, ARM11_RESTART, TAP_IDLE);
+ arm11_add_ir(arm11, ARM11_RESTART, TAP_IDLE);
CHECK_RETVAL(jtag_execute_queue());
int i = 0;
while (1) {
- CHECK_RETVAL(arm11_read_DSCR(arm11));
+ CHECK_RETVAL(arm11_read_dscr(arm11));
LOG_DEBUG("DSCR %08x", (unsigned) arm11->dscr);
break;
- long long then = 0;
+ int64_t then = 0;
if (i == 1000)
then = timeval_ms();
if (i >= 1000) {
}
static int arm11_step(struct target *target, int current,
- uint32_t address, int handle_breakpoints)
+ target_addr_t address, int handle_breakpoints)
{
LOG_DEBUG("target->state: %s",
target_state_name(target));
if (target->state != TARGET_HALTED) {
- LOG_WARNING("target was not halted");
+ LOG_TARGET_ERROR(target, "not halted");
return ERROR_TARGET_NOT_HALTED;
}
address = arm11_nextpc(arm11, current, address);
- LOG_DEBUG("STEP PC %08" PRIx32 "%s", address, !current ? "!" : "");
+ LOG_DEBUG("STEP PC %08" TARGET_PRIxADDR "%s", address, !current ? "!" : "");
/** \todo TODO: Thumb not supported here */
/* skip over BKPT */
if ((next_instruction & 0xFFF00070) == 0xe1200070) {
address = arm11_nextpc(arm11, 0, address + 4);
- LOG_DEBUG("Skipping BKPT %08" PRIx32, address);
+ LOG_DEBUG("Skipping BKPT %08" TARGET_PRIxADDR, address);
}
/* skip over Wait for interrupt / Standby
* mcr 15, 0, r?, cr7, cr0, {4} */
else if ((next_instruction & 0xFFFF0FFF) == 0xee070f90) {
address = arm11_nextpc(arm11, 0, address + 4);
- LOG_DEBUG("Skipping WFI %08" PRIx32, address);
+ LOG_DEBUG("Skipping WFI %08" TARGET_PRIxADDR, address);
}
/* ignore B to self */
else if ((next_instruction & 0xFEFFFFFF) == 0xeafffffe)
CHECK_RETVAL(arm11_leave_debug_state(arm11, handle_breakpoints));
- arm11_add_IR(arm11, ARM11_RESTART, TAP_IDLE);
+ arm11_add_ir(arm11, ARM11_RESTART, TAP_IDLE);
CHECK_RETVAL(jtag_execute_queue());
const uint32_t mask = DSCR_CORE_RESTARTED
| DSCR_CORE_HALTED;
- CHECK_RETVAL(arm11_read_DSCR(arm11));
+ CHECK_RETVAL(arm11_read_dscr(arm11));
LOG_DEBUG("DSCR %08x e", (unsigned) arm11->dscr);
if ((arm11->dscr & mask) == mask)
{
struct arm11_common *arm11 = target_to_arm11(target);
- /* optionally catch reset vector */
- if (target->reset_halt && !(arm11->vcr & 1))
- CHECK_RETVAL(arm11_sc7_set_vcr(arm11, arm11->vcr | 1));
-
- /* Issue some kind of warm reset. */
- if (target_has_event_action(target, TARGET_EVENT_RESET_ASSERT))
- target_handle_event(target, TARGET_EVENT_RESET_ASSERT);
- else if (jtag_get_reset_config() & RESET_HAS_SRST) {
- /* REVISIT handle "pulls" cases, if there's
- * hardware that needs them to work.
- */
- jtag_add_reset(0, 1);
+ if (!(target_was_examined(target))) {
+ if (jtag_get_reset_config() & RESET_HAS_SRST)
+ jtag_add_reset(0, 1);
+ else {
+ LOG_WARNING("Reset is not asserted because the target is not examined.");
+ LOG_WARNING("Use a reset button or power cycle the target.");
+ return ERROR_TARGET_NOT_EXAMINED;
+ }
} else {
- LOG_ERROR("%s: how to reset?", target_name(target));
- return ERROR_FAIL;
+
+ /* optionally catch reset vector */
+ if (target->reset_halt && !(arm11->vcr & 1))
+ CHECK_RETVAL(arm11_sc7_set_vcr(arm11, arm11->vcr | 1));
+
+ /* Issue some kind of warm reset. */
+ if (target_has_event_action(target, TARGET_EVENT_RESET_ASSERT))
+ target_handle_event(target, TARGET_EVENT_RESET_ASSERT);
+ else if (jtag_get_reset_config() & RESET_HAS_SRST) {
+ /* REVISIT handle "pulls" cases, if there's
+ * hardware that needs them to work.
+ */
+ jtag_add_reset(0, 1);
+ } else {
+ LOG_ERROR("%s: how to reset?", target_name(target));
+ return ERROR_FAIL;
+ }
}
/* registers are now invalid */
return ERROR_OK;
}
-static int arm11_soft_reset_halt(struct target *target)
-{
- LOG_WARNING("Not implemented: %s", __func__);
-
- return ERROR_FAIL;
-}
-
/* target memory access
* size: 1 = byte (8bit), 2 = half-word (16bit), 4 = word (32bit)
* count: number of items of <size>
int retval;
if (target->state != TARGET_HALTED) {
- LOG_WARNING("target was not halted");
+ LOG_TARGET_ERROR(target, "not halted");
return ERROR_TARGET_NOT_HALTED;
}
}
static int arm11_read_memory(struct target *target,
- uint32_t address,
+ target_addr_t address,
uint32_t size,
uint32_t count,
uint8_t *buffer)
int retval;
if (target->state != TARGET_HALTED) {
- LOG_WARNING("target was not halted");
+ LOG_TARGET_ERROR(target, "not halted");
return ERROR_TARGET_NOT_HALTED;
}
}
static int arm11_write_memory(struct target *target,
- uint32_t address, uint32_t size,
+ target_addr_t address, uint32_t size,
uint32_t count, const uint8_t *buffer)
{
/* pointer increment matters only for multi-unit writes ...
count, buffer, count == 1);
}
-/* write target memory in multiples of 4 byte, optimized for writing large quantities of data */
-static int arm11_bulk_write_memory(struct target *target,
- uint32_t address, uint32_t count, const uint8_t *buffer)
-{
- if (target->state != TARGET_HALTED) {
- LOG_WARNING("target was not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- return arm11_write_memory(target, address, 4, count, buffer);
-}
-
/* target break-/watchpoint control
* rw: 0 = write, 1 = read, 2 = access
*/
{
struct arm11_common *arm11;
- if (target->tap == NULL)
+ if (!target->tap)
return ERROR_FAIL;
if (target->tap->ir_length != 5) {
return ERROR_COMMAND_SYNTAX_ERROR;
}
- arm11 = calloc(1, sizeof *arm11);
+ arm11 = calloc(1, sizeof(*arm11));
if (!arm11)
return ERROR_FAIL;
+ arm11->arm.core_type = ARM_CORE_TYPE_STD;
arm_init_arch_info(target, &arm11->arm);
arm11->jtag_info.tap = target->tap;
return ERROR_OK;
}
+static void arm11_deinit_target(struct target *target)
+{
+ struct arm11_common *arm11 = target_to_arm11(target);
+
+ arm11_dpm_deinit(arm11);
+ free(arm11);
+}
+
/* talk to the target and set things up */
static int arm11_examine(struct target *target)
{
/* check IDCODE */
- arm11_add_IR(arm11, ARM11_IDCODE, ARM11_TAP_DEFAULT);
+ arm11_add_ir(arm11, ARM11_IDCODE, ARM11_TAP_DEFAULT);
struct scan_field idcode_field;
/* check DIDR */
- arm11_add_debug_SCAN_N(arm11, 0x00, ARM11_TAP_DEFAULT);
+ arm11_add_debug_scan_n(arm11, 0x00, ARM11_TAP_DEFAULT);
- arm11_add_IR(arm11, ARM11_INTEST, ARM11_TAP_DEFAULT);
+ arm11_add_ir(arm11, ARM11_INTEST, ARM11_TAP_DEFAULT);
struct scan_field chain0_fields[2];
type = "ARM1156";
break;
case 0x7B76:
- arm11->arm.core_type = ARM_MODE_MON;
+ arm11->arm.core_type = ARM_CORE_TYPE_SEC_EXT;
/* NOTE: could default arm11->hardware_step to true */
type = "ARM1176";
break;
LOG_DEBUG("IDCODE %08" PRIx32 " IMPLEMENTOR %02x DIDR %08" PRIx32,
device_id, implementor, didr);
+ /* Build register cache "late", after target_init(), since we
+ * want to know if this core supports Secure Monitor mode.
+ */
+ if (!target_was_examined(target))
+ CHECK_RETVAL(arm11_dpm_init(arm11, didr));
+
/* as a side-effect this reads DSCR and thus
* clears the ARM11_DSCR_STICKY_PRECISE_DATA_ABORT / Sticky Precise Data Abort Flag
* as suggested by the spec.
if (retval != ERROR_OK)
return retval;
- /* Build register cache "late", after target_init(), since we
- * want to know if this core supports Secure Monitor mode.
- */
- if (!target_was_examined(target))
- CHECK_RETVAL(arm11_dpm_init(arm11, didr));
-
/* ETM on ARM11 still uses original scanchain 6 access mode */
if (arm11->arm.etm && !target_was_examined(target)) {
*register_get_last_cache_p(&target->reg_cache) =
.poll = arm11_poll,
.arch_state = arm11_arch_state,
- .target_request_data = arm11_target_request_data,
-
.halt = arm11_halt,
.resume = arm11_resume,
.step = arm11_step,
.assert_reset = arm11_assert_reset,
.deassert_reset = arm11_deassert_reset,
- .soft_reset_halt = arm11_soft_reset_halt,
+ .get_gdb_arch = arm_get_gdb_arch,
.get_gdb_reg_list = arm_get_gdb_reg_list,
.read_memory = arm11_read_memory,
.write_memory = arm11_write_memory,
- .bulk_write_memory = arm11_bulk_write_memory,
-
.checksum_memory = arm_checksum_memory,
.blank_check_memory = arm_blank_check_memory,
.commands = arm11_command_handlers,
.target_create = arm11_target_create,
.init_target = arm11_init_target,
+ .deinit_target = arm11_deinit_target,
.examine = arm11_examine,
};