2008-02-25 11:48:04 -06:00
|
|
|
/***************************************************************************
|
|
|
|
* Copyright (C) 2005 by Dominic Rath *
|
|
|
|
* Dominic.Rath@gmx.de *
|
|
|
|
* *
|
2009-10-23 05:38:19 -05:00
|
|
|
* Copyright (C) 2009 by Øyvind Harboe *
|
|
|
|
* oyvind.harboe@zylin.com *
|
|
|
|
* *
|
2008-02-25 11:48:04 -06:00
|
|
|
* 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 *
|
2016-05-16 15:41:00 -05:00
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
2008-02-25 11:48:04 -06:00
|
|
|
***************************************************************************/
|
2012-02-05 06:03:04 -06:00
|
|
|
|
2008-02-25 11:48:04 -06:00
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
#include "config.h"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include "arm720t.h"
|
2009-12-03 06:14:29 -06:00
|
|
|
#include <helper/time_support.h>
|
2009-05-31 07:38:28 -05:00
|
|
|
#include "target_type.h"
|
2009-11-16 02:35:14 -06:00
|
|
|
#include "register.h"
|
2009-12-07 16:54:12 -06:00
|
|
|
#include "arm_opcodes.h"
|
2008-02-25 11:48:04 -06:00
|
|
|
|
|
|
|
|
2009-11-05 22:36:27 -06:00
|
|
|
/*
|
|
|
|
* ARM720 is an ARM7TDMI-S with MMU and ETM7. For information, see
|
|
|
|
* ARM DDI 0229C especially Chapter 9 about debug support.
|
|
|
|
*/
|
|
|
|
|
2008-02-25 11:48:04 -06:00
|
|
|
#if 0
|
|
|
|
#define _DEBUG_INSTRUCTION_EXECUTION_
|
|
|
|
#endif
|
|
|
|
|
2009-11-13 12:11:13 -06:00
|
|
|
static int arm720t_scan_cp15(struct target *target,
|
2010-06-15 16:17:00 -05:00
|
|
|
uint32_t out, uint32_t *in, int instruction, int clock_arg)
|
2008-02-25 11:48:04 -06:00
|
|
|
{
|
2009-11-06 00:03:56 -06:00
|
|
|
int retval;
|
2009-11-13 10:39:57 -06:00
|
|
|
struct arm720t_common *arm720t = target_to_arm720(target);
|
2009-11-13 10:41:00 -06:00
|
|
|
struct arm_jtag *jtag_info;
|
2009-11-13 05:28:03 -06:00
|
|
|
struct scan_field fields[2];
|
2009-06-18 02:04:08 -05:00
|
|
|
uint8_t out_buf[4];
|
|
|
|
uint8_t instruction_buf = instruction;
|
2008-12-13 00:25:50 -06:00
|
|
|
|
2009-11-17 03:09:06 -06:00
|
|
|
jtag_info = &arm720t->arm7_9_common.jtag_info;
|
2009-11-06 00:03:56 -06:00
|
|
|
|
2008-02-25 11:48:04 -06:00
|
|
|
buf_set_u32(out_buf, 0, 32, flip_u32(out, 32));
|
2008-12-13 00:25:50 -06:00
|
|
|
|
2012-02-05 06:03:04 -06:00
|
|
|
retval = arm_jtag_scann(jtag_info, 0xf, TAP_DRPAUSE);
|
|
|
|
if (retval != ERROR_OK)
|
2008-10-14 06:06:30 -05:00
|
|
|
return retval;
|
2015-11-13 17:30:28 -06:00
|
|
|
retval = arm_jtag_set_instr(jtag_info->tap, jtag_info->intest_instr, NULL, TAP_DRPAUSE);
|
2012-02-05 06:03:04 -06:00
|
|
|
if (retval != ERROR_OK)
|
2008-10-14 06:06:30 -05:00
|
|
|
return retval;
|
2008-12-13 00:25:50 -06:00
|
|
|
|
2008-02-25 11:48:04 -06:00
|
|
|
fields[0].num_bits = 1;
|
|
|
|
fields[0].out_value = &instruction_buf;
|
|
|
|
fields[0].in_value = NULL;
|
|
|
|
|
|
|
|
fields[1].num_bits = 32;
|
|
|
|
fields[1].out_value = out_buf;
|
|
|
|
fields[1].in_value = NULL;
|
2009-05-10 14:02:07 -05:00
|
|
|
|
2012-02-05 06:03:04 -06:00
|
|
|
if (in) {
|
2009-06-18 02:04:08 -05:00
|
|
|
fields[1].in_value = (uint8_t *)in;
|
2010-03-16 08:13:03 -05:00
|
|
|
jtag_add_dr_scan(jtag_info->tap, 2, fields, TAP_DRPAUSE);
|
2009-06-19 03:18:36 -05:00
|
|
|
jtag_add_callback(arm7flip32, (jtag_callback_data_t)in);
|
2008-02-25 11:48:04 -06:00
|
|
|
} else
|
2010-03-16 08:13:03 -05:00
|
|
|
jtag_add_dr_scan(jtag_info->tap, 2, fields, TAP_DRPAUSE);
|
2008-02-25 11:48:04 -06:00
|
|
|
|
2010-06-15 16:17:00 -05:00
|
|
|
if (clock_arg)
|
2010-03-16 08:13:03 -05:00
|
|
|
jtag_add_runtest(0, TAP_DRPAUSE);
|
2008-02-25 11:48:04 -06:00
|
|
|
|
|
|
|
#ifdef _DEBUG_INSTRUCTION_EXECUTION_
|
2012-02-05 06:03:04 -06:00
|
|
|
retval = jtag_execute_queue();
|
|
|
|
if (retval != ERROR_OK)
|
2008-10-14 06:06:30 -05:00
|
|
|
return retval;
|
2008-02-25 11:48:04 -06:00
|
|
|
|
|
|
|
if (in)
|
2008-03-25 10:45:17 -05:00
|
|
|
LOG_DEBUG("out: %8.8x, in: %8.8x, instruction: %i, clock: %i", out, *in, instruction, clock);
|
2008-02-25 11:48:04 -06:00
|
|
|
else
|
2010-06-15 16:17:00 -05:00
|
|
|
LOG_DEBUG("out: %8.8x, instruction: %i, clock: %i", out, instruction, clock_arg);
|
2008-02-25 11:48:04 -06:00
|
|
|
#else
|
2010-06-15 16:17:00 -05:00
|
|
|
LOG_DEBUG("out: %8.8" PRIx32 ", instruction: %i, clock: %i", out, instruction, clock_arg);
|
2008-02-25 11:48:04 -06:00
|
|
|
#endif
|
|
|
|
|
|
|
|
return ERROR_OK;
|
|
|
|
}
|
|
|
|
|
2009-11-13 12:11:13 -06:00
|
|
|
static int arm720t_read_cp15(struct target *target, uint32_t opcode, uint32_t *value)
|
2008-02-25 11:48:04 -06:00
|
|
|
{
|
|
|
|
/* fetch CP15 opcode */
|
|
|
|
arm720t_scan_cp15(target, opcode, NULL, 1, 1);
|
|
|
|
/* "DECODE" stage */
|
|
|
|
arm720t_scan_cp15(target, ARMV4_5_NOP, NULL, 1, 1);
|
|
|
|
/* "EXECUTE" stage (1) */
|
|
|
|
arm720t_scan_cp15(target, ARMV4_5_NOP, NULL, 1, 0);
|
|
|
|
arm720t_scan_cp15(target, 0x0, NULL, 0, 1);
|
|
|
|
/* "EXECUTE" stage (2) */
|
|
|
|
arm720t_scan_cp15(target, 0x0, NULL, 0, 1);
|
|
|
|
/* "EXECUTE" stage (3), CDATA is read */
|
|
|
|
arm720t_scan_cp15(target, ARMV4_5_NOP, value, 1, 1);
|
2008-12-13 00:25:50 -06:00
|
|
|
|
2008-02-25 11:48:04 -06:00
|
|
|
return ERROR_OK;
|
|
|
|
}
|
|
|
|
|
2009-11-13 12:11:13 -06:00
|
|
|
static int arm720t_write_cp15(struct target *target, uint32_t opcode, uint32_t value)
|
2008-02-25 11:48:04 -06:00
|
|
|
{
|
|
|
|
/* fetch CP15 opcode */
|
|
|
|
arm720t_scan_cp15(target, opcode, NULL, 1, 1);
|
|
|
|
/* "DECODE" stage */
|
|
|
|
arm720t_scan_cp15(target, ARMV4_5_NOP, NULL, 1, 1);
|
|
|
|
/* "EXECUTE" stage (1) */
|
|
|
|
arm720t_scan_cp15(target, ARMV4_5_NOP, NULL, 1, 0);
|
|
|
|
arm720t_scan_cp15(target, 0x0, NULL, 0, 1);
|
|
|
|
/* "EXECUTE" stage (2) */
|
|
|
|
arm720t_scan_cp15(target, value, NULL, 0, 1);
|
|
|
|
arm720t_scan_cp15(target, ARMV4_5_NOP, NULL, 1, 1);
|
|
|
|
|
|
|
|
return ERROR_OK;
|
|
|
|
}
|
|
|
|
|
2010-07-19 01:45:45 -05:00
|
|
|
static int arm720t_get_ttb(struct target *target, uint32_t *result)
|
2008-02-25 11:48:04 -06:00
|
|
|
{
|
2009-06-18 02:08:52 -05:00
|
|
|
uint32_t ttb = 0x0;
|
2008-02-25 11:48:04 -06:00
|
|
|
|
2010-07-19 01:45:45 -05:00
|
|
|
int retval;
|
|
|
|
|
|
|
|
retval = arm720t_read_cp15(target, 0xee120f10, &ttb);
|
|
|
|
if (retval != ERROR_OK)
|
|
|
|
return retval;
|
|
|
|
retval = jtag_execute_queue();
|
|
|
|
if (retval != ERROR_OK)
|
|
|
|
return retval;
|
2008-12-13 00:25:50 -06:00
|
|
|
|
2008-02-25 11:48:04 -06:00
|
|
|
ttb &= 0xffffc000;
|
2008-12-13 00:25:50 -06:00
|
|
|
|
2010-07-19 01:45:45 -05:00
|
|
|
*result = ttb;
|
|
|
|
|
|
|
|
return ERROR_OK;
|
2008-02-25 11:48:04 -06:00
|
|
|
}
|
|
|
|
|
2010-07-19 03:58:07 -05:00
|
|
|
static int arm720t_disable_mmu_caches(struct target *target,
|
2009-11-05 22:36:27 -06:00
|
|
|
int mmu, int d_u_cache, int i_cache)
|
2008-02-25 11:48:04 -06:00
|
|
|
{
|
2009-06-18 02:08:52 -05:00
|
|
|
uint32_t cp15_control;
|
2010-07-19 03:58:07 -05:00
|
|
|
int retval;
|
2008-02-25 11:48:04 -06:00
|
|
|
|
|
|
|
/* read cp15 control register */
|
2010-07-19 03:58:07 -05:00
|
|
|
retval = arm720t_read_cp15(target, 0xee110f10, &cp15_control);
|
|
|
|
if (retval != ERROR_OK)
|
|
|
|
return retval;
|
|
|
|
retval = jtag_execute_queue();
|
|
|
|
if (retval != ERROR_OK)
|
|
|
|
return retval;
|
2008-12-13 00:25:50 -06:00
|
|
|
|
2008-02-25 11:48:04 -06:00
|
|
|
if (mmu)
|
|
|
|
cp15_control &= ~0x1U;
|
2008-12-13 00:25:50 -06:00
|
|
|
|
2008-02-25 11:48:04 -06:00
|
|
|
if (d_u_cache || i_cache)
|
|
|
|
cp15_control &= ~0x4U;
|
|
|
|
|
2010-07-19 03:58:07 -05:00
|
|
|
retval = arm720t_write_cp15(target, 0xee010f10, cp15_control);
|
|
|
|
return retval;
|
2008-02-25 11:48:04 -06:00
|
|
|
}
|
|
|
|
|
2010-07-19 03:58:07 -05:00
|
|
|
static int arm720t_enable_mmu_caches(struct target *target,
|
2009-11-05 22:36:27 -06:00
|
|
|
int mmu, int d_u_cache, int i_cache)
|
2008-02-25 11:48:04 -06:00
|
|
|
{
|
2009-06-18 02:08:52 -05:00
|
|
|
uint32_t cp15_control;
|
2010-07-19 03:58:07 -05:00
|
|
|
int retval;
|
2008-02-25 11:48:04 -06:00
|
|
|
|
|
|
|
/* read cp15 control register */
|
2010-07-19 03:58:07 -05:00
|
|
|
retval = arm720t_read_cp15(target, 0xee110f10, &cp15_control);
|
|
|
|
if (retval != ERROR_OK)
|
|
|
|
return retval;
|
|
|
|
retval = jtag_execute_queue();
|
|
|
|
if (retval != ERROR_OK)
|
|
|
|
return retval;
|
2008-12-13 00:25:50 -06:00
|
|
|
|
2008-02-25 11:48:04 -06:00
|
|
|
if (mmu)
|
|
|
|
cp15_control |= 0x1U;
|
2008-12-13 00:25:50 -06:00
|
|
|
|
2008-02-25 11:48:04 -06:00
|
|
|
if (d_u_cache || i_cache)
|
|
|
|
cp15_control |= 0x4U;
|
2008-12-13 00:25:50 -06:00
|
|
|
|
2010-07-19 03:58:07 -05:00
|
|
|
retval = arm720t_write_cp15(target, 0xee010f10, cp15_control);
|
|
|
|
return retval;
|
2008-02-25 11:48:04 -06:00
|
|
|
}
|
|
|
|
|
2010-07-19 05:34:54 -05:00
|
|
|
static int arm720t_post_debug_entry(struct target *target)
|
2008-02-25 11:48:04 -06:00
|
|
|
{
|
2009-11-13 10:39:57 -06:00
|
|
|
struct arm720t_common *arm720t = target_to_arm720(target);
|
2010-07-19 05:34:54 -05:00
|
|
|
int retval;
|
2008-12-13 00:25:50 -06:00
|
|
|
|
2008-02-25 11:48:04 -06:00
|
|
|
/* examine cp15 control reg */
|
2010-07-19 05:34:54 -05:00
|
|
|
retval = arm720t_read_cp15(target, 0xee110f10, &arm720t->cp15_control_reg);
|
|
|
|
if (retval != ERROR_OK)
|
|
|
|
return retval;
|
|
|
|
retval = jtag_execute_queue();
|
|
|
|
if (retval != ERROR_OK)
|
|
|
|
return retval;
|
2009-06-20 22:15:03 -05:00
|
|
|
LOG_DEBUG("cp15_control_reg: %8.8" PRIx32 "", arm720t->cp15_control_reg);
|
2008-02-25 11:48:04 -06:00
|
|
|
|
|
|
|
arm720t->armv4_5_mmu.mmu_enabled = (arm720t->cp15_control_reg & 0x1U) ? 1 : 0;
|
|
|
|
arm720t->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled = (arm720t->cp15_control_reg & 0x4U) ? 1 : 0;
|
|
|
|
arm720t->armv4_5_mmu.armv4_5_cache.i_cache_enabled = 0;
|
|
|
|
|
|
|
|
/* save i/d fault status and address register */
|
2010-07-19 05:34:54 -05:00
|
|
|
retval = arm720t_read_cp15(target, 0xee150f10, &arm720t->fsr_reg);
|
|
|
|
if (retval != ERROR_OK)
|
|
|
|
return retval;
|
|
|
|
retval = arm720t_read_cp15(target, 0xee160f10, &arm720t->far_reg);
|
|
|
|
if (retval != ERROR_OK)
|
|
|
|
return retval;
|
|
|
|
retval = jtag_execute_queue();
|
|
|
|
return retval;
|
2008-02-25 11:48:04 -06:00
|
|
|
}
|
|
|
|
|
2009-11-13 12:11:13 -06:00
|
|
|
static void arm720t_pre_restore_context(struct target *target)
|
2008-02-25 11:48:04 -06:00
|
|
|
{
|
2009-11-13 10:39:57 -06:00
|
|
|
struct arm720t_common *arm720t = target_to_arm720(target);
|
2008-12-13 00:25:50 -06:00
|
|
|
|
2008-02-25 11:48:04 -06:00
|
|
|
/* restore i/d fault status and address register */
|
|
|
|
arm720t_write_cp15(target, 0xee050f10, arm720t->fsr_reg);
|
|
|
|
arm720t_write_cp15(target, 0xee060f10, arm720t->far_reg);
|
|
|
|
}
|
|
|
|
|
2009-11-13 12:11:13 -06:00
|
|
|
static int arm720t_arch_state(struct target *target)
|
2008-02-25 11:48:04 -06:00
|
|
|
{
|
2009-11-13 10:39:57 -06:00
|
|
|
struct arm720t_common *arm720t = target_to_arm720(target);
|
2008-12-13 00:25:50 -06:00
|
|
|
|
2012-02-05 06:03:04 -06:00
|
|
|
static const char *state[] = {
|
2008-02-25 11:48:04 -06:00
|
|
|
"disabled", "enabled"
|
|
|
|
};
|
2008-12-13 00:25:50 -06:00
|
|
|
|
2009-12-07 16:55:08 -06:00
|
|
|
arm_arch_state(target);
|
|
|
|
LOG_USER("MMU: %s, Cache: %s",
|
2008-02-25 11:48:04 -06:00
|
|
|
state[arm720t->armv4_5_mmu.mmu_enabled],
|
|
|
|
state[arm720t->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled]);
|
2008-12-13 00:25:50 -06:00
|
|
|
|
2008-02-25 11:48:04 -06:00
|
|
|
return ERROR_OK;
|
|
|
|
}
|
|
|
|
|
2009-11-13 12:11:13 -06:00
|
|
|
static int arm720_mmu(struct target *target, int *enabled)
|
2009-11-10 03:35:50 -06:00
|
|
|
{
|
|
|
|
if (target->state != TARGET_HALTED) {
|
|
|
|
LOG_ERROR("%s: target not halted", __func__);
|
|
|
|
return ERROR_TARGET_INVALID;
|
|
|
|
}
|
|
|
|
|
|
|
|
*enabled = target_to_arm720(target)->armv4_5_mmu.mmu_enabled;
|
|
|
|
return ERROR_OK;
|
|
|
|
}
|
|
|
|
|
2009-11-13 12:11:13 -06:00
|
|
|
static int arm720_virt2phys(struct target *target,
|
2013-09-23 03:27:03 -05:00
|
|
|
target_addr_t virtual, target_addr_t *physical)
|
2009-11-10 03:35:50 -06:00
|
|
|
{
|
2010-02-12 01:39:56 -06:00
|
|
|
uint32_t cb;
|
|
|
|
struct arm720t_common *arm720t = target_to_arm720(target);
|
|
|
|
|
2010-06-10 09:18:14 -05:00
|
|
|
uint32_t ret;
|
2010-06-11 22:58:50 -05:00
|
|
|
int retval = armv4_5_mmu_translate_va(target,
|
2010-06-12 05:35:06 -05:00
|
|
|
&arm720t->armv4_5_mmu, virtual, &cb, &ret);
|
2010-06-10 09:18:14 -05:00
|
|
|
if (retval != ERROR_OK)
|
|
|
|
return retval;
|
2010-02-12 01:39:56 -06:00
|
|
|
*physical = ret;
|
|
|
|
return ERROR_OK;
|
2009-11-10 03:35:50 -06:00
|
|
|
}
|
|
|
|
|
2009-11-13 12:11:13 -06:00
|
|
|
static int arm720t_read_memory(struct target *target,
|
2013-09-23 03:27:03 -05:00
|
|
|
target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer)
|
2008-02-25 11:48:04 -06:00
|
|
|
{
|
|
|
|
int retval;
|
2009-11-13 10:39:57 -06:00
|
|
|
struct arm720t_common *arm720t = target_to_arm720(target);
|
2008-12-13 00:25:50 -06:00
|
|
|
|
2008-02-25 11:48:04 -06:00
|
|
|
/* disable cache, but leave MMU enabled */
|
2012-02-05 06:03:04 -06:00
|
|
|
if (arm720t->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled) {
|
2010-07-19 03:58:07 -05:00
|
|
|
retval = arm720t_disable_mmu_caches(target, 0, 1, 0);
|
|
|
|
if (retval != ERROR_OK)
|
|
|
|
return retval;
|
|
|
|
}
|
2008-02-25 11:48:04 -06:00
|
|
|
retval = arm7_9_read_memory(target, address, size, count, buffer);
|
2008-12-13 00:25:50 -06:00
|
|
|
|
2012-02-05 06:03:04 -06:00
|
|
|
if (arm720t->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled) {
|
2010-07-19 03:58:07 -05:00
|
|
|
retval = arm720t_enable_mmu_caches(target, 0, 1, 0);
|
|
|
|
if (retval != ERROR_OK)
|
|
|
|
return retval;
|
|
|
|
}
|
2008-12-13 00:25:50 -06:00
|
|
|
|
2008-02-25 11:48:04 -06:00
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
2009-11-13 12:11:13 -06:00
|
|
|
static int arm720t_read_phys_memory(struct target *target,
|
2013-09-23 03:27:03 -05:00
|
|
|
target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer)
|
2009-10-21 08:32:29 -05:00
|
|
|
{
|
2009-11-13 10:39:57 -06:00
|
|
|
struct arm720t_common *arm720t = target_to_arm720(target);
|
2009-10-21 08:32:29 -05:00
|
|
|
|
|
|
|
return armv4_5_mmu_read_physical(target, &arm720t->armv4_5_mmu, address, size, count, buffer);
|
|
|
|
}
|
|
|
|
|
2009-11-13 12:11:13 -06:00
|
|
|
static int arm720t_write_phys_memory(struct target *target,
|
2013-09-23 03:27:03 -05:00
|
|
|
target_addr_t address, uint32_t size, uint32_t count, const uint8_t *buffer)
|
2009-10-21 08:32:29 -05:00
|
|
|
{
|
2009-11-13 10:39:57 -06:00
|
|
|
struct arm720t_common *arm720t = target_to_arm720(target);
|
2009-10-21 08:32:29 -05:00
|
|
|
|
|
|
|
return armv4_5_mmu_write_physical(target, &arm720t->armv4_5_mmu, address, size, count, buffer);
|
|
|
|
}
|
|
|
|
|
2009-11-13 12:11:13 -06:00
|
|
|
static int arm720t_soft_reset_halt(struct target *target)
|
2008-02-25 11:48:04 -06:00
|
|
|
{
|
2008-10-14 06:06:30 -05:00
|
|
|
int retval = ERROR_OK;
|
2009-11-13 10:39:57 -06:00
|
|
|
struct arm720t_common *arm720t = target_to_arm720(target);
|
2009-11-17 03:09:06 -06:00
|
|
|
struct reg *dbg_stat = &arm720t->arm7_9_common
|
2009-11-06 00:03:56 -06:00
|
|
|
.eice_cache->reg_list[EICE_DBG_STAT];
|
2012-01-19 04:06:37 -06:00
|
|
|
struct arm *arm = &arm720t->arm7_9_common.arm;
|
2008-12-13 00:25:50 -06:00
|
|
|
|
2012-02-05 06:03:04 -06:00
|
|
|
retval = target_halt(target);
|
|
|
|
if (retval != ERROR_OK)
|
2008-10-14 06:06:30 -05:00
|
|
|
return retval;
|
2008-12-13 00:25:50 -06:00
|
|
|
|
2016-05-21 21:34:04 -05:00
|
|
|
int64_t then = timeval_ms();
|
2008-08-20 02:14:45 -05:00
|
|
|
int timeout;
|
2012-02-05 06:03:04 -06:00
|
|
|
while (!(timeout = ((timeval_ms()-then) > 1000))) {
|
|
|
|
if (buf_get_u32(dbg_stat->value, EICE_DBG_STATUS_DBGACK, 1) == 0) {
|
2008-04-02 01:37:08 -05:00
|
|
|
embeddedice_read_reg(dbg_stat);
|
2012-02-05 06:03:04 -06:00
|
|
|
retval = jtag_execute_queue();
|
|
|
|
if (retval != ERROR_OK)
|
2008-10-14 06:06:30 -05:00
|
|
|
return retval;
|
2008-04-02 01:37:08 -05:00
|
|
|
} else
|
|
|
|
break;
|
2009-06-23 17:40:10 -05:00
|
|
|
if (debug_level >= 3)
|
2008-08-20 02:14:45 -05:00
|
|
|
alive_sleep(100);
|
2012-02-05 06:03:04 -06:00
|
|
|
else
|
2008-08-20 02:14:45 -05:00
|
|
|
keep_alive();
|
2008-04-02 01:37:08 -05:00
|
|
|
}
|
2012-02-05 06:03:04 -06:00
|
|
|
if (timeout) {
|
2008-04-02 01:37:08 -05:00
|
|
|
LOG_ERROR("Failed to halt CPU after 1 sec");
|
|
|
|
return ERROR_TARGET_TIMEOUT;
|
2008-02-25 11:48:04 -06:00
|
|
|
}
|
2008-12-13 00:25:50 -06:00
|
|
|
|
2008-02-25 11:48:04 -06:00
|
|
|
target->state = TARGET_HALTED;
|
2008-12-13 00:25:50 -06:00
|
|
|
|
2008-02-25 11:48:04 -06:00
|
|
|
/* SVC, ARM state, IRQ and FIQ disabled */
|
2009-11-22 05:38:34 -06:00
|
|
|
uint32_t cpsr;
|
|
|
|
|
2012-01-19 04:06:37 -06:00
|
|
|
cpsr = buf_get_u32(arm->cpsr->value, 0, 32);
|
2009-11-22 05:38:34 -06:00
|
|
|
cpsr &= ~0xff;
|
|
|
|
cpsr |= 0xd3;
|
2012-01-19 04:06:37 -06:00
|
|
|
arm_set_cpsr(arm, cpsr);
|
2019-02-26 07:05:22 -06:00
|
|
|
arm->cpsr->dirty = true;
|
2008-12-13 00:25:50 -06:00
|
|
|
|
2008-02-25 11:48:04 -06:00
|
|
|
/* start fetching from 0x0 */
|
2012-01-19 04:06:37 -06:00
|
|
|
buf_set_u32(arm->pc->value, 0, 32, 0x0);
|
2019-02-26 07:05:22 -06:00
|
|
|
arm->pc->dirty = true;
|
|
|
|
arm->pc->valid = true;
|
2008-12-13 00:25:50 -06:00
|
|
|
|
2010-07-19 03:58:07 -05:00
|
|
|
retval = arm720t_disable_mmu_caches(target, 1, 1, 1);
|
|
|
|
if (retval != ERROR_OK)
|
|
|
|
return retval;
|
2008-02-25 11:48:04 -06:00
|
|
|
arm720t->armv4_5_mmu.mmu_enabled = 0;
|
|
|
|
arm720t->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled = 0;
|
|
|
|
arm720t->armv4_5_mmu.armv4_5_cache.i_cache_enabled = 0;
|
|
|
|
|
2012-02-05 06:03:04 -06:00
|
|
|
retval = target_call_event_callbacks(target, TARGET_EVENT_HALTED);
|
|
|
|
if (retval != ERROR_OK)
|
2008-10-14 06:06:30 -05:00
|
|
|
return retval;
|
2008-12-13 00:25:50 -06:00
|
|
|
|
2008-02-25 11:48:04 -06:00
|
|
|
return ERROR_OK;
|
|
|
|
}
|
|
|
|
|
2009-11-13 15:25:47 -06:00
|
|
|
static int arm720t_init_target(struct command_context *cmd_ctx, struct target *target)
|
2008-02-25 11:48:04 -06:00
|
|
|
{
|
2009-11-05 22:36:27 -06:00
|
|
|
return arm7tdmi_init_target(cmd_ctx, target);
|
2008-02-25 11:48:04 -06:00
|
|
|
}
|
|
|
|
|
2020-05-25 04:19:07 -05:00
|
|
|
static void arm720t_deinit_target(struct target *target)
|
|
|
|
{
|
|
|
|
arm7tdmi_deinit_target(target);
|
|
|
|
}
|
|
|
|
|
2009-12-01 02:48:53 -06:00
|
|
|
/* FIXME remove forward decls */
|
|
|
|
static int arm720t_mrc(struct target *target, int cpnum,
|
|
|
|
uint32_t op1, uint32_t op2,
|
|
|
|
uint32_t CRn, uint32_t CRm,
|
|
|
|
uint32_t *value);
|
|
|
|
static int arm720t_mcr(struct target *target, int cpnum,
|
|
|
|
uint32_t op1, uint32_t op2,
|
|
|
|
uint32_t CRn, uint32_t CRm,
|
|
|
|
uint32_t value);
|
|
|
|
|
2009-11-13 12:11:13 -06:00
|
|
|
static int arm720t_init_arch_info(struct target *target,
|
2009-11-13 10:39:57 -06:00
|
|
|
struct arm720t_common *arm720t, struct jtag_tap *tap)
|
2008-02-25 11:48:04 -06:00
|
|
|
{
|
2009-11-17 03:09:06 -06:00
|
|
|
struct arm7_9_common *arm7_9 = &arm720t->arm7_9_common;
|
2008-12-13 00:25:50 -06:00
|
|
|
|
2012-01-19 04:06:37 -06:00
|
|
|
arm7_9->arm.mrc = arm720t_mrc;
|
|
|
|
arm7_9->arm.mcr = arm720t_mcr;
|
2009-12-01 02:48:53 -06:00
|
|
|
|
2009-11-17 03:09:06 -06:00
|
|
|
arm7tdmi_init_arch_info(target, arm7_9, tap);
|
2008-02-25 11:48:04 -06:00
|
|
|
|
|
|
|
arm720t->common_magic = ARM720T_COMMON_MAGIC;
|
2008-12-13 00:25:50 -06:00
|
|
|
|
2008-02-25 11:48:04 -06:00
|
|
|
arm7_9->post_debug_entry = arm720t_post_debug_entry;
|
|
|
|
arm7_9->pre_restore_context = arm720t_pre_restore_context;
|
2008-12-13 00:25:50 -06:00
|
|
|
|
2008-02-25 11:48:04 -06:00
|
|
|
arm720t->armv4_5_mmu.armv4_5_cache.ctype = -1;
|
|
|
|
arm720t->armv4_5_mmu.get_ttb = arm720t_get_ttb;
|
|
|
|
arm720t->armv4_5_mmu.read_memory = arm7_9_read_memory;
|
|
|
|
arm720t->armv4_5_mmu.write_memory = arm7_9_write_memory;
|
|
|
|
arm720t->armv4_5_mmu.disable_mmu_caches = arm720t_disable_mmu_caches;
|
|
|
|
arm720t->armv4_5_mmu.enable_mmu_caches = arm720t_enable_mmu_caches;
|
|
|
|
arm720t->armv4_5_mmu.has_tiny_pages = 0;
|
|
|
|
arm720t->armv4_5_mmu.mmu_enabled = 0;
|
2008-12-13 00:25:50 -06:00
|
|
|
|
2008-02-25 11:48:04 -06:00
|
|
|
return ERROR_OK;
|
|
|
|
}
|
|
|
|
|
2009-11-13 12:11:13 -06:00
|
|
|
static int arm720t_target_create(struct target *target, Jim_Interp *interp)
|
2008-02-25 11:48:04 -06:00
|
|
|
{
|
2009-11-13 10:39:57 -06:00
|
|
|
struct arm720t_common *arm720t = calloc(1, sizeof(*arm720t));
|
2008-12-13 00:25:50 -06:00
|
|
|
|
2012-01-19 04:06:37 -06:00
|
|
|
arm720t->arm7_9_common.arm.is_armv4 = true;
|
2009-11-05 22:36:27 -06:00
|
|
|
return arm720t_init_arch_info(target, arm720t, target->tap);
|
2008-02-25 11:48:04 -06:00
|
|
|
}
|
|
|
|
|
2009-12-07 16:54:12 -06:00
|
|
|
static int arm720t_mrc(struct target *target, int cpnum,
|
|
|
|
uint32_t op1, uint32_t op2,
|
|
|
|
uint32_t CRn, uint32_t CRm,
|
|
|
|
uint32_t *value)
|
2009-10-23 05:38:19 -05:00
|
|
|
{
|
2012-02-05 06:03:04 -06:00
|
|
|
if (cpnum != 15) {
|
2009-10-23 05:38:19 -05:00
|
|
|
LOG_ERROR("Only cp15 is supported");
|
|
|
|
return ERROR_FAIL;
|
|
|
|
}
|
|
|
|
|
2009-12-07 16:54:12 -06:00
|
|
|
/* read "to" r0 */
|
|
|
|
return arm720t_read_cp15(target,
|
|
|
|
ARMV4_5_MRC(cpnum, op1, 0, CRn, CRm, op2),
|
|
|
|
value);
|
2009-10-23 05:38:19 -05:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2009-12-07 16:54:12 -06:00
|
|
|
static int arm720t_mcr(struct target *target, int cpnum,
|
|
|
|
uint32_t op1, uint32_t op2,
|
|
|
|
uint32_t CRn, uint32_t CRm,
|
|
|
|
uint32_t value)
|
2009-10-23 05:38:19 -05:00
|
|
|
{
|
2012-02-05 06:03:04 -06:00
|
|
|
if (cpnum != 15) {
|
2009-10-23 05:38:19 -05:00
|
|
|
LOG_ERROR("Only cp15 is supported");
|
|
|
|
return ERROR_FAIL;
|
|
|
|
}
|
|
|
|
|
2009-12-07 16:54:12 -06:00
|
|
|
/* write "from" r0 */
|
|
|
|
return arm720t_write_cp15(target,
|
|
|
|
ARMV4_5_MCR(cpnum, op1, 0, CRn, CRm, op2),
|
|
|
|
value);
|
2009-10-23 05:38:19 -05:00
|
|
|
}
|
|
|
|
|
2009-11-23 09:43:05 -06:00
|
|
|
static const struct command_registration arm720t_command_handlers[] = {
|
2009-11-23 10:17:01 -06:00
|
|
|
{
|
|
|
|
.chain = arm7_9_command_handlers,
|
|
|
|
},
|
2009-11-23 09:43:05 -06:00
|
|
|
COMMAND_REGISTRATION_DONE
|
|
|
|
};
|
|
|
|
|
2009-11-05 22:36:27 -06:00
|
|
|
/** Holds methods for ARM720 targets. */
|
2012-02-05 06:03:04 -06:00
|
|
|
struct target_type arm720t_target = {
|
2009-11-05 22:36:27 -06:00
|
|
|
.name = "arm720t",
|
|
|
|
|
|
|
|
.poll = arm7_9_poll,
|
|
|
|
.arch_state = arm720t_arch_state,
|
|
|
|
|
|
|
|
.halt = arm7_9_halt,
|
|
|
|
.resume = arm7_9_resume,
|
|
|
|
.step = arm7_9_step,
|
|
|
|
|
|
|
|
.assert_reset = arm7_9_assert_reset,
|
|
|
|
.deassert_reset = arm7_9_deassert_reset,
|
|
|
|
.soft_reset_halt = arm720t_soft_reset_halt,
|
|
|
|
|
target/arm: add support for multi-architecture gdb
GDB can be built for multi-architecture through the command
./configure --enable-targets=all && make
Such multi-architecture GDB requires the target's architecture to
be selected either manually by the user through the GDB command
"set architecture" or automatically by the target description sent
by the remote target (i.e. OpenOCD).
Commit e65acd889c61a424c7bd72fdee5d6a3aee1d8504 ("gdb_server: add
support for architecture element") already provides the required
infrastructure to support multi-architecture gdb.
arm-none-eabi-gdb 8.2 uses "arm" as default architecture, but also
supports the following values: "arm_any", "armv2", "armv2a",
"armv3", "armv3m", "armv4", "armv4t", "armv5", "armv5t", "armv5te",
"armv5tej", "armv6", "armv6k", "armv6kz", "armv6-m", "armv6s-m",
"armv6t2", "armv7", "armv7e-m", "armv8-a", "armv8-m.base",
"armv8-m.main", "armv8-r", "ep9312", "iwmmxt", "iwmmxt2", "xscale".
These values can be displayed on arm gdb prompt by typing
"set architecture " followed by a TAB for autocompletion.
Set the gdb architecture value for all arm targets to "arm".
Change-Id: I176cb89878606e1febd546ce26543b3e7849500a
Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
Reviewed-on: http://openocd.zylin.com/4754
Tested-by: jenkins
Reviewed-by: Spencer Oliver <spen@spen-soft.co.uk>
2018-11-01 08:50:27 -05:00
|
|
|
.get_gdb_arch = arm_get_gdb_arch,
|
2009-12-07 16:54:13 -06:00
|
|
|
.get_gdb_reg_list = arm_get_gdb_reg_list,
|
2009-11-05 22:36:27 -06:00
|
|
|
|
|
|
|
.read_memory = arm720t_read_memory,
|
2013-03-11 16:21:13 -05:00
|
|
|
.write_memory = arm7_9_write_memory_opt,
|
2009-11-05 22:36:27 -06:00
|
|
|
.read_phys_memory = arm720t_read_phys_memory,
|
|
|
|
.write_phys_memory = arm720t_write_phys_memory,
|
2009-11-10 03:35:50 -06:00
|
|
|
.mmu = arm720_mmu,
|
|
|
|
.virt2phys = arm720_virt2phys,
|
|
|
|
|
2009-11-15 12:35:34 -06:00
|
|
|
.checksum_memory = arm_checksum_memory,
|
|
|
|
.blank_check_memory = arm_blank_check_memory,
|
2009-10-23 05:38:19 -05:00
|
|
|
|
2009-11-05 22:36:27 -06:00
|
|
|
.run_algorithm = armv4_5_run_algorithm,
|
|
|
|
|
|
|
|
.add_breakpoint = arm7_9_add_breakpoint,
|
|
|
|
.remove_breakpoint = arm7_9_remove_breakpoint,
|
|
|
|
.add_watchpoint = arm7_9_add_watchpoint,
|
|
|
|
.remove_watchpoint = arm7_9_remove_watchpoint,
|
|
|
|
|
2009-11-23 10:17:01 -06:00
|
|
|
.commands = arm720t_command_handlers,
|
2009-11-05 22:36:27 -06:00
|
|
|
.target_create = arm720t_target_create,
|
|
|
|
.init_target = arm720t_init_target,
|
2020-05-25 04:19:07 -05:00
|
|
|
.deinit_target = arm720t_deinit_target,
|
2009-11-13 18:26:39 -06:00
|
|
|
.examine = arm7_9_examine,
|
2010-01-11 08:30:22 -06:00
|
|
|
.check_reset = arm7_9_check_reset,
|
2009-11-05 22:36:27 -06:00
|
|
|
};
|