build: cleanup src/target directory
Change-Id: Ia055b6d2b5f6449a38afd0539a8c66e7d7e0c059 Signed-off-by: Spencer Oliver <spen@spen-soft.co.uk> Reviewed-on: http://openocd.zylin.com/430 Tested-by: jenkins
This commit is contained in:
parent
de0130a0aa
commit
374127301e
|
@ -40,7 +40,6 @@
|
||||||
#include "arm_adi_v5.h"
|
#include "arm_adi_v5.h"
|
||||||
#include <helper/time_support.h>
|
#include <helper/time_support.h>
|
||||||
|
|
||||||
|
|
||||||
/* JTAG instructions/registers for JTAG-DP and SWJ-DP */
|
/* JTAG instructions/registers for JTAG-DP and SWJ-DP */
|
||||||
#define JTAG_DP_ABORT 0x8
|
#define JTAG_DP_ABORT 0x8
|
||||||
#define JTAG_DP_DPACC 0xA
|
#define JTAG_DP_DPACC 0xA
|
||||||
|
@ -223,22 +222,19 @@ static int jtagdp_transaction_endcheck(struct adiv5_dap *dap)
|
||||||
DP_CTRL_STAT, DPAP_READ, 0, &ctrlstat);
|
DP_CTRL_STAT, DPAP_READ, 0, &ctrlstat);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
if ((retval = jtag_execute_queue()) != ERROR_OK)
|
retval = jtag_execute_queue();
|
||||||
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
dap->ack = dap->ack & 0x7;
|
dap->ack = dap->ack & 0x7;
|
||||||
|
|
||||||
/* common code path avoids calling timeval_ms() */
|
/* common code path avoids calling timeval_ms() */
|
||||||
if (dap->ack != JTAG_ACK_OK_FAULT)
|
if (dap->ack != JTAG_ACK_OK_FAULT) {
|
||||||
{
|
|
||||||
long long then = timeval_ms();
|
long long then = timeval_ms();
|
||||||
|
|
||||||
while (dap->ack != JTAG_ACK_OK_FAULT)
|
while (dap->ack != JTAG_ACK_OK_FAULT) {
|
||||||
{
|
if (dap->ack == JTAG_ACK_WAIT) {
|
||||||
if (dap->ack == JTAG_ACK_WAIT)
|
if ((timeval_ms()-then) > 1000) {
|
||||||
{
|
|
||||||
if ((timeval_ms()-then) > 1000)
|
|
||||||
{
|
|
||||||
/* NOTE: this would be a good spot
|
/* NOTE: this would be a good spot
|
||||||
* to use JTAG_DP_ABORT.
|
* to use JTAG_DP_ABORT.
|
||||||
*/
|
*/
|
||||||
|
@ -247,9 +243,7 @@ static int jtagdp_transaction_endcheck(struct adiv5_dap *dap)
|
||||||
"in JTAG-DP transaction");
|
"in JTAG-DP transaction");
|
||||||
return ERROR_JTAG_DEVICE_ERROR;
|
return ERROR_JTAG_DEVICE_ERROR;
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
LOG_WARNING("Invalid ACK %#x "
|
LOG_WARNING("Invalid ACK %#x "
|
||||||
"in JTAG-DP transaction",
|
"in JTAG-DP transaction",
|
||||||
dap->ack);
|
dap->ack);
|
||||||
|
@ -260,7 +254,8 @@ static int jtagdp_transaction_endcheck(struct adiv5_dap *dap)
|
||||||
DP_CTRL_STAT, DPAP_READ, 0, &ctrlstat);
|
DP_CTRL_STAT, DPAP_READ, 0, &ctrlstat);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
if ((retval = dap_run(dap)) != ERROR_OK)
|
retval = dap_run(dap);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
dap->ack = dap->ack & 0x7;
|
dap->ack = dap->ack & 0x7;
|
||||||
}
|
}
|
||||||
|
@ -269,18 +264,14 @@ static int jtagdp_transaction_endcheck(struct adiv5_dap *dap)
|
||||||
/* REVISIT also STICKYCMP, for pushed comparisons (nyet used) */
|
/* REVISIT also STICKYCMP, for pushed comparisons (nyet used) */
|
||||||
|
|
||||||
/* Check for STICKYERR and STICKYORUN */
|
/* Check for STICKYERR and STICKYORUN */
|
||||||
if (ctrlstat & (SSTICKYORUN | SSTICKYERR))
|
if (ctrlstat & (SSTICKYORUN | SSTICKYERR)) {
|
||||||
{
|
|
||||||
LOG_DEBUG("jtag-dp: CTRL/STAT error, 0x%" PRIx32, ctrlstat);
|
LOG_DEBUG("jtag-dp: CTRL/STAT error, 0x%" PRIx32, ctrlstat);
|
||||||
/* Check power to debug regions */
|
/* Check power to debug regions */
|
||||||
if ((ctrlstat & 0xf0000000) != 0xf0000000)
|
if ((ctrlstat & 0xf0000000) != 0xf0000000) {
|
||||||
{
|
|
||||||
retval = ahbap_debugport_init(dap);
|
retval = ahbap_debugport_init(dap);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
uint32_t mem_ap_csw, mem_ap_tar;
|
uint32_t mem_ap_csw, mem_ap_tar;
|
||||||
|
|
||||||
/* Maybe print information about last intended
|
/* Maybe print information about last intended
|
||||||
|
@ -314,7 +305,8 @@ static int jtagdp_transaction_endcheck(struct adiv5_dap *dap)
|
||||||
DP_CTRL_STAT, DPAP_READ, 0, &ctrlstat);
|
DP_CTRL_STAT, DPAP_READ, 0, &ctrlstat);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
if ((retval = dap_run(dap)) != ERROR_OK)
|
retval = dap_run(dap);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
LOG_DEBUG("jtag-dp: CTRL/STAT 0x%" PRIx32, ctrlstat);
|
LOG_DEBUG("jtag-dp: CTRL/STAT 0x%" PRIx32, ctrlstat);
|
||||||
|
@ -329,13 +321,15 @@ static int jtagdp_transaction_endcheck(struct adiv5_dap *dap)
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
if ((retval = dap_run(dap)) != ERROR_OK)
|
retval = dap_run(dap);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
LOG_ERROR("MEM_AP_CSW 0x%" PRIx32 ", MEM_AP_TAR 0x%"
|
LOG_ERROR("MEM_AP_CSW 0x%" PRIx32 ", MEM_AP_TAR 0x%"
|
||||||
PRIx32, mem_ap_csw, mem_ap_tar);
|
PRIx32, mem_ap_csw, mem_ap_tar);
|
||||||
|
|
||||||
}
|
}
|
||||||
if ((retval = dap_run(dap)) != ERROR_OK)
|
retval = dap_run(dap);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
return ERROR_JTAG_DEVICE_ERROR;
|
return ERROR_JTAG_DEVICE_ERROR;
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,12 +55,10 @@
|
||||||
|
|
||||||
#include <jtag/swd.h>
|
#include <jtag/swd.h>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static int swd_queue_dp_read(struct adiv5_dap *dap, unsigned reg,
|
static int swd_queue_dp_read(struct adiv5_dap *dap, unsigned reg,
|
||||||
uint32_t *data)
|
uint32_t *data)
|
||||||
{
|
{
|
||||||
// REVISIT status return vs ack ...
|
/* REVISIT status return vs ack ... */
|
||||||
return swd->read_reg(swd_cmd(true, false, reg), data);
|
return swd->read_reg(swd_cmd(true, false, reg), data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,14 +69,14 @@ static int swd_queue_idcode_read(struct adiv5_dap *dap,
|
||||||
if (status < 0)
|
if (status < 0)
|
||||||
return status;
|
return status;
|
||||||
*ack = status;
|
*ack = status;
|
||||||
// ??
|
/* ?? */
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int (swd_queue_dp_write)(struct adiv5_dap *dap, unsigned reg,
|
static int (swd_queue_dp_write)(struct adiv5_dap *dap, unsigned reg,
|
||||||
uint32_t data)
|
uint32_t data)
|
||||||
{
|
{
|
||||||
// REVISIT status return vs ack ...
|
/* REVISIT status return vs ack ... */
|
||||||
return swd->write_reg(swd_cmd(false, false, reg), data);
|
return swd->write_reg(swd_cmd(false, false, reg), data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,16 +84,16 @@ static int (swd_queue_dp_write)(struct adiv5_dap *dap, unsigned reg,
|
||||||
static int (swd_queue_ap_read)(struct adiv5_dap *dap, unsigned reg,
|
static int (swd_queue_ap_read)(struct adiv5_dap *dap, unsigned reg,
|
||||||
uint32_t *data)
|
uint32_t *data)
|
||||||
{
|
{
|
||||||
// REVISIT APSEL ...
|
/* REVISIT APSEL ... */
|
||||||
// REVISIT status return ...
|
/* REVISIT status return ... */
|
||||||
return swd->read_reg(swd_cmd(true, true, reg), data);
|
return swd->read_reg(swd_cmd(true, true, reg), data);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int (swd_queue_ap_write)(struct adiv5_dap *dap, unsigned reg,
|
static int (swd_queue_ap_write)(struct adiv5_dap *dap, unsigned reg,
|
||||||
uint32_t data)
|
uint32_t data)
|
||||||
{
|
{
|
||||||
// REVISIT APSEL ...
|
/* REVISIT APSEL ... */
|
||||||
// REVISIT status return ...
|
/* REVISIT status return ... */
|
||||||
return swd->write_reg(swd_cmd(false, true, reg), data);
|
return swd->write_reg(swd_cmd(false, true, reg), data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -194,15 +192,14 @@ COMMAND_HANDLER(handle_swd_wcr)
|
||||||
int retval;
|
int retval;
|
||||||
struct target *target = get_current_target(CMD_CTX);
|
struct target *target = get_current_target(CMD_CTX);
|
||||||
struct arm *arm = target_to_arm(target);
|
struct arm *arm = target_to_arm(target);
|
||||||
struct adiv5_dap *dap = arm->dap;
|
struct adiv5_dap *dap = arm->dap;
|
||||||
uint32_t wcr;
|
uint32_t wcr;
|
||||||
unsigned trn, scale = 0;
|
unsigned trn, scale = 0;
|
||||||
|
|
||||||
|
|
||||||
switch (CMD_ARGC) {
|
switch (CMD_ARGC) {
|
||||||
/* no-args: just dump state */
|
/* no-args: just dump state */
|
||||||
case 0:
|
case 0:
|
||||||
//retval = swd_queue_dp_read(dap, DP_WCR, &wcr);
|
/*retval = swd_queue_dp_read(dap, DP_WCR, &wcr); */
|
||||||
retval = dap_queue_dp_read(dap, DP_WCR, &wcr);
|
retval = dap_queue_dp_read(dap, DP_WCR, &wcr);
|
||||||
if (retval == ERROR_OK)
|
if (retval == ERROR_OK)
|
||||||
dap->ops->run(dap);
|
dap->ops->run(dap);
|
||||||
|
@ -315,11 +312,10 @@ static int swd_init(struct command_context *ctx)
|
||||||
{
|
{
|
||||||
struct target *target = get_current_target(ctx);
|
struct target *target = get_current_target(ctx);
|
||||||
struct arm *arm = target_to_arm(target);
|
struct arm *arm = target_to_arm(target);
|
||||||
struct adiv5_dap *dap = arm->dap;
|
struct adiv5_dap *dap = arm->dap;
|
||||||
uint32_t idcode;
|
uint32_t idcode;
|
||||||
int status;
|
int status;
|
||||||
|
|
||||||
|
|
||||||
/* FIXME validate transport config ... is the
|
/* FIXME validate transport config ... is the
|
||||||
* configured DAP present (check IDCODE)?
|
* configured DAP present (check IDCODE)?
|
||||||
* Is *only* one DAP configured?
|
* Is *only* one DAP configured?
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
* Free Software Foundation, Inc., *
|
* Free Software Foundation, Inc., *
|
||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -24,7 +25,6 @@
|
||||||
#include "algorithm.h"
|
#include "algorithm.h"
|
||||||
#include <helper/binarybuffer.h>
|
#include <helper/binarybuffer.h>
|
||||||
|
|
||||||
|
|
||||||
void init_mem_param(struct mem_param *param, uint32_t address, uint32_t size, enum param_direction direction)
|
void init_mem_param(struct mem_param *param, uint32_t address, uint32_t size, enum param_direction direction)
|
||||||
{
|
{
|
||||||
param->address = address;
|
param->address = address;
|
||||||
|
|
|
@ -17,26 +17,24 @@
|
||||||
* Free Software Foundation, Inc., *
|
* Free Software Foundation, Inc., *
|
||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#ifndef ALGORITHM_H
|
#ifndef ALGORITHM_H
|
||||||
#define ALGORITHM_H
|
#define ALGORITHM_H
|
||||||
|
|
||||||
enum param_direction
|
enum param_direction {
|
||||||
{
|
|
||||||
PARAM_IN,
|
PARAM_IN,
|
||||||
PARAM_OUT,
|
PARAM_OUT,
|
||||||
PARAM_IN_OUT
|
PARAM_IN_OUT
|
||||||
};
|
};
|
||||||
|
|
||||||
struct mem_param
|
struct mem_param {
|
||||||
{
|
|
||||||
uint32_t address;
|
uint32_t address;
|
||||||
uint32_t size;
|
uint32_t size;
|
||||||
uint8_t *value;
|
uint8_t *value;
|
||||||
enum param_direction direction;
|
enum param_direction direction;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct reg_param
|
struct reg_param {
|
||||||
{
|
|
||||||
const char *reg_name;
|
const char *reg_name;
|
||||||
uint32_t size;
|
uint32_t size;
|
||||||
uint8_t *value;
|
uint8_t *value;
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
* Free Software Foundation, Inc.,
|
* Free Software Foundation, Inc.,
|
||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef ARM_H
|
#ifndef ARM_H
|
||||||
#define ARM_H
|
#define ARM_H
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -26,38 +26,36 @@
|
||||||
#include "arm.h"
|
#include "arm.h"
|
||||||
#include "arm_dpm.h"
|
#include "arm_dpm.h"
|
||||||
|
|
||||||
#define ARM11_TAP_DEFAULT TAP_INVALID
|
#define ARM11_TAP_DEFAULT TAP_INVALID
|
||||||
|
|
||||||
#define CHECK_RETVAL(action) \
|
#define CHECK_RETVAL(action) \
|
||||||
do { \
|
do { \
|
||||||
int __retval = (action); \
|
int __retval = (action); \
|
||||||
if (__retval != ERROR_OK) { \
|
if (__retval != ERROR_OK) { \
|
||||||
LOG_DEBUG("error while calling \"%s\"", \
|
LOG_DEBUG("error while calling \"%s\"", \
|
||||||
# action ); \
|
# action); \
|
||||||
return __retval; \
|
return __retval; \
|
||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
/* bits from ARMv7 DIDR */
|
/* bits from ARMv7 DIDR */
|
||||||
enum arm11_debug_version
|
enum arm11_debug_version {
|
||||||
{
|
ARM11_DEBUG_V6 = 0x01,
|
||||||
ARM11_DEBUG_V6 = 0x01,
|
ARM11_DEBUG_V61 = 0x02,
|
||||||
ARM11_DEBUG_V61 = 0x02,
|
ARM11_DEBUG_V7 = 0x03,
|
||||||
ARM11_DEBUG_V7 = 0x03,
|
ARM11_DEBUG_V7_CP14 = 0x04,
|
||||||
ARM11_DEBUG_V7_CP14 = 0x04,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct arm11_common
|
struct arm11_common {
|
||||||
{
|
struct arm arm;
|
||||||
struct arm arm;
|
|
||||||
|
|
||||||
/** Debug module state. */
|
/** Debug module state. */
|
||||||
struct arm_dpm dpm;
|
struct arm_dpm dpm;
|
||||||
struct arm11_sc7_action *bpwp_actions;
|
struct arm11_sc7_action *bpwp_actions;
|
||||||
unsigned bpwp_n;
|
unsigned bpwp_n;
|
||||||
|
|
||||||
size_t brp; /**< Number of Breakpoint Register Pairs from DIDR */
|
size_t brp; /**< Number of Breakpoint Register Pairs from DIDR */
|
||||||
size_t free_brps; /**< Number of breakpoints allocated */
|
size_t free_brps; /**< Number of breakpoints allocated */
|
||||||
|
|
||||||
uint32_t dscr; /**< Last retrieved DSCR value. */
|
uint32_t dscr; /**< Last retrieved DSCR value. */
|
||||||
|
|
||||||
|
@ -67,7 +65,7 @@ struct arm11_common
|
||||||
bool is_rdtr_saved;
|
bool is_rdtr_saved;
|
||||||
bool is_wdtr_saved;
|
bool is_wdtr_saved;
|
||||||
|
|
||||||
bool simulate_reset_on_next_halt; /**< Perform cleanups of the ARM state on next halt */
|
bool simulate_reset_on_next_halt; /**< Perform cleanups of the ARM state on next halt **/
|
||||||
|
|
||||||
/* Per-core configurable options.
|
/* Per-core configurable options.
|
||||||
* NOTE that several of these boolean options should not exist
|
* NOTE that several of these boolean options should not exist
|
||||||
|
@ -86,8 +84,7 @@ struct arm11_common
|
||||||
|
|
||||||
static inline struct arm11_common *target_to_arm11(struct target *target)
|
static inline struct arm11_common *target_to_arm11(struct target *target)
|
||||||
{
|
{
|
||||||
return container_of(target->arch_info, struct arm11_common,
|
return container_of(target->arch_info, struct arm11_common, arm);
|
||||||
arm);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -95,27 +92,25 @@ static inline struct arm11_common *target_to_arm11(struct target *target)
|
||||||
*
|
*
|
||||||
* http://infocenter.arm.com/help/topic/com.arm.doc.ddi0301f/I1006229.html
|
* http://infocenter.arm.com/help/topic/com.arm.doc.ddi0301f/I1006229.html
|
||||||
*/
|
*/
|
||||||
enum arm11_instructions
|
enum arm11_instructions {
|
||||||
{
|
|
||||||
ARM11_EXTEST = 0x00,
|
ARM11_EXTEST = 0x00,
|
||||||
ARM11_SCAN_N = 0x02,
|
ARM11_SCAN_N = 0x02,
|
||||||
ARM11_RESTART = 0x04,
|
ARM11_RESTART = 0x04,
|
||||||
ARM11_HALT = 0x08,
|
ARM11_HALT = 0x08,
|
||||||
ARM11_INTEST = 0x0C,
|
ARM11_INTEST = 0x0C,
|
||||||
ARM11_ITRSEL = 0x1D,
|
ARM11_ITRSEL = 0x1D,
|
||||||
ARM11_IDCODE = 0x1E,
|
ARM11_IDCODE = 0x1E,
|
||||||
ARM11_BYPASS = 0x1F,
|
ARM11_BYPASS = 0x1F,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum arm11_sc7
|
enum arm11_sc7 {
|
||||||
{
|
ARM11_SC7_NULL = 0,
|
||||||
ARM11_SC7_NULL = 0,
|
ARM11_SC7_VCR = 7,
|
||||||
ARM11_SC7_VCR = 7,
|
ARM11_SC7_PC = 8,
|
||||||
ARM11_SC7_PC = 8,
|
ARM11_SC7_BVR0 = 64,
|
||||||
ARM11_SC7_BVR0 = 64,
|
ARM11_SC7_BCR0 = 80,
|
||||||
ARM11_SC7_BCR0 = 80,
|
ARM11_SC7_WVR0 = 96,
|
||||||
ARM11_SC7_WVR0 = 96,
|
ARM11_SC7_WCR0 = 112,
|
||||||
ARM11_SC7_WCR0 = 112,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* ARM11_H */
|
#endif /* ARM11_H */
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,3 +1,25 @@
|
||||||
|
/***************************************************************************
|
||||||
|
* Copyright (C) 2008 digenius technology GmbH. *
|
||||||
|
* Michael Bruck *
|
||||||
|
* *
|
||||||
|
* Copyright (C) 2008,2009 Oyvind Harboe oyvind.harboe@zylin.com *
|
||||||
|
* *
|
||||||
|
* 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. *
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
#ifndef ARM11_DBGTAP_H
|
#ifndef ARM11_DBGTAP_H
|
||||||
#define ARM11_DBGTAP_H
|
#define ARM11_DBGTAP_H
|
||||||
|
|
||||||
|
@ -37,10 +59,9 @@ void arm11_add_dr_scan_vc(struct jtag_tap *tap, int num_fields, struct scan_fiel
|
||||||
* Used with arm11_sc7_run to make a list of read/write commands for
|
* Used with arm11_sc7_run to make a list of read/write commands for
|
||||||
* scan chain 7
|
* scan chain 7
|
||||||
*/
|
*/
|
||||||
struct arm11_sc7_action
|
struct arm11_sc7_action {
|
||||||
{
|
bool write; /**< Access mode: true for write, false for read. */
|
||||||
bool write; /**< Access mode: true for write, false for read. */
|
uint8_t address;/**< Register address mode. Use enum #arm11_sc7 */
|
||||||
uint8_t address; /**< Register address mode. Use enum #arm11_sc7 */
|
|
||||||
/**
|
/**
|
||||||
* If write then set this to value to be written. In read mode
|
* If write then set this to value to be written. In read mode
|
||||||
* this receives the read value when the function returns.
|
* this receives the read value when the function returns.
|
||||||
|
@ -61,4 +82,4 @@ int arm11_read_memory_word(struct arm11_common *arm11,
|
||||||
int arm11_dpm_init(struct arm11_common *arm11, uint32_t didr);
|
int arm11_dpm_init(struct arm11_common *arm11, uint32_t didr);
|
||||||
int arm11_bpwp_flush(struct arm11_common *arm11);
|
int arm11_bpwp_flush(struct arm11_common *arm11);
|
||||||
|
|
||||||
#endif // ARM11_DBGTAP_H
|
#endif /* ARM11_DBGTAP_H */
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
* Free Software Foundation, Inc., *
|
* Free Software Foundation, Inc., *
|
||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -54,14 +55,12 @@ static int arm720t_scan_cp15(struct target *target,
|
||||||
|
|
||||||
buf_set_u32(out_buf, 0, 32, flip_u32(out, 32));
|
buf_set_u32(out_buf, 0, 32, flip_u32(out, 32));
|
||||||
|
|
||||||
if ((retval = arm_jtag_scann(jtag_info, 0xf, TAP_DRPAUSE)) != ERROR_OK)
|
retval = arm_jtag_scann(jtag_info, 0xf, TAP_DRPAUSE);
|
||||||
{
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
retval = arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL, TAP_DRPAUSE);
|
||||||
if ((retval = arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL, TAP_DRPAUSE)) != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
{
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
|
||||||
|
|
||||||
fields[0].num_bits = 1;
|
fields[0].num_bits = 1;
|
||||||
fields[0].out_value = &instruction_buf;
|
fields[0].out_value = &instruction_buf;
|
||||||
|
@ -71,24 +70,20 @@ static int arm720t_scan_cp15(struct target *target,
|
||||||
fields[1].out_value = out_buf;
|
fields[1].out_value = out_buf;
|
||||||
fields[1].in_value = NULL;
|
fields[1].in_value = NULL;
|
||||||
|
|
||||||
if (in)
|
if (in) {
|
||||||
{
|
|
||||||
fields[1].in_value = (uint8_t *)in;
|
fields[1].in_value = (uint8_t *)in;
|
||||||
jtag_add_dr_scan(jtag_info->tap, 2, fields, TAP_DRPAUSE);
|
jtag_add_dr_scan(jtag_info->tap, 2, fields, TAP_DRPAUSE);
|
||||||
jtag_add_callback(arm7flip32, (jtag_callback_data_t)in);
|
jtag_add_callback(arm7flip32, (jtag_callback_data_t)in);
|
||||||
} else
|
} else
|
||||||
{
|
|
||||||
jtag_add_dr_scan(jtag_info->tap, 2, fields, TAP_DRPAUSE);
|
jtag_add_dr_scan(jtag_info->tap, 2, fields, TAP_DRPAUSE);
|
||||||
}
|
|
||||||
|
|
||||||
if (clock_arg)
|
if (clock_arg)
|
||||||
jtag_add_runtest(0, TAP_DRPAUSE);
|
jtag_add_runtest(0, TAP_DRPAUSE);
|
||||||
|
|
||||||
#ifdef _DEBUG_INSTRUCTION_EXECUTION_
|
#ifdef _DEBUG_INSTRUCTION_EXECUTION_
|
||||||
if ((retval = jtag_execute_queue()) != ERROR_OK)
|
retval = jtag_execute_queue();
|
||||||
{
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
|
||||||
|
|
||||||
if (in)
|
if (in)
|
||||||
LOG_DEBUG("out: %8.8x, in: %8.8x, instruction: %i, clock: %i", out, *in, instruction, clock);
|
LOG_DEBUG("out: %8.8x, in: %8.8x, instruction: %i, clock: %i", out, *in, instruction, clock);
|
||||||
|
@ -254,8 +249,7 @@ static int arm720t_arch_state(struct target *target)
|
||||||
{
|
{
|
||||||
struct arm720t_common *arm720t = target_to_arm720(target);
|
struct arm720t_common *arm720t = target_to_arm720(target);
|
||||||
|
|
||||||
static const char *state[] =
|
static const char *state[] = {
|
||||||
{
|
|
||||||
"disabled", "enabled"
|
"disabled", "enabled"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -300,16 +294,14 @@ static int arm720t_read_memory(struct target *target,
|
||||||
struct arm720t_common *arm720t = target_to_arm720(target);
|
struct arm720t_common *arm720t = target_to_arm720(target);
|
||||||
|
|
||||||
/* disable cache, but leave MMU enabled */
|
/* disable cache, but leave MMU enabled */
|
||||||
if (arm720t->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled)
|
if (arm720t->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled) {
|
||||||
{
|
|
||||||
retval = arm720t_disable_mmu_caches(target, 0, 1, 0);
|
retval = arm720t_disable_mmu_caches(target, 0, 1, 0);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
retval = arm7_9_read_memory(target, address, size, count, buffer);
|
retval = arm7_9_read_memory(target, address, size, count, buffer);
|
||||||
|
|
||||||
if (arm720t->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled)
|
if (arm720t->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled) {
|
||||||
{
|
|
||||||
retval = arm720t_enable_mmu_caches(target, 0, 1, 0);
|
retval = arm720t_enable_mmu_caches(target, 0, 1, 0);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
@ -342,36 +334,26 @@ static int arm720t_soft_reset_halt(struct target *target)
|
||||||
.eice_cache->reg_list[EICE_DBG_STAT];
|
.eice_cache->reg_list[EICE_DBG_STAT];
|
||||||
struct arm *arm = &arm720t->arm7_9_common.arm;
|
struct arm *arm = &arm720t->arm7_9_common.arm;
|
||||||
|
|
||||||
if ((retval = target_halt(target)) != ERROR_OK)
|
retval = target_halt(target);
|
||||||
{
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
|
||||||
|
|
||||||
long long then = timeval_ms();
|
long long then = timeval_ms();
|
||||||
int timeout;
|
int timeout;
|
||||||
while (!(timeout = ((timeval_ms()-then) > 1000)))
|
while (!(timeout = ((timeval_ms()-then) > 1000))) {
|
||||||
{
|
if (buf_get_u32(dbg_stat->value, EICE_DBG_STATUS_DBGACK, 1) == 0) {
|
||||||
if (buf_get_u32(dbg_stat->value, EICE_DBG_STATUS_DBGACK, 1) == 0)
|
|
||||||
{
|
|
||||||
embeddedice_read_reg(dbg_stat);
|
embeddedice_read_reg(dbg_stat);
|
||||||
if ((retval = jtag_execute_queue()) != ERROR_OK)
|
retval = jtag_execute_queue();
|
||||||
{
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
|
||||||
} else
|
} else
|
||||||
{
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
if (debug_level >= 3)
|
if (debug_level >= 3)
|
||||||
{
|
|
||||||
alive_sleep(100);
|
alive_sleep(100);
|
||||||
} else
|
else
|
||||||
{
|
|
||||||
keep_alive();
|
keep_alive();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (timeout)
|
if (timeout) {
|
||||||
{
|
|
||||||
LOG_ERROR("Failed to halt CPU after 1 sec");
|
LOG_ERROR("Failed to halt CPU after 1 sec");
|
||||||
return ERROR_TARGET_TIMEOUT;
|
return ERROR_TARGET_TIMEOUT;
|
||||||
}
|
}
|
||||||
|
@ -399,10 +381,9 @@ static int arm720t_soft_reset_halt(struct target *target)
|
||||||
arm720t->armv4_5_mmu.armv4_5_cache.d_u_cache_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;
|
arm720t->armv4_5_mmu.armv4_5_cache.i_cache_enabled = 0;
|
||||||
|
|
||||||
if ((retval = target_call_event_callbacks(target, TARGET_EVENT_HALTED)) != ERROR_OK)
|
retval = target_call_event_callbacks(target, TARGET_EVENT_HALTED);
|
||||||
{
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
@ -467,42 +448,35 @@ COMMAND_HANDLER(arm720t_handle_cp15_command)
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
|
if (target->state != TARGET_HALTED) {
|
||||||
if (target->state != TARGET_HALTED)
|
|
||||||
{
|
|
||||||
command_print(CMD_CTX, "target must be stopped for \"%s\" command", CMD_NAME);
|
command_print(CMD_CTX, "target must be stopped for \"%s\" command", CMD_NAME);
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* one or more argument, access a single register (write if second argument is given */
|
/* one or more argument, access a single register (write if second argument is given */
|
||||||
if (CMD_ARGC >= 1)
|
if (CMD_ARGC >= 1) {
|
||||||
{
|
|
||||||
uint32_t opcode;
|
uint32_t opcode;
|
||||||
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], opcode);
|
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], opcode);
|
||||||
|
|
||||||
if (CMD_ARGC == 1)
|
if (CMD_ARGC == 1) {
|
||||||
{
|
|
||||||
uint32_t value;
|
uint32_t value;
|
||||||
if ((retval = arm720t_read_cp15(target, opcode, &value)) != ERROR_OK)
|
retval = arm720t_read_cp15(target, opcode, &value);
|
||||||
{
|
if (retval != ERROR_OK) {
|
||||||
command_print(CMD_CTX, "couldn't access cp15 with opcode 0x%8.8" PRIx32 "", opcode);
|
command_print(CMD_CTX, "couldn't access cp15 with opcode 0x%8.8" PRIx32 "", opcode);
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((retval = jtag_execute_queue()) != ERROR_OK)
|
retval = jtag_execute_queue();
|
||||||
{
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
|
||||||
|
|
||||||
command_print(CMD_CTX, "0x%8.8" PRIx32 ": 0x%8.8" PRIx32 "", opcode, value);
|
command_print(CMD_CTX, "0x%8.8" PRIx32 ": 0x%8.8" PRIx32 "", opcode, value);
|
||||||
}
|
} else if (CMD_ARGC == 2) {
|
||||||
else if (CMD_ARGC == 2)
|
|
||||||
{
|
|
||||||
uint32_t value;
|
uint32_t value;
|
||||||
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], value);
|
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], value);
|
||||||
|
|
||||||
if ((retval = arm720t_write_cp15(target, opcode, value)) != ERROR_OK)
|
retval = arm720t_write_cp15(target, opcode, value);
|
||||||
{
|
if (retval != ERROR_OK) {
|
||||||
command_print(CMD_CTX, "couldn't access cp15 with opcode 0x%8.8" PRIx32 "", opcode);
|
command_print(CMD_CTX, "couldn't access cp15 with opcode 0x%8.8" PRIx32 "", opcode);
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
@ -518,8 +492,7 @@ static int arm720t_mrc(struct target *target, int cpnum,
|
||||||
uint32_t CRn, uint32_t CRm,
|
uint32_t CRn, uint32_t CRm,
|
||||||
uint32_t *value)
|
uint32_t *value)
|
||||||
{
|
{
|
||||||
if (cpnum!=15)
|
if (cpnum != 15) {
|
||||||
{
|
|
||||||
LOG_ERROR("Only cp15 is supported");
|
LOG_ERROR("Only cp15 is supported");
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
@ -536,8 +509,7 @@ static int arm720t_mcr(struct target *target, int cpnum,
|
||||||
uint32_t CRn, uint32_t CRm,
|
uint32_t CRn, uint32_t CRm,
|
||||||
uint32_t value)
|
uint32_t value)
|
||||||
{
|
{
|
||||||
if (cpnum!=15)
|
if (cpnum != 15) {
|
||||||
{
|
|
||||||
LOG_ERROR("Only cp15 is supported");
|
LOG_ERROR("Only cp15 is supported");
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
@ -576,8 +548,7 @@ static const struct command_registration arm720t_command_handlers[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Holds methods for ARM720 targets. */
|
/** Holds methods for ARM720 targets. */
|
||||||
struct target_type arm720t_target =
|
struct target_type arm720t_target = {
|
||||||
{
|
|
||||||
.name = "arm720t",
|
.name = "arm720t",
|
||||||
|
|
||||||
.poll = arm7_9_poll,
|
.poll = arm7_9_poll,
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
* Free Software Foundation, Inc., *
|
* Free Software Foundation, Inc., *
|
||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#ifndef ARM720T_H
|
#ifndef ARM720T_H
|
||||||
#define ARM720T_H
|
#define ARM720T_H
|
||||||
|
|
||||||
|
@ -25,8 +26,7 @@
|
||||||
|
|
||||||
#define ARM720T_COMMON_MAGIC 0xa720a720
|
#define ARM720T_COMMON_MAGIC 0xa720a720
|
||||||
|
|
||||||
struct arm720t_common
|
struct arm720t_common {
|
||||||
{
|
|
||||||
struct arm7_9_common arm7_9_common;
|
struct arm7_9_common arm7_9_common;
|
||||||
uint32_t common_magic;
|
uint32_t common_magic;
|
||||||
struct armv4_5_mmu_common armv4_5_mmu;
|
struct armv4_5_mmu_common armv4_5_mmu;
|
||||||
|
@ -35,11 +35,9 @@ struct arm720t_common
|
||||||
uint32_t far_reg;
|
uint32_t far_reg;
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline struct arm720t_common *
|
static inline struct arm720t_common *target_to_arm720(struct target *target)
|
||||||
target_to_arm720(struct target *target)
|
|
||||||
{
|
{
|
||||||
return container_of(target->arch_info, struct arm720t_common,
|
return container_of(target->arch_info, struct arm720t_common, arm7_9_common.arm);
|
||||||
arm7_9_common.arm);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* ARM720T_H */
|
#endif /* ARM720T_H */
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -26,6 +26,7 @@
|
||||||
* Free Software Foundation, Inc., *
|
* Free Software Foundation, Inc., *
|
||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#ifndef ARM7_9_COMMON_H
|
#ifndef ARM7_9_COMMON_H
|
||||||
#define ARM7_9_COMMON_H
|
#define ARM7_9_COMMON_H
|
||||||
|
|
||||||
|
@ -37,8 +38,7 @@
|
||||||
/**
|
/**
|
||||||
* Structure for items that are common between both ARM7 and ARM9 targets.
|
* Structure for items that are common between both ARM7 and ARM9 targets.
|
||||||
*/
|
*/
|
||||||
struct arm7_9_common
|
struct arm7_9_common {
|
||||||
{
|
|
||||||
struct arm arm;
|
struct arm arm;
|
||||||
uint32_t common_magic;
|
uint32_t common_magic;
|
||||||
|
|
||||||
|
@ -71,16 +71,26 @@ struct arm7_9_common
|
||||||
|
|
||||||
struct working_area *dcc_working_area;
|
struct working_area *dcc_working_area;
|
||||||
|
|
||||||
int (*examine_debug_reason)(struct target *target); /**< Function for determining why debug state was entered */
|
int (*examine_debug_reason)(struct target *target);
|
||||||
|
/**< Function for determining why debug state was entered */
|
||||||
|
|
||||||
void (*change_to_arm)(struct target *target, uint32_t *r0, uint32_t *pc); /**< Function for changing from Thumb to ARM mode */
|
void (*change_to_arm)(struct target *target, uint32_t *r0, uint32_t *pc);
|
||||||
|
/**< Function for changing from Thumb to ARM mode */
|
||||||
|
|
||||||
void (*read_core_regs)(struct target *target, uint32_t mask, uint32_t *core_regs[16]); /**< Function for reading the core registers */
|
void (*read_core_regs)(struct target *target, uint32_t mask, uint32_t *core_regs[16]);
|
||||||
void (*read_core_regs_target_buffer)(struct target *target, uint32_t mask, void *buffer, int size);
|
/**< Function for reading the core registers */
|
||||||
void (*read_xpsr)(struct target *target, uint32_t *xpsr, int spsr); /**< Function for reading CPSR or SPSR */
|
|
||||||
|
void (*read_core_regs_target_buffer)(struct target *target, uint32_t mask,
|
||||||
|
void *buffer, int size);
|
||||||
|
void (*read_xpsr)(struct target *target, uint32_t *xpsr, int spsr);
|
||||||
|
/**< Function for reading CPSR or SPSR */
|
||||||
|
|
||||||
|
void (*write_xpsr)(struct target *target, uint32_t xpsr, int spsr);
|
||||||
|
/**< Function for writing to CPSR or SPSR */
|
||||||
|
|
||||||
|
void (*write_xpsr_im8)(struct target *target, uint8_t xpsr_im, int rot, int spsr);
|
||||||
|
/**< Function for writing an immediate value to CPSR or SPSR */
|
||||||
|
|
||||||
void (*write_xpsr)(struct target *target, uint32_t xpsr, int spsr); /**< Function for writing to CPSR or SPSR */
|
|
||||||
void (*write_xpsr_im8)(struct target *target, uint8_t xpsr_im, int rot, int spsr); /**< Function for writing an immediate value to CPSR or SPSR */
|
|
||||||
void (*write_core_regs)(struct target *target, uint32_t mask, uint32_t core_regs[16]);
|
void (*write_core_regs)(struct target *target, uint32_t mask, uint32_t core_regs[16]);
|
||||||
|
|
||||||
void (*load_word_regs)(struct target *target, uint32_t mask);
|
void (*load_word_regs)(struct target *target, uint32_t mask);
|
||||||
|
@ -91,25 +101,28 @@ struct arm7_9_common
|
||||||
void (*store_hword_reg)(struct target *target, int num);
|
void (*store_hword_reg)(struct target *target, int num);
|
||||||
void (*store_byte_reg)(struct target *target, int num);
|
void (*store_byte_reg)(struct target *target, int num);
|
||||||
|
|
||||||
void (*write_pc)(struct target *target, uint32_t pc); /**< Function for writing to the program counter */
|
void (*write_pc)(struct target *target, uint32_t pc);
|
||||||
|
/**< Function for writing to the program counter */
|
||||||
|
|
||||||
void (*branch_resume)(struct target *target);
|
void (*branch_resume)(struct target *target);
|
||||||
void (*branch_resume_thumb)(struct target *target);
|
void (*branch_resume_thumb)(struct target *target);
|
||||||
|
|
||||||
void (*enable_single_step)(struct target *target, uint32_t next_pc);
|
void (*enable_single_step)(struct target *target, uint32_t next_pc);
|
||||||
void (*disable_single_step)(struct target *target);
|
void (*disable_single_step)(struct target *target);
|
||||||
|
|
||||||
void (*set_special_dbgrq)(struct target *target); /**< Function for setting DBGRQ if the normal way won't work */
|
void (*set_special_dbgrq)(struct target *target);
|
||||||
|
/**< Function for setting DBGRQ if the normal way won't work */
|
||||||
|
|
||||||
int (*post_debug_entry)(struct target *target); /**< Callback function called after entering debug mode */
|
int (*post_debug_entry)(struct target *target);
|
||||||
|
/**< Callback function called after entering debug mode */
|
||||||
|
|
||||||
void (*pre_restore_context)(struct target *target); /**< Callback function called before restoring the processor context */
|
void (*pre_restore_context)(struct target *target);
|
||||||
|
/**< Callback function called before restoring the processor context */
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline struct arm7_9_common *
|
static inline struct arm7_9_common *target_to_arm7_9(struct target *target)
|
||||||
target_to_arm7_9(struct target *target)
|
|
||||||
{
|
{
|
||||||
return container_of(target->arch_info, struct arm7_9_common,
|
return container_of(target->arch_info, struct arm7_9_common, arm);
|
||||||
arm);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool is_arm7_9(struct arm7_9_common *arm7_9)
|
static inline bool is_arm7_9(struct arm7_9_common *arm7_9)
|
||||||
|
@ -131,13 +144,20 @@ int arm7_9_soft_reset_halt(struct target *target);
|
||||||
int arm7_9_prepare_reset_halt(struct target *target);
|
int arm7_9_prepare_reset_halt(struct target *target);
|
||||||
|
|
||||||
int arm7_9_halt(struct target *target);
|
int arm7_9_halt(struct target *target);
|
||||||
int arm7_9_resume(struct target *target, int current, uint32_t address, int handle_breakpoints, int debug_execution);
|
int arm7_9_resume(struct target *target, int current, uint32_t address,
|
||||||
int arm7_9_step(struct target *target, int current, uint32_t address, int handle_breakpoints);
|
int handle_breakpoints, int debug_execution);
|
||||||
int arm7_9_read_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer);
|
int arm7_9_step(struct target *target, int current, uint32_t address,
|
||||||
int arm7_9_write_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer);
|
int handle_breakpoints);
|
||||||
int arm7_9_bulk_write_memory(struct target *target, uint32_t address, uint32_t count, const uint8_t *buffer);
|
int arm7_9_read_memory(struct target *target, uint32_t address,
|
||||||
|
uint32_t size, uint32_t count, uint8_t *buffer);
|
||||||
|
int arm7_9_write_memory(struct target *target, uint32_t address,
|
||||||
|
uint32_t size, uint32_t count, const uint8_t *buffer);
|
||||||
|
int arm7_9_bulk_write_memory(struct target *target, uint32_t address,
|
||||||
|
uint32_t count, const uint8_t *buffer);
|
||||||
|
|
||||||
int arm7_9_run_algorithm(struct target *target, int num_mem_params, struct mem_param *mem_params, int num_reg_prams, struct reg_param *reg_param, uint32_t entry_point, void *arch_info);
|
int arm7_9_run_algorithm(struct target *target, int num_mem_params,
|
||||||
|
struct mem_param *mem_params, int num_reg_prams,
|
||||||
|
struct reg_param *reg_param, uint32_t entry_point, void *arch_info);
|
||||||
|
|
||||||
int arm7_9_add_breakpoint(struct target *target, struct breakpoint *breakpoint);
|
int arm7_9_add_breakpoint(struct target *target, struct breakpoint *breakpoint);
|
||||||
int arm7_9_remove_breakpoint(struct target *target, struct breakpoint *breakpoint);
|
int arm7_9_remove_breakpoint(struct target *target, struct breakpoint *breakpoint);
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
* Free Software Foundation, Inc., *
|
* Free Software Foundation, Inc., *
|
||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -32,7 +33,6 @@
|
||||||
#include "register.h"
|
#include "register.h"
|
||||||
#include "arm_opcodes.h"
|
#include "arm_opcodes.h"
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* For information about ARM7TDMI, see ARM DDI 0210C (r4p1)
|
* For information about ARM7TDMI, see ARM DDI 0210C (r4p1)
|
||||||
* or ARM DDI 0029G (r3). "Debug In Depth", Appendix B,
|
* or ARM DDI 0029G (r3). "Debug In Depth", Appendix B,
|
||||||
|
@ -50,8 +50,7 @@ static int arm7tdmi_examine_debug_reason(struct target *target)
|
||||||
|
|
||||||
/* only check the debug reason if we don't know it already */
|
/* only check the debug reason if we don't know it already */
|
||||||
if ((target->debug_reason != DBG_REASON_DBGRQ)
|
if ((target->debug_reason != DBG_REASON_DBGRQ)
|
||||||
&& (target->debug_reason != DBG_REASON_SINGLESTEP))
|
&& (target->debug_reason != DBG_REASON_SINGLESTEP)) {
|
||||||
{
|
|
||||||
struct scan_field fields[2];
|
struct scan_field fields[2];
|
||||||
uint8_t databus[4];
|
uint8_t databus[4];
|
||||||
uint8_t breakpoint;
|
uint8_t breakpoint;
|
||||||
|
@ -64,19 +63,17 @@ static int arm7tdmi_examine_debug_reason(struct target *target)
|
||||||
fields[1].out_value = NULL;
|
fields[1].out_value = NULL;
|
||||||
fields[1].in_value = databus;
|
fields[1].in_value = databus;
|
||||||
|
|
||||||
if ((retval = arm_jtag_scann(&arm7_9->jtag_info, 0x1, TAP_DRPAUSE)) != ERROR_OK)
|
retval = arm_jtag_scann(&arm7_9->jtag_info, 0x1, TAP_DRPAUSE);
|
||||||
{
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
|
||||||
retval = arm_jtag_set_instr(&arm7_9->jtag_info, arm7_9->jtag_info.intest_instr, NULL, TAP_DRPAUSE);
|
retval = arm_jtag_set_instr(&arm7_9->jtag_info, arm7_9->jtag_info.intest_instr, NULL, TAP_DRPAUSE);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
jtag_add_dr_scan(arm7_9->jtag_info.tap, 2, fields, TAP_DRPAUSE);
|
jtag_add_dr_scan(arm7_9->jtag_info.tap, 2, fields, TAP_DRPAUSE);
|
||||||
if ((retval = jtag_execute_queue()) != ERROR_OK)
|
retval = jtag_execute_queue();
|
||||||
{
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
|
||||||
|
|
||||||
fields[0].in_value = NULL;
|
fields[0].in_value = NULL;
|
||||||
fields[0].out_value = &breakpoint;
|
fields[0].out_value = &breakpoint;
|
||||||
|
@ -96,9 +93,9 @@ static int arm7tdmi_examine_debug_reason(struct target *target)
|
||||||
|
|
||||||
static const int arm7tdmi_num_bits[] = {1, 32};
|
static const int arm7tdmi_num_bits[] = {1, 32};
|
||||||
|
|
||||||
static __inline int arm7tdmi_clock_out_inner(struct arm_jtag *jtag_info, uint32_t out, int breakpoint)
|
static inline int arm7tdmi_clock_out_inner(struct arm_jtag *jtag_info, uint32_t out, int breakpoint)
|
||||||
{
|
{
|
||||||
uint32_t values[2]={breakpoint, flip_u32(out, 32)};
|
uint32_t values[2] = {breakpoint, flip_u32(out, 32)};
|
||||||
|
|
||||||
jtag_add_dr_out(jtag_info->tap,
|
jtag_add_dr_out(jtag_info->tap,
|
||||||
2,
|
2,
|
||||||
|
@ -116,7 +113,7 @@ static __inline int arm7tdmi_clock_out_inner(struct arm_jtag *jtag_info, uint32_
|
||||||
*
|
*
|
||||||
* FIXME remove the unused "deprecated" parameter
|
* FIXME remove the unused "deprecated" parameter
|
||||||
*/
|
*/
|
||||||
static __inline int arm7tdmi_clock_out(struct arm_jtag *jtag_info,
|
static inline int arm7tdmi_clock_out(struct arm_jtag *jtag_info,
|
||||||
uint32_t out, uint32_t *deprecated, int breakpoint)
|
uint32_t out, uint32_t *deprecated, int breakpoint)
|
||||||
{
|
{
|
||||||
int retval;
|
int retval;
|
||||||
|
@ -136,10 +133,9 @@ static int arm7tdmi_clock_data_in(struct arm_jtag *jtag_info, uint32_t *in)
|
||||||
int retval = ERROR_OK;
|
int retval = ERROR_OK;
|
||||||
struct scan_field fields[2];
|
struct scan_field fields[2];
|
||||||
|
|
||||||
if ((retval = arm_jtag_scann(jtag_info, 0x1, TAP_DRPAUSE)) != ERROR_OK)
|
retval = arm_jtag_scann(jtag_info, 0x1, TAP_DRPAUSE);
|
||||||
{
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
|
||||||
retval = arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL, TAP_DRPAUSE);
|
retval = arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL, TAP_DRPAUSE);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
@ -159,7 +155,8 @@ static int arm7tdmi_clock_data_in(struct arm_jtag *jtag_info, uint32_t *in)
|
||||||
jtag_add_runtest(0, TAP_DRPAUSE);
|
jtag_add_runtest(0, TAP_DRPAUSE);
|
||||||
|
|
||||||
#ifdef _DEBUG_INSTRUCTION_EXECUTION_
|
#ifdef _DEBUG_INSTRUCTION_EXECUTION_
|
||||||
if ((retval = jtag_execute_queue()) != ERROR_OK)
|
retval = jtag_execute_queue();
|
||||||
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
if (in)
|
if (in)
|
||||||
|
@ -176,28 +173,21 @@ void arm_endianness(uint8_t *tmp, void *in, int size, int be, int flip)
|
||||||
uint32_t readback = le_to_h_u32(tmp);
|
uint32_t readback = le_to_h_u32(tmp);
|
||||||
if (flip)
|
if (flip)
|
||||||
readback = flip_u32(readback, 32);
|
readback = flip_u32(readback, 32);
|
||||||
switch (size)
|
switch (size) {
|
||||||
{
|
|
||||||
case 4:
|
case 4:
|
||||||
if (be)
|
if (be)
|
||||||
{
|
h_u32_to_be(((uint8_t *)in), readback);
|
||||||
h_u32_to_be(((uint8_t*)in), readback);
|
else
|
||||||
} else
|
h_u32_to_le(((uint8_t *)in), readback);
|
||||||
{
|
|
||||||
h_u32_to_le(((uint8_t*)in), readback);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
if (be)
|
if (be)
|
||||||
{
|
h_u16_to_be(((uint8_t *)in), readback & 0xffff);
|
||||||
h_u16_to_be(((uint8_t*)in), readback & 0xffff);
|
else
|
||||||
} else
|
h_u16_to_le(((uint8_t *)in), readback & 0xffff);
|
||||||
{
|
|
||||||
h_u16_to_le(((uint8_t*)in), readback & 0xffff);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
*((uint8_t *)in)= readback & 0xff;
|
*((uint8_t *)in) = readback & 0xff;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -222,10 +212,9 @@ static int arm7tdmi_clock_data_in_endianness(struct arm_jtag *jtag_info,
|
||||||
int retval = ERROR_OK;
|
int retval = ERROR_OK;
|
||||||
struct scan_field fields[2];
|
struct scan_field fields[2];
|
||||||
|
|
||||||
if ((retval = arm_jtag_scann(jtag_info, 0x1, TAP_DRPAUSE)) != ERROR_OK)
|
retval = arm_jtag_scann(jtag_info, 0x1, TAP_DRPAUSE);
|
||||||
{
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
|
||||||
retval = arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL, TAP_DRPAUSE);
|
retval = arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL, TAP_DRPAUSE);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
@ -250,19 +239,14 @@ static int arm7tdmi_clock_data_in_endianness(struct arm_jtag *jtag_info,
|
||||||
|
|
||||||
#ifdef _DEBUG_INSTRUCTION_EXECUTION_
|
#ifdef _DEBUG_INSTRUCTION_EXECUTION_
|
||||||
{
|
{
|
||||||
if ((retval = jtag_execute_queue()) != ERROR_OK)
|
retval = jtag_execute_queue();
|
||||||
{
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
|
||||||
|
|
||||||
if (in)
|
if (in)
|
||||||
{
|
LOG_DEBUG("in: 0x%8.8x", *(uint32_t *)in);
|
||||||
LOG_DEBUG("in: 0x%8.8x", *(uint32_t*)in);
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
LOG_ERROR("BUG: called with in == NULL");
|
LOG_ERROR("BUG: called with in == NULL");
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -318,7 +302,6 @@ static void arm7tdmi_change_to_arm(struct target *target,
|
||||||
*pc -= 0xa;
|
*pc -= 0xa;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* FIX!!! is this a potential performance bottleneck w.r.t. requiring too many
|
/* FIX!!! is this a potential performance bottleneck w.r.t. requiring too many
|
||||||
* roundtrips when jtag_execute_queue() has a large overhead(e.g. for USB)s?
|
* roundtrips when jtag_execute_queue() has a large overhead(e.g. for USB)s?
|
||||||
*
|
*
|
||||||
|
@ -326,7 +309,7 @@ static void arm7tdmi_change_to_arm(struct target *target,
|
||||||
* and convert data afterwards.
|
* and convert data afterwards.
|
||||||
*/
|
*/
|
||||||
static void arm7tdmi_read_core_regs(struct target *target,
|
static void arm7tdmi_read_core_regs(struct target *target,
|
||||||
uint32_t mask, uint32_t* core_regs[16])
|
uint32_t mask, uint32_t *core_regs[16])
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
|
struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
|
||||||
|
@ -342,8 +325,7 @@ static void arm7tdmi_read_core_regs(struct target *target,
|
||||||
/* fetch NOP, STM in EXECUTE stage (1st cycle) */
|
/* fetch NOP, STM in EXECUTE stage (1st cycle) */
|
||||||
arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
|
arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
|
||||||
|
|
||||||
for (i = 0; i <= 15; i++)
|
for (i = 0; i <= 15; i++) {
|
||||||
{
|
|
||||||
if (mask & (1 << i))
|
if (mask & (1 << i))
|
||||||
/* nothing fetched, STM still in EXECUTE (1 + i cycle) */
|
/* nothing fetched, STM still in EXECUTE (1 + i cycle) */
|
||||||
arm7tdmi_clock_data_in(jtag_info, core_regs[i]);
|
arm7tdmi_clock_data_in(jtag_info, core_regs[i]);
|
||||||
|
@ -351,7 +333,7 @@ static void arm7tdmi_read_core_regs(struct target *target,
|
||||||
}
|
}
|
||||||
|
|
||||||
static void arm7tdmi_read_core_regs_target_buffer(struct target *target,
|
static void arm7tdmi_read_core_regs_target_buffer(struct target *target,
|
||||||
uint32_t mask, void* buffer, int size)
|
uint32_t mask, void *buffer, int size)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
|
struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
|
||||||
|
@ -371,13 +353,10 @@ static void arm7tdmi_read_core_regs_target_buffer(struct target *target,
|
||||||
/* fetch NOP, STM in EXECUTE stage (1st cycle) */
|
/* fetch NOP, STM in EXECUTE stage (1st cycle) */
|
||||||
arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
|
arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
|
||||||
|
|
||||||
for (i = 0; i <= 15; i++)
|
for (i = 0; i <= 15; i++) {
|
||||||
{
|
|
||||||
/* nothing fetched, STM still in EXECUTE (1 + i cycle), read databus */
|
/* nothing fetched, STM still in EXECUTE (1 + i cycle), read databus */
|
||||||
if (mask & (1 << i))
|
if (mask & (1 << i)) {
|
||||||
{
|
switch (size) {
|
||||||
switch (size)
|
|
||||||
{
|
|
||||||
case 4:
|
case 4:
|
||||||
arm7tdmi_clock_data_in_endianness(jtag_info, buf_u32++, 4, be);
|
arm7tdmi_clock_data_in_endianness(jtag_info, buf_u32++, 4, be);
|
||||||
break;
|
break;
|
||||||
|
@ -474,8 +453,7 @@ static void arm7tdmi_write_core_regs(struct target *target,
|
||||||
/* fetch NOP, LDM in EXECUTE stage (1st cycle) */
|
/* fetch NOP, LDM in EXECUTE stage (1st cycle) */
|
||||||
arm7tdmi_clock_out_inner(jtag_info, ARMV4_5_NOP, 0);
|
arm7tdmi_clock_out_inner(jtag_info, ARMV4_5_NOP, 0);
|
||||||
|
|
||||||
for (i = 0; i <= 15; i++)
|
for (i = 0; i <= 15; i++) {
|
||||||
{
|
|
||||||
if (mask & (1 << i))
|
if (mask & (1 << i))
|
||||||
/* nothing fetched, LDM still in EXECUTE (1 + i cycle) */
|
/* nothing fetched, LDM still in EXECUTE (1 + i cycle) */
|
||||||
arm7tdmi_clock_out_inner(jtag_info, core_regs[i], 0);
|
arm7tdmi_clock_out_inner(jtag_info, core_regs[i], 0);
|
||||||
|
@ -711,7 +689,7 @@ static int arm7tdmi_target_create(struct target *target, Jim_Interp *interp)
|
||||||
{
|
{
|
||||||
struct arm7_9_common *arm7_9;
|
struct arm7_9_common *arm7_9;
|
||||||
|
|
||||||
arm7_9 = calloc(1,sizeof(struct arm7_9_common));
|
arm7_9 = calloc(1, sizeof(struct arm7_9_common));
|
||||||
arm7tdmi_init_arch_info(target, arm7_9, target->tap);
|
arm7tdmi_init_arch_info(target, arm7_9, target->tap);
|
||||||
arm7_9->arm.is_armv4 = true;
|
arm7_9->arm.is_armv4 = true;
|
||||||
|
|
||||||
|
@ -719,8 +697,7 @@ static int arm7tdmi_target_create(struct target *target, Jim_Interp *interp)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Holds methods for ARM7TDMI targets. */
|
/** Holds methods for ARM7TDMI targets. */
|
||||||
struct target_type arm7tdmi_target =
|
struct target_type arm7tdmi_target = {
|
||||||
{
|
|
||||||
.name = "arm7tdmi",
|
.name = "arm7tdmi",
|
||||||
|
|
||||||
.poll = arm7_9_poll,
|
.poll = arm7_9_poll,
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
* Free Software Foundation, Inc., *
|
* Free Software Foundation, Inc., *
|
||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#ifndef ARM7TDMI_H
|
#ifndef ARM7TDMI_H
|
||||||
#define ARM7TDMI_H
|
#define ARM7TDMI_H
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -17,6 +17,7 @@
|
||||||
* Free Software Foundation, Inc., *
|
* Free Software Foundation, Inc., *
|
||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#ifndef ARM920T_H
|
#ifndef ARM920T_H
|
||||||
#define ARM920T_H
|
#define ARM920T_H
|
||||||
|
|
||||||
|
@ -25,8 +26,7 @@
|
||||||
|
|
||||||
#define ARM920T_COMMON_MAGIC 0xa920a920
|
#define ARM920T_COMMON_MAGIC 0xa920a920
|
||||||
|
|
||||||
struct arm920t_common
|
struct arm920t_common {
|
||||||
{
|
|
||||||
struct arm7_9_common arm7_9_common;
|
struct arm7_9_common arm7_9_common;
|
||||||
uint32_t common_magic;
|
uint32_t common_magic;
|
||||||
struct armv4_5_mmu_common armv4_5_mmu;
|
struct armv4_5_mmu_common armv4_5_mmu;
|
||||||
|
@ -38,21 +38,17 @@ struct arm920t_common
|
||||||
int preserve_cache;
|
int preserve_cache;
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline struct arm920t_common *
|
static inline struct arm920t_common *target_to_arm920(struct target *target)
|
||||||
target_to_arm920(struct target *target)
|
|
||||||
{
|
{
|
||||||
return container_of(target->arch_info, struct arm920t_common,
|
return container_of(target->arch_info, struct arm920t_common, arm7_9_common.arm);
|
||||||
arm7_9_common.arm);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct arm920t_cache_line
|
struct arm920t_cache_line {
|
||||||
{
|
|
||||||
uint32_t cam;
|
uint32_t cam;
|
||||||
uint32_t data[8];
|
uint32_t data[8];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct arm920t_tlb_entry
|
struct arm920t_tlb_entry {
|
||||||
{
|
|
||||||
uint32_t cam;
|
uint32_t cam;
|
||||||
uint32_t ram1;
|
uint32_t ram1;
|
||||||
uint32_t ram2;
|
uint32_t ram2;
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
* Free Software Foundation, Inc., *
|
* Free Software Foundation, Inc., *
|
||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -63,10 +64,9 @@ static int arm926ejs_cp15_read(struct target *target, uint32_t op1, uint32_t op2
|
||||||
|
|
||||||
buf_set_u32(address_buf, 0, 14, address);
|
buf_set_u32(address_buf, 0, 14, address);
|
||||||
|
|
||||||
if ((retval = arm_jtag_scann(jtag_info, 0xf, TAP_IDLE)) != ERROR_OK)
|
retval = arm_jtag_scann(jtag_info, 0xf, TAP_IDLE);
|
||||||
{
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
|
||||||
retval = arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL, TAP_IDLE);
|
retval = arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL, TAP_IDLE);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
@ -91,8 +91,7 @@ static int arm926ejs_cp15_read(struct target *target, uint32_t op1, uint32_t op2
|
||||||
|
|
||||||
long long then = timeval_ms();
|
long long then = timeval_ms();
|
||||||
|
|
||||||
for (;;)
|
for (;;) {
|
||||||
{
|
|
||||||
/* rescan with NOP, to wait for the access to complete */
|
/* rescan with NOP, to wait for the access to complete */
|
||||||
access_t = 0;
|
access_t = 0;
|
||||||
nr_w_buf = 0;
|
nr_w_buf = 0;
|
||||||
|
@ -100,19 +99,15 @@ static int arm926ejs_cp15_read(struct target *target, uint32_t op1, uint32_t op2
|
||||||
|
|
||||||
jtag_add_callback(arm_le_to_h_u32, (jtag_callback_data_t)value);
|
jtag_add_callback(arm_le_to_h_u32, (jtag_callback_data_t)value);
|
||||||
|
|
||||||
if ((retval = jtag_execute_queue()) != ERROR_OK)
|
retval = jtag_execute_queue();
|
||||||
{
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
|
||||||
|
|
||||||
if (buf_get_u32(&access_t, 0, 1) == 1)
|
if (buf_get_u32(&access_t, 0, 1) == 1)
|
||||||
{
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
/* 10ms timeout */
|
/* 10ms timeout */
|
||||||
if ((timeval_ms()-then)>10)
|
if ((timeval_ms()-then) > 10) {
|
||||||
{
|
|
||||||
LOG_ERROR("cp15 read operation timed out");
|
LOG_ERROR("cp15 read operation timed out");
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
@ -155,10 +150,9 @@ static int arm926ejs_cp15_write(struct target *target, uint32_t op1, uint32_t op
|
||||||
buf_set_u32(address_buf, 0, 14, address);
|
buf_set_u32(address_buf, 0, 14, address);
|
||||||
buf_set_u32(value_buf, 0, 32, value);
|
buf_set_u32(value_buf, 0, 32, value);
|
||||||
|
|
||||||
if ((retval = arm_jtag_scann(jtag_info, 0xf, TAP_IDLE)) != ERROR_OK)
|
retval = arm_jtag_scann(jtag_info, 0xf, TAP_IDLE);
|
||||||
{
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
|
||||||
retval = arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL, TAP_IDLE);
|
retval = arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL, TAP_IDLE);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
@ -183,25 +177,20 @@ static int arm926ejs_cp15_write(struct target *target, uint32_t op1, uint32_t op
|
||||||
|
|
||||||
long long then = timeval_ms();
|
long long then = timeval_ms();
|
||||||
|
|
||||||
for (;;)
|
for (;;) {
|
||||||
{
|
|
||||||
/* rescan with NOP, to wait for the access to complete */
|
/* rescan with NOP, to wait for the access to complete */
|
||||||
access_t = 0;
|
access_t = 0;
|
||||||
nr_w_buf = 0;
|
nr_w_buf = 0;
|
||||||
jtag_add_dr_scan(jtag_info->tap, 4, fields, TAP_IDLE);
|
jtag_add_dr_scan(jtag_info->tap, 4, fields, TAP_IDLE);
|
||||||
if ((retval = jtag_execute_queue()) != ERROR_OK)
|
retval = jtag_execute_queue();
|
||||||
{
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
|
||||||
|
|
||||||
if (buf_get_u32(&access_t, 0, 1) == 1)
|
if (buf_get_u32(&access_t, 0, 1) == 1)
|
||||||
{
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
/* 10ms timeout */
|
/* 10ms timeout */
|
||||||
if ((timeval_ms()-then)>10)
|
if ((timeval_ms()-then) > 10) {
|
||||||
{
|
|
||||||
LOG_ERROR("cp15 write operation timed out");
|
LOG_ERROR("cp15 write operation timed out");
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
@ -236,14 +225,14 @@ static int arm926ejs_examine_debug_reason(struct target *target)
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
embeddedice_read_reg(dbg_stat);
|
embeddedice_read_reg(dbg_stat);
|
||||||
if ((retval = jtag_execute_queue()) != ERROR_OK)
|
retval = jtag_execute_queue();
|
||||||
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
/* Method-Of-Entry (MOE) field */
|
/* Method-Of-Entry (MOE) field */
|
||||||
debug_reason = buf_get_u32(dbg_stat->value, 6, 4);
|
debug_reason = buf_get_u32(dbg_stat->value, 6, 4);
|
||||||
|
|
||||||
switch (debug_reason)
|
switch (debug_reason) {
|
||||||
{
|
|
||||||
case 0:
|
case 0:
|
||||||
LOG_DEBUG("no *NEW* debug entry (?missed one?)");
|
LOG_DEBUG("no *NEW* debug entry (?missed one?)");
|
||||||
/* ... since last restart or debug reset ... */
|
/* ... since last restart or debug reset ... */
|
||||||
|
@ -337,7 +326,8 @@ static int arm926ejs_get_ttb(struct target *target, uint32_t *result)
|
||||||
int retval;
|
int retval;
|
||||||
uint32_t ttb = 0x0;
|
uint32_t ttb = 0x0;
|
||||||
|
|
||||||
if ((retval = arm926ejs->read_cp15(target, 0, 0, 2, 0, &ttb)) != ERROR_OK)
|
retval = arm926ejs->read_cp15(target, 0, 0, 2, 0, &ttb);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
*result = ttb;
|
*result = ttb;
|
||||||
|
@ -360,8 +350,7 @@ static int arm926ejs_disable_mmu_caches(struct target *target, int mmu,
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
if (mmu)
|
if (mmu) {
|
||||||
{
|
|
||||||
/* invalidate TLB */
|
/* invalidate TLB */
|
||||||
retval = arm926ejs->write_cp15(target, 0, 0, 8, 7, 0x0);
|
retval = arm926ejs->write_cp15(target, 0, 0, 8, 7, 0x0);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
|
@ -370,8 +359,7 @@ static int arm926ejs_disable_mmu_caches(struct target *target, int mmu,
|
||||||
cp15_control &= ~0x1U;
|
cp15_control &= ~0x1U;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (d_u_cache)
|
if (d_u_cache) {
|
||||||
{
|
|
||||||
uint32_t debug_override;
|
uint32_t debug_override;
|
||||||
/* read-modify-write CP15 debug override register
|
/* read-modify-write CP15 debug override register
|
||||||
* to enable "test and clean all" */
|
* to enable "test and clean all" */
|
||||||
|
@ -398,8 +386,7 @@ static int arm926ejs_disable_mmu_caches(struct target *target, int mmu,
|
||||||
cp15_control &= ~0x4U;
|
cp15_control &= ~0x4U;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i_cache)
|
if (i_cache) {
|
||||||
{
|
|
||||||
/* invalidate ICache */
|
/* invalidate ICache */
|
||||||
retval = arm926ejs->write_cp15(target, 0, 0, 7, 5, 0x0);
|
retval = arm926ejs->write_cp15(target, 0, 0, 7, 5, 0x0);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
|
@ -454,8 +441,7 @@ static int arm926ejs_post_debug_entry(struct target *target)
|
||||||
return retval;
|
return retval;
|
||||||
LOG_DEBUG("cp15_control_reg: %8.8" PRIx32 "", arm926ejs->cp15_control_reg);
|
LOG_DEBUG("cp15_control_reg: %8.8" PRIx32 "", arm926ejs->cp15_control_reg);
|
||||||
|
|
||||||
if (arm926ejs->armv4_5_mmu.armv4_5_cache.ctype == -1)
|
if (arm926ejs->armv4_5_mmu.armv4_5_cache.ctype == -1) {
|
||||||
{
|
|
||||||
uint32_t cache_type_reg;
|
uint32_t cache_type_reg;
|
||||||
/* identify caches */
|
/* identify caches */
|
||||||
retval = arm926ejs->read_cp15(target, 0, 1, 0, 0, &cache_type_reg);
|
retval = arm926ejs->read_cp15(target, 0, 1, 0, 0, &cache_type_reg);
|
||||||
|
@ -530,15 +516,13 @@ static int arm926ejs_verify_pointer(struct command_context *cmd_ctx,
|
||||||
/** Logs summary of ARM926 state for a halted target. */
|
/** Logs summary of ARM926 state for a halted target. */
|
||||||
int arm926ejs_arch_state(struct target *target)
|
int arm926ejs_arch_state(struct target *target)
|
||||||
{
|
{
|
||||||
static const char *state[] =
|
static const char *state[] = {
|
||||||
{
|
|
||||||
"disabled", "enabled"
|
"disabled", "enabled"
|
||||||
};
|
};
|
||||||
|
|
||||||
struct arm926ejs_common *arm926ejs = target_to_arm926(target);
|
struct arm926ejs_common *arm926ejs = target_to_arm926(target);
|
||||||
|
|
||||||
if (arm926ejs->common_magic != ARM926EJS_COMMON_MAGIC)
|
if (arm926ejs->common_magic != ARM926EJS_COMMON_MAGIC) {
|
||||||
{
|
|
||||||
LOG_ERROR("BUG: %s", arm926_not);
|
LOG_ERROR("BUG: %s", arm926_not);
|
||||||
return ERROR_TARGET_INVALID;
|
return ERROR_TARGET_INVALID;
|
||||||
}
|
}
|
||||||
|
@ -560,37 +544,27 @@ int arm926ejs_soft_reset_halt(struct target *target)
|
||||||
struct arm *arm = &arm7_9->arm;
|
struct arm *arm = &arm7_9->arm;
|
||||||
struct reg *dbg_stat = &arm7_9->eice_cache->reg_list[EICE_DBG_STAT];
|
struct reg *dbg_stat = &arm7_9->eice_cache->reg_list[EICE_DBG_STAT];
|
||||||
|
|
||||||
if ((retval = target_halt(target)) != ERROR_OK)
|
retval = target_halt(target);
|
||||||
{
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
|
||||||
|
|
||||||
long long then = timeval_ms();
|
long long then = timeval_ms();
|
||||||
int timeout;
|
int timeout;
|
||||||
while (!(timeout = ((timeval_ms()-then) > 1000)))
|
while (!(timeout = ((timeval_ms()-then) > 1000))) {
|
||||||
{
|
if (buf_get_u32(dbg_stat->value, EICE_DBG_STATUS_DBGACK, 1) == 0) {
|
||||||
if (buf_get_u32(dbg_stat->value, EICE_DBG_STATUS_DBGACK, 1) == 0)
|
|
||||||
{
|
|
||||||
embeddedice_read_reg(dbg_stat);
|
embeddedice_read_reg(dbg_stat);
|
||||||
if ((retval = jtag_execute_queue()) != ERROR_OK)
|
retval = jtag_execute_queue();
|
||||||
{
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
} else
|
||||||
} else
|
|
||||||
{
|
|
||||||
break;
|
break;
|
||||||
}
|
if (debug_level >= 1) {
|
||||||
if (debug_level >= 1)
|
|
||||||
{
|
|
||||||
/* do not eat all CPU, time out after 1 se*/
|
/* do not eat all CPU, time out after 1 se*/
|
||||||
alive_sleep(100);
|
alive_sleep(100);
|
||||||
} else
|
} else
|
||||||
{
|
|
||||||
keep_alive();
|
keep_alive();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (timeout)
|
if (timeout) {
|
||||||
{
|
|
||||||
LOG_ERROR("Failed to halt CPU after 1 sec");
|
LOG_ERROR("Failed to halt CPU after 1 sec");
|
||||||
return ERROR_TARGET_TIMEOUT;
|
return ERROR_TARGET_TIMEOUT;
|
||||||
}
|
}
|
||||||
|
@ -636,13 +610,11 @@ int arm926ejs_write_memory(struct target *target, uint32_t address,
|
||||||
* Also it should be moved to the callbacks that handle breakpoints
|
* Also it should be moved to the callbacks that handle breakpoints
|
||||||
* specifically and not the generic memory write fn's. See XScale code.
|
* specifically and not the generic memory write fn's. See XScale code.
|
||||||
**/
|
**/
|
||||||
if (arm926ejs->armv4_5_mmu.mmu_enabled && (count == 1) && ((size==2) || (size==4)))
|
if (arm926ejs->armv4_5_mmu.mmu_enabled && (count == 1) && ((size == 2) || (size == 4))) {
|
||||||
{
|
|
||||||
/* special case the handling of single word writes to bypass MMU
|
/* special case the handling of single word writes to bypass MMU
|
||||||
* to allow implementation of breakpoints in memory marked read only
|
* to allow implementation of breakpoints in memory marked read only
|
||||||
* by MMU */
|
* by MMU */
|
||||||
if (arm926ejs->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled)
|
if (arm926ejs->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled) {
|
||||||
{
|
|
||||||
/* flush and invalidate data cache
|
/* flush and invalidate data cache
|
||||||
*
|
*
|
||||||
* MCR p15,0,p,c7,c10,1 - clean cache line using virtual address
|
* MCR p15,0,p,c7,c10,1 - clean cache line using virtual address
|
||||||
|
@ -662,24 +634,20 @@ int arm926ejs_write_memory(struct target *target, uint32_t address,
|
||||||
retval = armv4_5_mmu_write_physical(target, &arm926ejs->armv4_5_mmu, pa, size, count, buffer);
|
retval = armv4_5_mmu_write_physical(target, &arm926ejs->armv4_5_mmu, pa, size, count, buffer);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
} else
|
} else {
|
||||||
{
|
retval = arm7_9_write_memory(target, address, size, count, buffer);
|
||||||
if ((retval = arm7_9_write_memory(target, address, size, count, buffer)) != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If ICache is enabled, we have to invalidate affected ICache lines
|
/* If ICache is enabled, we have to invalidate affected ICache lines
|
||||||
* the DCache is forced to write-through, so we don't have to clean it here
|
* the DCache is forced to write-through, so we don't have to clean it here
|
||||||
*/
|
*/
|
||||||
if (arm926ejs->armv4_5_mmu.armv4_5_cache.i_cache_enabled)
|
if (arm926ejs->armv4_5_mmu.armv4_5_cache.i_cache_enabled) {
|
||||||
{
|
if (count <= 1) {
|
||||||
if (count <= 1)
|
|
||||||
{
|
|
||||||
/* invalidate ICache single entry with MVA */
|
/* invalidate ICache single entry with MVA */
|
||||||
arm926ejs->write_cp15(target, 0, 1, 7, 5, address);
|
arm926ejs->write_cp15(target, 0, 1, 7, 5, address);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
/* invalidate ICache */
|
/* invalidate ICache */
|
||||||
arm926ejs->write_cp15(target, 0, 0, 7, 5, address);
|
arm926ejs->write_cp15(target, 0, 0, 7, 5, address);
|
||||||
}
|
}
|
||||||
|
@ -748,7 +716,7 @@ int arm926ejs_init_arch_info(struct target *target, struct arm926ejs_common *arm
|
||||||
|
|
||||||
static int arm926ejs_target_create(struct target *target, Jim_Interp *interp)
|
static int arm926ejs_target_create(struct target *target, Jim_Interp *interp)
|
||||||
{
|
{
|
||||||
struct arm926ejs_common *arm926ejs = calloc(1,sizeof(struct arm926ejs_common));
|
struct arm926ejs_common *arm926ejs = calloc(1, sizeof(struct arm926ejs_common));
|
||||||
|
|
||||||
/* ARM9EJ-S core always reports 0x1 in Capture-IR */
|
/* ARM9EJ-S core always reports 0x1 in Capture-IR */
|
||||||
target->tap->ir_capture_mask = 0x0f;
|
target->tap->ir_capture_mask = 0x0f;
|
||||||
|
@ -787,8 +755,7 @@ static int arm926ejs_mmu(struct target *target, int *enabled)
|
||||||
{
|
{
|
||||||
struct arm926ejs_common *arm926ejs = target_to_arm926(target);
|
struct arm926ejs_common *arm926ejs = target_to_arm926(target);
|
||||||
|
|
||||||
if (target->state != TARGET_HALTED)
|
if (target->state != TARGET_HALTED) {
|
||||||
{
|
|
||||||
LOG_ERROR("Target not halted");
|
LOG_ERROR("Target not halted");
|
||||||
return ERROR_TARGET_INVALID;
|
return ERROR_TARGET_INVALID;
|
||||||
}
|
}
|
||||||
|
@ -822,8 +789,7 @@ const struct command_registration arm926ejs_command_handlers[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Holds methods for ARM926 targets. */
|
/** Holds methods for ARM926 targets. */
|
||||||
struct target_type arm926ejs_target =
|
struct target_type arm926ejs_target = {
|
||||||
{
|
|
||||||
.name = "arm926ejs",
|
.name = "arm926ejs",
|
||||||
|
|
||||||
.poll = arm7_9_poll,
|
.poll = arm7_9_poll,
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
* Free Software Foundation, Inc., *
|
* Free Software Foundation, Inc., *
|
||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#ifndef ARM926EJS_H
|
#ifndef ARM926EJS_H
|
||||||
#define ARM926EJS_H
|
#define ARM926EJS_H
|
||||||
|
|
||||||
|
@ -25,27 +26,25 @@
|
||||||
|
|
||||||
#define ARM926EJS_COMMON_MAGIC 0xa926a926
|
#define ARM926EJS_COMMON_MAGIC 0xa926a926
|
||||||
|
|
||||||
struct arm926ejs_common
|
struct arm926ejs_common {
|
||||||
{
|
|
||||||
struct arm7_9_common arm7_9_common;
|
struct arm7_9_common arm7_9_common;
|
||||||
uint32_t common_magic;
|
uint32_t common_magic;
|
||||||
struct armv4_5_mmu_common armv4_5_mmu;
|
struct armv4_5_mmu_common armv4_5_mmu;
|
||||||
int (*read_cp15)(struct target *target, uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm, uint32_t *value);
|
int (*read_cp15)(struct target *target, uint32_t op1, uint32_t op2,
|
||||||
int (*write_cp15)(struct target *target, uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm, uint32_t value);
|
uint32_t CRn, uint32_t CRm, uint32_t *value);
|
||||||
|
int (*write_cp15)(struct target *target, uint32_t op1, uint32_t op2,
|
||||||
|
uint32_t CRn, uint32_t CRm, uint32_t value);
|
||||||
uint32_t cp15_control_reg;
|
uint32_t cp15_control_reg;
|
||||||
uint32_t d_fsr;
|
uint32_t d_fsr;
|
||||||
uint32_t i_fsr;
|
uint32_t i_fsr;
|
||||||
uint32_t d_far;
|
uint32_t d_far;
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline struct arm926ejs_common *
|
static inline struct arm926ejs_common *target_to_arm926(struct target *target)
|
||||||
target_to_arm926(struct target *target)
|
|
||||||
{
|
{
|
||||||
return container_of(target->arch_info, struct arm926ejs_common,
|
return container_of(target->arch_info, struct arm926ejs_common, arm7_9_common.arm);
|
||||||
arm7_9_common.arm);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int arm926ejs_init_arch_info(struct target *target,
|
int arm926ejs_init_arch_info(struct target *target,
|
||||||
struct arm926ejs_common *arm926ejs, struct jtag_tap *tap);
|
struct arm926ejs_common *arm926ejs, struct jtag_tap *tap);
|
||||||
int arm926ejs_arch_state(struct target *target);
|
int arm926ejs_arch_state(struct target *target);
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
* Free Software Foundation, Inc., *
|
* Free Software Foundation, Inc., *
|
||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -39,8 +40,8 @@
|
||||||
|
|
||||||
#define NB_CACHE_WAYS 4
|
#define NB_CACHE_WAYS 4
|
||||||
|
|
||||||
static uint32_t dc = 0x0;
|
static uint32_t dc;
|
||||||
static uint32_t ic = 0x0;
|
static uint32_t ic;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* flag to give info about cache manipulation during debug :
|
* flag to give info about cache manipulation during debug :
|
||||||
|
@ -55,8 +56,9 @@ int arm946e_post_debug_entry(struct target *target);
|
||||||
void arm946e_pre_restore_context(struct target *target);
|
void arm946e_pre_restore_context(struct target *target);
|
||||||
static int arm946e_read_cp15(struct target *target, int reg_addr, uint32_t *value);
|
static int arm946e_read_cp15(struct target *target, int reg_addr, uint32_t *value);
|
||||||
|
|
||||||
|
int arm946e_init_arch_info(struct target *target,
|
||||||
int arm946e_init_arch_info(struct target *target, struct arm946e_common *arm946e, struct jtag_tap *tap)
|
struct arm946e_common *arm946e,
|
||||||
|
struct jtag_tap *tap)
|
||||||
{
|
{
|
||||||
struct arm7_9_common *arm7_9 = &arm946e->arm7_9_common;
|
struct arm7_9_common *arm7_9 = &arm946e->arm7_9_common;
|
||||||
|
|
||||||
|
@ -84,14 +86,14 @@ int arm946e_init_arch_info(struct target *target, struct arm946e_common *arm946e
|
||||||
arm946e_preserve_cache = 0;
|
arm946e_preserve_cache = 0;
|
||||||
|
|
||||||
/* override hw single-step capability from ARM9TDMI */
|
/* override hw single-step capability from ARM9TDMI */
|
||||||
//arm7_9->has_single_step = 1;
|
/* arm7_9->has_single_step = 1; */
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int arm946e_target_create(struct target *target, Jim_Interp *interp)
|
static int arm946e_target_create(struct target *target, Jim_Interp *interp)
|
||||||
{
|
{
|
||||||
struct arm946e_common *arm946e = calloc(1,sizeof(struct arm946e_common));
|
struct arm946e_common *arm946e = calloc(1, sizeof(struct arm946e_common));
|
||||||
|
|
||||||
arm946e_init_arch_info(target, arm946e, target->tap);
|
arm946e_init_arch_info(target, arm946e, target->tap);
|
||||||
|
|
||||||
|
@ -99,7 +101,7 @@ static int arm946e_target_create(struct target *target, Jim_Interp *interp)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int arm946e_verify_pointer(struct command_context *cmd_ctx,
|
static int arm946e_verify_pointer(struct command_context *cmd_ctx,
|
||||||
struct arm946e_common *arm946e)
|
struct arm946e_common *arm946e)
|
||||||
{
|
{
|
||||||
if (arm946e->common_magic != ARM946E_COMMON_MAGIC) {
|
if (arm946e->common_magic != ARM946E_COMMON_MAGIC) {
|
||||||
command_print(cmd_ctx, "target is not an ARM946");
|
command_print(cmd_ctx, "target is not an ARM946");
|
||||||
|
@ -123,10 +125,9 @@ static int arm946e_read_cp15(struct target *target, int reg_addr, uint32_t *valu
|
||||||
uint8_t reg_addr_buf = reg_addr & 0x3f;
|
uint8_t reg_addr_buf = reg_addr & 0x3f;
|
||||||
uint8_t nr_w_buf = 0;
|
uint8_t nr_w_buf = 0;
|
||||||
|
|
||||||
if ((retval = arm_jtag_scann(jtag_info, 0xf, TAP_IDLE)) != ERROR_OK)
|
retval = arm_jtag_scann(jtag_info, 0xf, TAP_IDLE);
|
||||||
{
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
|
||||||
retval = arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL, TAP_IDLE);
|
retval = arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL, TAP_IDLE);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
@ -157,10 +158,9 @@ static int arm946e_read_cp15(struct target *target, int reg_addr, uint32_t *valu
|
||||||
LOG_DEBUG("addr: 0x%x value: %8.8x", reg_addr, *value);
|
LOG_DEBUG("addr: 0x%x value: %8.8x", reg_addr, *value);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if ((retval = jtag_execute_queue()) != ERROR_OK)
|
retval = jtag_execute_queue();
|
||||||
{
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
@ -177,10 +177,9 @@ int arm946e_write_cp15(struct target *target, int reg_addr, uint32_t value)
|
||||||
|
|
||||||
buf_set_u32(value_buf, 0, 32, value);
|
buf_set_u32(value_buf, 0, 32, value);
|
||||||
|
|
||||||
if ((retval = arm_jtag_scann(jtag_info, 0xf, TAP_IDLE)) != ERROR_OK)
|
retval = arm_jtag_scann(jtag_info, 0xf, TAP_IDLE);
|
||||||
{
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
|
||||||
retval = arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL, TAP_IDLE);
|
retval = arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL, TAP_IDLE);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
@ -203,10 +202,9 @@ int arm946e_write_cp15(struct target *target, int reg_addr, uint32_t value)
|
||||||
LOG_DEBUG("addr: 0x%x value: %8.8x", reg_addr, value);
|
LOG_DEBUG("addr: 0x%x value: %8.8x", reg_addr, value);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if ((retval = jtag_execute_queue()) != ERROR_OK)
|
retval = jtag_execute_queue();
|
||||||
{
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
@ -214,21 +212,21 @@ int arm946e_write_cp15(struct target *target, int reg_addr, uint32_t value)
|
||||||
uint32_t arm946e_invalidate_whole_dcache(struct target *target)
|
uint32_t arm946e_invalidate_whole_dcache(struct target *target)
|
||||||
{
|
{
|
||||||
|
|
||||||
uint32_t csize = 0;
|
uint32_t csize = 0;
|
||||||
uint32_t shift = 0;
|
uint32_t shift = 0;
|
||||||
uint32_t cp15_idx, seg, dtag;
|
uint32_t cp15_idx, seg, dtag;
|
||||||
int nb_idx, idx = 0;
|
int nb_idx, idx = 0;
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
/* Get cache type */
|
/* Get cache type */
|
||||||
arm946e_read_cp15(target, 0x01, (uint32_t *) &csize);
|
arm946e_read_cp15(target, 0x01, (uint32_t *) &csize);
|
||||||
|
|
||||||
csize = (csize >> 18) & 0x0F;
|
csize = (csize >> 18) & 0x0F;
|
||||||
|
|
||||||
if (csize == 0)
|
if (csize == 0)
|
||||||
shift = 0;
|
shift = 0;
|
||||||
else
|
else
|
||||||
shift = csize - 0x3; /* Now 0 = 4KB, 1 = 8KB, ... */
|
shift = csize - 0x3; /* Now 0 = 4KB, 1 = 8KB, ... */
|
||||||
|
|
||||||
/* Cache size, given in bytes */
|
/* Cache size, given in bytes */
|
||||||
csize = 1 << (12 + shift);
|
csize = 1 << (12 + shift);
|
||||||
|
@ -236,16 +234,13 @@ uint32_t arm946e_invalidate_whole_dcache(struct target *target)
|
||||||
nb_idx = (csize / 32); /* gives nb of lines (indexes) in the cache */
|
nb_idx = (csize / 32); /* gives nb of lines (indexes) in the cache */
|
||||||
|
|
||||||
/* Loop for all segmentde (i.e. ways) */
|
/* Loop for all segmentde (i.e. ways) */
|
||||||
for( seg=0; seg < NB_CACHE_WAYS; seg++)
|
for (seg = 0; seg < NB_CACHE_WAYS; seg++) {
|
||||||
{
|
|
||||||
/* Loop for all indexes */
|
/* Loop for all indexes */
|
||||||
for(idx=0; idx < nb_idx; idx++)
|
for (idx = 0; idx < nb_idx; idx++) {
|
||||||
{
|
|
||||||
/* Form and write cp15 index (segment + line idx) */
|
/* Form and write cp15 index (segment + line idx) */
|
||||||
cp15_idx = seg << 30 | idx << 5;
|
cp15_idx = seg << 30 | idx << 5;
|
||||||
retval = arm946e_write_cp15(target, 0x3a, cp15_idx);
|
retval = arm946e_write_cp15(target, 0x3a, cp15_idx);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK) {
|
||||||
{
|
|
||||||
LOG_DEBUG("ERROR writing index");
|
LOG_DEBUG("ERROR writing index");
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
@ -254,21 +249,19 @@ uint32_t arm946e_invalidate_whole_dcache(struct target *target)
|
||||||
arm946e_read_cp15(target, 0x16, (uint32_t *) &dtag);
|
arm946e_read_cp15(target, 0x16, (uint32_t *) &dtag);
|
||||||
|
|
||||||
/* Check cache line VALID bit */
|
/* Check cache line VALID bit */
|
||||||
if ( !(dtag >> 4 & 0x1) )
|
if (!(dtag >> 4 & 0x1))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* Clean data cache line */
|
/* Clean data cache line */
|
||||||
retval = arm946e_write_cp15(target, 0x35, 0x1);
|
retval = arm946e_write_cp15(target, 0x35, 0x1);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK) {
|
||||||
{
|
|
||||||
LOG_DEBUG("ERROR cleaning cache line");
|
LOG_DEBUG("ERROR cleaning cache line");
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Flush data cache line */
|
/* Flush data cache line */
|
||||||
retval = arm946e_write_cp15(target, 0x1a, 0x1);
|
retval = arm946e_write_cp15(target, 0x1a, 0x1);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK) {
|
||||||
{
|
|
||||||
LOG_DEBUG("ERROR flushing cache line");
|
LOG_DEBUG("ERROR flushing cache line");
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
@ -289,8 +282,7 @@ uint32_t arm946e_invalidate_whole_icache(struct target *target)
|
||||||
* mcr 15, 0, r0, cr7, cr5, {0}
|
* mcr 15, 0, r0, cr7, cr5, {0}
|
||||||
*/
|
*/
|
||||||
retval = arm946e_write_cp15(target, 0x0f, 0x1);
|
retval = arm946e_write_cp15(target, 0x0f, 0x1);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK) {
|
||||||
{
|
|
||||||
LOG_DEBUG("ERROR flushing I$");
|
LOG_DEBUG("ERROR flushing I$");
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
@ -309,10 +301,8 @@ int arm946e_post_debug_entry(struct target *target)
|
||||||
dc = (ctr_reg >> 2) & 0x01;
|
dc = (ctr_reg >> 2) & 0x01;
|
||||||
ic = (ctr_reg >> 12) & 0x01;
|
ic = (ctr_reg >> 12) & 0x01;
|
||||||
|
|
||||||
if (arm946e_preserve_cache)
|
if (arm946e_preserve_cache) {
|
||||||
{
|
if (dc == 1) {
|
||||||
if (dc == 1)
|
|
||||||
{
|
|
||||||
/* Clean and flush D$ */
|
/* Clean and flush D$ */
|
||||||
arm946e_invalidate_whole_dcache(target);
|
arm946e_invalidate_whole_dcache(target);
|
||||||
|
|
||||||
|
@ -320,8 +310,7 @@ int arm946e_post_debug_entry(struct target *target)
|
||||||
ctr_reg &= ~(1 << 2);
|
ctr_reg &= ~(1 << 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ic == 1)
|
if (ic == 1) {
|
||||||
{
|
|
||||||
/* Flush I$ */
|
/* Flush I$ */
|
||||||
arm946e_invalidate_whole_icache(target);
|
arm946e_invalidate_whole_icache(target);
|
||||||
|
|
||||||
|
@ -331,12 +320,11 @@ int arm946e_post_debug_entry(struct target *target)
|
||||||
|
|
||||||
/* Write the new configuration */
|
/* Write the new configuration */
|
||||||
retval = arm946e_write_cp15(target, 0x02, ctr_reg);
|
retval = arm946e_write_cp15(target, 0x02, ctr_reg);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK) {
|
||||||
{
|
|
||||||
LOG_DEBUG("ERROR disabling cache");
|
LOG_DEBUG("ERROR disabling cache");
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
} /* if preserve_cache */
|
} /* if preserve_cache */
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
@ -346,8 +334,7 @@ void arm946e_pre_restore_context(struct target *target)
|
||||||
uint32_t ctr_reg = 0x0;
|
uint32_t ctr_reg = 0x0;
|
||||||
uint32_t retval;
|
uint32_t retval;
|
||||||
|
|
||||||
if (arm946e_preserve_cache)
|
if (arm946e_preserve_cache) {
|
||||||
{
|
|
||||||
/* Get the contents of the CTR reg */
|
/* Get the contents of the CTR reg */
|
||||||
arm946e_read_cp15(target, 0x02, (uint32_t *) &ctr_reg);
|
arm946e_read_cp15(target, 0x02, (uint32_t *) &ctr_reg);
|
||||||
|
|
||||||
|
@ -355,14 +342,12 @@ void arm946e_pre_restore_context(struct target *target)
|
||||||
* Read-modify-write CP15 test state register
|
* Read-modify-write CP15 test state register
|
||||||
* to reenable I/D-cache linefills
|
* to reenable I/D-cache linefills
|
||||||
*/
|
*/
|
||||||
if (dc == 1)
|
if (dc == 1) {
|
||||||
{
|
|
||||||
/* Enable D$ */
|
/* Enable D$ */
|
||||||
ctr_reg |= 1 << 2;
|
ctr_reg |= 1 << 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ic == 1)
|
if (ic == 1) {
|
||||||
{
|
|
||||||
/* Enable I$ */
|
/* Enable I$ */
|
||||||
ctr_reg |= 1 << 12;
|
ctr_reg |= 1 << 12;
|
||||||
}
|
}
|
||||||
|
@ -370,14 +355,12 @@ void arm946e_pre_restore_context(struct target *target)
|
||||||
/* Write the new configuration */
|
/* Write the new configuration */
|
||||||
retval = arm946e_write_cp15(target, 0x02, ctr_reg);
|
retval = arm946e_write_cp15(target, 0x02, ctr_reg);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
{
|
|
||||||
LOG_DEBUG("ERROR enabling cache");
|
LOG_DEBUG("ERROR enabling cache");
|
||||||
}
|
} /* if preserve_cache */
|
||||||
} /* if preserve_cache */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t arm946e_invalidate_dcache(struct target *target, uint32_t address,
|
uint32_t arm946e_invalidate_dcache(struct target *target, uint32_t address,
|
||||||
uint32_t size, uint32_t count)
|
uint32_t size, uint32_t count)
|
||||||
{
|
{
|
||||||
uint32_t csize = 0x0;
|
uint32_t csize = 0x0;
|
||||||
uint32_t shift = 0;
|
uint32_t shift = 0;
|
||||||
|
@ -386,8 +369,7 @@ uint32_t arm946e_invalidate_dcache(struct target *target, uint32_t address,
|
||||||
uint32_t i = 0;
|
uint32_t i = 0;
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
for(i = 0; i < count*size; i++)
|
for (i = 0; i < count*size; i++) {
|
||||||
{
|
|
||||||
cur_addr = address + i;
|
cur_addr = address + i;
|
||||||
|
|
||||||
/* Get cache type */
|
/* Get cache type */
|
||||||
|
@ -399,14 +381,13 @@ uint32_t arm946e_invalidate_dcache(struct target *target, uint32_t address,
|
||||||
if (csize == 0)
|
if (csize == 0)
|
||||||
shift = 0;
|
shift = 0;
|
||||||
else
|
else
|
||||||
shift = csize - 0x3; /* Now 0 = 4KB, 1 = 8KB, ... */
|
shift = csize - 0x3; /* Now 0 = 4KB, 1 = 8KB, ... */
|
||||||
|
|
||||||
csize = 1 << (12 + shift);
|
csize = 1 << (12 + shift);
|
||||||
|
|
||||||
set = (cur_addr >> 5) & 0xff; /* set field is 8 bits long */
|
set = (cur_addr >> 5) & 0xff; /* set field is 8 bits long */
|
||||||
|
|
||||||
for (way = 0; way < NB_CACHE_WAYS; way++)
|
for (way = 0; way < NB_CACHE_WAYS; way++) {
|
||||||
{
|
|
||||||
/**
|
/**
|
||||||
* Find if the affected address is kept in the cache.
|
* Find if the affected address is kept in the cache.
|
||||||
* Because JTAG Scan Chain 15 offers limited approach,
|
* Because JTAG Scan Chain 15 offers limited approach,
|
||||||
|
@ -417,8 +398,7 @@ uint32_t arm946e_invalidate_dcache(struct target *target, uint32_t address,
|
||||||
/* Form and write cp15 index (segment + line idx) */
|
/* Form and write cp15 index (segment + line idx) */
|
||||||
cp15_idx = way << 30 | set << 5;
|
cp15_idx = way << 30 | set << 5;
|
||||||
retval = arm946e_write_cp15(target, 0x3a, cp15_idx);
|
retval = arm946e_write_cp15(target, 0x3a, cp15_idx);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK) {
|
||||||
{
|
|
||||||
LOG_DEBUG("ERROR writing index");
|
LOG_DEBUG("ERROR writing index");
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
@ -427,57 +407,51 @@ uint32_t arm946e_invalidate_dcache(struct target *target, uint32_t address,
|
||||||
arm946e_read_cp15(target, 0x16, (uint32_t *) &dtag);
|
arm946e_read_cp15(target, 0x16, (uint32_t *) &dtag);
|
||||||
|
|
||||||
/* Check cache line VALID bit */
|
/* Check cache line VALID bit */
|
||||||
if ( !(dtag >> 4 & 0x1) )
|
if (!(dtag >> 4 & 0x1))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* If line is valid and corresponds to affected address - invalidate it */
|
/* If line is valid and corresponds to affected address - invalidate it */
|
||||||
if (dtag >> 5 == cur_addr >> 5)
|
if (dtag >> 5 == cur_addr >> 5) {
|
||||||
{
|
|
||||||
/* Clean data cache line */
|
/* Clean data cache line */
|
||||||
retval = arm946e_write_cp15(target, 0x35, 0x1);
|
retval = arm946e_write_cp15(target, 0x35, 0x1);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK) {
|
||||||
{
|
|
||||||
LOG_DEBUG("ERROR cleaning cache line");
|
LOG_DEBUG("ERROR cleaning cache line");
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Flush data cache line */
|
/* Flush data cache line */
|
||||||
retval = arm946e_write_cp15(target, 0x1c, 0x1);
|
retval = arm946e_write_cp15(target, 0x1c, 0x1);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK) {
|
||||||
{
|
|
||||||
LOG_DEBUG("ERROR flushing cache line");
|
LOG_DEBUG("ERROR flushing cache line");
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} /* loop through all 4 ways */
|
} /* loop through all 4 ways */
|
||||||
} /* loop through all addresses */
|
} /* loop through all addresses */
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t arm946e_invalidate_icache(struct target *target, uint32_t address,
|
uint32_t arm946e_invalidate_icache(struct target *target, uint32_t address,
|
||||||
uint32_t size, uint32_t count)
|
uint32_t size, uint32_t count)
|
||||||
{
|
{
|
||||||
uint32_t cur_addr = 0x0;
|
uint32_t cur_addr = 0x0;
|
||||||
uint32_t cp15_idx, set, way, itag;
|
uint32_t cp15_idx, set, way, itag;
|
||||||
uint32_t i = 0;
|
uint32_t i = 0;
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
for(i = 0; i < count*size; i++)
|
for (i = 0; i < count*size; i++) {
|
||||||
{
|
|
||||||
cur_addr = address + i;
|
cur_addr = address + i;
|
||||||
|
|
||||||
set = (cur_addr >> 5) & 0xff; /* set field is 8 bits long */
|
set = (cur_addr >> 5) & 0xff; /* set field is 8 bits long */
|
||||||
|
|
||||||
for (way = 0; way < NB_CACHE_WAYS; way++)
|
for (way = 0; way < NB_CACHE_WAYS; way++) {
|
||||||
{
|
|
||||||
/* Form and write cp15 index (segment + line idx) */
|
/* Form and write cp15 index (segment + line idx) */
|
||||||
cp15_idx = way << 30 | set << 5;
|
cp15_idx = way << 30 | set << 5;
|
||||||
retval = arm946e_write_cp15(target, 0x3a, cp15_idx);
|
retval = arm946e_write_cp15(target, 0x3a, cp15_idx);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK) {
|
||||||
{
|
|
||||||
LOG_DEBUG("ERROR writing index");
|
LOG_DEBUG("ERROR writing index");
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
@ -486,31 +460,29 @@ uint32_t arm946e_invalidate_icache(struct target *target, uint32_t address,
|
||||||
arm946e_read_cp15(target, 0x17, (uint32_t *) &itag);
|
arm946e_read_cp15(target, 0x17, (uint32_t *) &itag);
|
||||||
|
|
||||||
/* Check cache line VALID bit */
|
/* Check cache line VALID bit */
|
||||||
if ( !(itag >> 4 & 0x1) )
|
if (!(itag >> 4 & 0x1))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* If line is valid and corresponds to affected address - invalidate it */
|
/* If line is valid and corresponds to affected address - invalidate it */
|
||||||
if (itag >> 5 == cur_addr >> 5)
|
if (itag >> 5 == cur_addr >> 5) {
|
||||||
{
|
|
||||||
/* Flush I$ line */
|
/* Flush I$ line */
|
||||||
retval = arm946e_write_cp15(target, 0x1d, 0x0);
|
retval = arm946e_write_cp15(target, 0x1d, 0x0);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK) {
|
||||||
{
|
|
||||||
LOG_DEBUG("ERROR flushing cache line");
|
LOG_DEBUG("ERROR flushing cache line");
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} /* way loop */
|
} /* way loop */
|
||||||
} /* addr loop */
|
} /* addr loop */
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Writes a buffer, in the specified word size, with current MMU settings. */
|
/** Writes a buffer, in the specified word size, with current MMU settings. */
|
||||||
int arm946e_write_memory(struct target *target, uint32_t address,
|
int arm946e_write_memory(struct target *target, uint32_t address,
|
||||||
uint32_t size, uint32_t count, const uint8_t *buffer)
|
uint32_t size, uint32_t count, const uint8_t *buffer)
|
||||||
{
|
{
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
|
@ -518,18 +490,14 @@ int arm946e_write_memory(struct target *target, uint32_t address,
|
||||||
|
|
||||||
/* Invalidate D$ if it is ON */
|
/* Invalidate D$ if it is ON */
|
||||||
if (!arm946e_preserve_cache && dc == 1)
|
if (!arm946e_preserve_cache && dc == 1)
|
||||||
{
|
|
||||||
arm946e_invalidate_dcache(target, address, size, count);
|
arm946e_invalidate_dcache(target, address, size, count);
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Write memory
|
* Write memory
|
||||||
*/
|
*/
|
||||||
if ( ( retval = arm7_9_write_memory(target, address,
|
retval = arm7_9_write_memory(target, address, size, count, buffer);
|
||||||
size, count, buffer) ) != ERROR_OK )
|
if (retval != ERROR_OK)
|
||||||
{
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
|
||||||
|
|
||||||
/* *
|
/* *
|
||||||
* Invalidate I$ if it is ON.
|
* Invalidate I$ if it is ON.
|
||||||
|
@ -554,26 +522,22 @@ int arm946e_write_memory(struct target *target, uint32_t address,
|
||||||
* If the data is not in the cache, the controller writes to main memory only.
|
* If the data is not in the cache, the controller writes to main memory only.
|
||||||
*/
|
*/
|
||||||
if (!arm946e_preserve_cache && ic == 1)
|
if (!arm946e_preserve_cache && ic == 1)
|
||||||
{
|
|
||||||
arm946e_invalidate_icache(target, address, size, count);
|
arm946e_invalidate_icache(target, address, size, count);
|
||||||
}
|
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int arm946e_read_memory(struct target *target, uint32_t address,
|
int arm946e_read_memory(struct target *target, uint32_t address,
|
||||||
uint32_t size, uint32_t count, uint8_t *buffer)
|
uint32_t size, uint32_t count, uint8_t *buffer)
|
||||||
{
|
{
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
LOG_DEBUG("-");
|
LOG_DEBUG("-");
|
||||||
|
|
||||||
if ( ( retval = arm7_9_read_memory(target, address,
|
retval = arm7_9_read_memory(target, address, size, count, buffer);
|
||||||
size, count, buffer) ) != ERROR_OK )
|
if (retval != ERROR_OK)
|
||||||
{
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
@ -589,49 +553,37 @@ COMMAND_HANDLER(arm946e_handle_cp15_command)
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
if (target->state != TARGET_HALTED)
|
if (target->state != TARGET_HALTED) {
|
||||||
{
|
|
||||||
command_print(CMD_CTX, "target must be stopped for \"%s\" command", CMD_NAME);
|
command_print(CMD_CTX, "target must be stopped for \"%s\" command", CMD_NAME);
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* one or more argument, access a single register (write if second argument is given */
|
/* one or more argument, access a single register (write if second argument is given */
|
||||||
if (CMD_ARGC >= 1)
|
if (CMD_ARGC >= 1) {
|
||||||
{
|
|
||||||
uint32_t address;
|
uint32_t address;
|
||||||
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address);
|
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address);
|
||||||
|
|
||||||
if (CMD_ARGC == 1)
|
if (CMD_ARGC == 1) {
|
||||||
{
|
|
||||||
uint32_t value;
|
uint32_t value;
|
||||||
if ((retval = arm946e_read_cp15(target, address, &value)) != ERROR_OK)
|
retval = arm946e_read_cp15(target, address, &value);
|
||||||
{
|
if (retval != ERROR_OK) {
|
||||||
command_print(CMD_CTX,
|
command_print(CMD_CTX, "couldn't access reg %" PRIi32, address);
|
||||||
"couldn't access reg %" PRIi32,
|
|
||||||
address);
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
if ((retval = jtag_execute_queue()) != ERROR_OK)
|
retval = jtag_execute_queue();
|
||||||
{
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
|
||||||
|
|
||||||
command_print(CMD_CTX, "%" PRIi32 ": %8.8" PRIx32,
|
command_print(CMD_CTX, "%" PRIi32 ": %8.8" PRIx32, address, value);
|
||||||
address, value);
|
} else if (CMD_ARGC == 2) {
|
||||||
}
|
|
||||||
else if (CMD_ARGC == 2)
|
|
||||||
{
|
|
||||||
uint32_t value;
|
uint32_t value;
|
||||||
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], value);
|
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], value);
|
||||||
if ((retval = arm946e_write_cp15(target, address, value)) != ERROR_OK)
|
retval = arm946e_write_cp15(target, address, value);
|
||||||
{
|
if (retval != ERROR_OK) {
|
||||||
command_print(CMD_CTX,
|
command_print(CMD_CTX, "couldn't access reg %" PRIi32, address);
|
||||||
"couldn't access reg %" PRIi32,
|
|
||||||
address);
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
command_print(CMD_CTX, "%" PRIi32 ": %8.8" PRIx32,
|
command_print(CMD_CTX, "%" PRIi32 ": %8.8" PRIx32, address, value);
|
||||||
address, value);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -664,8 +616,7 @@ const struct command_registration arm946e_command_handlers[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Holds methods for ARM946 targets. */
|
/** Holds methods for ARM946 targets. */
|
||||||
struct target_type arm946e_target =
|
struct target_type arm946e_target = {
|
||||||
{
|
|
||||||
.name = "arm946e",
|
.name = "arm946e",
|
||||||
|
|
||||||
.poll = arm7_9_poll,
|
.poll = arm7_9_poll,
|
||||||
|
@ -683,8 +634,8 @@ struct target_type arm946e_target =
|
||||||
|
|
||||||
.get_gdb_reg_list = arm_get_gdb_reg_list,
|
.get_gdb_reg_list = arm_get_gdb_reg_list,
|
||||||
|
|
||||||
//.read_memory = arm7_9_read_memory,
|
/* .read_memory = arm7_9_read_memory, */
|
||||||
//.write_memory = arm7_9_write_memory,
|
/* .write_memory = arm7_9_write_memory, */
|
||||||
.read_memory = arm946e_read_memory,
|
.read_memory = arm946e_read_memory,
|
||||||
.write_memory = arm946e_write_memory,
|
.write_memory = arm946e_write_memory,
|
||||||
|
|
||||||
|
@ -697,8 +648,8 @@ struct target_type arm946e_target =
|
||||||
|
|
||||||
.add_breakpoint = arm7_9_add_breakpoint,
|
.add_breakpoint = arm7_9_add_breakpoint,
|
||||||
.remove_breakpoint = arm7_9_remove_breakpoint,
|
.remove_breakpoint = arm7_9_remove_breakpoint,
|
||||||
//.add_breakpoint = arm946e_add_breakpoint,
|
/* .add_breakpoint = arm946e_add_breakpoint, */
|
||||||
//.remove_breakpoint = arm946e_remove_breakpoint,
|
/* .remove_breakpoint = arm946e_remove_breakpoint, */
|
||||||
|
|
||||||
.add_watchpoint = arm7_9_add_watchpoint,
|
.add_watchpoint = arm7_9_add_watchpoint,
|
||||||
.remove_watchpoint = arm7_9_remove_watchpoint,
|
.remove_watchpoint = arm7_9_remove_watchpoint,
|
||||||
|
|
|
@ -23,31 +23,30 @@
|
||||||
* Free Software Foundation, Inc., *
|
* Free Software Foundation, Inc., *
|
||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#ifndef ARM946E_H
|
#ifndef ARM946E_H
|
||||||
#define ARM946E_H
|
#define ARM946E_H
|
||||||
|
|
||||||
#include "arm9tdmi.h"
|
#include "arm9tdmi.h"
|
||||||
|
|
||||||
#define ARM946E_COMMON_MAGIC 0x20f920f9
|
#define ARM946E_COMMON_MAGIC 0x20f920f9
|
||||||
|
|
||||||
struct arm946e_common
|
struct arm946e_common {
|
||||||
{
|
|
||||||
struct arm7_9_common arm7_9_common;
|
struct arm7_9_common arm7_9_common;
|
||||||
int common_magic;
|
int common_magic;
|
||||||
uint32_t cp15_control_reg;
|
uint32_t cp15_control_reg;
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline struct arm946e_common *
|
static inline struct arm946e_common *target_to_arm946(struct target *target)
|
||||||
target_to_arm946(struct target *target)
|
|
||||||
{
|
{
|
||||||
return container_of(target->arch_info, struct arm946e_common,
|
return container_of(target->arch_info, struct arm946e_common,
|
||||||
arm7_9_common.arm);
|
arm7_9_common.arm);
|
||||||
}
|
}
|
||||||
|
|
||||||
int arm946e_init_arch_info(struct target *target,
|
int arm946e_init_arch_info(struct target *target,
|
||||||
struct arm946e_common *arm946e, struct jtag_tap *tap);
|
struct arm946e_common *arm946e, struct jtag_tap *tap);
|
||||||
int arm946e_write_cp15(struct target *target, int reg_addr, uint32_t value);
|
int arm946e_write_cp15(struct target *target, int reg_addr, uint32_t value);
|
||||||
|
|
||||||
extern const struct command_registration arm946e_command_handlers[];
|
extern const struct command_registration arm946e_command_handlers[];
|
||||||
|
|
||||||
#endif /* ARM946E_H */
|
#endif /* ARM946E_H */
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
* Free Software Foundation, Inc., *
|
* Free Software Foundation, Inc., *
|
||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -28,7 +29,6 @@
|
||||||
#include "target_type.h"
|
#include "target_type.h"
|
||||||
#include "arm_opcodes.h"
|
#include "arm_opcodes.h"
|
||||||
|
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
#define _DEBUG_INSTRUCTION_EXECUTION_
|
#define _DEBUG_INSTRUCTION_EXECUTION_
|
||||||
#endif
|
#endif
|
||||||
|
@ -53,7 +53,7 @@ int arm966e_init_arch_info(struct target *target, struct arm966e_common *arm966e
|
||||||
|
|
||||||
static int arm966e_target_create(struct target *target, Jim_Interp *interp)
|
static int arm966e_target_create(struct target *target, Jim_Interp *interp)
|
||||||
{
|
{
|
||||||
struct arm966e_common *arm966e = calloc(1,sizeof(struct arm966e_common));
|
struct arm966e_common *arm966e = calloc(1, sizeof(struct arm966e_common));
|
||||||
|
|
||||||
return arm966e_init_arch_info(target, arm966e, target->tap);
|
return arm966e_init_arch_info(target, arm966e, target->tap);
|
||||||
}
|
}
|
||||||
|
@ -84,10 +84,9 @@ static int arm966e_read_cp15(struct target *target, int reg_addr, uint32_t *valu
|
||||||
uint8_t reg_addr_buf = reg_addr & 0x3f;
|
uint8_t reg_addr_buf = reg_addr & 0x3f;
|
||||||
uint8_t nr_w_buf = 0;
|
uint8_t nr_w_buf = 0;
|
||||||
|
|
||||||
if ((retval = arm_jtag_scann(jtag_info, 0xf, TAP_IDLE)) != ERROR_OK)
|
retval = arm_jtag_scann(jtag_info, 0xf, TAP_IDLE);
|
||||||
{
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
|
||||||
retval = arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL, TAP_IDLE);
|
retval = arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL, TAP_IDLE);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
@ -117,17 +116,16 @@ static int arm966e_read_cp15(struct target *target, int reg_addr, uint32_t *valu
|
||||||
|
|
||||||
|
|
||||||
#ifdef _DEBUG_INSTRUCTION_EXECUTION_
|
#ifdef _DEBUG_INSTRUCTION_EXECUTION_
|
||||||
if ((retval = jtag_execute_queue()) != ERROR_OK)
|
retval = jtag_execute_queue();
|
||||||
{
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
|
||||||
LOG_DEBUG("addr: 0x%x value: %8.8x", reg_addr, *value);
|
LOG_DEBUG("addr: 0x%x value: %8.8x", reg_addr, *value);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
// EXPORTED to str9x (flash)
|
/* EXPORTED to str9x (flash) */
|
||||||
int arm966e_write_cp15(struct target *target, int reg_addr, uint32_t value)
|
int arm966e_write_cp15(struct target *target, int reg_addr, uint32_t value)
|
||||||
{
|
{
|
||||||
int retval = ERROR_OK;
|
int retval = ERROR_OK;
|
||||||
|
@ -140,10 +138,9 @@ int arm966e_write_cp15(struct target *target, int reg_addr, uint32_t value)
|
||||||
|
|
||||||
buf_set_u32(value_buf, 0, 32, value);
|
buf_set_u32(value_buf, 0, 32, value);
|
||||||
|
|
||||||
if ((retval = arm_jtag_scann(jtag_info, 0xf, TAP_IDLE)) != ERROR_OK)
|
retval = arm_jtag_scann(jtag_info, 0xf, TAP_IDLE);
|
||||||
{
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
|
||||||
retval = arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL, TAP_IDLE);
|
retval = arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL, TAP_IDLE);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
@ -179,42 +176,36 @@ COMMAND_HANDLER(arm966e_handle_cp15_command)
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
if (target->state != TARGET_HALTED)
|
if (target->state != TARGET_HALTED) {
|
||||||
{
|
|
||||||
command_print(CMD_CTX, "target must be stopped for \"%s\" command", CMD_NAME);
|
command_print(CMD_CTX, "target must be stopped for \"%s\" command", CMD_NAME);
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* one or more argument, access a single register (write if second argument is given */
|
/* one or more argument, access a single register (write if second argument is given */
|
||||||
if (CMD_ARGC >= 1)
|
if (CMD_ARGC >= 1) {
|
||||||
{
|
|
||||||
uint32_t address;
|
uint32_t address;
|
||||||
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address);
|
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address);
|
||||||
|
|
||||||
if (CMD_ARGC == 1)
|
if (CMD_ARGC == 1) {
|
||||||
{
|
|
||||||
uint32_t value;
|
uint32_t value;
|
||||||
if ((retval = arm966e_read_cp15(target, address, &value)) != ERROR_OK)
|
retval = arm966e_read_cp15(target, address, &value);
|
||||||
{
|
if (retval != ERROR_OK) {
|
||||||
command_print(CMD_CTX,
|
command_print(CMD_CTX,
|
||||||
"couldn't access reg %" PRIi32,
|
"couldn't access reg %" PRIi32,
|
||||||
address);
|
address);
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
if ((retval = jtag_execute_queue()) != ERROR_OK)
|
retval = jtag_execute_queue();
|
||||||
{
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
|
||||||
|
|
||||||
command_print(CMD_CTX, "%" PRIi32 ": %8.8" PRIx32,
|
command_print(CMD_CTX, "%" PRIi32 ": %8.8" PRIx32,
|
||||||
address, value);
|
address, value);
|
||||||
}
|
} else if (CMD_ARGC == 2) {
|
||||||
else if (CMD_ARGC == 2)
|
|
||||||
{
|
|
||||||
uint32_t value;
|
uint32_t value;
|
||||||
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], value);
|
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], value);
|
||||||
if ((retval = arm966e_write_cp15(target, address, value)) != ERROR_OK)
|
retval = arm966e_write_cp15(target, address, value);
|
||||||
{
|
if (retval != ERROR_OK) {
|
||||||
command_print(CMD_CTX,
|
command_print(CMD_CTX,
|
||||||
"couldn't access reg %" PRIi32,
|
"couldn't access reg %" PRIi32,
|
||||||
address);
|
address);
|
||||||
|
@ -254,8 +245,7 @@ const struct command_registration arm966e_command_handlers[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Holds methods for ARM966 targets. */
|
/** Holds methods for ARM966 targets. */
|
||||||
struct target_type arm966e_target =
|
struct target_type arm966e_target = {
|
||||||
{
|
|
||||||
.name = "arm966e",
|
.name = "arm966e",
|
||||||
|
|
||||||
.poll = arm7_9_poll,
|
.poll = arm7_9_poll,
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
* Free Software Foundation, Inc., *
|
* Free Software Foundation, Inc., *
|
||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#ifndef ARM966E_H
|
#ifndef ARM966E_H
|
||||||
#define ARM966E_H
|
#define ARM966E_H
|
||||||
|
|
||||||
|
@ -27,8 +28,7 @@
|
||||||
|
|
||||||
#define ARM966E_COMMON_MAGIC 0x20f920f9
|
#define ARM966E_COMMON_MAGIC 0x20f920f9
|
||||||
|
|
||||||
struct arm966e_common
|
struct arm966e_common {
|
||||||
{
|
|
||||||
struct arm7_9_common arm7_9_common;
|
struct arm7_9_common arm7_9_common;
|
||||||
int common_magic;
|
int common_magic;
|
||||||
uint32_t cp15_control_reg;
|
uint32_t cp15_control_reg;
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
* Free Software Foundation, Inc., *
|
* Free Software Foundation, Inc., *
|
||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -32,7 +33,6 @@
|
||||||
#include "register.h"
|
#include "register.h"
|
||||||
#include "arm_opcodes.h"
|
#include "arm_opcodes.h"
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* NOTE: this holds code that's used with multiple ARM9 processors:
|
* NOTE: this holds code that's used with multiple ARM9 processors:
|
||||||
* - ARM9TDMI (ARMv4T) ... in ARM920, ARM922, and ARM940 cores
|
* - ARM9TDMI (ARMv4T) ... in ARM920, ARM922, and ARM940 cores
|
||||||
|
@ -47,8 +47,7 @@
|
||||||
#define _DEBUG_INSTRUCTION_EXECUTION_
|
#define _DEBUG_INSTRUCTION_EXECUTION_
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
enum arm9tdmi_vector_bit
|
enum arm9tdmi_vector_bit {
|
||||||
{
|
|
||||||
ARM9TDMI_RESET_VECTOR = 0x01,
|
ARM9TDMI_RESET_VECTOR = 0x01,
|
||||||
ARM9TDMI_UNDEF_VECTOR = 0x02,
|
ARM9TDMI_UNDEF_VECTOR = 0x02,
|
||||||
ARM9TDMI_SWI_VECTOR = 0x04,
|
ARM9TDMI_SWI_VECTOR = 0x04,
|
||||||
|
@ -80,8 +79,7 @@ int arm9tdmi_examine_debug_reason(struct target *target)
|
||||||
|
|
||||||
/* only check the debug reason if we don't know it already */
|
/* only check the debug reason if we don't know it already */
|
||||||
if ((target->debug_reason != DBG_REASON_DBGRQ)
|
if ((target->debug_reason != DBG_REASON_DBGRQ)
|
||||||
&& (target->debug_reason != DBG_REASON_SINGLESTEP))
|
&& (target->debug_reason != DBG_REASON_SINGLESTEP)) {
|
||||||
{
|
|
||||||
struct scan_field fields[3];
|
struct scan_field fields[3];
|
||||||
uint8_t databus[4];
|
uint8_t databus[4];
|
||||||
uint8_t instructionbus[4];
|
uint8_t instructionbus[4];
|
||||||
|
@ -99,19 +97,17 @@ int arm9tdmi_examine_debug_reason(struct target *target)
|
||||||
fields[2].out_value = NULL;
|
fields[2].out_value = NULL;
|
||||||
fields[2].in_value = instructionbus;
|
fields[2].in_value = instructionbus;
|
||||||
|
|
||||||
if ((retval = arm_jtag_scann(&arm7_9->jtag_info, 0x1, TAP_DRPAUSE)) != ERROR_OK)
|
retval = arm_jtag_scann(&arm7_9->jtag_info, 0x1, TAP_DRPAUSE);
|
||||||
{
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
|
||||||
retval = arm_jtag_set_instr(&arm7_9->jtag_info, arm7_9->jtag_info.intest_instr, NULL, TAP_DRPAUSE);
|
retval = arm_jtag_set_instr(&arm7_9->jtag_info, arm7_9->jtag_info.intest_instr, NULL, TAP_DRPAUSE);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
jtag_add_dr_scan(arm7_9->jtag_info.tap, 3, fields, TAP_DRPAUSE);
|
jtag_add_dr_scan(arm7_9->jtag_info.tap, 3, fields, TAP_DRPAUSE);
|
||||||
if ((retval = jtag_execute_queue()) != ERROR_OK)
|
retval = jtag_execute_queue();
|
||||||
{
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
|
||||||
|
|
||||||
fields[0].in_value = NULL;
|
fields[0].in_value = NULL;
|
||||||
fields[0].out_value = databus;
|
fields[0].out_value = databus;
|
||||||
|
@ -154,10 +150,9 @@ int arm9tdmi_clock_out(struct arm_jtag *jtag_info, uint32_t instr,
|
||||||
if (sysspeed)
|
if (sysspeed)
|
||||||
buf_set_u32(&sysspeed_buf, 2, 1, 1);
|
buf_set_u32(&sysspeed_buf, 2, 1, 1);
|
||||||
|
|
||||||
if ((retval = arm_jtag_scann(jtag_info, 0x1, TAP_DRPAUSE)) != ERROR_OK)
|
retval = arm_jtag_scann(jtag_info, 0x1, TAP_DRPAUSE);
|
||||||
{
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
|
||||||
|
|
||||||
retval = arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL, TAP_DRPAUSE);
|
retval = arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL, TAP_DRPAUSE);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
|
@ -175,31 +170,24 @@ int arm9tdmi_clock_out(struct arm_jtag *jtag_info, uint32_t instr,
|
||||||
fields[2].out_value = instr_buf;
|
fields[2].out_value = instr_buf;
|
||||||
fields[2].in_value = NULL;
|
fields[2].in_value = NULL;
|
||||||
|
|
||||||
if (in)
|
if (in) {
|
||||||
{
|
|
||||||
fields[0].in_value = (uint8_t *)in;
|
fields[0].in_value = (uint8_t *)in;
|
||||||
jtag_add_dr_scan(jtag_info->tap, 3, fields, TAP_DRPAUSE);
|
jtag_add_dr_scan(jtag_info->tap, 3, fields, TAP_DRPAUSE);
|
||||||
|
|
||||||
jtag_add_callback(arm_le_to_h_u32, (jtag_callback_data_t)in);
|
jtag_add_callback(arm_le_to_h_u32, (jtag_callback_data_t)in);
|
||||||
}
|
} else
|
||||||
else
|
|
||||||
{
|
|
||||||
jtag_add_dr_scan(jtag_info->tap, 3, fields, TAP_DRPAUSE);
|
jtag_add_dr_scan(jtag_info->tap, 3, fields, TAP_DRPAUSE);
|
||||||
}
|
|
||||||
|
|
||||||
jtag_add_runtest(0, TAP_DRPAUSE);
|
jtag_add_runtest(0, TAP_DRPAUSE);
|
||||||
|
|
||||||
#ifdef _DEBUG_INSTRUCTION_EXECUTION_
|
#ifdef _DEBUG_INSTRUCTION_EXECUTION_
|
||||||
{
|
{
|
||||||
if ((retval = jtag_execute_queue()) != ERROR_OK)
|
retval = jtag_execute_queue();
|
||||||
{
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
|
||||||
|
|
||||||
if (in)
|
if (in)
|
||||||
{
|
|
||||||
LOG_DEBUG("instr: 0x%8.8x, out: 0x%8.8x, in: 0x%8.8x", instr, out, *in);
|
LOG_DEBUG("instr: 0x%8.8x, out: 0x%8.8x, in: 0x%8.8x", instr, out, *in);
|
||||||
}
|
|
||||||
else
|
else
|
||||||
LOG_DEBUG("instr: 0x%8.8x, out: 0x%8.8x", instr, out);
|
LOG_DEBUG("instr: 0x%8.8x, out: 0x%8.8x", instr, out);
|
||||||
}
|
}
|
||||||
|
@ -211,13 +199,12 @@ int arm9tdmi_clock_out(struct arm_jtag *jtag_info, uint32_t instr,
|
||||||
/* just read data (instruction and data-out = don't care) */
|
/* just read data (instruction and data-out = don't care) */
|
||||||
int arm9tdmi_clock_data_in(struct arm_jtag *jtag_info, uint32_t *in)
|
int arm9tdmi_clock_data_in(struct arm_jtag *jtag_info, uint32_t *in)
|
||||||
{
|
{
|
||||||
int retval = ERROR_OK;;
|
int retval = ERROR_OK;
|
||||||
struct scan_field fields[3];
|
struct scan_field fields[3];
|
||||||
|
|
||||||
if ((retval = arm_jtag_scann(jtag_info, 0x1, TAP_DRPAUSE)) != ERROR_OK)
|
retval = arm_jtag_scann(jtag_info, 0x1, TAP_DRPAUSE);
|
||||||
{
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
|
||||||
|
|
||||||
retval = arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL, TAP_DRPAUSE);
|
retval = arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL, TAP_DRPAUSE);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
|
@ -243,19 +230,14 @@ int arm9tdmi_clock_data_in(struct arm_jtag *jtag_info, uint32_t *in)
|
||||||
|
|
||||||
#ifdef _DEBUG_INSTRUCTION_EXECUTION_
|
#ifdef _DEBUG_INSTRUCTION_EXECUTION_
|
||||||
{
|
{
|
||||||
if ((retval = jtag_execute_queue()) != ERROR_OK)
|
retval = jtag_execute_queue();
|
||||||
{
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
|
||||||
|
|
||||||
if (in)
|
if (in)
|
||||||
{
|
|
||||||
LOG_DEBUG("in: 0x%8.8x", *in);
|
LOG_DEBUG("in: 0x%8.8x", *in);
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
LOG_ERROR("BUG: called with in == NULL");
|
LOG_ERROR("BUG: called with in == NULL");
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -282,10 +264,9 @@ int arm9tdmi_clock_data_in_endianness(struct arm_jtag *jtag_info,
|
||||||
int retval = ERROR_OK;
|
int retval = ERROR_OK;
|
||||||
struct scan_field fields[3];
|
struct scan_field fields[3];
|
||||||
|
|
||||||
if ((retval = arm_jtag_scann(jtag_info, 0x1, TAP_DRPAUSE)) != ERROR_OK)
|
retval = arm_jtag_scann(jtag_info, 0x1, TAP_DRPAUSE);
|
||||||
{
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
|
||||||
|
|
||||||
retval = arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL, TAP_DRPAUSE);
|
retval = arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL, TAP_DRPAUSE);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
|
@ -315,19 +296,14 @@ int arm9tdmi_clock_data_in_endianness(struct arm_jtag *jtag_info,
|
||||||
|
|
||||||
#ifdef _DEBUG_INSTRUCTION_EXECUTION_
|
#ifdef _DEBUG_INSTRUCTION_EXECUTION_
|
||||||
{
|
{
|
||||||
if ((retval = jtag_execute_queue()) != ERROR_OK)
|
retval = jtag_execute_queue();
|
||||||
{
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
|
||||||
|
|
||||||
if (in)
|
if (in)
|
||||||
{
|
LOG_DEBUG("in: 0x%8.8x", *(uint32_t *)in);
|
||||||
LOG_DEBUG("in: 0x%8.8x", *(uint32_t*)in);
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
LOG_ERROR("BUG: called with in == NULL");
|
LOG_ERROR("BUG: called with in == NULL");
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -376,10 +352,9 @@ static void arm9tdmi_change_to_arm(struct target *target,
|
||||||
/* NOP fetched, BX in Execute (1) */
|
/* NOP fetched, BX in Execute (1) */
|
||||||
arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
|
||||||
|
|
||||||
if ((retval = jtag_execute_queue()) != ERROR_OK)
|
retval = jtag_execute_queue();
|
||||||
{
|
if (retval != ERROR_OK)
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
/* fix program counter:
|
/* fix program counter:
|
||||||
* MOV r0, r15 was the 5th instruction (+8)
|
* MOV r0, r15 was the 5th instruction (+8)
|
||||||
|
@ -389,7 +364,7 @@ static void arm9tdmi_change_to_arm(struct target *target,
|
||||||
}
|
}
|
||||||
|
|
||||||
void arm9tdmi_read_core_regs(struct target *target,
|
void arm9tdmi_read_core_regs(struct target *target,
|
||||||
uint32_t mask, uint32_t* core_regs[16])
|
uint32_t mask, uint32_t *core_regs[16])
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
|
struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
|
||||||
|
@ -405,8 +380,7 @@ void arm9tdmi_read_core_regs(struct target *target,
|
||||||
/* fetch NOP, STM in EXECUTE stage (1st cycle) */
|
/* fetch NOP, STM in EXECUTE stage (1st cycle) */
|
||||||
arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
|
||||||
|
|
||||||
for (i = 0; i <= 15; i++)
|
for (i = 0; i <= 15; i++) {
|
||||||
{
|
|
||||||
if (mask & (1 << i))
|
if (mask & (1 << i))
|
||||||
/* nothing fetched, STM in MEMORY (i'th cycle) */
|
/* nothing fetched, STM in MEMORY (i'th cycle) */
|
||||||
arm9tdmi_clock_data_in(jtag_info, core_regs[i]);
|
arm9tdmi_clock_data_in(jtag_info, core_regs[i]);
|
||||||
|
@ -414,7 +388,7 @@ void arm9tdmi_read_core_regs(struct target *target,
|
||||||
}
|
}
|
||||||
|
|
||||||
static void arm9tdmi_read_core_regs_target_buffer(struct target *target,
|
static void arm9tdmi_read_core_regs_target_buffer(struct target *target,
|
||||||
uint32_t mask, void* buffer, int size)
|
uint32_t mask, void *buffer, int size)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
|
struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
|
||||||
|
@ -434,12 +408,10 @@ static void arm9tdmi_read_core_regs_target_buffer(struct target *target,
|
||||||
/* fetch NOP, STM in EXECUTE stage (1st cycle) */
|
/* fetch NOP, STM in EXECUTE stage (1st cycle) */
|
||||||
arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
|
||||||
|
|
||||||
for (i = 0; i <= 15; i++)
|
for (i = 0; i <= 15; i++) {
|
||||||
{
|
|
||||||
if (mask & (1 << i))
|
if (mask & (1 << i))
|
||||||
/* nothing fetched, STM in MEMORY (i'th cycle) */
|
/* nothing fetched, STM in MEMORY (i'th cycle) */
|
||||||
switch (size)
|
switch (size) {
|
||||||
{
|
|
||||||
case 4:
|
case 4:
|
||||||
arm9tdmi_clock_data_in_endianness(jtag_info, buf_u32++, 4, be);
|
arm9tdmi_clock_data_in_endianness(jtag_info, buf_u32++, 4, be);
|
||||||
break;
|
break;
|
||||||
|
@ -525,8 +497,7 @@ static void arm9tdmi_write_xpsr_im8(struct target *target,
|
||||||
arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
|
||||||
|
|
||||||
/* rot == 4 writes flags, which takes only one cycle */
|
/* rot == 4 writes flags, which takes only one cycle */
|
||||||
if (rot != 4)
|
if (rot != 4) {
|
||||||
{
|
|
||||||
/* nothing fetched, MSR in EXECUTE (2) */
|
/* nothing fetched, MSR in EXECUTE (2) */
|
||||||
arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
|
||||||
/* nothing fetched, MSR in EXECUTE (3) */
|
/* nothing fetched, MSR in EXECUTE (3) */
|
||||||
|
@ -551,8 +522,7 @@ void arm9tdmi_write_core_regs(struct target *target,
|
||||||
/* fetch NOP, LDM in EXECUTE stage (1st cycle) */
|
/* fetch NOP, LDM in EXECUTE stage (1st cycle) */
|
||||||
arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
|
||||||
|
|
||||||
for (i = 0; i <= 15; i++)
|
for (i = 0; i <= 15; i++) {
|
||||||
{
|
|
||||||
if (mask & (1 << i))
|
if (mask & (1 << i))
|
||||||
/* nothing fetched, LDM still in EXECUTE (1 + i cycle) */
|
/* nothing fetched, LDM still in EXECUTE (1 + i cycle) */
|
||||||
arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, core_regs[i], NULL, 0);
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, core_regs[i], NULL, 0);
|
||||||
|
@ -718,30 +688,22 @@ void arm9tdmi_enable_single_step(struct target *target, uint32_t next_pc)
|
||||||
{
|
{
|
||||||
struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
|
struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
|
||||||
|
|
||||||
if (arm7_9->has_single_step)
|
if (arm7_9->has_single_step) {
|
||||||
{
|
|
||||||
buf_set_u32(arm7_9->eice_cache->reg_list[EICE_DBG_CTRL].value, 3, 1, 1);
|
buf_set_u32(arm7_9->eice_cache->reg_list[EICE_DBG_CTRL].value, 3, 1, 1);
|
||||||
embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_DBG_CTRL]);
|
embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_DBG_CTRL]);
|
||||||
}
|
} else
|
||||||
else
|
|
||||||
{
|
|
||||||
arm7_9_enable_eice_step(target, next_pc);
|
arm7_9_enable_eice_step(target, next_pc);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void arm9tdmi_disable_single_step(struct target *target)
|
void arm9tdmi_disable_single_step(struct target *target)
|
||||||
{
|
{
|
||||||
struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
|
struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
|
||||||
|
|
||||||
if (arm7_9->has_single_step)
|
if (arm7_9->has_single_step) {
|
||||||
{
|
|
||||||
buf_set_u32(arm7_9->eice_cache->reg_list[EICE_DBG_CTRL].value, 3, 1, 0);
|
buf_set_u32(arm7_9->eice_cache->reg_list[EICE_DBG_CTRL].value, 3, 1, 0);
|
||||||
embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_DBG_CTRL]);
|
embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_DBG_CTRL]);
|
||||||
}
|
} else
|
||||||
else
|
|
||||||
{
|
|
||||||
arm7_9_disable_eice_step(target);
|
arm7_9_disable_eice_step(target);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void arm9tdmi_build_reg_cache(struct target *target)
|
static void arm9tdmi_build_reg_cache(struct target *target)
|
||||||
|
@ -815,7 +777,7 @@ int arm9tdmi_init_arch_info(struct target *target,
|
||||||
|
|
||||||
static int arm9tdmi_target_create(struct target *target, Jim_Interp *interp)
|
static int arm9tdmi_target_create(struct target *target, Jim_Interp *interp)
|
||||||
{
|
{
|
||||||
struct arm7_9_common *arm7_9 = calloc(1,sizeof(struct arm7_9_common));
|
struct arm7_9_common *arm7_9 = calloc(1, sizeof(struct arm7_9_common));
|
||||||
|
|
||||||
arm9tdmi_init_arch_info(target, arm7_9, target->tap);
|
arm9tdmi_init_arch_info(target, arm7_9, target->tap);
|
||||||
arm7_9->arm.is_armv4 = true;
|
arm7_9->arm.is_armv4 = true;
|
||||||
|
@ -830,8 +792,7 @@ COMMAND_HANDLER(handle_arm9tdmi_catch_vectors_command)
|
||||||
struct reg *vector_catch;
|
struct reg *vector_catch;
|
||||||
uint32_t vector_catch_value;
|
uint32_t vector_catch_value;
|
||||||
|
|
||||||
if (!target_was_examined(target))
|
if (!target_was_examined(target)) {
|
||||||
{
|
|
||||||
LOG_ERROR("Target not examined yet");
|
LOG_ERROR("Target not examined yet");
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
@ -853,42 +814,31 @@ COMMAND_HANDLER(handle_arm9tdmi_catch_vectors_command)
|
||||||
/* get the current setting */
|
/* get the current setting */
|
||||||
vector_catch_value = buf_get_u32(vector_catch->value, 0, 8);
|
vector_catch_value = buf_get_u32(vector_catch->value, 0, 8);
|
||||||
|
|
||||||
if (CMD_ARGC > 0)
|
if (CMD_ARGC > 0) {
|
||||||
{
|
|
||||||
vector_catch_value = 0x0;
|
vector_catch_value = 0x0;
|
||||||
if (strcmp(CMD_ARGV[0], "all") == 0)
|
if (strcmp(CMD_ARGV[0], "all") == 0)
|
||||||
{
|
|
||||||
vector_catch_value = 0xdf;
|
vector_catch_value = 0xdf;
|
||||||
}
|
else if (strcmp(CMD_ARGV[0], "none") == 0) {
|
||||||
else if (strcmp(CMD_ARGV[0], "none") == 0)
|
|
||||||
{
|
|
||||||
/* do nothing */
|
/* do nothing */
|
||||||
}
|
} else {
|
||||||
else
|
for (unsigned i = 0; i < CMD_ARGC; i++) {
|
||||||
{
|
|
||||||
for (unsigned i = 0; i < CMD_ARGC; i++)
|
|
||||||
{
|
|
||||||
/* go through list of vectors */
|
/* go through list of vectors */
|
||||||
unsigned j;
|
unsigned j;
|
||||||
for (j = 0; arm9tdmi_vectors[j].name; j++)
|
for (j = 0; arm9tdmi_vectors[j].name; j++) {
|
||||||
{
|
if (strcmp(CMD_ARGV[i], arm9tdmi_vectors[j].name) == 0) {
|
||||||
if (strcmp(CMD_ARGV[i], arm9tdmi_vectors[j].name) == 0)
|
|
||||||
{
|
|
||||||
vector_catch_value |= arm9tdmi_vectors[j].value;
|
vector_catch_value |= arm9tdmi_vectors[j].value;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* complain if vector wasn't found */
|
/* complain if vector wasn't found */
|
||||||
if (!arm9tdmi_vectors[j].name)
|
if (!arm9tdmi_vectors[j].name) {
|
||||||
{
|
|
||||||
command_print(CMD_CTX, "vector '%s' not found, leaving current setting unchanged", CMD_ARGV[i]);
|
command_print(CMD_CTX, "vector '%s' not found, leaving current setting unchanged", CMD_ARGV[i]);
|
||||||
|
|
||||||
/* reread current setting */
|
/* reread current setting */
|
||||||
vector_catch_value = buf_get_u32(
|
vector_catch_value = buf_get_u32(
|
||||||
vector_catch->value,
|
vector_catch->value,
|
||||||
0, 8);
|
0, 8);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -935,8 +885,7 @@ const struct command_registration arm9tdmi_command_handlers[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Holds methods for ARM9TDMI targets. */
|
/** Holds methods for ARM9TDMI targets. */
|
||||||
struct target_type arm9tdmi_target =
|
struct target_type arm9tdmi_target = {
|
||||||
{
|
|
||||||
.name = "arm9tdmi",
|
.name = "arm9tdmi",
|
||||||
|
|
||||||
.poll = arm7_9_poll,
|
.poll = arm7_9_poll,
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
* Free Software Foundation, Inc., *
|
* Free Software Foundation, Inc., *
|
||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#ifndef ARM9TDMI_H
|
#ifndef ARM9TDMI_H
|
||||||
#define ARM9TDMI_H
|
#define ARM9TDMI_H
|
||||||
|
|
||||||
|
@ -37,7 +38,7 @@ int arm9tdmi_clock_data_in(struct arm_jtag *jtag_info, uint32_t *in);
|
||||||
int arm9tdmi_clock_data_in_endianness(struct arm_jtag *jtag_info,
|
int arm9tdmi_clock_data_in_endianness(struct arm_jtag *jtag_info,
|
||||||
void *in, int size, int be);
|
void *in, int size, int be);
|
||||||
void arm9tdmi_read_core_regs(struct target *target,
|
void arm9tdmi_read_core_regs(struct target *target,
|
||||||
uint32_t mask, uint32_t* core_regs[16]);
|
uint32_t mask, uint32_t *core_regs[16]);
|
||||||
void arm9tdmi_write_core_regs(struct target *target,
|
void arm9tdmi_write_core_regs(struct target *target,
|
||||||
uint32_t mask, uint32_t core_regs[16]);
|
uint32_t mask, uint32_t core_regs[16]);
|
||||||
|
|
||||||
|
|
|
@ -73,7 +73,6 @@
|
||||||
#include "arm_adi_v5.h"
|
#include "arm_adi_v5.h"
|
||||||
#include <helper/time_support.h>
|
#include <helper/time_support.h>
|
||||||
|
|
||||||
|
|
||||||
/* ARM ADI Specification requires at least 10 bits used for TAR autoincrement */
|
/* ARM ADI Specification requires at least 10 bits used for TAR autoincrement */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -100,12 +99,11 @@ static uint32_t max_tar_block_size(uint32_t tar_autoincr_block, uint32_t address
|
||||||
* @param apsel Number of the AP to (implicitly) use with further
|
* @param apsel Number of the AP to (implicitly) use with further
|
||||||
* transactions. This normally identifies a MEM-AP.
|
* transactions. This normally identifies a MEM-AP.
|
||||||
*/
|
*/
|
||||||
void dap_ap_select(struct adiv5_dap *dap,uint8_t ap)
|
void dap_ap_select(struct adiv5_dap *dap, uint8_t ap)
|
||||||
{
|
{
|
||||||
uint32_t new_ap = (ap << 24) & 0xFF000000;
|
uint32_t new_ap = (ap << 24) & 0xFF000000;
|
||||||
|
|
||||||
if (new_ap != dap->ap_current)
|
if (new_ap != dap->ap_current) {
|
||||||
{
|
|
||||||
dap->ap_current = new_ap;
|
dap->ap_current = new_ap;
|
||||||
/* Switching AP invalidates cached values.
|
/* Switching AP invalidates cached values.
|
||||||
* Values MUST BE UPDATED BEFORE AP ACCESS.
|
* Values MUST BE UPDATED BEFORE AP ACCESS.
|
||||||
|
@ -140,16 +138,14 @@ int dap_setup_accessport(struct adiv5_dap *dap, uint32_t csw, uint32_t tar)
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
csw = csw | CSW_DBGSWENABLE | CSW_MASTER_DEBUG | CSW_HPROT;
|
csw = csw | CSW_DBGSWENABLE | CSW_MASTER_DEBUG | CSW_HPROT;
|
||||||
if (csw != dap->ap_csw_value)
|
if (csw != dap->ap_csw_value) {
|
||||||
{
|
|
||||||
/* LOG_DEBUG("DAP: Set CSW %x",csw); */
|
/* LOG_DEBUG("DAP: Set CSW %x",csw); */
|
||||||
retval = dap_queue_ap_write(dap, AP_REG_CSW, csw);
|
retval = dap_queue_ap_write(dap, AP_REG_CSW, csw);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
dap->ap_csw_value = csw;
|
dap->ap_csw_value = csw;
|
||||||
}
|
}
|
||||||
if (tar != dap->ap_tar_value)
|
if (tar != dap->ap_tar_value) {
|
||||||
{
|
|
||||||
/* LOG_DEBUG("DAP: Set TAR %x",tar); */
|
/* LOG_DEBUG("DAP: Set TAR %x",tar); */
|
||||||
retval = dap_queue_ap_write(dap, AP_REG_TAR, tar);
|
retval = dap_queue_ap_write(dap, AP_REG_TAR, tar);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
|
@ -274,23 +270,20 @@ int mem_ap_write_buf_u32(struct adiv5_dap *dap, const uint8_t *buffer, int count
|
||||||
{
|
{
|
||||||
int wcount, blocksize, writecount, errorcount = 0, retval = ERROR_OK;
|
int wcount, blocksize, writecount, errorcount = 0, retval = ERROR_OK;
|
||||||
uint32_t adr = address;
|
uint32_t adr = address;
|
||||||
const uint8_t* pBuffer = buffer;
|
const uint8_t *pBuffer = buffer;
|
||||||
|
|
||||||
count >>= 2;
|
count >>= 2;
|
||||||
wcount = count;
|
wcount = count;
|
||||||
|
|
||||||
/* if we have an unaligned access - reorder data */
|
/* if we have an unaligned access - reorder data */
|
||||||
if (adr & 0x3u)
|
if (adr & 0x3u) {
|
||||||
{
|
for (writecount = 0; writecount < count; writecount++) {
|
||||||
for (writecount = 0; writecount < count; writecount++)
|
|
||||||
{
|
|
||||||
int i;
|
int i;
|
||||||
uint32_t outvalue;
|
uint32_t outvalue;
|
||||||
memcpy(&outvalue, pBuffer, sizeof(uint32_t));
|
memcpy(&outvalue, pBuffer, sizeof(uint32_t));
|
||||||
|
|
||||||
for (i = 0; i < 4; i++)
|
for (i = 0; i < 4; i++) {
|
||||||
{
|
*((uint8_t *)pBuffer + (adr & 0x3)) = outvalue;
|
||||||
*((uint8_t*)pBuffer + (adr & 0x3)) = outvalue;
|
|
||||||
outvalue >>= 8;
|
outvalue >>= 8;
|
||||||
adr++;
|
adr++;
|
||||||
}
|
}
|
||||||
|
@ -298,8 +291,7 @@ int mem_ap_write_buf_u32(struct adiv5_dap *dap, const uint8_t *buffer, int count
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
while (wcount > 0)
|
while (wcount > 0) {
|
||||||
{
|
|
||||||
/* Adjust to write blocks within boundaries aligned to the TAR autoincremnent size*/
|
/* Adjust to write blocks within boundaries aligned to the TAR autoincremnent size*/
|
||||||
blocksize = max_tar_block_size(dap->tar_autoincr_block, address);
|
blocksize = max_tar_block_size(dap->tar_autoincr_block, address);
|
||||||
if (wcount < blocksize)
|
if (wcount < blocksize)
|
||||||
|
@ -313,27 +305,22 @@ int mem_ap_write_buf_u32(struct adiv5_dap *dap, const uint8_t *buffer, int count
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
for (writecount = 0; writecount < blocksize; writecount++)
|
for (writecount = 0; writecount < blocksize; writecount++) {
|
||||||
{
|
|
||||||
retval = dap_queue_ap_write(dap, AP_REG_DRW,
|
retval = dap_queue_ap_write(dap, AP_REG_DRW,
|
||||||
*(uint32_t *) ((void *) (buffer + 4 * writecount)));
|
*(uint32_t *) ((void *) (buffer + 4 * writecount)));
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((retval = dap_run(dap)) == ERROR_OK)
|
retval = dap_run(dap);
|
||||||
{
|
if (retval == ERROR_OK) {
|
||||||
wcount = wcount - blocksize;
|
wcount = wcount - blocksize;
|
||||||
address = address + 4 * blocksize;
|
address = address + 4 * blocksize;
|
||||||
buffer = buffer + 4 * blocksize;
|
buffer = buffer + 4 * blocksize;
|
||||||
}
|
} else
|
||||||
else
|
|
||||||
{
|
|
||||||
errorcount++;
|
errorcount++;
|
||||||
}
|
|
||||||
|
|
||||||
if (errorcount > 1)
|
if (errorcount > 1) {
|
||||||
{
|
|
||||||
LOG_WARNING("Block write error address 0x%" PRIx32 ", wcount 0x%x", address, wcount);
|
LOG_WARNING("Block write error address 0x%" PRIx32 ", wcount 0x%x", address, wcount);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
@ -350,8 +337,7 @@ static int mem_ap_write_buf_packed_u16(struct adiv5_dap *dap,
|
||||||
|
|
||||||
wcount = count >> 1;
|
wcount = count >> 1;
|
||||||
|
|
||||||
while (wcount > 0)
|
while (wcount > 0) {
|
||||||
{
|
|
||||||
int nbytes;
|
int nbytes;
|
||||||
|
|
||||||
/* Adjust to write blocks within boundaries aligned to the TAR autoincremnent size*/
|
/* Adjust to write blocks within boundaries aligned to the TAR autoincremnent size*/
|
||||||
|
@ -369,16 +355,13 @@ static int mem_ap_write_buf_packed_u16(struct adiv5_dap *dap,
|
||||||
return retval;
|
return retval;
|
||||||
writecount = blocksize;
|
writecount = blocksize;
|
||||||
|
|
||||||
do
|
do {
|
||||||
{
|
|
||||||
nbytes = MIN((writecount << 1), 4);
|
nbytes = MIN((writecount << 1), 4);
|
||||||
|
|
||||||
if (nbytes < 4)
|
if (nbytes < 4) {
|
||||||
{
|
|
||||||
retval = mem_ap_write_buf_u16(dap, buffer,
|
retval = mem_ap_write_buf_u16(dap, buffer,
|
||||||
nbytes, address);
|
nbytes, address);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK) {
|
||||||
{
|
|
||||||
LOG_WARNING("Block write error address "
|
LOG_WARNING("Block write error address "
|
||||||
"0x%" PRIx32 ", count 0x%x",
|
"0x%" PRIx32 ", count 0x%x",
|
||||||
address, count);
|
address, count);
|
||||||
|
@ -386,15 +369,12 @@ static int mem_ap_write_buf_packed_u16(struct adiv5_dap *dap,
|
||||||
}
|
}
|
||||||
|
|
||||||
address += nbytes >> 1;
|
address += nbytes >> 1;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
uint32_t outvalue;
|
uint32_t outvalue;
|
||||||
memcpy(&outvalue, buffer, sizeof(uint32_t));
|
memcpy(&outvalue, buffer, sizeof(uint32_t));
|
||||||
|
|
||||||
for (i = 0; i < nbytes; i++)
|
for (i = 0; i < nbytes; i++) {
|
||||||
{
|
*((uint8_t *)buffer + (address & 0x3)) = outvalue;
|
||||||
*((uint8_t*)buffer + (address & 0x3)) = outvalue;
|
|
||||||
outvalue >>= 8;
|
outvalue >>= 8;
|
||||||
address++;
|
address++;
|
||||||
}
|
}
|
||||||
|
@ -405,8 +385,8 @@ static int mem_ap_write_buf_packed_u16(struct adiv5_dap *dap,
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if ((retval = dap_run(dap)) != ERROR_OK)
|
retval = dap_run(dap);
|
||||||
{
|
if (retval != ERROR_OK) {
|
||||||
LOG_WARNING("Block write error address "
|
LOG_WARNING("Block write error address "
|
||||||
"0x%" PRIx32 ", count 0x%x",
|
"0x%" PRIx32 ", count 0x%x",
|
||||||
address, count);
|
address, count);
|
||||||
|
@ -431,8 +411,7 @@ int mem_ap_write_buf_u16(struct adiv5_dap *dap, const uint8_t *buffer, int count
|
||||||
if (count >= 4)
|
if (count >= 4)
|
||||||
return mem_ap_write_buf_packed_u16(dap, buffer, count, address);
|
return mem_ap_write_buf_packed_u16(dap, buffer, count, address);
|
||||||
|
|
||||||
while (count > 0)
|
while (count > 0) {
|
||||||
{
|
|
||||||
retval = dap_setup_accessport(dap, CSW_16BIT | CSW_ADDRINC_SINGLE, address);
|
retval = dap_setup_accessport(dap, CSW_16BIT | CSW_ADDRINC_SINGLE, address);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
@ -463,8 +442,7 @@ static int mem_ap_write_buf_packed_u8(struct adiv5_dap *dap,
|
||||||
|
|
||||||
wcount = count;
|
wcount = count;
|
||||||
|
|
||||||
while (wcount > 0)
|
while (wcount > 0) {
|
||||||
{
|
|
||||||
int nbytes;
|
int nbytes;
|
||||||
|
|
||||||
/* Adjust to write blocks within boundaries aligned to the TAR autoincremnent size*/
|
/* Adjust to write blocks within boundaries aligned to the TAR autoincremnent size*/
|
||||||
|
@ -478,15 +456,12 @@ static int mem_ap_write_buf_packed_u8(struct adiv5_dap *dap,
|
||||||
return retval;
|
return retval;
|
||||||
writecount = blocksize;
|
writecount = blocksize;
|
||||||
|
|
||||||
do
|
do {
|
||||||
{
|
|
||||||
nbytes = MIN(writecount, 4);
|
nbytes = MIN(writecount, 4);
|
||||||
|
|
||||||
if (nbytes < 4)
|
if (nbytes < 4) {
|
||||||
{
|
|
||||||
retval = mem_ap_write_buf_u8(dap, buffer, nbytes, address);
|
retval = mem_ap_write_buf_u8(dap, buffer, nbytes, address);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK) {
|
||||||
{
|
|
||||||
LOG_WARNING("Block write error address "
|
LOG_WARNING("Block write error address "
|
||||||
"0x%" PRIx32 ", count 0x%x",
|
"0x%" PRIx32 ", count 0x%x",
|
||||||
address, count);
|
address, count);
|
||||||
|
@ -494,15 +469,12 @@ static int mem_ap_write_buf_packed_u8(struct adiv5_dap *dap,
|
||||||
}
|
}
|
||||||
|
|
||||||
address += nbytes;
|
address += nbytes;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
uint32_t outvalue;
|
uint32_t outvalue;
|
||||||
memcpy(&outvalue, buffer, sizeof(uint32_t));
|
memcpy(&outvalue, buffer, sizeof(uint32_t));
|
||||||
|
|
||||||
for (i = 0; i < nbytes; i++)
|
for (i = 0; i < nbytes; i++) {
|
||||||
{
|
*((uint8_t *)buffer + (address & 0x3)) = outvalue;
|
||||||
*((uint8_t*)buffer + (address & 0x3)) = outvalue;
|
|
||||||
outvalue >>= 8;
|
outvalue >>= 8;
|
||||||
address++;
|
address++;
|
||||||
}
|
}
|
||||||
|
@ -513,8 +485,8 @@ static int mem_ap_write_buf_packed_u8(struct adiv5_dap *dap,
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if ((retval = dap_run(dap)) != ERROR_OK)
|
retval = dap_run(dap);
|
||||||
{
|
if (retval != ERROR_OK) {
|
||||||
LOG_WARNING("Block write error address "
|
LOG_WARNING("Block write error address "
|
||||||
"0x%" PRIx32 ", count 0x%x",
|
"0x%" PRIx32 ", count 0x%x",
|
||||||
address, count);
|
address, count);
|
||||||
|
@ -539,8 +511,7 @@ int mem_ap_write_buf_u8(struct adiv5_dap *dap, const uint8_t *buffer, int count,
|
||||||
if (count >= 4)
|
if (count >= 4)
|
||||||
return mem_ap_write_buf_packed_u8(dap, buffer, count, address);
|
return mem_ap_write_buf_packed_u8(dap, buffer, count, address);
|
||||||
|
|
||||||
while (count > 0)
|
while (count > 0) {
|
||||||
{
|
|
||||||
retval = dap_setup_accessport(dap, CSW_8BIT | CSW_ADDRINC_SINGLE, address);
|
retval = dap_setup_accessport(dap, CSW_8BIT | CSW_ADDRINC_SINGLE, address);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
@ -581,13 +552,12 @@ int mem_ap_read_buf_u32(struct adiv5_dap *dap, uint8_t *buffer,
|
||||||
{
|
{
|
||||||
int wcount, blocksize, readcount, errorcount = 0, retval = ERROR_OK;
|
int wcount, blocksize, readcount, errorcount = 0, retval = ERROR_OK;
|
||||||
uint32_t adr = address;
|
uint32_t adr = address;
|
||||||
uint8_t* pBuffer = buffer;
|
uint8_t *pBuffer = buffer;
|
||||||
|
|
||||||
count >>= 2;
|
count >>= 2;
|
||||||
wcount = count;
|
wcount = count;
|
||||||
|
|
||||||
while (wcount > 0)
|
while (wcount > 0) {
|
||||||
{
|
|
||||||
/* Adjust to read blocks within boundaries aligned to the
|
/* Adjust to read blocks within boundaries aligned to the
|
||||||
* TAR autoincrement size (at least 2^10). Autoincrement
|
* TAR autoincrement size (at least 2^10). Autoincrement
|
||||||
* mode avoids an extra per-word roundtrip to update TAR.
|
* mode avoids an extra per-word roundtrip to update TAR.
|
||||||
|
@ -618,8 +588,7 @@ int mem_ap_read_buf_u32(struct adiv5_dap *dap, uint8_t *buffer,
|
||||||
DPAP_READ, 0, NULL, NULL);
|
DPAP_READ, 0, NULL, NULL);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
for (readcount = 0; readcount < blocksize - 1; readcount++)
|
for (readcount = 0; readcount < blocksize - 1; readcount++) {
|
||||||
{
|
|
||||||
/* Scan out next read; scan in posted value for the
|
/* Scan out next read; scan in posted value for the
|
||||||
* previous one. Assumes read is acked "OK/FAULT",
|
* previous one. Assumes read is acked "OK/FAULT",
|
||||||
* and CTRL_STAT says that meant "OK".
|
* and CTRL_STAT says that meant "OK".
|
||||||
|
@ -641,11 +610,9 @@ int mem_ap_read_buf_u32(struct adiv5_dap *dap, uint8_t *buffer,
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
retval = dap_run(dap);
|
retval = dap_run(dap);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK) {
|
||||||
{
|
|
||||||
errorcount++;
|
errorcount++;
|
||||||
if (errorcount <= 1)
|
if (errorcount <= 1) {
|
||||||
{
|
|
||||||
/* try again */
|
/* try again */
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -658,17 +625,14 @@ int mem_ap_read_buf_u32(struct adiv5_dap *dap, uint8_t *buffer,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if we have an unaligned access - reorder data */
|
/* if we have an unaligned access - reorder data */
|
||||||
if (adr & 0x3u)
|
if (adr & 0x3u) {
|
||||||
{
|
for (readcount = 0; readcount < count; readcount++) {
|
||||||
for (readcount = 0; readcount < count; readcount++)
|
|
||||||
{
|
|
||||||
int i;
|
int i;
|
||||||
uint32_t data;
|
uint32_t data;
|
||||||
memcpy(&data, pBuffer, sizeof(uint32_t));
|
memcpy(&data, pBuffer, sizeof(uint32_t));
|
||||||
|
|
||||||
for (i = 0; i < 4; i++)
|
for (i = 0; i < 4; i++) {
|
||||||
{
|
*((uint8_t *)pBuffer) =
|
||||||
*((uint8_t*)pBuffer) =
|
|
||||||
(data >> 8 * (adr & 0x3));
|
(data >> 8 * (adr & 0x3));
|
||||||
pBuffer++;
|
pBuffer++;
|
||||||
adr++;
|
adr++;
|
||||||
|
@ -688,8 +652,7 @@ static int mem_ap_read_buf_packed_u16(struct adiv5_dap *dap,
|
||||||
|
|
||||||
wcount = count >> 1;
|
wcount = count >> 1;
|
||||||
|
|
||||||
while (wcount > 0)
|
while (wcount > 0) {
|
||||||
{
|
|
||||||
int nbytes;
|
int nbytes;
|
||||||
|
|
||||||
/* Adjust to read blocks within boundaries aligned to the TAR autoincremnent size*/
|
/* Adjust to read blocks within boundaries aligned to the TAR autoincremnent size*/
|
||||||
|
@ -706,22 +669,20 @@ static int mem_ap_read_buf_packed_u16(struct adiv5_dap *dap,
|
||||||
blocksize = 1;
|
blocksize = 1;
|
||||||
readcount = blocksize;
|
readcount = blocksize;
|
||||||
|
|
||||||
do
|
do {
|
||||||
{
|
|
||||||
retval = dap_queue_ap_read(dap, AP_REG_DRW, &invalue);
|
retval = dap_queue_ap_read(dap, AP_REG_DRW, &invalue);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
if ((retval = dap_run(dap)) != ERROR_OK)
|
retval = dap_run(dap);
|
||||||
{
|
if (retval != ERROR_OK) {
|
||||||
LOG_WARNING("Block read error address 0x%" PRIx32 ", count 0x%x", address, count);
|
LOG_WARNING("Block read error address 0x%" PRIx32 ", count 0x%x", address, count);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
nbytes = MIN((readcount << 1), 4);
|
nbytes = MIN((readcount << 1), 4);
|
||||||
|
|
||||||
for (i = 0; i < nbytes; i++)
|
for (i = 0; i < nbytes; i++) {
|
||||||
{
|
*((uint8_t *)buffer) = (invalue >> 8 * (address & 0x3));
|
||||||
*((uint8_t*)buffer) = (invalue >> 8 * (address & 0x3));
|
|
||||||
buffer++;
|
buffer++;
|
||||||
address++;
|
address++;
|
||||||
}
|
}
|
||||||
|
@ -751,8 +712,7 @@ int mem_ap_read_buf_u16(struct adiv5_dap *dap, uint8_t *buffer,
|
||||||
if (count >= 4)
|
if (count >= 4)
|
||||||
return mem_ap_read_buf_packed_u16(dap, buffer, count, address);
|
return mem_ap_read_buf_packed_u16(dap, buffer, count, address);
|
||||||
|
|
||||||
while (count > 0)
|
while (count > 0) {
|
||||||
{
|
|
||||||
retval = dap_setup_accessport(dap, CSW_16BIT | CSW_ADDRINC_SINGLE, address);
|
retval = dap_setup_accessport(dap, CSW_16BIT | CSW_ADDRINC_SINGLE, address);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
@ -764,17 +724,13 @@ int mem_ap_read_buf_u16(struct adiv5_dap *dap, uint8_t *buffer,
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (address & 0x1)
|
if (address & 0x1) {
|
||||||
{
|
for (i = 0; i < 2; i++) {
|
||||||
for (i = 0; i < 2; i++)
|
*((uint8_t *)buffer) = (invalue >> 8 * (address & 0x3));
|
||||||
{
|
|
||||||
*((uint8_t*)buffer) = (invalue >> 8 * (address & 0x3));
|
|
||||||
buffer++;
|
buffer++;
|
||||||
address++;
|
address++;
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
uint16_t svalue = (invalue >> 8 * (address & 0x3));
|
uint16_t svalue = (invalue >> 8 * (address & 0x3));
|
||||||
memcpy(buffer, &svalue, sizeof(uint16_t));
|
memcpy(buffer, &svalue, sizeof(uint16_t));
|
||||||
address += 2;
|
address += 2;
|
||||||
|
@ -801,8 +757,7 @@ static int mem_ap_read_buf_packed_u8(struct adiv5_dap *dap,
|
||||||
|
|
||||||
wcount = count;
|
wcount = count;
|
||||||
|
|
||||||
while (wcount > 0)
|
while (wcount > 0) {
|
||||||
{
|
|
||||||
int nbytes;
|
int nbytes;
|
||||||
|
|
||||||
/* Adjust to read blocks within boundaries aligned to the TAR autoincremnent size*/
|
/* Adjust to read blocks within boundaries aligned to the TAR autoincremnent size*/
|
||||||
|
@ -816,22 +771,20 @@ static int mem_ap_read_buf_packed_u8(struct adiv5_dap *dap,
|
||||||
return retval;
|
return retval;
|
||||||
readcount = blocksize;
|
readcount = blocksize;
|
||||||
|
|
||||||
do
|
do {
|
||||||
{
|
|
||||||
retval = dap_queue_ap_read(dap, AP_REG_DRW, &invalue);
|
retval = dap_queue_ap_read(dap, AP_REG_DRW, &invalue);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
if ((retval = dap_run(dap)) != ERROR_OK)
|
retval = dap_run(dap);
|
||||||
{
|
if (retval != ERROR_OK) {
|
||||||
LOG_WARNING("Block read error address 0x%" PRIx32 ", count 0x%x", address, count);
|
LOG_WARNING("Block read error address 0x%" PRIx32 ", count 0x%x", address, count);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
nbytes = MIN(readcount, 4);
|
nbytes = MIN(readcount, 4);
|
||||||
|
|
||||||
for (i = 0; i < nbytes; i++)
|
for (i = 0; i < nbytes; i++) {
|
||||||
{
|
*((uint8_t *)buffer) = (invalue >> 8 * (address & 0x3));
|
||||||
*((uint8_t*)buffer) = (invalue >> 8 * (address & 0x3));
|
|
||||||
buffer++;
|
buffer++;
|
||||||
address++;
|
address++;
|
||||||
}
|
}
|
||||||
|
@ -861,8 +814,7 @@ int mem_ap_read_buf_u8(struct adiv5_dap *dap, uint8_t *buffer,
|
||||||
if (count >= 4)
|
if (count >= 4)
|
||||||
return mem_ap_read_buf_packed_u8(dap, buffer, count, address);
|
return mem_ap_read_buf_packed_u8(dap, buffer, count, address);
|
||||||
|
|
||||||
while (count > 0)
|
while (count > 0) {
|
||||||
{
|
|
||||||
retval = dap_setup_accessport(dap, CSW_8BIT | CSW_ADDRINC_SINGLE, address);
|
retval = dap_setup_accessport(dap, CSW_8BIT | CSW_ADDRINC_SINGLE, address);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
@ -873,7 +825,7 @@ int mem_ap_read_buf_u8(struct adiv5_dap *dap, uint8_t *buffer,
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
*((uint8_t*)buffer) = (invalue >> 8 * (address & 0x3));
|
*((uint8_t *)buffer) = (invalue >> 8 * (address & 0x3));
|
||||||
count--;
|
count--;
|
||||||
address++;
|
address++;
|
||||||
buffer++;
|
buffer++;
|
||||||
|
@ -999,9 +951,8 @@ int dap_syssec_kinetis_mdmap(struct adiv5_dap *dap)
|
||||||
return retval;
|
return retval;
|
||||||
dap_run(dap);
|
dap_run(dap);
|
||||||
|
|
||||||
if ( val != 0x001C0000 )
|
if (val != 0x001C0000) {
|
||||||
{
|
LOG_DEBUG("id doesn't match %08X != 0x001C0000", val);
|
||||||
LOG_DEBUG("id doesn't match %08X != 0x001C0000",val);
|
|
||||||
dap_ap_select(dap, 0);
|
dap_ap_select(dap, 0);
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
@ -1015,40 +966,28 @@ int dap_syssec_kinetis_mdmap(struct adiv5_dap *dap)
|
||||||
return retval;
|
return retval;
|
||||||
dap_run(dap);
|
dap_run(dap);
|
||||||
|
|
||||||
LOG_DEBUG("MDM_REG_STAT %08X",val);
|
LOG_DEBUG("MDM_REG_STAT %08X", val);
|
||||||
|
|
||||||
if ( (val & (MDM_STAT_SYSSEC|MDM_STAT_FREADY)) != (MDM_STAT_FREADY) )
|
if ((val & (MDM_STAT_SYSSEC|MDM_STAT_FREADY)) != (MDM_STAT_FREADY)) {
|
||||||
{
|
|
||||||
LOG_DEBUG("MDMAP: system is secured, masserase needed");
|
LOG_DEBUG("MDMAP: system is secured, masserase needed");
|
||||||
|
|
||||||
if ( !(val & MDM_STAT_FMEEN) )
|
if (!(val & MDM_STAT_FMEEN))
|
||||||
{
|
|
||||||
LOG_DEBUG("MDMAP: masserase is disabled");
|
LOG_DEBUG("MDMAP: masserase is disabled");
|
||||||
}
|
else {
|
||||||
else
|
|
||||||
{
|
|
||||||
/* we need to assert reset */
|
/* we need to assert reset */
|
||||||
if ( jtag_reset_config & RESET_HAS_SRST )
|
if (jtag_reset_config & RESET_HAS_SRST) {
|
||||||
{
|
|
||||||
/* default to asserting srst */
|
/* default to asserting srst */
|
||||||
if (jtag_reset_config & RESET_SRST_PULLS_TRST)
|
if (jtag_reset_config & RESET_SRST_PULLS_TRST)
|
||||||
{
|
|
||||||
jtag_add_reset(1, 1);
|
jtag_add_reset(1, 1);
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
jtag_add_reset(0, 1);
|
jtag_add_reset(0, 1);
|
||||||
}
|
} else {
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
LOG_DEBUG("SRST not configured");
|
LOG_DEBUG("SRST not configured");
|
||||||
dap_ap_select(dap, 0);
|
dap_ap_select(dap, 0);
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
while(1)
|
while (1) {
|
||||||
{
|
|
||||||
retval = dap_queue_ap_write(dap, MDM_REG_CTRL, MEM_CTRL_FMEIP);
|
retval = dap_queue_ap_write(dap, MDM_REG_CTRL, MEM_CTRL_FMEIP);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
@ -1058,14 +997,13 @@ int dap_syssec_kinetis_mdmap(struct adiv5_dap *dap)
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
dap_run(dap);
|
dap_run(dap);
|
||||||
LOG_DEBUG("MDM_REG_STAT %08X",val);
|
LOG_DEBUG("MDM_REG_STAT %08X", val);
|
||||||
|
|
||||||
if ( (val&1))
|
if ((val & 1))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
while(1)
|
while (1) {
|
||||||
{
|
|
||||||
retval = dap_queue_ap_write(dap, MDM_REG_CTRL, 0);
|
retval = dap_queue_ap_write(dap, MDM_REG_CTRL, 0);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
@ -1075,15 +1013,15 @@ int dap_syssec_kinetis_mdmap(struct adiv5_dap *dap)
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
dap_run(dap);
|
dap_run(dap);
|
||||||
LOG_DEBUG("MDM_REG_STAT %08X",val);
|
LOG_DEBUG("MDM_REG_STAT %08X", val);
|
||||||
/* read control register and wait for ready */
|
/* read control register and wait for ready */
|
||||||
retval = dap_queue_ap_read(dap, MDM_REG_CTRL, &val);
|
retval = dap_queue_ap_read(dap, MDM_REG_CTRL, &val);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
dap_run(dap);
|
dap_run(dap);
|
||||||
LOG_DEBUG("MDM_REG_CTRL %08X",val);
|
LOG_DEBUG("MDM_REG_CTRL %08X", val);
|
||||||
|
|
||||||
if ( val == 0x00 )
|
if (val == 0x00)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1107,7 +1045,6 @@ static struct dap_syssec_filter dap_syssec_filter_data[] = {
|
||||||
{ 0x4BA00477, dap_syssec_kinetis_mdmap }
|
{ 0x4BA00477, dap_syssec_kinetis_mdmap }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
@ -1116,15 +1053,12 @@ int dap_syssec(struct adiv5_dap *dap)
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
struct jtag_tap *tap;
|
struct jtag_tap *tap;
|
||||||
|
|
||||||
for(i=0;i<sizeof(dap_syssec_filter_data);i++)
|
for (i = 0; i < sizeof(dap_syssec_filter_data); i++) {
|
||||||
{
|
|
||||||
tap = dap->jtag_info->tap;
|
tap = dap->jtag_info->tap;
|
||||||
|
|
||||||
while (tap != NULL)
|
while (tap != NULL) {
|
||||||
{
|
if (tap->hasidcode && (dap_syssec_filter_data[i].idcode == tap->idcode)) {
|
||||||
if ( tap->hasidcode && (dap_syssec_filter_data[i].idcode == tap->idcode) )
|
LOG_DEBUG("DAP: mdmap_init for idcode: %08x", tap->idcode);
|
||||||
{
|
|
||||||
LOG_DEBUG("DAP: mdmap_init for idcode: %08x",tap->idcode);
|
|
||||||
dap_syssec_filter_data[i].dap_init(dap);
|
dap_syssec_filter_data[i].dap_init(dap);
|
||||||
}
|
}
|
||||||
tap = tap->next_tap;
|
tap = tap->next_tap;
|
||||||
|
@ -1202,28 +1136,29 @@ int ahbap_debugport_init(struct adiv5_dap *dap)
|
||||||
retval = dap_queue_dp_read(dap, DP_CTRL_STAT, &ctrlstat);
|
retval = dap_queue_dp_read(dap, DP_CTRL_STAT, &ctrlstat);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
if ((retval = dap_run(dap)) != ERROR_OK)
|
retval = dap_run(dap);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
/* Check that we have debug power domains activated */
|
/* Check that we have debug power domains activated */
|
||||||
while (!(ctrlstat & CDBGPWRUPACK) && (cnt++ < 10))
|
while (!(ctrlstat & CDBGPWRUPACK) && (cnt++ < 10)) {
|
||||||
{
|
|
||||||
LOG_DEBUG("DAP: wait CDBGPWRUPACK");
|
LOG_DEBUG("DAP: wait CDBGPWRUPACK");
|
||||||
retval = dap_queue_dp_read(dap, DP_CTRL_STAT, &ctrlstat);
|
retval = dap_queue_dp_read(dap, DP_CTRL_STAT, &ctrlstat);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
if ((retval = dap_run(dap)) != ERROR_OK)
|
retval = dap_run(dap);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
alive_sleep(10);
|
alive_sleep(10);
|
||||||
}
|
}
|
||||||
|
|
||||||
while (!(ctrlstat & CSYSPWRUPACK) && (cnt++ < 10))
|
while (!(ctrlstat & CSYSPWRUPACK) && (cnt++ < 10)) {
|
||||||
{
|
|
||||||
LOG_DEBUG("DAP: wait CSYSPWRUPACK");
|
LOG_DEBUG("DAP: wait CSYSPWRUPACK");
|
||||||
retval = dap_queue_dp_read(dap, DP_CTRL_STAT, &ctrlstat);
|
retval = dap_queue_dp_read(dap, DP_CTRL_STAT, &ctrlstat);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
if ((retval = dap_run(dap)) != ERROR_OK)
|
retval = dap_run(dap);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
alive_sleep(10);
|
alive_sleep(10);
|
||||||
}
|
}
|
||||||
|
@ -1248,16 +1183,15 @@ int ahbap_debugport_init(struct adiv5_dap *dap)
|
||||||
/* CID interpretation -- see ARM IHI 0029B section 3
|
/* CID interpretation -- see ARM IHI 0029B section 3
|
||||||
* and ARM IHI 0031A table 13-3.
|
* and ARM IHI 0031A table 13-3.
|
||||||
*/
|
*/
|
||||||
static const char *class_description[16] ={
|
static const char *class_description[16] = {
|
||||||
"Reserved", "ROM table", "Reserved", "Reserved",
|
"Reserved", "ROM table", "Reserved", "Reserved",
|
||||||
"Reserved", "Reserved", "Reserved", "Reserved",
|
"Reserved", "Reserved", "Reserved", "Reserved",
|
||||||
"Reserved", "CoreSight component", "Reserved", "Peripheral Test Block",
|
"Reserved", "CoreSight component", "Reserved", "Peripheral Test Block",
|
||||||
"Reserved", "OptimoDE DESS",
|
"Reserved", "OptimoDE DESS",
|
||||||
"Generic IP component", "PrimeCell or System component"
|
"Generic IP component", "PrimeCell or System component"
|
||||||
};
|
};
|
||||||
|
|
||||||
static bool
|
static bool is_dap_cid_ok(uint32_t cid3, uint32_t cid2, uint32_t cid1, uint32_t cid0)
|
||||||
is_dap_cid_ok(uint32_t cid3, uint32_t cid2, uint32_t cid1, uint32_t cid0)
|
|
||||||
{
|
{
|
||||||
return cid3 == 0xb1 && cid2 == 0x05
|
return cid3 == 0xb1 && cid2 == 0x05
|
||||||
&& ((cid1 & 0x0f) == 0) && cid0 == 0x0d;
|
&& ((cid1 & 0x0f) == 0) && cid0 == 0x0d;
|
||||||
|
@ -1320,8 +1254,7 @@ int dap_lookup_cs_component(struct adiv5_dap *dap, int ap,
|
||||||
ap_old = dap->ap_current;
|
ap_old = dap->ap_current;
|
||||||
dap_ap_select(dap, ap);
|
dap_ap_select(dap, ap);
|
||||||
|
|
||||||
do
|
do {
|
||||||
{
|
|
||||||
retval = mem_ap_read_atomic_u32(dap, (dbgbase&0xFFFFF000) |
|
retval = mem_ap_read_atomic_u32(dap, (dbgbase&0xFFFFF000) |
|
||||||
entry_offset, &romentry);
|
entry_offset, &romentry);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
|
@ -1367,10 +1300,8 @@ static int dap_info_command(struct command_context *cmd_ctx,
|
||||||
/* Now we read ROM table ID registers, ref. ARM IHI 0029B sec */
|
/* Now we read ROM table ID registers, ref. ARM IHI 0029B sec */
|
||||||
mem_ap = ((apid&0x10000) && ((apid&0x0F) != 0));
|
mem_ap = ((apid&0x10000) && ((apid&0x0F) != 0));
|
||||||
command_print(cmd_ctx, "AP ID register 0x%8.8" PRIx32, apid);
|
command_print(cmd_ctx, "AP ID register 0x%8.8" PRIx32, apid);
|
||||||
if (apid)
|
if (apid) {
|
||||||
{
|
switch (apid&0x0F) {
|
||||||
switch (apid&0x0F)
|
|
||||||
{
|
|
||||||
case 0:
|
case 0:
|
||||||
command_print(cmd_ctx, "\tType is JTAG-AP");
|
command_print(cmd_ctx, "\tType is JTAG-AP");
|
||||||
break;
|
break;
|
||||||
|
@ -1389,18 +1320,13 @@ static int dap_info_command(struct command_context *cmd_ctx,
|
||||||
* not a ROM table ... or have no such components at all.
|
* not a ROM table ... or have no such components at all.
|
||||||
*/
|
*/
|
||||||
if (mem_ap)
|
if (mem_ap)
|
||||||
command_print(cmd_ctx, "AP BASE 0x%8.8" PRIx32,
|
command_print(cmd_ctx, "AP BASE 0x%8.8" PRIx32, dbgbase);
|
||||||
dbgbase);
|
} else
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
command_print(cmd_ctx, "No AP found at this ap 0x%x", ap);
|
command_print(cmd_ctx, "No AP found at this ap 0x%x", ap);
|
||||||
}
|
|
||||||
|
|
||||||
romtable_present = ((mem_ap) && (dbgbase != 0xFFFFFFFF));
|
romtable_present = ((mem_ap) && (dbgbase != 0xFFFFFFFF));
|
||||||
if (romtable_present)
|
if (romtable_present) {
|
||||||
{
|
uint32_t cid0, cid1, cid2, cid3, memtype, romentry;
|
||||||
uint32_t cid0,cid1,cid2,cid3,memtype,romentry;
|
|
||||||
uint16_t entry_offset;
|
uint16_t entry_offset;
|
||||||
|
|
||||||
/* bit 16 of apid indicates a memory access port */
|
/* bit 16 of apid indicates a memory access port */
|
||||||
|
@ -1444,78 +1370,61 @@ static int dap_info_command(struct command_context *cmd_ctx,
|
||||||
|
|
||||||
/* Now we read ROM table entries from dbgbase&0xFFFFF000) | 0x000 until we get 0x00000000 */
|
/* Now we read ROM table entries from dbgbase&0xFFFFF000) | 0x000 until we get 0x00000000 */
|
||||||
entry_offset = 0;
|
entry_offset = 0;
|
||||||
do
|
do {
|
||||||
{
|
|
||||||
retval = mem_ap_read_atomic_u32(dap, (dbgbase&0xFFFFF000) | entry_offset, &romentry);
|
retval = mem_ap_read_atomic_u32(dap, (dbgbase&0xFFFFF000) | entry_offset, &romentry);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
command_print(cmd_ctx, "\tROMTABLE[0x%x] = 0x%" PRIx32 "",entry_offset,romentry);
|
command_print(cmd_ctx, "\tROMTABLE[0x%x] = 0x%" PRIx32 "", entry_offset, romentry);
|
||||||
if (romentry&0x01)
|
if (romentry & 0x01) {
|
||||||
{
|
|
||||||
uint32_t c_cid0, c_cid1, c_cid2, c_cid3;
|
uint32_t c_cid0, c_cid1, c_cid2, c_cid3;
|
||||||
uint32_t c_pid0, c_pid1, c_pid2, c_pid3, c_pid4;
|
uint32_t c_pid0, c_pid1, c_pid2, c_pid3, c_pid4;
|
||||||
uint32_t component_base;
|
uint32_t component_base;
|
||||||
unsigned part_num;
|
unsigned part_num;
|
||||||
char *type, *full;
|
char *type, *full;
|
||||||
|
|
||||||
component_base = (dbgbase & 0xFFFFF000)
|
component_base = (dbgbase & 0xFFFFF000) + (romentry & 0xFFFFF000);
|
||||||
+ (romentry & 0xFFFFF000);
|
|
||||||
|
|
||||||
/* IDs are in last 4K section */
|
/* IDs are in last 4K section */
|
||||||
|
retval = mem_ap_read_atomic_u32(dap, component_base + 0xFE0, &c_pid0);
|
||||||
|
|
||||||
retval = mem_ap_read_atomic_u32(dap,
|
|
||||||
component_base + 0xFE0, &c_pid0);
|
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
c_pid0 &= 0xff;
|
c_pid0 &= 0xff;
|
||||||
retval = mem_ap_read_atomic_u32(dap,
|
retval = mem_ap_read_atomic_u32(dap, component_base + 0xFE4, &c_pid1);
|
||||||
component_base + 0xFE4, &c_pid1);
|
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
c_pid1 &= 0xff;
|
c_pid1 &= 0xff;
|
||||||
retval = mem_ap_read_atomic_u32(dap,
|
retval = mem_ap_read_atomic_u32(dap, component_base + 0xFE8, &c_pid2);
|
||||||
component_base + 0xFE8, &c_pid2);
|
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
c_pid2 &= 0xff;
|
c_pid2 &= 0xff;
|
||||||
retval = mem_ap_read_atomic_u32(dap,
|
retval = mem_ap_read_atomic_u32(dap, component_base + 0xFEC, &c_pid3);
|
||||||
component_base + 0xFEC, &c_pid3);
|
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
c_pid3 &= 0xff;
|
c_pid3 &= 0xff;
|
||||||
retval = mem_ap_read_atomic_u32(dap,
|
retval = mem_ap_read_atomic_u32(dap, component_base + 0xFD0, &c_pid4);
|
||||||
component_base + 0xFD0, &c_pid4);
|
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
c_pid4 &= 0xff;
|
c_pid4 &= 0xff;
|
||||||
|
|
||||||
retval = mem_ap_read_atomic_u32(dap,
|
retval = mem_ap_read_atomic_u32(dap, component_base + 0xFF0, &c_cid0);
|
||||||
component_base + 0xFF0, &c_cid0);
|
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
c_cid0 &= 0xff;
|
c_cid0 &= 0xff;
|
||||||
retval = mem_ap_read_atomic_u32(dap,
|
retval = mem_ap_read_atomic_u32(dap, component_base + 0xFF4, &c_cid1);
|
||||||
component_base + 0xFF4, &c_cid1);
|
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
c_cid1 &= 0xff;
|
c_cid1 &= 0xff;
|
||||||
retval = mem_ap_read_atomic_u32(dap,
|
retval = mem_ap_read_atomic_u32(dap, component_base + 0xFF8, &c_cid2);
|
||||||
component_base + 0xFF8, &c_cid2);
|
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
c_cid2 &= 0xff;
|
c_cid2 &= 0xff;
|
||||||
retval = mem_ap_read_atomic_u32(dap,
|
retval = mem_ap_read_atomic_u32(dap, component_base + 0xFFC, &c_cid3);
|
||||||
component_base + 0xFFC, &c_cid3);
|
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
c_cid3 &= 0xff;
|
c_cid3 &= 0xff;
|
||||||
|
|
||||||
|
command_print(cmd_ctx, "\t\tComponent base address 0x%" PRIx32 ","
|
||||||
command_print(cmd_ctx,
|
"start address 0x%" PRIx32, component_base,
|
||||||
"\t\tComponent base address 0x%" PRIx32
|
|
||||||
", start address 0x%" PRIx32,
|
|
||||||
component_base,
|
|
||||||
/* component may take multiple 4K pages */
|
/* component may take multiple 4K pages */
|
||||||
component_base - 0x1000*(c_pid4 >> 4));
|
component_base - 0x1000*(c_pid4 >> 4));
|
||||||
command_print(cmd_ctx, "\t\tComponent class is 0x%x, %s",
|
command_print(cmd_ctx, "\t\tComponent class is 0x%x, %s",
|
||||||
|
@ -1638,7 +1547,7 @@ static int dap_info_command(struct command_context *cmd_ctx,
|
||||||
|
|
||||||
if (!is_dap_cid_ok(cid3, cid2, cid1, cid0))
|
if (!is_dap_cid_ok(cid3, cid2, cid1, cid0))
|
||||||
command_print(cmd_ctx,
|
command_print(cmd_ctx,
|
||||||
"\t\tCID3 0%2.2x"
|
"\t\tCID3 0%2.2x"
|
||||||
", CID2 0%2.2x"
|
", CID2 0%2.2x"
|
||||||
", CID1 0%2.2x"
|
", CID1 0%2.2x"
|
||||||
", CID0 0%2.2x",
|
", CID0 0%2.2x",
|
||||||
|
@ -1681,7 +1590,7 @@ static int dap_info_command(struct command_context *cmd_ctx,
|
||||||
type = "CoreSight ETM11";
|
type = "CoreSight ETM11";
|
||||||
full = "(Embedded Trace)";
|
full = "(Embedded Trace)";
|
||||||
break;
|
break;
|
||||||
// case 0x113: what?
|
/* case 0x113: what? */
|
||||||
case 0x120: /* from OMAP3 memmap */
|
case 0x120: /* from OMAP3 memmap */
|
||||||
type = "TI SDTI";
|
type = "TI SDTI";
|
||||||
full = "(System Debug Trace Interface)";
|
full = "(System Debug Trace Interface)";
|
||||||
|
@ -1741,9 +1650,7 @@ static int dap_info_command(struct command_context *cmd_ctx,
|
||||||
}
|
}
|
||||||
command_print(cmd_ctx, "\t\tPart is %s %s",
|
command_print(cmd_ctx, "\t\tPart is %s %s",
|
||||||
type, full);
|
type, full);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
if (romentry)
|
if (romentry)
|
||||||
command_print(cmd_ctx, "\t\tComponent not present");
|
command_print(cmd_ctx, "\t\tComponent not present");
|
||||||
else
|
else
|
||||||
|
@ -1751,11 +1658,8 @@ static int dap_info_command(struct command_context *cmd_ctx,
|
||||||
}
|
}
|
||||||
entry_offset += 4;
|
entry_offset += 4;
|
||||||
} while (romentry > 0);
|
} while (romentry > 0);
|
||||||
}
|
} else
|
||||||
else
|
|
||||||
{
|
|
||||||
command_print(cmd_ctx, "\tNo ROM table present");
|
command_print(cmd_ctx, "\tNo ROM table present");
|
||||||
}
|
|
||||||
dap_ap_select(dap, ap_old);
|
dap_ap_select(dap, ap_old);
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
|
@ -1980,5 +1884,3 @@ const struct command_registration dap_command_handlers[] = {
|
||||||
},
|
},
|
||||||
COMMAND_REGISTRATION_DONE
|
COMMAND_REGISTRATION_DONE
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
* Free Software Foundation, Inc., *
|
* Free Software Foundation, Inc., *
|
||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#ifndef ARM_ADI_V5_H
|
#ifndef ARM_ADI_V5_H
|
||||||
#define ARM_ADI_V5_H
|
#define ARM_ADI_V5_H
|
||||||
|
|
||||||
|
@ -133,15 +134,13 @@
|
||||||
* as part of setting up a debug session (if all the dual-role JTAG/SWD
|
* as part of setting up a debug session (if all the dual-role JTAG/SWD
|
||||||
* signals are available).
|
* signals are available).
|
||||||
*/
|
*/
|
||||||
struct adiv5_dap
|
struct adiv5_dap {
|
||||||
{
|
|
||||||
const struct dap_ops *ops;
|
const struct dap_ops *ops;
|
||||||
|
|
||||||
struct arm_jtag *jtag_info;
|
struct arm_jtag *jtag_info;
|
||||||
/* Control config */
|
/* Control config */
|
||||||
uint32_t dp_ctrl_stat;
|
uint32_t dp_ctrl_stat;
|
||||||
|
|
||||||
|
|
||||||
uint32_t apsel;
|
uint32_t apsel;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -182,6 +181,7 @@ struct adiv5_dap
|
||||||
* MEM-AP access before we try to read its status (and/or result).
|
* MEM-AP access before we try to read its status (and/or result).
|
||||||
*/
|
*/
|
||||||
uint32_t memaccess_tck;
|
uint32_t memaccess_tck;
|
||||||
|
|
||||||
/* Size of TAR autoincrement block, ARM ADI Specification requires at least 10 bits */
|
/* Size of TAR autoincrement block, ARM ADI Specification requires at least 10 bits */
|
||||||
uint32_t tar_autoincr_block;
|
uint32_t tar_autoincr_block;
|
||||||
};
|
};
|
||||||
|
@ -216,6 +216,7 @@ struct dap_ops {
|
||||||
/** AP register write. */
|
/** AP register write. */
|
||||||
int (*queue_ap_write)(struct adiv5_dap *dap, unsigned reg,
|
int (*queue_ap_write)(struct adiv5_dap *dap, unsigned reg,
|
||||||
uint32_t data);
|
uint32_t data);
|
||||||
|
|
||||||
/** AP operation abort. */
|
/** AP operation abort. */
|
||||||
int (*queue_ap_abort)(struct adiv5_dap *dap, uint8_t *ack);
|
int (*queue_ap_abort)(struct adiv5_dap *dap, uint8_t *ack);
|
||||||
|
|
||||||
|
@ -249,7 +250,7 @@ static inline int dap_queue_idcode_read(struct adiv5_dap *dap,
|
||||||
* @param dap The DAP used for reading.
|
* @param dap The DAP used for reading.
|
||||||
* @param reg The two-bit number of the DP register being read.
|
* @param reg The two-bit number of the DP register being read.
|
||||||
* @param data Pointer saying where to store the register's value
|
* @param data Pointer saying where to store the register's value
|
||||||
* (in host endianness).
|
* (in host endianness).
|
||||||
*
|
*
|
||||||
* @return ERROR_OK for success, else a fault code.
|
* @return ERROR_OK for success, else a fault code.
|
||||||
*/
|
*/
|
||||||
|
@ -284,7 +285,7 @@ static inline int dap_queue_dp_write(struct adiv5_dap *dap,
|
||||||
* @param dap The DAP used for reading.
|
* @param dap The DAP used for reading.
|
||||||
* @param reg The number of the AP register being read.
|
* @param reg The number of the AP register being read.
|
||||||
* @param data Pointer saying where to store the register's value
|
* @param data Pointer saying where to store the register's value
|
||||||
* (in host endianness).
|
* (in host endianness).
|
||||||
*
|
*
|
||||||
* @return ERROR_OK for success, else a fault code.
|
* @return ERROR_OK for success, else a fault code.
|
||||||
*/
|
*/
|
||||||
|
@ -347,11 +348,11 @@ static inline int dap_run(struct adiv5_dap *dap)
|
||||||
/** Accessor for currently selected DAP-AP number (0..255) */
|
/** Accessor for currently selected DAP-AP number (0..255) */
|
||||||
static inline uint8_t dap_ap_get_select(struct adiv5_dap *swjdp)
|
static inline uint8_t dap_ap_get_select(struct adiv5_dap *swjdp)
|
||||||
{
|
{
|
||||||
return (uint8_t)(swjdp ->ap_current >> 24);
|
return (uint8_t)(swjdp->ap_current >> 24);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* AP selection applies to future AP transactions */
|
/* AP selection applies to future AP transactions */
|
||||||
void dap_ap_select(struct adiv5_dap *dap,uint8_t ap);
|
void dap_ap_select(struct adiv5_dap *dap, uint8_t ap);
|
||||||
|
|
||||||
/* Queued AP transactions */
|
/* Queued AP transactions */
|
||||||
int dap_setup_accessport(struct adiv5_dap *swjdp,
|
int dap_setup_accessport(struct adiv5_dap *swjdp,
|
||||||
|
@ -382,8 +383,6 @@ int mem_ap_write_buf_u16(struct adiv5_dap *swjdp,
|
||||||
int mem_ap_write_buf_u32(struct adiv5_dap *swjdp,
|
int mem_ap_write_buf_u32(struct adiv5_dap *swjdp,
|
||||||
const uint8_t *buffer, int count, uint32_t address);
|
const uint8_t *buffer, int count, uint32_t address);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Queued MEM-AP memory mapped single word transfers with selection of ap */
|
/* Queued MEM-AP memory mapped single word transfers with selection of ap */
|
||||||
int mem_ap_sel_read_u32(struct adiv5_dap *swjdp, uint8_t ap,
|
int mem_ap_sel_read_u32(struct adiv5_dap *swjdp, uint8_t ap,
|
||||||
uint32_t address, uint32_t *value);
|
uint32_t address, uint32_t *value);
|
||||||
|
@ -411,8 +410,6 @@ int mem_ap_sel_write_buf_u16(struct adiv5_dap *swjdp, uint8_t ap,
|
||||||
int mem_ap_sel_write_buf_u32(struct adiv5_dap *swjdp, uint8_t ap,
|
int mem_ap_sel_write_buf_u32(struct adiv5_dap *swjdp, uint8_t ap,
|
||||||
const uint8_t *buffer, int count, uint32_t address);
|
const uint8_t *buffer, int count, uint32_t address);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Initialisation of the debug system, power domains and registers */
|
/* Initialisation of the debug system, power domains and registers */
|
||||||
int ahbap_debugport_init(struct adiv5_dap *swjdp);
|
int ahbap_debugport_init(struct adiv5_dap *swjdp);
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -17,13 +17,13 @@
|
||||||
* Free Software Foundation, Inc., *
|
* Free Software Foundation, Inc., *
|
||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#ifndef ARM_DISASSEMBLER_H
|
#ifndef ARM_DISASSEMBLER_H
|
||||||
#define ARM_DISASSEMBLER_H
|
#define ARM_DISASSEMBLER_H
|
||||||
|
|
||||||
#include <helper/types.h>
|
#include <helper/types.h>
|
||||||
|
|
||||||
enum arm_instruction_type
|
enum arm_instruction_type {
|
||||||
{
|
|
||||||
ARM_UNKNOWN_INSTUCTION,
|
ARM_UNKNOWN_INSTUCTION,
|
||||||
|
|
||||||
/* Branch instructions */
|
/* Branch instructions */
|
||||||
|
@ -120,14 +120,12 @@ enum arm_instruction_type
|
||||||
ARM_UNDEFINED_INSTRUCTION = 0xffffffff,
|
ARM_UNDEFINED_INSTRUCTION = 0xffffffff,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct arm_b_bl_bx_blx_instr
|
struct arm_b_bl_bx_blx_instr {
|
||||||
{
|
|
||||||
int reg_operand;
|
int reg_operand;
|
||||||
uint32_t target_address;
|
uint32_t target_address;
|
||||||
};
|
};
|
||||||
|
|
||||||
union arm_shifter_operand
|
union arm_shifter_operand {
|
||||||
{
|
|
||||||
struct {
|
struct {
|
||||||
uint32_t immediate;
|
uint32_t immediate;
|
||||||
} immediate;
|
} immediate;
|
||||||
|
@ -143,8 +141,7 @@ union arm_shifter_operand
|
||||||
} register_shift;
|
} register_shift;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct arm_data_proc_instr
|
struct arm_data_proc_instr {
|
||||||
{
|
|
||||||
int variant; /* 0: immediate, 1: immediate_shift, 2: register_shift */
|
int variant; /* 0: immediate, 1: immediate_shift, 2: register_shift */
|
||||||
uint8_t S;
|
uint8_t S;
|
||||||
uint8_t Rn;
|
uint8_t Rn;
|
||||||
|
@ -152,15 +149,13 @@ struct arm_data_proc_instr
|
||||||
union arm_shifter_operand shifter_operand;
|
union arm_shifter_operand shifter_operand;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct arm_load_store_instr
|
struct arm_load_store_instr {
|
||||||
{
|
|
||||||
uint8_t Rd;
|
uint8_t Rd;
|
||||||
uint8_t Rn;
|
uint8_t Rn;
|
||||||
uint8_t U;
|
uint8_t U;
|
||||||
int index_mode; /* 0: offset, 1: pre-indexed, 2: post-indexed */
|
int index_mode; /* 0: offset, 1: pre-indexed, 2: post-indexed */
|
||||||
int offset_mode; /* 0: immediate, 1: (scaled) register */
|
int offset_mode; /* 0: immediate, 1: (scaled) register */
|
||||||
union
|
union {
|
||||||
{
|
|
||||||
uint32_t offset;
|
uint32_t offset;
|
||||||
struct {
|
struct {
|
||||||
uint8_t Rm;
|
uint8_t Rm;
|
||||||
|
@ -170,8 +165,7 @@ struct arm_load_store_instr
|
||||||
} offset;
|
} offset;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct arm_load_store_multiple_instr
|
struct arm_load_store_multiple_instr {
|
||||||
{
|
|
||||||
uint8_t Rn;
|
uint8_t Rn;
|
||||||
uint32_t register_list;
|
uint32_t register_list;
|
||||||
uint8_t addressing_mode; /* 0: IA, 1: IB, 2: DA, 3: DB */
|
uint8_t addressing_mode; /* 0: IA, 1: IB, 2: DA, 3: DB */
|
||||||
|
@ -179,8 +173,7 @@ struct arm_load_store_multiple_instr
|
||||||
uint8_t W;
|
uint8_t W;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct arm_instruction
|
struct arm_instruction {
|
||||||
{
|
|
||||||
enum arm_instruction_type type;
|
enum arm_instruction_type type;
|
||||||
char text[128];
|
char text[128];
|
||||||
uint32_t opcode;
|
uint32_t opcode;
|
||||||
|
|
|
@ -51,8 +51,8 @@
|
||||||
|
|
||||||
/* Read coprocessor */
|
/* Read coprocessor */
|
||||||
static int dpm_mrc(struct target *target, int cpnum,
|
static int dpm_mrc(struct target *target, int cpnum,
|
||||||
uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm,
|
uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm,
|
||||||
uint32_t *value)
|
uint32_t *value)
|
||||||
{
|
{
|
||||||
struct arm *arm = target_to_arm(target);
|
struct arm *arm = target_to_arm(target);
|
||||||
struct arm_dpm *dpm = arm->dpm;
|
struct arm_dpm *dpm = arm->dpm;
|
||||||
|
@ -63,8 +63,8 @@ static int dpm_mrc(struct target *target, int cpnum,
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
LOG_DEBUG("MRC p%d, %d, r0, c%d, c%d, %d", cpnum,
|
LOG_DEBUG("MRC p%d, %d, r0, c%d, c%d, %d", cpnum,
|
||||||
(int) op1, (int) CRn,
|
(int) op1, (int) CRn,
|
||||||
(int) CRm, (int) op2);
|
(int) CRm, (int) op2);
|
||||||
|
|
||||||
/* read coprocessor register into R0; return via DCC */
|
/* read coprocessor register into R0; return via DCC */
|
||||||
retval = dpm->instr_read_data_r0(dpm,
|
retval = dpm->instr_read_data_r0(dpm,
|
||||||
|
@ -76,8 +76,8 @@ static int dpm_mrc(struct target *target, int cpnum,
|
||||||
}
|
}
|
||||||
|
|
||||||
static int dpm_mcr(struct target *target, int cpnum,
|
static int dpm_mcr(struct target *target, int cpnum,
|
||||||
uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm,
|
uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm,
|
||||||
uint32_t value)
|
uint32_t value)
|
||||||
{
|
{
|
||||||
struct arm *arm = target_to_arm(target);
|
struct arm *arm = target_to_arm(target);
|
||||||
struct arm_dpm *dpm = arm->dpm;
|
struct arm_dpm *dpm = arm->dpm;
|
||||||
|
@ -88,8 +88,8 @@ static int dpm_mcr(struct target *target, int cpnum,
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
LOG_DEBUG("MCR p%d, %d, r0, c%d, c%d, %d", cpnum,
|
LOG_DEBUG("MCR p%d, %d, r0, c%d, c%d, %d", cpnum,
|
||||||
(int) op1, (int) CRn,
|
(int) op1, (int) CRn,
|
||||||
(int) CRm, (int) op2);
|
(int) CRm, (int) op2);
|
||||||
|
|
||||||
/* read DCC into r0; then write coprocessor register from R0 */
|
/* read DCC into r0; then write coprocessor register from R0 */
|
||||||
retval = dpm->instr_write_data_r0(dpm,
|
retval = dpm->instr_write_data_r0(dpm,
|
||||||
|
@ -139,44 +139,44 @@ static int dpm_read_reg(struct arm_dpm *dpm, struct reg *r, unsigned regnum)
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
switch (regnum) {
|
switch (regnum) {
|
||||||
case 0 ... 14:
|
case 0 ... 14:
|
||||||
/* return via DCC: "MCR p14, 0, Rnum, c0, c5, 0" */
|
/* return via DCC: "MCR p14, 0, Rnum, c0, c5, 0" */
|
||||||
retval = dpm->instr_read_data_dcc(dpm,
|
retval = dpm->instr_read_data_dcc(dpm,
|
||||||
ARMV4_5_MCR(14, 0, regnum, 0, 5, 0),
|
ARMV4_5_MCR(14, 0, regnum, 0, 5, 0),
|
||||||
&value);
|
&value);
|
||||||
break;
|
break;
|
||||||
case 15: /* PC */
|
case 15:/* PC
|
||||||
/* "MOV r0, pc"; then return via DCC */
|
* "MOV r0, pc"; then return via DCC */
|
||||||
retval = dpm->instr_read_data_r0(dpm, 0xe1a0000f, &value);
|
retval = dpm->instr_read_data_r0(dpm, 0xe1a0000f, &value);
|
||||||
|
|
||||||
/* NOTE: this seems like a slightly awkward place to update
|
/* NOTE: this seems like a slightly awkward place to update
|
||||||
* this value ... but if the PC gets written (the only way
|
* this value ... but if the PC gets written (the only way
|
||||||
* to change what we compute), the arch spec says subsequent
|
* to change what we compute), the arch spec says subsequent
|
||||||
* reads return values which are "unpredictable". So this
|
* reads return values which are "unpredictable". So this
|
||||||
* is always right except in those broken-by-intent cases.
|
* is always right except in those broken-by-intent cases.
|
||||||
*/
|
*/
|
||||||
switch (dpm->arm->core_state) {
|
switch (dpm->arm->core_state) {
|
||||||
case ARM_STATE_ARM:
|
case ARM_STATE_ARM:
|
||||||
value -= 8;
|
value -= 8;
|
||||||
|
break;
|
||||||
|
case ARM_STATE_THUMB:
|
||||||
|
case ARM_STATE_THUMB_EE:
|
||||||
|
value -= 4;
|
||||||
|
break;
|
||||||
|
case ARM_STATE_JAZELLE:
|
||||||
|
/* core-specific ... ? */
|
||||||
|
LOG_WARNING("Jazelle PC adjustment unknown");
|
||||||
|
break;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case ARM_STATE_THUMB:
|
default:
|
||||||
case ARM_STATE_THUMB_EE:
|
/* 16: "MRS r0, CPSR"; then return via DCC
|
||||||
value -= 4;
|
* 17: "MRS r0, SPSR"; then return via DCC
|
||||||
break;
|
*/
|
||||||
case ARM_STATE_JAZELLE:
|
retval = dpm->instr_read_data_r0(dpm,
|
||||||
/* core-specific ... ? */
|
|
||||||
LOG_WARNING("Jazelle PC adjustment unknown");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
/* 16: "MRS r0, CPSR"; then return via DCC
|
|
||||||
* 17: "MRS r0, SPSR"; then return via DCC
|
|
||||||
*/
|
|
||||||
retval = dpm->instr_read_data_r0(dpm,
|
|
||||||
ARMV4_5_MRS(0, regnum & 1),
|
ARMV4_5_MRS(0, regnum & 1),
|
||||||
&value);
|
&value);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (retval == ERROR_OK) {
|
if (retval == ERROR_OK) {
|
||||||
|
@ -196,30 +196,30 @@ static int dpm_write_reg(struct arm_dpm *dpm, struct reg *r, unsigned regnum)
|
||||||
uint32_t value = buf_get_u32(r->value, 0, 32);
|
uint32_t value = buf_get_u32(r->value, 0, 32);
|
||||||
|
|
||||||
switch (regnum) {
|
switch (regnum) {
|
||||||
case 0 ... 14:
|
case 0 ... 14:
|
||||||
/* load register from DCC: "MRC p14, 0, Rnum, c0, c5, 0" */
|
/* load register from DCC: "MRC p14, 0, Rnum, c0, c5, 0" */
|
||||||
retval = dpm->instr_write_data_dcc(dpm,
|
retval = dpm->instr_write_data_dcc(dpm,
|
||||||
ARMV4_5_MRC(14, 0, regnum, 0, 5, 0),
|
ARMV4_5_MRC(14, 0, regnum, 0, 5, 0),
|
||||||
value);
|
value);
|
||||||
break;
|
break;
|
||||||
case 15: /* PC */
|
case 15:/* PC
|
||||||
/* read r0 from DCC; then "MOV pc, r0" */
|
* read r0 from DCC; then "MOV pc, r0" */
|
||||||
retval = dpm->instr_write_data_r0(dpm, 0xe1a0f000, value);
|
retval = dpm->instr_write_data_r0(dpm, 0xe1a0f000, value);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
/* 16: read r0 from DCC, then "MSR r0, CPSR_cxsf"
|
/* 16: read r0 from DCC, then "MSR r0, CPSR_cxsf"
|
||||||
* 17: read r0 from DCC, then "MSR r0, SPSR_cxsf"
|
* 17: read r0 from DCC, then "MSR r0, SPSR_cxsf"
|
||||||
*/
|
*/
|
||||||
retval = dpm->instr_write_data_r0(dpm,
|
retval = dpm->instr_write_data_r0(dpm,
|
||||||
ARMV4_5_MSR_GP(0, 0xf, regnum & 1),
|
ARMV4_5_MSR_GP(0, 0xf, regnum & 1),
|
||||||
value);
|
value);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
if (regnum == 16 && dpm->instr_cpsr_sync)
|
if (regnum == 16 && dpm->instr_cpsr_sync)
|
||||||
retval = dpm->instr_cpsr_sync(dpm);
|
retval = dpm->instr_cpsr_sync(dpm);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (retval == ERROR_OK) {
|
if (retval == ERROR_OK) {
|
||||||
|
@ -292,7 +292,7 @@ fail:
|
||||||
* or running debugger code.
|
* or running debugger code.
|
||||||
*/
|
*/
|
||||||
static int dpm_maybe_update_bpwp(struct arm_dpm *dpm, bool bpwp,
|
static int dpm_maybe_update_bpwp(struct arm_dpm *dpm, bool bpwp,
|
||||||
struct dpm_bpwp *xp, int *set_p)
|
struct dpm_bpwp *xp, int *set_p)
|
||||||
{
|
{
|
||||||
int retval = ERROR_OK;
|
int retval = ERROR_OK;
|
||||||
bool disable;
|
bool disable;
|
||||||
|
@ -325,10 +325,10 @@ static int dpm_maybe_update_bpwp(struct arm_dpm *dpm, bool bpwp,
|
||||||
|
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
LOG_ERROR("%s: can't %s HW %spoint %d",
|
LOG_ERROR("%s: can't %s HW %spoint %d",
|
||||||
disable ? "disable" : "enable",
|
disable ? "disable" : "enable",
|
||||||
target_name(dpm->arm->target),
|
target_name(dpm->arm->target),
|
||||||
(xp->number < 16) ? "break" : "watch",
|
(xp->number < 16) ? "break" : "watch",
|
||||||
xp->number & 0xf);
|
xp->number & 0xf);
|
||||||
done:
|
done:
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
@ -423,25 +423,24 @@ int arm_dpm_write_dirty_registers(struct arm_dpm *dpm, bool bpwp)
|
||||||
|
|
||||||
/* cope with special cases */
|
/* cope with special cases */
|
||||||
switch (regnum) {
|
switch (regnum) {
|
||||||
case 8 ... 12:
|
case 8 ... 12:
|
||||||
/* r8..r12 "anything but FIQ" case;
|
/* r8..r12 "anything but FIQ" case;
|
||||||
* we "know" core mode is accurate
|
* we "know" core mode is accurate
|
||||||
* since we haven't changed it yet
|
* since we haven't changed it yet
|
||||||
*/
|
*/
|
||||||
if (arm->core_mode == ARM_MODE_FIQ
|
if (arm->core_mode == ARM_MODE_FIQ
|
||||||
&& ARM_MODE_ANY
|
&& ARM_MODE_ANY
|
||||||
!= mode)
|
!= mode)
|
||||||
tmode = ARM_MODE_USR;
|
tmode = ARM_MODE_USR;
|
||||||
break;
|
break;
|
||||||
case 16:
|
case 16:
|
||||||
/* SPSR */
|
/* SPSR */
|
||||||
regnum++;
|
regnum++;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* REVISIT error checks */
|
/* REVISIT error checks */
|
||||||
if (tmode != ARM_MODE_ANY)
|
if (tmode != ARM_MODE_ANY) {
|
||||||
{
|
|
||||||
retval = dpm_modeswitch(dpm, tmode);
|
retval = dpm_modeswitch(dpm, tmode);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
goto done;
|
goto done;
|
||||||
|
@ -490,34 +489,34 @@ done:
|
||||||
* or MODE_ANY.
|
* or MODE_ANY.
|
||||||
*/
|
*/
|
||||||
static enum arm_mode dpm_mapmode(struct arm *arm,
|
static enum arm_mode dpm_mapmode(struct arm *arm,
|
||||||
unsigned num, enum arm_mode mode)
|
unsigned num, enum arm_mode mode)
|
||||||
{
|
{
|
||||||
enum arm_mode amode = arm->core_mode;
|
enum arm_mode amode = arm->core_mode;
|
||||||
|
|
||||||
/* don't switch if the mode is already correct */
|
/* don't switch if the mode is already correct */
|
||||||
if (amode == ARM_MODE_SYS)
|
if (amode == ARM_MODE_SYS)
|
||||||
amode = ARM_MODE_USR;
|
amode = ARM_MODE_USR;
|
||||||
if (mode == amode)
|
if (mode == amode)
|
||||||
return ARM_MODE_ANY;
|
return ARM_MODE_ANY;
|
||||||
|
|
||||||
switch (num) {
|
switch (num) {
|
||||||
/* don't switch for non-shadowed registers (r0..r7, r15/pc, cpsr) */
|
/* don't switch for non-shadowed registers (r0..r7, r15/pc, cpsr) */
|
||||||
case 0 ... 7:
|
case 0 ... 7:
|
||||||
case 15:
|
case 15:
|
||||||
case 16:
|
case 16:
|
||||||
break;
|
break;
|
||||||
/* r8..r12 aren't shadowed for anything except FIQ */
|
/* r8..r12 aren't shadowed for anything except FIQ */
|
||||||
case 8 ... 12:
|
case 8 ... 12:
|
||||||
if (mode == ARM_MODE_FIQ)
|
if (mode == ARM_MODE_FIQ)
|
||||||
|
return mode;
|
||||||
|
break;
|
||||||
|
/* r13/sp, and r14/lr are always shadowed */
|
||||||
|
case 13:
|
||||||
|
case 14:
|
||||||
return mode;
|
return mode;
|
||||||
break;
|
default:
|
||||||
/* r13/sp, and r14/lr are always shadowed */
|
LOG_WARNING("invalid register #%u", num);
|
||||||
case 13:
|
break;
|
||||||
case 14:
|
|
||||||
return mode;
|
|
||||||
default:
|
|
||||||
LOG_WARNING("invalid register #%u", num);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
return ARM_MODE_ANY;
|
return ARM_MODE_ANY;
|
||||||
}
|
}
|
||||||
|
@ -530,7 +529,7 @@ static enum arm_mode dpm_mapmode(struct arm *arm,
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static int arm_dpm_read_core_reg(struct target *target, struct reg *r,
|
static int arm_dpm_read_core_reg(struct target *target, struct reg *r,
|
||||||
int regnum, enum arm_mode mode)
|
int regnum, enum arm_mode mode)
|
||||||
{
|
{
|
||||||
struct arm_dpm *dpm = target_to_arm(target)->dpm;
|
struct arm_dpm *dpm = target_to_arm(target)->dpm;
|
||||||
int retval;
|
int retval;
|
||||||
|
@ -572,7 +571,7 @@ fail:
|
||||||
}
|
}
|
||||||
|
|
||||||
static int arm_dpm_write_core_reg(struct target *target, struct reg *r,
|
static int arm_dpm_write_core_reg(struct target *target, struct reg *r,
|
||||||
int regnum, enum arm_mode mode, uint32_t value)
|
int regnum, enum arm_mode mode, uint32_t value)
|
||||||
{
|
{
|
||||||
struct arm_dpm *dpm = target_to_arm(target)->dpm;
|
struct arm_dpm *dpm = target_to_arm(target)->dpm;
|
||||||
int retval;
|
int retval;
|
||||||
|
@ -693,7 +692,7 @@ done:
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static int dpm_bpwp_setup(struct arm_dpm *dpm, struct dpm_bpwp *xp,
|
static int dpm_bpwp_setup(struct arm_dpm *dpm, struct dpm_bpwp *xp,
|
||||||
uint32_t addr, uint32_t length)
|
uint32_t addr, uint32_t length)
|
||||||
{
|
{
|
||||||
uint32_t control;
|
uint32_t control;
|
||||||
|
|
||||||
|
@ -710,26 +709,26 @@ static int dpm_bpwp_setup(struct arm_dpm *dpm, struct dpm_bpwp *xp,
|
||||||
* v7 hardware, unaligned 4-byte ones too.
|
* v7 hardware, unaligned 4-byte ones too.
|
||||||
*/
|
*/
|
||||||
switch (length) {
|
switch (length) {
|
||||||
case 1:
|
case 1:
|
||||||
control |= (1 << (addr & 3)) << 5;
|
control |= (1 << (addr & 3)) << 5;
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
/* require 2-byte alignment */
|
|
||||||
if (!(addr & 1)) {
|
|
||||||
control |= (3 << (addr & 2)) << 5;
|
|
||||||
break;
|
break;
|
||||||
}
|
case 2:
|
||||||
|
/* require 2-byte alignment */
|
||||||
|
if (!(addr & 1)) {
|
||||||
|
control |= (3 << (addr & 2)) << 5;
|
||||||
|
break;
|
||||||
|
}
|
||||||
/* FALL THROUGH */
|
/* FALL THROUGH */
|
||||||
case 4:
|
case 4:
|
||||||
/* require 4-byte alignment */
|
/* require 4-byte alignment */
|
||||||
if (!(addr & 3)) {
|
if (!(addr & 3)) {
|
||||||
control |= 0xf << 5;
|
control |= 0xf << 5;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/* FALL THROUGH */
|
/* FALL THROUGH */
|
||||||
default:
|
default:
|
||||||
LOG_ERROR("unsupported {break,watch}point length/alignment");
|
LOG_ERROR("unsupported {break,watch}point length/alignment");
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* other shared control bits:
|
/* other shared control bits:
|
||||||
|
@ -743,7 +742,7 @@ static int dpm_bpwp_setup(struct arm_dpm *dpm, struct dpm_bpwp *xp,
|
||||||
xp->dirty = true;
|
xp->dirty = true;
|
||||||
|
|
||||||
LOG_DEBUG("BPWP: addr %8.8" PRIx32 ", control %" PRIx32 ", number %d",
|
LOG_DEBUG("BPWP: addr %8.8" PRIx32 ", control %" PRIx32 ", number %d",
|
||||||
xp->address, control, xp->number);
|
xp->address, control, xp->number);
|
||||||
|
|
||||||
/* hardware is updated in write_dirty_registers() */
|
/* hardware is updated in write_dirty_registers() */
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
|
@ -798,7 +797,7 @@ static int dpm_remove_breakpoint(struct target *target, struct breakpoint *bp)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int dpm_watchpoint_setup(struct arm_dpm *dpm, unsigned index_t,
|
static int dpm_watchpoint_setup(struct arm_dpm *dpm, unsigned index_t,
|
||||||
struct watchpoint *wp)
|
struct watchpoint *wp)
|
||||||
{
|
{
|
||||||
int retval;
|
int retval;
|
||||||
struct dpm_wp *dwp = dpm->dwp + index_t;
|
struct dpm_wp *dwp = dpm->dwp + index_t;
|
||||||
|
@ -816,15 +815,15 @@ static int dpm_watchpoint_setup(struct arm_dpm *dpm, unsigned index_t,
|
||||||
|
|
||||||
control = dwp->bpwp.control;
|
control = dwp->bpwp.control;
|
||||||
switch (wp->rw) {
|
switch (wp->rw) {
|
||||||
case WPT_READ:
|
case WPT_READ:
|
||||||
control |= 1 << 3;
|
control |= 1 << 3;
|
||||||
break;
|
break;
|
||||||
case WPT_WRITE:
|
case WPT_WRITE:
|
||||||
control |= 2 << 3;
|
control |= 2 << 3;
|
||||||
break;
|
break;
|
||||||
case WPT_ACCESS:
|
case WPT_ACCESS:
|
||||||
control |= 3 << 3;
|
control |= 3 << 3;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
dwp->bpwp.control = control;
|
dwp->bpwp.control = control;
|
||||||
|
|
||||||
|
@ -874,16 +873,16 @@ static int dpm_remove_watchpoint(struct target *target, struct watchpoint *wp)
|
||||||
void arm_dpm_report_wfar(struct arm_dpm *dpm, uint32_t addr)
|
void arm_dpm_report_wfar(struct arm_dpm *dpm, uint32_t addr)
|
||||||
{
|
{
|
||||||
switch (dpm->arm->core_state) {
|
switch (dpm->arm->core_state) {
|
||||||
case ARM_STATE_ARM:
|
case ARM_STATE_ARM:
|
||||||
addr -= 8;
|
addr -= 8;
|
||||||
break;
|
break;
|
||||||
case ARM_STATE_THUMB:
|
case ARM_STATE_THUMB:
|
||||||
case ARM_STATE_THUMB_EE:
|
case ARM_STATE_THUMB_EE:
|
||||||
addr -= 4;
|
addr -= 4;
|
||||||
break;
|
break;
|
||||||
case ARM_STATE_JAZELLE:
|
case ARM_STATE_JAZELLE:
|
||||||
/* ?? */
|
/* ?? */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
dpm->wp_pc = addr;
|
dpm->wp_pc = addr;
|
||||||
}
|
}
|
||||||
|
@ -902,25 +901,25 @@ void arm_dpm_report_dscr(struct arm_dpm *dpm, uint32_t dscr)
|
||||||
|
|
||||||
/* Examine debug reason */
|
/* Examine debug reason */
|
||||||
switch (DSCR_ENTRY(dscr)) {
|
switch (DSCR_ENTRY(dscr)) {
|
||||||
case 6: /* Data abort (v6 only) */
|
case 6: /* Data abort (v6 only) */
|
||||||
case 7: /* Prefetch abort (v6 only) */
|
case 7: /* Prefetch abort (v6 only) */
|
||||||
/* FALL THROUGH -- assume a v6 core in abort mode */
|
/* FALL THROUGH -- assume a v6 core in abort mode */
|
||||||
case 0: /* HALT request from debugger */
|
case 0: /* HALT request from debugger */
|
||||||
case 4: /* EDBGRQ */
|
case 4: /* EDBGRQ */
|
||||||
target->debug_reason = DBG_REASON_DBGRQ;
|
target->debug_reason = DBG_REASON_DBGRQ;
|
||||||
break;
|
break;
|
||||||
case 1: /* HW breakpoint */
|
case 1: /* HW breakpoint */
|
||||||
case 3: /* SW BKPT */
|
case 3: /* SW BKPT */
|
||||||
case 5: /* vector catch */
|
case 5: /* vector catch */
|
||||||
target->debug_reason = DBG_REASON_BREAKPOINT;
|
target->debug_reason = DBG_REASON_BREAKPOINT;
|
||||||
break;
|
break;
|
||||||
case 2: /* asynch watchpoint */
|
case 2: /* asynch watchpoint */
|
||||||
case 10: /* precise watchpoint */
|
case 10:/* precise watchpoint */
|
||||||
target->debug_reason = DBG_REASON_WATCHPOINT;
|
target->debug_reason = DBG_REASON_WATCHPOINT;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
target->debug_reason = DBG_REASON_UNDEFINED;
|
target->debug_reason = DBG_REASON_UNDEFINED;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -984,7 +983,7 @@ int arm_dpm_setup(struct arm_dpm *dpm)
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_INFO("%s: hardware has %d breakpoints, %d watchpoints",
|
LOG_INFO("%s: hardware has %d breakpoints, %d watchpoints",
|
||||||
target_name(target), dpm->nbp, dpm->nwp);
|
target_name(target), dpm->nbp, dpm->nwp);
|
||||||
|
|
||||||
/* REVISIT ... and some of those breakpoints could match
|
/* REVISIT ... and some of those breakpoints could match
|
||||||
* execution context IDs...
|
* execution context IDs...
|
||||||
|
|
|
@ -126,7 +126,7 @@ struct arm_dpm {
|
||||||
/** Recent value of DSCR. */
|
/** Recent value of DSCR. */
|
||||||
uint32_t dscr;
|
uint32_t dscr;
|
||||||
|
|
||||||
// FIXME -- read/write DCSR methods and symbols
|
/* FIXME -- read/write DCSR methods and symbols */
|
||||||
};
|
};
|
||||||
|
|
||||||
int arm_dpm_setup(struct arm_dpm *dpm);
|
int arm_dpm_setup(struct arm_dpm *dpm);
|
||||||
|
|
|
@ -20,18 +20,19 @@
|
||||||
* Free Software Foundation, Inc., *
|
* Free Software Foundation, Inc., *
|
||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "arm_jtag.h"
|
#include "arm_jtag.h"
|
||||||
|
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
#define _ARM_JTAG_SCAN_N_CHECK_
|
#define _ARM_JTAG_SCAN_N_CHECK_
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int arm_jtag_set_instr_inner(struct arm_jtag *jtag_info, uint32_t new_instr, void *no_verify_capture, tap_state_t end_state)
|
int arm_jtag_set_instr_inner(struct arm_jtag *jtag_info,
|
||||||
|
uint32_t new_instr, void *no_verify_capture, tap_state_t end_state)
|
||||||
{
|
{
|
||||||
struct jtag_tap *tap;
|
struct jtag_tap *tap;
|
||||||
tap = jtag_info->tap;
|
tap = jtag_info->tap;
|
||||||
|
@ -44,10 +45,8 @@ int arm_jtag_set_instr_inner(struct arm_jtag *jtag_info, uint32_t new_instr, vo
|
||||||
field.in_value = NULL;
|
field.in_value = NULL;
|
||||||
|
|
||||||
if (no_verify_capture == NULL)
|
if (no_verify_capture == NULL)
|
||||||
{
|
|
||||||
jtag_add_ir_scan(tap, &field, end_state);
|
jtag_add_ir_scan(tap, &field, end_state);
|
||||||
} else
|
else {
|
||||||
{
|
|
||||||
/* FIX!!!! this is a kludge!!! arm926ejs.c should reimplement this arm_jtag_set_instr to
|
/* FIX!!!! this is a kludge!!! arm926ejs.c should reimplement this arm_jtag_set_instr to
|
||||||
* have special verification code.
|
* have special verification code.
|
||||||
*/
|
*/
|
||||||
|
@ -63,13 +62,12 @@ int arm_jtag_scann_inner(struct arm_jtag *jtag_info, uint32_t new_scan_chain, ta
|
||||||
uint32_t values[1];
|
uint32_t values[1];
|
||||||
int num_bits[1];
|
int num_bits[1];
|
||||||
|
|
||||||
values[0]=new_scan_chain;
|
values[0] = new_scan_chain;
|
||||||
num_bits[0]=jtag_info->scann_size;
|
num_bits[0] = jtag_info->scann_size;
|
||||||
|
|
||||||
if ((retval = arm_jtag_set_instr(jtag_info, jtag_info->scann_instr, NULL, end_state)) != ERROR_OK)
|
retval = arm_jtag_set_instr(jtag_info, jtag_info->scann_instr, NULL, end_state);
|
||||||
{
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
|
||||||
|
|
||||||
jtag_add_dr_out(jtag_info->tap,
|
jtag_add_dr_out(jtag_info->tap,
|
||||||
1,
|
1,
|
||||||
|
@ -87,9 +85,7 @@ static int arm_jtag_reset_callback(enum jtag_event event, void *priv)
|
||||||
struct arm_jtag *jtag_info = priv;
|
struct arm_jtag *jtag_info = priv;
|
||||||
|
|
||||||
if (event == JTAG_TRST_ASSERTED)
|
if (event == JTAG_TRST_ASSERTED)
|
||||||
{
|
|
||||||
jtag_info->cur_scan_chain = 0;
|
jtag_info->cur_scan_chain = 0;
|
||||||
}
|
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,13 +20,13 @@
|
||||||
* Free Software Foundation, Inc., *
|
* Free Software Foundation, Inc., *
|
||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#ifndef ARM_JTAG
|
#ifndef ARM_JTAG
|
||||||
#define ARM_JTAG
|
#define ARM_JTAG
|
||||||
|
|
||||||
#include <jtag/jtag.h>
|
#include <jtag/jtag.h>
|
||||||
|
|
||||||
struct arm_jtag
|
struct arm_jtag {
|
||||||
{
|
|
||||||
struct jtag_tap *tap;
|
struct jtag_tap *tap;
|
||||||
|
|
||||||
uint32_t scann_size;
|
uint32_t scann_size;
|
||||||
|
@ -39,53 +39,46 @@ struct arm_jtag
|
||||||
int arm_jtag_set_instr_inner(struct arm_jtag *jtag_info, uint32_t new_instr,
|
int arm_jtag_set_instr_inner(struct arm_jtag *jtag_info, uint32_t new_instr,
|
||||||
void *no_verify_capture,
|
void *no_verify_capture,
|
||||||
tap_state_t end_state);
|
tap_state_t end_state);
|
||||||
|
|
||||||
static inline int arm_jtag_set_instr(struct arm_jtag *jtag_info,
|
static inline int arm_jtag_set_instr(struct arm_jtag *jtag_info,
|
||||||
uint32_t new_instr, void *no_verify_capture, tap_state_t end_state)
|
uint32_t new_instr, void *no_verify_capture, tap_state_t end_state)
|
||||||
{
|
{
|
||||||
/* inline most common code path */
|
/* inline most common code path */
|
||||||
struct jtag_tap *tap;
|
struct jtag_tap *tap;
|
||||||
tap = jtag_info->tap;
|
tap = jtag_info->tap;
|
||||||
assert (tap != NULL);
|
assert(tap != NULL);
|
||||||
|
|
||||||
if (buf_get_u32(tap->cur_instr, 0, tap->ir_length) != new_instr)
|
if (buf_get_u32(tap->cur_instr, 0, tap->ir_length) != new_instr)
|
||||||
{
|
|
||||||
return arm_jtag_set_instr_inner(jtag_info, new_instr, no_verify_capture, end_state);
|
return arm_jtag_set_instr_inner(jtag_info, new_instr, no_verify_capture, end_state);
|
||||||
}
|
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int arm_jtag_scann_inner(struct arm_jtag *jtag_info, uint32_t new_scan_chain, tap_state_t end_state);
|
int arm_jtag_scann_inner(struct arm_jtag *jtag_info, uint32_t new_scan_chain, tap_state_t end_state);
|
||||||
static inline int arm_jtag_scann(struct arm_jtag *jtag_info, uint32_t new_scan_chain, tap_state_t end_state)
|
static inline int arm_jtag_scann(struct arm_jtag *jtag_info, uint32_t new_scan_chain, tap_state_t end_state)
|
||||||
{
|
{
|
||||||
/* inline most common code path */
|
/* inline most common code path */
|
||||||
int retval = ERROR_OK;
|
int retval = ERROR_OK;
|
||||||
if (jtag_info->cur_scan_chain != new_scan_chain)
|
if (jtag_info->cur_scan_chain != new_scan_chain)
|
||||||
{
|
|
||||||
return arm_jtag_scann_inner(jtag_info, new_scan_chain, end_state);
|
return arm_jtag_scann_inner(jtag_info, new_scan_chain, end_state);
|
||||||
}
|
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int arm_jtag_setup_connection(struct arm_jtag *jtag_info);
|
int arm_jtag_setup_connection(struct arm_jtag *jtag_info);
|
||||||
|
|
||||||
/* use this as a static so we can inline it in -O3 and refer to it via a pointer */
|
/* use this as a static so we can inline it in -O3 and refer to it via a pointer */
|
||||||
static __inline__ void arm7flip32(jtag_callback_data_t arg)
|
static inline void arm7flip32(jtag_callback_data_t arg)
|
||||||
{
|
{
|
||||||
uint8_t *in = (uint8_t *)arg;
|
uint8_t *in = (uint8_t *)arg;
|
||||||
*((uint32_t *)arg) = flip_u32(le_to_h_u32(in), 32);
|
*((uint32_t *)arg) = flip_u32(le_to_h_u32(in), 32);
|
||||||
}
|
}
|
||||||
|
|
||||||
static __inline__ void arm_le_to_h_u32(jtag_callback_data_t arg)
|
static inline void arm_le_to_h_u32(jtag_callback_data_t arg)
|
||||||
{
|
{
|
||||||
uint8_t *in = (uint8_t *)arg;
|
uint8_t *in = (uint8_t *)arg;
|
||||||
*((uint32_t *)arg) = le_to_h_u32(in);
|
*((uint32_t *)arg) = le_to_h_u32(in);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif /* ARM_JTAG */
|
#endif /* ARM_JTAG */
|
||||||
|
|
||||||
|
|
|
@ -90,8 +90,8 @@
|
||||||
* Rd: register to load
|
* Rd: register to load
|
||||||
* Rn: base register
|
* Rn: base register
|
||||||
*/
|
*/
|
||||||
#define ARMV4_5_LDRW_IP(Rd, Rn) (0xe4900004 | ((Rd) << 12) | ((Rn) << 16))
|
#define ARMV4_5_LDRW_IP(Rd, Rn) (0xe4900004 | ((Rd) << 12) | ((Rn) << 16))
|
||||||
|
|
||||||
/* Load Register Halfword Immediate Post-Index
|
/* Load Register Halfword Immediate Post-Index
|
||||||
* Rd: register to load
|
* Rd: register to load
|
||||||
* Rn: base register
|
* Rn: base register
|
||||||
|
@ -108,7 +108,7 @@
|
||||||
* Rd: register to store
|
* Rd: register to store
|
||||||
* Rn: base register
|
* Rn: base register
|
||||||
*/
|
*/
|
||||||
#define ARMV4_5_STRW_IP(Rd, Rn) (0xe4800004 | ((Rd) << 12) | ((Rn) << 16))
|
#define ARMV4_5_STRW_IP(Rd, Rn) (0xe4800004 | ((Rd) << 12) | ((Rn) << 16))
|
||||||
|
|
||||||
/* Store register Halfword Immediate Post-Index
|
/* Store register Halfword Immediate Post-Index
|
||||||
* Rd: register to store
|
* Rd: register to store
|
||||||
|
|
|
@ -323,7 +323,7 @@ static int do_semihosting(struct target *target)
|
||||||
if (l < s)
|
if (l < s)
|
||||||
result = -1;
|
result = -1;
|
||||||
else {
|
else {
|
||||||
retval = target_write_buffer(target, a, s, (void*)arg);
|
retval = target_write_buffer(target, a, s, (void *)arg);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
result = 0;
|
result = 0;
|
||||||
|
@ -392,8 +392,7 @@ static int do_semihosting(struct target *target)
|
||||||
/* REVISIT this looks wrong ... ARM11 and Cortex-A8
|
/* REVISIT this looks wrong ... ARM11 and Cortex-A8
|
||||||
* should work this way at least sometimes.
|
* should work this way at least sometimes.
|
||||||
*/
|
*/
|
||||||
if (is_arm7_9(target_to_arm7_9(target)))
|
if (is_arm7_9(target_to_arm7_9(target))) {
|
||||||
{
|
|
||||||
uint32_t spsr;
|
uint32_t spsr;
|
||||||
|
|
||||||
/* return value in R0 */
|
/* return value in R0 */
|
||||||
|
@ -402,7 +401,7 @@ static int do_semihosting(struct target *target)
|
||||||
|
|
||||||
/* LR --> PC */
|
/* LR --> PC */
|
||||||
buf_set_u32(arm->core_cache->reg_list[15].value, 0, 32,
|
buf_set_u32(arm->core_cache->reg_list[15].value, 0, 32,
|
||||||
buf_get_u32(arm_reg_current(arm,14)->value, 0, 32));
|
buf_get_u32(arm_reg_current(arm, 14)->value, 0, 32));
|
||||||
arm->core_cache->reg_list[15].dirty = 1;
|
arm->core_cache->reg_list[15].dirty = 1;
|
||||||
|
|
||||||
/* saved PSR --> current PSR */
|
/* saved PSR --> current PSR */
|
||||||
|
@ -418,9 +417,7 @@ static int do_semihosting(struct target *target)
|
||||||
if (spsr & 0x20)
|
if (spsr & 0x20)
|
||||||
arm->core_state = ARM_STATE_THUMB;
|
arm->core_state = ARM_STATE_THUMB;
|
||||||
|
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
/* resume execution, this will be pc+2 to skip over the
|
/* resume execution, this will be pc+2 to skip over the
|
||||||
* bkpt instruction */
|
* bkpt instruction */
|
||||||
|
|
||||||
|
@ -454,8 +451,7 @@ int arm_semihosting(struct target *target, int *retval)
|
||||||
if (!arm->is_semihosting)
|
if (!arm->is_semihosting)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (is_arm7_9(target_to_arm7_9(target)))
|
if (is_arm7_9(target_to_arm7_9(target))) {
|
||||||
{
|
|
||||||
if (arm->core_mode != ARM_MODE_SVC)
|
if (arm->core_mode != ARM_MODE_SVC)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -510,9 +506,7 @@ int arm_semihosting(struct target *target, int *retval)
|
||||||
if (insn != 0xEF123456)
|
if (insn != 0xEF123456)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
} else if (is_armv7m(target_to_armv7m(target))) {
|
||||||
else if (is_armv7m(target_to_armv7m(target)))
|
|
||||||
{
|
|
||||||
uint16_t insn;
|
uint16_t insn;
|
||||||
|
|
||||||
if (target->debug_reason != DBG_REASON_BREAKPOINT)
|
if (target->debug_reason != DBG_REASON_BREAKPOINT)
|
||||||
|
@ -529,9 +523,7 @@ int arm_semihosting(struct target *target, int *retval)
|
||||||
/* bkpt 0xAB */
|
/* bkpt 0xAB */
|
||||||
if (insn != 0xBEAB)
|
if (insn != 0xBEAB)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
LOG_ERROR("Unsupported semi-hosting Target");
|
LOG_ERROR("Unsupported semi-hosting Target");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
* Free Software Foundation, Inc., *
|
* Free Software Foundation, Inc., *
|
||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -32,51 +33,32 @@
|
||||||
#include "register.h"
|
#include "register.h"
|
||||||
#include <helper/log.h>
|
#include <helper/log.h>
|
||||||
|
|
||||||
|
|
||||||
static uint32_t arm_shift(uint8_t shift, uint32_t Rm,
|
static uint32_t arm_shift(uint8_t shift, uint32_t Rm,
|
||||||
uint32_t shift_amount, uint8_t *carry)
|
uint32_t shift_amount, uint8_t *carry)
|
||||||
{
|
{
|
||||||
uint32_t return_value = 0;
|
uint32_t return_value = 0;
|
||||||
shift_amount &= 0xff;
|
shift_amount &= 0xff;
|
||||||
|
|
||||||
if (shift == 0x0) /* LSL */
|
if (shift == 0x0) { /* LSL */
|
||||||
{
|
if ((shift_amount > 0) && (shift_amount <= 32)) {
|
||||||
if ((shift_amount > 0) && (shift_amount <= 32))
|
|
||||||
{
|
|
||||||
return_value = Rm << shift_amount;
|
return_value = Rm << shift_amount;
|
||||||
*carry = Rm >> (32 - shift_amount);
|
*carry = Rm >> (32 - shift_amount);
|
||||||
}
|
} else if (shift_amount > 32) {
|
||||||
else if (shift_amount > 32)
|
|
||||||
{
|
|
||||||
return_value = 0x0;
|
return_value = 0x0;
|
||||||
*carry = 0x0;
|
*carry = 0x0;
|
||||||
}
|
} else /* (shift_amount == 0) */
|
||||||
else /* (shift_amount == 0) */
|
|
||||||
{
|
|
||||||
return_value = Rm;
|
return_value = Rm;
|
||||||
}
|
} else if (shift == 0x1) { /* LSR */
|
||||||
}
|
if ((shift_amount > 0) && (shift_amount <= 32)) {
|
||||||
else if (shift == 0x1) /* LSR */
|
|
||||||
{
|
|
||||||
if ((shift_amount > 0) && (shift_amount <= 32))
|
|
||||||
{
|
|
||||||
return_value = Rm >> shift_amount;
|
return_value = Rm >> shift_amount;
|
||||||
*carry = (Rm >> (shift_amount - 1)) & 1;
|
*carry = (Rm >> (shift_amount - 1)) & 1;
|
||||||
}
|
} else if (shift_amount > 32) {
|
||||||
else if (shift_amount > 32)
|
|
||||||
{
|
|
||||||
return_value = 0x0;
|
return_value = 0x0;
|
||||||
*carry = 0x0;
|
*carry = 0x0;
|
||||||
}
|
} else /* (shift_amount == 0) */
|
||||||
else /* (shift_amount == 0) */
|
|
||||||
{
|
|
||||||
return_value = Rm;
|
return_value = Rm;
|
||||||
}
|
} else if (shift == 0x2) { /* ASR */
|
||||||
}
|
if ((shift_amount > 0) && (shift_amount <= 32)) {
|
||||||
else if (shift == 0x2) /* ASR */
|
|
||||||
{
|
|
||||||
if ((shift_amount > 0) && (shift_amount <= 32))
|
|
||||||
{
|
|
||||||
/* C right shifts of unsigned values are guaranteed to
|
/* C right shifts of unsigned values are guaranteed to
|
||||||
* be logical (shift in zeroes); simulate an arithmetic
|
* be logical (shift in zeroes); simulate an arithmetic
|
||||||
* shift (shift in signed-bit) by adding the sign bit
|
* shift (shift in signed-bit) by adding the sign bit
|
||||||
|
@ -85,40 +67,25 @@ static uint32_t arm_shift(uint8_t shift, uint32_t Rm,
|
||||||
return_value = Rm >> shift_amount;
|
return_value = Rm >> shift_amount;
|
||||||
if (Rm & 0x80000000)
|
if (Rm & 0x80000000)
|
||||||
return_value |= 0xffffffff << (32 - shift_amount);
|
return_value |= 0xffffffff << (32 - shift_amount);
|
||||||
}
|
} else if (shift_amount > 32) {
|
||||||
else if (shift_amount > 32)
|
if (Rm & 0x80000000) {
|
||||||
{
|
|
||||||
if (Rm & 0x80000000)
|
|
||||||
{
|
|
||||||
return_value = 0xffffffff;
|
return_value = 0xffffffff;
|
||||||
*carry = 0x1;
|
*carry = 0x1;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
return_value = 0x0;
|
return_value = 0x0;
|
||||||
*carry = 0x0;
|
*carry = 0x0;
|
||||||
}
|
}
|
||||||
}
|
} else /* (shift_amount == 0) */
|
||||||
else /* (shift_amount == 0) */
|
|
||||||
{
|
|
||||||
return_value = Rm;
|
return_value = Rm;
|
||||||
}
|
} else if (shift == 0x3) { /* ROR */
|
||||||
}
|
|
||||||
else if (shift == 0x3) /* ROR */
|
|
||||||
{
|
|
||||||
if (shift_amount == 0)
|
if (shift_amount == 0)
|
||||||
{
|
|
||||||
return_value = Rm;
|
return_value = Rm;
|
||||||
}
|
else {
|
||||||
else
|
|
||||||
{
|
|
||||||
shift_amount = shift_amount % 32;
|
shift_amount = shift_amount % 32;
|
||||||
return_value = (Rm >> shift_amount) | (Rm << (32 - shift_amount));
|
return_value = (Rm >> shift_amount) | (Rm << (32 - shift_amount));
|
||||||
*carry = (return_value >> 31) & 0x1;
|
*carry = (return_value >> 31) & 0x1;
|
||||||
}
|
}
|
||||||
}
|
} else if (shift == 0x4) { /* RRX */
|
||||||
else if (shift == 0x4) /* RRX */
|
|
||||||
{
|
|
||||||
return_value = Rm >> 1;
|
return_value = Rm >> 1;
|
||||||
if (*carry)
|
if (*carry)
|
||||||
Rm |= 0x80000000;
|
Rm |= 0x80000000;
|
||||||
|
@ -130,8 +97,8 @@ static uint32_t arm_shift(uint8_t shift, uint32_t Rm,
|
||||||
|
|
||||||
|
|
||||||
static uint32_t arm_shifter_operand(struct arm_sim_interface *sim,
|
static uint32_t arm_shifter_operand(struct arm_sim_interface *sim,
|
||||||
int variant, union arm_shifter_operand shifter_operand,
|
int variant, union arm_shifter_operand shifter_operand,
|
||||||
uint8_t *shifter_carry_out)
|
uint8_t *shifter_carry_out)
|
||||||
{
|
{
|
||||||
uint32_t return_value;
|
uint32_t return_value;
|
||||||
int instruction_size;
|
int instruction_size;
|
||||||
|
@ -144,11 +111,8 @@ static uint32_t arm_shifter_operand(struct arm_sim_interface *sim,
|
||||||
*shifter_carry_out = sim->get_cpsr(sim, 29, 1);
|
*shifter_carry_out = sim->get_cpsr(sim, 29, 1);
|
||||||
|
|
||||||
if (variant == 0) /* 32-bit immediate */
|
if (variant == 0) /* 32-bit immediate */
|
||||||
{
|
|
||||||
return_value = shifter_operand.immediate.immediate;
|
return_value = shifter_operand.immediate.immediate;
|
||||||
}
|
else if (variant == 1) {/* immediate shift */
|
||||||
else if (variant == 1) /* immediate shift */
|
|
||||||
{
|
|
||||||
uint32_t Rm = sim->get_reg_mode(sim, shifter_operand.immediate_shift.Rm);
|
uint32_t Rm = sim->get_reg_mode(sim, shifter_operand.immediate_shift.Rm);
|
||||||
|
|
||||||
/* adjust RM in case the PC is being read */
|
/* adjust RM in case the PC is being read */
|
||||||
|
@ -158,9 +122,7 @@ static uint32_t arm_shifter_operand(struct arm_sim_interface *sim,
|
||||||
return_value = arm_shift(shifter_operand.immediate_shift.shift,
|
return_value = arm_shift(shifter_operand.immediate_shift.shift,
|
||||||
Rm, shifter_operand.immediate_shift.shift_imm,
|
Rm, shifter_operand.immediate_shift.shift_imm,
|
||||||
shifter_carry_out);
|
shifter_carry_out);
|
||||||
}
|
} else if (variant == 2) { /* register shift */
|
||||||
else if (variant == 2) /* register shift */
|
|
||||||
{
|
|
||||||
uint32_t Rm = sim->get_reg_mode(sim, shifter_operand.register_shift.Rm);
|
uint32_t Rm = sim->get_reg_mode(sim, shifter_operand.register_shift.Rm);
|
||||||
uint32_t Rs = sim->get_reg_mode(sim, shifter_operand.register_shift.Rs);
|
uint32_t Rs = sim->get_reg_mode(sim, shifter_operand.register_shift.Rs);
|
||||||
|
|
||||||
|
@ -170,9 +132,7 @@ static uint32_t arm_shifter_operand(struct arm_sim_interface *sim,
|
||||||
|
|
||||||
return_value = arm_shift(shifter_operand.immediate_shift.shift,
|
return_value = arm_shift(shifter_operand.immediate_shift.shift,
|
||||||
Rm, Rs, shifter_carry_out);
|
Rm, Rs, shifter_carry_out);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
LOG_ERROR("BUG: shifter_operand.variant not 0, 1 or 2");
|
LOG_ERROR("BUG: shifter_operand.variant not 0, 1 or 2");
|
||||||
return_value = 0xffffffff;
|
return_value = 0xffffffff;
|
||||||
}
|
}
|
||||||
|
@ -182,8 +142,7 @@ static uint32_t arm_shifter_operand(struct arm_sim_interface *sim,
|
||||||
|
|
||||||
static int pass_condition(uint32_t cpsr, uint32_t opcode)
|
static int pass_condition(uint32_t cpsr, uint32_t opcode)
|
||||||
{
|
{
|
||||||
switch ((opcode & 0xf0000000) >> 28)
|
switch ((opcode & 0xf0000000) >> 28) {
|
||||||
{
|
|
||||||
case 0x0: /* EQ */
|
case 0x0: /* EQ */
|
||||||
if (cpsr & 0x40000000)
|
if (cpsr & 0x40000000)
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -280,45 +239,35 @@ static int thumb_pass_branch_condition(uint32_t cpsr, uint16_t opcode)
|
||||||
* but the new pc is stored in the variable pointed at by the argument
|
* but the new pc is stored in the variable pointed at by the argument
|
||||||
*/
|
*/
|
||||||
static int arm_simulate_step_core(struct target *target,
|
static int arm_simulate_step_core(struct target *target,
|
||||||
uint32_t *dry_run_pc, struct arm_sim_interface *sim)
|
uint32_t *dry_run_pc, struct arm_sim_interface *sim)
|
||||||
{
|
{
|
||||||
uint32_t current_pc = sim->get_reg(sim, 15);
|
uint32_t current_pc = sim->get_reg(sim, 15);
|
||||||
struct arm_instruction instruction;
|
struct arm_instruction instruction;
|
||||||
int instruction_size;
|
int instruction_size;
|
||||||
int retval = ERROR_OK;
|
int retval = ERROR_OK;
|
||||||
|
|
||||||
if (sim->get_state(sim) == ARM_STATE_ARM)
|
if (sim->get_state(sim) == ARM_STATE_ARM) {
|
||||||
{
|
|
||||||
uint32_t opcode;
|
uint32_t opcode;
|
||||||
|
|
||||||
/* get current instruction, and identify it */
|
/* get current instruction, and identify it */
|
||||||
if ((retval = target_read_u32(target, current_pc, &opcode)) != ERROR_OK)
|
retval = target_read_u32(target, current_pc, &opcode);
|
||||||
{
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
retval = arm_evaluate_opcode(opcode, current_pc, &instruction);
|
||||||
if ((retval = arm_evaluate_opcode(opcode, current_pc, &instruction)) != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
{
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
|
||||||
instruction_size = 4;
|
instruction_size = 4;
|
||||||
|
|
||||||
/* check condition code (for all instructions) */
|
/* check condition code (for all instructions) */
|
||||||
if (!pass_condition(sim->get_cpsr(sim, 0, 32), opcode))
|
if (!pass_condition(sim->get_cpsr(sim, 0, 32), opcode)) {
|
||||||
{
|
|
||||||
if (dry_run_pc)
|
if (dry_run_pc)
|
||||||
{
|
|
||||||
*dry_run_pc = current_pc + instruction_size;
|
*dry_run_pc = current_pc + instruction_size;
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
sim->set_reg(sim, 15, current_pc + instruction_size);
|
sim->set_reg(sim, 15, current_pc + instruction_size);
|
||||||
}
|
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
uint16_t opcode;
|
uint16_t opcode;
|
||||||
|
|
||||||
retval = target_read_u16(target, current_pc, &opcode);
|
retval = target_read_u16(target, current_pc, &opcode);
|
||||||
|
@ -331,17 +280,12 @@ static int arm_simulate_step_core(struct target *target,
|
||||||
|
|
||||||
/* check condition code (only for branch (1) instructions) */
|
/* check condition code (only for branch (1) instructions) */
|
||||||
if ((opcode & 0xf000) == 0xd000
|
if ((opcode & 0xf000) == 0xd000
|
||||||
&& !thumb_pass_branch_condition(
|
&& !thumb_pass_branch_condition(
|
||||||
sim->get_cpsr(sim, 0, 32), opcode))
|
sim->get_cpsr(sim, 0, 32), opcode)) {
|
||||||
{
|
|
||||||
if (dry_run_pc)
|
if (dry_run_pc)
|
||||||
{
|
|
||||||
*dry_run_pc = current_pc + instruction_size;
|
*dry_run_pc = current_pc + instruction_size;
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
sim->set_reg(sim, 15, current_pc + instruction_size);
|
sim->set_reg(sim, 15, current_pc + instruction_size);
|
||||||
}
|
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
@ -362,67 +306,44 @@ static int arm_simulate_step_core(struct target *target,
|
||||||
/* examine instruction type */
|
/* examine instruction type */
|
||||||
|
|
||||||
/* branch instructions */
|
/* branch instructions */
|
||||||
if ((instruction.type >= ARM_B) && (instruction.type <= ARM_BLX))
|
if ((instruction.type >= ARM_B) && (instruction.type <= ARM_BLX)) {
|
||||||
{
|
|
||||||
uint32_t target_address;
|
uint32_t target_address;
|
||||||
|
|
||||||
if (instruction.info.b_bl_bx_blx.reg_operand == -1)
|
if (instruction.info.b_bl_bx_blx.reg_operand == -1)
|
||||||
{
|
|
||||||
target_address = instruction.info.b_bl_bx_blx.target_address;
|
target_address = instruction.info.b_bl_bx_blx.target_address;
|
||||||
}
|
else {
|
||||||
else
|
target_address = sim->get_reg_mode(sim,
|
||||||
{
|
instruction.info.b_bl_bx_blx.reg_operand);
|
||||||
target_address = sim->get_reg_mode(sim, instruction.info.b_bl_bx_blx.reg_operand);
|
|
||||||
if (instruction.info.b_bl_bx_blx.reg_operand == 15)
|
if (instruction.info.b_bl_bx_blx.reg_operand == 15)
|
||||||
{
|
|
||||||
target_address += 2 * instruction_size;
|
target_address += 2 * instruction_size;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dry_run_pc)
|
if (dry_run_pc) {
|
||||||
{
|
|
||||||
*dry_run_pc = target_address & ~1;
|
*dry_run_pc = target_address & ~1;
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
if (instruction.type == ARM_B)
|
if (instruction.type == ARM_B)
|
||||||
{
|
|
||||||
sim->set_reg(sim, 15, target_address);
|
sim->set_reg(sim, 15, target_address);
|
||||||
}
|
else if (instruction.type == ARM_BL) {
|
||||||
else if (instruction.type == ARM_BL)
|
|
||||||
{
|
|
||||||
uint32_t old_pc = sim->get_reg(sim, 15);
|
uint32_t old_pc = sim->get_reg(sim, 15);
|
||||||
int T = (sim->get_state(sim) == ARM_STATE_THUMB);
|
int T = (sim->get_state(sim) == ARM_STATE_THUMB);
|
||||||
sim->set_reg_mode(sim, 14, old_pc + 4 + T);
|
sim->set_reg_mode(sim, 14, old_pc + 4 + T);
|
||||||
sim->set_reg(sim, 15, target_address);
|
sim->set_reg(sim, 15, target_address);
|
||||||
}
|
} else if (instruction.type == ARM_BX) {
|
||||||
else if (instruction.type == ARM_BX)
|
|
||||||
{
|
|
||||||
if (target_address & 0x1)
|
if (target_address & 0x1)
|
||||||
{
|
|
||||||
sim->set_state(sim, ARM_STATE_THUMB);
|
sim->set_state(sim, ARM_STATE_THUMB);
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
sim->set_state(sim, ARM_STATE_ARM);
|
sim->set_state(sim, ARM_STATE_ARM);
|
||||||
}
|
|
||||||
sim->set_reg(sim, 15, target_address & 0xfffffffe);
|
sim->set_reg(sim, 15, target_address & 0xfffffffe);
|
||||||
}
|
} else if (instruction.type == ARM_BLX) {
|
||||||
else if (instruction.type == ARM_BLX)
|
|
||||||
{
|
|
||||||
uint32_t old_pc = sim->get_reg(sim, 15);
|
uint32_t old_pc = sim->get_reg(sim, 15);
|
||||||
int T = (sim->get_state(sim) == ARM_STATE_THUMB);
|
int T = (sim->get_state(sim) == ARM_STATE_THUMB);
|
||||||
sim->set_reg_mode(sim, 14, old_pc + 4 + T);
|
sim->set_reg_mode(sim, 14, old_pc + 4 + T);
|
||||||
|
|
||||||
if (target_address & 0x1)
|
if (target_address & 0x1)
|
||||||
{
|
|
||||||
sim->set_state(sim, ARM_STATE_THUMB);
|
sim->set_state(sim, ARM_STATE_THUMB);
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
sim->set_state(sim, ARM_STATE_ARM);
|
sim->set_state(sim, ARM_STATE_ARM);
|
||||||
}
|
|
||||||
sim->set_reg(sim, 15, target_address & 0xfffffffe);
|
sim->set_reg(sim, 15, target_address & 0xfffffffe);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -431,8 +352,7 @@ static int arm_simulate_step_core(struct target *target,
|
||||||
}
|
}
|
||||||
/* data processing instructions, except compare instructions (CMP, CMN, TST, TEQ) */
|
/* data processing instructions, except compare instructions (CMP, CMN, TST, TEQ) */
|
||||||
else if (((instruction.type >= ARM_AND) && (instruction.type <= ARM_RSC))
|
else if (((instruction.type >= ARM_AND) && (instruction.type <= ARM_RSC))
|
||||||
|| ((instruction.type >= ARM_ORR) && (instruction.type <= ARM_MVN)))
|
|| ((instruction.type >= ARM_ORR) && (instruction.type <= ARM_MVN))) {
|
||||||
{
|
|
||||||
uint32_t Rd, Rn, shifter_operand;
|
uint32_t Rd, Rn, shifter_operand;
|
||||||
uint8_t C = sim->get_cpsr(sim, 29, 1);
|
uint8_t C = sim->get_cpsr(sim, 29, 1);
|
||||||
uint8_t carry_out;
|
uint8_t carry_out;
|
||||||
|
@ -480,17 +400,14 @@ static int arm_simulate_step_core(struct target *target,
|
||||||
else
|
else
|
||||||
LOG_WARNING("unhandled instruction type");
|
LOG_WARNING("unhandled instruction type");
|
||||||
|
|
||||||
if (dry_run_pc)
|
if (dry_run_pc) {
|
||||||
{
|
|
||||||
if (instruction.info.data_proc.Rd == 15)
|
if (instruction.info.data_proc.Rd == 15)
|
||||||
*dry_run_pc = Rd & ~1;
|
*dry_run_pc = Rd & ~1;
|
||||||
else
|
else
|
||||||
*dry_run_pc = current_pc + instruction_size;
|
*dry_run_pc = current_pc + instruction_size;
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
if (instruction.info.data_proc.Rd == 15) {
|
if (instruction.info.data_proc.Rd == 15) {
|
||||||
sim->set_reg_mode(sim, 15, Rd & ~1);
|
sim->set_reg_mode(sim, 15, Rd & ~1);
|
||||||
if (Rd & 1)
|
if (Rd & 1)
|
||||||
|
@ -504,21 +421,15 @@ static int arm_simulate_step_core(struct target *target,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* compare instructions (CMP, CMN, TST, TEQ) */
|
/* compare instructions (CMP, CMN, TST, TEQ) */
|
||||||
else if ((instruction.type >= ARM_TST) && (instruction.type <= ARM_CMN))
|
else if ((instruction.type >= ARM_TST) && (instruction.type <= ARM_CMN)) {
|
||||||
{
|
if (dry_run_pc) {
|
||||||
if (dry_run_pc)
|
|
||||||
{
|
|
||||||
*dry_run_pc = current_pc + instruction_size;
|
*dry_run_pc = current_pc + instruction_size;
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
} else
|
||||||
else
|
|
||||||
{
|
|
||||||
LOG_WARNING("no updating of flags yet");
|
LOG_WARNING("no updating of flags yet");
|
||||||
}
|
|
||||||
}
|
}
|
||||||
/* load register instructions */
|
/* load register instructions */
|
||||||
else if ((instruction.type >= ARM_LDR) && (instruction.type <= ARM_LDRSH))
|
else if ((instruction.type >= ARM_LDR) && (instruction.type <= ARM_LDRSH)) {
|
||||||
{
|
|
||||||
uint32_t load_address = 0, modified_address = 0, load_value = 0;
|
uint32_t load_address = 0, modified_address = 0, load_value = 0;
|
||||||
uint32_t Rn = sim->get_reg_mode(sim, instruction.info.load_store.Rn);
|
uint32_t Rn = sim->get_reg_mode(sim, instruction.info.load_store.Rn);
|
||||||
|
|
||||||
|
@ -526,15 +437,12 @@ static int arm_simulate_step_core(struct target *target,
|
||||||
if (instruction.info.load_store.Rn == 15)
|
if (instruction.info.load_store.Rn == 15)
|
||||||
Rn += 2 * instruction_size;
|
Rn += 2 * instruction_size;
|
||||||
|
|
||||||
if (instruction.info.load_store.offset_mode == 0)
|
if (instruction.info.load_store.offset_mode == 0) {
|
||||||
{
|
|
||||||
if (instruction.info.load_store.U)
|
if (instruction.info.load_store.U)
|
||||||
modified_address = Rn + instruction.info.load_store.offset.offset;
|
modified_address = Rn + instruction.info.load_store.offset.offset;
|
||||||
else
|
else
|
||||||
modified_address = Rn - instruction.info.load_store.offset.offset;
|
modified_address = Rn - instruction.info.load_store.offset.offset;
|
||||||
}
|
} else if (instruction.info.load_store.offset_mode == 1) {
|
||||||
else if (instruction.info.load_store.offset_mode == 1)
|
|
||||||
{
|
|
||||||
uint32_t offset;
|
uint32_t offset;
|
||||||
uint32_t Rm = sim->get_reg_mode(sim,
|
uint32_t Rm = sim->get_reg_mode(sim,
|
||||||
instruction.info.load_store.offset.reg.Rm);
|
instruction.info.load_store.offset.reg.Rm);
|
||||||
|
@ -548,31 +456,23 @@ static int arm_simulate_step_core(struct target *target,
|
||||||
modified_address = Rn + offset;
|
modified_address = Rn + offset;
|
||||||
else
|
else
|
||||||
modified_address = Rn - offset;
|
modified_address = Rn - offset;
|
||||||
}
|
} else
|
||||||
else
|
|
||||||
{
|
|
||||||
LOG_ERROR("BUG: offset_mode neither 0 (offset) nor 1 (scaled register)");
|
LOG_ERROR("BUG: offset_mode neither 0 (offset) nor 1 (scaled register)");
|
||||||
}
|
|
||||||
|
|
||||||
if (instruction.info.load_store.index_mode == 0)
|
if (instruction.info.load_store.index_mode == 0) {
|
||||||
{
|
|
||||||
/* offset mode
|
/* offset mode
|
||||||
* we load from the modified address, but don't change
|
* we load from the modified address, but don't change
|
||||||
* the base address register
|
* the base address register
|
||||||
*/
|
*/
|
||||||
load_address = modified_address;
|
load_address = modified_address;
|
||||||
modified_address = Rn;
|
modified_address = Rn;
|
||||||
}
|
} else if (instruction.info.load_store.index_mode == 1) {
|
||||||
else if (instruction.info.load_store.index_mode == 1)
|
|
||||||
{
|
|
||||||
/* pre-indexed mode
|
/* pre-indexed mode
|
||||||
* we load from the modified address, and write it
|
* we load from the modified address, and write it
|
||||||
* back to the base address register
|
* back to the base address register
|
||||||
*/
|
*/
|
||||||
load_address = modified_address;
|
load_address = modified_address;
|
||||||
}
|
} else if (instruction.info.load_store.index_mode == 2) {
|
||||||
else if (instruction.info.load_store.index_mode == 2)
|
|
||||||
{
|
|
||||||
/* post-indexed mode
|
/* post-indexed mode
|
||||||
* we load from the unmodified address, and write the
|
* we load from the unmodified address, and write the
|
||||||
* modified address back
|
* modified address back
|
||||||
|
@ -580,28 +480,24 @@ static int arm_simulate_step_core(struct target *target,
|
||||||
load_address = Rn;
|
load_address = Rn;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((!dry_run_pc) || (instruction.info.load_store.Rd == 15))
|
if ((!dry_run_pc) || (instruction.info.load_store.Rd == 15)) {
|
||||||
{
|
|
||||||
retval = target_read_u32(target, load_address, &load_value);
|
retval = target_read_u32(target, load_address, &load_value);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dry_run_pc)
|
if (dry_run_pc) {
|
||||||
{
|
|
||||||
if (instruction.info.load_store.Rd == 15)
|
if (instruction.info.load_store.Rd == 15)
|
||||||
*dry_run_pc = load_value & ~1;
|
*dry_run_pc = load_value & ~1;
|
||||||
else
|
else
|
||||||
*dry_run_pc = current_pc + instruction_size;
|
*dry_run_pc = current_pc + instruction_size;
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
if ((instruction.info.load_store.index_mode == 1) ||
|
if ((instruction.info.load_store.index_mode == 1) ||
|
||||||
(instruction.info.load_store.index_mode == 2))
|
(instruction.info.load_store.index_mode == 2))
|
||||||
{
|
sim->set_reg_mode(sim,
|
||||||
sim->set_reg_mode(sim, instruction.info.load_store.Rn, modified_address);
|
instruction.info.load_store.Rn,
|
||||||
}
|
modified_address);
|
||||||
|
|
||||||
if (instruction.info.load_store.Rd == 15) {
|
if (instruction.info.load_store.Rd == 15) {
|
||||||
sim->set_reg_mode(sim, 15, load_value & ~1);
|
sim->set_reg_mode(sim, 15, load_value & ~1);
|
||||||
|
@ -615,84 +511,68 @@ static int arm_simulate_step_core(struct target *target,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* load multiple instruction */
|
/* load multiple instruction */
|
||||||
else if (instruction.type == ARM_LDM)
|
else if (instruction.type == ARM_LDM) {
|
||||||
{
|
|
||||||
int i;
|
int i;
|
||||||
uint32_t Rn = sim->get_reg_mode(sim, instruction.info.load_store_multiple.Rn);
|
uint32_t Rn = sim->get_reg_mode(sim, instruction.info.load_store_multiple.Rn);
|
||||||
uint32_t load_values[16];
|
uint32_t load_values[16];
|
||||||
int bits_set = 0;
|
int bits_set = 0;
|
||||||
|
|
||||||
for (i = 0; i < 16; i++)
|
for (i = 0; i < 16; i++) {
|
||||||
{
|
|
||||||
if (instruction.info.load_store_multiple.register_list & (1 << i))
|
if (instruction.info.load_store_multiple.register_list & (1 << i))
|
||||||
bits_set++;
|
bits_set++;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (instruction.info.load_store_multiple.addressing_mode)
|
switch (instruction.info.load_store_multiple.addressing_mode) {
|
||||||
{
|
case 0: /* Increment after */
|
||||||
case 0: /* Increment after */
|
|
||||||
Rn = Rn;
|
Rn = Rn;
|
||||||
break;
|
break;
|
||||||
case 1: /* Increment before */
|
case 1: /* Increment before */
|
||||||
Rn = Rn + 4;
|
Rn = Rn + 4;
|
||||||
break;
|
break;
|
||||||
case 2: /* Decrement after */
|
case 2: /* Decrement after */
|
||||||
Rn = Rn - (bits_set * 4) + 4;
|
Rn = Rn - (bits_set * 4) + 4;
|
||||||
break;
|
break;
|
||||||
case 3: /* Decrement before */
|
case 3: /* Decrement before */
|
||||||
Rn = Rn - (bits_set * 4);
|
Rn = Rn - (bits_set * 4);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < 16; i++)
|
for (i = 0; i < 16; i++) {
|
||||||
{
|
if (instruction.info.load_store_multiple.register_list & (1 << i)) {
|
||||||
if (instruction.info.load_store_multiple.register_list & (1 << i))
|
|
||||||
{
|
|
||||||
if ((!dry_run_pc) || (i == 15))
|
if ((!dry_run_pc) || (i == 15))
|
||||||
{
|
|
||||||
target_read_u32(target, Rn, &load_values[i]);
|
target_read_u32(target, Rn, &load_values[i]);
|
||||||
}
|
|
||||||
Rn += 4;
|
Rn += 4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dry_run_pc)
|
if (dry_run_pc) {
|
||||||
{
|
if (instruction.info.load_store_multiple.register_list & 0x8000) {
|
||||||
if (instruction.info.load_store_multiple.register_list & 0x8000)
|
|
||||||
{
|
|
||||||
*dry_run_pc = load_values[15] & ~1;
|
*dry_run_pc = load_values[15] & ~1;
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
int update_cpsr = 0;
|
int update_cpsr = 0;
|
||||||
|
|
||||||
if (instruction.info.load_store_multiple.S)
|
if (instruction.info.load_store_multiple.S) {
|
||||||
{
|
|
||||||
if (instruction.info.load_store_multiple.register_list & 0x8000)
|
if (instruction.info.load_store_multiple.register_list & 0x8000)
|
||||||
update_cpsr = 1;
|
update_cpsr = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < 16; i++)
|
for (i = 0; i < 16; i++) {
|
||||||
{
|
if (instruction.info.load_store_multiple.register_list & (1 << i)) {
|
||||||
if (instruction.info.load_store_multiple.register_list & (1 << i))
|
|
||||||
{
|
|
||||||
if (i == 15) {
|
if (i == 15) {
|
||||||
uint32_t val = load_values[i];
|
uint32_t val = load_values[i];
|
||||||
sim->set_reg_mode(sim, i, val & ~1);
|
sim->set_reg_mode(sim, i, val & ~1);
|
||||||
if (val & 1)
|
if (val & 1)
|
||||||
sim->set_state(sim, ARM_STATE_THUMB);
|
sim->set_state(sim, ARM_STATE_THUMB);
|
||||||
else
|
else
|
||||||
sim->set_state(sim, ARM_STATE_ARM);
|
sim->set_state(sim, ARM_STATE_ARM);
|
||||||
} else {
|
} else
|
||||||
sim->set_reg_mode(sim, i, load_values[i]);
|
sim->set_reg_mode(sim, i, load_values[i]);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (update_cpsr)
|
if (update_cpsr) {
|
||||||
{
|
|
||||||
uint32_t spsr = sim->get_reg_mode(sim, 16);
|
uint32_t spsr = sim->get_reg_mode(sim, 16);
|
||||||
sim->set_reg(sim, ARMV4_5_CPSR, spsr);
|
sim->set_reg(sim, ARMV4_5_CPSR, spsr);
|
||||||
}
|
}
|
||||||
|
@ -701,51 +581,44 @@ static int arm_simulate_step_core(struct target *target,
|
||||||
if (instruction.info.load_store_multiple.W)
|
if (instruction.info.load_store_multiple.W)
|
||||||
sim->set_reg_mode(sim, instruction.info.load_store_multiple.Rn, Rn);
|
sim->set_reg_mode(sim, instruction.info.load_store_multiple.Rn, Rn);
|
||||||
|
|
||||||
|
|
||||||
if (instruction.info.load_store_multiple.register_list & 0x8000)
|
if (instruction.info.load_store_multiple.register_list & 0x8000)
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* store multiple instruction */
|
/* store multiple instruction */
|
||||||
else if (instruction.type == ARM_STM)
|
else if (instruction.type == ARM_STM) {
|
||||||
{
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (dry_run_pc)
|
if (dry_run_pc) {
|
||||||
{
|
|
||||||
/* STM wont affect PC (advance by instruction size */
|
/* STM wont affect PC (advance by instruction size */
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
uint32_t Rn = sim->get_reg_mode(sim,
|
uint32_t Rn = sim->get_reg_mode(sim,
|
||||||
instruction.info.load_store_multiple.Rn);
|
instruction.info.load_store_multiple.Rn);
|
||||||
int bits_set = 0;
|
int bits_set = 0;
|
||||||
|
|
||||||
for (i = 0; i < 16; i++)
|
for (i = 0; i < 16; i++) {
|
||||||
{
|
|
||||||
if (instruction.info.load_store_multiple.register_list & (1 << i))
|
if (instruction.info.load_store_multiple.register_list & (1 << i))
|
||||||
bits_set++;
|
bits_set++;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (instruction.info.load_store_multiple.addressing_mode)
|
switch (instruction.info.load_store_multiple.addressing_mode) {
|
||||||
{
|
case 0: /* Increment after */
|
||||||
case 0: /* Increment after */
|
|
||||||
Rn = Rn;
|
Rn = Rn;
|
||||||
break;
|
break;
|
||||||
case 1: /* Increment before */
|
case 1: /* Increment before */
|
||||||
Rn = Rn + 4;
|
Rn = Rn + 4;
|
||||||
break;
|
break;
|
||||||
case 2: /* Decrement after */
|
case 2: /* Decrement after */
|
||||||
Rn = Rn - (bits_set * 4) + 4;
|
Rn = Rn - (bits_set * 4) + 4;
|
||||||
break;
|
break;
|
||||||
case 3: /* Decrement before */
|
case 3: /* Decrement before */
|
||||||
Rn = Rn - (bits_set * 4);
|
Rn = Rn - (bits_set * 4);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < 16; i++)
|
for (i = 0; i < 16; i++) {
|
||||||
{
|
if (instruction.info.load_store_multiple.register_list & (1 << i)) {
|
||||||
if (instruction.info.load_store_multiple.register_list & (1 << i))
|
|
||||||
{
|
|
||||||
target_write_u32(target, Rn, sim->get_reg_mode(sim, i));
|
target_write_u32(target, Rn, sim->get_reg_mode(sim, i));
|
||||||
Rn += 4;
|
Rn += 4;
|
||||||
}
|
}
|
||||||
|
@ -757,22 +630,17 @@ static int arm_simulate_step_core(struct target *target,
|
||||||
instruction.info.load_store_multiple.Rn, Rn);
|
instruction.info.load_store_multiple.Rn, Rn);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
} else if (!dry_run_pc) {
|
||||||
else if (!dry_run_pc)
|
|
||||||
{
|
|
||||||
/* the instruction wasn't handled, but we're supposed to simulate it
|
/* the instruction wasn't handled, but we're supposed to simulate it
|
||||||
*/
|
*/
|
||||||
LOG_ERROR("Unimplemented instruction, could not simulate it.");
|
LOG_ERROR("Unimplemented instruction, could not simulate it.");
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dry_run_pc)
|
if (dry_run_pc) {
|
||||||
{
|
|
||||||
*dry_run_pc = current_pc + instruction_size;
|
*dry_run_pc = current_pc + instruction_size;
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
sim->set_reg(sim, 15, current_pc + instruction_size);
|
sim->set_reg(sim, 15, current_pc + instruction_size);
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
@ -806,7 +674,7 @@ static void armv4_5_set_reg_mode(struct arm_sim_interface *sim, int reg, uint32_
|
||||||
struct arm *arm = (struct arm *)sim->user_data;
|
struct arm *arm = (struct arm *)sim->user_data;
|
||||||
|
|
||||||
buf_set_u32(ARMV4_5_CORE_REG_MODE(arm->core_cache,
|
buf_set_u32(ARMV4_5_CORE_REG_MODE(arm->core_cache,
|
||||||
arm->core_mode, reg).value, 0, 32, value);
|
arm->core_mode, reg).value, 0, 32, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t armv4_5_get_cpsr(struct arm_sim_interface *sim, int pos, int bits)
|
static uint32_t armv4_5_get_cpsr(struct arm_sim_interface *sim, int pos, int bits)
|
||||||
|
@ -830,7 +698,6 @@ static void armv4_5_set_state(struct arm_sim_interface *sim, enum arm_state mode
|
||||||
arm->core_state = mode;
|
arm->core_state = mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static enum arm_mode armv4_5_get_mode(struct arm_sim_interface *sim)
|
static enum arm_mode armv4_5_get_mode(struct arm_sim_interface *sim)
|
||||||
{
|
{
|
||||||
struct arm *arm = (struct arm *)sim->user_data;
|
struct arm *arm = (struct arm *)sim->user_data;
|
||||||
|
@ -838,8 +705,6 @@ static enum arm_mode armv4_5_get_mode(struct arm_sim_interface *sim)
|
||||||
return arm->core_mode;
|
return arm->core_mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int arm_simulate_step(struct target *target, uint32_t *dry_run_pc)
|
int arm_simulate_step(struct target *target, uint32_t *dry_run_pc)
|
||||||
{
|
{
|
||||||
struct arm *arm = target_to_arm(target);
|
struct arm *arm = target_to_arm(target);
|
||||||
|
@ -857,4 +722,3 @@ int arm_simulate_step(struct target *target, uint32_t *dry_run_pc)
|
||||||
|
|
||||||
return arm_simulate_step_core(target, dry_run_pc, &sim);
|
return arm_simulate_step_core(target, dry_run_pc, &sim);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
* Free Software Foundation, Inc., *
|
* Free Software Foundation, Inc., *
|
||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#ifndef ARM_SIMULATOR_H
|
#ifndef ARM_SIMULATOR_H
|
||||||
#define ARM_SIMULATOR_H
|
#define ARM_SIMULATOR_H
|
||||||
|
|
||||||
|
@ -24,8 +25,7 @@
|
||||||
|
|
||||||
struct target;
|
struct target;
|
||||||
|
|
||||||
struct arm_sim_interface
|
struct arm_sim_interface {
|
||||||
{
|
|
||||||
void *user_data;
|
void *user_data;
|
||||||
uint32_t (*get_reg)(struct arm_sim_interface *sim, int reg);
|
uint32_t (*get_reg)(struct arm_sim_interface *sim, int reg);
|
||||||
void (*set_reg)(struct arm_sim_interface *sim, int reg, uint32_t value);
|
void (*set_reg)(struct arm_sim_interface *sim, int reg, uint32_t value);
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
* Free Software Foundation, Inc., *
|
* Free Software Foundation, Inc., *
|
||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -36,10 +37,9 @@
|
||||||
#include "algorithm.h"
|
#include "algorithm.h"
|
||||||
#include "register.h"
|
#include "register.h"
|
||||||
|
|
||||||
|
|
||||||
/* offsets into armv4_5 core register cache */
|
/* offsets into armv4_5 core register cache */
|
||||||
enum {
|
enum {
|
||||||
// ARMV4_5_CPSR = 31,
|
/* ARMV4_5_CPSR = 31, */
|
||||||
ARMV4_5_SPSR_FIQ = 32,
|
ARMV4_5_SPSR_FIQ = 32,
|
||||||
ARMV4_5_SPSR_IRQ = 33,
|
ARMV4_5_SPSR_IRQ = 33,
|
||||||
ARMV4_5_SPSR_SVC = 34,
|
ARMV4_5_SPSR_SVC = 34,
|
||||||
|
@ -167,27 +167,27 @@ bool is_arm_mode(unsigned psr_mode)
|
||||||
int arm_mode_to_number(enum arm_mode mode)
|
int arm_mode_to_number(enum arm_mode mode)
|
||||||
{
|
{
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case ARM_MODE_ANY:
|
case ARM_MODE_ANY:
|
||||||
/* map MODE_ANY to user mode */
|
/* map MODE_ANY to user mode */
|
||||||
case ARM_MODE_USR:
|
case ARM_MODE_USR:
|
||||||
return 0;
|
return 0;
|
||||||
case ARM_MODE_FIQ:
|
case ARM_MODE_FIQ:
|
||||||
return 1;
|
return 1;
|
||||||
case ARM_MODE_IRQ:
|
case ARM_MODE_IRQ:
|
||||||
return 2;
|
return 2;
|
||||||
case ARM_MODE_SVC:
|
case ARM_MODE_SVC:
|
||||||
return 3;
|
return 3;
|
||||||
case ARM_MODE_ABT:
|
case ARM_MODE_ABT:
|
||||||
return 4;
|
return 4;
|
||||||
case ARM_MODE_UND:
|
case ARM_MODE_UND:
|
||||||
return 5;
|
return 5;
|
||||||
case ARM_MODE_SYS:
|
case ARM_MODE_SYS:
|
||||||
return 6;
|
return 6;
|
||||||
case ARM_MODE_MON:
|
case ARM_MODE_MON:
|
||||||
return 7;
|
return 7;
|
||||||
default:
|
default:
|
||||||
LOG_ERROR("invalid mode value encountered %d", mode);
|
LOG_ERROR("invalid mode value encountered %d", mode);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -195,30 +195,29 @@ int arm_mode_to_number(enum arm_mode mode)
|
||||||
enum arm_mode armv4_5_number_to_mode(int number)
|
enum arm_mode armv4_5_number_to_mode(int number)
|
||||||
{
|
{
|
||||||
switch (number) {
|
switch (number) {
|
||||||
case 0:
|
case 0:
|
||||||
return ARM_MODE_USR;
|
return ARM_MODE_USR;
|
||||||
case 1:
|
case 1:
|
||||||
return ARM_MODE_FIQ;
|
return ARM_MODE_FIQ;
|
||||||
case 2:
|
case 2:
|
||||||
return ARM_MODE_IRQ;
|
return ARM_MODE_IRQ;
|
||||||
case 3:
|
case 3:
|
||||||
return ARM_MODE_SVC;
|
return ARM_MODE_SVC;
|
||||||
case 4:
|
case 4:
|
||||||
return ARM_MODE_ABT;
|
return ARM_MODE_ABT;
|
||||||
case 5:
|
case 5:
|
||||||
return ARM_MODE_UND;
|
return ARM_MODE_UND;
|
||||||
case 6:
|
case 6:
|
||||||
return ARM_MODE_SYS;
|
return ARM_MODE_SYS;
|
||||||
case 7:
|
case 7:
|
||||||
return ARM_MODE_MON;
|
return ARM_MODE_MON;
|
||||||
default:
|
default:
|
||||||
LOG_ERROR("mode index out of bounds %d", number);
|
LOG_ERROR("mode index out of bounds %d", number);
|
||||||
return ARM_MODE_ANY;
|
return ARM_MODE_ANY;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *arm_state_strings[] =
|
static const char *arm_state_strings[] = {
|
||||||
{
|
|
||||||
"ARM", "Thumb", "Jazelle", "ThumbEE",
|
"ARM", "Thumb", "Jazelle", "ThumbEE",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -312,8 +311,7 @@ static const struct {
|
||||||
/* map core mode (USR, FIQ, ...) and register number to
|
/* map core mode (USR, FIQ, ...) and register number to
|
||||||
* indices into the register cache
|
* indices into the register cache
|
||||||
*/
|
*/
|
||||||
const int armv4_5_core_reg_map[8][17] =
|
const int armv4_5_core_reg_map[8][17] = {
|
||||||
{
|
|
||||||
{ /* USR */
|
{ /* USR */
|
||||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 31
|
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 31
|
||||||
},
|
},
|
||||||
|
@ -371,8 +369,8 @@ void arm_set_cpsr(struct arm *arm, uint32_t cpsr)
|
||||||
|
|
||||||
arm->map = &armv4_5_core_reg_map[num][0];
|
arm->map = &armv4_5_core_reg_map[num][0];
|
||||||
arm->spsr = (mode == ARM_MODE_USR || mode == ARM_MODE_SYS)
|
arm->spsr = (mode == ARM_MODE_USR || mode == ARM_MODE_SYS)
|
||||||
? NULL
|
? NULL
|
||||||
: arm->core_cache->reg_list + arm->map[16];
|
: arm->core_cache->reg_list + arm->map[16];
|
||||||
|
|
||||||
/* Older ARMs won't have the J bit */
|
/* Older ARMs won't have the J bit */
|
||||||
enum arm_state state;
|
enum arm_state state;
|
||||||
|
@ -393,8 +391,8 @@ void arm_set_cpsr(struct arm *arm, uint32_t cpsr)
|
||||||
arm->core_state = state;
|
arm->core_state = state;
|
||||||
|
|
||||||
LOG_DEBUG("set CPSR %#8.8x: %s mode, %s state", (unsigned) cpsr,
|
LOG_DEBUG("set CPSR %#8.8x: %s mode, %s state", (unsigned) cpsr,
|
||||||
arm_mode_name(mode),
|
arm_mode_name(mode),
|
||||||
arm_state_strings[arm->core_state]);
|
arm_state_strings[arm->core_state]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -437,8 +435,7 @@ static const uint8_t arm_gdb_dummy_fp_value[12];
|
||||||
* Modern ARM cores use Vector Floating Point (VFP), if they
|
* Modern ARM cores use Vector Floating Point (VFP), if they
|
||||||
* have any floating point support. VFP is not FPA-compatible.
|
* have any floating point support. VFP is not FPA-compatible.
|
||||||
*/
|
*/
|
||||||
struct reg arm_gdb_dummy_fp_reg =
|
struct reg arm_gdb_dummy_fp_reg = {
|
||||||
{
|
|
||||||
.name = "GDB dummy FPA register",
|
.name = "GDB dummy FPA register",
|
||||||
.value = (uint8_t *) arm_gdb_dummy_fp_value,
|
.value = (uint8_t *) arm_gdb_dummy_fp_value,
|
||||||
.valid = 1,
|
.valid = 1,
|
||||||
|
@ -451,8 +448,7 @@ static const uint8_t arm_gdb_dummy_fps_value[4];
|
||||||
* Dummy FPA status registers are required to support GDB on ARM.
|
* Dummy FPA status registers are required to support GDB on ARM.
|
||||||
* Register packets require an obsolete FPA status register.
|
* Register packets require an obsolete FPA status register.
|
||||||
*/
|
*/
|
||||||
struct reg arm_gdb_dummy_fps_reg =
|
struct reg arm_gdb_dummy_fps_reg = {
|
||||||
{
|
|
||||||
.name = "GDB dummy FPA status register",
|
.name = "GDB dummy FPA status register",
|
||||||
.value = (uint8_t *) arm_gdb_dummy_fps_value,
|
.value = (uint8_t *) arm_gdb_dummy_fps_value,
|
||||||
.valid = 1,
|
.valid = 1,
|
||||||
|
@ -473,8 +469,7 @@ static int armv4_5_get_core_reg(struct reg *reg)
|
||||||
struct arm_reg *reg_arch_info = reg->arch_info;
|
struct arm_reg *reg_arch_info = reg->arch_info;
|
||||||
struct target *target = reg_arch_info->target;
|
struct target *target = reg_arch_info->target;
|
||||||
|
|
||||||
if (target->state != TARGET_HALTED)
|
if (target->state != TARGET_HALTED) {
|
||||||
{
|
|
||||||
LOG_ERROR("Target not halted");
|
LOG_ERROR("Target not halted");
|
||||||
return ERROR_TARGET_NOT_HALTED;
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
}
|
}
|
||||||
|
@ -496,8 +491,7 @@ static int armv4_5_set_core_reg(struct reg *reg, uint8_t *buf)
|
||||||
struct arm *armv4_5_target = target_to_arm(target);
|
struct arm *armv4_5_target = target_to_arm(target);
|
||||||
uint32_t value = buf_get_u32(buf, 0, 32);
|
uint32_t value = buf_get_u32(buf, 0, 32);
|
||||||
|
|
||||||
if (target->state != TARGET_HALTED)
|
if (target->state != TARGET_HALTED) {
|
||||||
{
|
|
||||||
LOG_ERROR("Target not halted");
|
LOG_ERROR("Target not halted");
|
||||||
return ERROR_TARGET_NOT_HALTED;
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
}
|
}
|
||||||
|
@ -514,12 +508,12 @@ static int armv4_5_set_core_reg(struct reg *reg, uint8_t *buf)
|
||||||
* it won't hurt since CPSR is always flushed anyway.
|
* it won't hurt since CPSR is always flushed anyway.
|
||||||
*/
|
*/
|
||||||
if (armv4_5_target->core_mode !=
|
if (armv4_5_target->core_mode !=
|
||||||
(enum arm_mode)(value & 0x1f)) {
|
(enum arm_mode)(value & 0x1f)) {
|
||||||
LOG_DEBUG("changing ARM core mode to '%s'",
|
LOG_DEBUG("changing ARM core mode to '%s'",
|
||||||
arm_mode_name(value & 0x1f));
|
arm_mode_name(value & 0x1f));
|
||||||
value &= ~((1 << 24) | (1 << 5));
|
value &= ~((1 << 24) | (1 << 5));
|
||||||
armv4_5_target->write_core_reg(target, reg,
|
armv4_5_target->write_core_reg(target, reg,
|
||||||
16, ARM_MODE_ANY, value);
|
16, ARM_MODE_ANY, value);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
buf_set_u32(reg->value, 0, 32, value);
|
buf_set_u32(reg->value, 0, 32, value);
|
||||||
|
@ -555,11 +549,10 @@ struct reg_cache *arm_build_reg_cache(struct target *target, struct arm *arm)
|
||||||
cache->reg_list = reg_list;
|
cache->reg_list = reg_list;
|
||||||
cache->num_regs = 0;
|
cache->num_regs = 0;
|
||||||
|
|
||||||
for (i = 0; i < num_regs; i++)
|
for (i = 0; i < num_regs; i++) {
|
||||||
{
|
|
||||||
/* Skip registers this core doesn't expose */
|
/* Skip registers this core doesn't expose */
|
||||||
if (arm_core_regs[i].mode == ARM_MODE_MON
|
if (arm_core_regs[i].mode == ARM_MODE_MON
|
||||||
&& arm->core_type != ARM_MODE_MON)
|
&& arm->core_type != ARM_MODE_MON)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* REVISIT handle Cortex-M, which only shadows R13/SP */
|
/* REVISIT handle Cortex-M, which only shadows R13/SP */
|
||||||
|
@ -588,26 +581,25 @@ int arm_arch_state(struct target *target)
|
||||||
{
|
{
|
||||||
struct arm *arm = target_to_arm(target);
|
struct arm *arm = target_to_arm(target);
|
||||||
|
|
||||||
if (arm->common_magic != ARM_COMMON_MAGIC)
|
if (arm->common_magic != ARM_COMMON_MAGIC) {
|
||||||
{
|
|
||||||
LOG_ERROR("BUG: called for a non-ARM target");
|
LOG_ERROR("BUG: called for a non-ARM target");
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_USER("target halted in %s state due to %s, current mode: %s\n"
|
LOG_USER("target halted in %s state due to %s, current mode: %s\n"
|
||||||
"cpsr: 0x%8.8" PRIx32 " pc: 0x%8.8" PRIx32 "%s",
|
"cpsr: 0x%8.8" PRIx32 " pc: 0x%8.8" PRIx32 "%s",
|
||||||
arm_state_strings[arm->core_state],
|
arm_state_strings[arm->core_state],
|
||||||
debug_reason_name(target),
|
debug_reason_name(target),
|
||||||
arm_mode_name(arm->core_mode),
|
arm_mode_name(arm->core_mode),
|
||||||
buf_get_u32(arm->cpsr->value, 0, 32),
|
buf_get_u32(arm->cpsr->value, 0, 32),
|
||||||
buf_get_u32(arm->pc->value, 0, 32),
|
buf_get_u32(arm->pc->value, 0, 32),
|
||||||
arm->is_semihosting ? ", semihosting" : "");
|
arm->is_semihosting ? ", semihosting" : "");
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define ARMV4_5_CORE_REG_MODENUM(cache, mode, num) \
|
#define ARMV4_5_CORE_REG_MODENUM(cache, mode, num) \
|
||||||
cache->reg_list[armv4_5_core_reg_map[mode][num]]
|
(cache->reg_list[armv4_5_core_reg_map[mode][num]])
|
||||||
|
|
||||||
COMMAND_HANDLER(handle_armv4_5_reg_command)
|
COMMAND_HANDLER(handle_armv4_5_reg_command)
|
||||||
{
|
{
|
||||||
|
@ -615,33 +607,30 @@ COMMAND_HANDLER(handle_armv4_5_reg_command)
|
||||||
struct arm *arm = target_to_arm(target);
|
struct arm *arm = target_to_arm(target);
|
||||||
struct reg *regs;
|
struct reg *regs;
|
||||||
|
|
||||||
if (!is_arm(arm))
|
if (!is_arm(arm)) {
|
||||||
{
|
|
||||||
command_print(CMD_CTX, "current target isn't an ARM");
|
command_print(CMD_CTX, "current target isn't an ARM");
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (target->state != TARGET_HALTED)
|
if (target->state != TARGET_HALTED) {
|
||||||
{
|
|
||||||
command_print(CMD_CTX, "error: target must be halted for register accesses");
|
command_print(CMD_CTX, "error: target must be halted for register accesses");
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (arm->core_type != ARM_MODE_ANY)
|
if (arm->core_type != ARM_MODE_ANY) {
|
||||||
{
|
command_print(CMD_CTX,
|
||||||
command_print(CMD_CTX, "Microcontroller Profile not supported - use standard reg cmd");
|
"Microcontroller Profile not supported - use standard reg cmd");
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!is_arm_mode(arm->core_mode))
|
if (!is_arm_mode(arm->core_mode)) {
|
||||||
{
|
|
||||||
LOG_ERROR("not a valid arm core mode - communication failure?");
|
LOG_ERROR("not a valid arm core mode - communication failure?");
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!arm->full_context) {
|
if (!arm->full_context) {
|
||||||
command_print(CMD_CTX, "error: target doesn't support %s",
|
command_print(CMD_CTX, "error: target doesn't support %s",
|
||||||
CMD_NAME);
|
CMD_NAME);
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -654,26 +643,26 @@ COMMAND_HANDLER(handle_armv4_5_reg_command)
|
||||||
|
|
||||||
/* label this bank of registers (or shadows) */
|
/* label this bank of registers (or shadows) */
|
||||||
switch (arm_mode_data[mode].psr) {
|
switch (arm_mode_data[mode].psr) {
|
||||||
case ARM_MODE_SYS:
|
case ARM_MODE_SYS:
|
||||||
continue;
|
|
||||||
case ARM_MODE_USR:
|
|
||||||
name = "System and User";
|
|
||||||
sep = "";
|
|
||||||
break;
|
|
||||||
case ARM_MODE_MON:
|
|
||||||
if (arm->core_type != ARM_MODE_MON)
|
|
||||||
continue;
|
continue;
|
||||||
|
case ARM_MODE_USR:
|
||||||
|
name = "System and User";
|
||||||
|
sep = "";
|
||||||
|
break;
|
||||||
|
case ARM_MODE_MON:
|
||||||
|
if (arm->core_type != ARM_MODE_MON)
|
||||||
|
continue;
|
||||||
/* FALLTHROUGH */
|
/* FALLTHROUGH */
|
||||||
default:
|
default:
|
||||||
name = arm_mode_data[mode].name;
|
name = arm_mode_data[mode].name;
|
||||||
shadow = "shadow ";
|
shadow = "shadow ";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
command_print(CMD_CTX, "%s%s mode %sregisters",
|
command_print(CMD_CTX, "%s%s mode %sregisters",
|
||||||
sep, name, shadow);
|
sep, name, shadow);
|
||||||
|
|
||||||
/* display N rows of up to 4 registers each */
|
/* display N rows of up to 4 registers each */
|
||||||
for (unsigned i = 0; i < arm_mode_data[mode].n_indices;) {
|
for (unsigned i = 0; i < arm_mode_data[mode].n_indices; ) {
|
||||||
char output[80];
|
char output[80];
|
||||||
int output_len = 0;
|
int output_len = 0;
|
||||||
|
|
||||||
|
@ -693,8 +682,8 @@ COMMAND_HANDLER(handle_armv4_5_reg_command)
|
||||||
value = buf_get_u32(reg->value, 0, 32);
|
value = buf_get_u32(reg->value, 0, 32);
|
||||||
output_len += snprintf(output + output_len,
|
output_len += snprintf(output + output_len,
|
||||||
sizeof(output) - output_len,
|
sizeof(output) - output_len,
|
||||||
"%8s: %8.8" PRIx32 " ",
|
"%8s: %8.8" PRIx32 " ",
|
||||||
reg->name, value);
|
reg->name, value);
|
||||||
}
|
}
|
||||||
command_print(CMD_CTX, "%s", output);
|
command_print(CMD_CTX, "%s", output);
|
||||||
}
|
}
|
||||||
|
@ -708,29 +697,22 @@ COMMAND_HANDLER(handle_armv4_5_core_state_command)
|
||||||
struct target *target = get_current_target(CMD_CTX);
|
struct target *target = get_current_target(CMD_CTX);
|
||||||
struct arm *arm = target_to_arm(target);
|
struct arm *arm = target_to_arm(target);
|
||||||
|
|
||||||
if (!is_arm(arm))
|
if (!is_arm(arm)) {
|
||||||
{
|
|
||||||
command_print(CMD_CTX, "current target isn't an ARM");
|
command_print(CMD_CTX, "current target isn't an ARM");
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (arm->core_type == ARM_MODE_THREAD)
|
if (arm->core_type == ARM_MODE_THREAD) {
|
||||||
{
|
|
||||||
/* armv7m not supported */
|
/* armv7m not supported */
|
||||||
command_print(CMD_CTX, "Unsupported Command");
|
command_print(CMD_CTX, "Unsupported Command");
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CMD_ARGC > 0)
|
if (CMD_ARGC > 0) {
|
||||||
{
|
|
||||||
if (strcmp(CMD_ARGV[0], "arm") == 0)
|
if (strcmp(CMD_ARGV[0], "arm") == 0)
|
||||||
{
|
|
||||||
arm->core_state = ARM_STATE_ARM;
|
arm->core_state = ARM_STATE_ARM;
|
||||||
}
|
|
||||||
if (strcmp(CMD_ARGV[0], "thumb") == 0)
|
if (strcmp(CMD_ARGV[0], "thumb") == 0)
|
||||||
{
|
|
||||||
arm->core_state = ARM_STATE_THUMB;
|
arm->core_state = ARM_STATE_THUMB;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
command_print(CMD_CTX, "core state: %s", arm_state_strings[arm->core_state]);
|
command_print(CMD_CTX, "core state: %s", arm_state_strings[arm->core_state]);
|
||||||
|
@ -758,35 +740,34 @@ COMMAND_HANDLER(handle_arm_disassemble_command)
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (arm->core_type == ARM_MODE_THREAD)
|
if (arm->core_type == ARM_MODE_THREAD) {
|
||||||
{
|
|
||||||
/* armv7m is always thumb mode */
|
/* armv7m is always thumb mode */
|
||||||
thumb = 1;
|
thumb = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (CMD_ARGC) {
|
switch (CMD_ARGC) {
|
||||||
case 3:
|
case 3:
|
||||||
if (strcmp(CMD_ARGV[2], "thumb") != 0)
|
if (strcmp(CMD_ARGV[2], "thumb") != 0)
|
||||||
goto usage;
|
goto usage;
|
||||||
thumb = 1;
|
thumb = 1;
|
||||||
/* FALL THROUGH */
|
/* FALL THROUGH */
|
||||||
case 2:
|
case 2:
|
||||||
COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], count);
|
COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], count);
|
||||||
/* FALL THROUGH */
|
/* FALL THROUGH */
|
||||||
case 1:
|
case 1:
|
||||||
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address);
|
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address);
|
||||||
if (address & 0x01) {
|
if (address & 0x01) {
|
||||||
if (!thumb) {
|
if (!thumb) {
|
||||||
command_print(CMD_CTX, "Disassemble as Thumb");
|
command_print(CMD_CTX, "Disassemble as Thumb");
|
||||||
thumb = 1;
|
thumb = 1;
|
||||||
|
}
|
||||||
|
address &= ~1;
|
||||||
}
|
}
|
||||||
address &= ~1;
|
break;
|
||||||
}
|
default:
|
||||||
break;
|
|
||||||
default:
|
|
||||||
usage:
|
usage:
|
||||||
count = 0;
|
count = 0;
|
||||||
retval = ERROR_COMMAND_SYNTAX_ERROR;
|
retval = ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (count-- > 0) {
|
while (count-- > 0) {
|
||||||
|
@ -819,7 +800,7 @@ usage:
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int jim_mcrmrc(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
|
static int jim_mcrmrc(Jim_Interp *interp, int argc, Jim_Obj * const *argv)
|
||||||
{
|
{
|
||||||
struct command_context *context;
|
struct command_context *context;
|
||||||
struct target *target;
|
struct target *target;
|
||||||
|
@ -827,7 +808,7 @@ static int jim_mcrmrc(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
context = current_command_context(interp);
|
context = current_command_context(interp);
|
||||||
assert( context != NULL);
|
assert(context != NULL);
|
||||||
|
|
||||||
target = get_current_target(context);
|
target = get_current_target(context);
|
||||||
if (target == NULL) {
|
if (target == NULL) {
|
||||||
|
@ -868,7 +849,7 @@ static int jim_mcrmrc(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
|
||||||
return retval;
|
return retval;
|
||||||
if (l & ~0xf) {
|
if (l & ~0xf) {
|
||||||
LOG_ERROR("%s: %s %d out of range", __func__,
|
LOG_ERROR("%s: %s %d out of range", __func__,
|
||||||
"coprocessor", (int) l);
|
"coprocessor", (int) l);
|
||||||
return JIM_ERR;
|
return JIM_ERR;
|
||||||
}
|
}
|
||||||
cpnum = l;
|
cpnum = l;
|
||||||
|
@ -878,7 +859,7 @@ static int jim_mcrmrc(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
|
||||||
return retval;
|
return retval;
|
||||||
if (l & ~0x7) {
|
if (l & ~0x7) {
|
||||||
LOG_ERROR("%s: %s %d out of range", __func__,
|
LOG_ERROR("%s: %s %d out of range", __func__,
|
||||||
"op1", (int) l);
|
"op1", (int) l);
|
||||||
return JIM_ERR;
|
return JIM_ERR;
|
||||||
}
|
}
|
||||||
op1 = l;
|
op1 = l;
|
||||||
|
@ -888,7 +869,7 @@ static int jim_mcrmrc(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
|
||||||
return retval;
|
return retval;
|
||||||
if (l & ~0xf) {
|
if (l & ~0xf) {
|
||||||
LOG_ERROR("%s: %s %d out of range", __func__,
|
LOG_ERROR("%s: %s %d out of range", __func__,
|
||||||
"CRn", (int) l);
|
"CRn", (int) l);
|
||||||
return JIM_ERR;
|
return JIM_ERR;
|
||||||
}
|
}
|
||||||
CRn = l;
|
CRn = l;
|
||||||
|
@ -898,7 +879,7 @@ static int jim_mcrmrc(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
|
||||||
return retval;
|
return retval;
|
||||||
if (l & ~0xf) {
|
if (l & ~0xf) {
|
||||||
LOG_ERROR("%s: %s %d out of range", __func__,
|
LOG_ERROR("%s: %s %d out of range", __func__,
|
||||||
"CRm", (int) l);
|
"CRm", (int) l);
|
||||||
return JIM_ERR;
|
return JIM_ERR;
|
||||||
}
|
}
|
||||||
CRm = l;
|
CRm = l;
|
||||||
|
@ -908,7 +889,7 @@ static int jim_mcrmrc(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
|
||||||
return retval;
|
return retval;
|
||||||
if (l & ~0x7) {
|
if (l & ~0x7) {
|
||||||
LOG_ERROR("%s: %s %d out of range", __func__,
|
LOG_ERROR("%s: %s %d out of range", __func__,
|
||||||
"op2", (int) l);
|
"op2", (int) l);
|
||||||
return JIM_ERR;
|
return JIM_ERR;
|
||||||
}
|
}
|
||||||
op2 = l;
|
op2 = l;
|
||||||
|
@ -925,19 +906,18 @@ static int jim_mcrmrc(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
|
||||||
*/
|
*/
|
||||||
if (argc == 7) {
|
if (argc == 7) {
|
||||||
retval = Jim_GetLong(interp, argv[6], &l);
|
retval = Jim_GetLong(interp, argv[6], &l);
|
||||||
if (retval != JIM_OK) {
|
if (retval != JIM_OK)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
|
||||||
value = l;
|
value = l;
|
||||||
|
|
||||||
/* NOTE: parameters reordered! */
|
/* NOTE: parameters reordered! */
|
||||||
// ARMV4_5_MCR(cpnum, op1, 0, CRn, CRm, op2)
|
/* ARMV4_5_MCR(cpnum, op1, 0, CRn, CRm, op2) */
|
||||||
retval = arm->mcr(target, cpnum, op1, op2, CRn, CRm, value);
|
retval = arm->mcr(target, cpnum, op1, op2, CRn, CRm, value);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return JIM_ERR;
|
return JIM_ERR;
|
||||||
} else {
|
} else {
|
||||||
/* NOTE: parameters reordered! */
|
/* NOTE: parameters reordered! */
|
||||||
// ARMV4_5_MRC(cpnum, op1, 0, CRn, CRm, op2)
|
/* ARMV4_5_MRC(cpnum, op1, 0, CRn, CRm, op2) */
|
||||||
retval = arm->mrc(target, cpnum, op1, op2, CRn, CRm, &value);
|
retval = arm->mrc(target, cpnum, op1, op2, CRn, CRm, &value);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return JIM_ERR;
|
return JIM_ERR;
|
||||||
|
@ -964,20 +944,17 @@ COMMAND_HANDLER(handle_arm_semihosting_command)
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!arm->setup_semihosting)
|
if (!arm->setup_semihosting) {
|
||||||
{
|
|
||||||
command_print(CMD_CTX, "semihosting not supported for current target");
|
command_print(CMD_CTX, "semihosting not supported for current target");
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CMD_ARGC > 0)
|
if (CMD_ARGC > 0) {
|
||||||
{
|
|
||||||
int semihosting;
|
int semihosting;
|
||||||
|
|
||||||
COMMAND_PARSE_ENABLE(CMD_ARGV[0], semihosting);
|
COMMAND_PARSE_ENABLE(CMD_ARGV[0], semihosting);
|
||||||
|
|
||||||
if (!target_was_examined(target))
|
if (!target_was_examined(target)) {
|
||||||
{
|
|
||||||
LOG_ERROR("Target not examined yet");
|
LOG_ERROR("Target not examined yet");
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
@ -992,8 +969,8 @@ COMMAND_HANDLER(handle_arm_semihosting_command)
|
||||||
}
|
}
|
||||||
|
|
||||||
command_print(CMD_CTX, "semihosting is %s",
|
command_print(CMD_CTX, "semihosting is %s",
|
||||||
arm->is_semihosting
|
arm->is_semihosting
|
||||||
? "enabled" : "disabled");
|
? "enabled" : "disabled");
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
@ -1055,19 +1032,18 @@ const struct command_registration arm_command_handlers[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
int arm_get_gdb_reg_list(struct target *target,
|
int arm_get_gdb_reg_list(struct target *target,
|
||||||
struct reg **reg_list[], int *reg_list_size)
|
struct reg **reg_list[], int *reg_list_size)
|
||||||
{
|
{
|
||||||
struct arm *arm = target_to_arm(target);
|
struct arm *arm = target_to_arm(target);
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (!is_arm_mode(arm->core_mode))
|
if (!is_arm_mode(arm->core_mode)) {
|
||||||
{
|
|
||||||
LOG_ERROR("not a valid arm core mode - communication failure?");
|
LOG_ERROR("not a valid arm core mode - communication failure?");
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
*reg_list_size = 26;
|
*reg_list_size = 26;
|
||||||
*reg_list = malloc(sizeof(struct reg*) * (*reg_list_size));
|
*reg_list = malloc(sizeof(struct reg *) * (*reg_list_size));
|
||||||
|
|
||||||
for (i = 0; i < 16; i++)
|
for (i = 0; i < 16; i++)
|
||||||
(*reg_list)[i] = arm_reg_current(arm, i);
|
(*reg_list)[i] = arm_reg_current(arm, i);
|
||||||
|
@ -1082,30 +1058,31 @@ int arm_get_gdb_reg_list(struct target *target,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* wait for execution to complete and check exit point */
|
/* wait for execution to complete and check exit point */
|
||||||
static int armv4_5_run_algorithm_completion(struct target *target, uint32_t exit_point, int timeout_ms, void *arch_info)
|
static int armv4_5_run_algorithm_completion(struct target *target,
|
||||||
|
uint32_t exit_point,
|
||||||
|
int timeout_ms,
|
||||||
|
void *arch_info)
|
||||||
{
|
{
|
||||||
int retval;
|
int retval;
|
||||||
struct arm *arm = target_to_arm(target);
|
struct arm *arm = target_to_arm(target);
|
||||||
|
|
||||||
if ((retval = target_wait_state(target, TARGET_HALTED, timeout_ms)) != ERROR_OK)
|
retval = target_wait_state(target, TARGET_HALTED, timeout_ms);
|
||||||
{
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
if (target->state != TARGET_HALTED) {
|
||||||
if (target->state != TARGET_HALTED)
|
retval = target_halt(target);
|
||||||
{
|
if (retval != ERROR_OK)
|
||||||
if ((retval = target_halt(target)) != ERROR_OK)
|
|
||||||
return retval;
|
return retval;
|
||||||
if ((retval = target_wait_state(target, TARGET_HALTED, 500)) != ERROR_OK)
|
retval = target_wait_state(target, TARGET_HALTED, 500);
|
||||||
{
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
|
||||||
return ERROR_TARGET_TIMEOUT;
|
return ERROR_TARGET_TIMEOUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* fast exit: ARMv5+ code can use BKPT */
|
/* fast exit: ARMv5+ code can use BKPT */
|
||||||
if (exit_point && buf_get_u32(arm->pc->value, 0, 32) != exit_point)
|
if (exit_point && buf_get_u32(arm->pc->value, 0, 32) != exit_point) {
|
||||||
{
|
LOG_WARNING(
|
||||||
LOG_WARNING("target reentered debug state, but not at the desired exit point: 0x%4.4" PRIx32 "",
|
"target reentered debug state, but not at the desired exit point: 0x%4.4" PRIx32 "",
|
||||||
buf_get_u32(arm->pc->value, 0, 32));
|
buf_get_u32(arm->pc->value, 0, 32));
|
||||||
return ERROR_TARGET_TIMEOUT;
|
return ERROR_TARGET_TIMEOUT;
|
||||||
}
|
}
|
||||||
|
@ -1114,12 +1091,12 @@ static int armv4_5_run_algorithm_completion(struct target *target, uint32_t exit
|
||||||
}
|
}
|
||||||
|
|
||||||
int armv4_5_run_algorithm_inner(struct target *target,
|
int armv4_5_run_algorithm_inner(struct target *target,
|
||||||
int num_mem_params, struct mem_param *mem_params,
|
int num_mem_params, struct mem_param *mem_params,
|
||||||
int num_reg_params, struct reg_param *reg_params,
|
int num_reg_params, struct reg_param *reg_params,
|
||||||
uint32_t entry_point, uint32_t exit_point,
|
uint32_t entry_point, uint32_t exit_point,
|
||||||
int timeout_ms, void *arch_info,
|
int timeout_ms, void *arch_info,
|
||||||
int (*run_it)(struct target *target, uint32_t exit_point,
|
int (*run_it)(struct target *target, uint32_t exit_point,
|
||||||
int timeout_ms, void *arch_info))
|
int timeout_ms, void *arch_info))
|
||||||
{
|
{
|
||||||
struct arm *arm = target_to_arm(target);
|
struct arm *arm = target_to_arm(target);
|
||||||
struct arm_algorithm *arm_algorithm_info = arch_info;
|
struct arm_algorithm *arm_algorithm_info = arch_info;
|
||||||
|
@ -1132,27 +1109,23 @@ int armv4_5_run_algorithm_inner(struct target *target,
|
||||||
|
|
||||||
LOG_DEBUG("Running algorithm");
|
LOG_DEBUG("Running algorithm");
|
||||||
|
|
||||||
if (arm_algorithm_info->common_magic != ARM_COMMON_MAGIC)
|
if (arm_algorithm_info->common_magic != ARM_COMMON_MAGIC) {
|
||||||
{
|
|
||||||
LOG_ERROR("current target isn't an ARMV4/5 target");
|
LOG_ERROR("current target isn't an ARMV4/5 target");
|
||||||
return ERROR_TARGET_INVALID;
|
return ERROR_TARGET_INVALID;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (target->state != TARGET_HALTED)
|
if (target->state != TARGET_HALTED) {
|
||||||
{
|
|
||||||
LOG_WARNING("target not halted");
|
LOG_WARNING("target not halted");
|
||||||
return ERROR_TARGET_NOT_HALTED;
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!is_arm_mode(arm->core_mode))
|
if (!is_arm_mode(arm->core_mode)) {
|
||||||
{
|
|
||||||
LOG_ERROR("not a valid arm core mode - communication failure?");
|
LOG_ERROR("not a valid arm core mode - communication failure?");
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* armv5 and later can terminate with BKPT instruction; less overhead */
|
/* armv5 and later can terminate with BKPT instruction; less overhead */
|
||||||
if (!exit_point && arm->is_armv4)
|
if (!exit_point && arm->is_armv4) {
|
||||||
{
|
|
||||||
LOG_ERROR("ARMv4 target needs HW breakpoint location");
|
LOG_ERROR("ARMv4 target needs HW breakpoint location");
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
@ -1160,46 +1133,41 @@ int armv4_5_run_algorithm_inner(struct target *target,
|
||||||
/* save r0..pc, cpsr-or-spsr, and then cpsr-for-sure;
|
/* save r0..pc, cpsr-or-spsr, and then cpsr-for-sure;
|
||||||
* they'll be restored later.
|
* they'll be restored later.
|
||||||
*/
|
*/
|
||||||
for (i = 0; i <= 16; i++)
|
for (i = 0; i <= 16; i++) {
|
||||||
{
|
|
||||||
struct reg *r;
|
struct reg *r;
|
||||||
|
|
||||||
r = &ARMV4_5_CORE_REG_MODE(arm->core_cache,
|
r = &ARMV4_5_CORE_REG_MODE(arm->core_cache,
|
||||||
arm_algorithm_info->core_mode, i);
|
arm_algorithm_info->core_mode, i);
|
||||||
if (!r->valid)
|
if (!r->valid)
|
||||||
arm->read_core_reg(target, r, i,
|
arm->read_core_reg(target, r, i,
|
||||||
arm_algorithm_info->core_mode);
|
arm_algorithm_info->core_mode);
|
||||||
context[i] = buf_get_u32(r->value, 0, 32);
|
context[i] = buf_get_u32(r->value, 0, 32);
|
||||||
}
|
}
|
||||||
cpsr = buf_get_u32(arm->cpsr->value, 0, 32);
|
cpsr = buf_get_u32(arm->cpsr->value, 0, 32);
|
||||||
|
|
||||||
for (i = 0; i < num_mem_params; i++)
|
for (i = 0; i < num_mem_params; i++) {
|
||||||
{
|
retval = target_write_buffer(target, mem_params[i].address, mem_params[i].size,
|
||||||
if ((retval = target_write_buffer(target, mem_params[i].address, mem_params[i].size, mem_params[i].value)) != ERROR_OK)
|
mem_params[i].value);
|
||||||
{
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < num_reg_params; i++)
|
for (i = 0; i < num_reg_params; i++) {
|
||||||
{
|
|
||||||
struct reg *reg = register_get_by_name(arm->core_cache, reg_params[i].reg_name, 0);
|
struct reg *reg = register_get_by_name(arm->core_cache, reg_params[i].reg_name, 0);
|
||||||
if (!reg)
|
if (!reg) {
|
||||||
{
|
|
||||||
LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name);
|
LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name);
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (reg->size != reg_params[i].size)
|
if (reg->size != reg_params[i].size) {
|
||||||
{
|
LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size",
|
||||||
LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size", reg_params[i].reg_name);
|
reg_params[i].reg_name);
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((retval = armv4_5_set_core_reg(reg, reg_params[i].value)) != ERROR_OK)
|
retval = armv4_5_set_core_reg(reg, reg_params[i].value);
|
||||||
{
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
arm->core_state = arm_algorithm_info->core_state;
|
arm->core_state = arm_algorithm_info->core_state;
|
||||||
|
@ -1207,35 +1175,33 @@ int armv4_5_run_algorithm_inner(struct target *target,
|
||||||
exit_breakpoint_size = 4;
|
exit_breakpoint_size = 4;
|
||||||
else if (arm->core_state == ARM_STATE_THUMB)
|
else if (arm->core_state == ARM_STATE_THUMB)
|
||||||
exit_breakpoint_size = 2;
|
exit_breakpoint_size = 2;
|
||||||
else
|
else {
|
||||||
{
|
|
||||||
LOG_ERROR("BUG: can't execute algorithms when not in ARM or Thumb state");
|
LOG_ERROR("BUG: can't execute algorithms when not in ARM or Thumb state");
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (arm_algorithm_info->core_mode != ARM_MODE_ANY)
|
if (arm_algorithm_info->core_mode != ARM_MODE_ANY) {
|
||||||
{
|
|
||||||
LOG_DEBUG("setting core_mode: 0x%2.2x",
|
LOG_DEBUG("setting core_mode: 0x%2.2x",
|
||||||
arm_algorithm_info->core_mode);
|
arm_algorithm_info->core_mode);
|
||||||
buf_set_u32(arm->cpsr->value, 0, 5,
|
buf_set_u32(arm->cpsr->value, 0, 5,
|
||||||
arm_algorithm_info->core_mode);
|
arm_algorithm_info->core_mode);
|
||||||
arm->cpsr->dirty = 1;
|
arm->cpsr->dirty = 1;
|
||||||
arm->cpsr->valid = 1;
|
arm->cpsr->valid = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* terminate using a hardware or (ARMv5+) software breakpoint */
|
/* terminate using a hardware or (ARMv5+) software breakpoint */
|
||||||
if (exit_point && (retval = breakpoint_add(target, exit_point,
|
if (exit_point) {
|
||||||
exit_breakpoint_size, BKPT_HARD)) != ERROR_OK)
|
retval = breakpoint_add(target, exit_point,
|
||||||
{
|
exit_breakpoint_size, BKPT_HARD);
|
||||||
LOG_ERROR("can't add HW breakpoint to terminate algorithm");
|
if (retval != ERROR_OK) {
|
||||||
return ERROR_TARGET_FAILURE;
|
LOG_ERROR("can't add HW breakpoint to terminate algorithm");
|
||||||
|
return ERROR_TARGET_FAILURE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((retval = target_resume(target, 0, entry_point, 1, 1)) != ERROR_OK)
|
retval = target_resume(target, 0, entry_point, 1, 1);
|
||||||
{
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
|
||||||
int retvaltemp;
|
|
||||||
retval = run_it(target, exit_point, timeout_ms, arch_info);
|
retval = run_it(target, exit_point, timeout_ms, arch_info);
|
||||||
|
|
||||||
if (exit_point)
|
if (exit_point)
|
||||||
|
@ -1244,31 +1210,32 @@ int armv4_5_run_algorithm_inner(struct target *target,
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
for (i = 0; i < num_mem_params; i++)
|
for (i = 0; i < num_mem_params; i++) {
|
||||||
{
|
if (mem_params[i].direction != PARAM_OUT) {
|
||||||
if (mem_params[i].direction != PARAM_OUT)
|
int retvaltemp = target_read_buffer(target, mem_params[i].address,
|
||||||
if ((retvaltemp = target_read_buffer(target, mem_params[i].address, mem_params[i].size, mem_params[i].value)) != ERROR_OK)
|
mem_params[i].size,
|
||||||
{
|
mem_params[i].value);
|
||||||
retval = retvaltemp;
|
if (retvaltemp != ERROR_OK)
|
||||||
}
|
retval = retvaltemp;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < num_reg_params; i++)
|
for (i = 0; i < num_reg_params; i++) {
|
||||||
{
|
if (reg_params[i].direction != PARAM_OUT) {
|
||||||
if (reg_params[i].direction != PARAM_OUT)
|
|
||||||
{
|
|
||||||
|
|
||||||
struct reg *reg = register_get_by_name(arm->core_cache, reg_params[i].reg_name, 0);
|
struct reg *reg = register_get_by_name(arm->core_cache,
|
||||||
if (!reg)
|
reg_params[i].reg_name,
|
||||||
{
|
0);
|
||||||
|
if (!reg) {
|
||||||
LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name);
|
LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name);
|
||||||
retval = ERROR_COMMAND_SYNTAX_ERROR;
|
retval = ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (reg->size != reg_params[i].size)
|
if (reg->size != reg_params[i].size) {
|
||||||
{
|
LOG_ERROR(
|
||||||
LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size", reg_params[i].reg_name);
|
"BUG: register '%s' size doesn't match reg_params[i].size",
|
||||||
|
reg_params[i].reg_name);
|
||||||
retval = ERROR_COMMAND_SYNTAX_ERROR;
|
retval = ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -1278,20 +1245,20 @@ int armv4_5_run_algorithm_inner(struct target *target,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* restore everything we saved before (17 or 18 registers) */
|
/* restore everything we saved before (17 or 18 registers) */
|
||||||
for (i = 0; i <= 16; i++)
|
for (i = 0; i <= 16; i++) {
|
||||||
{
|
|
||||||
uint32_t regvalue;
|
uint32_t regvalue;
|
||||||
regvalue = buf_get_u32(ARMV4_5_CORE_REG_MODE(arm->core_cache,
|
regvalue = buf_get_u32(ARMV4_5_CORE_REG_MODE(arm->core_cache,
|
||||||
arm_algorithm_info->core_mode, i).value, 0, 32);
|
arm_algorithm_info->core_mode, i).value, 0, 32);
|
||||||
if (regvalue != context[i])
|
if (regvalue != context[i]) {
|
||||||
{
|
|
||||||
LOG_DEBUG("restoring register %s with value 0x%8.8" PRIx32 "",
|
LOG_DEBUG("restoring register %s with value 0x%8.8" PRIx32 "",
|
||||||
ARMV4_5_CORE_REG_MODE(arm->core_cache,
|
ARMV4_5_CORE_REG_MODE(arm->core_cache,
|
||||||
arm_algorithm_info->core_mode, i).name, context[i]);
|
arm_algorithm_info->core_mode, i).name, context[i]);
|
||||||
buf_set_u32(ARMV4_5_CORE_REG_MODE(arm->core_cache,
|
buf_set_u32(ARMV4_5_CORE_REG_MODE(arm->core_cache,
|
||||||
arm_algorithm_info->core_mode, i).value, 0, 32, context[i]);
|
arm_algorithm_info->core_mode, i).value, 0, 32, context[i]);
|
||||||
ARMV4_5_CORE_REG_MODE(arm->core_cache, arm_algorithm_info->core_mode, i).valid = 1;
|
ARMV4_5_CORE_REG_MODE(arm->core_cache, arm_algorithm_info->core_mode,
|
||||||
ARMV4_5_CORE_REG_MODE(arm->core_cache, arm_algorithm_info->core_mode, i).dirty = 1;
|
i).valid = 1;
|
||||||
|
ARMV4_5_CORE_REG_MODE(arm->core_cache, arm_algorithm_info->core_mode,
|
||||||
|
i).dirty = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1303,9 +1270,26 @@ int armv4_5_run_algorithm_inner(struct target *target,
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
int armv4_5_run_algorithm(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 armv4_5_run_algorithm(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)
|
||||||
{
|
{
|
||||||
return armv4_5_run_algorithm_inner(target, num_mem_params, mem_params, num_reg_params, reg_params, entry_point, exit_point, timeout_ms, arch_info, armv4_5_run_algorithm_completion);
|
return armv4_5_run_algorithm_inner(target,
|
||||||
|
num_mem_params,
|
||||||
|
mem_params,
|
||||||
|
num_reg_params,
|
||||||
|
reg_params,
|
||||||
|
entry_point,
|
||||||
|
exit_point,
|
||||||
|
timeout_ms,
|
||||||
|
arch_info,
|
||||||
|
armv4_5_run_algorithm_completion);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1313,7 +1297,7 @@ int armv4_5_run_algorithm(struct target *target, int num_mem_params, struct mem_
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
int arm_checksum_memory(struct target *target,
|
int arm_checksum_memory(struct target *target,
|
||||||
uint32_t address, uint32_t count, uint32_t *checksum)
|
uint32_t address, uint32_t count, uint32_t *checksum)
|
||||||
{
|
{
|
||||||
struct working_area *crc_algorithm;
|
struct working_area *crc_algorithm;
|
||||||
struct arm_algorithm armv4_5_info;
|
struct arm_algorithm armv4_5_info;
|
||||||
|
@ -1414,7 +1398,7 @@ int arm_checksum_memory(struct target *target,
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
int arm_blank_check_memory(struct target *target,
|
int arm_blank_check_memory(struct target *target,
|
||||||
uint32_t address, uint32_t count, uint32_t *blank)
|
uint32_t address, uint32_t count, uint32_t *blank)
|
||||||
{
|
{
|
||||||
struct working_area *check_algorithm;
|
struct working_area *check_algorithm;
|
||||||
struct reg_param reg_params[3];
|
struct reg_param reg_params[3];
|
||||||
|
@ -1444,7 +1428,7 @@ int arm_blank_check_memory(struct target *target,
|
||||||
for (i = 0; i < ARRAY_SIZE(check_code); i++) {
|
for (i = 0; i < ARRAY_SIZE(check_code); i++) {
|
||||||
retval = target_write_u32(target,
|
retval = target_write_u32(target,
|
||||||
check_algorithm->address
|
check_algorithm->address
|
||||||
+ i * sizeof(uint32_t),
|
+ i * sizeof(uint32_t),
|
||||||
check_code[i]);
|
check_code[i]);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
@ -1506,18 +1490,18 @@ static int arm_full_context(struct target *target)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int arm_default_mrc(struct target *target, int cpnum,
|
static int arm_default_mrc(struct target *target, int cpnum,
|
||||||
uint32_t op1, uint32_t op2,
|
uint32_t op1, uint32_t op2,
|
||||||
uint32_t CRn, uint32_t CRm,
|
uint32_t CRn, uint32_t CRm,
|
||||||
uint32_t *value)
|
uint32_t *value)
|
||||||
{
|
{
|
||||||
LOG_ERROR("%s doesn't implement MRC", target_type_name(target));
|
LOG_ERROR("%s doesn't implement MRC", target_type_name(target));
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int arm_default_mcr(struct target *target, int cpnum,
|
static int arm_default_mcr(struct target *target, int cpnum,
|
||||||
uint32_t op1, uint32_t op2,
|
uint32_t op1, uint32_t op2,
|
||||||
uint32_t CRn, uint32_t CRm,
|
uint32_t CRn, uint32_t CRm,
|
||||||
uint32_t value)
|
uint32_t value)
|
||||||
{
|
{
|
||||||
LOG_ERROR("%s doesn't implement MCR", target_type_name(target));
|
LOG_ERROR("%s doesn't implement MCR", target_type_name(target));
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
* Free Software Foundation, Inc., *
|
* Free Software Foundation, Inc., *
|
||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#ifndef ARMV4_5_H
|
#ifndef ARMV4_5_H
|
||||||
#define ARMV4_5_H
|
#define ARMV4_5_H
|
||||||
|
|
||||||
|
@ -42,7 +43,7 @@ enum arm_mode armv4_5_number_to_mode(int number);
|
||||||
extern const int armv4_5_core_reg_map[8][17];
|
extern const int armv4_5_core_reg_map[8][17];
|
||||||
|
|
||||||
#define ARMV4_5_CORE_REG_MODE(cache, mode, num) \
|
#define ARMV4_5_CORE_REG_MODE(cache, mode, num) \
|
||||||
cache->reg_list[armv4_5_core_reg_map[arm_mode_to_number(mode)][num]]
|
(cache->reg_list[armv4_5_core_reg_map[arm_mode_to_number(mode)][num]])
|
||||||
|
|
||||||
/* offset into armv4_5 core register cache -- OBSOLETE, DO NOT USE! */
|
/* offset into armv4_5 core register cache -- OBSOLETE, DO NOT USE! */
|
||||||
enum { ARMV4_5_CPSR = 31, };
|
enum { ARMV4_5_CPSR = 31, };
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
* Free Software Foundation, Inc., *
|
* Free Software Foundation, Inc., *
|
||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -37,16 +38,13 @@ int armv4_5_identify_cache(uint32_t cache_type_reg, struct armv4_5_cache_common
|
||||||
len = (cache_type_reg & 0x3000) >> 12;
|
len = (cache_type_reg & 0x3000) >> 12;
|
||||||
multiplier = 2 + M;
|
multiplier = 2 + M;
|
||||||
|
|
||||||
if ((assoc != 0) || (M != 1)) /* assoc 0 and M 1 means cache absent */
|
if ((assoc != 0) || (M != 1)) /* assoc 0 and M 1 means cache absent */ {
|
||||||
{
|
|
||||||
/* cache is present */
|
/* cache is present */
|
||||||
cache->d_u_size.linelen = 1 << (len + 3);
|
cache->d_u_size.linelen = 1 << (len + 3);
|
||||||
cache->d_u_size.associativity = multiplier << (assoc - 1);
|
cache->d_u_size.associativity = multiplier << (assoc - 1);
|
||||||
cache->d_u_size.nsets = 1 << (size + 6 - assoc - len);
|
cache->d_u_size.nsets = 1 << (size + 6 - assoc - len);
|
||||||
cache->d_u_size.cachesize = multiplier << (size + 8);
|
cache->d_u_size.cachesize = multiplier << (size + 8);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
/* cache is absent */
|
/* cache is absent */
|
||||||
cache->d_u_size.linelen = -1;
|
cache->d_u_size.linelen = -1;
|
||||||
cache->d_u_size.associativity = -1;
|
cache->d_u_size.associativity = -1;
|
||||||
|
@ -54,43 +52,35 @@ int armv4_5_identify_cache(uint32_t cache_type_reg, struct armv4_5_cache_common
|
||||||
cache->d_u_size.cachesize = -1;
|
cache->d_u_size.cachesize = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cache->separate)
|
if (cache->separate) {
|
||||||
{
|
|
||||||
size = (cache_type_reg & 0x1c0) >> 6;
|
size = (cache_type_reg & 0x1c0) >> 6;
|
||||||
assoc = (cache_type_reg & 0x38) >> 3;
|
assoc = (cache_type_reg & 0x38) >> 3;
|
||||||
M = (cache_type_reg & 0x4) >> 2;
|
M = (cache_type_reg & 0x4) >> 2;
|
||||||
len = (cache_type_reg & 0x3);
|
len = (cache_type_reg & 0x3);
|
||||||
multiplier = 2 + M;
|
multiplier = 2 + M;
|
||||||
|
|
||||||
if ((assoc != 0) || (M != 1)) /* assoc 0 and M 1 means cache absent */
|
if ((assoc != 0) || (M != 1)) /* assoc 0 and M 1 means cache absent */ {
|
||||||
{
|
|
||||||
/* cache is present */
|
/* cache is present */
|
||||||
cache->i_size.linelen = 1 << (len + 3);
|
cache->i_size.linelen = 1 << (len + 3);
|
||||||
cache->i_size.associativity = multiplier << (assoc - 1);
|
cache->i_size.associativity = multiplier << (assoc - 1);
|
||||||
cache->i_size.nsets = 1 << (size + 6 - assoc - len);
|
cache->i_size.nsets = 1 << (size + 6 - assoc - len);
|
||||||
cache->i_size.cachesize = multiplier << (size + 8);
|
cache->i_size.cachesize = multiplier << (size + 8);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
/* cache is absent */
|
/* cache is absent */
|
||||||
cache->i_size.linelen = -1;
|
cache->i_size.linelen = -1;
|
||||||
cache->i_size.associativity = -1;
|
cache->i_size.associativity = -1;
|
||||||
cache->i_size.nsets = -1;
|
cache->i_size.nsets = -1;
|
||||||
cache->i_size.cachesize = -1;
|
cache->i_size.cachesize = -1;
|
||||||
}
|
}
|
||||||
}
|
} else
|
||||||
else
|
|
||||||
{
|
|
||||||
cache->i_size = cache->d_u_size;
|
cache->i_size = cache->d_u_size;
|
||||||
}
|
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int armv4_5_handle_cache_info_command(struct command_context *cmd_ctx, struct armv4_5_cache_common *armv4_5_cache)
|
int armv4_5_handle_cache_info_command(struct command_context *cmd_ctx, struct armv4_5_cache_common *armv4_5_cache)
|
||||||
{
|
{
|
||||||
if (armv4_5_cache->ctype == -1)
|
if (armv4_5_cache->ctype == -1) {
|
||||||
{
|
|
||||||
command_print(cmd_ctx, "cache not yet identified");
|
command_print(cmd_ctx, "cache not yet identified");
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
* Free Software Foundation, Inc., *
|
* Free Software Foundation, Inc., *
|
||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#ifndef ARMV4_5_CACHE_H
|
#ifndef ARMV4_5_CACHE_H
|
||||||
#define ARMV4_5_CACHE_H
|
#define ARMV4_5_CACHE_H
|
||||||
|
|
||||||
|
@ -24,16 +25,14 @@
|
||||||
|
|
||||||
struct command_context;
|
struct command_context;
|
||||||
|
|
||||||
struct armv4_5_cachesize
|
struct armv4_5_cachesize {
|
||||||
{
|
|
||||||
int linelen;
|
int linelen;
|
||||||
int associativity;
|
int associativity;
|
||||||
int nsets;
|
int nsets;
|
||||||
int cachesize;
|
int cachesize;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct armv4_5_cache_common
|
struct armv4_5_cache_common {
|
||||||
{
|
|
||||||
int ctype; /* specify supported cache operations */
|
int ctype; /* specify supported cache operations */
|
||||||
int separate; /* separate caches or unified cache */
|
int separate; /* separate caches or unified cache */
|
||||||
struct armv4_5_cachesize d_u_size; /* data cache */
|
struct armv4_5_cachesize d_u_size; /* data cache */
|
||||||
|
@ -50,8 +49,7 @@ int armv4_5_cache_state(uint32_t cp15_control_reg,
|
||||||
int armv4_5_handle_cache_info_command(struct command_context *cmd_ctx,
|
int armv4_5_handle_cache_info_command(struct command_context *cmd_ctx,
|
||||||
struct armv4_5_cache_common *armv4_5_cache);
|
struct armv4_5_cache_common *armv4_5_cache);
|
||||||
|
|
||||||
enum
|
enum {
|
||||||
{
|
|
||||||
ARMV4_5_D_U_CACHE_ENABLED = 0x4,
|
ARMV4_5_D_U_CACHE_ENABLED = 0x4,
|
||||||
ARMV4_5_I_CACHE_ENABLED = 0x1000,
|
ARMV4_5_I_CACHE_ENABLED = 0x1000,
|
||||||
ARMV4_5_WRITE_BUFFER_ENABLED = 0x8,
|
ARMV4_5_WRITE_BUFFER_ENABLED = 0x8,
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
* Free Software Foundation, Inc., *
|
* Free Software Foundation, Inc., *
|
||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -25,8 +26,8 @@
|
||||||
#include "target.h"
|
#include "target.h"
|
||||||
#include "armv4_5_mmu.h"
|
#include "armv4_5_mmu.h"
|
||||||
|
|
||||||
|
int armv4_5_mmu_translate_va(struct target *target,
|
||||||
int armv4_5_mmu_translate_va(struct target *target, struct armv4_5_mmu_common *armv4_5_mmu, uint32_t va, uint32_t *cb, uint32_t *val)
|
struct armv4_5_mmu_common *armv4_5_mmu, uint32_t va, uint32_t *cb, uint32_t *val)
|
||||||
{
|
{
|
||||||
uint32_t first_lvl_descriptor = 0x0;
|
uint32_t first_lvl_descriptor = 0x0;
|
||||||
uint32_t second_lvl_descriptor = 0x0;
|
uint32_t second_lvl_descriptor = 0x0;
|
||||||
|
@ -34,62 +35,55 @@ int armv4_5_mmu_translate_va(struct target *target, struct armv4_5_mmu_common *a
|
||||||
int retval;
|
int retval;
|
||||||
retval = armv4_5_mmu->get_ttb(target, &ttb);
|
retval = armv4_5_mmu->get_ttb(target, &ttb);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
retval = armv4_5_mmu_read_physical(target, armv4_5_mmu,
|
retval = armv4_5_mmu_read_physical(target, armv4_5_mmu,
|
||||||
(ttb & 0xffffc000) | ((va & 0xfff00000) >> 18),
|
(ttb & 0xffffc000) | ((va & 0xfff00000) >> 18),
|
||||||
4, 1, (uint8_t*)&first_lvl_descriptor);
|
4, 1, (uint8_t *)&first_lvl_descriptor);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
first_lvl_descriptor = target_buffer_get_u32(target, (uint8_t*)&first_lvl_descriptor);
|
first_lvl_descriptor = target_buffer_get_u32(target, (uint8_t *)&first_lvl_descriptor);
|
||||||
|
|
||||||
LOG_DEBUG("1st lvl desc: %8.8" PRIx32 "", first_lvl_descriptor);
|
LOG_DEBUG("1st lvl desc: %8.8" PRIx32 "", first_lvl_descriptor);
|
||||||
|
|
||||||
if ((first_lvl_descriptor & 0x3) == 0)
|
if ((first_lvl_descriptor & 0x3) == 0) {
|
||||||
{
|
|
||||||
LOG_ERROR("Address translation failure");
|
LOG_ERROR("Address translation failure");
|
||||||
return ERROR_TARGET_TRANSLATION_FAULT;
|
return ERROR_TARGET_TRANSLATION_FAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!armv4_5_mmu->has_tiny_pages && ((first_lvl_descriptor & 0x3) == 3))
|
if (!armv4_5_mmu->has_tiny_pages && ((first_lvl_descriptor & 0x3) == 3)) {
|
||||||
{
|
|
||||||
LOG_ERROR("Address translation failure");
|
LOG_ERROR("Address translation failure");
|
||||||
return ERROR_TARGET_TRANSLATION_FAULT;
|
return ERROR_TARGET_TRANSLATION_FAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((first_lvl_descriptor & 0x3) == 2)
|
if ((first_lvl_descriptor & 0x3) == 2) {
|
||||||
{
|
|
||||||
/* section descriptor */
|
/* section descriptor */
|
||||||
*cb = (first_lvl_descriptor & 0xc) >> 2;
|
*cb = (first_lvl_descriptor & 0xc) >> 2;
|
||||||
*val = (first_lvl_descriptor & 0xfff00000) | (va & 0x000fffff);
|
*val = (first_lvl_descriptor & 0xfff00000) | (va & 0x000fffff);
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((first_lvl_descriptor & 0x3) == 1)
|
if ((first_lvl_descriptor & 0x3) == 1) {
|
||||||
{
|
|
||||||
/* coarse page table */
|
/* coarse page table */
|
||||||
retval = armv4_5_mmu_read_physical(target, armv4_5_mmu,
|
retval = armv4_5_mmu_read_physical(target, armv4_5_mmu,
|
||||||
(first_lvl_descriptor & 0xfffffc00) | ((va & 0x000ff000) >> 10),
|
(first_lvl_descriptor & 0xfffffc00) | ((va & 0x000ff000) >> 10),
|
||||||
4, 1, (uint8_t*)&second_lvl_descriptor);
|
4, 1, (uint8_t *)&second_lvl_descriptor);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
} else if ((first_lvl_descriptor & 0x3) == 3) {
|
||||||
else if ((first_lvl_descriptor & 0x3) == 3)
|
|
||||||
{
|
|
||||||
/* fine page table */
|
/* fine page table */
|
||||||
retval = armv4_5_mmu_read_physical(target, armv4_5_mmu,
|
retval = armv4_5_mmu_read_physical(target, armv4_5_mmu,
|
||||||
(first_lvl_descriptor & 0xfffff000) | ((va & 0x000ffc00) >> 8),
|
(first_lvl_descriptor & 0xfffff000) | ((va & 0x000ffc00) >> 8),
|
||||||
4, 1, (uint8_t*)&second_lvl_descriptor);
|
4, 1, (uint8_t *)&second_lvl_descriptor);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
second_lvl_descriptor = target_buffer_get_u32(target, (uint8_t*)&second_lvl_descriptor);
|
second_lvl_descriptor = target_buffer_get_u32(target, (uint8_t *)&second_lvl_descriptor);
|
||||||
|
|
||||||
LOG_DEBUG("2nd lvl desc: %8.8" PRIx32 "", second_lvl_descriptor);
|
LOG_DEBUG("2nd lvl desc: %8.8" PRIx32 "", second_lvl_descriptor);
|
||||||
|
|
||||||
if ((second_lvl_descriptor & 0x3) == 0)
|
if ((second_lvl_descriptor & 0x3) == 0) {
|
||||||
{
|
|
||||||
LOG_ERROR("Address translation failure");
|
LOG_ERROR("Address translation failure");
|
||||||
return ERROR_TARGET_TRANSLATION_FAULT;
|
return ERROR_TARGET_TRANSLATION_FAULT;
|
||||||
}
|
}
|
||||||
|
@ -97,22 +91,19 @@ int armv4_5_mmu_translate_va(struct target *target, struct armv4_5_mmu_common *a
|
||||||
/* cacheable/bufferable is always specified in bits 3-2 */
|
/* cacheable/bufferable is always specified in bits 3-2 */
|
||||||
*cb = (second_lvl_descriptor & 0xc) >> 2;
|
*cb = (second_lvl_descriptor & 0xc) >> 2;
|
||||||
|
|
||||||
if ((second_lvl_descriptor & 0x3) == 1)
|
if ((second_lvl_descriptor & 0x3) == 1) {
|
||||||
{
|
|
||||||
/* large page descriptor */
|
/* large page descriptor */
|
||||||
*val = (second_lvl_descriptor & 0xffff0000) | (va & 0x0000ffff);
|
*val = (second_lvl_descriptor & 0xffff0000) | (va & 0x0000ffff);
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((second_lvl_descriptor & 0x3) == 2)
|
if ((second_lvl_descriptor & 0x3) == 2) {
|
||||||
{
|
|
||||||
/* small page descriptor */
|
/* small page descriptor */
|
||||||
*val = (second_lvl_descriptor & 0xfffff000) | (va & 0x00000fff);
|
*val = (second_lvl_descriptor & 0xfffff000) | (va & 0x00000fff);
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((second_lvl_descriptor & 0x3) == 3)
|
if ((second_lvl_descriptor & 0x3) == 3) {
|
||||||
{
|
|
||||||
/* tiny page descriptor */
|
/* tiny page descriptor */
|
||||||
*val = (second_lvl_descriptor & 0xfffffc00) | (va & 0x000003ff);
|
*val = (second_lvl_descriptor & 0xfffffc00) | (va & 0x000003ff);
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
|
@ -123,7 +114,9 @@ int armv4_5_mmu_translate_va(struct target *target, struct armv4_5_mmu_common *a
|
||||||
return ERROR_TARGET_TRANSLATION_FAULT;
|
return ERROR_TARGET_TRANSLATION_FAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
int armv4_5_mmu_read_physical(struct target *target, struct armv4_5_mmu_common *armv4_5_mmu, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer)
|
int armv4_5_mmu_read_physical(struct target *target,
|
||||||
|
struct armv4_5_mmu_common *armv4_5_mmu, uint32_t address,
|
||||||
|
uint32_t size, uint32_t count, uint8_t *buffer)
|
||||||
{
|
{
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
|
@ -132,24 +125,26 @@ int armv4_5_mmu_read_physical(struct target *target, struct armv4_5_mmu_common *
|
||||||
|
|
||||||
/* disable MMU and data (or unified) cache */
|
/* disable MMU and data (or unified) cache */
|
||||||
retval = armv4_5_mmu->disable_mmu_caches(target, 1, 1, 0);
|
retval = armv4_5_mmu->disable_mmu_caches(target, 1, 1, 0);
|
||||||
if (retval !=ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
retval = armv4_5_mmu->read_memory(target, address, size, count, buffer);
|
retval = armv4_5_mmu->read_memory(target, address, size, count, buffer);
|
||||||
if (retval !=ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
/* reenable MMU / cache */
|
/* reenable MMU / cache */
|
||||||
retval = armv4_5_mmu->enable_mmu_caches(target, armv4_5_mmu->mmu_enabled,
|
retval = armv4_5_mmu->enable_mmu_caches(target, armv4_5_mmu->mmu_enabled,
|
||||||
armv4_5_mmu->armv4_5_cache.d_u_cache_enabled,
|
armv4_5_mmu->armv4_5_cache.d_u_cache_enabled,
|
||||||
armv4_5_mmu->armv4_5_cache.i_cache_enabled);
|
armv4_5_mmu->armv4_5_cache.i_cache_enabled);
|
||||||
if (retval !=ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
int armv4_5_mmu_write_physical(struct target *target, struct armv4_5_mmu_common *armv4_5_mmu, uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer)
|
int armv4_5_mmu_write_physical(struct target *target,
|
||||||
|
struct armv4_5_mmu_common *armv4_5_mmu, uint32_t address,
|
||||||
|
uint32_t size, uint32_t count, const uint8_t *buffer)
|
||||||
{
|
{
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
|
@ -158,18 +153,18 @@ int armv4_5_mmu_write_physical(struct target *target, struct armv4_5_mmu_common
|
||||||
|
|
||||||
/* disable MMU and data (or unified) cache */
|
/* disable MMU and data (or unified) cache */
|
||||||
retval = armv4_5_mmu->disable_mmu_caches(target, 1, 1, 0);
|
retval = armv4_5_mmu->disable_mmu_caches(target, 1, 1, 0);
|
||||||
if (retval !=ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
retval = armv4_5_mmu->write_memory(target, address, size, count, buffer);
|
retval = armv4_5_mmu->write_memory(target, address, size, count, buffer);
|
||||||
if (retval !=ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
/* reenable MMU / cache */
|
/* reenable MMU / cache */
|
||||||
retval = armv4_5_mmu->enable_mmu_caches(target, armv4_5_mmu->mmu_enabled,
|
retval = armv4_5_mmu->enable_mmu_caches(target, armv4_5_mmu->mmu_enabled,
|
||||||
armv4_5_mmu->armv4_5_cache.d_u_cache_enabled,
|
armv4_5_mmu->armv4_5_cache.d_u_cache_enabled,
|
||||||
armv4_5_mmu->armv4_5_cache.i_cache_enabled);
|
armv4_5_mmu->armv4_5_cache.i_cache_enabled);
|
||||||
if (retval !=ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
* Free Software Foundation, Inc., *
|
* Free Software Foundation, Inc., *
|
||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#ifndef ARMV4_5_MMU_H
|
#ifndef ARMV4_5_MMU_H
|
||||||
#define ARMV4_5_MMU_H
|
#define ARMV4_5_MMU_H
|
||||||
|
|
||||||
|
@ -24,8 +25,7 @@
|
||||||
|
|
||||||
struct target;
|
struct target;
|
||||||
|
|
||||||
struct armv4_5_mmu_common
|
struct armv4_5_mmu_common {
|
||||||
{
|
|
||||||
int (*get_ttb)(struct target *target, uint32_t *result);
|
int (*get_ttb)(struct target *target, uint32_t *result);
|
||||||
int (*read_memory)(struct target *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer);
|
int (*read_memory)(struct target *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer);
|
||||||
int (*write_memory)(struct target *target, uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer);
|
int (*write_memory)(struct target *target, uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer);
|
||||||
|
@ -48,8 +48,7 @@ int armv4_5_mmu_write_physical(struct target *target,
|
||||||
struct armv4_5_mmu_common *armv4_5_mmu,
|
struct armv4_5_mmu_common *armv4_5_mmu,
|
||||||
uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer);
|
uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer);
|
||||||
|
|
||||||
enum
|
enum {
|
||||||
{
|
|
||||||
ARMV4_5_MMU_ENABLED = 0x1,
|
ARMV4_5_MMU_ENABLED = 0x1,
|
||||||
ARMV4_5_ALIGNMENT_CHECK = 0x2,
|
ARMV4_5_ALIGNMENT_CHECK = 0x2,
|
||||||
ARMV4_5_MMU_S_BIT = 0x100,
|
ARMV4_5_MMU_S_BIT = 0x100,
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
* Free Software Foundation, Inc., *
|
* Free Software Foundation, Inc., *
|
||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -79,9 +80,9 @@ static void armv7a_show_fault_registers(struct target *target)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
LOG_USER("Data fault registers DFSR: %8.8" PRIx32
|
LOG_USER("Data fault registers DFSR: %8.8" PRIx32
|
||||||
", DFAR: %8.8" PRIx32, dfsr, dfar);
|
", DFAR: %8.8" PRIx32, dfsr, dfar);
|
||||||
LOG_USER("Instruction fault registers IFSR: %8.8" PRIx32
|
LOG_USER("Instruction fault registers IFSR: %8.8" PRIx32
|
||||||
", IFAR: %8.8" PRIx32, ifsr, ifar);
|
", IFAR: %8.8" PRIx32, ifsr, ifar);
|
||||||
|
|
||||||
done:
|
done:
|
||||||
/* (void) */ dpm->finish(dpm);
|
/* (void) */ dpm->finish(dpm);
|
||||||
|
@ -93,29 +94,28 @@ static int armv7a_read_ttbcr(struct target *target)
|
||||||
struct arm_dpm *dpm = armv7a->arm.dpm;
|
struct arm_dpm *dpm = armv7a->arm.dpm;
|
||||||
uint32_t ttbcr;
|
uint32_t ttbcr;
|
||||||
int retval = dpm->prepare(dpm);
|
int retval = dpm->prepare(dpm);
|
||||||
if (retval!=ERROR_OK) goto done;
|
if (retval != ERROR_OK)
|
||||||
|
goto done;
|
||||||
/* MRC p15,0,<Rt>,c2,c0,2 ; Read CP15 Translation Table Base Control Register*/
|
/* MRC p15,0,<Rt>,c2,c0,2 ; Read CP15 Translation Table Base Control Register*/
|
||||||
retval = dpm->instr_read_data_r0(dpm,
|
retval = dpm->instr_read_data_r0(dpm,
|
||||||
ARMV4_5_MRC(15, 0, 0, 2, 0, 2),
|
ARMV4_5_MRC(15, 0, 0, 2, 0, 2),
|
||||||
&ttbcr);
|
&ttbcr);
|
||||||
if (retval!=ERROR_OK) goto done;
|
if (retval != ERROR_OK)
|
||||||
armv7a->armv7a_mmu.ttbr1_used = ((ttbcr & 0x7)!=0)? 1: 0;
|
goto done;
|
||||||
armv7a->armv7a_mmu.ttbr0_mask = 7 << (32 -((ttbcr & 0x7)));
|
armv7a->armv7a_mmu.ttbr1_used = ((ttbcr & 0x7) != 0) ? 1 : 0;
|
||||||
|
armv7a->armv7a_mmu.ttbr0_mask = 7 << (32 - ((ttbcr & 0x7)));
|
||||||
#if 0
|
#if 0
|
||||||
LOG_INFO("ttb1 %s ,ttb0_mask %x",
|
LOG_INFO("ttb1 %s ,ttb0_mask %x",
|
||||||
armv7a->armv7a_mmu.ttbr1_used ? "used":"not used",
|
armv7a->armv7a_mmu.ttbr1_used ? "used" : "not used",
|
||||||
armv7a->armv7a_mmu.ttbr0_mask);
|
armv7a->armv7a_mmu.ttbr0_mask);
|
||||||
#endif
|
#endif
|
||||||
if (armv7a->armv7a_mmu.ttbr1_used == 1)
|
if (armv7a->armv7a_mmu.ttbr1_used == 1) {
|
||||||
{
|
|
||||||
LOG_INFO("SVC access above %x",
|
LOG_INFO("SVC access above %x",
|
||||||
(0xffffffff & armv7a->armv7a_mmu.ttbr0_mask));
|
(0xffffffff & armv7a->armv7a_mmu.ttbr0_mask));
|
||||||
armv7a->armv7a_mmu.os_border = 0xffffffff & armv7a->armv7a_mmu.ttbr0_mask;
|
armv7a->armv7a_mmu.os_border = 0xffffffff & armv7a->armv7a_mmu.ttbr0_mask;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
/* fix me , default is hard coded LINUX border */
|
/* fix me , default is hard coded LINUX border */
|
||||||
armv7a->armv7a_mmu.os_border = 0xc0000000;
|
armv7a->armv7a_mmu.os_border = 0xc0000000;
|
||||||
}
|
}
|
||||||
done:
|
done:
|
||||||
dpm->finish(dpm);
|
dpm->finish(dpm);
|
||||||
|
@ -131,11 +131,11 @@ int armv7a_mmu_translate_va(struct target *target, uint32_t va, uint32_t *val)
|
||||||
int retval;
|
int retval;
|
||||||
struct armv7a_common *armv7a = target_to_armv7a(target);
|
struct armv7a_common *armv7a = target_to_armv7a(target);
|
||||||
struct arm_dpm *dpm = armv7a->arm.dpm;
|
struct arm_dpm *dpm = armv7a->arm.dpm;
|
||||||
uint32_t ttb = 0; /* default ttb0 */
|
uint32_t ttb = 0; /* default ttb0 */
|
||||||
if (armv7a->armv7a_mmu.ttbr1_used == -1) armv7a_read_ttbcr(target);
|
if (armv7a->armv7a_mmu.ttbr1_used == -1)
|
||||||
|
armv7a_read_ttbcr(target);
|
||||||
if ((armv7a->armv7a_mmu.ttbr1_used) &&
|
if ((armv7a->armv7a_mmu.ttbr1_used) &&
|
||||||
(va > (0xffffffff & armv7a->armv7a_mmu.ttbr0_mask)))
|
(va > (0xffffffff & armv7a->armv7a_mmu.ttbr0_mask))) {
|
||||||
{
|
|
||||||
/* select ttb 1 */
|
/* select ttb 1 */
|
||||||
ttb = 1;
|
ttb = 1;
|
||||||
}
|
}
|
||||||
|
@ -151,74 +151,65 @@ int armv7a_mmu_translate_va(struct target *target, uint32_t va, uint32_t *val)
|
||||||
return retval;
|
return retval;
|
||||||
retval = armv7a->armv7a_mmu.read_physical_memory(target,
|
retval = armv7a->armv7a_mmu.read_physical_memory(target,
|
||||||
(ttb & 0xffffc000) | ((va & 0xfff00000) >> 18),
|
(ttb & 0xffffc000) | ((va & 0xfff00000) >> 18),
|
||||||
4, 1, (uint8_t*)&first_lvl_descriptor);
|
4, 1, (uint8_t *)&first_lvl_descriptor);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
first_lvl_descriptor = target_buffer_get_u32(target, (uint8_t*)
|
first_lvl_descriptor = target_buffer_get_u32(target, (uint8_t *)
|
||||||
&first_lvl_descriptor);
|
&first_lvl_descriptor);
|
||||||
/* reuse armv4_5 piece of code, specific armv7a changes may come later */
|
/* reuse armv4_5 piece of code, specific armv7a changes may come later */
|
||||||
LOG_DEBUG("1st lvl desc: %8.8" PRIx32 "", first_lvl_descriptor);
|
LOG_DEBUG("1st lvl desc: %8.8" PRIx32 "", first_lvl_descriptor);
|
||||||
|
|
||||||
if ((first_lvl_descriptor & 0x3) == 0)
|
if ((first_lvl_descriptor & 0x3) == 0) {
|
||||||
{
|
|
||||||
LOG_ERROR("Address translation failure");
|
LOG_ERROR("Address translation failure");
|
||||||
return ERROR_TARGET_TRANSLATION_FAULT;
|
return ERROR_TARGET_TRANSLATION_FAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if ((first_lvl_descriptor & 0x3) == 2)
|
if ((first_lvl_descriptor & 0x3) == 2) {
|
||||||
{
|
|
||||||
/* section descriptor */
|
/* section descriptor */
|
||||||
*val = (first_lvl_descriptor & 0xfff00000) | (va & 0x000fffff);
|
*val = (first_lvl_descriptor & 0xfff00000) | (va & 0x000fffff);
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((first_lvl_descriptor & 0x3) == 1)
|
if ((first_lvl_descriptor & 0x3) == 1) {
|
||||||
{
|
|
||||||
/* coarse page table */
|
/* coarse page table */
|
||||||
retval = armv7a->armv7a_mmu.read_physical_memory(target,
|
retval = armv7a->armv7a_mmu.read_physical_memory(target,
|
||||||
(first_lvl_descriptor & 0xfffffc00) | ((va & 0x000ff000) >> 10),
|
(first_lvl_descriptor & 0xfffffc00) | ((va & 0x000ff000) >> 10),
|
||||||
4, 1, (uint8_t*)&second_lvl_descriptor);
|
4, 1, (uint8_t *)&second_lvl_descriptor);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
} else if ((first_lvl_descriptor & 0x3) == 3) {
|
||||||
else if ((first_lvl_descriptor & 0x3) == 3)
|
|
||||||
{
|
|
||||||
/* fine page table */
|
/* fine page table */
|
||||||
retval = armv7a->armv7a_mmu.read_physical_memory(target,
|
retval = armv7a->armv7a_mmu.read_physical_memory(target,
|
||||||
(first_lvl_descriptor & 0xfffff000) | ((va & 0x000ffc00) >> 8),
|
(first_lvl_descriptor & 0xfffff000) | ((va & 0x000ffc00) >> 8),
|
||||||
4, 1, (uint8_t*)&second_lvl_descriptor);
|
4, 1, (uint8_t *)&second_lvl_descriptor);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
second_lvl_descriptor = target_buffer_get_u32(target, (uint8_t*)
|
second_lvl_descriptor = target_buffer_get_u32(target, (uint8_t *)
|
||||||
&second_lvl_descriptor);
|
&second_lvl_descriptor);
|
||||||
|
|
||||||
LOG_DEBUG("2nd lvl desc: %8.8" PRIx32 "", second_lvl_descriptor);
|
LOG_DEBUG("2nd lvl desc: %8.8" PRIx32 "", second_lvl_descriptor);
|
||||||
|
|
||||||
if ((second_lvl_descriptor & 0x3) == 0)
|
if ((second_lvl_descriptor & 0x3) == 0) {
|
||||||
{
|
|
||||||
LOG_ERROR("Address translation failure");
|
LOG_ERROR("Address translation failure");
|
||||||
return ERROR_TARGET_TRANSLATION_FAULT;
|
return ERROR_TARGET_TRANSLATION_FAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((second_lvl_descriptor & 0x3) == 1)
|
if ((second_lvl_descriptor & 0x3) == 1) {
|
||||||
{
|
|
||||||
/* large page descriptor */
|
/* large page descriptor */
|
||||||
*val = (second_lvl_descriptor & 0xffff0000) | (va & 0x0000ffff);
|
*val = (second_lvl_descriptor & 0xffff0000) | (va & 0x0000ffff);
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((second_lvl_descriptor & 0x3) == 2)
|
if ((second_lvl_descriptor & 0x3) == 2) {
|
||||||
{
|
|
||||||
/* small page descriptor */
|
/* small page descriptor */
|
||||||
*val = (second_lvl_descriptor & 0xfffff000) | (va & 0x00000fff);
|
*val = (second_lvl_descriptor & 0xfffff000) | (va & 0x00000fff);
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((second_lvl_descriptor & 0x3) == 3)
|
if ((second_lvl_descriptor & 0x3) == 3) {
|
||||||
{
|
|
||||||
*val = (second_lvl_descriptor & 0xfffffc00) | (va & 0x000003ff);
|
*val = (second_lvl_descriptor & 0xfffffc00) | (va & 0x000003ff);
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
@ -231,69 +222,80 @@ done:
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* V7 method VA TO PA */
|
/* V7 method VA TO PA */
|
||||||
int armv7a_mmu_translate_va_pa(struct target *target, uint32_t va,
|
int armv7a_mmu_translate_va_pa(struct target *target, uint32_t va,
|
||||||
uint32_t *val, int meminfo)
|
uint32_t *val, int meminfo)
|
||||||
{
|
{
|
||||||
int retval = ERROR_FAIL;
|
int retval = ERROR_FAIL;
|
||||||
struct armv7a_common *armv7a = target_to_armv7a(target);
|
struct armv7a_common *armv7a = target_to_armv7a(target);
|
||||||
struct arm_dpm *dpm = armv7a->arm.dpm;
|
struct arm_dpm *dpm = armv7a->arm.dpm;
|
||||||
uint32_t virt = va & ~0xfff;
|
uint32_t virt = va & ~0xfff;
|
||||||
uint32_t NOS,NS,INNER,OUTER;
|
uint32_t NOS, NS, INNER, OUTER;
|
||||||
*val = 0xdeadbeef;
|
*val = 0xdeadbeef;
|
||||||
retval = dpm->prepare(dpm);
|
retval = dpm->prepare(dpm);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
goto done;
|
goto done;
|
||||||
/* mmu must be enable in order to get a correct translation */
|
/* mmu must be enable in order to get a correct translation
|
||||||
/* use VA to PA CP15 register for conversion */
|
* use VA to PA CP15 register for conversion */
|
||||||
retval = dpm->instr_write_data_r0(dpm,
|
retval = dpm->instr_write_data_r0(dpm,
|
||||||
ARMV4_5_MCR(15, 0, 0, 7, 8, 0),
|
ARMV4_5_MCR(15, 0, 0, 7, 8, 0),
|
||||||
virt);
|
virt);
|
||||||
if (retval!=ERROR_OK) goto done;
|
if (retval != ERROR_OK)
|
||||||
|
goto done;
|
||||||
retval = dpm->instr_read_data_r0(dpm,
|
retval = dpm->instr_read_data_r0(dpm,
|
||||||
ARMV4_5_MRC(15, 0, 0, 7, 4, 0),
|
ARMV4_5_MRC(15, 0, 0, 7, 4, 0),
|
||||||
val);
|
val);
|
||||||
/* decode memory attribute */
|
/* decode memory attribute */
|
||||||
NOS = (*val >> 10) & 1; /* Not Outer shareable */
|
NOS = (*val >> 10) & 1; /* Not Outer shareable */
|
||||||
NS = (*val >> 9) & 1; /* Non secure */
|
NS = (*val >> 9) & 1; /* Non secure */
|
||||||
INNER = (*val >> 4) & 0x7;
|
INNER = (*val >> 4) & 0x7;
|
||||||
OUTER = (*val >> 2) & 0x3;
|
OUTER = (*val >> 2) & 0x3;
|
||||||
|
|
||||||
if (retval!=ERROR_OK) goto done;
|
if (retval != ERROR_OK)
|
||||||
|
goto done;
|
||||||
*val = (*val & ~0xfff) + (va & 0xfff);
|
*val = (*val & ~0xfff) + (va & 0xfff);
|
||||||
if (*val == va)
|
if (*val == va)
|
||||||
LOG_WARNING("virt = phys : MMU disable !!");
|
LOG_WARNING("virt = phys : MMU disable !!");
|
||||||
if (meminfo)
|
if (meminfo) {
|
||||||
{
|
|
||||||
LOG_INFO("%x : %x %s outer shareable %s secured",
|
LOG_INFO("%x : %x %s outer shareable %s secured",
|
||||||
va, *val,
|
va, *val,
|
||||||
NOS == 1 ? "not" : " ",
|
NOS == 1 ? "not" : " ",
|
||||||
NS == 1 ? "not" :"");
|
NS == 1 ? "not" : "");
|
||||||
switch (OUTER) {
|
switch (OUTER) {
|
||||||
case 0 : LOG_INFO("outer: Non-Cacheable");
|
case 0:
|
||||||
break;
|
LOG_INFO("outer: Non-Cacheable");
|
||||||
case 1 : LOG_INFO("outer: Write-Back, Write-Allocate");
|
break;
|
||||||
break;
|
case 1:
|
||||||
case 2 : LOG_INFO("outer: Write-Through, No Write-Allocate");
|
LOG_INFO("outer: Write-Back, Write-Allocate");
|
||||||
break;
|
break;
|
||||||
case 3 : LOG_INFO("outer: Write-Back, no Write-Allocate");
|
case 2:
|
||||||
break;
|
LOG_INFO("outer: Write-Through, No Write-Allocate");
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
LOG_INFO("outer: Write-Back, no Write-Allocate");
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
switch (INNER) {
|
switch (INNER) {
|
||||||
case 0 : LOG_INFO("inner: Non-Cacheable");
|
case 0:
|
||||||
break;
|
LOG_INFO("inner: Non-Cacheable");
|
||||||
case 1 : LOG_INFO("inner: Strongly-ordered");
|
break;
|
||||||
break;
|
case 1:
|
||||||
case 3 : LOG_INFO("inner: Device");
|
LOG_INFO("inner: Strongly-ordered");
|
||||||
break;
|
break;
|
||||||
case 5 : LOG_INFO("inner: Write-Back, Write-Allocate");
|
case 3:
|
||||||
break;
|
LOG_INFO("inner: Device");
|
||||||
case 6 : LOG_INFO("inner: Write-Through");
|
break;
|
||||||
break;
|
case 5:
|
||||||
case 7 : LOG_INFO("inner: Write-Back, no Write-Allocate");
|
LOG_INFO("inner: Write-Back, Write-Allocate");
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
LOG_INFO("inner: Write-Through");
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
LOG_INFO("inner: Write-Back, no Write-Allocate");
|
||||||
|
|
||||||
default: LOG_INFO("inner: %x ???",INNER);
|
default:
|
||||||
|
LOG_INFO("inner: %x ???", INNER);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -304,27 +306,26 @@ done:
|
||||||
}
|
}
|
||||||
|
|
||||||
static int armv7a_handle_inner_cache_info_command(struct command_context *cmd_ctx,
|
static int armv7a_handle_inner_cache_info_command(struct command_context *cmd_ctx,
|
||||||
struct armv7a_cache_common *armv7a_cache)
|
struct armv7a_cache_common *armv7a_cache)
|
||||||
{
|
{
|
||||||
if (armv7a_cache->ctype == -1)
|
if (armv7a_cache->ctype == -1) {
|
||||||
{
|
|
||||||
command_print(cmd_ctx, "cache not yet identified");
|
command_print(cmd_ctx, "cache not yet identified");
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
command_print(cmd_ctx,
|
command_print(cmd_ctx,
|
||||||
"D-Cache: linelen %i, associativity %i, nsets %i, cachesize %d KBytes",
|
"D-Cache: linelen %i, associativity %i, nsets %i, cachesize %d KBytes",
|
||||||
armv7a_cache->d_u_size.linelen,
|
armv7a_cache->d_u_size.linelen,
|
||||||
armv7a_cache->d_u_size.associativity,
|
armv7a_cache->d_u_size.associativity,
|
||||||
armv7a_cache->d_u_size.nsets,
|
armv7a_cache->d_u_size.nsets,
|
||||||
armv7a_cache->d_u_size.cachesize);
|
armv7a_cache->d_u_size.cachesize);
|
||||||
|
|
||||||
command_print(cmd_ctx,
|
command_print(cmd_ctx,
|
||||||
"I-Cache: linelen %i, associativity %i, nsets %i, cachesize %d KBytes",
|
"I-Cache: linelen %i, associativity %i, nsets %i, cachesize %d KBytes",
|
||||||
armv7a_cache->i_size.linelen,
|
armv7a_cache->i_size.linelen,
|
||||||
armv7a_cache->i_size.associativity,
|
armv7a_cache->i_size.associativity,
|
||||||
armv7a_cache->i_size.nsets,
|
armv7a_cache->i_size.nsets,
|
||||||
armv7a_cache->i_size.cachesize);
|
armv7a_cache->i_size.cachesize);
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
@ -338,28 +339,29 @@ static int _armv7a_flush_all_data(struct target *target)
|
||||||
int32_t c_way, c_index = d_u_size->index;
|
int32_t c_way, c_index = d_u_size->index;
|
||||||
int retval;
|
int retval;
|
||||||
/* check that cache data is on at target halt */
|
/* check that cache data is on at target halt */
|
||||||
if (!armv7a->armv7a_mmu.armv7a_cache.d_u_cache_enabled)
|
if (!armv7a->armv7a_mmu.armv7a_cache.d_u_cache_enabled) {
|
||||||
{
|
|
||||||
LOG_INFO("flushed not performed :cache not on at target halt");
|
LOG_INFO("flushed not performed :cache not on at target halt");
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
retval = dpm->prepare(dpm);
|
retval = dpm->prepare(dpm);
|
||||||
if (retval != ERROR_OK) goto done;
|
if (retval != ERROR_OK)
|
||||||
|
goto done;
|
||||||
do {
|
do {
|
||||||
c_way = d_u_size->way;
|
c_way = d_u_size->way;
|
||||||
do {
|
do {
|
||||||
uint32_t value = (c_index << d_u_size->index_shift)
|
uint32_t value = (c_index << d_u_size->index_shift)
|
||||||
| (c_way << d_u_size->way_shift);
|
| (c_way << d_u_size->way_shift);
|
||||||
/* DCCISW */
|
/* DCCISW */
|
||||||
//LOG_INFO ("%d %d %x",c_way,c_index,value);
|
/* LOG_INFO ("%d %d %x",c_way,c_index,value); */
|
||||||
retval = dpm->instr_write_data_r0(dpm,
|
retval = dpm->instr_write_data_r0(dpm,
|
||||||
ARMV4_5_MCR(15, 0, 0, 7, 14, 2),
|
ARMV4_5_MCR(15, 0, 0, 7, 14, 2),
|
||||||
value);
|
value);
|
||||||
if (retval!= ERROR_OK) goto done;
|
if (retval != ERROR_OK)
|
||||||
|
goto done;
|
||||||
c_way -= 1;
|
c_way -= 1;
|
||||||
} while (c_way >=0);
|
} while (c_way >= 0);
|
||||||
c_index -= 1;
|
c_index -= 1;
|
||||||
} while (c_index >=0);
|
} while (c_index >= 0);
|
||||||
return retval;
|
return retval;
|
||||||
done:
|
done:
|
||||||
LOG_ERROR("flushed failed");
|
LOG_ERROR("flushed failed");
|
||||||
|
@ -367,89 +369,85 @@ done:
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int armv7a_flush_all_data( struct target * target)
|
static int armv7a_flush_all_data(struct target *target)
|
||||||
{
|
{
|
||||||
int retval = ERROR_FAIL;
|
int retval = ERROR_FAIL;
|
||||||
/* check that armv7a_cache is correctly identify */
|
/* check that armv7a_cache is correctly identify */
|
||||||
struct armv7a_common *armv7a = target_to_armv7a(target);
|
struct armv7a_common *armv7a = target_to_armv7a(target);
|
||||||
if (armv7a->armv7a_mmu.armv7a_cache.ctype == -1)
|
if (armv7a->armv7a_mmu.armv7a_cache.ctype == -1) {
|
||||||
{
|
|
||||||
LOG_ERROR("trying to flush un-identified cache");
|
LOG_ERROR("trying to flush un-identified cache");
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (target->smp)
|
if (target->smp) {
|
||||||
{
|
|
||||||
/* look if all the other target have been flushed in order to flush level
|
/* look if all the other target have been flushed in order to flush level
|
||||||
* 2 */
|
* 2 */
|
||||||
struct target_list *head;
|
struct target_list *head;
|
||||||
struct target *curr;
|
struct target *curr;
|
||||||
head = target->head;
|
head = target->head;
|
||||||
while(head != (struct target_list*)NULL)
|
while (head != (struct target_list *)NULL) {
|
||||||
{
|
|
||||||
curr = head->target;
|
curr = head->target;
|
||||||
if ((curr->state == TARGET_HALTED))
|
if ((curr->state == TARGET_HALTED)) {
|
||||||
{ LOG_INFO("Wait flushing data l1 on core %d",curr->coreid);
|
LOG_INFO("Wait flushing data l1 on core %d", curr->coreid);
|
||||||
retval = _armv7a_flush_all_data(curr);
|
retval = _armv7a_flush_all_data(curr);
|
||||||
}
|
}
|
||||||
head = head->next;
|
head = head->next;
|
||||||
}
|
}
|
||||||
}
|
} else
|
||||||
else retval = _armv7a_flush_all_data(target);
|
retval = _armv7a_flush_all_data(target);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* L2 is not specific to armv7a a specific file is needed */
|
/* L2 is not specific to armv7a a specific file is needed */
|
||||||
static int armv7a_l2x_flush_all_data(struct target * target)
|
static int armv7a_l2x_flush_all_data(struct target *target)
|
||||||
{
|
{
|
||||||
|
|
||||||
#define L2X0_CLEAN_INV_WAY 0x7FC
|
#define L2X0_CLEAN_INV_WAY 0x7FC
|
||||||
int retval = ERROR_FAIL;
|
int retval = ERROR_FAIL;
|
||||||
struct armv7a_common *armv7a = target_to_armv7a(target);
|
struct armv7a_common *armv7a = target_to_armv7a(target);
|
||||||
struct armv7a_l2x_cache *l2x_cache = (struct armv7a_l2x_cache*)
|
struct armv7a_l2x_cache *l2x_cache = (struct armv7a_l2x_cache *)
|
||||||
(armv7a->armv7a_mmu.armv7a_cache.l2_cache);
|
(armv7a->armv7a_mmu.armv7a_cache.l2_cache);
|
||||||
uint32_t base = l2x_cache->base;
|
uint32_t base = l2x_cache->base;
|
||||||
uint32_t l2_way = l2x_cache->way;
|
uint32_t l2_way = l2x_cache->way;
|
||||||
uint32_t l2_way_val = (1<<l2_way) -1;
|
uint32_t l2_way_val = (1 << l2_way) - 1;
|
||||||
retval = armv7a_flush_all_data(target);
|
retval = armv7a_flush_all_data(target);
|
||||||
if (retval!=ERROR_OK) return retval;
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
retval = target->type->write_phys_memory(target,
|
retval = target->type->write_phys_memory(target,
|
||||||
(uint32_t)(base+(uint32_t)L2X0_CLEAN_INV_WAY),
|
(uint32_t)(base+(uint32_t)L2X0_CLEAN_INV_WAY),
|
||||||
(uint32_t)4,
|
(uint32_t)4,
|
||||||
(uint32_t)1,
|
(uint32_t)1,
|
||||||
(uint8_t*)&l2_way_val);
|
(uint8_t *)&l2_way_val);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int armv7a_handle_l2x_cache_info_command(struct command_context *cmd_ctx,
|
static int armv7a_handle_l2x_cache_info_command(struct command_context *cmd_ctx,
|
||||||
struct armv7a_cache_common *armv7a_cache)
|
struct armv7a_cache_common *armv7a_cache)
|
||||||
{
|
{
|
||||||
|
|
||||||
struct armv7a_l2x_cache *l2x_cache = (struct armv7a_l2x_cache*)
|
struct armv7a_l2x_cache *l2x_cache = (struct armv7a_l2x_cache *)
|
||||||
(armv7a_cache->l2_cache);
|
(armv7a_cache->l2_cache);
|
||||||
|
|
||||||
if (armv7a_cache->ctype == -1)
|
if (armv7a_cache->ctype == -1) {
|
||||||
{
|
|
||||||
command_print(cmd_ctx, "cache not yet identified");
|
command_print(cmd_ctx, "cache not yet identified");
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
command_print(cmd_ctx,
|
command_print(cmd_ctx,
|
||||||
"L1 D-Cache: linelen %i, associativity %i, nsets %i, cachesize %d KBytes",
|
"L1 D-Cache: linelen %i, associativity %i, nsets %i, cachesize %d KBytes",
|
||||||
armv7a_cache->d_u_size.linelen,
|
armv7a_cache->d_u_size.linelen,
|
||||||
armv7a_cache->d_u_size.associativity,
|
armv7a_cache->d_u_size.associativity,
|
||||||
armv7a_cache->d_u_size.nsets,
|
armv7a_cache->d_u_size.nsets,
|
||||||
armv7a_cache->d_u_size.cachesize);
|
armv7a_cache->d_u_size.cachesize);
|
||||||
|
|
||||||
command_print(cmd_ctx,
|
command_print(cmd_ctx,
|
||||||
"L1 I-Cache: linelen %i, associativity %i, nsets %i, cachesize %d KBytes",
|
"L1 I-Cache: linelen %i, associativity %i, nsets %i, cachesize %d KBytes",
|
||||||
armv7a_cache->i_size.linelen,
|
armv7a_cache->i_size.linelen,
|
||||||
armv7a_cache->i_size.associativity,
|
armv7a_cache->i_size.associativity,
|
||||||
armv7a_cache->i_size.nsets,
|
armv7a_cache->i_size.nsets,
|
||||||
armv7a_cache->i_size.cachesize);
|
armv7a_cache->i_size.cachesize);
|
||||||
command_print(cmd_ctx, "L2 unified cache Base Address 0x%x, %d ways",
|
command_print(cmd_ctx, "L2 unified cache Base Address 0x%x, %d ways",
|
||||||
l2x_cache->base, l2x_cache->way);
|
l2x_cache->base, l2x_cache->way);
|
||||||
|
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
|
@ -469,34 +467,28 @@ static int armv7a_l2x_cache_init(struct target *target, uint32_t base, uint32_t
|
||||||
/*LOG_INFO("cache l2 initialized base %x way %d",
|
/*LOG_INFO("cache l2 initialized base %x way %d",
|
||||||
l2x_cache->base,l2x_cache->way);*/
|
l2x_cache->base,l2x_cache->way);*/
|
||||||
if (armv7a->armv7a_mmu.armv7a_cache.l2_cache)
|
if (armv7a->armv7a_mmu.armv7a_cache.l2_cache)
|
||||||
{
|
|
||||||
LOG_INFO("cache l2 already initialized\n");
|
LOG_INFO("cache l2 already initialized\n");
|
||||||
}
|
armv7a->armv7a_mmu.armv7a_cache.l2_cache = (void *) l2x_cache;
|
||||||
armv7a->armv7a_mmu.armv7a_cache.l2_cache = (void*) l2x_cache;
|
|
||||||
/* initialize l1 / l2x cache function */
|
/* initialize l1 / l2x cache function */
|
||||||
armv7a->armv7a_mmu.armv7a_cache.flush_all_data_cache
|
armv7a->armv7a_mmu.armv7a_cache.flush_all_data_cache
|
||||||
= armv7a_l2x_flush_all_data;
|
= armv7a_l2x_flush_all_data;
|
||||||
armv7a->armv7a_mmu.armv7a_cache.display_cache_info =
|
armv7a->armv7a_mmu.armv7a_cache.display_cache_info =
|
||||||
armv7a_handle_l2x_cache_info_command;
|
armv7a_handle_l2x_cache_info_command;
|
||||||
/* initialize all target in this cluster (smp target)*/
|
/* initialize all target in this cluster (smp target)
|
||||||
/* l2 cache must be configured after smp declaration */
|
* l2 cache must be configured after smp declaration */
|
||||||
while(head != (struct target_list*)NULL)
|
while (head != (struct target_list *)NULL) {
|
||||||
{
|
|
||||||
curr = head->target;
|
curr = head->target;
|
||||||
if (curr != target)
|
if (curr != target) {
|
||||||
{
|
|
||||||
armv7a = target_to_armv7a(curr);
|
armv7a = target_to_armv7a(curr);
|
||||||
if (armv7a->armv7a_mmu.armv7a_cache.l2_cache)
|
if (armv7a->armv7a_mmu.armv7a_cache.l2_cache)
|
||||||
{
|
|
||||||
LOG_ERROR("smp target : cache l2 already initialized\n");
|
LOG_ERROR("smp target : cache l2 already initialized\n");
|
||||||
}
|
armv7a->armv7a_mmu.armv7a_cache.l2_cache = (void *) l2x_cache;
|
||||||
armv7a->armv7a_mmu.armv7a_cache.l2_cache = (void*) l2x_cache;
|
|
||||||
armv7a->armv7a_mmu.armv7a_cache.flush_all_data_cache =
|
armv7a->armv7a_mmu.armv7a_cache.flush_all_data_cache =
|
||||||
armv7a_l2x_flush_all_data;
|
armv7a_l2x_flush_all_data;
|
||||||
armv7a->armv7a_mmu.armv7a_cache.display_cache_info =
|
armv7a->armv7a_mmu.armv7a_cache.display_cache_info =
|
||||||
armv7a_handle_l2x_cache_info_command;
|
armv7a_handle_l2x_cache_info_command;
|
||||||
}
|
}
|
||||||
head = head -> next;
|
head = head->next;
|
||||||
}
|
}
|
||||||
return JIM_OK;
|
return JIM_OK;
|
||||||
}
|
}
|
||||||
|
@ -504,33 +496,29 @@ static int armv7a_l2x_cache_init(struct target *target, uint32_t base, uint32_t
|
||||||
COMMAND_HANDLER(handle_cache_l2x)
|
COMMAND_HANDLER(handle_cache_l2x)
|
||||||
{
|
{
|
||||||
struct target *target = get_current_target(CMD_CTX);
|
struct target *target = get_current_target(CMD_CTX);
|
||||||
uint32_t base, way;
|
uint32_t base, way;
|
||||||
switch (CMD_ARGC) {
|
switch (CMD_ARGC) {
|
||||||
case 0:
|
case 0:
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
//command_print(CMD_CTX, "%s %s", CMD_ARGV[0], CMD_ARGV[1]);
|
/* command_print(CMD_CTX, "%s %s", CMD_ARGV[0], CMD_ARGV[1]); */
|
||||||
|
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], base);
|
||||||
|
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], way);
|
||||||
|
|
||||||
|
/* AP address is in bits 31:24 of DP_SELECT */
|
||||||
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], base);
|
armv7a_l2x_cache_init(target, base, way);
|
||||||
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], way);
|
break;
|
||||||
|
default:
|
||||||
/* AP address is in bits 31:24 of DP_SELECT */
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
armv7a_l2x_cache_init(target, base, way);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
|
||||||
}
|
}
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int armv7a_handle_cache_info_command(struct command_context *cmd_ctx,
|
int armv7a_handle_cache_info_command(struct command_context *cmd_ctx,
|
||||||
struct armv7a_cache_common *armv7a_cache)
|
struct armv7a_cache_common *armv7a_cache)
|
||||||
{
|
{
|
||||||
if (armv7a_cache->ctype == -1)
|
if (armv7a_cache->ctype == -1) {
|
||||||
{
|
|
||||||
command_print(cmd_ctx, "cache not yet identified");
|
command_print(cmd_ctx, "cache not yet identified");
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
@ -540,35 +528,34 @@ int armv7a_handle_cache_info_command(struct command_context *cmd_ctx,
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* retrieve core id cluster id */
|
/* retrieve core id cluster id */
|
||||||
static int armv7a_read_mpidr(struct target *target)
|
static int armv7a_read_mpidr(struct target *target)
|
||||||
{
|
{
|
||||||
int retval = ERROR_FAIL;
|
int retval = ERROR_FAIL;
|
||||||
struct armv7a_common *armv7a = target_to_armv7a(target);
|
struct armv7a_common *armv7a = target_to_armv7a(target);
|
||||||
struct arm_dpm *dpm = armv7a->arm.dpm;
|
struct arm_dpm *dpm = armv7a->arm.dpm;
|
||||||
uint32_t mpidr;
|
uint32_t mpidr;
|
||||||
retval = dpm->prepare(dpm);
|
retval = dpm->prepare(dpm);
|
||||||
if (retval!=ERROR_OK) goto done;
|
if (retval != ERROR_OK)
|
||||||
|
goto done;
|
||||||
/* MRC p15,0,<Rd>,c0,c0,5; read Multiprocessor ID register*/
|
/* MRC p15,0,<Rd>,c0,c0,5; read Multiprocessor ID register*/
|
||||||
|
|
||||||
retval = dpm->instr_read_data_r0(dpm,
|
retval = dpm->instr_read_data_r0(dpm,
|
||||||
ARMV4_5_MRC(15, 0, 0, 0, 0, 5),
|
ARMV4_5_MRC(15, 0, 0, 0, 0, 5),
|
||||||
&mpidr);
|
&mpidr);
|
||||||
if (retval!=ERROR_OK) goto done;
|
if (retval != ERROR_OK)
|
||||||
if (mpidr & 1<<31)
|
goto done;
|
||||||
{
|
if (mpidr & 1<<31) {
|
||||||
armv7a->multi_processor_system = (mpidr >> 30) & 1;
|
armv7a->multi_processor_system = (mpidr >> 30) & 1;
|
||||||
armv7a->cluster_id = (mpidr >> 8) & 0xf;
|
armv7a->cluster_id = (mpidr >> 8) & 0xf;
|
||||||
armv7a->cpu_id = mpidr & 0x3;
|
armv7a->cpu_id = mpidr & 0x3;
|
||||||
LOG_INFO("%s cluster %x core %x %s", target->cmd_name,
|
LOG_INFO("%s cluster %x core %x %s", target->cmd_name,
|
||||||
armv7a->cluster_id,
|
armv7a->cluster_id,
|
||||||
armv7a->cpu_id,
|
armv7a->cpu_id,
|
||||||
armv7a->multi_processor_system == 0 ? "multi core": "mono core");
|
armv7a->multi_processor_system == 0 ? "multi core" : "mono core");
|
||||||
|
|
||||||
}
|
} else
|
||||||
else
|
LOG_ERROR("mpdir not in multiprocessor format");
|
||||||
LOG_ERROR("mpdir not in multiprocessor format");
|
|
||||||
|
|
||||||
done:
|
done:
|
||||||
dpm->finish(dpm);
|
dpm->finish(dpm);
|
||||||
|
@ -577,138 +564,149 @@ done:
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int armv7a_identify_cache(struct target *target)
|
int armv7a_identify_cache(struct target *target)
|
||||||
{
|
{
|
||||||
/* read cache descriptor */
|
/* read cache descriptor */
|
||||||
int retval = ERROR_FAIL;
|
int retval = ERROR_FAIL;
|
||||||
struct armv7a_common *armv7a = target_to_armv7a(target);
|
struct armv7a_common *armv7a = target_to_armv7a(target);
|
||||||
struct arm_dpm *dpm = armv7a->arm.dpm;
|
struct arm_dpm *dpm = armv7a->arm.dpm;
|
||||||
uint32_t cache_selected,clidr;
|
uint32_t cache_selected, clidr;
|
||||||
uint32_t cache_i_reg, cache_d_reg;
|
uint32_t cache_i_reg, cache_d_reg;
|
||||||
struct armv7a_cache_common *cache = &(armv7a->armv7a_mmu.armv7a_cache);
|
struct armv7a_cache_common *cache = &(armv7a->armv7a_mmu.armv7a_cache);
|
||||||
armv7a_read_ttbcr(target);
|
armv7a_read_ttbcr(target);
|
||||||
retval = dpm->prepare(dpm);
|
retval = dpm->prepare(dpm);
|
||||||
|
|
||||||
if (retval!=ERROR_OK) goto done;
|
if (retval != ERROR_OK)
|
||||||
/* retrieve CLIDR */
|
goto done;
|
||||||
/* mrc p15, 1, r0, c0, c0, 1 @ read clidr */
|
/* retrieve CLIDR
|
||||||
|
* mrc p15, 1, r0, c0, c0, 1 @ read clidr */
|
||||||
retval = dpm->instr_read_data_r0(dpm,
|
retval = dpm->instr_read_data_r0(dpm,
|
||||||
ARMV4_5_MRC(15, 1, 0, 0, 0, 1),
|
ARMV4_5_MRC(15, 1, 0, 0, 0, 1),
|
||||||
&clidr);
|
&clidr);
|
||||||
if (retval!=ERROR_OK) goto done;
|
if (retval != ERROR_OK)
|
||||||
|
goto done;
|
||||||
clidr = (clidr & 0x7000000) >> 23;
|
clidr = (clidr & 0x7000000) >> 23;
|
||||||
LOG_INFO("number of cache level %d",clidr /2 );
|
LOG_INFO("number of cache level %d", clidr / 2);
|
||||||
if ((clidr /2) > 1)
|
if ((clidr / 2) > 1) {
|
||||||
{
|
/* FIXME not supported present in cortex A8 and later */
|
||||||
// FIXME not supported present in cortex A8 and later
|
/* in cortex A7, A15 */
|
||||||
// in cortex A7, A15
|
|
||||||
LOG_ERROR("cache l2 present :not supported");
|
LOG_ERROR("cache l2 present :not supported");
|
||||||
}
|
}
|
||||||
/* retrieve selected cache */
|
/* retrieve selected cache
|
||||||
/* MRC p15, 2,<Rd>, c0, c0, 0; Read CSSELR */
|
* MRC p15, 2,<Rd>, c0, c0, 0; Read CSSELR */
|
||||||
retval = dpm->instr_read_data_r0(dpm,
|
retval = dpm->instr_read_data_r0(dpm,
|
||||||
ARMV4_5_MRC(15, 2, 0, 0, 0, 0),
|
ARMV4_5_MRC(15, 2, 0, 0, 0, 0),
|
||||||
&cache_selected);
|
&cache_selected);
|
||||||
if (retval!=ERROR_OK) goto done;
|
if (retval != ERROR_OK)
|
||||||
|
goto done;
|
||||||
|
|
||||||
retval = armv7a->arm.mrc(target, 15,
|
retval = armv7a->arm.mrc(target, 15,
|
||||||
2, 0, /* op1, op2 */
|
2, 0, /* op1, op2 */
|
||||||
0, 0, /* CRn, CRm */
|
0, 0, /* CRn, CRm */
|
||||||
&cache_selected);
|
&cache_selected);
|
||||||
if (retval!=ERROR_OK) goto done;
|
if (retval != ERROR_OK)
|
||||||
/* select instruction cache*/
|
goto done;
|
||||||
/* MCR p15, 2,<Rd>, c0, c0, 0; Write CSSELR */
|
/* select instruction cache
|
||||||
/* [0] : 1 instruction cache selection , 0 data cache selection */
|
* MCR p15, 2,<Rd>, c0, c0, 0; Write CSSELR
|
||||||
|
* [0] : 1 instruction cache selection , 0 data cache selection */
|
||||||
retval = dpm->instr_write_data_r0(dpm,
|
retval = dpm->instr_write_data_r0(dpm,
|
||||||
ARMV4_5_MRC(15, 2, 0, 0, 0, 0),
|
ARMV4_5_MRC(15, 2, 0, 0, 0, 0),
|
||||||
1);
|
1);
|
||||||
if (retval!=ERROR_OK) goto done;
|
if (retval != ERROR_OK)
|
||||||
|
goto done;
|
||||||
|
|
||||||
/* read CCSIDR*/
|
/* read CCSIDR
|
||||||
/* MRC P15,1,<RT>,C0, C0,0 ;on cortex A9 read CCSIDR */
|
* MRC P15,1,<RT>,C0, C0,0 ;on cortex A9 read CCSIDR
|
||||||
/* [2:0] line size 001 eight word per line */
|
* [2:0] line size 001 eight word per line
|
||||||
/* [27:13] NumSet 0x7f 16KB, 0xff 32Kbytes, 0x1ff 64Kbytes */
|
* [27:13] NumSet 0x7f 16KB, 0xff 32Kbytes, 0x1ff 64Kbytes */
|
||||||
retval = dpm->instr_read_data_r0(dpm,
|
retval = dpm->instr_read_data_r0(dpm,
|
||||||
ARMV4_5_MRC(15, 1, 0, 0, 0, 0),
|
ARMV4_5_MRC(15, 1, 0, 0, 0, 0),
|
||||||
&cache_i_reg);
|
&cache_i_reg);
|
||||||
if (retval!=ERROR_OK) goto done;
|
if (retval != ERROR_OK)
|
||||||
|
goto done;
|
||||||
|
|
||||||
/* select data cache*/
|
/* select data cache*/
|
||||||
retval = dpm->instr_write_data_r0(dpm,
|
retval = dpm->instr_write_data_r0(dpm,
|
||||||
ARMV4_5_MRC(15, 2, 0, 0, 0, 0),
|
ARMV4_5_MRC(15, 2, 0, 0, 0, 0),
|
||||||
0);
|
0);
|
||||||
if (retval!=ERROR_OK) goto done;
|
if (retval != ERROR_OK)
|
||||||
|
goto done;
|
||||||
|
|
||||||
retval = dpm->instr_read_data_r0(dpm,
|
retval = dpm->instr_read_data_r0(dpm,
|
||||||
ARMV4_5_MRC(15, 1, 0, 0, 0, 0),
|
ARMV4_5_MRC(15, 1, 0, 0, 0, 0),
|
||||||
&cache_d_reg);
|
&cache_d_reg);
|
||||||
if (retval!=ERROR_OK) goto done;
|
if (retval != ERROR_OK)
|
||||||
|
goto done;
|
||||||
|
|
||||||
/* restore selected cache */
|
/* restore selected cache */
|
||||||
dpm->instr_write_data_r0(dpm,
|
dpm->instr_write_data_r0(dpm,
|
||||||
ARMV4_5_MRC(15, 2, 0, 0, 0, 0),
|
ARMV4_5_MRC(15, 2, 0, 0, 0, 0),
|
||||||
cache_selected);
|
cache_selected);
|
||||||
|
|
||||||
if (retval != ERROR_OK) goto done;
|
if (retval != ERROR_OK)
|
||||||
|
goto done;
|
||||||
dpm->finish(dpm);
|
dpm->finish(dpm);
|
||||||
|
|
||||||
// put fake type
|
/* put fake type */
|
||||||
cache->d_u_size.linelen = 16 << (cache_d_reg & 0x7);
|
cache->d_u_size.linelen = 16 << (cache_d_reg & 0x7);
|
||||||
cache->d_u_size.cachesize = (((cache_d_reg >> 13) & 0x7fff)+1)/8;
|
cache->d_u_size.cachesize = (((cache_d_reg >> 13) & 0x7fff)+1)/8;
|
||||||
cache->d_u_size.nsets = (cache_d_reg >> 13) & 0x7fff;
|
cache->d_u_size.nsets = (cache_d_reg >> 13) & 0x7fff;
|
||||||
cache->d_u_size.associativity = ((cache_d_reg >> 3) & 0x3ff) +1;
|
cache->d_u_size.associativity = ((cache_d_reg >> 3) & 0x3ff) + 1;
|
||||||
/* compute info for set way operation on cache */
|
/* compute info for set way operation on cache */
|
||||||
cache->d_u_size.index_shift = (cache_d_reg & 0x7) + 4;
|
cache->d_u_size.index_shift = (cache_d_reg & 0x7) + 4;
|
||||||
cache->d_u_size.index = (cache_d_reg >> 13) & 0x7fff;
|
cache->d_u_size.index = (cache_d_reg >> 13) & 0x7fff;
|
||||||
cache->d_u_size.way = ((cache_d_reg >> 3) & 0x3ff);
|
cache->d_u_size.way = ((cache_d_reg >> 3) & 0x3ff);
|
||||||
cache->d_u_size.way_shift = cache->d_u_size.way+1;
|
cache->d_u_size.way_shift = cache->d_u_size.way + 1;
|
||||||
{
|
{
|
||||||
int i=0;
|
int i = 0;
|
||||||
while(((cache->d_u_size.way_shift >> i) & 1)!=1) i++;
|
while (((cache->d_u_size.way_shift >> i) & 1) != 1)
|
||||||
|
i++;
|
||||||
cache->d_u_size.way_shift = 32-i;
|
cache->d_u_size.way_shift = 32-i;
|
||||||
}
|
}
|
||||||
/*LOG_INFO("data cache index %d << %d, way %d << %d",
|
#if 0
|
||||||
|
LOG_INFO("data cache index %d << %d, way %d << %d",
|
||||||
cache->d_u_size.index, cache->d_u_size.index_shift,
|
cache->d_u_size.index, cache->d_u_size.index_shift,
|
||||||
cache->d_u_size.way, cache->d_u_size.way_shift);
|
cache->d_u_size.way,
|
||||||
|
cache->d_u_size.way_shift);
|
||||||
|
|
||||||
LOG_INFO("data cache %d bytes %d KBytes asso %d ways",
|
LOG_INFO("data cache %d bytes %d KBytes asso %d ways",
|
||||||
cache->d_u_size.linelen,
|
cache->d_u_size.linelen,
|
||||||
cache->d_u_size.cachesize,
|
cache->d_u_size.cachesize,
|
||||||
cache->d_u_size.associativity
|
cache->d_u_size.associativity);
|
||||||
);*/
|
#endif
|
||||||
cache->i_size.linelen = 16 << (cache_i_reg & 0x7);
|
cache->i_size.linelen = 16 << (cache_i_reg & 0x7);
|
||||||
cache->i_size.associativity = ((cache_i_reg >> 3) & 0x3ff) +1;
|
cache->i_size.associativity = ((cache_i_reg >> 3) & 0x3ff) + 1;
|
||||||
cache->i_size.nsets = (cache_i_reg >> 13) & 0x7fff;
|
cache->i_size.nsets = (cache_i_reg >> 13) & 0x7fff;
|
||||||
cache->i_size.cachesize = (((cache_i_reg >> 13) & 0x7fff)+1)/8;
|
cache->i_size.cachesize = (((cache_i_reg >> 13) & 0x7fff)+1)/8;
|
||||||
/* compute info for set way operation on cache */
|
/* compute info for set way operation on cache */
|
||||||
cache->i_size.index_shift = (cache_i_reg & 0x7) + 4;
|
cache->i_size.index_shift = (cache_i_reg & 0x7) + 4;
|
||||||
cache->i_size.index = (cache_i_reg >> 13) & 0x7fff;
|
cache->i_size.index = (cache_i_reg >> 13) & 0x7fff;
|
||||||
cache->i_size.way = ((cache_i_reg >> 3) & 0x3ff);
|
cache->i_size.way = ((cache_i_reg >> 3) & 0x3ff);
|
||||||
cache->i_size.way_shift = cache->i_size.way+1;
|
cache->i_size.way_shift = cache->i_size.way + 1;
|
||||||
{
|
{
|
||||||
int i=0;
|
int i = 0;
|
||||||
while(((cache->i_size.way_shift >> i) & 1)!=1) i++;
|
while (((cache->i_size.way_shift >> i) & 1) != 1)
|
||||||
|
i++;
|
||||||
cache->i_size.way_shift = 32-i;
|
cache->i_size.way_shift = 32-i;
|
||||||
}
|
}
|
||||||
/*LOG_INFO("instruction cache index %d << %d, way %d << %d",
|
#if 0
|
||||||
|
LOG_INFO("instruction cache index %d << %d, way %d << %d",
|
||||||
cache->i_size.index, cache->i_size.index_shift,
|
cache->i_size.index, cache->i_size.index_shift,
|
||||||
cache->i_size.way, cache->i_size.way_shift);
|
cache->i_size.way, cache->i_size.way_shift);
|
||||||
|
|
||||||
LOG_INFO("instruction cache %d bytes %d KBytes asso %d ways",
|
LOG_INFO("instruction cache %d bytes %d KBytes asso %d ways",
|
||||||
cache->i_size.linelen,
|
cache->i_size.linelen,
|
||||||
cache->i_size.cachesize,
|
cache->i_size.cachesize,
|
||||||
cache->i_size.associativity
|
cache->i_size.associativity);
|
||||||
);*/
|
#endif
|
||||||
/* if no l2 cache initialize l1 data cache flush function function */
|
/* if no l2 cache initialize l1 data cache flush function function */
|
||||||
if (armv7a->armv7a_mmu.armv7a_cache.flush_all_data_cache == NULL)
|
if (armv7a->armv7a_mmu.armv7a_cache.flush_all_data_cache == NULL) {
|
||||||
{
|
|
||||||
armv7a->armv7a_mmu.armv7a_cache.display_cache_info =
|
armv7a->armv7a_mmu.armv7a_cache.display_cache_info =
|
||||||
armv7a_handle_inner_cache_info_command;
|
armv7a_handle_inner_cache_info_command;
|
||||||
armv7a->armv7a_mmu.armv7a_cache.flush_all_data_cache =
|
armv7a->armv7a_mmu.armv7a_cache.flush_all_data_cache =
|
||||||
armv7a_flush_all_data;
|
armv7a_flush_all_data;
|
||||||
}
|
}
|
||||||
armv7a->armv7a_mmu.armv7a_cache.ctype = 0;
|
armv7a->armv7a_mmu.armv7a_cache.ctype = 0;
|
||||||
|
|
||||||
done:
|
done:
|
||||||
dpm->finish(dpm);
|
dpm->finish(dpm);
|
||||||
|
@ -717,8 +715,6 @@ done:
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int armv7a_init_arch_info(struct target *target, struct armv7a_common *armv7a)
|
int armv7a_init_arch_info(struct target *target, struct armv7a_common *armv7a)
|
||||||
{
|
{
|
||||||
struct arm *arm = &armv7a->arm;
|
struct arm *arm = &armv7a->arm;
|
||||||
|
@ -726,27 +722,25 @@ int armv7a_init_arch_info(struct target *target, struct armv7a_common *armv7a)
|
||||||
target->arch_info = &armv7a->arm;
|
target->arch_info = &armv7a->arm;
|
||||||
/* target is useful in all function arm v4 5 compatible */
|
/* target is useful in all function arm v4 5 compatible */
|
||||||
armv7a->arm.target = target;
|
armv7a->arm.target = target;
|
||||||
armv7a->arm.common_magic = ARM_COMMON_MAGIC;
|
armv7a->arm.common_magic = ARM_COMMON_MAGIC;
|
||||||
armv7a->common_magic = ARMV7_COMMON_MAGIC;
|
armv7a->common_magic = ARMV7_COMMON_MAGIC;
|
||||||
armv7a->armv7a_mmu.armv7a_cache.l2_cache = NULL;
|
armv7a->armv7a_mmu.armv7a_cache.l2_cache = NULL;
|
||||||
armv7a->armv7a_mmu.armv7a_cache.ctype = -1;
|
armv7a->armv7a_mmu.armv7a_cache.ctype = -1;
|
||||||
armv7a->armv7a_mmu.armv7a_cache.flush_all_data_cache = NULL;
|
armv7a->armv7a_mmu.armv7a_cache.flush_all_data_cache = NULL;
|
||||||
armv7a->armv7a_mmu.armv7a_cache.display_cache_info = NULL;
|
armv7a->armv7a_mmu.armv7a_cache.display_cache_info = NULL;
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int armv7a_arch_state(struct target *target)
|
int armv7a_arch_state(struct target *target)
|
||||||
{
|
{
|
||||||
static const char *state[] =
|
static const char *state[] = {
|
||||||
{
|
|
||||||
"disabled", "enabled"
|
"disabled", "enabled"
|
||||||
};
|
};
|
||||||
|
|
||||||
struct armv7a_common *armv7a = target_to_armv7a(target);
|
struct armv7a_common *armv7a = target_to_armv7a(target);
|
||||||
struct arm *arm = &armv7a->arm;
|
struct arm *arm = &armv7a->arm;
|
||||||
|
|
||||||
if (armv7a->common_magic != ARMV7_COMMON_MAGIC)
|
if (armv7a->common_magic != ARMV7_COMMON_MAGIC) {
|
||||||
{
|
|
||||||
LOG_ERROR("BUG: called for a non-ARMv7A target");
|
LOG_ERROR("BUG: called for a non-ARMv7A target");
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
}
|
}
|
||||||
|
@ -754,15 +748,15 @@ int armv7a_arch_state(struct target *target)
|
||||||
arm_arch_state(target);
|
arm_arch_state(target);
|
||||||
|
|
||||||
LOG_USER("MMU: %s, D-Cache: %s, I-Cache: %s",
|
LOG_USER("MMU: %s, D-Cache: %s, I-Cache: %s",
|
||||||
state[armv7a->armv7a_mmu.mmu_enabled],
|
state[armv7a->armv7a_mmu.mmu_enabled],
|
||||||
state[armv7a->armv7a_mmu.armv7a_cache.d_u_cache_enabled],
|
state[armv7a->armv7a_mmu.armv7a_cache.d_u_cache_enabled],
|
||||||
state[armv7a->armv7a_mmu.armv7a_cache.i_cache_enabled]);
|
state[armv7a->armv7a_mmu.armv7a_cache.i_cache_enabled]);
|
||||||
|
|
||||||
if (arm->core_mode == ARM_MODE_ABT)
|
if (arm->core_mode == ARM_MODE_ABT)
|
||||||
armv7a_show_fault_registers(target);
|
armv7a_show_fault_registers(target);
|
||||||
if (target->debug_reason == DBG_REASON_WATCHPOINT)
|
if (target->debug_reason == DBG_REASON_WATCHPOINT)
|
||||||
LOG_USER("Watchpoint triggered at PC %#08x",
|
LOG_USER("Watchpoint triggered at PC %#08x",
|
||||||
(unsigned) armv7a->dpm.wp_pc);
|
(unsigned) armv7a->dpm.wp_pc);
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
@ -776,7 +770,7 @@ static const struct command_registration l2_cache_commands[] = {
|
||||||
"",
|
"",
|
||||||
.usage = "[base_addr] [number_of_way]",
|
.usage = "[base_addr] [number_of_way]",
|
||||||
},
|
},
|
||||||
COMMAND_REGISTRATION_DONE
|
COMMAND_REGISTRATION_DONE
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -801,4 +795,3 @@ const struct command_registration armv7a_command_handlers[] = {
|
||||||
},
|
},
|
||||||
COMMAND_REGISTRATION_DONE
|
COMMAND_REGISTRATION_DONE
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
* Free Software Foundation, Inc., *
|
* Free Software Foundation, Inc., *
|
||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#ifndef ARMV7A_H
|
#ifndef ARMV7A_H
|
||||||
#define ARMV7A_H
|
#define ARMV7A_H
|
||||||
|
|
||||||
|
@ -25,12 +26,10 @@
|
||||||
#include "armv4_5_cache.h"
|
#include "armv4_5_cache.h"
|
||||||
#include "arm_dpm.h"
|
#include "arm_dpm.h"
|
||||||
|
|
||||||
enum
|
enum {
|
||||||
{
|
|
||||||
ARM_PC = 15,
|
ARM_PC = 15,
|
||||||
ARM_CPSR = 16
|
ARM_CPSR = 16
|
||||||
}
|
};
|
||||||
;
|
|
||||||
|
|
||||||
#define ARMV7_COMMON_MAGIC 0x0A450999
|
#define ARMV7_COMMON_MAGIC 0x0A450999
|
||||||
|
|
||||||
|
@ -49,8 +48,7 @@ struct armv7a_l2x_cache {
|
||||||
uint32_t way;
|
uint32_t way;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct armv7a_cachesize
|
struct armv7a_cachesize {
|
||||||
{
|
|
||||||
uint32_t level_num;
|
uint32_t level_num;
|
||||||
/* cache dimensionning */
|
/* cache dimensionning */
|
||||||
uint32_t linelen;
|
uint32_t linelen;
|
||||||
|
@ -64,38 +62,32 @@ struct armv7a_cachesize
|
||||||
uint32_t way_shift;
|
uint32_t way_shift;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct armv7a_cache_common {
|
||||||
struct armv7a_cache_common
|
|
||||||
{
|
|
||||||
int ctype;
|
int ctype;
|
||||||
struct armv7a_cachesize d_u_size; /* data cache */
|
struct armv7a_cachesize d_u_size; /* data cache */
|
||||||
struct armv7a_cachesize i_size; /* instruction cache */
|
struct armv7a_cachesize i_size; /* instruction cache */
|
||||||
int i_cache_enabled;
|
int i_cache_enabled;
|
||||||
int d_u_cache_enabled;
|
int d_u_cache_enabled;
|
||||||
/* l2 external unified cache if some */
|
/* l2 external unified cache if some */
|
||||||
void *l2_cache;
|
void *l2_cache;
|
||||||
int (*flush_all_data_cache)(struct target *target);
|
int (*flush_all_data_cache)(struct target *target);
|
||||||
int (*display_cache_info)(struct command_context *cmd_ctx,
|
int (*display_cache_info)(struct command_context *cmd_ctx,
|
||||||
struct armv7a_cache_common *armv7a_cache);
|
struct armv7a_cache_common *armv7a_cache);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct armv7a_mmu_common {
|
||||||
struct armv7a_mmu_common
|
/* following field mmu working way */
|
||||||
{
|
|
||||||
/* following field mmu working way */
|
|
||||||
int32_t ttbr1_used; /* -1 not initialized, 0 no ttbr1 1 ttbr1 used and */
|
int32_t ttbr1_used; /* -1 not initialized, 0 no ttbr1 1 ttbr1 used and */
|
||||||
uint32_t ttbr0_mask;/* masked to be used */
|
uint32_t ttbr0_mask;/* masked to be used */
|
||||||
uint32_t os_border;
|
uint32_t os_border;
|
||||||
|
|
||||||
int (*read_physical_memory)(struct target *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer);
|
int (*read_physical_memory)(struct target *target, uint32_t address, uint32_t size,
|
||||||
|
uint32_t count, uint8_t *buffer);
|
||||||
struct armv7a_cache_common armv7a_cache;
|
struct armv7a_cache_common armv7a_cache;
|
||||||
uint32_t mmu_enabled;
|
uint32_t mmu_enabled;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct armv7a_common {
|
||||||
|
|
||||||
struct armv7a_common
|
|
||||||
{
|
|
||||||
struct arm arm;
|
struct arm arm;
|
||||||
int common_magic;
|
int common_magic;
|
||||||
struct reg_cache *core_cache;
|
struct reg_cache *core_cache;
|
||||||
|
@ -124,8 +116,7 @@ struct armv7a_common
|
||||||
static inline struct armv7a_common *
|
static inline struct armv7a_common *
|
||||||
target_to_armv7a(struct target *target)
|
target_to_armv7a(struct target *target)
|
||||||
{
|
{
|
||||||
return container_of(target->arch_info, struct armv7a_common,
|
return container_of(target->arch_info, struct armv7a_common, arm);
|
||||||
arm);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* register offsets from armv7a.debug_base */
|
/* register offsets from armv7a.debug_base */
|
||||||
|
@ -169,7 +160,7 @@ int armv7a_arch_state(struct target *target);
|
||||||
int armv7a_identify_cache(struct target *target);
|
int armv7a_identify_cache(struct target *target);
|
||||||
int armv7a_init_arch_info(struct target *target, struct armv7a_common *armv7a);
|
int armv7a_init_arch_info(struct target *target, struct armv7a_common *armv7a);
|
||||||
int armv7a_mmu_translate_va_pa(struct target *target, uint32_t va,
|
int armv7a_mmu_translate_va_pa(struct target *target, uint32_t va,
|
||||||
uint32_t *val,int meminfo);
|
uint32_t *val, int meminfo);
|
||||||
int armv7a_mmu_translate_va(struct target *target, uint32_t va, uint32_t *val);
|
int armv7a_mmu_translate_va(struct target *target, uint32_t va, uint32_t *val);
|
||||||
|
|
||||||
int armv7a_handle_cache_info_command(struct command_context *cmd_ctx,
|
int armv7a_handle_cache_info_command(struct command_context *cmd_ctx,
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
* ARM DDI 0405C (September 2008) *
|
* ARM DDI 0405C (September 2008) *
|
||||||
* *
|
* *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -39,19 +40,16 @@
|
||||||
#include "algorithm.h"
|
#include "algorithm.h"
|
||||||
#include "register.h"
|
#include "register.h"
|
||||||
|
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
#define _DEBUG_INSTRUCTION_EXECUTION_
|
#define _DEBUG_INSTRUCTION_EXECUTION_
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/** Maps from enum armv7m_mode (except ARMV7M_MODE_ANY) to name. */
|
/** Maps from enum armv7m_mode (except ARMV7M_MODE_ANY) to name. */
|
||||||
char *armv7m_mode_strings[] =
|
char *armv7m_mode_strings[] = {
|
||||||
{
|
|
||||||
"Thread", "Thread (User)", "Handler",
|
"Thread", "Thread (User)", "Handler",
|
||||||
};
|
};
|
||||||
|
|
||||||
static char *armv7m_exception_strings[] =
|
static char *armv7m_exception_strings[] = {
|
||||||
{
|
|
||||||
"", "Reset", "NMI", "HardFault",
|
"", "Reset", "NMI", "HardFault",
|
||||||
"MemManage", "BusFault", "UsageFault", "RESERVED",
|
"MemManage", "BusFault", "UsageFault", "RESERVED",
|
||||||
"RESERVED", "RESERVED", "RESERVED", "SVCall",
|
"RESERVED", "RESERVED", "RESERVED", "SVCall",
|
||||||
|
@ -79,8 +77,7 @@ const int armv7m_msp_reg_map[17] = {
|
||||||
#ifdef ARMV7_GDB_HACKS
|
#ifdef ARMV7_GDB_HACKS
|
||||||
uint8_t armv7m_gdb_dummy_cpsr_value[] = {0, 0, 0, 0};
|
uint8_t armv7m_gdb_dummy_cpsr_value[] = {0, 0, 0, 0};
|
||||||
|
|
||||||
struct reg armv7m_gdb_dummy_cpsr_reg =
|
struct reg armv7m_gdb_dummy_cpsr_reg = {
|
||||||
{
|
|
||||||
.name = "GDB dummy cpsr register",
|
.name = "GDB dummy cpsr register",
|
||||||
.value = armv7m_gdb_dummy_cpsr_value,
|
.value = armv7m_gdb_dummy_cpsr_value,
|
||||||
.dirty = 0,
|
.dirty = 0,
|
||||||
|
@ -133,7 +130,7 @@ static const struct {
|
||||||
{ ARMV7M_CONTROL, "control", 2 },
|
{ ARMV7M_CONTROL, "control", 2 },
|
||||||
};
|
};
|
||||||
|
|
||||||
#define ARMV7M_NUM_REGS ARRAY_SIZE(armv7m_regs)
|
#define ARMV7M_NUM_REGS ARRAY_SIZE(armv7m_regs)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Restores target context using the cache of core registers set up
|
* Restores target context using the cache of core registers set up
|
||||||
|
@ -149,12 +146,9 @@ int armv7m_restore_context(struct target *target)
|
||||||
if (armv7m->pre_restore_context)
|
if (armv7m->pre_restore_context)
|
||||||
armv7m->pre_restore_context(target);
|
armv7m->pre_restore_context(target);
|
||||||
|
|
||||||
for (i = ARMV7M_NUM_REGS - 1; i >= 0; i--)
|
for (i = ARMV7M_NUM_REGS - 1; i >= 0; i--) {
|
||||||
{
|
|
||||||
if (armv7m->core_cache->reg_list[i].dirty)
|
if (armv7m->core_cache->reg_list[i].dirty)
|
||||||
{
|
|
||||||
armv7m->write_core_reg(target, i);
|
armv7m->write_core_reg(target, i);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
|
@ -189,9 +183,7 @@ static int armv7m_get_core_reg(struct reg *reg)
|
||||||
struct armv7m_common *armv7m = target_to_armv7m(target);
|
struct armv7m_common *armv7m = target_to_armv7m(target);
|
||||||
|
|
||||||
if (target->state != TARGET_HALTED)
|
if (target->state != TARGET_HALTED)
|
||||||
{
|
|
||||||
return ERROR_TARGET_NOT_HALTED;
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
}
|
|
||||||
|
|
||||||
retval = armv7m->read_core_reg(target, armv7m_reg->num);
|
retval = armv7m->read_core_reg(target, armv7m_reg->num);
|
||||||
|
|
||||||
|
@ -205,9 +197,7 @@ static int armv7m_set_core_reg(struct reg *reg, uint8_t *buf)
|
||||||
uint32_t value = buf_get_u32(buf, 0, 32);
|
uint32_t value = buf_get_u32(buf, 0, 32);
|
||||||
|
|
||||||
if (target->state != TARGET_HALTED)
|
if (target->state != TARGET_HALTED)
|
||||||
{
|
|
||||||
return ERROR_TARGET_NOT_HALTED;
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
}
|
|
||||||
|
|
||||||
buf_set_u32(reg->value, 0, 32, value);
|
buf_set_u32(reg->value, 0, 32, value);
|
||||||
reg->dirty = 1;
|
reg->dirty = 1;
|
||||||
|
@ -220,14 +210,17 @@ static int armv7m_read_core_reg(struct target *target, unsigned num)
|
||||||
{
|
{
|
||||||
uint32_t reg_value;
|
uint32_t reg_value;
|
||||||
int retval;
|
int retval;
|
||||||
struct armv7m_core_reg * armv7m_core_reg;
|
struct armv7m_core_reg *armv7m_core_reg;
|
||||||
struct armv7m_common *armv7m = target_to_armv7m(target);
|
struct armv7m_common *armv7m = target_to_armv7m(target);
|
||||||
|
|
||||||
if (num >= ARMV7M_NUM_REGS)
|
if (num >= ARMV7M_NUM_REGS)
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
|
|
||||||
armv7m_core_reg = armv7m->core_cache->reg_list[num].arch_info;
|
armv7m_core_reg = armv7m->core_cache->reg_list[num].arch_info;
|
||||||
retval = armv7m->load_core_reg_u32(target, armv7m_core_reg->type, armv7m_core_reg->num, ®_value);
|
retval = armv7m->load_core_reg_u32(target,
|
||||||
|
armv7m_core_reg->type,
|
||||||
|
armv7m_core_reg->num,
|
||||||
|
®_value);
|
||||||
buf_set_u32(armv7m->core_cache->reg_list[num].value, 0, 32, reg_value);
|
buf_set_u32(armv7m->core_cache->reg_list[num].value, 0, 32, reg_value);
|
||||||
armv7m->core_cache->reg_list[num].valid = 1;
|
armv7m->core_cache->reg_list[num].valid = 1;
|
||||||
armv7m->core_cache->reg_list[num].dirty = 0;
|
armv7m->core_cache->reg_list[num].dirty = 0;
|
||||||
|
@ -247,14 +240,16 @@ static int armv7m_write_core_reg(struct target *target, unsigned num)
|
||||||
|
|
||||||
reg_value = buf_get_u32(armv7m->core_cache->reg_list[num].value, 0, 32);
|
reg_value = buf_get_u32(armv7m->core_cache->reg_list[num].value, 0, 32);
|
||||||
armv7m_core_reg = armv7m->core_cache->reg_list[num].arch_info;
|
armv7m_core_reg = armv7m->core_cache->reg_list[num].arch_info;
|
||||||
retval = armv7m->store_core_reg_u32(target, armv7m_core_reg->type, armv7m_core_reg->num, reg_value);
|
retval = armv7m->store_core_reg_u32(target,
|
||||||
if (retval != ERROR_OK)
|
armv7m_core_reg->type,
|
||||||
{
|
armv7m_core_reg->num,
|
||||||
|
reg_value);
|
||||||
|
if (retval != ERROR_OK) {
|
||||||
LOG_ERROR("JTAG failure");
|
LOG_ERROR("JTAG failure");
|
||||||
armv7m->core_cache->reg_list[num].dirty = armv7m->core_cache->reg_list[num].valid;
|
armv7m->core_cache->reg_list[num].dirty = armv7m->core_cache->reg_list[num].valid;
|
||||||
return ERROR_JTAG_DEVICE_ERROR;
|
return ERROR_JTAG_DEVICE_ERROR;
|
||||||
}
|
}
|
||||||
LOG_DEBUG("write core reg %i value 0x%" PRIx32 "", num , reg_value);
|
LOG_DEBUG("write core reg %i value 0x%" PRIx32 "", num, reg_value);
|
||||||
armv7m->core_cache->reg_list[num].valid = 1;
|
armv7m->core_cache->reg_list[num].valid = 1;
|
||||||
armv7m->core_cache->reg_list[num].dirty = 0;
|
armv7m->core_cache->reg_list[num].dirty = 0;
|
||||||
|
|
||||||
|
@ -273,7 +268,7 @@ int armv7m_get_gdb_reg_list(struct target *target, struct reg **reg_list[], int
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
*reg_list_size = 26;
|
*reg_list_size = 26;
|
||||||
*reg_list = malloc(sizeof(struct reg*) * (*reg_list_size));
|
*reg_list = malloc(sizeof(struct reg *) * (*reg_list_size));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* GDB register packet format for ARM:
|
* GDB register packet format for ARM:
|
||||||
|
@ -283,9 +278,7 @@ int armv7m_get_gdb_reg_list(struct target *target, struct reg **reg_list[], int
|
||||||
* - CPSR
|
* - CPSR
|
||||||
*/
|
*/
|
||||||
for (i = 0; i < 16; i++)
|
for (i = 0; i < 16; i++)
|
||||||
{
|
|
||||||
(*reg_list)[i] = &armv7m->core_cache->reg_list[i];
|
(*reg_list)[i] = &armv7m->core_cache->reg_list[i];
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 16; i < 24; i++)
|
for (i = 16; i < 24; i++)
|
||||||
(*reg_list)[i] = &arm_gdb_dummy_fp_reg;
|
(*reg_list)[i] = &arm_gdb_dummy_fp_reg;
|
||||||
|
@ -297,7 +290,7 @@ int armv7m_get_gdb_reg_list(struct target *target, struct reg **reg_list[], int
|
||||||
|
|
||||||
/* ARMV7M is always in thumb mode, try to make GDB understand this
|
/* ARMV7M is always in thumb mode, try to make GDB understand this
|
||||||
* if it does not support this arch */
|
* if it does not support this arch */
|
||||||
*((char*)armv7m->arm.pc->value) |= 1;
|
*((char *)armv7m->arm.pc->value) |= 1;
|
||||||
#else
|
#else
|
||||||
(*reg_list)[25] = &armv7m->core_cache->reg_list[ARMV7M_xPSR];
|
(*reg_list)[25] = &armv7m->core_cache->reg_list[ARMV7M_xPSR];
|
||||||
#endif
|
#endif
|
||||||
|
@ -345,60 +338,60 @@ int armv7m_start_algorithm(struct target *target,
|
||||||
/* NOTE: armv7m_run_algorithm requires that each algorithm uses a software breakpoint
|
/* NOTE: armv7m_run_algorithm requires that each algorithm uses a software breakpoint
|
||||||
* at the exit point */
|
* at the exit point */
|
||||||
|
|
||||||
if (armv7m_algorithm_info->common_magic != ARMV7M_COMMON_MAGIC)
|
if (armv7m_algorithm_info->common_magic != ARMV7M_COMMON_MAGIC) {
|
||||||
{
|
|
||||||
LOG_ERROR("current target isn't an ARMV7M target");
|
LOG_ERROR("current target isn't an ARMV7M target");
|
||||||
return ERROR_TARGET_INVALID;
|
return ERROR_TARGET_INVALID;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (target->state != TARGET_HALTED)
|
if (target->state != TARGET_HALTED) {
|
||||||
{
|
|
||||||
LOG_WARNING("target not halted");
|
LOG_WARNING("target not halted");
|
||||||
return ERROR_TARGET_NOT_HALTED;
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* refresh core register cache */
|
/* refresh core register cache
|
||||||
/* Not needed if core register cache is always consistent with target process state */
|
* Not needed if core register cache is always consistent with target process state */
|
||||||
for (unsigned i = 0; i < ARMV7M_NUM_REGS; i++)
|
for (unsigned i = 0; i < ARMV7M_NUM_REGS; i++) {
|
||||||
{
|
|
||||||
if (!armv7m->core_cache->reg_list[i].valid)
|
if (!armv7m->core_cache->reg_list[i].valid)
|
||||||
armv7m->read_core_reg(target, i);
|
armv7m->read_core_reg(target, i);
|
||||||
armv7m_algorithm_info->context[i] = buf_get_u32(armv7m->core_cache->reg_list[i].value, 0, 32);
|
armv7m_algorithm_info->context[i] = buf_get_u32(
|
||||||
|
armv7m->core_cache->reg_list[i].value,
|
||||||
|
0,
|
||||||
|
32);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < num_mem_params; i++)
|
for (int i = 0; i < num_mem_params; i++) {
|
||||||
{
|
/* TODO: Write only out params */
|
||||||
// TODO: Write only out params
|
retval = target_write_buffer(target, mem_params[i].address,
|
||||||
if ((retval = target_write_buffer(target, mem_params[i].address, mem_params[i].size, mem_params[i].value)) != ERROR_OK)
|
mem_params[i].size,
|
||||||
|
mem_params[i].value);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < num_reg_params; i++)
|
for (int i = 0; i < num_reg_params; i++) {
|
||||||
{
|
struct reg *reg =
|
||||||
struct reg *reg = register_get_by_name(armv7m->core_cache, reg_params[i].reg_name, 0);
|
register_get_by_name(armv7m->core_cache, reg_params[i].reg_name, 0);
|
||||||
// uint32_t regvalue;
|
/* uint32_t regvalue; */
|
||||||
|
|
||||||
if (!reg)
|
if (!reg) {
|
||||||
{
|
|
||||||
LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name);
|
LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name);
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (reg->size != reg_params[i].size)
|
if (reg->size != reg_params[i].size) {
|
||||||
{
|
LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size",
|
||||||
LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size", reg_params[i].reg_name);
|
reg_params[i].reg_name);
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
// regvalue = buf_get_u32(reg_params[i].value, 0, 32);
|
/* regvalue = buf_get_u32(reg_params[i].value, 0, 32); */
|
||||||
armv7m_set_core_reg(reg, reg_params[i].value);
|
armv7m_set_core_reg(reg, reg_params[i].value);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (armv7m_algorithm_info->core_mode != ARMV7M_MODE_ANY)
|
if (armv7m_algorithm_info->core_mode != ARMV7M_MODE_ANY) {
|
||||||
{
|
|
||||||
LOG_DEBUG("setting core_mode: 0x%2.2x", armv7m_algorithm_info->core_mode);
|
LOG_DEBUG("setting core_mode: 0x%2.2x", armv7m_algorithm_info->core_mode);
|
||||||
buf_set_u32(armv7m->core_cache->reg_list[ARMV7M_CONTROL].value,
|
buf_set_u32(armv7m->core_cache->reg_list[ARMV7M_CONTROL].value,
|
||||||
0, 1, armv7m_algorithm_info->core_mode);
|
0, 1, armv7m_algorithm_info->core_mode);
|
||||||
armv7m->core_cache->reg_list[ARMV7M_CONTROL].dirty = 1;
|
armv7m->core_cache->reg_list[ARMV7M_CONTROL].dirty = 1;
|
||||||
armv7m->core_cache->reg_list[ARMV7M_CONTROL].valid = 1;
|
armv7m->core_cache->reg_list[ARMV7M_CONTROL].valid = 1;
|
||||||
}
|
}
|
||||||
|
@ -424,58 +417,58 @@ int armv7m_wait_algorithm(struct target *target,
|
||||||
/* NOTE: armv7m_run_algorithm requires that each algorithm uses a software breakpoint
|
/* NOTE: armv7m_run_algorithm requires that each algorithm uses a software breakpoint
|
||||||
* at the exit point */
|
* at the exit point */
|
||||||
|
|
||||||
if (armv7m_algorithm_info->common_magic != ARMV7M_COMMON_MAGIC)
|
if (armv7m_algorithm_info->common_magic != ARMV7M_COMMON_MAGIC) {
|
||||||
{
|
|
||||||
LOG_ERROR("current target isn't an ARMV7M target");
|
LOG_ERROR("current target isn't an ARMV7M target");
|
||||||
return ERROR_TARGET_INVALID;
|
return ERROR_TARGET_INVALID;
|
||||||
}
|
}
|
||||||
|
|
||||||
retval = target_wait_state(target, TARGET_HALTED, timeout_ms);
|
retval = target_wait_state(target, TARGET_HALTED, timeout_ms);
|
||||||
/* If the target fails to halt due to the breakpoint, force a halt */
|
/* If the target fails to halt due to the breakpoint, force a halt */
|
||||||
if (retval != ERROR_OK || target->state != TARGET_HALTED)
|
if (retval != ERROR_OK || target->state != TARGET_HALTED) {
|
||||||
{
|
retval = target_halt(target);
|
||||||
if ((retval = target_halt(target)) != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
if ((retval = target_wait_state(target, TARGET_HALTED, 500)) != ERROR_OK)
|
retval = target_wait_state(target, TARGET_HALTED, 500);
|
||||||
{
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
|
||||||
return ERROR_TARGET_TIMEOUT;
|
return ERROR_TARGET_TIMEOUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
armv7m->load_core_reg_u32(target, ARMV7M_REGISTER_CORE_GP, 15, &pc);
|
armv7m->load_core_reg_u32(target, ARMV7M_REGISTER_CORE_GP, 15, &pc);
|
||||||
if (exit_point && (pc != exit_point))
|
if (exit_point && (pc != exit_point)) {
|
||||||
{
|
LOG_DEBUG("failed algorithm halted at 0x%" PRIx32 ", expected 0x%" PRIx32,
|
||||||
LOG_DEBUG("failed algorithm halted at 0x%" PRIx32 ", expected 0x%" PRIx32 , pc, exit_point);
|
pc,
|
||||||
|
exit_point);
|
||||||
return ERROR_TARGET_TIMEOUT;
|
return ERROR_TARGET_TIMEOUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read memory values to mem_params[] */
|
/* Read memory values to mem_params[] */
|
||||||
for (int i = 0; i < num_mem_params; i++)
|
for (int i = 0; i < num_mem_params; i++) {
|
||||||
{
|
if (mem_params[i].direction != PARAM_OUT) {
|
||||||
if (mem_params[i].direction != PARAM_OUT)
|
retval = target_read_buffer(target, mem_params[i].address,
|
||||||
if ((retval = target_read_buffer(target, mem_params[i].address, mem_params[i].size, mem_params[i].value)) != ERROR_OK)
|
mem_params[i].size,
|
||||||
{
|
mem_params[i].value);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Copy core register values to reg_params[] */
|
/* Copy core register values to reg_params[] */
|
||||||
for (int i = 0; i < num_reg_params; i++)
|
for (int i = 0; i < num_reg_params; i++) {
|
||||||
{
|
if (reg_params[i].direction != PARAM_OUT) {
|
||||||
if (reg_params[i].direction != PARAM_OUT)
|
struct reg *reg = register_get_by_name(armv7m->core_cache,
|
||||||
{
|
reg_params[i].reg_name,
|
||||||
struct reg *reg = register_get_by_name(armv7m->core_cache, reg_params[i].reg_name, 0);
|
0);
|
||||||
|
|
||||||
if (!reg)
|
if (!reg) {
|
||||||
{
|
|
||||||
LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name);
|
LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name);
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (reg->size != reg_params[i].size)
|
if (reg->size != reg_params[i].size) {
|
||||||
{
|
LOG_ERROR(
|
||||||
LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size", reg_params[i].reg_name);
|
"BUG: register '%s' size doesn't match reg_params[i].size",
|
||||||
|
reg_params[i].reg_name);
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -483,16 +476,15 @@ int armv7m_wait_algorithm(struct target *target,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = ARMV7M_NUM_REGS - 1; i >= 0; i--)
|
for (int i = ARMV7M_NUM_REGS - 1; i >= 0; i--) {
|
||||||
{
|
|
||||||
uint32_t regvalue;
|
uint32_t regvalue;
|
||||||
regvalue = buf_get_u32(armv7m->core_cache->reg_list[i].value, 0, 32);
|
regvalue = buf_get_u32(armv7m->core_cache->reg_list[i].value, 0, 32);
|
||||||
if (regvalue != armv7m_algorithm_info->context[i])
|
if (regvalue != armv7m_algorithm_info->context[i]) {
|
||||||
{
|
|
||||||
LOG_DEBUG("restoring register %s with value 0x%8.8" PRIx32,
|
LOG_DEBUG("restoring register %s with value 0x%8.8" PRIx32,
|
||||||
armv7m->core_cache->reg_list[i].name, armv7m_algorithm_info->context[i]);
|
armv7m->core_cache->reg_list[i].name,
|
||||||
|
armv7m_algorithm_info->context[i]);
|
||||||
buf_set_u32(armv7m->core_cache->reg_list[i].value,
|
buf_set_u32(armv7m->core_cache->reg_list[i].value,
|
||||||
0, 32, armv7m_algorithm_info->context[i]);
|
0, 32, armv7m_algorithm_info->context[i]);
|
||||||
armv7m->core_cache->reg_list[i].valid = 1;
|
armv7m->core_cache->reg_list[i].valid = 1;
|
||||||
armv7m->core_cache->reg_list[i].dirty = 1;
|
armv7m->core_cache->reg_list[i].dirty = 1;
|
||||||
}
|
}
|
||||||
|
@ -555,8 +547,7 @@ struct reg_cache *armv7m_build_reg_cache(struct target *target)
|
||||||
(*cache_p) = cache;
|
(*cache_p) = cache;
|
||||||
armv7m->core_cache = cache;
|
armv7m->core_cache = cache;
|
||||||
|
|
||||||
for (i = 0; i < num_regs; i++)
|
for (i = 0; i < num_regs; i++) {
|
||||||
{
|
|
||||||
arch_info[i].num = armv7m_regs[i].id;
|
arch_info[i].num = armv7m_regs[i].id;
|
||||||
arch_info[i].target = target;
|
arch_info[i].target = target;
|
||||||
arch_info[i].armv7m_common = armv7m;
|
arch_info[i].armv7m_common = armv7m;
|
||||||
|
@ -603,7 +594,7 @@ int armv7m_init_arch_info(struct target *target, struct armv7m_common *armv7m)
|
||||||
|
|
||||||
/** Generates a CRC32 checksum of a memory region. */
|
/** Generates a CRC32 checksum of a memory region. */
|
||||||
int armv7m_checksum_memory(struct target *target,
|
int armv7m_checksum_memory(struct target *target,
|
||||||
uint32_t address, uint32_t count, uint32_t* checksum)
|
uint32_t address, uint32_t count, uint32_t *checksum)
|
||||||
{
|
{
|
||||||
struct working_area *crc_algorithm;
|
struct working_area *crc_algorithm;
|
||||||
struct armv7m_algorithm armv7m_info;
|
struct armv7m_algorithm armv7m_info;
|
||||||
|
@ -618,27 +609,27 @@ int armv7m_checksum_memory(struct target *target,
|
||||||
0x460B, /* mov r3, r1 */
|
0x460B, /* mov r3, r1 */
|
||||||
0xF04F, 0x0400, /* mov r4, #0 */
|
0xF04F, 0x0400, /* mov r4, #0 */
|
||||||
0xE013, /* b ncomp */
|
0xE013, /* b ncomp */
|
||||||
/* nbyte: */
|
/* nbyte: */
|
||||||
0x5D11, /* ldrb r1, [r2, r4] */
|
0x5D11, /* ldrb r1, [r2, r4] */
|
||||||
0xF8DF, 0x7028, /* ldr r7, CRC32XOR */
|
0xF8DF, 0x7028, /* ldr r7, CRC32XOR */
|
||||||
0xEA80, 0x6001, /* eor r0, r0, r1, asl #24 */
|
0xEA80, 0x6001, /* eor r0, r0, r1, asl #24 */
|
||||||
|
|
||||||
0xF04F, 0x0500, /* mov r5, #0 */
|
0xF04F, 0x0500, /* mov r5, #0 */
|
||||||
/* loop: */
|
/* loop: */
|
||||||
0x2800, /* cmp r0, #0 */
|
0x2800, /* cmp r0, #0 */
|
||||||
0xEA4F, 0x0640, /* mov r6, r0, asl #1 */
|
0xEA4F, 0x0640, /* mov r6, r0, asl #1 */
|
||||||
0xF105, 0x0501, /* add r5, r5, #1 */
|
0xF105, 0x0501, /* add r5, r5, #1 */
|
||||||
0x4630, /* mov r0, r6 */
|
0x4630, /* mov r0, r6 */
|
||||||
0xBFB8, /* it lt */
|
0xBFB8, /* it lt */
|
||||||
0xEA86, 0x0007, /* eor r0, r6, r7 */
|
0xEA86, 0x0007, /* eor r0, r6, r7 */
|
||||||
0x2D08, /* cmp r5, #8 */
|
0x2D08, /* cmp r5, #8 */
|
||||||
0xD1F4, /* bne loop */
|
0xD1F4, /* bne loop */
|
||||||
|
|
||||||
0xF104, 0x0401, /* add r4, r4, #1 */
|
0xF104, 0x0401, /* add r4, r4, #1 */
|
||||||
/* ncomp: */
|
/* ncomp: */
|
||||||
0x429C, /* cmp r4, r3 */
|
0x429C, /* cmp r4, r3 */
|
||||||
0xD1E9, /* bne nbyte */
|
0xD1E9, /* bne nbyte */
|
||||||
0xBE00, /* bkpt #0 */
|
0xBE00, /* bkpt #0 */
|
||||||
0x1DB7, 0x04C1 /* CRC32XOR: .word 0x04C11DB7 */
|
0x1DB7, 0x04C1 /* CRC32XOR: .word 0x04C11DB7 */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -650,7 +641,9 @@ int armv7m_checksum_memory(struct target *target,
|
||||||
|
|
||||||
/* convert flash writing code into a buffer in target endianness */
|
/* convert flash writing code into a buffer in target endianness */
|
||||||
for (i = 0; i < ARRAY_SIZE(cortex_m3_crc_code); i++) {
|
for (i = 0; i < ARRAY_SIZE(cortex_m3_crc_code); i++) {
|
||||||
retval = target_write_u16(target, crc_algorithm->address + i*sizeof(uint16_t), cortex_m3_crc_code[i]);
|
retval = target_write_u16(target,
|
||||||
|
crc_algorithm->address + i*sizeof(uint16_t),
|
||||||
|
cortex_m3_crc_code[i]);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
@ -667,8 +660,8 @@ int armv7m_checksum_memory(struct target *target,
|
||||||
int timeout = 20000 * (1 + (count / (1024 * 1024)));
|
int timeout = 20000 * (1 + (count / (1024 * 1024)));
|
||||||
|
|
||||||
retval = target_run_algorithm(target, 0, NULL, 2, reg_params, crc_algorithm->address,
|
retval = target_run_algorithm(target, 0, NULL, 2, reg_params, crc_algorithm->address,
|
||||||
crc_algorithm->address + (sizeof(cortex_m3_crc_code) - 6),
|
crc_algorithm->address + (sizeof(cortex_m3_crc_code) - 6),
|
||||||
timeout, &armv7m_info);
|
timeout, &armv7m_info);
|
||||||
|
|
||||||
if (retval == ERROR_OK)
|
if (retval == ERROR_OK)
|
||||||
*checksum = buf_get_u32(reg_params[0].value, 0, 32);
|
*checksum = buf_get_u32(reg_params[0].value, 0, 32);
|
||||||
|
@ -686,7 +679,7 @@ cleanup:
|
||||||
|
|
||||||
/** Checks whether a memory region is zeroed. */
|
/** Checks whether a memory region is zeroed. */
|
||||||
int armv7m_blank_check_memory(struct target *target,
|
int armv7m_blank_check_memory(struct target *target,
|
||||||
uint32_t address, uint32_t count, uint32_t* blank)
|
uint32_t address, uint32_t count, uint32_t *blank)
|
||||||
{
|
{
|
||||||
struct working_area *erase_check_algorithm;
|
struct working_area *erase_check_algorithm;
|
||||||
struct reg_param reg_params[3];
|
struct reg_param reg_params[3];
|
||||||
|
@ -694,25 +687,25 @@ int armv7m_blank_check_memory(struct target *target,
|
||||||
int retval;
|
int retval;
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
|
|
||||||
static const uint16_t erase_check_code[] =
|
static const uint16_t erase_check_code[] = {
|
||||||
{
|
|
||||||
/* loop: */
|
/* loop: */
|
||||||
0xF810, 0x3B01, /* ldrb r3, [r0], #1 */
|
0xF810, 0x3B01, /* ldrb r3, [r0], #1 */
|
||||||
0xEA02, 0x0203, /* and r2, r2, r3 */
|
0xEA02, 0x0203, /* and r2, r2, r3 */
|
||||||
0x3901, /* subs r1, r1, #1 */
|
0x3901, /* subs r1, r1, #1 */
|
||||||
0xD1F9, /* bne loop */
|
0xD1F9, /* bne loop */
|
||||||
0xBE00, /* bkpt #0 */
|
0xBE00, /* bkpt #0 */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* make sure we have a working area */
|
/* make sure we have a working area */
|
||||||
if (target_alloc_working_area(target, sizeof(erase_check_code), &erase_check_algorithm) != ERROR_OK)
|
if (target_alloc_working_area(target, sizeof(erase_check_code),
|
||||||
{
|
&erase_check_algorithm) != ERROR_OK)
|
||||||
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
|
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
|
||||||
}
|
|
||||||
|
|
||||||
/* convert flash writing code into a buffer in target endianness */
|
/* convert flash writing code into a buffer in target endianness */
|
||||||
for (i = 0; i < ARRAY_SIZE(erase_check_code); i++)
|
for (i = 0; i < ARRAY_SIZE(erase_check_code); i++)
|
||||||
target_write_u16(target, erase_check_algorithm->address + i*sizeof(uint16_t), erase_check_code[i]);
|
target_write_u16(target,
|
||||||
|
erase_check_algorithm->address + i*sizeof(uint16_t),
|
||||||
|
erase_check_code[i]);
|
||||||
|
|
||||||
armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
|
armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
|
||||||
armv7m_info.core_mode = ARMV7M_MODE_ANY;
|
armv7m_info.core_mode = ARMV7M_MODE_ANY;
|
||||||
|
@ -726,9 +719,15 @@ int armv7m_blank_check_memory(struct target *target,
|
||||||
init_reg_param(®_params[2], "r2", 32, PARAM_IN_OUT);
|
init_reg_param(®_params[2], "r2", 32, PARAM_IN_OUT);
|
||||||
buf_set_u32(reg_params[2].value, 0, 32, 0xff);
|
buf_set_u32(reg_params[2].value, 0, 32, 0xff);
|
||||||
|
|
||||||
retval = target_run_algorithm(target, 0, NULL, 3, reg_params, erase_check_algorithm->address,
|
retval = target_run_algorithm(target,
|
||||||
erase_check_algorithm->address + (sizeof(erase_check_code) - 2),
|
0,
|
||||||
10000, &armv7m_info);
|
NULL,
|
||||||
|
3,
|
||||||
|
reg_params,
|
||||||
|
erase_check_algorithm->address,
|
||||||
|
erase_check_algorithm->address + (sizeof(erase_check_code) - 2),
|
||||||
|
10000,
|
||||||
|
&armv7m_info);
|
||||||
|
|
||||||
if (retval == ERROR_OK)
|
if (retval == ERROR_OK)
|
||||||
*blank = buf_get_u32(reg_params[2].value, 0, 32);
|
*blank = buf_get_u32(reg_params[2].value, 0, 32);
|
||||||
|
@ -753,16 +752,13 @@ int armv7m_maybe_skip_bkpt_inst(struct target *target, bool *inst_found)
|
||||||
* then we have to manually step over it, otherwise
|
* then we have to manually step over it, otherwise
|
||||||
* the core will break again */
|
* the core will break again */
|
||||||
|
|
||||||
if (target->debug_reason == DBG_REASON_BREAKPOINT)
|
if (target->debug_reason == DBG_REASON_BREAKPOINT) {
|
||||||
{
|
|
||||||
uint16_t op;
|
uint16_t op;
|
||||||
uint32_t pc = buf_get_u32(r->value, 0, 32);
|
uint32_t pc = buf_get_u32(r->value, 0, 32);
|
||||||
|
|
||||||
pc &= ~1;
|
pc &= ~1;
|
||||||
if (target_read_u16(target, pc, &op) == ERROR_OK)
|
if (target_read_u16(target, pc, &op) == ERROR_OK) {
|
||||||
{
|
if ((op & 0xFF00) == 0xBE00) {
|
||||||
if ((op & 0xFF00) == 0xBE00)
|
|
||||||
{
|
|
||||||
pc = buf_get_u32(r->value, 0, 32) + 2;
|
pc = buf_get_u32(r->value, 0, 32) + 2;
|
||||||
buf_set_u32(r->value, 0, 32, pc);
|
buf_set_u32(r->value, 0, 32, pc);
|
||||||
r->dirty = true;
|
r->dirty = true;
|
||||||
|
@ -773,9 +769,8 @@ int armv7m_maybe_skip_bkpt_inst(struct target *target, bool *inst_found)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inst_found) {
|
if (inst_found)
|
||||||
*inst_found = result;
|
*inst_found = result;
|
||||||
}
|
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
* Free Software Foundation, Inc., *
|
* Free Software Foundation, Inc., *
|
||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#ifndef ARMV7M_COMMON_H
|
#ifndef ARMV7M_COMMON_H
|
||||||
#define ARMV7M_COMMON_H
|
#define ARMV7M_COMMON_H
|
||||||
|
|
||||||
|
@ -39,9 +40,7 @@ extern uint8_t armv7m_gdb_dummy_cpsr_value[];
|
||||||
extern struct reg armv7m_gdb_dummy_cpsr_reg;
|
extern struct reg armv7m_gdb_dummy_cpsr_reg;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
enum armv7m_mode {
|
||||||
enum armv7m_mode
|
|
||||||
{
|
|
||||||
ARMV7M_MODE_THREAD = 0,
|
ARMV7M_MODE_THREAD = 0,
|
||||||
ARMV7M_MODE_USER_THREAD = 1,
|
ARMV7M_MODE_USER_THREAD = 1,
|
||||||
ARMV7M_MODE_HANDLER = 2,
|
ARMV7M_MODE_HANDLER = 2,
|
||||||
|
@ -52,8 +51,7 @@ extern char *armv7m_mode_strings[];
|
||||||
extern const int armv7m_psp_reg_map[];
|
extern const int armv7m_psp_reg_map[];
|
||||||
extern const int armv7m_msp_reg_map[];
|
extern const int armv7m_msp_reg_map[];
|
||||||
|
|
||||||
enum armv7m_regtype
|
enum armv7m_regtype {
|
||||||
{
|
|
||||||
ARMV7M_REGISTER_CORE_GP,
|
ARMV7M_REGISTER_CORE_GP,
|
||||||
ARMV7M_REGISTER_CORE_SP,
|
ARMV7M_REGISTER_CORE_SP,
|
||||||
ARMV7M_REGISTER_MEMMAP
|
ARMV7M_REGISTER_MEMMAP
|
||||||
|
@ -62,8 +60,7 @@ enum armv7m_regtype
|
||||||
char *armv7m_exception_string(int number);
|
char *armv7m_exception_string(int number);
|
||||||
|
|
||||||
/* offsets into armv7m core register cache */
|
/* offsets into armv7m core register cache */
|
||||||
enum
|
enum {
|
||||||
{
|
|
||||||
/* for convenience, the first set of indices match
|
/* for convenience, the first set of indices match
|
||||||
* the Cortex-M3 DCRSR selectors
|
* the Cortex-M3 DCRSR selectors
|
||||||
*/
|
*/
|
||||||
|
@ -100,8 +97,7 @@ enum
|
||||||
|
|
||||||
#define ARMV7M_COMMON_MAGIC 0x2A452A45
|
#define ARMV7M_COMMON_MAGIC 0x2A452A45
|
||||||
|
|
||||||
struct armv7m_common
|
struct armv7m_common {
|
||||||
{
|
|
||||||
struct arm arm;
|
struct arm arm;
|
||||||
|
|
||||||
int common_magic;
|
int common_magic;
|
||||||
|
@ -139,17 +135,15 @@ static inline bool is_armv7m(struct armv7m_common *armv7m)
|
||||||
return armv7m->common_magic == ARMV7M_COMMON_MAGIC;
|
return armv7m->common_magic == ARMV7M_COMMON_MAGIC;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct armv7m_algorithm
|
struct armv7m_algorithm {
|
||||||
{
|
|
||||||
int common_magic;
|
int common_magic;
|
||||||
|
|
||||||
enum armv7m_mode core_mode;
|
enum armv7m_mode core_mode;
|
||||||
|
|
||||||
uint32_t context[ARMV7M_CONTROL + 1]; //ARMV7M_NUM_REGS
|
uint32_t context[ARMV7M_CONTROL + 1]; /* ARMV7M_NUM_REGS */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct armv7m_core_reg
|
struct armv7m_core_reg {
|
||||||
{
|
|
||||||
uint32_t num;
|
uint32_t num;
|
||||||
enum armv7m_regtype type;
|
enum armv7m_regtype type;
|
||||||
struct target *target;
|
struct target *target;
|
||||||
|
@ -189,9 +183,9 @@ int armv7m_invalidate_core_regs(struct target *target);
|
||||||
int armv7m_restore_context(struct target *target);
|
int armv7m_restore_context(struct target *target);
|
||||||
|
|
||||||
int armv7m_checksum_memory(struct target *target,
|
int armv7m_checksum_memory(struct target *target,
|
||||||
uint32_t address, uint32_t count, uint32_t* checksum);
|
uint32_t address, uint32_t count, uint32_t *checksum);
|
||||||
int armv7m_blank_check_memory(struct target *target,
|
int armv7m_blank_check_memory(struct target *target,
|
||||||
uint32_t address, uint32_t count, uint32_t* blank);
|
uint32_t address, uint32_t count, uint32_t *blank);
|
||||||
|
|
||||||
int armv7m_maybe_skip_bkpt_inst(struct target *target, bool *inst_found);
|
int armv7m_maybe_skip_bkpt_inst(struct target *target, bool *inst_found);
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
* Free Software Foundation, Inc., *
|
* Free Software Foundation, Inc., *
|
||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -34,15 +35,13 @@
|
||||||
#include "avr32_regs.h"
|
#include "avr32_regs.h"
|
||||||
#include "avr32_ap7k.h"
|
#include "avr32_ap7k.h"
|
||||||
|
|
||||||
static char* avr32_core_reg_list[] =
|
static char *avr32_core_reg_list[] = {
|
||||||
{
|
"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8",
|
||||||
"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8",
|
|
||||||
"r9", "r10", "r11", "r12", "sp", "lr", "pc", "sr"
|
"r9", "r10", "r11", "r12", "sp", "lr", "pc", "sr"
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct avr32_core_reg
|
static struct avr32_core_reg
|
||||||
avr32_core_reg_list_arch_info[AVR32NUMCOREREGS] =
|
avr32_core_reg_list_arch_info[AVR32NUMCOREREGS] = {
|
||||||
{
|
|
||||||
{0, NULL, NULL},
|
{0, NULL, NULL},
|
||||||
{1, NULL, NULL},
|
{1, NULL, NULL},
|
||||||
{2, NULL, NULL},
|
{2, NULL, NULL},
|
||||||
|
@ -75,12 +74,9 @@ int avr32_ap7k_save_context(struct target *target)
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
for (i = 0; i < AVR32NUMCOREREGS; i++)
|
for (i = 0; i < AVR32NUMCOREREGS; i++) {
|
||||||
{
|
|
||||||
if (!ap7k->core_cache->reg_list[i].valid)
|
if (!ap7k->core_cache->reg_list[i].valid)
|
||||||
{
|
|
||||||
avr32_read_core_reg(target, i);
|
avr32_read_core_reg(target, i);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
|
@ -93,12 +89,9 @@ int avr32_ap7k_restore_context(struct target *target)
|
||||||
/* get pointers to arch-specific information */
|
/* get pointers to arch-specific information */
|
||||||
struct avr32_ap7k_common *ap7k = target_to_ap7k(target);
|
struct avr32_ap7k_common *ap7k = target_to_ap7k(target);
|
||||||
|
|
||||||
for (i = 0; i < AVR32NUMCOREREGS; i++)
|
for (i = 0; i < AVR32NUMCOREREGS; i++) {
|
||||||
{
|
|
||||||
if (ap7k->core_cache->reg_list[i].dirty)
|
if (ap7k->core_cache->reg_list[i].dirty)
|
||||||
{
|
|
||||||
avr32_write_core_reg(target, i);
|
avr32_write_core_reg(target, i);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* write core regs */
|
/* write core regs */
|
||||||
|
@ -137,7 +130,7 @@ static int avr32_write_core_reg(struct target *target, int num)
|
||||||
|
|
||||||
reg_value = buf_get_u32(ap7k->core_cache->reg_list[num].value, 0, 32);
|
reg_value = buf_get_u32(ap7k->core_cache->reg_list[num].value, 0, 32);
|
||||||
ap7k->core_regs[num] = reg_value;
|
ap7k->core_regs[num] = reg_value;
|
||||||
LOG_DEBUG("write core reg %i value 0x%" PRIx32 "", num , reg_value);
|
LOG_DEBUG("write core reg %i value 0x%" PRIx32 "", num, reg_value);
|
||||||
ap7k->core_cache->reg_list[num].valid = 1;
|
ap7k->core_cache->reg_list[num].valid = 1;
|
||||||
ap7k->core_cache->reg_list[num].dirty = 0;
|
ap7k->core_cache->reg_list[num].dirty = 0;
|
||||||
|
|
||||||
|
@ -151,9 +144,7 @@ static int avr32_get_core_reg(struct reg *reg)
|
||||||
struct target *target = avr32_reg->target;
|
struct target *target = avr32_reg->target;
|
||||||
|
|
||||||
if (target->state != TARGET_HALTED)
|
if (target->state != TARGET_HALTED)
|
||||||
{
|
|
||||||
return ERROR_TARGET_NOT_HALTED;
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
}
|
|
||||||
|
|
||||||
retval = avr32_read_core_reg(target, avr32_reg->num);
|
retval = avr32_read_core_reg(target, avr32_reg->num);
|
||||||
|
|
||||||
|
@ -167,9 +158,7 @@ static int avr32_set_core_reg(struct reg *reg, uint8_t *buf)
|
||||||
uint32_t value = buf_get_u32(buf, 0, 32);
|
uint32_t value = buf_get_u32(buf, 0, 32);
|
||||||
|
|
||||||
if (target->state != TARGET_HALTED)
|
if (target->state != TARGET_HALTED)
|
||||||
{
|
|
||||||
return ERROR_TARGET_NOT_HALTED;
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
}
|
|
||||||
|
|
||||||
buf_set_u32(reg->value, 0, 32, value);
|
buf_set_u32(reg->value, 0, 32, value);
|
||||||
reg->dirty = 1;
|
reg->dirty = 1;
|
||||||
|
@ -190,7 +179,7 @@ static struct reg_cache *avr32_build_reg_cache(struct target *target)
|
||||||
struct reg_cache **cache_p = register_get_last_cache_p(&target->reg_cache);
|
struct reg_cache **cache_p = register_get_last_cache_p(&target->reg_cache);
|
||||||
struct reg_cache *cache = malloc(sizeof(struct reg_cache));
|
struct reg_cache *cache = malloc(sizeof(struct reg_cache));
|
||||||
struct reg *reg_list = malloc(sizeof(struct reg) * num_regs);
|
struct reg *reg_list = malloc(sizeof(struct reg) * num_regs);
|
||||||
struct avr32_core_reg *arch_info =
|
struct avr32_core_reg *arch_info =
|
||||||
malloc(sizeof(struct avr32_core_reg) * num_regs);
|
malloc(sizeof(struct avr32_core_reg) * num_regs);
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
@ -202,8 +191,7 @@ static struct reg_cache *avr32_build_reg_cache(struct target *target)
|
||||||
(*cache_p) = cache;
|
(*cache_p) = cache;
|
||||||
ap7k->core_cache = cache;
|
ap7k->core_cache = cache;
|
||||||
|
|
||||||
for (i = 0; i < num_regs; i++)
|
for (i = 0; i < num_regs; i++) {
|
||||||
{
|
|
||||||
arch_info[i] = avr32_core_reg_list_arch_info[i];
|
arch_info[i] = avr32_core_reg_list_arch_info[i];
|
||||||
arch_info[i].target = target;
|
arch_info[i].target = target;
|
||||||
arch_info[i].avr32_common = ap7k;
|
arch_info[i].avr32_common = ap7k;
|
||||||
|
@ -253,31 +241,26 @@ static int avr32_ap7k_poll(struct target *target)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
/* check for processor halted */
|
/* check for processor halted */
|
||||||
if (ds & OCDREG_DS_DBA)
|
if (ds & OCDREG_DS_DBA) {
|
||||||
{
|
if ((target->state == TARGET_RUNNING) || (target->state == TARGET_RESET)) {
|
||||||
if ((target->state == TARGET_RUNNING) || (target->state == TARGET_RESET))
|
|
||||||
{
|
|
||||||
target->state = TARGET_HALTED;
|
target->state = TARGET_HALTED;
|
||||||
|
|
||||||
if ((retval = avr32_ap7k_debug_entry(target)) != ERROR_OK)
|
retval = avr32_ap7k_debug_entry(target);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
target_call_event_callbacks(target, TARGET_EVENT_HALTED);
|
target_call_event_callbacks(target, TARGET_EVENT_HALTED);
|
||||||
}
|
} else if (target->state == TARGET_DEBUG_RUNNING) {
|
||||||
else if (target->state == TARGET_DEBUG_RUNNING)
|
|
||||||
{
|
|
||||||
target->state = TARGET_HALTED;
|
target->state = TARGET_HALTED;
|
||||||
|
|
||||||
if ((retval = avr32_ap7k_debug_entry(target)) != ERROR_OK)
|
retval = avr32_ap7k_debug_entry(target);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
target_call_event_callbacks(target, TARGET_EVENT_DEBUG_HALTED);
|
target_call_event_callbacks(target, TARGET_EVENT_DEBUG_HALTED);
|
||||||
}
|
}
|
||||||
}
|
} else
|
||||||
else
|
|
||||||
{
|
|
||||||
target->state = TARGET_RUNNING;
|
target->state = TARGET_RUNNING;
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
|
@ -288,28 +271,21 @@ static int avr32_ap7k_halt(struct target *target)
|
||||||
struct avr32_ap7k_common *ap7k = target_to_ap7k(target);
|
struct avr32_ap7k_common *ap7k = target_to_ap7k(target);
|
||||||
|
|
||||||
LOG_DEBUG("target->state: %s",
|
LOG_DEBUG("target->state: %s",
|
||||||
target_state_name(target));
|
target_state_name(target));
|
||||||
|
|
||||||
if (target->state == TARGET_HALTED)
|
if (target->state == TARGET_HALTED) {
|
||||||
{
|
|
||||||
LOG_DEBUG("target was already halted");
|
LOG_DEBUG("target was already halted");
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (target->state == TARGET_UNKNOWN)
|
if (target->state == TARGET_UNKNOWN)
|
||||||
{
|
|
||||||
LOG_WARNING("target was in unknown state when halt was requested");
|
LOG_WARNING("target was in unknown state when halt was requested");
|
||||||
}
|
|
||||||
|
|
||||||
if (target->state == TARGET_RESET)
|
if (target->state == TARGET_RESET) {
|
||||||
{
|
if ((jtag_get_reset_config() & RESET_SRST_PULLS_TRST) && jtag_get_srst()) {
|
||||||
if ((jtag_get_reset_config() & RESET_SRST_PULLS_TRST) && jtag_get_srst())
|
|
||||||
{
|
|
||||||
LOG_ERROR("can't request a halt while in reset if nSRST pulls nTRST");
|
LOG_ERROR("can't request a halt while in reset if nSRST pulls nTRST");
|
||||||
return ERROR_TARGET_FAILURE;
|
return ERROR_TARGET_FAILURE;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
target->debug_reason = DBG_REASON_DBGRQ;
|
target->debug_reason = DBG_REASON_DBGRQ;
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
|
@ -345,21 +321,19 @@ static int avr32_ap7k_soft_reset_halt(struct target *target)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int avr32_ap7k_resume(struct target *target, int current,
|
static int avr32_ap7k_resume(struct target *target, int current,
|
||||||
uint32_t address, int handle_breakpoints, int debug_execution)
|
uint32_t address, int handle_breakpoints, int debug_execution)
|
||||||
{
|
{
|
||||||
struct avr32_ap7k_common *ap7k = target_to_ap7k(target);
|
struct avr32_ap7k_common *ap7k = target_to_ap7k(target);
|
||||||
struct breakpoint *breakpoint = NULL;
|
struct breakpoint *breakpoint = NULL;
|
||||||
uint32_t resume_pc;
|
uint32_t resume_pc;
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
if (target->state != TARGET_HALTED)
|
if (target->state != TARGET_HALTED) {
|
||||||
{
|
|
||||||
LOG_WARNING("target not halted");
|
LOG_WARNING("target not halted");
|
||||||
return ERROR_TARGET_NOT_HALTED;
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!debug_execution)
|
if (!debug_execution) {
|
||||||
{
|
|
||||||
target_free_all_working_areas(target);
|
target_free_all_working_areas(target);
|
||||||
/*
|
/*
|
||||||
avr32_ap7k_enable_breakpoints(target);
|
avr32_ap7k_enable_breakpoints(target);
|
||||||
|
@ -368,24 +342,21 @@ static int avr32_ap7k_resume(struct target *target, int current,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* current = 1: continue on current pc, otherwise continue at <address> */
|
/* current = 1: continue on current pc, otherwise continue at <address> */
|
||||||
if (!current)
|
if (!current) {
|
||||||
{
|
|
||||||
#if 0
|
#if 0
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
resume_pc =
|
resume_pc = buf_get_u32(ap7k->core_cache->reg_list[AVR32_REG_PC].value, 0, 32);
|
||||||
buf_get_u32(ap7k->core_cache->reg_list[AVR32_REG_PC].value, 0, 32);
|
|
||||||
avr32_ap7k_restore_context(target);
|
avr32_ap7k_restore_context(target);
|
||||||
|
|
||||||
/* the front-end may request us not to handle breakpoints */
|
/* the front-end may request us not to handle breakpoints */
|
||||||
if (handle_breakpoints)
|
if (handle_breakpoints) {
|
||||||
{
|
|
||||||
/* Single step past breakpoint at current address */
|
/* Single step past breakpoint at current address */
|
||||||
if ((breakpoint = breakpoint_find(target, resume_pc)))
|
breakpoint = breakpoint_find(target, resume_pc);
|
||||||
{
|
if (breakpoint) {
|
||||||
LOG_DEBUG("unset breakpoint at 0x%8.8" PRIx32 "", breakpoint->address);
|
LOG_DEBUG("unset breakpoint at 0x%8.8" PRIx32 "", breakpoint->address);
|
||||||
#if 0
|
#if 0
|
||||||
avr32_ap7k_unset_breakpoint(target, breakpoint);
|
avr32_ap7k_unset_breakpoint(target, breakpoint);
|
||||||
|
@ -418,14 +389,11 @@ static int avr32_ap7k_resume(struct target *target, int current,
|
||||||
/* registers are now invalid */
|
/* registers are now invalid */
|
||||||
register_cache_invalidate(ap7k->core_cache);
|
register_cache_invalidate(ap7k->core_cache);
|
||||||
|
|
||||||
if (!debug_execution)
|
if (!debug_execution) {
|
||||||
{
|
|
||||||
target->state = TARGET_RUNNING;
|
target->state = TARGET_RUNNING;
|
||||||
target_call_event_callbacks(target, TARGET_EVENT_RESUMED);
|
target_call_event_callbacks(target, TARGET_EVENT_RESUMED);
|
||||||
LOG_DEBUG("target resumed at 0x%" PRIx32 "", resume_pc);
|
LOG_DEBUG("target resumed at 0x%" PRIx32 "", resume_pc);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
target->state = TARGET_DEBUG_RUNNING;
|
target->state = TARGET_DEBUG_RUNNING;
|
||||||
target_call_event_callbacks(target, TARGET_EVENT_DEBUG_RESUMED);
|
target_call_event_callbacks(target, TARGET_EVENT_DEBUG_RESUMED);
|
||||||
LOG_DEBUG("target debug resumed at 0x%" PRIx32 "", resume_pc);
|
LOG_DEBUG("target debug resumed at 0x%" PRIx32 "", resume_pc);
|
||||||
|
@ -435,7 +403,7 @@ static int avr32_ap7k_resume(struct target *target, int current,
|
||||||
}
|
}
|
||||||
|
|
||||||
static int avr32_ap7k_step(struct target *target, int current,
|
static int avr32_ap7k_step(struct target *target, int current,
|
||||||
uint32_t address, int handle_breakpoints)
|
uint32_t address, int handle_breakpoints)
|
||||||
{
|
{
|
||||||
LOG_ERROR("%s: implement me", __func__);
|
LOG_ERROR("%s: implement me", __func__);
|
||||||
|
|
||||||
|
@ -450,7 +418,7 @@ static int avr32_ap7k_add_breakpoint(struct target *target, struct breakpoint *b
|
||||||
}
|
}
|
||||||
|
|
||||||
static int avr32_ap7k_remove_breakpoint(struct target *target,
|
static int avr32_ap7k_remove_breakpoint(struct target *target,
|
||||||
struct breakpoint *breakpoint)
|
struct breakpoint *breakpoint)
|
||||||
{
|
{
|
||||||
LOG_ERROR("%s: implement me", __func__);
|
LOG_ERROR("%s: implement me", __func__);
|
||||||
|
|
||||||
|
@ -465,7 +433,7 @@ static int avr32_ap7k_add_watchpoint(struct target *target, struct watchpoint *w
|
||||||
}
|
}
|
||||||
|
|
||||||
static int avr32_ap7k_remove_watchpoint(struct target *target,
|
static int avr32_ap7k_remove_watchpoint(struct target *target,
|
||||||
struct watchpoint *watchpoint)
|
struct watchpoint *watchpoint)
|
||||||
{
|
{
|
||||||
LOG_ERROR("%s: implement me", __func__);
|
LOG_ERROR("%s: implement me", __func__);
|
||||||
|
|
||||||
|
@ -473,14 +441,16 @@ static int avr32_ap7k_remove_watchpoint(struct target *target,
|
||||||
}
|
}
|
||||||
|
|
||||||
static int avr32_ap7k_read_memory(struct target *target, uint32_t address,
|
static int avr32_ap7k_read_memory(struct target *target, uint32_t address,
|
||||||
uint32_t size, uint32_t count, uint8_t *buffer)
|
uint32_t size, uint32_t count, uint8_t *buffer)
|
||||||
{
|
{
|
||||||
struct avr32_ap7k_common *ap7k = target_to_ap7k(target);
|
struct avr32_ap7k_common *ap7k = target_to_ap7k(target);
|
||||||
|
|
||||||
LOG_DEBUG("address: 0x%8.8" PRIx32 ", size: 0x%8.8" PRIx32 ", count: 0x%8.8" PRIx32 "", address, size, count);
|
LOG_DEBUG("address: 0x%8.8" PRIx32 ", size: 0x%8.8" PRIx32 ", count: 0x%8.8" PRIx32 "",
|
||||||
|
address,
|
||||||
|
size,
|
||||||
|
count);
|
||||||
|
|
||||||
if (target->state != TARGET_HALTED)
|
if (target->state != TARGET_HALTED) {
|
||||||
{
|
|
||||||
LOG_WARNING("target not halted");
|
LOG_WARNING("target not halted");
|
||||||
return ERROR_TARGET_NOT_HALTED;
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
}
|
}
|
||||||
|
@ -492,33 +462,36 @@ static int avr32_ap7k_read_memory(struct target *target, uint32_t address,
|
||||||
if (((size == 4) && (address & 0x3u)) || ((size == 2) && (address & 0x1u)))
|
if (((size == 4) && (address & 0x3u)) || ((size == 2) && (address & 0x1u)))
|
||||||
return ERROR_TARGET_UNALIGNED_ACCESS;
|
return ERROR_TARGET_UNALIGNED_ACCESS;
|
||||||
|
|
||||||
switch (size)
|
switch (size) {
|
||||||
{
|
case 4:
|
||||||
case 4:
|
return avr32_jtag_read_memory32(&ap7k->jtag, address, count,
|
||||||
return avr32_jtag_read_memory32(&ap7k->jtag, address, count, (uint32_t*)(void *)buffer);
|
(uint32_t *)(void *)buffer);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
return avr32_jtag_read_memory16(&ap7k->jtag, address, count, (uint16_t*)(void *)buffer);
|
return avr32_jtag_read_memory16(&ap7k->jtag, address, count,
|
||||||
break;
|
(uint16_t *)(void *)buffer);
|
||||||
case 1:
|
break;
|
||||||
return avr32_jtag_read_memory8(&ap7k->jtag, address, count, buffer);
|
case 1:
|
||||||
break;
|
return avr32_jtag_read_memory8(&ap7k->jtag, address, count, buffer);
|
||||||
default:
|
break;
|
||||||
break;
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int avr32_ap7k_write_memory(struct target *target, uint32_t address,
|
static int avr32_ap7k_write_memory(struct target *target, uint32_t address,
|
||||||
uint32_t size, uint32_t count, const uint8_t *buffer)
|
uint32_t size, uint32_t count, const uint8_t *buffer)
|
||||||
{
|
{
|
||||||
struct avr32_ap7k_common *ap7k = target_to_ap7k(target);
|
struct avr32_ap7k_common *ap7k = target_to_ap7k(target);
|
||||||
|
|
||||||
LOG_DEBUG("address: 0x%8.8" PRIx32 ", size: 0x%8.8" PRIx32 ", count: 0x%8.8" PRIx32 "", address, size, count);
|
LOG_DEBUG("address: 0x%8.8" PRIx32 ", size: 0x%8.8" PRIx32 ", count: 0x%8.8" PRIx32 "",
|
||||||
|
address,
|
||||||
|
size,
|
||||||
|
count);
|
||||||
|
|
||||||
if (target->state != TARGET_HALTED)
|
if (target->state != TARGET_HALTED) {
|
||||||
{
|
|
||||||
LOG_WARNING("target not halted");
|
LOG_WARNING("target not halted");
|
||||||
return ERROR_TARGET_NOT_HALTED;
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
}
|
}
|
||||||
|
@ -530,26 +503,27 @@ static int avr32_ap7k_write_memory(struct target *target, uint32_t address,
|
||||||
if (((size == 4) && (address & 0x3u)) || ((size == 2) && (address & 0x1u)))
|
if (((size == 4) && (address & 0x3u)) || ((size == 2) && (address & 0x1u)))
|
||||||
return ERROR_TARGET_UNALIGNED_ACCESS;
|
return ERROR_TARGET_UNALIGNED_ACCESS;
|
||||||
|
|
||||||
switch (size)
|
switch (size) {
|
||||||
{
|
case 4:
|
||||||
case 4:
|
return avr32_jtag_write_memory32(&ap7k->jtag, address, count,
|
||||||
return avr32_jtag_write_memory32(&ap7k->jtag, address, count, (uint32_t*)(void *)buffer);
|
(uint32_t *)(void *)buffer);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
return avr32_jtag_write_memory16(&ap7k->jtag, address, count, (uint16_t*)(void *)buffer);
|
return avr32_jtag_write_memory16(&ap7k->jtag, address, count,
|
||||||
break;
|
(uint16_t *)(void *)buffer);
|
||||||
case 1:
|
break;
|
||||||
return avr32_jtag_write_memory8(&ap7k->jtag, address, count, buffer);
|
case 1:
|
||||||
break;
|
return avr32_jtag_write_memory8(&ap7k->jtag, address, count, buffer);
|
||||||
default:
|
break;
|
||||||
break;
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int avr32_ap7k_init_target(struct command_context *cmd_ctx,
|
static int avr32_ap7k_init_target(struct command_context *cmd_ctx,
|
||||||
struct target *target)
|
struct target *target)
|
||||||
{
|
{
|
||||||
struct avr32_ap7k_common *ap7k = target_to_ap7k(target);
|
struct avr32_ap7k_common *ap7k = target_to_ap7k(target);
|
||||||
|
|
||||||
|
@ -561,7 +535,7 @@ static int avr32_ap7k_init_target(struct command_context *cmd_ctx,
|
||||||
static int avr32_ap7k_target_create(struct target *target, Jim_Interp *interp)
|
static int avr32_ap7k_target_create(struct target *target, Jim_Interp *interp)
|
||||||
{
|
{
|
||||||
struct avr32_ap7k_common *ap7k = calloc(1, sizeof(struct
|
struct avr32_ap7k_common *ap7k = calloc(1, sizeof(struct
|
||||||
avr32_ap7k_common));
|
avr32_ap7k_common));
|
||||||
|
|
||||||
ap7k->common_magic = AP7k_COMMON_MAGIC;
|
ap7k->common_magic = AP7k_COMMON_MAGIC;
|
||||||
target->arch_info = ap7k;
|
target->arch_info = ap7k;
|
||||||
|
@ -574,21 +548,18 @@ static int avr32_ap7k_examine(struct target *target)
|
||||||
uint32_t devid, ds;
|
uint32_t devid, ds;
|
||||||
struct avr32_ap7k_common *ap7k = target_to_ap7k(target);
|
struct avr32_ap7k_common *ap7k = target_to_ap7k(target);
|
||||||
|
|
||||||
if (!target_was_examined(target))
|
if (!target_was_examined(target)) {
|
||||||
{
|
|
||||||
target_set_examined(target);
|
target_set_examined(target);
|
||||||
avr32_jtag_nexus_read(&ap7k->jtag, AVR32_OCDREG_DID, &devid);
|
avr32_jtag_nexus_read(&ap7k->jtag, AVR32_OCDREG_DID, &devid);
|
||||||
LOG_INFO("device id: %08x", devid);
|
LOG_INFO("device id: %08x", devid);
|
||||||
avr32_ocd_setbits(&ap7k->jtag, AVR32_OCDREG_DC,OCDREG_DC_DBE);
|
avr32_ocd_setbits(&ap7k->jtag, AVR32_OCDREG_DC, OCDREG_DC_DBE);
|
||||||
avr32_jtag_nexus_read(&ap7k->jtag, AVR32_OCDREG_DS, &ds);
|
avr32_jtag_nexus_read(&ap7k->jtag, AVR32_OCDREG_DS, &ds);
|
||||||
|
|
||||||
/* check for processor halted */
|
/* check for processor halted */
|
||||||
if (ds & OCDREG_DS_DBA)
|
if (ds & OCDREG_DS_DBA) {
|
||||||
{
|
|
||||||
LOG_INFO("target is halted");
|
LOG_INFO("target is halted");
|
||||||
target->state = TARGET_HALTED;
|
target->state = TARGET_HALTED;
|
||||||
}
|
} else
|
||||||
else
|
|
||||||
target->state = TARGET_RUNNING;
|
target->state = TARGET_RUNNING;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -596,7 +567,7 @@ static int avr32_ap7k_examine(struct target *target)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int avr32_ap7k_bulk_write_memory(struct target *target, uint32_t address,
|
static int avr32_ap7k_bulk_write_memory(struct target *target, uint32_t address,
|
||||||
uint32_t count, const uint8_t *buffer)
|
uint32_t count, const uint8_t *buffer)
|
||||||
{
|
{
|
||||||
LOG_ERROR("%s: implement me", __func__);
|
LOG_ERROR("%s: implement me", __func__);
|
||||||
|
|
||||||
|
@ -609,31 +580,28 @@ int avr32_ap7k_arch_state(struct target *target)
|
||||||
struct avr32_ap7k_common *ap7k = target_to_ap7k(target);
|
struct avr32_ap7k_common *ap7k = target_to_ap7k(target);
|
||||||
|
|
||||||
LOG_USER("target halted due to %s, pc: 0x%8.8" PRIx32 "",
|
LOG_USER("target halted due to %s, pc: 0x%8.8" PRIx32 "",
|
||||||
debug_reason_name(target), ap7k->jtag.dpc);
|
debug_reason_name(target), ap7k->jtag.dpc);
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int avr32_ap7k_get_gdb_reg_list(struct target *target, struct reg **reg_list[], int *reg_list_size)
|
int avr32_ap7k_get_gdb_reg_list(struct target *target, struct reg **reg_list[], int *reg_list_size)
|
||||||
{
|
{
|
||||||
#if 0
|
#if 0
|
||||||
/* get pointers to arch-specific information */
|
/* get pointers to arch-specific information */
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* include floating point registers */
|
/* include floating point registers */
|
||||||
*reg_list_size = AVR32NUMCOREREGS + AVR32NUMFPREGS;
|
*reg_list_size = AVR32NUMCOREREGS + AVR32NUMFPREGS;
|
||||||
*reg_list = malloc(sizeof(struct reg*) * (*reg_list_size));
|
*reg_list = malloc(sizeof(struct reg *) * (*reg_list_size));
|
||||||
|
|
||||||
for (i = 0; i < AVR32NUMCOREREGS; i++)
|
for (i = 0; i < AVR32NUMCOREREGS; i++)
|
||||||
{
|
(*reg_list)[i] = &mips32->core_cache->reg_list[i];
|
||||||
(*reg_list)[i] = &mips32->core_cache->reg_list[i];
|
|
||||||
}
|
/* add dummy floating points regs */
|
||||||
|
for (i = AVR32NUMCOREREGS; i < (AVR32NUMCOREREGS + AVR32NUMFPREGS); i++)
|
||||||
|
(*reg_list)[i] = &avr32_ap7k_gdb_dummy_fp_reg;
|
||||||
|
|
||||||
/* add dummy floating points regs */
|
|
||||||
for (i = AVR32NUMCOREREGS; i < (AVR32NUMCOREREGS + AVR32NUMFPREGS); i++)
|
|
||||||
{
|
|
||||||
(*reg_list)[i] = &avr32_ap7k_gdb_dummy_fp_reg;
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
LOG_ERROR("%s: implement me", __func__);
|
LOG_ERROR("%s: implement me", __func__);
|
||||||
|
@ -642,8 +610,7 @@ int avr32_ap7k_get_gdb_reg_list(struct target *target, struct reg **reg_list[],
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
struct target_type avr32_ap7k_target =
|
struct target_type avr32_ap7k_target = {
|
||||||
{
|
|
||||||
.name = "avr32_ap7k",
|
.name = "avr32_ap7k",
|
||||||
|
|
||||||
.poll = avr32_ap7k_poll,
|
.poll = avr32_ap7k_poll,
|
||||||
|
@ -664,10 +631,10 @@ struct target_type avr32_ap7k_target =
|
||||||
.read_memory = avr32_ap7k_read_memory,
|
.read_memory = avr32_ap7k_read_memory,
|
||||||
.write_memory = avr32_ap7k_write_memory,
|
.write_memory = avr32_ap7k_write_memory,
|
||||||
.bulk_write_memory = avr32_ap7k_bulk_write_memory,
|
.bulk_write_memory = avr32_ap7k_bulk_write_memory,
|
||||||
// .checksum_memory = avr32_ap7k_checksum_memory,
|
/* .checksum_memory = avr32_ap7k_checksum_memory, */
|
||||||
// .blank_check_memory = avr32_ap7k_blank_check_memory,
|
/* .blank_check_memory = avr32_ap7k_blank_check_memory, */
|
||||||
|
|
||||||
// .run_algorithm = avr32_ap7k_run_algorithm,
|
/* .run_algorithm = avr32_ap7k_run_algorithm, */
|
||||||
|
|
||||||
.add_breakpoint = avr32_ap7k_add_breakpoint,
|
.add_breakpoint = avr32_ap7k_add_breakpoint,
|
||||||
.remove_breakpoint = avr32_ap7k_remove_breakpoint,
|
.remove_breakpoint = avr32_ap7k_remove_breakpoint,
|
||||||
|
|
|
@ -25,8 +25,7 @@
|
||||||
struct target;
|
struct target;
|
||||||
|
|
||||||
#define AP7k_COMMON_MAGIC 0x4150374b
|
#define AP7k_COMMON_MAGIC 0x4150374b
|
||||||
struct avr32_ap7k_common
|
struct avr32_ap7k_common {
|
||||||
{
|
|
||||||
int common_magic;
|
int common_magic;
|
||||||
struct avr32_jtag jtag;
|
struct avr32_jtag jtag;
|
||||||
struct reg_cache *core_cache;
|
struct reg_cache *core_cache;
|
||||||
|
@ -36,11 +35,10 @@ struct avr32_ap7k_common
|
||||||
static inline struct avr32_ap7k_common *
|
static inline struct avr32_ap7k_common *
|
||||||
target_to_ap7k(struct target *target)
|
target_to_ap7k(struct target *target)
|
||||||
{
|
{
|
||||||
return (struct avr32_ap7k_common*)target->arch_info;
|
return (struct avr32_ap7k_common *)target->arch_info;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct avr32_core_reg
|
struct avr32_core_reg {
|
||||||
{
|
|
||||||
uint32_t num;
|
uint32_t num;
|
||||||
struct target *target;
|
struct target *target;
|
||||||
struct avr32_ap7k_common *avr32_common;
|
struct avr32_ap7k_common *avr32_common;
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
* Free Software Foundation, Inc., *
|
* Free Software Foundation, Inc., *
|
||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -34,8 +35,7 @@ static int avr32_jtag_set_instr(struct avr32_jtag *jtag_info, int new_instr)
|
||||||
if (tap == NULL)
|
if (tap == NULL)
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
|
|
||||||
if (buf_get_u32(tap->cur_instr, 0, tap->ir_length) != (uint32_t)new_instr)
|
if (buf_get_u32(tap->cur_instr, 0, tap->ir_length) != (uint32_t)new_instr) {
|
||||||
{
|
|
||||||
do {
|
do {
|
||||||
struct scan_field field;
|
struct scan_field field;
|
||||||
uint8_t t[4];
|
uint8_t t[4];
|
||||||
|
@ -47,8 +47,7 @@ static int avr32_jtag_set_instr(struct avr32_jtag *jtag_info, int new_instr)
|
||||||
field.in_value = ret;
|
field.in_value = ret;
|
||||||
|
|
||||||
jtag_add_ir_scan(tap, &field, TAP_IDLE);
|
jtag_add_ir_scan(tap, &field, TAP_IDLE);
|
||||||
if (jtag_execute_queue() != ERROR_OK)
|
if (jtag_execute_queue() != ERROR_OK) {
|
||||||
{
|
|
||||||
LOG_ERROR("%s: setting address failed", __func__);
|
LOG_ERROR("%s: setting address failed", __func__);
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
@ -59,7 +58,7 @@ static int avr32_jtag_set_instr(struct avr32_jtag *jtag_info, int new_instr)
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int avr32_jtag_nexus_set_address(struct avr32_jtag *jtag_info,
|
int avr32_jtag_nexus_set_address(struct avr32_jtag *jtag_info,
|
||||||
uint32_t addr, int mode)
|
uint32_t addr, int mode)
|
||||||
{
|
{
|
||||||
struct scan_field fields[2];
|
struct scan_field fields[2];
|
||||||
|
@ -85,19 +84,18 @@ int avr32_jtag_nexus_set_address(struct avr32_jtag *jtag_info,
|
||||||
fields[1].out_value = addr_buf;
|
fields[1].out_value = addr_buf;
|
||||||
|
|
||||||
jtag_add_dr_scan(jtag_info->tap, 2, fields, TAP_IDLE);
|
jtag_add_dr_scan(jtag_info->tap, 2, fields, TAP_IDLE);
|
||||||
if (jtag_execute_queue() != ERROR_OK)
|
if (jtag_execute_queue() != ERROR_OK) {
|
||||||
{
|
|
||||||
LOG_ERROR("%s: setting address failed", __func__);
|
LOG_ERROR("%s: setting address failed", __func__);
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
busy = buf_get_u32(busy_buf, 6, 1);
|
busy = buf_get_u32(busy_buf, 6, 1);
|
||||||
} while(busy);
|
} while (busy);
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int avr32_jtag_nexus_read_data(struct avr32_jtag *jtag_info,
|
int avr32_jtag_nexus_read_data(struct avr32_jtag *jtag_info,
|
||||||
uint32_t *pdata)
|
uint32_t *pdata)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -121,8 +119,7 @@ int avr32_jtag_nexus_read_data(struct avr32_jtag *jtag_info,
|
||||||
|
|
||||||
jtag_add_dr_scan(jtag_info->tap, 2, fields, TAP_IDLE);
|
jtag_add_dr_scan(jtag_info->tap, 2, fields, TAP_IDLE);
|
||||||
|
|
||||||
if (jtag_execute_queue() != ERROR_OK)
|
if (jtag_execute_queue() != ERROR_OK) {
|
||||||
{
|
|
||||||
LOG_ERROR("%s: reading data failed", __func__);
|
LOG_ERROR("%s: reading data failed", __func__);
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
@ -135,8 +132,7 @@ int avr32_jtag_nexus_read_data(struct avr32_jtag *jtag_info,
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int avr32_jtag_nexus_write_data(struct avr32_jtag *jtag_info,
|
||||||
int avr32_jtag_nexus_write_data(struct avr32_jtag *jtag_info,
|
|
||||||
uint32_t data)
|
uint32_t data)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -163,8 +159,7 @@ int avr32_jtag_nexus_write_data(struct avr32_jtag *jtag_info,
|
||||||
|
|
||||||
jtag_add_dr_scan(jtag_info->tap, 2, fields, TAP_IDLE);
|
jtag_add_dr_scan(jtag_info->tap, 2, fields, TAP_IDLE);
|
||||||
|
|
||||||
if (jtag_execute_queue() != ERROR_OK)
|
if (jtag_execute_queue() != ERROR_OK) {
|
||||||
{
|
|
||||||
LOG_ERROR("%s: reading data failed", __func__);
|
LOG_ERROR("%s: reading data failed", __func__);
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
@ -176,9 +171,6 @@ int avr32_jtag_nexus_write_data(struct avr32_jtag *jtag_info,
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int avr32_jtag_nexus_read(struct avr32_jtag *jtag_info,
|
int avr32_jtag_nexus_read(struct avr32_jtag *jtag_info,
|
||||||
uint32_t addr, uint32_t *value)
|
uint32_t addr, uint32_t *value)
|
||||||
{
|
{
|
||||||
|
@ -228,18 +220,17 @@ int avr32_jtag_mwa_set_address(struct avr32_jtag *jtag_info, int slave,
|
||||||
fields[1].out_value = slave_buf;
|
fields[1].out_value = slave_buf;
|
||||||
|
|
||||||
jtag_add_dr_scan(jtag_info->tap, 2, fields, TAP_IDLE);
|
jtag_add_dr_scan(jtag_info->tap, 2, fields, TAP_IDLE);
|
||||||
if (jtag_execute_queue() != ERROR_OK)
|
if (jtag_execute_queue() != ERROR_OK) {
|
||||||
{
|
|
||||||
LOG_ERROR("%s: setting address failed", __func__);
|
LOG_ERROR("%s: setting address failed", __func__);
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
busy = buf_get_u32(busy_buf, 1, 1);
|
busy = buf_get_u32(busy_buf, 1, 1);
|
||||||
} while(busy);
|
} while (busy);
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int avr32_jtag_mwa_read_data(struct avr32_jtag *jtag_info,
|
int avr32_jtag_mwa_read_data(struct avr32_jtag *jtag_info,
|
||||||
uint32_t *pdata)
|
uint32_t *pdata)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -263,8 +254,7 @@ int avr32_jtag_mwa_read_data(struct avr32_jtag *jtag_info,
|
||||||
|
|
||||||
jtag_add_dr_scan(jtag_info->tap, 2, fields, TAP_IDLE);
|
jtag_add_dr_scan(jtag_info->tap, 2, fields, TAP_IDLE);
|
||||||
|
|
||||||
if (jtag_execute_queue() != ERROR_OK)
|
if (jtag_execute_queue() != ERROR_OK) {
|
||||||
{
|
|
||||||
LOG_ERROR("%s: reading data failed", __func__);
|
LOG_ERROR("%s: reading data failed", __func__);
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
@ -277,7 +267,7 @@ int avr32_jtag_mwa_read_data(struct avr32_jtag *jtag_info,
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int avr32_jtag_mwa_write_data(struct avr32_jtag *jtag_info,
|
int avr32_jtag_mwa_write_data(struct avr32_jtag *jtag_info,
|
||||||
uint32_t data)
|
uint32_t data)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -304,8 +294,7 @@ int avr32_jtag_mwa_write_data(struct avr32_jtag *jtag_info,
|
||||||
|
|
||||||
jtag_add_dr_scan(jtag_info->tap, 2, fields, TAP_IDLE);
|
jtag_add_dr_scan(jtag_info->tap, 2, fields, TAP_IDLE);
|
||||||
|
|
||||||
if (jtag_execute_queue() != ERROR_OK)
|
if (jtag_execute_queue() != ERROR_OK) {
|
||||||
{
|
|
||||||
LOG_ERROR("%s: reading data failed", __func__);
|
LOG_ERROR("%s: reading data failed", __func__);
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
@ -316,8 +305,6 @@ int avr32_jtag_mwa_write_data(struct avr32_jtag *jtag_info,
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int avr32_jtag_mwa_read(struct avr32_jtag *jtag_info, int slave,
|
int avr32_jtag_mwa_read(struct avr32_jtag *jtag_info, int slave,
|
||||||
uint32_t addr, uint32_t *value)
|
uint32_t addr, uint32_t *value)
|
||||||
{
|
{
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
* Free Software Foundation, Inc., *
|
* Free Software Foundation, Inc., *
|
||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#ifndef AVR32_JTAG
|
#ifndef AVR32_JTAG
|
||||||
#define AVR32_JTAG
|
#define AVR32_JTAG
|
||||||
|
|
||||||
|
@ -81,8 +82,7 @@
|
||||||
#define MTSR(sysreg, reg) (0xe3b00002 | ((reg) << 16) | sysreg)
|
#define MTSR(sysreg, reg) (0xe3b00002 | ((reg) << 16) | sysreg)
|
||||||
#define MFSR(reg, sysreg) (0xe1b00002 | ((reg) << 16) | sysreg)
|
#define MFSR(reg, sysreg) (0xe1b00002 | ((reg) << 16) | sysreg)
|
||||||
|
|
||||||
struct avr32_jtag
|
struct avr32_jtag {
|
||||||
{
|
|
||||||
struct jtag_tap *tap;
|
struct jtag_tap *tap;
|
||||||
uint32_t dpc; /* Debug PC value */
|
uint32_t dpc; /* Debug PC value */
|
||||||
};
|
};
|
||||||
|
@ -97,11 +97,9 @@ int avr32_jtag_mwa_read(struct avr32_jtag *jtag_info, int slave,
|
||||||
int avr32_jtag_mwa_write(struct avr32_jtag *jtag_info, int slave,
|
int avr32_jtag_mwa_write(struct avr32_jtag *jtag_info, int slave,
|
||||||
uint32_t addr, uint32_t value);
|
uint32_t addr, uint32_t value);
|
||||||
|
|
||||||
|
|
||||||
int avr32_ocd_setbits(struct avr32_jtag *jtag, int reg, uint32_t bits);
|
int avr32_ocd_setbits(struct avr32_jtag *jtag, int reg, uint32_t bits);
|
||||||
int avr32_ocd_clearbits(struct avr32_jtag *jtag, int reg, uint32_t bits);
|
int avr32_ocd_clearbits(struct avr32_jtag *jtag, int reg, uint32_t bits);
|
||||||
|
|
||||||
int avr32_jtag_exec(struct avr32_jtag *jtag_info, uint32_t inst);
|
int avr32_jtag_exec(struct avr32_jtag *jtag_info, uint32_t inst);
|
||||||
|
|
||||||
#endif /* AVR32_JTAG */
|
#endif /* AVR32_JTAG */
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
* Free Software Foundation, Inc., *
|
* Free Software Foundation, Inc., *
|
||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -25,14 +26,13 @@
|
||||||
#include "avr32_jtag.h"
|
#include "avr32_jtag.h"
|
||||||
#include "avr32_mem.h"
|
#include "avr32_mem.h"
|
||||||
|
|
||||||
int avr32_jtag_read_memory32(struct avr32_jtag *jtag_info,
|
int avr32_jtag_read_memory32(struct avr32_jtag *jtag_info,
|
||||||
uint32_t addr, int count, uint32_t *buffer)
|
uint32_t addr, int count, uint32_t *buffer)
|
||||||
{
|
{
|
||||||
int i, retval;
|
int i, retval;
|
||||||
uint32_t data;
|
uint32_t data;
|
||||||
|
|
||||||
for (i = 0; i < count; i++)
|
for (i = 0; i < count; i++) {
|
||||||
{
|
|
||||||
retval = avr32_jtag_mwa_read(jtag_info, SLAVE_HSB_UNCACHED,
|
retval = avr32_jtag_mwa_read(jtag_info, SLAVE_HSB_UNCACHED,
|
||||||
addr + i*4, &data);
|
addr + i*4, &data);
|
||||||
|
|
||||||
|
@ -40,14 +40,14 @@ int avr32_jtag_read_memory32(struct avr32_jtag *jtag_info,
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
/* XXX: Assume AVR32 is BE */
|
/* XXX: Assume AVR32 is BE */
|
||||||
buffer[i] = be_to_h_u32((uint8_t*)&data);
|
buffer[i] = be_to_h_u32((uint8_t *)&data);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int avr32_jtag_read_memory16(struct avr32_jtag *jtag_info,
|
int avr32_jtag_read_memory16(struct avr32_jtag *jtag_info,
|
||||||
uint32_t addr, int count, uint16_t *buffer)
|
uint32_t addr, int count, uint16_t *buffer)
|
||||||
{
|
{
|
||||||
int i, retval;
|
int i, retval;
|
||||||
uint32_t data;
|
uint32_t data;
|
||||||
|
@ -55,8 +55,7 @@ int avr32_jtag_read_memory16(struct avr32_jtag *jtag_info,
|
||||||
i = 0;
|
i = 0;
|
||||||
|
|
||||||
/* any unaligned half-words? */
|
/* any unaligned half-words? */
|
||||||
if (addr & 3)
|
if (addr & 3) {
|
||||||
{
|
|
||||||
retval = avr32_jtag_mwa_read(jtag_info, SLAVE_HSB_UNCACHED,
|
retval = avr32_jtag_mwa_read(jtag_info, SLAVE_HSB_UNCACHED,
|
||||||
addr + i*2, &data);
|
addr + i*2, &data);
|
||||||
|
|
||||||
|
@ -64,14 +63,13 @@ int avr32_jtag_read_memory16(struct avr32_jtag *jtag_info,
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
/* XXX: Assume AVR32 is BE */
|
/* XXX: Assume AVR32 is BE */
|
||||||
data = be_to_h_u32((uint8_t*)&data);
|
data = be_to_h_u32((uint8_t *)&data);
|
||||||
buffer[i] = (data >> 16) & 0xffff;
|
buffer[i] = (data >> 16) & 0xffff;
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* read all complete words */
|
/* read all complete words */
|
||||||
for (; i < (count & ~1); i+=2)
|
for (; i < (count & ~1); i += 2) {
|
||||||
{
|
|
||||||
retval = avr32_jtag_mwa_read(jtag_info, SLAVE_HSB_UNCACHED,
|
retval = avr32_jtag_mwa_read(jtag_info, SLAVE_HSB_UNCACHED,
|
||||||
addr + i*2, &data);
|
addr + i*2, &data);
|
||||||
|
|
||||||
|
@ -79,14 +77,13 @@ int avr32_jtag_read_memory16(struct avr32_jtag *jtag_info,
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
/* XXX: Assume AVR32 is BE */
|
/* XXX: Assume AVR32 is BE */
|
||||||
data = be_to_h_u32((uint8_t*)&data);
|
data = be_to_h_u32((uint8_t *)&data);
|
||||||
buffer[i] = data & 0xffff;
|
buffer[i] = data & 0xffff;
|
||||||
buffer[i+1] = (data >> 16) & 0xffff;
|
buffer[i+1] = (data >> 16) & 0xffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* last halfword */
|
/* last halfword */
|
||||||
if (i < count)
|
if (i < count) {
|
||||||
{
|
|
||||||
retval = avr32_jtag_mwa_read(jtag_info, SLAVE_HSB_UNCACHED,
|
retval = avr32_jtag_mwa_read(jtag_info, SLAVE_HSB_UNCACHED,
|
||||||
addr + i*2, &data);
|
addr + i*2, &data);
|
||||||
|
|
||||||
|
@ -94,73 +91,68 @@ int avr32_jtag_read_memory16(struct avr32_jtag *jtag_info,
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
/* XXX: Assume AVR32 is BE */
|
/* XXX: Assume AVR32 is BE */
|
||||||
data = be_to_h_u32((uint8_t*)&data);
|
data = be_to_h_u32((uint8_t *)&data);
|
||||||
buffer[i] = data & 0xffff;
|
buffer[i] = data & 0xffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int avr32_jtag_read_memory8(struct avr32_jtag *jtag_info,
|
int avr32_jtag_read_memory8(struct avr32_jtag *jtag_info,
|
||||||
uint32_t addr, int count, uint8_t *buffer)
|
uint32_t addr, int count, uint8_t *buffer)
|
||||||
{
|
{
|
||||||
int i, j, retval;
|
int i, j, retval;
|
||||||
uint8_t data[4];
|
uint8_t data[4];
|
||||||
i = 0;
|
i = 0;
|
||||||
|
|
||||||
/* Do we have non-aligned bytes? */
|
/* Do we have non-aligned bytes? */
|
||||||
if (addr & 3)
|
if (addr & 3) {
|
||||||
{
|
|
||||||
retval = avr32_jtag_mwa_read(jtag_info, SLAVE_HSB_UNCACHED,
|
retval = avr32_jtag_mwa_read(jtag_info, SLAVE_HSB_UNCACHED,
|
||||||
addr + i, (uint32_t*)(void *)data);
|
addr + i, (uint32_t *)(void *)data);
|
||||||
|
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
for (j = addr & 3; (j < 4) && (i < count); j++, i++)
|
for (j = addr & 3; (j < 4) && (i < count); j++, i++)
|
||||||
buffer[i] = data[3-j];
|
buffer[i] = data[3-j];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* read all complete words */
|
/* read all complete words */
|
||||||
for (; i < (count & ~3); i+=4)
|
for (; i < (count & ~3); i += 4) {
|
||||||
{
|
|
||||||
retval = avr32_jtag_mwa_read(jtag_info, SLAVE_HSB_UNCACHED,
|
retval = avr32_jtag_mwa_read(jtag_info, SLAVE_HSB_UNCACHED,
|
||||||
addr + i, (uint32_t*)(void *)data);
|
addr + i, (uint32_t *)(void *)data);
|
||||||
|
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
for (j = 0; j < 4; j++)
|
for (j = 0; j < 4; j++)
|
||||||
buffer[i+j] = data[3-j];
|
buffer[i+j] = data[3-j];
|
||||||
}
|
}
|
||||||
|
|
||||||
/* remaining bytes */
|
/* remaining bytes */
|
||||||
if (i < count)
|
if (i < count) {
|
||||||
{
|
|
||||||
retval = avr32_jtag_mwa_read(jtag_info, SLAVE_HSB_UNCACHED,
|
retval = avr32_jtag_mwa_read(jtag_info, SLAVE_HSB_UNCACHED,
|
||||||
addr + i, (uint32_t*)(void *)data);
|
addr + i, (uint32_t *)(void *)data);
|
||||||
|
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
for (j = 0; i + j < count; j++)
|
for (j = 0; i + j < count; j++)
|
||||||
buffer[i+j] = data[3-j];
|
buffer[i+j] = data[3-j];
|
||||||
}
|
}
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int avr32_jtag_write_memory32(struct avr32_jtag *jtag_info,
|
int avr32_jtag_write_memory32(struct avr32_jtag *jtag_info,
|
||||||
uint32_t addr, int count, const uint32_t *buffer)
|
uint32_t addr, int count, const uint32_t *buffer)
|
||||||
{
|
{
|
||||||
int i, retval;
|
int i, retval;
|
||||||
uint32_t data;
|
uint32_t data;
|
||||||
|
|
||||||
for (i = 0; i < count; i++)
|
for (i = 0; i < count; i++) {
|
||||||
{
|
|
||||||
/* XXX: Assume AVR32 is BE */
|
/* XXX: Assume AVR32 is BE */
|
||||||
h_u32_to_be((uint8_t*)&data, buffer[i]);
|
h_u32_to_be((uint8_t *)&data, buffer[i]);
|
||||||
retval = avr32_jtag_mwa_write(jtag_info, SLAVE_HSB_UNCACHED,
|
retval = avr32_jtag_mwa_write(jtag_info, SLAVE_HSB_UNCACHED,
|
||||||
addr + i*4, data);
|
addr + i*4, data);
|
||||||
|
|
||||||
|
@ -172,8 +164,8 @@ int avr32_jtag_write_memory32(struct avr32_jtag *jtag_info,
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int avr32_jtag_write_memory16(struct avr32_jtag *jtag_info,
|
int avr32_jtag_write_memory16(struct avr32_jtag *jtag_info,
|
||||||
uint32_t addr, int count, const uint16_t *buffer)
|
uint32_t addr, int count, const uint16_t *buffer)
|
||||||
{
|
{
|
||||||
int i, retval;
|
int i, retval;
|
||||||
uint32_t data;
|
uint32_t data;
|
||||||
|
@ -185,7 +177,7 @@ int avr32_jtag_write_memory16(struct avr32_jtag *jtag_info,
|
||||||
* Do we have any non-aligned half-words?
|
* Do we have any non-aligned half-words?
|
||||||
*/
|
*/
|
||||||
if (addr & 3) {
|
if (addr & 3) {
|
||||||
/*
|
/*
|
||||||
* mwa_read will read whole world, no nead to fiddle
|
* mwa_read will read whole world, no nead to fiddle
|
||||||
* with address. It will be truncated in set_addr
|
* with address. It will be truncated in set_addr
|
||||||
*/
|
*/
|
||||||
|
@ -195,9 +187,9 @@ int avr32_jtag_write_memory16(struct avr32_jtag *jtag_info,
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
data = be_to_h_u32((uint8_t*)&data);
|
data = be_to_h_u32((uint8_t *)&data);
|
||||||
data = (buffer[i] << 16) | (data & 0xffff);
|
data = (buffer[i] << 16) | (data & 0xffff);
|
||||||
h_u32_to_be((uint8_t*)&data_out, data);
|
h_u32_to_be((uint8_t *)&data_out, data);
|
||||||
|
|
||||||
retval = avr32_jtag_mwa_write(jtag_info, SLAVE_HSB_UNCACHED,
|
retval = avr32_jtag_mwa_write(jtag_info, SLAVE_HSB_UNCACHED,
|
||||||
addr, data_out);
|
addr, data_out);
|
||||||
|
@ -208,13 +200,11 @@ int avr32_jtag_write_memory16(struct avr32_jtag *jtag_info,
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* write all complete words */
|
/* write all complete words */
|
||||||
for (; i < (count & ~1); i+=2)
|
for (; i < (count & ~1); i += 2) {
|
||||||
{
|
|
||||||
/* XXX: Assume AVR32 is BE */
|
/* XXX: Assume AVR32 is BE */
|
||||||
data = (buffer[i+1] << 16) | buffer[i];
|
data = (buffer[i+1] << 16) | buffer[i];
|
||||||
h_u32_to_be((uint8_t*)&data_out, data);
|
h_u32_to_be((uint8_t *)&data_out, data);
|
||||||
|
|
||||||
retval = avr32_jtag_mwa_write(jtag_info, SLAVE_HSB_UNCACHED,
|
retval = avr32_jtag_mwa_write(jtag_info, SLAVE_HSB_UNCACHED,
|
||||||
addr + i*2, data_out);
|
addr + i*2, data_out);
|
||||||
|
@ -224,18 +214,17 @@ int avr32_jtag_write_memory16(struct avr32_jtag *jtag_info,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* last halfword */
|
/* last halfword */
|
||||||
if (i < count)
|
if (i < count) {
|
||||||
{
|
|
||||||
retval = avr32_jtag_mwa_read(jtag_info, SLAVE_HSB_UNCACHED,
|
retval = avr32_jtag_mwa_read(jtag_info, SLAVE_HSB_UNCACHED,
|
||||||
addr + i*2, &data);
|
addr + i*2, &data);
|
||||||
|
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
data = be_to_h_u32((uint8_t*)&data);
|
data = be_to_h_u32((uint8_t *)&data);
|
||||||
data &= ~0xffff;
|
data &= ~0xffff;
|
||||||
data |= buffer[i];
|
data |= buffer[i];
|
||||||
h_u32_to_be((uint8_t*)&data_out, data);
|
h_u32_to_be((uint8_t *)&data_out, data);
|
||||||
|
|
||||||
retval = avr32_jtag_mwa_write(jtag_info, SLAVE_HSB_UNCACHED,
|
retval = avr32_jtag_mwa_write(jtag_info, SLAVE_HSB_UNCACHED,
|
||||||
addr + i*2, data_out);
|
addr + i*2, data_out);
|
||||||
|
@ -247,8 +236,8 @@ int avr32_jtag_write_memory16(struct avr32_jtag *jtag_info,
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int avr32_jtag_write_memory8(struct avr32_jtag *jtag_info,
|
int avr32_jtag_write_memory8(struct avr32_jtag *jtag_info,
|
||||||
uint32_t addr, int count, const uint8_t *buffer)
|
uint32_t addr, int count, const uint8_t *buffer)
|
||||||
{
|
{
|
||||||
int i, j, retval;
|
int i, j, retval;
|
||||||
uint32_t data;
|
uint32_t data;
|
||||||
|
@ -260,7 +249,7 @@ int avr32_jtag_write_memory8(struct avr32_jtag *jtag_info,
|
||||||
* Do we have any non-aligned bytes?
|
* Do we have any non-aligned bytes?
|
||||||
*/
|
*/
|
||||||
if (addr & 3) {
|
if (addr & 3) {
|
||||||
/*
|
/*
|
||||||
* mwa_read will read whole world, no nead to fiddle
|
* mwa_read will read whole world, no nead to fiddle
|
||||||
* with address. It will be truncated in set_addr
|
* with address. It will be truncated in set_addr
|
||||||
*/
|
*/
|
||||||
|
@ -270,14 +259,13 @@ int avr32_jtag_write_memory8(struct avr32_jtag *jtag_info,
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
data = be_to_h_u32((uint8_t*)&data);
|
data = be_to_h_u32((uint8_t *)&data);
|
||||||
for (j = addr & 3; (j < 4) && (i < count); j++, i++)
|
for (j = addr & 3; (j < 4) && (i < count); j++, i++) {
|
||||||
{
|
|
||||||
data &= ~(0xff << j*8);
|
data &= ~(0xff << j*8);
|
||||||
data |= (buffer[i] << j*8);
|
data |= (buffer[i] << j*8);
|
||||||
}
|
}
|
||||||
|
|
||||||
h_u32_to_be((uint8_t*)&data_out, data);
|
h_u32_to_be((uint8_t *)&data_out, data);
|
||||||
retval = avr32_jtag_mwa_write(jtag_info, SLAVE_HSB_UNCACHED,
|
retval = avr32_jtag_mwa_write(jtag_info, SLAVE_HSB_UNCACHED,
|
||||||
addr, data_out);
|
addr, data_out);
|
||||||
|
|
||||||
|
@ -287,14 +275,13 @@ int avr32_jtag_write_memory8(struct avr32_jtag *jtag_info,
|
||||||
|
|
||||||
|
|
||||||
/* write all complete words */
|
/* write all complete words */
|
||||||
for (; i < (count & ~3); i+=4)
|
for (; i < (count & ~3); i += 4) {
|
||||||
{
|
|
||||||
data = 0;
|
data = 0;
|
||||||
|
|
||||||
for (j = 0; j < 4; j++)
|
for (j = 0; j < 4; j++)
|
||||||
data |= (buffer[j+i] << j*8);
|
data |= (buffer[j+i] << j*8);
|
||||||
|
|
||||||
h_u32_to_be((uint8_t*)&data_out, data);
|
h_u32_to_be((uint8_t *)&data_out, data);
|
||||||
|
|
||||||
retval = avr32_jtag_mwa_write(jtag_info, SLAVE_HSB_UNCACHED,
|
retval = avr32_jtag_mwa_write(jtag_info, SLAVE_HSB_UNCACHED,
|
||||||
addr + i, data_out);
|
addr + i, data_out);
|
||||||
|
@ -313,14 +300,13 @@ int avr32_jtag_write_memory8(struct avr32_jtag *jtag_info,
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
data = be_to_h_u32((uint8_t*)&data);
|
data = be_to_h_u32((uint8_t *)&data);
|
||||||
for (j = 0; i < count; j++, i++)
|
for (j = 0; i < count; j++, i++) {
|
||||||
{
|
|
||||||
data &= ~(0xff << j*8);
|
data &= ~(0xff << j*8);
|
||||||
data |= (buffer[j+i] << j*8);
|
data |= (buffer[j+i] << j*8);
|
||||||
}
|
}
|
||||||
|
|
||||||
h_u32_to_be((uint8_t*)&data_out, data);
|
h_u32_to_be((uint8_t *)&data_out, data);
|
||||||
|
|
||||||
retval = avr32_jtag_mwa_write(jtag_info, SLAVE_HSB_UNCACHED,
|
retval = avr32_jtag_mwa_write(jtag_info, SLAVE_HSB_UNCACHED,
|
||||||
addr+i, data_out);
|
addr+i, data_out);
|
||||||
|
|
|
@ -16,22 +16,22 @@
|
||||||
* Free Software Foundation, Inc., *
|
* Free Software Foundation, Inc., *
|
||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#ifndef AVR32_MEM
|
#ifndef AVR32_MEM
|
||||||
#define AVR32_MEM
|
#define AVR32_MEM
|
||||||
|
|
||||||
int avr32_jtag_read_memory32(struct avr32_jtag *jtag_info,
|
int avr32_jtag_read_memory32(struct avr32_jtag *jtag_info,
|
||||||
uint32_t addr, int count, uint32_t *buffer);
|
uint32_t addr, int count, uint32_t *buffer);
|
||||||
int avr32_jtag_read_memory16(struct avr32_jtag *jtag_info,
|
int avr32_jtag_read_memory16(struct avr32_jtag *jtag_info,
|
||||||
uint32_t addr, int count, uint16_t *buffer);
|
uint32_t addr, int count, uint16_t *buffer);
|
||||||
int avr32_jtag_read_memory8(struct avr32_jtag *jtag_info,
|
int avr32_jtag_read_memory8(struct avr32_jtag *jtag_info,
|
||||||
uint32_t addr, int count, uint8_t *buffer);
|
uint32_t addr, int count, uint8_t *buffer);
|
||||||
|
|
||||||
int avr32_jtag_write_memory32(struct avr32_jtag *jtag_info,
|
int avr32_jtag_write_memory32(struct avr32_jtag *jtag_info,
|
||||||
uint32_t addr, int count, const uint32_t *buffer);
|
uint32_t addr, int count, const uint32_t *buffer);
|
||||||
int avr32_jtag_write_memory16(struct avr32_jtag *jtag_info,
|
int avr32_jtag_write_memory16(struct avr32_jtag *jtag_info,
|
||||||
uint32_t addr, int count, const uint16_t *buffer);
|
uint32_t addr, int count, const uint16_t *buffer);
|
||||||
int avr32_jtag_write_memory8(struct avr32_jtag *jtag_info,
|
int avr32_jtag_write_memory8(struct avr32_jtag *jtag_info,
|
||||||
uint32_t addr, int count, const uint8_t *buffer);
|
uint32_t addr, int count, const uint8_t *buffer);
|
||||||
|
|
||||||
#endif /* AVR32_MEM */
|
#endif /* AVR32_MEM */
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
* Free Software Foundation, Inc., *
|
* Free Software Foundation, Inc., *
|
||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -25,7 +26,7 @@
|
||||||
#include "avr32_jtag.h"
|
#include "avr32_jtag.h"
|
||||||
#include "avr32_regs.h"
|
#include "avr32_regs.h"
|
||||||
|
|
||||||
static int avr32_jtag_read_reg(struct avr32_jtag *jtag_info, int reg,
|
static int avr32_jtag_read_reg(struct avr32_jtag *jtag_info, int reg,
|
||||||
uint32_t *val)
|
uint32_t *val)
|
||||||
{
|
{
|
||||||
int retval;
|
int retval;
|
||||||
|
@ -36,27 +37,27 @@ static int avr32_jtag_read_reg(struct avr32_jtag *jtag_info, int reg,
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
retval = avr32_jtag_nexus_read(jtag_info,
|
retval = avr32_jtag_nexus_read(jtag_info,
|
||||||
AVR32_OCDREG_DCSR, &dcsr);
|
AVR32_OCDREG_DCSR, &dcsr);
|
||||||
|
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
} while (!(dcsr & OCDREG_DCSR_CPUD));
|
} while (!(dcsr & OCDREG_DCSR_CPUD));
|
||||||
|
|
||||||
retval = avr32_jtag_nexus_read(jtag_info,
|
retval = avr32_jtag_nexus_read(jtag_info,
|
||||||
AVR32_OCDREG_DCCPU, val);
|
AVR32_OCDREG_DCCPU, val);
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int avr32_jtag_write_reg(struct avr32_jtag *jtag_info, int reg,
|
static int avr32_jtag_write_reg(struct avr32_jtag *jtag_info, int reg,
|
||||||
uint32_t val)
|
uint32_t val)
|
||||||
{
|
{
|
||||||
int retval;
|
int retval;
|
||||||
uint32_t dcsr;
|
uint32_t dcsr;
|
||||||
|
|
||||||
/* Restore Status reg */
|
/* Restore Status reg */
|
||||||
retval = avr32_jtag_nexus_write(jtag_info,
|
retval = avr32_jtag_nexus_write(jtag_info,
|
||||||
AVR32_OCDREG_DCEMU, val);
|
AVR32_OCDREG_DCEMU, val);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
@ -65,7 +66,7 @@ static int avr32_jtag_write_reg(struct avr32_jtag *jtag_info, int reg,
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
do {
|
do {
|
||||||
retval = avr32_jtag_nexus_read(jtag_info,
|
retval = avr32_jtag_nexus_read(jtag_info,
|
||||||
AVR32_OCDREG_DCSR, &dcsr);
|
AVR32_OCDREG_DCSR, &dcsr);
|
||||||
} while (!(dcsr & OCDREG_DCSR_EMUD) && (retval == ERROR_OK));
|
} while (!(dcsr & OCDREG_DCSR_EMUD) && (retval == ERROR_OK));
|
||||||
|
|
||||||
|
@ -79,7 +80,7 @@ int avr32_jtag_read_regs(struct avr32_jtag *jtag_info, uint32_t *regs)
|
||||||
int i, retval;
|
int i, retval;
|
||||||
|
|
||||||
/* read core registers */
|
/* read core registers */
|
||||||
for (i = 0; i < AVR32NUMCOREREGS - 1; i++)
|
for (i = 0; i < AVR32NUMCOREREGS - 1; i++)
|
||||||
avr32_jtag_read_reg(jtag_info, i, regs + i);
|
avr32_jtag_read_reg(jtag_info, i, regs + i);
|
||||||
|
|
||||||
/* read status register */
|
/* read status register */
|
||||||
|
@ -108,7 +109,7 @@ int avr32_jtag_write_regs(struct avr32_jtag *jtag_info, uint32_t *regs)
|
||||||
/*
|
/*
|
||||||
* And now the rest of registers
|
* And now the rest of registers
|
||||||
*/
|
*/
|
||||||
for (i = 0; i < AVR32NUMCOREREGS - 1; i++)
|
for (i = 0; i < AVR32NUMCOREREGS - 1; i++)
|
||||||
avr32_jtag_write_reg(jtag_info, i, regs[i]);
|
avr32_jtag_write_reg(jtag_info, i, regs[i]);
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
* Free Software Foundation, Inc., *
|
* Free Software Foundation, Inc., *
|
||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#ifndef AVR32_REGS
|
#ifndef AVR32_REGS
|
||||||
#define AVR32_REGS
|
#define AVR32_REGS
|
||||||
|
|
||||||
|
@ -43,4 +44,3 @@ int avr32_jtag_read_regs(struct avr32_jtag *jtag_info, uint32_t *regs);
|
||||||
int avr32_jtag_write_regs(struct avr32_jtag *jtag_info, uint32_t *regs);
|
int avr32_jtag_write_regs(struct avr32_jtag *jtag_info, uint32_t *regs);
|
||||||
|
|
||||||
#endif /* AVR32_REGS */
|
#endif /* AVR32_REGS */
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
* Free Software Foundation, Inc., *
|
* Free Software Foundation, Inc., *
|
||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -25,7 +26,6 @@
|
||||||
#include "target.h"
|
#include "target.h"
|
||||||
#include "target_type.h"
|
#include "target_type.h"
|
||||||
|
|
||||||
|
|
||||||
#define AVR_JTAG_INS_LEN 4
|
#define AVR_JTAG_INS_LEN 4
|
||||||
|
|
||||||
/* forward declarations */
|
/* forward declarations */
|
||||||
|
@ -35,8 +35,10 @@ static int avr_init_target(struct command_context *cmd_ctx, struct target *targe
|
||||||
static int avr_arch_state(struct target *target);
|
static int avr_arch_state(struct target *target);
|
||||||
static int avr_poll(struct target *target);
|
static int avr_poll(struct target *target);
|
||||||
static int avr_halt(struct target *target);
|
static int avr_halt(struct target *target);
|
||||||
static int avr_resume(struct target *target, int current, uint32_t address, int handle_breakpoints, int debug_execution);
|
static int avr_resume(struct target *target, int current, uint32_t address,
|
||||||
static int avr_step(struct target *target, int current, uint32_t address, int handle_breakpoints);
|
int handle_breakpoints, int debug_execution);
|
||||||
|
static int avr_step(struct target *target, int current, uint32_t address,
|
||||||
|
int handle_breakpoints);
|
||||||
|
|
||||||
static int avr_assert_reset(struct target *target);
|
static int avr_assert_reset(struct target *target);
|
||||||
static int avr_deassert_reset(struct target *target);
|
static int avr_deassert_reset(struct target *target);
|
||||||
|
@ -48,8 +50,7 @@ static int mcu_write_dr(struct jtag_tap *tap, uint8_t *dr_in, uint8_t *dr_out, i
|
||||||
static int mcu_write_ir_u8(struct jtag_tap *tap, uint8_t *ir_in, uint8_t ir_out, int ir_len, int rti);
|
static int mcu_write_ir_u8(struct jtag_tap *tap, uint8_t *ir_in, uint8_t ir_out, int ir_len, int rti);
|
||||||
static int mcu_write_dr_u32(struct jtag_tap *tap, uint32_t *ir_in, uint32_t ir_out, int dr_len, int rti);
|
static int mcu_write_dr_u32(struct jtag_tap *tap, uint32_t *ir_in, uint32_t ir_out, int dr_len, int rti);
|
||||||
|
|
||||||
struct target_type avr_target =
|
struct target_type avr_target = {
|
||||||
{
|
|
||||||
.name = "avr",
|
.name = "avr",
|
||||||
|
|
||||||
.poll = avr_poll,
|
.poll = avr_poll,
|
||||||
|
@ -96,43 +97,41 @@ static int avr_target_create(struct target *target, Jim_Interp *interp)
|
||||||
|
|
||||||
static int avr_init_target(struct command_context *cmd_ctx, struct target *target)
|
static int avr_init_target(struct command_context *cmd_ctx, struct target *target)
|
||||||
{
|
{
|
||||||
LOG_DEBUG("%s", __FUNCTION__);
|
LOG_DEBUG("%s", __func__);
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int avr_arch_state(struct target *target)
|
static int avr_arch_state(struct target *target)
|
||||||
{
|
{
|
||||||
LOG_DEBUG("%s", __FUNCTION__);
|
LOG_DEBUG("%s", __func__);
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int avr_poll(struct target *target)
|
static int avr_poll(struct target *target)
|
||||||
{
|
{
|
||||||
if ((target->state == TARGET_RUNNING) || (target->state == TARGET_DEBUG_RUNNING))
|
if ((target->state == TARGET_RUNNING) || (target->state == TARGET_DEBUG_RUNNING))
|
||||||
{
|
|
||||||
target->state = TARGET_HALTED;
|
target->state = TARGET_HALTED;
|
||||||
}
|
|
||||||
|
|
||||||
LOG_DEBUG("%s", __FUNCTION__);
|
LOG_DEBUG("%s", __func__);
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int avr_halt(struct target *target)
|
static int avr_halt(struct target *target)
|
||||||
{
|
{
|
||||||
LOG_DEBUG("%s", __FUNCTION__);
|
LOG_DEBUG("%s", __func__);
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int avr_resume(struct target *target, int current, uint32_t address,
|
static int avr_resume(struct target *target, int current, uint32_t address,
|
||||||
int handle_breakpoints, int debug_execution)
|
int handle_breakpoints, int debug_execution)
|
||||||
{
|
{
|
||||||
LOG_DEBUG("%s", __FUNCTION__);
|
LOG_DEBUG("%s", __func__);
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int avr_step(struct target *target, int current, uint32_t address, int handle_breakpoints)
|
static int avr_step(struct target *target, int current, uint32_t address, int handle_breakpoints)
|
||||||
{
|
{
|
||||||
LOG_DEBUG("%s", __FUNCTION__);
|
LOG_DEBUG("%s", __func__);
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,7 +139,7 @@ static int avr_assert_reset(struct target *target)
|
||||||
{
|
{
|
||||||
target->state = TARGET_RESET;
|
target->state = TARGET_RESET;
|
||||||
|
|
||||||
LOG_DEBUG("%s", __FUNCTION__);
|
LOG_DEBUG("%s", __func__);
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -148,13 +147,13 @@ static int avr_deassert_reset(struct target *target)
|
||||||
{
|
{
|
||||||
target->state = TARGET_RUNNING;
|
target->state = TARGET_RUNNING;
|
||||||
|
|
||||||
LOG_DEBUG("%s", __FUNCTION__);
|
LOG_DEBUG("%s", __func__);
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int avr_soft_reset_halt(struct target *target)
|
static int avr_soft_reset_halt(struct target *target)
|
||||||
{
|
{
|
||||||
LOG_DEBUG("%s", __FUNCTION__);
|
LOG_DEBUG("%s", __func__);
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -173,13 +172,11 @@ int avr_jtag_sendinstr(struct jtag_tap *tap, uint8_t *ir_in, uint8_t ir_out)
|
||||||
static int mcu_write_ir(struct jtag_tap *tap, uint8_t *ir_in, uint8_t *ir_out,
|
static int mcu_write_ir(struct jtag_tap *tap, uint8_t *ir_in, uint8_t *ir_out,
|
||||||
int ir_len, int rti)
|
int ir_len, int rti)
|
||||||
{
|
{
|
||||||
if (NULL == tap)
|
if (NULL == tap) {
|
||||||
{
|
|
||||||
LOG_ERROR("invalid tap");
|
LOG_ERROR("invalid tap");
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
if (ir_len != tap->ir_length)
|
if (ir_len != tap->ir_length) {
|
||||||
{
|
|
||||||
LOG_ERROR("invalid ir_len");
|
LOG_ERROR("invalid ir_len");
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
@ -194,8 +191,7 @@ static int mcu_write_ir(struct jtag_tap *tap, uint8_t *ir_in, uint8_t *ir_out,
|
||||||
static int mcu_write_dr(struct jtag_tap *tap, uint8_t *dr_in, uint8_t *dr_out,
|
static int mcu_write_dr(struct jtag_tap *tap, uint8_t *dr_in, uint8_t *dr_out,
|
||||||
int dr_len, int rti)
|
int dr_len, int rti)
|
||||||
{
|
{
|
||||||
if (NULL == tap)
|
if (NULL == tap) {
|
||||||
{
|
|
||||||
LOG_ERROR("invalid tap");
|
LOG_ERROR("invalid tap");
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
@ -210,8 +206,7 @@ static int mcu_write_dr(struct jtag_tap *tap, uint8_t *dr_in, uint8_t *dr_out,
|
||||||
static int mcu_write_ir_u8(struct jtag_tap *tap, uint8_t *ir_in,
|
static int mcu_write_ir_u8(struct jtag_tap *tap, uint8_t *ir_in,
|
||||||
uint8_t ir_out, int ir_len, int rti)
|
uint8_t ir_out, int ir_len, int rti)
|
||||||
{
|
{
|
||||||
if (ir_len > 8)
|
if (ir_len > 8) {
|
||||||
{
|
|
||||||
LOG_ERROR("ir_len overflow, maxium is 8");
|
LOG_ERROR("ir_len overflow, maxium is 8");
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
@ -224,13 +219,12 @@ static int mcu_write_ir_u8(struct jtag_tap *tap, uint8_t *ir_in,
|
||||||
static int mcu_write_dr_u32(struct jtag_tap *tap, uint32_t *dr_in,
|
static int mcu_write_dr_u32(struct jtag_tap *tap, uint32_t *dr_in,
|
||||||
uint32_t dr_out, int dr_len, int rti)
|
uint32_t dr_out, int dr_len, int rti)
|
||||||
{
|
{
|
||||||
if (dr_len > 32)
|
if (dr_len > 32) {
|
||||||
{
|
|
||||||
LOG_ERROR("dr_len overflow, maxium is 32");
|
LOG_ERROR("dr_len overflow, maxium is 32");
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
mcu_write_dr(tap, (uint8_t*)dr_in, (uint8_t*)&dr_out, dr_len, rti);
|
mcu_write_dr(tap, (uint8_t *)dr_in, (uint8_t *)&dr_out, dr_len, rti);
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,18 +17,17 @@
|
||||||
* Free Software Foundation, Inc., *
|
* Free Software Foundation, Inc., *
|
||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#ifndef AVRT_H
|
#ifndef AVRT_H
|
||||||
#define AVRT_H
|
#define AVRT_H
|
||||||
|
|
||||||
#include <jtag/jtag.h>
|
#include <jtag/jtag.h>
|
||||||
|
|
||||||
struct mcu_jtag
|
struct mcu_jtag {
|
||||||
{
|
|
||||||
struct jtag_tap *tap;
|
struct jtag_tap *tap;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct avr_common
|
struct avr_common {
|
||||||
{
|
|
||||||
struct mcu_jtag jtag_info;
|
struct mcu_jtag jtag_info;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
* Free Software Foundation, Inc., *
|
* Free Software Foundation, Inc., *
|
||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -28,24 +29,24 @@
|
||||||
#include <helper/log.h>
|
#include <helper/log.h>
|
||||||
#include "breakpoints.h"
|
#include "breakpoints.h"
|
||||||
|
|
||||||
|
static char *breakpoint_type_strings[] = {
|
||||||
static char *breakpoint_type_strings[] =
|
|
||||||
{
|
|
||||||
"hardware",
|
"hardware",
|
||||||
"software"
|
"software"
|
||||||
};
|
};
|
||||||
|
|
||||||
static char *watchpoint_rw_strings[] =
|
static char *watchpoint_rw_strings[] = {
|
||||||
{
|
|
||||||
"read",
|
"read",
|
||||||
"write",
|
"write",
|
||||||
"access"
|
"access"
|
||||||
};
|
};
|
||||||
|
|
||||||
// monotonic counter/id-number for breakpoints and watch points
|
/* monotonic counter/id-number for breakpoints and watch points */
|
||||||
static int bpwp_unique_id;
|
static int bpwp_unique_id;
|
||||||
|
|
||||||
int breakpoint_add_internal(struct target *target, uint32_t address, uint32_t length, enum breakpoint_type type)
|
int breakpoint_add_internal(struct target *target,
|
||||||
|
uint32_t address,
|
||||||
|
uint32_t length,
|
||||||
|
enum breakpoint_type type)
|
||||||
{
|
{
|
||||||
struct breakpoint *breakpoint = target->breakpoints;
|
struct breakpoint *breakpoint = target->breakpoints;
|
||||||
struct breakpoint **breakpoint_p = &target->breakpoints;
|
struct breakpoint **breakpoint_p = &target->breakpoints;
|
||||||
|
@ -54,8 +55,7 @@ int breakpoint_add_internal(struct target *target, uint32_t address, uint32_t le
|
||||||
int n;
|
int n;
|
||||||
|
|
||||||
n = 0;
|
n = 0;
|
||||||
while (breakpoint)
|
while (breakpoint) {
|
||||||
{
|
|
||||||
n++;
|
n++;
|
||||||
if (breakpoint->address == address) {
|
if (breakpoint->address == address) {
|
||||||
/* FIXME don't assume "same address" means "same
|
/* FIXME don't assume "same address" means "same
|
||||||
|
@ -63,7 +63,7 @@ int breakpoint_add_internal(struct target *target, uint32_t address, uint32_t le
|
||||||
* succeeding.
|
* succeeding.
|
||||||
*/
|
*/
|
||||||
LOG_DEBUG("Duplicate Breakpoint address: 0x%08" PRIx32 " (BP %d)",
|
LOG_DEBUG("Duplicate Breakpoint address: 0x%08" PRIx32 " (BP %d)",
|
||||||
address, breakpoint->unique_id);
|
address, breakpoint->unique_id);
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
breakpoint_p = &breakpoint->next;
|
breakpoint_p = &breakpoint->next;
|
||||||
|
@ -82,33 +82,36 @@ int breakpoint_add_internal(struct target *target, uint32_t address, uint32_t le
|
||||||
|
|
||||||
retval = target_add_breakpoint(target, *breakpoint_p);
|
retval = target_add_breakpoint(target, *breakpoint_p);
|
||||||
switch (retval) {
|
switch (retval) {
|
||||||
case ERROR_OK:
|
case ERROR_OK:
|
||||||
break;
|
break;
|
||||||
case ERROR_TARGET_RESOURCE_NOT_AVAILABLE:
|
case ERROR_TARGET_RESOURCE_NOT_AVAILABLE:
|
||||||
reason = "resource not available";
|
reason = "resource not available";
|
||||||
goto fail;
|
goto fail;
|
||||||
case ERROR_TARGET_NOT_HALTED:
|
case ERROR_TARGET_NOT_HALTED:
|
||||||
reason = "target running";
|
reason = "target running";
|
||||||
goto fail;
|
goto fail;
|
||||||
default:
|
default:
|
||||||
reason = "unknown reason";
|
reason = "unknown reason";
|
||||||
fail:
|
fail:
|
||||||
LOG_ERROR("can't add breakpoint: %s", reason);
|
LOG_ERROR("can't add breakpoint: %s", reason);
|
||||||
free((*breakpoint_p)->orig_instr);
|
free((*breakpoint_p)->orig_instr);
|
||||||
free(*breakpoint_p);
|
free(*breakpoint_p);
|
||||||
*breakpoint_p = NULL;
|
*breakpoint_p = NULL;
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_DEBUG("added %s breakpoint at 0x%8.8" PRIx32 " of length 0x%8.8x, (BPID: %d)",
|
LOG_DEBUG("added %s breakpoint at 0x%8.8" PRIx32 " of length 0x%8.8x, (BPID: %d)",
|
||||||
breakpoint_type_strings[(*breakpoint_p)->type],
|
breakpoint_type_strings[(*breakpoint_p)->type],
|
||||||
(*breakpoint_p)->address, (*breakpoint_p)->length,
|
(*breakpoint_p)->address, (*breakpoint_p)->length,
|
||||||
(*breakpoint_p)->unique_id);
|
(*breakpoint_p)->unique_id);
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int context_breakpoint_add_internal(struct target *target, uint32_t asid, uint32_t length, enum breakpoint_type type)
|
int context_breakpoint_add_internal(struct target *target,
|
||||||
|
uint32_t asid,
|
||||||
|
uint32_t length,
|
||||||
|
enum breakpoint_type type)
|
||||||
{
|
{
|
||||||
struct breakpoint *breakpoint = target->breakpoints;
|
struct breakpoint *breakpoint = target->breakpoints;
|
||||||
struct breakpoint **breakpoint_p = &target->breakpoints;
|
struct breakpoint **breakpoint_p = &target->breakpoints;
|
||||||
|
@ -116,17 +119,15 @@ int context_breakpoint_add_internal(struct target *target, uint32_t asid, uint32
|
||||||
int n;
|
int n;
|
||||||
|
|
||||||
n = 0;
|
n = 0;
|
||||||
while (breakpoint)
|
while (breakpoint) {
|
||||||
{
|
|
||||||
n++;
|
n++;
|
||||||
if (breakpoint->asid == asid)
|
if (breakpoint->asid == asid) {
|
||||||
{
|
|
||||||
/* FIXME don't assume "same address" means "same
|
/* FIXME don't assume "same address" means "same
|
||||||
* breakpoint" ... check all the parameters before
|
* breakpoint" ... check all the parameters before
|
||||||
* succeeding.
|
* succeeding.
|
||||||
*/
|
*/
|
||||||
LOG_DEBUG("Duplicate Breakpoint asid: 0x%08" PRIx32 " (BP %d)",
|
LOG_DEBUG("Duplicate Breakpoint asid: 0x%08" PRIx32 " (BP %d)",
|
||||||
asid, breakpoint->unique_id);
|
asid, breakpoint->unique_id);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
breakpoint_p = &breakpoint->next;
|
breakpoint_p = &breakpoint->next;
|
||||||
|
@ -143,8 +144,7 @@ int context_breakpoint_add_internal(struct target *target, uint32_t asid, uint32
|
||||||
(*breakpoint_p)->next = NULL;
|
(*breakpoint_p)->next = NULL;
|
||||||
(*breakpoint_p)->unique_id = bpwp_unique_id++;
|
(*breakpoint_p)->unique_id = bpwp_unique_id++;
|
||||||
retval = target_add_context_breakpoint(target, *breakpoint_p);
|
retval = target_add_context_breakpoint(target, *breakpoint_p);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK) {
|
||||||
{
|
|
||||||
LOG_ERROR("could not add breakpoint");
|
LOG_ERROR("could not add breakpoint");
|
||||||
free((*breakpoint_p)->orig_instr);
|
free((*breakpoint_p)->orig_instr);
|
||||||
free(*breakpoint_p);
|
free(*breakpoint_p);
|
||||||
|
@ -153,22 +153,25 @@ int context_breakpoint_add_internal(struct target *target, uint32_t asid, uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_DEBUG("added %s Context breakpoint at 0x%8.8" PRIx32 " of length 0x%8.8x, (BPID: %d)",
|
LOG_DEBUG("added %s Context breakpoint at 0x%8.8" PRIx32 " of length 0x%8.8x, (BPID: %d)",
|
||||||
breakpoint_type_strings[(*breakpoint_p)->type],
|
breakpoint_type_strings[(*breakpoint_p)->type],
|
||||||
(*breakpoint_p)->asid, (*breakpoint_p)->length,
|
(*breakpoint_p)->asid, (*breakpoint_p)->length,
|
||||||
(*breakpoint_p)->unique_id);
|
(*breakpoint_p)->unique_id);
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int hybrid_breakpoint_add_internal(struct target *target, uint32_t address, uint32_t asid, uint32_t length, enum breakpoint_type type)
|
int hybrid_breakpoint_add_internal(struct target *target,
|
||||||
|
uint32_t address,
|
||||||
|
uint32_t asid,
|
||||||
|
uint32_t length,
|
||||||
|
enum breakpoint_type type)
|
||||||
{
|
{
|
||||||
struct breakpoint *breakpoint = target->breakpoints;
|
struct breakpoint *breakpoint = target->breakpoints;
|
||||||
struct breakpoint **breakpoint_p = &target->breakpoints;
|
struct breakpoint **breakpoint_p = &target->breakpoints;
|
||||||
int retval;
|
int retval;
|
||||||
int n;
|
int n;
|
||||||
n = 0;
|
n = 0;
|
||||||
while (breakpoint)
|
while (breakpoint) {
|
||||||
{
|
|
||||||
n++;
|
n++;
|
||||||
if ((breakpoint->asid == asid) && (breakpoint->address == address)) {
|
if ((breakpoint->asid == asid) && (breakpoint->address == address)) {
|
||||||
/* FIXME don't assume "same address" means "same
|
/* FIXME don't assume "same address" means "same
|
||||||
|
@ -176,13 +179,11 @@ int hybrid_breakpoint_add_internal(struct target *target, uint32_t address, uint
|
||||||
* succeeding.
|
* succeeding.
|
||||||
*/
|
*/
|
||||||
LOG_DEBUG("Duplicate Hybrid Breakpoint asid: 0x%08" PRIx32 " (BP %d)",
|
LOG_DEBUG("Duplicate Hybrid Breakpoint asid: 0x%08" PRIx32 " (BP %d)",
|
||||||
asid, breakpoint->unique_id);
|
asid, breakpoint->unique_id);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
} else if ((breakpoint->address == address) && (breakpoint->asid == 0)) {
|
||||||
else if ((breakpoint->address == address) && (breakpoint->asid == 0))
|
|
||||||
{
|
|
||||||
LOG_DEBUG("Duplicate Breakpoint IVA: 0x%08" PRIx32 " (BP %d)",
|
LOG_DEBUG("Duplicate Breakpoint IVA: 0x%08" PRIx32 " (BP %d)",
|
||||||
address, breakpoint->unique_id);
|
address, breakpoint->unique_id);
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -201,92 +202,89 @@ int hybrid_breakpoint_add_internal(struct target *target, uint32_t address, uint
|
||||||
|
|
||||||
|
|
||||||
retval = target_add_hybrid_breakpoint(target, *breakpoint_p);
|
retval = target_add_hybrid_breakpoint(target, *breakpoint_p);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK) {
|
||||||
{
|
|
||||||
LOG_ERROR("could not add breakpoint");
|
LOG_ERROR("could not add breakpoint");
|
||||||
free((*breakpoint_p)->orig_instr);
|
free((*breakpoint_p)->orig_instr);
|
||||||
free(*breakpoint_p);
|
free(*breakpoint_p);
|
||||||
*breakpoint_p = NULL;
|
*breakpoint_p = NULL;
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
LOG_DEBUG("added %s Hybrid breakpoint at address 0x%8.8" PRIx32 " of length 0x%8.8x, (BPID: %d)",
|
LOG_DEBUG(
|
||||||
breakpoint_type_strings[(*breakpoint_p)->type],
|
"added %s Hybrid breakpoint at address 0x%8.8" PRIx32 " of length 0x%8.8x, (BPID: %d)",
|
||||||
(*breakpoint_p)->address, (*breakpoint_p)->length,
|
breakpoint_type_strings[(*breakpoint_p)->type],
|
||||||
(*breakpoint_p)->unique_id);
|
(*breakpoint_p)->address,
|
||||||
|
(*breakpoint_p)->length,
|
||||||
|
(*breakpoint_p)->unique_id);
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int breakpoint_add(struct target *target,
|
||||||
|
uint32_t address,
|
||||||
int breakpoint_add(struct target *target, uint32_t address, uint32_t length, enum breakpoint_type type)
|
uint32_t length,
|
||||||
|
enum breakpoint_type type)
|
||||||
{
|
{
|
||||||
|
|
||||||
int retval = ERROR_OK;
|
int retval = ERROR_OK;
|
||||||
if (target->smp)
|
if (target->smp) {
|
||||||
{
|
|
||||||
struct target_list *head;
|
struct target_list *head;
|
||||||
struct target *curr;
|
struct target *curr;
|
||||||
head = target->head;
|
head = target->head;
|
||||||
if (type == BKPT_SOFT)
|
if (type == BKPT_SOFT)
|
||||||
return(breakpoint_add_internal(head->target, address,length, type));
|
return breakpoint_add_internal(head->target, address, length, type);
|
||||||
|
|
||||||
while(head != (struct target_list*)NULL)
|
while (head != (struct target_list *)NULL) {
|
||||||
{
|
|
||||||
curr = head->target;
|
curr = head->target;
|
||||||
retval = breakpoint_add_internal(curr, address,length, type);
|
retval = breakpoint_add_internal(curr, address, length, type);
|
||||||
if (retval != ERROR_OK) return retval;
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
head = head->next;
|
head = head->next;
|
||||||
}
|
}
|
||||||
return retval;
|
return retval;
|
||||||
}
|
} else
|
||||||
else
|
return breakpoint_add_internal(target, address, length, type);
|
||||||
return(breakpoint_add_internal(target, address, length, type));
|
|
||||||
|
|
||||||
}
|
}
|
||||||
int context_breakpoint_add(struct target *target, uint32_t asid, uint32_t length, enum breakpoint_type type)
|
int context_breakpoint_add(struct target *target,
|
||||||
|
uint32_t asid,
|
||||||
|
uint32_t length,
|
||||||
|
enum breakpoint_type type)
|
||||||
{
|
{
|
||||||
|
|
||||||
int retval = ERROR_OK;
|
int retval = ERROR_OK;
|
||||||
if (target->smp)
|
if (target->smp) {
|
||||||
{
|
|
||||||
struct target_list *head;
|
struct target_list *head;
|
||||||
struct target *curr;
|
struct target *curr;
|
||||||
head = target->head;
|
head = target->head;
|
||||||
while(head != (struct target_list*)NULL)
|
while (head != (struct target_list *)NULL) {
|
||||||
{
|
|
||||||
curr = head->target;
|
curr = head->target;
|
||||||
retval = context_breakpoint_add_internal(curr, asid,length, type);
|
retval = context_breakpoint_add_internal(curr, asid, length, type);
|
||||||
if (retval != ERROR_OK) return retval;
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
head = head->next;
|
head = head->next;
|
||||||
}
|
}
|
||||||
return retval;
|
return retval;
|
||||||
}
|
} else
|
||||||
else
|
return context_breakpoint_add_internal(target, asid, length, type);
|
||||||
return(context_breakpoint_add_internal(target, asid, length, type));
|
|
||||||
|
|
||||||
}
|
}
|
||||||
int hybrid_breakpoint_add(struct target *target, uint32_t address, uint32_t asid, uint32_t length, enum breakpoint_type type)
|
int hybrid_breakpoint_add(struct target *target,
|
||||||
|
uint32_t address,
|
||||||
|
uint32_t asid,
|
||||||
|
uint32_t length,
|
||||||
|
enum breakpoint_type type)
|
||||||
{
|
{
|
||||||
|
|
||||||
int retval = ERROR_OK;
|
int retval = ERROR_OK;
|
||||||
if (target->smp)
|
if (target->smp) {
|
||||||
{
|
|
||||||
struct target_list *head;
|
struct target_list *head;
|
||||||
struct target *curr;
|
struct target *curr;
|
||||||
head = target->head;
|
head = target->head;
|
||||||
while(head != (struct target_list*)NULL)
|
while (head != (struct target_list *)NULL) {
|
||||||
{
|
|
||||||
curr = head->target;
|
curr = head->target;
|
||||||
retval = hybrid_breakpoint_add_internal(curr, address, asid, length, type);
|
retval = hybrid_breakpoint_add_internal(curr, address, asid, length, type);
|
||||||
if (retval != ERROR_OK) return retval;
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
head = head->next;
|
head = head->next;
|
||||||
}
|
}
|
||||||
return retval;
|
return retval;
|
||||||
}
|
} else
|
||||||
else
|
return hybrid_breakpoint_add_internal(target, address, asid, length, type);
|
||||||
return(hybrid_breakpoint_add_internal(target, address, asid, length, type));
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* free up a breakpoint */
|
/* free up a breakpoint */
|
||||||
|
@ -296,8 +294,7 @@ static void breakpoint_free(struct target *target, struct breakpoint *breakpoint
|
||||||
struct breakpoint **breakpoint_p = &target->breakpoints;
|
struct breakpoint **breakpoint_p = &target->breakpoints;
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
while (breakpoint)
|
while (breakpoint) {
|
||||||
{
|
|
||||||
if (breakpoint == breakpoint_to_remove)
|
if (breakpoint == breakpoint_to_remove)
|
||||||
break;
|
break;
|
||||||
breakpoint_p = &breakpoint->next;
|
breakpoint_p = &breakpoint->next;
|
||||||
|
@ -319,8 +316,7 @@ int breakpoint_remove_internal(struct target *target, uint32_t address)
|
||||||
{
|
{
|
||||||
struct breakpoint *breakpoint = target->breakpoints;
|
struct breakpoint *breakpoint = target->breakpoints;
|
||||||
|
|
||||||
while (breakpoint)
|
while (breakpoint) {
|
||||||
{
|
|
||||||
if ((breakpoint->address == address) && (breakpoint->asid == 0))
|
if ((breakpoint->address == address) && (breakpoint->asid == 0))
|
||||||
break;
|
break;
|
||||||
else if ((breakpoint->address == 0) && (breakpoint->asid == address))
|
else if ((breakpoint->address == 0) && (breakpoint->asid == address))
|
||||||
|
@ -330,13 +326,10 @@ int breakpoint_remove_internal(struct target *target, uint32_t address)
|
||||||
breakpoint = breakpoint->next;
|
breakpoint = breakpoint->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (breakpoint)
|
if (breakpoint) {
|
||||||
{
|
|
||||||
breakpoint_free(target, breakpoint);
|
breakpoint_free(target, breakpoint);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
if (!target->smp)
|
if (!target->smp)
|
||||||
LOG_ERROR("no breakpoint at address 0x%8.8" PRIx32 " found", address);
|
LOG_ERROR("no breakpoint at address 0x%8.8" PRIx32 " found", address);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -345,60 +338,50 @@ int breakpoint_remove_internal(struct target *target, uint32_t address)
|
||||||
void breakpoint_remove(struct target *target, uint32_t address)
|
void breakpoint_remove(struct target *target, uint32_t address)
|
||||||
{
|
{
|
||||||
int found = 0;
|
int found = 0;
|
||||||
if (target->smp)
|
if (target->smp) {
|
||||||
{
|
|
||||||
struct target_list *head;
|
struct target_list *head;
|
||||||
struct target *curr;
|
struct target *curr;
|
||||||
head = target->head;
|
head = target->head;
|
||||||
while(head != (struct target_list*)NULL)
|
while (head != (struct target_list *)NULL) {
|
||||||
{
|
|
||||||
curr = head->target;
|
curr = head->target;
|
||||||
found += breakpoint_remove_internal(curr, address);
|
found += breakpoint_remove_internal(curr, address);
|
||||||
head = head->next;
|
head = head->next;
|
||||||
}
|
}
|
||||||
if (found == 0)
|
if (found == 0)
|
||||||
LOG_ERROR("no breakpoint at address 0x%8.8" PRIx32 " found", address);
|
LOG_ERROR("no breakpoint at address 0x%8.8" PRIx32 " found", address);
|
||||||
}
|
} else
|
||||||
else breakpoint_remove_internal(target, address);
|
breakpoint_remove_internal(target, address);
|
||||||
}
|
}
|
||||||
|
|
||||||
void breakpoint_clear_target_internal(struct target *target)
|
void breakpoint_clear_target_internal(struct target *target)
|
||||||
{
|
{
|
||||||
struct breakpoint *breakpoint;
|
|
||||||
|
|
||||||
LOG_DEBUG("Delete all breakpoints for target: %s",
|
LOG_DEBUG("Delete all breakpoints for target: %s",
|
||||||
target_name(target));
|
target_name(target));
|
||||||
while ((breakpoint = target->breakpoints) != NULL)
|
while (target->breakpoints != NULL)
|
||||||
{
|
breakpoint_free(target, target->breakpoints);
|
||||||
breakpoint_free(target, breakpoint);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void breakpoint_clear_target(struct target *target)
|
void breakpoint_clear_target(struct target *target)
|
||||||
{
|
{
|
||||||
if (target->smp)
|
if (target->smp) {
|
||||||
{
|
|
||||||
struct target_list *head;
|
struct target_list *head;
|
||||||
struct target *curr;
|
struct target *curr;
|
||||||
head = target->head;
|
head = target->head;
|
||||||
while(head != (struct target_list*)NULL)
|
while (head != (struct target_list *)NULL) {
|
||||||
{
|
|
||||||
curr = head->target;
|
curr = head->target;
|
||||||
breakpoint_clear_target_internal(curr);
|
breakpoint_clear_target_internal(curr);
|
||||||
head = head->next;
|
head = head->next;
|
||||||
}
|
}
|
||||||
}
|
} else
|
||||||
else breakpoint_clear_target_internal(target);
|
breakpoint_clear_target_internal(target);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct breakpoint *breakpoint_find(struct target *target, uint32_t address)
|
||||||
struct breakpoint* breakpoint_find(struct target *target, uint32_t address)
|
|
||||||
{
|
{
|
||||||
struct breakpoint *breakpoint = target->breakpoints;
|
struct breakpoint *breakpoint = target->breakpoints;
|
||||||
|
|
||||||
while (breakpoint)
|
while (breakpoint) {
|
||||||
{
|
|
||||||
if (breakpoint->address == address)
|
if (breakpoint->address == address)
|
||||||
return breakpoint;
|
return breakpoint;
|
||||||
breakpoint = breakpoint->next;
|
breakpoint = breakpoint->next;
|
||||||
|
@ -408,23 +391,22 @@ struct breakpoint* breakpoint_find(struct target *target, uint32_t address)
|
||||||
}
|
}
|
||||||
|
|
||||||
int watchpoint_add(struct target *target, uint32_t address, uint32_t length,
|
int watchpoint_add(struct target *target, uint32_t address, uint32_t length,
|
||||||
enum watchpoint_rw rw, uint32_t value, uint32_t mask)
|
enum watchpoint_rw rw, uint32_t value, uint32_t mask)
|
||||||
{
|
{
|
||||||
struct watchpoint *watchpoint = target->watchpoints;
|
struct watchpoint *watchpoint = target->watchpoints;
|
||||||
struct watchpoint **watchpoint_p = &target->watchpoints;
|
struct watchpoint **watchpoint_p = &target->watchpoints;
|
||||||
int retval;
|
int retval;
|
||||||
char *reason;
|
char *reason;
|
||||||
|
|
||||||
while (watchpoint)
|
while (watchpoint) {
|
||||||
{
|
|
||||||
if (watchpoint->address == address) {
|
if (watchpoint->address == address) {
|
||||||
if (watchpoint->length != length
|
if (watchpoint->length != length
|
||||||
|| watchpoint->value != value
|
|| watchpoint->value != value
|
||||||
|| watchpoint->mask != mask
|
|| watchpoint->mask != mask
|
||||||
|| watchpoint->rw != rw) {
|
|| watchpoint->rw != rw) {
|
||||||
LOG_ERROR("address 0x%8.8" PRIx32
|
LOG_ERROR("address 0x%8.8" PRIx32
|
||||||
"already has watchpoint %d",
|
"already has watchpoint %d",
|
||||||
address, watchpoint->unique_id);
|
address, watchpoint->unique_id);
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -445,31 +427,31 @@ int watchpoint_add(struct target *target, uint32_t address, uint32_t length,
|
||||||
|
|
||||||
retval = target_add_watchpoint(target, *watchpoint_p);
|
retval = target_add_watchpoint(target, *watchpoint_p);
|
||||||
switch (retval) {
|
switch (retval) {
|
||||||
case ERROR_OK:
|
case ERROR_OK:
|
||||||
break;
|
break;
|
||||||
case ERROR_TARGET_RESOURCE_NOT_AVAILABLE:
|
case ERROR_TARGET_RESOURCE_NOT_AVAILABLE:
|
||||||
reason = "resource not available";
|
reason = "resource not available";
|
||||||
goto bye;
|
goto bye;
|
||||||
case ERROR_TARGET_NOT_HALTED:
|
case ERROR_TARGET_NOT_HALTED:
|
||||||
reason = "target running";
|
reason = "target running";
|
||||||
goto bye;
|
goto bye;
|
||||||
default:
|
default:
|
||||||
reason = "unrecognized error";
|
reason = "unrecognized error";
|
||||||
bye:
|
bye:
|
||||||
LOG_ERROR("can't add %s watchpoint at 0x%8.8" PRIx32 ", %s",
|
LOG_ERROR("can't add %s watchpoint at 0x%8.8" PRIx32 ", %s",
|
||||||
watchpoint_rw_strings[(*watchpoint_p)->rw],
|
watchpoint_rw_strings[(*watchpoint_p)->rw],
|
||||||
address, reason);
|
address, reason);
|
||||||
free (*watchpoint_p);
|
free(*watchpoint_p);
|
||||||
*watchpoint_p = NULL;
|
*watchpoint_p = NULL;
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_DEBUG("added %s watchpoint at 0x%8.8" PRIx32
|
LOG_DEBUG("added %s watchpoint at 0x%8.8" PRIx32
|
||||||
" of length 0x%8.8" PRIx32 " (WPID: %d)",
|
" of length 0x%8.8" PRIx32 " (WPID: %d)",
|
||||||
watchpoint_rw_strings[(*watchpoint_p)->rw],
|
watchpoint_rw_strings[(*watchpoint_p)->rw],
|
||||||
(*watchpoint_p)->address,
|
(*watchpoint_p)->address,
|
||||||
(*watchpoint_p)->length,
|
(*watchpoint_p)->length,
|
||||||
(*watchpoint_p)->unique_id);
|
(*watchpoint_p)->unique_id);
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
@ -480,8 +462,7 @@ static void watchpoint_free(struct target *target, struct watchpoint *watchpoint
|
||||||
struct watchpoint **watchpoint_p = &target->watchpoints;
|
struct watchpoint **watchpoint_p = &target->watchpoints;
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
while (watchpoint)
|
while (watchpoint) {
|
||||||
{
|
|
||||||
if (watchpoint == watchpoint_to_remove)
|
if (watchpoint == watchpoint_to_remove)
|
||||||
break;
|
break;
|
||||||
watchpoint_p = &watchpoint->next;
|
watchpoint_p = &watchpoint->next;
|
||||||
|
@ -500,31 +481,22 @@ void watchpoint_remove(struct target *target, uint32_t address)
|
||||||
{
|
{
|
||||||
struct watchpoint *watchpoint = target->watchpoints;
|
struct watchpoint *watchpoint = target->watchpoints;
|
||||||
|
|
||||||
while (watchpoint)
|
while (watchpoint) {
|
||||||
{
|
|
||||||
if (watchpoint->address == address)
|
if (watchpoint->address == address)
|
||||||
break;
|
break;
|
||||||
watchpoint = watchpoint->next;
|
watchpoint = watchpoint->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (watchpoint)
|
if (watchpoint)
|
||||||
{
|
|
||||||
watchpoint_free(target, watchpoint);
|
watchpoint_free(target, watchpoint);
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
LOG_ERROR("no watchpoint at address 0x%8.8" PRIx32 " found", address);
|
LOG_ERROR("no watchpoint at address 0x%8.8" PRIx32 " found", address);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void watchpoint_clear_target(struct target *target)
|
void watchpoint_clear_target(struct target *target)
|
||||||
{
|
{
|
||||||
struct watchpoint *watchpoint;
|
|
||||||
|
|
||||||
LOG_DEBUG("Delete all watchpoints for target: %s",
|
LOG_DEBUG("Delete all watchpoints for target: %s",
|
||||||
target_name(target));
|
target_name(target));
|
||||||
while ((watchpoint = target->watchpoints) != NULL)
|
while (target->watchpoints != NULL)
|
||||||
{
|
watchpoint_free(target, target->watchpoints);
|
||||||
watchpoint_free(target, watchpoint);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
* Free Software Foundation, Inc., *
|
* Free Software Foundation, Inc., *
|
||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#ifndef BREAKPOINTS_H
|
#ifndef BREAKPOINTS_H
|
||||||
#define BREAKPOINTS_H
|
#define BREAKPOINTS_H
|
||||||
|
|
||||||
|
@ -24,19 +25,16 @@
|
||||||
|
|
||||||
struct target;
|
struct target;
|
||||||
|
|
||||||
enum breakpoint_type
|
enum breakpoint_type {
|
||||||
{
|
|
||||||
BKPT_HARD,
|
BKPT_HARD,
|
||||||
BKPT_SOFT,
|
BKPT_SOFT,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum watchpoint_rw
|
enum watchpoint_rw {
|
||||||
{
|
|
||||||
WPT_READ = 0, WPT_WRITE = 1, WPT_ACCESS = 2
|
WPT_READ = 0, WPT_WRITE = 1, WPT_ACCESS = 2
|
||||||
};
|
};
|
||||||
|
|
||||||
struct breakpoint
|
struct breakpoint {
|
||||||
{
|
|
||||||
uint32_t address;
|
uint32_t address;
|
||||||
uint32_t asid;
|
uint32_t asid;
|
||||||
int length;
|
int length;
|
||||||
|
@ -45,11 +43,10 @@ struct breakpoint
|
||||||
uint8_t *orig_instr;
|
uint8_t *orig_instr;
|
||||||
struct breakpoint *next;
|
struct breakpoint *next;
|
||||||
uint32_t unique_id;
|
uint32_t unique_id;
|
||||||
int linked_BRP;
|
int linked_BRP;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct watchpoint
|
struct watchpoint {
|
||||||
{
|
|
||||||
uint32_t address;
|
uint32_t address;
|
||||||
uint32_t length;
|
uint32_t length;
|
||||||
uint32_t mask;
|
uint32_t mask;
|
||||||
|
@ -69,7 +66,7 @@ int hybrid_breakpoint_add(struct target *target,
|
||||||
uint32_t address, uint32_t asid, uint32_t length, enum breakpoint_type type);
|
uint32_t address, uint32_t asid, uint32_t length, enum breakpoint_type type);
|
||||||
void breakpoint_remove(struct target *target, uint32_t address);
|
void breakpoint_remove(struct target *target, uint32_t address);
|
||||||
|
|
||||||
struct breakpoint* breakpoint_find(struct target *target, uint32_t address);
|
struct breakpoint *breakpoint_find(struct target *target, uint32_t address);
|
||||||
|
|
||||||
void watchpoint_clear_target(struct target *target);
|
void watchpoint_clear_target(struct target *target);
|
||||||
int watchpoint_add(struct target *target,
|
int watchpoint_add(struct target *target,
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -26,6 +26,7 @@
|
||||||
* Free Software Foundation, Inc., *
|
* Free Software Foundation, Inc., *
|
||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#ifndef CORTEX_A8_H
|
#ifndef CORTEX_A8_H
|
||||||
#define CORTEX_A8_H
|
#define CORTEX_A8_H
|
||||||
|
|
||||||
|
@ -44,8 +45,7 @@
|
||||||
|
|
||||||
#define CORTEX_A8_PADDRDBG_CPU_SHIFT 13
|
#define CORTEX_A8_PADDRDBG_CPU_SHIFT 13
|
||||||
|
|
||||||
struct cortex_a8_brp
|
struct cortex_a8_brp {
|
||||||
{
|
|
||||||
int used;
|
int used;
|
||||||
int type;
|
int type;
|
||||||
uint32_t value;
|
uint32_t value;
|
||||||
|
@ -53,8 +53,7 @@ struct cortex_a8_brp
|
||||||
uint8_t BRPn;
|
uint8_t BRPn;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct cortex_a8_common
|
struct cortex_a8_common {
|
||||||
{
|
|
||||||
int common_magic;
|
int common_magic;
|
||||||
struct arm_jtag jtag_info;
|
struct arm_jtag jtag_info;
|
||||||
|
|
||||||
|
@ -65,7 +64,7 @@ struct cortex_a8_common
|
||||||
uint32_t cp15_control_reg;
|
uint32_t cp15_control_reg;
|
||||||
/* latest cp15 register value written and cpsr processor mode */
|
/* latest cp15 register value written and cpsr processor mode */
|
||||||
uint32_t cp15_control_reg_curr;
|
uint32_t cp15_control_reg_curr;
|
||||||
enum arm_mode curr_mode;
|
enum arm_mode curr_mode;
|
||||||
|
|
||||||
|
|
||||||
/* Breakpoint register pairs */
|
/* Breakpoint register pairs */
|
||||||
|
@ -84,8 +83,7 @@ struct cortex_a8_common
|
||||||
static inline struct cortex_a8_common *
|
static inline struct cortex_a8_common *
|
||||||
target_to_cortex_a8(struct target *target)
|
target_to_cortex_a8(struct target *target)
|
||||||
{
|
{
|
||||||
return container_of(target->arch_info, struct cortex_a8_common,
|
return container_of(target->arch_info, struct cortex_a8_common, armv7a_common.arm);
|
||||||
armv7a_common.arm);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* CORTEX_A8_H */
|
#endif /* CORTEX_A8_H */
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -23,12 +23,12 @@
|
||||||
* Free Software Foundation, Inc., *
|
* Free Software Foundation, Inc., *
|
||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#ifndef CORTEX_M3_H
|
#ifndef CORTEX_M3_H
|
||||||
#define CORTEX_M3_H
|
#define CORTEX_M3_H
|
||||||
|
|
||||||
#include "armv7m.h"
|
#include "armv7m.h"
|
||||||
|
|
||||||
|
|
||||||
#define CORTEX_M3_COMMON_MAGIC 0x1A451A45
|
#define CORTEX_M3_COMMON_MAGIC 0x1A451A45
|
||||||
|
|
||||||
#define SYSTEM_CONTROL_BASE 0x400FE000
|
#define SYSTEM_CONTROL_BASE 0x400FE000
|
||||||
|
@ -117,16 +117,14 @@
|
||||||
#define FPCR_REPLACE_BKPT_HIGH (2 << 30)
|
#define FPCR_REPLACE_BKPT_HIGH (2 << 30)
|
||||||
#define FPCR_REPLACE_BKPT_BOTH (3 << 30)
|
#define FPCR_REPLACE_BKPT_BOTH (3 << 30)
|
||||||
|
|
||||||
struct cortex_m3_fp_comparator
|
struct cortex_m3_fp_comparator {
|
||||||
{
|
|
||||||
int used;
|
int used;
|
||||||
int type;
|
int type;
|
||||||
uint32_t fpcr_value;
|
uint32_t fpcr_value;
|
||||||
uint32_t fpcr_address;
|
uint32_t fpcr_address;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct cortex_m3_dwt_comparator
|
struct cortex_m3_dwt_comparator {
|
||||||
{
|
|
||||||
int used;
|
int used;
|
||||||
uint32_t comp;
|
uint32_t comp;
|
||||||
uint32_t mask;
|
uint32_t mask;
|
||||||
|
@ -134,21 +132,18 @@ struct cortex_m3_dwt_comparator
|
||||||
uint32_t dwt_comparator_address;
|
uint32_t dwt_comparator_address;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum cortex_m3_soft_reset_config
|
enum cortex_m3_soft_reset_config {
|
||||||
{
|
|
||||||
CORTEX_M3_RESET_SYSRESETREQ,
|
CORTEX_M3_RESET_SYSRESETREQ,
|
||||||
CORTEX_M3_RESET_VECTRESET,
|
CORTEX_M3_RESET_VECTRESET,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum cortex_m3_isrmasking_mode
|
enum cortex_m3_isrmasking_mode {
|
||||||
{
|
|
||||||
CORTEX_M3_ISRMASK_AUTO,
|
CORTEX_M3_ISRMASK_AUTO,
|
||||||
CORTEX_M3_ISRMASK_OFF,
|
CORTEX_M3_ISRMASK_OFF,
|
||||||
CORTEX_M3_ISRMASK_ON,
|
CORTEX_M3_ISRMASK_ON,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct cortex_m3_common
|
struct cortex_m3_common {
|
||||||
{
|
|
||||||
int common_magic;
|
int common_magic;
|
||||||
struct arm_jtag jtag_info;
|
struct arm_jtag jtag_info;
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -17,6 +17,7 @@
|
||||||
* Free Software Foundation, Inc., *
|
* Free Software Foundation, Inc., *
|
||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#ifndef DSP563XX_H
|
#ifndef DSP563XX_H
|
||||||
#define DSP563XX_H
|
#define DSP563XX_H
|
||||||
|
|
||||||
|
@ -26,25 +27,22 @@
|
||||||
#define DSP563XX_NUMCOREREGS 54
|
#define DSP563XX_NUMCOREREGS 54
|
||||||
#define DSP563XX_NUMONCEREGS 25
|
#define DSP563XX_NUMONCEREGS 25
|
||||||
|
|
||||||
struct mcu_jtag
|
struct mcu_jtag {
|
||||||
{
|
|
||||||
struct jtag_tap *tap;
|
struct jtag_tap *tap;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct dsp563xx_common
|
struct dsp563xx_common {
|
||||||
{
|
|
||||||
struct mcu_jtag jtag_info;
|
struct mcu_jtag jtag_info;
|
||||||
struct reg_cache *core_cache;
|
struct reg_cache *core_cache;
|
||||||
uint32_t core_regs[DSP563XX_NUMCOREREGS];
|
uint32_t core_regs[DSP563XX_NUMCOREREGS];
|
||||||
struct once_reg once_regs[DSP563XX_NUMONCEREGS];
|
struct once_reg once_regs[DSP563XX_NUMONCEREGS];
|
||||||
|
|
||||||
/* register cache to processor synchronization */
|
/* register cache to processor synchronization */
|
||||||
int (*read_core_reg) (struct target * target, int num);
|
int (*read_core_reg) (struct target *target, int num);
|
||||||
int (*write_core_reg) (struct target * target, int num);
|
int (*write_core_reg) (struct target *target, int num);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct dsp563xx_core_reg
|
struct dsp563xx_core_reg {
|
||||||
{
|
|
||||||
uint32_t num;
|
uint32_t num;
|
||||||
const char *name;
|
const char *name;
|
||||||
uint32_t size;
|
uint32_t size;
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
* Free Software Foundation, Inc., *
|
* Free Software Foundation, Inc., *
|
||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -63,7 +64,7 @@ static inline int dsp563xx_write_dr_u8(struct jtag_tap *tap, uint8_t * dr_in, ui
|
||||||
/** */
|
/** */
|
||||||
static inline int dsp563xx_write_dr_u32(struct jtag_tap *tap, uint32_t * dr_in, uint32_t dr_out, int dr_len, int rti)
|
static inline int dsp563xx_write_dr_u32(struct jtag_tap *tap, uint32_t * dr_in, uint32_t dr_out, int dr_len, int rti)
|
||||||
{
|
{
|
||||||
return dsp563xx_write_dr(tap, (uint8_t *) dr_in, (uint8_t *) & dr_out, dr_len, rti);
|
return dsp563xx_write_dr(tap, (uint8_t *) dr_in, (uint8_t *) &dr_out, dr_len, rti);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** single word instruction */
|
/** single word instruction */
|
||||||
|
@ -71,9 +72,10 @@ static inline int dsp563xx_once_ir_exec(struct jtag_tap *tap, int flush, uint8_t
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
if ((err = dsp563xx_write_dr_u8(tap, 0, instr | (ex << 5) | (go << 6) | (rw << 7), 8, 0)) != ERROR_OK)
|
err = dsp563xx_write_dr_u8(tap, 0, instr | (ex << 5) | (go << 6) | (rw << 7), 8, 0);
|
||||||
|
if (err != ERROR_OK)
|
||||||
return err;
|
return err;
|
||||||
if ( flush )
|
if (flush)
|
||||||
err = jtag_execute_queue();
|
err = jtag_execute_queue();
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
@ -102,13 +104,15 @@ int dsp563xx_once_target_status(struct jtag_tap *tap)
|
||||||
int err;
|
int err;
|
||||||
uint8_t jtag_status;
|
uint8_t jtag_status;
|
||||||
|
|
||||||
if ((err = dsp563xx_jtag_sendinstr(tap, &jtag_status, JTAG_INSTR_ENABLE_ONCE)) != ERROR_OK)
|
err = dsp563xx_jtag_sendinstr(tap, &jtag_status, JTAG_INSTR_ENABLE_ONCE);
|
||||||
|
if (err != ERROR_OK)
|
||||||
return TARGET_UNKNOWN;
|
return TARGET_UNKNOWN;
|
||||||
if ((err = jtag_execute_queue()) != ERROR_OK)
|
err = jtag_execute_queue();
|
||||||
|
if (err != ERROR_OK)
|
||||||
return TARGET_UNKNOWN;
|
return TARGET_UNKNOWN;
|
||||||
|
|
||||||
/* verify correct static status pattern */
|
/* verify correct static status pattern */
|
||||||
if ( (jtag_status & JTAG_STATUS_STATIC_MASK) != JTAG_STATUS_STATIC_VALUE )
|
if ((jtag_status & JTAG_STATUS_STATIC_MASK) != JTAG_STATUS_STATIC_VALUE)
|
||||||
return TARGET_UNKNOWN;
|
return TARGET_UNKNOWN;
|
||||||
|
|
||||||
if (jtag_status != JTAG_STATUS_DEBUG)
|
if (jtag_status != JTAG_STATUS_DEBUG)
|
||||||
|
@ -127,59 +131,50 @@ int dsp563xx_once_request_debug(struct jtag_tap *tap, int reset_state)
|
||||||
/* in reset state we only get a ACK
|
/* in reset state we only get a ACK
|
||||||
* from the interface */
|
* from the interface */
|
||||||
if (reset_state)
|
if (reset_state)
|
||||||
{
|
|
||||||
pattern = 1;
|
pattern = 1;
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
pattern = JTAG_STATUS_DEBUG;
|
pattern = JTAG_STATUS_DEBUG;
|
||||||
}
|
|
||||||
|
|
||||||
/* wait until we get the ack */
|
/* wait until we get the ack */
|
||||||
while (ir_in != pattern)
|
while (ir_in != pattern) {
|
||||||
{
|
err = dsp563xx_jtag_sendinstr(tap, &ir_in, JTAG_INSTR_DEBUG_REQUEST);
|
||||||
if ((err = dsp563xx_jtag_sendinstr(tap, &ir_in, JTAG_INSTR_DEBUG_REQUEST)) != ERROR_OK)
|
if (err != ERROR_OK)
|
||||||
return err;
|
return err;
|
||||||
if ((err = jtag_execute_queue()) != ERROR_OK)
|
err = jtag_execute_queue();
|
||||||
|
if (err != ERROR_OK)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
LOG_DEBUG("debug request: %02X", ir_in);
|
LOG_DEBUG("debug request: %02X", ir_in);
|
||||||
|
|
||||||
if (retry++ == 100)
|
if (retry++ == 100)
|
||||||
{
|
|
||||||
return ERROR_TARGET_FAILURE;
|
return ERROR_TARGET_FAILURE;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* we cant enable the once in reset state */
|
/* we cant enable the once in reset state */
|
||||||
if (pattern == 1)
|
if (pattern == 1)
|
||||||
{
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
|
||||||
|
|
||||||
/* try to enable once */
|
/* try to enable once */
|
||||||
retry = 0;
|
retry = 0;
|
||||||
ir_in = 0;
|
ir_in = 0;
|
||||||
while (ir_in != pattern)
|
while (ir_in != pattern) {
|
||||||
{
|
err = dsp563xx_jtag_sendinstr(tap, &ir_in, JTAG_INSTR_ENABLE_ONCE);
|
||||||
if ((err = dsp563xx_jtag_sendinstr(tap, &ir_in, JTAG_INSTR_ENABLE_ONCE)) != ERROR_OK)
|
if (err != ERROR_OK)
|
||||||
return err;
|
return err;
|
||||||
if ((err = jtag_execute_queue()) != ERROR_OK)
|
err = jtag_execute_queue();
|
||||||
|
if (err != ERROR_OK)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
LOG_DEBUG("enable once: %02X", ir_in);
|
LOG_DEBUG("enable once: %02X", ir_in);
|
||||||
|
|
||||||
if (retry++ == 100)
|
if (retry++ == 100) {
|
||||||
{
|
|
||||||
LOG_DEBUG("error");
|
LOG_DEBUG("error");
|
||||||
return ERROR_TARGET_FAILURE;
|
return ERROR_TARGET_FAILURE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ir_in != JTAG_STATUS_DEBUG)
|
if (ir_in != JTAG_STATUS_DEBUG)
|
||||||
{
|
|
||||||
return ERROR_TARGET_FAILURE;
|
return ERROR_TARGET_FAILURE;
|
||||||
}
|
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
@ -190,13 +185,13 @@ int dsp563xx_once_read_register(struct jtag_tap *tap, int flush, struct once_reg
|
||||||
int i;
|
int i;
|
||||||
int err = ERROR_OK;
|
int err = ERROR_OK;
|
||||||
|
|
||||||
for (i = 0; i < len; i++)
|
for (i = 0; i < len; i++) {
|
||||||
{
|
err = dsp563xx_once_reg_read_ex(tap, flush, regs[i].addr, regs[i].len, ®s[i].reg);
|
||||||
if ((err = dsp563xx_once_reg_read_ex(tap, flush, regs[i].addr, regs[i].len, ®s[i].reg)) != ERROR_OK)
|
if (err != ERROR_OK)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( flush )
|
if (flush)
|
||||||
err = jtag_execute_queue();
|
err = jtag_execute_queue();
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
@ -206,11 +201,13 @@ int dsp563xx_once_reg_read_ex(struct jtag_tap *tap, int flush, uint8_t reg, uint
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
if ((err = dsp563xx_once_ir_exec(tap, 1, reg, 1, 0, 0)) != ERROR_OK)
|
err = dsp563xx_once_ir_exec(tap, 1, reg, 1, 0, 0);
|
||||||
|
if (err != ERROR_OK)
|
||||||
return err;
|
return err;
|
||||||
if ((err = dsp563xx_write_dr_u32(tap, data, 0x00, len, 0)) != ERROR_OK)
|
err = dsp563xx_write_dr_u32(tap, data, 0x00, len, 0);
|
||||||
|
if (err != ERROR_OK)
|
||||||
return err;
|
return err;
|
||||||
if ( flush )
|
if (flush)
|
||||||
err = jtag_execute_queue();
|
err = jtag_execute_queue();
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
@ -220,11 +217,13 @@ int dsp563xx_once_reg_read(struct jtag_tap *tap, int flush, uint8_t reg, uint32_
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
if ((err = dsp563xx_once_ir_exec(tap, flush, reg, 1, 0, 0)) != ERROR_OK)
|
err = dsp563xx_once_ir_exec(tap, flush, reg, 1, 0, 0);
|
||||||
|
if (err != ERROR_OK)
|
||||||
return err;
|
return err;
|
||||||
if ((err = dsp563xx_write_dr_u32(tap, data, 0x00, 24, 0)) != ERROR_OK)
|
err = dsp563xx_write_dr_u32(tap, data, 0x00, 24, 0);
|
||||||
|
if (err != ERROR_OK)
|
||||||
return err;
|
return err;
|
||||||
if ( flush )
|
if (flush)
|
||||||
err = jtag_execute_queue();
|
err = jtag_execute_queue();
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
@ -234,11 +233,13 @@ int dsp563xx_once_reg_write(struct jtag_tap *tap, int flush, uint8_t reg, uint32
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
if ((err = dsp563xx_once_ir_exec(tap, flush, reg, 0, 0, 0)) != ERROR_OK)
|
err = dsp563xx_once_ir_exec(tap, flush, reg, 0, 0, 0);
|
||||||
|
if (err != ERROR_OK)
|
||||||
return err;
|
return err;
|
||||||
if ((err = dsp563xx_write_dr_u32(tap, 0x00, data, 24, 0)) != ERROR_OK)
|
err = dsp563xx_write_dr_u32(tap, 0x00, data, 24, 0);
|
||||||
|
if (err != ERROR_OK)
|
||||||
return err;
|
return err;
|
||||||
if ( flush )
|
if (flush)
|
||||||
err = jtag_execute_queue();
|
err = jtag_execute_queue();
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
@ -248,11 +249,13 @@ int dsp563xx_once_execute_sw_ir(struct jtag_tap *tap, int flush, uint32_t opcode
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
if ((err = dsp563xx_once_ir_exec(tap, flush, DSP563XX_ONCE_OPDBR, 0, 1, 0)) != ERROR_OK)
|
err = dsp563xx_once_ir_exec(tap, flush, DSP563XX_ONCE_OPDBR, 0, 1, 0);
|
||||||
|
if (err != ERROR_OK)
|
||||||
return err;
|
return err;
|
||||||
if ((err = dsp563xx_write_dr_u32(tap, 0, opcode, 24, 0)) != ERROR_OK)
|
err = dsp563xx_write_dr_u32(tap, 0, opcode, 24, 0);
|
||||||
|
if (err != ERROR_OK)
|
||||||
return err;
|
return err;
|
||||||
if ( flush )
|
if (flush)
|
||||||
err = jtag_execute_queue();
|
err = jtag_execute_queue();
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
@ -262,21 +265,29 @@ int dsp563xx_once_execute_dw_ir(struct jtag_tap *tap, int flush, uint32_t opcode
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
if ((err = dsp563xx_once_ir_exec(tap, flush, DSP563XX_ONCE_OPDBR, 0, 0, 0)) != ERROR_OK)
|
err = dsp563xx_once_ir_exec(tap, flush, DSP563XX_ONCE_OPDBR, 0, 0, 0);
|
||||||
|
if (err != ERROR_OK)
|
||||||
return err;
|
return err;
|
||||||
if ((err = dsp563xx_write_dr_u32(tap, 0, opcode, 24, 0)) != ERROR_OK)
|
err = dsp563xx_write_dr_u32(tap, 0, opcode, 24, 0);
|
||||||
|
if (err != ERROR_OK)
|
||||||
return err;
|
return err;
|
||||||
if ( flush )
|
if (flush) {
|
||||||
if ((err = jtag_execute_queue()) != ERROR_OK)
|
err = jtag_execute_queue();
|
||||||
|
if (err != ERROR_OK)
|
||||||
return err;
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
if ((err = dsp563xx_once_ir_exec(tap, flush, DSP563XX_ONCE_OPDBR, 0, 1, 0)) != ERROR_OK)
|
err = dsp563xx_once_ir_exec(tap, flush, DSP563XX_ONCE_OPDBR, 0, 1, 0);
|
||||||
|
if (err != ERROR_OK)
|
||||||
return err;
|
return err;
|
||||||
if ((err = dsp563xx_write_dr_u32(tap, 0, operand, 24, 0)) != ERROR_OK)
|
err = dsp563xx_write_dr_u32(tap, 0, operand, 24, 0);
|
||||||
|
if (err != ERROR_OK)
|
||||||
return err;
|
return err;
|
||||||
if ( flush )
|
if (flush) {
|
||||||
if ((err = jtag_execute_queue()) != ERROR_OK)
|
err = jtag_execute_queue();
|
||||||
|
if (err != ERROR_OK)
|
||||||
return err;
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
* Free Software Foundation, Inc., *
|
* Free Software Foundation, Inc., *
|
||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#ifndef DSP563XX_ONCE_H
|
#ifndef DSP563XX_ONCE_H
|
||||||
#define DSP563XX_ONCE_H
|
#define DSP563XX_ONCE_H
|
||||||
|
|
||||||
|
@ -57,8 +58,7 @@
|
||||||
#define DSP563XX_ONCE_OPABF11 0x012 /* trace buffer/inc ptr */
|
#define DSP563XX_ONCE_OPABF11 0x012 /* trace buffer/inc ptr */
|
||||||
#define DSP563XX_ONCE_NOREG 0x01F /* no register selected */
|
#define DSP563XX_ONCE_NOREG 0x01F /* no register selected */
|
||||||
|
|
||||||
struct once_reg
|
struct once_reg {
|
||||||
{
|
|
||||||
uint8_t num;
|
uint8_t num;
|
||||||
uint8_t addr;
|
uint8_t addr;
|
||||||
uint8_t len;
|
uint8_t len;
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
* Free Software Foundation, Inc., *
|
* Free Software Foundation, Inc., *
|
||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -1542,7 +1543,7 @@ static int perl_crc(uint8_t *buff8, uint32_t word_count)
|
||||||
data = (buff8[2 * i] | (buff8[2 * i + 1] << 8));
|
data = (buff8[2 * i] | (buff8[2 * i + 1] << 8));
|
||||||
fbmisr =
|
fbmisr =
|
||||||
(checksum & 2) >> 1 ^ (checksum & 4) >> 2 ^ (checksum & 16)
|
(checksum & 2) >> 1 ^ (checksum & 4) >> 2 ^ (checksum & 16)
|
||||||
>> 4 ^ (checksum & 0x8000) >> 15;
|
>> 4 ^ (checksum & 0x8000) >> 15;
|
||||||
checksum = (data ^ ((checksum << 1) | fbmisr));
|
checksum = (data ^ ((checksum << 1) | fbmisr));
|
||||||
}
|
}
|
||||||
i--;
|
i--;
|
||||||
|
@ -1978,13 +1979,13 @@ int dsp5680xx_f_erase(struct target *target, int first, int last)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const uint16_t pgm_write_pflash[] = { 0x8A46, 0x0013, 0x807D, 0xE700,
|
const uint16_t pgm_write_pflash[] = { 0x8A46, 0x0013, 0x807D, 0xE700,
|
||||||
0xE700, 0x8A44, 0xFFFE, 0x017B,
|
0xE700, 0x8A44, 0xFFFE, 0x017B,
|
||||||
0xE700, 0xF514, 0x8563, 0x8646,
|
0xE700, 0xF514, 0x8563, 0x8646,
|
||||||
0x0020, 0x0014, 0x8646, 0x0080,
|
0x0020, 0x0014, 0x8646, 0x0080,
|
||||||
0x0013, 0xF042, 0x0013, 0x8B40,
|
0x0013, 0xF042, 0x0013, 0x8B40,
|
||||||
0x2004, 0x8246, 0x0013, 0x0020,
|
0x2004, 0x8246, 0x0013, 0x0020,
|
||||||
0xA967, 0x8B40, 0x1065, 0x8246,
|
0xA967, 0x8B40, 0x1065, 0x8246,
|
||||||
0x0013, 0x0010, 0xA961
|
0x0013, 0x0010, 0xA961
|
||||||
};
|
};
|
||||||
|
|
||||||
const uint32_t pgm_write_pflash_length = 31;
|
const uint32_t pgm_write_pflash_length = 31;
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
* Free Software Foundation, Inc., *
|
* Free Software Foundation, Inc., *
|
||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#ifndef DSP5680XX_H
|
#ifndef DSP5680XX_H
|
||||||
#define DSP5680XX_H
|
#define DSP5680XX_H
|
||||||
|
|
||||||
|
@ -29,12 +30,12 @@
|
||||||
* @file dsp5680xx.h
|
* @file dsp5680xx.h
|
||||||
* @author Rodrigo Rosa <rodrigorosa.LG@gmail.com>
|
* @author Rodrigo Rosa <rodrigorosa.LG@gmail.com>
|
||||||
* @date Thu Jun 9 18:54:38 2011
|
* @date Thu Jun 9 18:54:38 2011
|
||||||
*
|
*
|
||||||
* @brief Basic support for the 5680xx DSP from Freescale.
|
* @brief Basic support for the 5680xx DSP from Freescale.
|
||||||
* The chip has two taps in the JTAG chain, the Master tap and the Core tap.
|
* The chip has two taps in the JTAG chain, the Master tap and the Core tap.
|
||||||
* In this code the Master tap is only used to unlock the flash memory by executing a JTAG instruction.
|
* In this code the Master tap is only used to unlock the flash memory by executing a JTAG instruction.
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define S_FILE_DATA_OFFSET 0x200000
|
#define S_FILE_DATA_OFFSET 0x200000
|
||||||
|
@ -153,7 +154,7 @@
|
||||||
* ----------------------------------------------------------------
|
* ----------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define FLUSH_COUNT_READ_WRITE 8192 // This value works, higher values (and lower...) may work as well.
|
#define FLUSH_COUNT_READ_WRITE 8192 /* This value works, higher values (and lower...) may work as well. */
|
||||||
#define FLUSH_COUNT_FLASH 8192
|
#define FLUSH_COUNT_FLASH 8192
|
||||||
/** ----------------------------------------------------------------
|
/** ----------------------------------------------------------------
|
||||||
* HFM (flash module) Commands (ref:MC56F801xRM.pdf@159)
|
* HFM (flash module) Commands (ref:MC56F801xRM.pdf@159)
|
||||||
|
@ -201,7 +202,7 @@
|
||||||
/**
|
/**
|
||||||
* The value used on for the FM clock is important to prevent flashing errors and to prevent deterioration of the FM.
|
* The value used on for the FM clock is important to prevent flashing errors and to prevent deterioration of the FM.
|
||||||
* This value was calculated using a spreadsheet tool available on the Freescale website under FAQ 25464.
|
* This value was calculated using a spreadsheet tool available on the Freescale website under FAQ 25464.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#define HFM_CLK_DEFAULT 0x27
|
#define HFM_CLK_DEFAULT 0x27
|
||||||
/* 0x27 according to freescale cfg, but 0x40 according to freescale spreadsheet... */
|
/* 0x27 according to freescale cfg, but 0x40 according to freescale spreadsheet... */
|
||||||
|
@ -299,73 +300,86 @@ static inline struct dsp5680xx_common *target_to_dsp5680xx(struct target
|
||||||
return target->arch_info;
|
return target->arch_info;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Writes to flash memory.
|
* Writes to flash memory.
|
||||||
* Does not check if flash is erased, it's up to the user to erase the flash before running this function.
|
* Does not check if flash is erased, it's up to the user to erase the flash before running
|
||||||
* The flashing algorithm runs from RAM, reading from a register to which this function writes to. The algorithm is open loop, there is no control to verify that the FM read the register before writing the next data. A closed loop approach was much slower, and the current implementation does not fail, and if it did the crc check would detect it, allowing to flash again.
|
* this function.
|
||||||
*
|
* The flashing algorithm runs from RAM, reading from a register to which this function
|
||||||
* @param target
|
* writes to. The algorithm is open loop, there is no control to verify that the FM read
|
||||||
* @param buffer
|
* the register before writing the next data. A closed loop approach was much slower,
|
||||||
|
* and the current implementation does not fail, and if it did the crc check would detect it,
|
||||||
|
* allowing to flash again.
|
||||||
|
*
|
||||||
|
* @param target
|
||||||
|
* @param buffer
|
||||||
* @param address Word addressing.
|
* @param address Word addressing.
|
||||||
* @param count In bytes.
|
* @param count In bytes.
|
||||||
* @param verify_flash Execute a CRC check after flashing.
|
* @param verify_flash Execute a CRC check after flashing.
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
int dsp5680xx_f_wr(struct target *target, uint8_t * buffer, uint32_t address,
|
int dsp5680xx_f_wr(struct target *target, uint8_t * buffer, uint32_t address,
|
||||||
uint32_t count, int is_flash_lock);
|
uint32_t count, int is_flash_lock);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The FM has the funcionality of checking if the flash array is erased. This function executes it. It does not support individual sector analysis.
|
* The FM has the funcionality of checking if the flash array is erased. This function
|
||||||
*
|
* executes it. It does not support individual sector analysis.
|
||||||
* @param target
|
*
|
||||||
* @param erased
|
* @param target
|
||||||
* @param sector This parameter is ignored because the FM does not support checking if individual sectors are erased.
|
* @param erased
|
||||||
*
|
* @param sector This parameter is ignored because the FM does not support checking if
|
||||||
* @return
|
* individual sectors are erased.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
*/
|
*/
|
||||||
int dsp5680xx_f_erase_check(struct target *target, uint8_t * erased,
|
int dsp5680xx_f_erase_check(struct target *target, uint8_t * erased,
|
||||||
uint32_t sector);
|
uint32_t sector);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Erases either a sector or the complete flash array. If either the range first-last covers the complete array or if @first == 0 and @last == 0 then a mass erase command is executed on the FM. If not, then individual sectors are erased.
|
* Erases either a sector or the complete flash array. If either the range first-last covers
|
||||||
*
|
* the complete array or if @first == 0 and @last == 0 then a mass erase command is executed
|
||||||
* @param target
|
* on the FM. If not, then individual sectors are erased.
|
||||||
* @param first
|
*
|
||||||
* @param last
|
* @param target
|
||||||
*
|
* @param first
|
||||||
* @return
|
* @param last
|
||||||
|
*
|
||||||
|
* @return
|
||||||
*/
|
*/
|
||||||
int dsp5680xx_f_erase(struct target *target, int first, int last);
|
int dsp5680xx_f_erase(struct target *target, int first, int last);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads the memory mapped protection register. A 1 implies the sector is protected, a 0 implies the sector is not protected.
|
* Reads the memory mapped protection register. A 1 implies the sector is protected,
|
||||||
*
|
* a 0 implies the sector is not protected.
|
||||||
* @param target
|
*
|
||||||
|
* @param target
|
||||||
* @param protected Data read from the protection register.
|
* @param protected Data read from the protection register.
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
int dsp5680xx_f_protect_check(struct target *target, uint16_t * protected);
|
int dsp5680xx_f_protect_check(struct target *target, uint16_t * protected);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Writes the flash security words with a specific value. The chip's security will be enabled after the first reset following the execution of this function.
|
* Writes the flash security words with a specific value. The chip's security will be
|
||||||
*
|
* enabled after the first reset following the execution of this function.
|
||||||
* @param target
|
*
|
||||||
*
|
* @param target
|
||||||
* @return
|
*
|
||||||
|
* @return
|
||||||
*/
|
*/
|
||||||
int dsp5680xx_f_lock(struct target *target);
|
int dsp5680xx_f_lock(struct target *target);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Executes a mass erase command. The must be done from the Master tap.
|
* Executes a mass erase command. The must be done from the Master tap.
|
||||||
* It is up to the user to select the master tap (jtag tapenable dsp5680xx.chp) before running this function.
|
* It is up to the user to select the master tap (jtag tapenable dsp5680xx.chp)
|
||||||
* The flash array will be unsecured (and erased) after the first reset following the execution of this function.
|
* before running this function.
|
||||||
*
|
* The flash array will be unsecured (and erased) after the first reset following
|
||||||
* @param target
|
* the execution of this function.
|
||||||
*
|
*
|
||||||
* @return
|
* @param target
|
||||||
|
*
|
||||||
|
* @return
|
||||||
*/
|
*/
|
||||||
int dsp5680xx_f_unlock(struct target *target);
|
int dsp5680xx_f_unlock(struct target *target);
|
||||||
|
|
||||||
#endif /* dsp5680xx.h */
|
#endif /* dsp5680xx.h */
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
* Free Software Foundation, Inc., *
|
* Free Software Foundation, Inc., *
|
||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -87,7 +88,7 @@ static const struct {
|
||||||
.addr = 9,
|
.addr = 9,
|
||||||
.width = 32,
|
.width = 32,
|
||||||
},
|
},
|
||||||
[EICE_W0_DATA_VALUE ] = {
|
[EICE_W0_DATA_VALUE] = {
|
||||||
.name = "watch_0_data_value",
|
.name = "watch_0_data_value",
|
||||||
.addr = 10,
|
.addr = 10,
|
||||||
.width = 32,
|
.width = 32,
|
||||||
|
@ -145,14 +146,16 @@ static const struct {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
static int embeddedice_get_reg(struct reg *reg)
|
static int embeddedice_get_reg(struct reg *reg)
|
||||||
{
|
{
|
||||||
int retval;
|
int retval = embeddedice_read_reg(reg);
|
||||||
|
if (retval != ERROR_OK) {
|
||||||
if ((retval = embeddedice_read_reg(reg)) != ERROR_OK)
|
|
||||||
LOG_ERROR("error queueing EmbeddedICE register read");
|
LOG_ERROR("error queueing EmbeddedICE register read");
|
||||||
else if ((retval = jtag_execute_queue()) != ERROR_OK)
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
retval = jtag_execute_queue();
|
||||||
|
if (retval != ERROR_OK)
|
||||||
LOG_ERROR("EmbeddedICE register read failed");
|
LOG_ERROR("EmbeddedICE register read failed");
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
|
@ -168,8 +171,8 @@ static const struct reg_arch_type eice_reg_type = {
|
||||||
* Different versions of the modules have different capabilities, such as
|
* Different versions of the modules have different capabilities, such as
|
||||||
* hardware support for vector_catch, single stepping, and monitor mode.
|
* hardware support for vector_catch, single stepping, and monitor mode.
|
||||||
*/
|
*/
|
||||||
struct reg_cache *
|
struct reg_cache *embeddedice_build_reg_cache(struct target *target,
|
||||||
embeddedice_build_reg_cache(struct target *target, struct arm7_9_common *arm7_9)
|
struct arm7_9_common *arm7_9)
|
||||||
{
|
{
|
||||||
int retval;
|
int retval;
|
||||||
struct reg_cache *reg_cache = malloc(sizeof(struct reg_cache));
|
struct reg_cache *reg_cache = malloc(sizeof(struct reg_cache));
|
||||||
|
@ -200,8 +203,7 @@ embeddedice_build_reg_cache(struct target *target, struct arm7_9_common *arm7_9)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* set up registers */
|
/* set up registers */
|
||||||
for (i = 0; i < num_regs; i++)
|
for (i = 0; i < num_regs; i++) {
|
||||||
{
|
|
||||||
reg_list[i].name = eice_regs[i].name;
|
reg_list[i].name = eice_regs[i].name;
|
||||||
reg_list[i].size = eice_regs[i].width;
|
reg_list[i].size = eice_regs[i].width;
|
||||||
reg_list[i].dirty = 0;
|
reg_list[i].dirty = 0;
|
||||||
|
@ -215,12 +217,10 @@ embeddedice_build_reg_cache(struct target *target, struct arm7_9_common *arm7_9)
|
||||||
|
|
||||||
/* identify EmbeddedICE version by reading DCC control register */
|
/* identify EmbeddedICE version by reading DCC control register */
|
||||||
embeddedice_read_reg(®_list[EICE_COMMS_CTRL]);
|
embeddedice_read_reg(®_list[EICE_COMMS_CTRL]);
|
||||||
if ((retval = jtag_execute_queue()) != ERROR_OK)
|
retval = jtag_execute_queue();
|
||||||
{
|
if (retval != ERROR_OK) {
|
||||||
for (i = 0; i < num_regs; i++)
|
for (i = 0; i < num_regs; i++)
|
||||||
{
|
|
||||||
free(reg_list[i].value);
|
free(reg_list[i].value);
|
||||||
}
|
|
||||||
free(reg_list);
|
free(reg_list);
|
||||||
free(reg_cache);
|
free(reg_cache);
|
||||||
free(arch_info);
|
free(arch_info);
|
||||||
|
@ -230,8 +230,7 @@ embeddedice_build_reg_cache(struct target *target, struct arm7_9_common *arm7_9)
|
||||||
eice_version = buf_get_u32(reg_list[EICE_COMMS_CTRL].value, 28, 4);
|
eice_version = buf_get_u32(reg_list[EICE_COMMS_CTRL].value, 28, 4);
|
||||||
LOG_INFO("Embedded ICE version %d", eice_version);
|
LOG_INFO("Embedded ICE version %d", eice_version);
|
||||||
|
|
||||||
switch (eice_version)
|
switch (eice_version) {
|
||||||
{
|
|
||||||
case 1:
|
case 1:
|
||||||
/* ARM7TDMI r3, ARM7TDMI-S r3
|
/* ARM7TDMI r3, ARM7TDMI-S r3
|
||||||
*
|
*
|
||||||
|
@ -290,7 +289,7 @@ embeddedice_build_reg_cache(struct target *target, struct arm7_9_common *arm7_9)
|
||||||
* and do the appropriate setup itself.
|
* and do the appropriate setup itself.
|
||||||
*/
|
*/
|
||||||
if (strcmp(target_type_name(target), "feroceon") == 0 ||
|
if (strcmp(target_type_name(target), "feroceon") == 0 ||
|
||||||
strcmp(target_type_name(target), "dragonite") == 0)
|
strcmp(target_type_name(target), "dragonite") == 0)
|
||||||
break;
|
break;
|
||||||
LOG_ERROR("unknown EmbeddedICE version "
|
LOG_ERROR("unknown EmbeddedICE version "
|
||||||
"(comms ctrl: 0x%8.8" PRIx32 ")",
|
"(comms ctrl: 0x%8.8" PRIx32 ")",
|
||||||
|
@ -318,12 +317,12 @@ int embeddedice_setup(struct target *target)
|
||||||
* that manages break requests. ARM's "Angel Debug Monitor" is one
|
* that manages break requests. ARM's "Angel Debug Monitor" is one
|
||||||
* common example of such code.
|
* common example of such code.
|
||||||
*/
|
*/
|
||||||
if (arm7_9->has_monitor_mode)
|
if (arm7_9->has_monitor_mode) {
|
||||||
{
|
|
||||||
struct reg *dbg_ctrl = &arm7_9->eice_cache->reg_list[EICE_DBG_CTRL];
|
struct reg *dbg_ctrl = &arm7_9->eice_cache->reg_list[EICE_DBG_CTRL];
|
||||||
|
|
||||||
embeddedice_read_reg(dbg_ctrl);
|
embeddedice_read_reg(dbg_ctrl);
|
||||||
if ((retval = jtag_execute_queue()) != ERROR_OK)
|
retval = jtag_execute_queue();
|
||||||
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
buf_set_u32(dbg_ctrl->value, 4, 1, 0);
|
buf_set_u32(dbg_ctrl->value, 4, 1, 0);
|
||||||
embeddedice_set_reg_w_exec(dbg_ctrl, dbg_ctrl->value);
|
embeddedice_set_reg_w_exec(dbg_ctrl, dbg_ctrl->value);
|
||||||
|
@ -350,7 +349,8 @@ int embeddedice_read_reg_w_check(struct reg *reg,
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
retval = arm_jtag_set_instr(ice_reg->jtag_info, ice_reg->jtag_info->intest_instr, NULL, TAP_IDLE);
|
retval = arm_jtag_set_instr(ice_reg->jtag_info,
|
||||||
|
ice_reg->jtag_info->intest_instr, NULL, TAP_IDLE);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
|
@ -435,8 +435,7 @@ int embeddedice_receive(struct arm_jtag *jtag_info, uint32_t *data, uint32_t siz
|
||||||
|
|
||||||
jtag_add_dr_scan(jtag_info->tap, 3, fields, TAP_IDLE);
|
jtag_add_dr_scan(jtag_info->tap, 3, fields, TAP_IDLE);
|
||||||
|
|
||||||
while (size > 0)
|
while (size > 0) {
|
||||||
{
|
|
||||||
/* when reading the last item, set the register address to the DCC control reg,
|
/* when reading the last item, set the register address to the DCC control reg,
|
||||||
* to avoid reading additional data from the DCC data reg
|
* to avoid reading additional data from the DCC data reg
|
||||||
*/
|
*/
|
||||||
|
@ -486,7 +485,8 @@ static int embeddedice_set_reg_w_exec(struct reg *reg, uint8_t *buf)
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
embeddedice_set_reg(reg, buf_get_u32(buf, 0, reg->size));
|
embeddedice_set_reg(reg, buf_get_u32(buf, 0, reg->size));
|
||||||
if ((retval = jtag_execute_queue()) != ERROR_OK)
|
retval = jtag_execute_queue();
|
||||||
|
if (retval != ERROR_OK)
|
||||||
LOG_ERROR("register write failed");
|
LOG_ERROR("register write failed");
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
@ -555,8 +555,7 @@ int embeddedice_send(struct arm_jtag *jtag_info, uint32_t *data, uint32_t size)
|
||||||
|
|
||||||
fields[2].in_value = NULL;
|
fields[2].in_value = NULL;
|
||||||
|
|
||||||
while (size > 0)
|
while (size > 0) {
|
||||||
{
|
|
||||||
buf_set_u32(field0_out, 0, 32, *data);
|
buf_set_u32(field0_out, 0, 32, *data);
|
||||||
jtag_add_dr_scan(jtag_info->tap, 3, fields, TAP_IDLE);
|
jtag_add_dr_scan(jtag_info->tap, 3, fields, TAP_IDLE);
|
||||||
|
|
||||||
|
@ -586,8 +585,7 @@ int embeddedice_handshake(struct arm_jtag *jtag_info, int hsbit, uint32_t timeou
|
||||||
hsact = 1;
|
hsact = 1;
|
||||||
else if (hsbit == EICE_COMM_CTRL_RBIT)
|
else if (hsbit == EICE_COMM_CTRL_RBIT)
|
||||||
hsact = 0;
|
hsact = 0;
|
||||||
else
|
else {
|
||||||
{
|
|
||||||
LOG_ERROR("Invalid arguments");
|
LOG_ERROR("Invalid arguments");
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
}
|
}
|
||||||
|
@ -617,7 +615,8 @@ int embeddedice_handshake(struct arm_jtag *jtag_info, int hsbit, uint32_t timeou
|
||||||
gettimeofday(&lap, NULL);
|
gettimeofday(&lap, NULL);
|
||||||
do {
|
do {
|
||||||
jtag_add_dr_scan(jtag_info->tap, 3, fields, TAP_IDLE);
|
jtag_add_dr_scan(jtag_info->tap, 3, fields, TAP_IDLE);
|
||||||
if ((retval = jtag_execute_queue()) != ERROR_OK)
|
retval = jtag_execute_queue();
|
||||||
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
if (buf_get_u32(field0_in, hsbit, 1) == hsact)
|
if (buf_get_u32(field0_in, hsbit, 1) == hsact)
|
||||||
|
@ -640,8 +639,7 @@ void embeddedice_write_dcc(struct jtag_tap *tap,
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < count; i++)
|
for (i = 0; i < count; i++) {
|
||||||
{
|
|
||||||
embeddedice_write_reg_inner(tap, reg_addr,
|
embeddedice_write_reg_inner(tap, reg_addr,
|
||||||
fast_target_buffer_get_u32(buffer, little));
|
fast_target_buffer_get_u32(buffer, little));
|
||||||
buffer += 4;
|
buffer += 4;
|
||||||
|
|
|
@ -23,13 +23,13 @@
|
||||||
* Free Software Foundation, Inc., *
|
* Free Software Foundation, Inc., *
|
||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#ifndef EMBEDDED_ICE_H
|
#ifndef EMBEDDED_ICE_H
|
||||||
#define EMBEDDED_ICE_H
|
#define EMBEDDED_ICE_H
|
||||||
|
|
||||||
#include "arm7_9_common.h"
|
#include "arm7_9_common.h"
|
||||||
|
|
||||||
enum
|
enum {
|
||||||
{
|
|
||||||
EICE_DBG_CTRL = 0,
|
EICE_DBG_CTRL = 0,
|
||||||
EICE_DBG_STAT = 1,
|
EICE_DBG_STAT = 1,
|
||||||
EICE_COMMS_CTRL = 2,
|
EICE_COMMS_CTRL = 2,
|
||||||
|
@ -49,8 +49,7 @@ enum
|
||||||
EICE_VEC_CATCH = 16
|
EICE_VEC_CATCH = 16
|
||||||
};
|
};
|
||||||
|
|
||||||
enum
|
enum {
|
||||||
{
|
|
||||||
EICE_DBG_CONTROL_ICEDIS = 5,
|
EICE_DBG_CONTROL_ICEDIS = 5,
|
||||||
EICE_DBG_CONTROL_MONEN = 4,
|
EICE_DBG_CONTROL_MONEN = 4,
|
||||||
EICE_DBG_CONTROL_INTDIS = 2,
|
EICE_DBG_CONTROL_INTDIS = 2,
|
||||||
|
@ -58,8 +57,7 @@ enum
|
||||||
EICE_DBG_CONTROL_DBGACK = 0,
|
EICE_DBG_CONTROL_DBGACK = 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum
|
enum {
|
||||||
{
|
|
||||||
EICE_DBG_STATUS_IJBIT = 5,
|
EICE_DBG_STATUS_IJBIT = 5,
|
||||||
EICE_DBG_STATUS_ITBIT = 4,
|
EICE_DBG_STATUS_ITBIT = 4,
|
||||||
EICE_DBG_STATUS_SYSCOMP = 3,
|
EICE_DBG_STATUS_SYSCOMP = 3,
|
||||||
|
@ -68,8 +66,7 @@ enum
|
||||||
EICE_DBG_STATUS_DBGACK = 0
|
EICE_DBG_STATUS_DBGACK = 0
|
||||||
};
|
};
|
||||||
|
|
||||||
enum
|
enum {
|
||||||
{
|
|
||||||
EICE_W_CTRL_ENABLE = 0x100,
|
EICE_W_CTRL_ENABLE = 0x100,
|
||||||
EICE_W_CTRL_RANGE = 0x80,
|
EICE_W_CTRL_RANGE = 0x80,
|
||||||
EICE_W_CTRL_CHAIN = 0x40,
|
EICE_W_CTRL_CHAIN = 0x40,
|
||||||
|
@ -81,26 +78,24 @@ enum
|
||||||
EICE_W_CTRL_nRW = 0x1
|
EICE_W_CTRL_nRW = 0x1
|
||||||
};
|
};
|
||||||
|
|
||||||
enum
|
enum {
|
||||||
{
|
|
||||||
EICE_COMM_CTRL_WBIT = 1,
|
EICE_COMM_CTRL_WBIT = 1,
|
||||||
EICE_COMM_CTRL_RBIT = 0
|
EICE_COMM_CTRL_RBIT = 0
|
||||||
};
|
};
|
||||||
|
|
||||||
struct embeddedice_reg
|
struct embeddedice_reg {
|
||||||
{
|
|
||||||
int addr;
|
int addr;
|
||||||
struct arm_jtag *jtag_info;
|
struct arm_jtag *jtag_info;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct reg_cache* embeddedice_build_reg_cache(struct target *target,
|
struct reg_cache *embeddedice_build_reg_cache(struct target *target,
|
||||||
struct arm7_9_common *arm7_9);
|
struct arm7_9_common *arm7_9);
|
||||||
|
|
||||||
int embeddedice_setup(struct target *target);
|
int embeddedice_setup(struct target *target);
|
||||||
|
|
||||||
int embeddedice_read_reg(struct reg *reg);
|
int embeddedice_read_reg(struct reg *reg);
|
||||||
int embeddedice_read_reg_w_check(struct reg *reg,
|
int embeddedice_read_reg_w_check(struct reg *reg,
|
||||||
uint8_t* check_value, uint8_t* check_mask);
|
uint8_t *check_value, uint8_t *check_mask);
|
||||||
|
|
||||||
void embeddedice_write_reg(struct reg *reg, uint32_t value);
|
void embeddedice_write_reg(struct reg *reg, uint32_t value);
|
||||||
void embeddedice_store_reg(struct reg *reg);
|
void embeddedice_store_reg(struct reg *reg);
|
||||||
|
@ -112,10 +107,10 @@ int embeddedice_send(struct arm_jtag *jtag_info, uint32_t *data, uint32_t size);
|
||||||
|
|
||||||
int embeddedice_handshake(struct arm_jtag *jtag_info, int hsbit, uint32_t timeout);
|
int embeddedice_handshake(struct arm_jtag *jtag_info, int hsbit, uint32_t timeout);
|
||||||
|
|
||||||
/* If many embeddedice_write_reg() follow eachother, then the >1 invocations can be this faster version of
|
/* If many embeddedice_write_reg() follow eachother, then the >1 invocations can be
|
||||||
* embeddedice_write_reg
|
* this faster version of embeddedice_write_reg
|
||||||
*/
|
*/
|
||||||
static __inline__ void embeddedice_write_reg_inner(struct jtag_tap *tap, int reg_addr, uint32_t value)
|
static inline void embeddedice_write_reg_inner(struct jtag_tap *tap, int reg_addr, uint32_t value)
|
||||||
{
|
{
|
||||||
static const int embeddedice_num_bits[] = {32, 6};
|
static const int embeddedice_num_bits[] = {32, 6};
|
||||||
uint32_t values[2];
|
uint32_t values[2];
|
||||||
|
@ -123,13 +118,10 @@ static __inline__ void embeddedice_write_reg_inner(struct jtag_tap *tap, int reg
|
||||||
values[0] = value;
|
values[0] = value;
|
||||||
values[1] = (1 << 5) | reg_addr;
|
values[1] = (1 << 5) | reg_addr;
|
||||||
|
|
||||||
jtag_add_dr_out(tap,
|
jtag_add_dr_out(tap, 2, embeddedice_num_bits, values, TAP_IDLE);
|
||||||
2,
|
|
||||||
embeddedice_num_bits,
|
|
||||||
values,
|
|
||||||
TAP_IDLE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void embeddedice_write_dcc(struct jtag_tap *tap, int reg_addr, const uint8_t *buffer, int little, int count);
|
void embeddedice_write_dcc(struct jtag_tap *tap, int reg_addr, const uint8_t *buffer,
|
||||||
|
int little, int count);
|
||||||
|
|
||||||
#endif /* EMBEDDED_ICE_H */
|
#endif /* EMBEDDED_ICE_H */
|
||||||
|
|
149
src/target/etb.c
149
src/target/etb.c
|
@ -17,6 +17,7 @@
|
||||||
* Free Software Foundation, Inc., *
|
* Free Software Foundation, Inc., *
|
||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -26,9 +27,7 @@
|
||||||
#include "etb.h"
|
#include "etb.h"
|
||||||
#include "register.h"
|
#include "register.h"
|
||||||
|
|
||||||
|
static char *etb_reg_list[] = {
|
||||||
static char* etb_reg_list[] =
|
|
||||||
{
|
|
||||||
"ETB_identification",
|
"ETB_identification",
|
||||||
"ETB_ram_depth",
|
"ETB_ram_depth",
|
||||||
"ETB_ram_width",
|
"ETB_ram_width",
|
||||||
|
@ -50,12 +49,11 @@ static int etb_set_instr(struct etb *etb, uint32_t new_instr)
|
||||||
if (tap == NULL)
|
if (tap == NULL)
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
|
|
||||||
if (buf_get_u32(tap->cur_instr, 0, tap->ir_length) != new_instr)
|
if (buf_get_u32(tap->cur_instr, 0, tap->ir_length) != new_instr) {
|
||||||
{
|
|
||||||
struct scan_field field;
|
struct scan_field field;
|
||||||
|
|
||||||
field.num_bits = tap->ir_length;
|
field.num_bits = tap->ir_length;
|
||||||
void * t = calloc(DIV_ROUND_UP(field.num_bits, 8), 1);
|
void *t = calloc(DIV_ROUND_UP(field.num_bits, 8), 1);
|
||||||
field.out_value = t;
|
field.out_value = t;
|
||||||
buf_set_u32(t, 0, field.num_bits, new_instr);
|
buf_set_u32(t, 0, field.num_bits, new_instr);
|
||||||
|
|
||||||
|
@ -71,12 +69,11 @@ static int etb_set_instr(struct etb *etb, uint32_t new_instr)
|
||||||
|
|
||||||
static int etb_scann(struct etb *etb, uint32_t new_scan_chain)
|
static int etb_scann(struct etb *etb, uint32_t new_scan_chain)
|
||||||
{
|
{
|
||||||
if (etb->cur_scan_chain != new_scan_chain)
|
if (etb->cur_scan_chain != new_scan_chain) {
|
||||||
{
|
|
||||||
struct scan_field field;
|
struct scan_field field;
|
||||||
|
|
||||||
field.num_bits = 5;
|
field.num_bits = 5;
|
||||||
void * t = calloc(DIV_ROUND_UP(field.num_bits, 8), 1);
|
void *t = calloc(DIV_ROUND_UP(field.num_bits, 8), 1);
|
||||||
field.out_value = t;
|
field.out_value = t;
|
||||||
buf_set_u32(t, 0, field.num_bits, new_scan_chain);
|
buf_set_u32(t, 0, field.num_bits, new_scan_chain);
|
||||||
|
|
||||||
|
@ -106,14 +103,14 @@ static int etb_get_reg(struct reg *reg)
|
||||||
{
|
{
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
if ((retval = etb_read_reg(reg)) != ERROR_OK)
|
retval = etb_read_reg(reg);
|
||||||
{
|
if (retval != ERROR_OK) {
|
||||||
LOG_ERROR("BUG: error scheduling ETB register read");
|
LOG_ERROR("BUG: error scheduling ETB register read");
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((retval = jtag_execute_queue()) != ERROR_OK)
|
retval = jtag_execute_queue();
|
||||||
{
|
if (retval != ERROR_OK) {
|
||||||
LOG_ERROR("ETB register read failed");
|
LOG_ERROR("ETB register read failed");
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
@ -126,7 +123,7 @@ static const struct reg_arch_type etb_reg_type = {
|
||||||
.set = etb_set_reg_w_exec,
|
.set = etb_set_reg_w_exec,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct reg_cache* etb_build_reg_cache(struct etb *etb)
|
struct reg_cache *etb_build_reg_cache(struct etb *etb)
|
||||||
{
|
{
|
||||||
struct reg_cache *reg_cache = malloc(sizeof(struct reg_cache));
|
struct reg_cache *reg_cache = malloc(sizeof(struct reg_cache));
|
||||||
struct reg *reg_list = NULL;
|
struct reg *reg_list = NULL;
|
||||||
|
@ -145,8 +142,7 @@ struct reg_cache* etb_build_reg_cache(struct etb *etb)
|
||||||
reg_cache->num_regs = num_regs;
|
reg_cache->num_regs = num_regs;
|
||||||
|
|
||||||
/* set up registers */
|
/* set up registers */
|
||||||
for (i = 0; i < num_regs; i++)
|
for (i = 0; i < num_regs; i++) {
|
||||||
{
|
|
||||||
reg_list[i].name = etb_reg_list[i];
|
reg_list[i].name = etb_reg_list[i];
|
||||||
reg_list[i].size = 32;
|
reg_list[i].size = 32;
|
||||||
reg_list[i].dirty = 0;
|
reg_list[i].dirty = 0;
|
||||||
|
@ -196,8 +192,7 @@ static int etb_read_ram(struct etb *etb, uint32_t *data, int num_frames)
|
||||||
|
|
||||||
jtag_add_dr_scan(etb->tap, 3, fields, TAP_IDLE);
|
jtag_add_dr_scan(etb->tap, 3, fields, TAP_IDLE);
|
||||||
|
|
||||||
for (i = 0; i < num_frames; i++)
|
for (i = 0; i < num_frames; i++) {
|
||||||
{
|
|
||||||
/* ensure nR/W reamins set to read */
|
/* ensure nR/W reamins set to read */
|
||||||
buf_set_u32(&temp2, 0, 1, 0);
|
buf_set_u32(&temp2, 0, 1, 0);
|
||||||
|
|
||||||
|
@ -219,7 +214,7 @@ static int etb_read_ram(struct etb *etb, uint32_t *data, int num_frames)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int etb_read_reg_w_check(struct reg *reg,
|
static int etb_read_reg_w_check(struct reg *reg,
|
||||||
uint8_t* check_value, uint8_t* check_mask)
|
uint8_t *check_value, uint8_t *check_mask)
|
||||||
{
|
{
|
||||||
struct etb_reg *etb_reg = reg->arch_info;
|
struct etb_reg *etb_reg = reg->arch_info;
|
||||||
uint8_t reg_addr = etb_reg->addr & 0x7f;
|
uint8_t reg_addr = etb_reg->addr & 0x7f;
|
||||||
|
@ -273,8 +268,8 @@ static int etb_set_reg(struct reg *reg, uint32_t value)
|
||||||
{
|
{
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
if ((retval = etb_write_reg(reg, value)) != ERROR_OK)
|
retval = etb_write_reg(reg, value);
|
||||||
{
|
if (retval != ERROR_OK) {
|
||||||
LOG_ERROR("BUG: error scheduling ETB register write");
|
LOG_ERROR("BUG: error scheduling ETB register write");
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
@ -292,8 +287,8 @@ static int etb_set_reg_w_exec(struct reg *reg, uint8_t *buf)
|
||||||
|
|
||||||
etb_set_reg(reg, buf_get_u32(buf, 0, reg->size));
|
etb_set_reg(reg, buf_get_u32(buf, 0, reg->size));
|
||||||
|
|
||||||
if ((retval = jtag_execute_queue()) != ERROR_OK)
|
retval = jtag_execute_queue();
|
||||||
{
|
if (retval != ERROR_OK) {
|
||||||
LOG_ERROR("ETB: register write failed");
|
LOG_ERROR("ETB: register write failed");
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
@ -341,34 +336,28 @@ COMMAND_HANDLER(handle_etb_config_command)
|
||||||
struct arm *arm;
|
struct arm *arm;
|
||||||
|
|
||||||
if (CMD_ARGC != 2)
|
if (CMD_ARGC != 2)
|
||||||
{
|
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
}
|
|
||||||
|
|
||||||
target = get_target(CMD_ARGV[0]);
|
target = get_target(CMD_ARGV[0]);
|
||||||
|
|
||||||
if (!target)
|
if (!target) {
|
||||||
{
|
|
||||||
LOG_ERROR("ETB: target '%s' not defined", CMD_ARGV[0]);
|
LOG_ERROR("ETB: target '%s' not defined", CMD_ARGV[0]);
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
arm = target_to_arm(target);
|
arm = target_to_arm(target);
|
||||||
if (!is_arm(arm))
|
if (!is_arm(arm)) {
|
||||||
{
|
|
||||||
command_print(CMD_CTX, "ETB: '%s' isn't an ARM", CMD_ARGV[0]);
|
command_print(CMD_CTX, "ETB: '%s' isn't an ARM", CMD_ARGV[0]);
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
tap = jtag_tap_by_string(CMD_ARGV[1]);
|
tap = jtag_tap_by_string(CMD_ARGV[1]);
|
||||||
if (tap == NULL)
|
if (tap == NULL) {
|
||||||
{
|
|
||||||
command_print(CMD_CTX, "ETB: TAP %s does not exist", CMD_ARGV[1]);
|
command_print(CMD_CTX, "ETB: TAP %s does not exist", CMD_ARGV[1]);
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (arm->etm)
|
if (arm->etm) {
|
||||||
{
|
|
||||||
struct etb *etb = malloc(sizeof(struct etb));
|
struct etb *etb = malloc(sizeof(struct etb));
|
||||||
|
|
||||||
arm->etm->capture_driver_priv = etb;
|
arm->etm->capture_driver_priv = etb;
|
||||||
|
@ -378,9 +367,7 @@ COMMAND_HANDLER(handle_etb_config_command)
|
||||||
etb->reg_cache = NULL;
|
etb->reg_cache = NULL;
|
||||||
etb->ram_width = 0;
|
etb->ram_width = 0;
|
||||||
etb->ram_depth = 0;
|
etb->ram_depth = 0;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
LOG_ERROR("ETM: target has no ETM defined, ETB left unconfigured");
|
LOG_ERROR("ETM: target has no ETM defined, ETB left unconfigured");
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
@ -397,8 +384,7 @@ COMMAND_HANDLER(handle_etb_trigger_percent_command)
|
||||||
|
|
||||||
target = get_current_target(CMD_CTX);
|
target = get_current_target(CMD_CTX);
|
||||||
arm = target_to_arm(target);
|
arm = target_to_arm(target);
|
||||||
if (!is_arm(arm))
|
if (!is_arm(arm)) {
|
||||||
{
|
|
||||||
command_print(CMD_CTX, "ETB: current target isn't an ARM");
|
command_print(CMD_CTX, "ETB: current target isn't an ARM");
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
@ -426,7 +412,7 @@ COMMAND_HANDLER(handle_etb_trigger_percent_command)
|
||||||
}
|
}
|
||||||
|
|
||||||
command_print(CMD_CTX, "%d percent of tracebuffer fills after trigger",
|
command_print(CMD_CTX, "%d percent of tracebuffer fills after trigger",
|
||||||
etb->trigger_percent);
|
etb->trigger_percent);
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
@ -550,13 +536,13 @@ static int etb_read_trace(struct etm_context *etm_ctx)
|
||||||
* i.e. don't read invalid entries
|
* i.e. don't read invalid entries
|
||||||
*/
|
*/
|
||||||
if (buf_get_u32(etb->reg_cache->reg_list[ETB_STATUS].value, 0, 1))
|
if (buf_get_u32(etb->reg_cache->reg_list[ETB_STATUS].value, 0, 1))
|
||||||
{
|
first_frame = buf_get_u32(etb->reg_cache->reg_list[ETB_RAM_WRITE_POINTER].value,
|
||||||
first_frame = buf_get_u32(etb->reg_cache->reg_list[ETB_RAM_WRITE_POINTER].value, 0, 32);
|
0,
|
||||||
}
|
32);
|
||||||
else
|
else
|
||||||
{
|
num_frames = buf_get_u32(etb->reg_cache->reg_list[ETB_RAM_WRITE_POINTER].value,
|
||||||
num_frames = buf_get_u32(etb->reg_cache->reg_list[ETB_RAM_WRITE_POINTER].value, 0, 32);
|
0,
|
||||||
}
|
32);
|
||||||
|
|
||||||
etb_write_reg(&etb->reg_cache->reg_list[ETB_RAM_READ_POINTER], first_frame);
|
etb_write_reg(&etb->reg_cache->reg_list[ETB_RAM_READ_POINTER], first_frame);
|
||||||
|
|
||||||
|
@ -565,9 +551,7 @@ static int etb_read_trace(struct etm_context *etm_ctx)
|
||||||
etb_read_ram(etb, trace_data, num_frames);
|
etb_read_ram(etb, trace_data, num_frames);
|
||||||
|
|
||||||
if (etm_ctx->trace_depth > 0)
|
if (etm_ctx->trace_depth > 0)
|
||||||
{
|
|
||||||
free(etm_ctx->trace_data);
|
free(etm_ctx->trace_data);
|
||||||
}
|
|
||||||
|
|
||||||
if ((etm_ctx->control & ETM_PORT_WIDTH_MASK) == ETM_PORT_4BIT)
|
if ((etm_ctx->control & ETM_PORT_WIDTH_MASK) == ETM_PORT_4BIT)
|
||||||
etm_ctx->trace_depth = num_frames * 3;
|
etm_ctx->trace_depth = num_frames * 3;
|
||||||
|
@ -578,21 +562,17 @@ static int etb_read_trace(struct etm_context *etm_ctx)
|
||||||
|
|
||||||
etm_ctx->trace_data = malloc(sizeof(struct etmv1_trace_data) * etm_ctx->trace_depth);
|
etm_ctx->trace_data = malloc(sizeof(struct etmv1_trace_data) * etm_ctx->trace_depth);
|
||||||
|
|
||||||
for (i = 0, j = 0; i < num_frames; i++)
|
for (i = 0, j = 0; i < num_frames; i++) {
|
||||||
{
|
if ((etm_ctx->control & ETM_PORT_WIDTH_MASK) == ETM_PORT_4BIT) {
|
||||||
if ((etm_ctx->control & ETM_PORT_WIDTH_MASK) == ETM_PORT_4BIT)
|
|
||||||
{
|
|
||||||
/* trace word j */
|
/* trace word j */
|
||||||
etm_ctx->trace_data[j].pipestat = trace_data[i] & 0x7;
|
etm_ctx->trace_data[j].pipestat = trace_data[i] & 0x7;
|
||||||
etm_ctx->trace_data[j].packet = (trace_data[i] & 0x78) >> 3;
|
etm_ctx->trace_data[j].packet = (trace_data[i] & 0x78) >> 3;
|
||||||
etm_ctx->trace_data[j].flags = 0;
|
etm_ctx->trace_data[j].flags = 0;
|
||||||
if ((trace_data[i] & 0x80) >> 7)
|
if ((trace_data[i] & 0x80) >> 7)
|
||||||
{
|
|
||||||
etm_ctx->trace_data[j].flags |= ETMV1_TRACESYNC_CYCLE;
|
etm_ctx->trace_data[j].flags |= ETMV1_TRACESYNC_CYCLE;
|
||||||
}
|
if (etm_ctx->trace_data[j].pipestat == STAT_TR) {
|
||||||
if (etm_ctx->trace_data[j].pipestat == STAT_TR)
|
etm_ctx->trace_data[j].pipestat = etm_ctx->trace_data[j].packet &
|
||||||
{
|
0x7;
|
||||||
etm_ctx->trace_data[j].pipestat = etm_ctx->trace_data[j].packet & 0x7;
|
|
||||||
etm_ctx->trace_data[j].flags |= ETMV1_TRIGGER_CYCLE;
|
etm_ctx->trace_data[j].flags |= ETMV1_TRIGGER_CYCLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -601,12 +581,10 @@ static int etb_read_trace(struct etm_context *etm_ctx)
|
||||||
etm_ctx->trace_data[j + 1].packet = (trace_data[i] & 0x7800) >> 11;
|
etm_ctx->trace_data[j + 1].packet = (trace_data[i] & 0x7800) >> 11;
|
||||||
etm_ctx->trace_data[j + 1].flags = 0;
|
etm_ctx->trace_data[j + 1].flags = 0;
|
||||||
if ((trace_data[i] & 0x8000) >> 15)
|
if ((trace_data[i] & 0x8000) >> 15)
|
||||||
{
|
|
||||||
etm_ctx->trace_data[j + 1].flags |= ETMV1_TRACESYNC_CYCLE;
|
etm_ctx->trace_data[j + 1].flags |= ETMV1_TRACESYNC_CYCLE;
|
||||||
}
|
if (etm_ctx->trace_data[j + 1].pipestat == STAT_TR) {
|
||||||
if (etm_ctx->trace_data[j + 1].pipestat == STAT_TR)
|
etm_ctx->trace_data[j +
|
||||||
{
|
1].pipestat = etm_ctx->trace_data[j + 1].packet & 0x7;
|
||||||
etm_ctx->trace_data[j + 1].pipestat = etm_ctx->trace_data[j + 1].packet & 0x7;
|
|
||||||
etm_ctx->trace_data[j + 1].flags |= ETMV1_TRIGGER_CYCLE;
|
etm_ctx->trace_data[j + 1].flags |= ETMV1_TRIGGER_CYCLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -615,30 +593,24 @@ static int etb_read_trace(struct etm_context *etm_ctx)
|
||||||
etm_ctx->trace_data[j + 2].packet = (trace_data[i] & 0x780000) >> 19;
|
etm_ctx->trace_data[j + 2].packet = (trace_data[i] & 0x780000) >> 19;
|
||||||
etm_ctx->trace_data[j + 2].flags = 0;
|
etm_ctx->trace_data[j + 2].flags = 0;
|
||||||
if ((trace_data[i] & 0x800000) >> 23)
|
if ((trace_data[i] & 0x800000) >> 23)
|
||||||
{
|
|
||||||
etm_ctx->trace_data[j + 2].flags |= ETMV1_TRACESYNC_CYCLE;
|
etm_ctx->trace_data[j + 2].flags |= ETMV1_TRACESYNC_CYCLE;
|
||||||
}
|
if (etm_ctx->trace_data[j + 2].pipestat == STAT_TR) {
|
||||||
if (etm_ctx->trace_data[j + 2].pipestat == STAT_TR)
|
etm_ctx->trace_data[j +
|
||||||
{
|
2].pipestat = etm_ctx->trace_data[j + 2].packet & 0x7;
|
||||||
etm_ctx->trace_data[j + 2].pipestat = etm_ctx->trace_data[j + 2].packet & 0x7;
|
|
||||||
etm_ctx->trace_data[j + 2].flags |= ETMV1_TRIGGER_CYCLE;
|
etm_ctx->trace_data[j + 2].flags |= ETMV1_TRIGGER_CYCLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
j += 3;
|
j += 3;
|
||||||
}
|
} else if ((etm_ctx->control & ETM_PORT_WIDTH_MASK) == ETM_PORT_8BIT) {
|
||||||
else if ((etm_ctx->control & ETM_PORT_WIDTH_MASK) == ETM_PORT_8BIT)
|
|
||||||
{
|
|
||||||
/* trace word j */
|
/* trace word j */
|
||||||
etm_ctx->trace_data[j].pipestat = trace_data[i] & 0x7;
|
etm_ctx->trace_data[j].pipestat = trace_data[i] & 0x7;
|
||||||
etm_ctx->trace_data[j].packet = (trace_data[i] & 0x7f8) >> 3;
|
etm_ctx->trace_data[j].packet = (trace_data[i] & 0x7f8) >> 3;
|
||||||
etm_ctx->trace_data[j].flags = 0;
|
etm_ctx->trace_data[j].flags = 0;
|
||||||
if ((trace_data[i] & 0x800) >> 11)
|
if ((trace_data[i] & 0x800) >> 11)
|
||||||
{
|
|
||||||
etm_ctx->trace_data[j].flags |= ETMV1_TRACESYNC_CYCLE;
|
etm_ctx->trace_data[j].flags |= ETMV1_TRACESYNC_CYCLE;
|
||||||
}
|
if (etm_ctx->trace_data[j].pipestat == STAT_TR) {
|
||||||
if (etm_ctx->trace_data[j].pipestat == STAT_TR)
|
etm_ctx->trace_data[j].pipestat = etm_ctx->trace_data[j].packet &
|
||||||
{
|
0x7;
|
||||||
etm_ctx->trace_data[j].pipestat = etm_ctx->trace_data[j].packet & 0x7;
|
|
||||||
etm_ctx->trace_data[j].flags |= ETMV1_TRIGGER_CYCLE;
|
etm_ctx->trace_data[j].flags |= ETMV1_TRIGGER_CYCLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -647,30 +619,24 @@ static int etb_read_trace(struct etm_context *etm_ctx)
|
||||||
etm_ctx->trace_data[j + 1].packet = (trace_data[i] & 0x7f8000) >> 15;
|
etm_ctx->trace_data[j + 1].packet = (trace_data[i] & 0x7f8000) >> 15;
|
||||||
etm_ctx->trace_data[j + 1].flags = 0;
|
etm_ctx->trace_data[j + 1].flags = 0;
|
||||||
if ((trace_data[i] & 0x800000) >> 23)
|
if ((trace_data[i] & 0x800000) >> 23)
|
||||||
{
|
|
||||||
etm_ctx->trace_data[j + 1].flags |= ETMV1_TRACESYNC_CYCLE;
|
etm_ctx->trace_data[j + 1].flags |= ETMV1_TRACESYNC_CYCLE;
|
||||||
}
|
if (etm_ctx->trace_data[j + 1].pipestat == STAT_TR) {
|
||||||
if (etm_ctx->trace_data[j + 1].pipestat == STAT_TR)
|
etm_ctx->trace_data[j +
|
||||||
{
|
1].pipestat = etm_ctx->trace_data[j + 1].packet & 0x7;
|
||||||
etm_ctx->trace_data[j + 1].pipestat = etm_ctx->trace_data[j + 1].packet & 0x7;
|
|
||||||
etm_ctx->trace_data[j + 1].flags |= ETMV1_TRIGGER_CYCLE;
|
etm_ctx->trace_data[j + 1].flags |= ETMV1_TRIGGER_CYCLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
j += 2;
|
j += 2;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
/* trace word j */
|
/* trace word j */
|
||||||
etm_ctx->trace_data[j].pipestat = trace_data[i] & 0x7;
|
etm_ctx->trace_data[j].pipestat = trace_data[i] & 0x7;
|
||||||
etm_ctx->trace_data[j].packet = (trace_data[i] & 0x7fff8) >> 3;
|
etm_ctx->trace_data[j].packet = (trace_data[i] & 0x7fff8) >> 3;
|
||||||
etm_ctx->trace_data[j].flags = 0;
|
etm_ctx->trace_data[j].flags = 0;
|
||||||
if ((trace_data[i] & 0x80000) >> 19)
|
if ((trace_data[i] & 0x80000) >> 19)
|
||||||
{
|
|
||||||
etm_ctx->trace_data[j].flags |= ETMV1_TRACESYNC_CYCLE;
|
etm_ctx->trace_data[j].flags |= ETMV1_TRACESYNC_CYCLE;
|
||||||
}
|
if (etm_ctx->trace_data[j].pipestat == STAT_TR) {
|
||||||
if (etm_ctx->trace_data[j].pipestat == STAT_TR)
|
etm_ctx->trace_data[j].pipestat = etm_ctx->trace_data[j].packet &
|
||||||
{
|
0x7;
|
||||||
etm_ctx->trace_data[j].pipestat = etm_ctx->trace_data[j].packet & 0x7;
|
|
||||||
etm_ctx->trace_data[j].flags |= ETMV1_TRIGGER_CYCLE;
|
etm_ctx->trace_data[j].flags |= ETMV1_TRIGGER_CYCLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -689,10 +655,8 @@ static int etb_start_capture(struct etm_context *etm_ctx)
|
||||||
uint32_t etb_ctrl_value = 0x1;
|
uint32_t etb_ctrl_value = 0x1;
|
||||||
uint32_t trigger_count;
|
uint32_t trigger_count;
|
||||||
|
|
||||||
if ((etm_ctx->control & ETM_PORT_MODE_MASK) == ETM_PORT_DEMUXED)
|
if ((etm_ctx->control & ETM_PORT_MODE_MASK) == ETM_PORT_DEMUXED) {
|
||||||
{
|
if ((etm_ctx->control & ETM_PORT_WIDTH_MASK) != ETM_PORT_8BIT) {
|
||||||
if ((etm_ctx->control & ETM_PORT_WIDTH_MASK) != ETM_PORT_8BIT)
|
|
||||||
{
|
|
||||||
LOG_ERROR("ETB can't run in demultiplexed mode with a 4 or 16 bit port");
|
LOG_ERROR("ETB can't run in demultiplexed mode with a 4 or 16 bit port");
|
||||||
return ERROR_ETM_PORTMODE_NOT_SUPPORTED;
|
return ERROR_ETM_PORTMODE_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
|
@ -731,8 +695,7 @@ static int etb_stop_capture(struct etm_context *etm_ctx)
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct etm_capture_driver etb_capture_driver =
|
struct etm_capture_driver etb_capture_driver = {
|
||||||
{
|
|
||||||
.name = "etb",
|
.name = "etb",
|
||||||
.commands = etb_command_handlers,
|
.commands = etb_command_handlers,
|
||||||
.init = etb_init,
|
.init = etb_init,
|
||||||
|
|
|
@ -17,12 +17,12 @@
|
||||||
* Free Software Foundation, Inc., *
|
* Free Software Foundation, Inc., *
|
||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#ifndef ETB_H
|
#ifndef ETB_H
|
||||||
#define ETB_H
|
#define ETB_H
|
||||||
|
|
||||||
/* ETB registers */
|
/* ETB registers */
|
||||||
enum
|
enum {
|
||||||
{
|
|
||||||
ETB_ID = 0x00,
|
ETB_ID = 0x00,
|
||||||
ETB_RAM_DEPTH = 0x01,
|
ETB_RAM_DEPTH = 0x01,
|
||||||
ETB_RAM_WIDTH = 0x02,
|
ETB_RAM_WIDTH = 0x02,
|
||||||
|
@ -34,8 +34,7 @@ enum
|
||||||
ETB_CTRL = 0x08,
|
ETB_CTRL = 0x08,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct etb
|
struct etb {
|
||||||
{
|
|
||||||
struct etm_context *etm_ctx;
|
struct etm_context *etm_ctx;
|
||||||
struct jtag_tap *tap;
|
struct jtag_tap *tap;
|
||||||
uint32_t cur_scan_chain;
|
uint32_t cur_scan_chain;
|
||||||
|
@ -49,14 +48,13 @@ struct etb
|
||||||
unsigned trigger_percent;
|
unsigned trigger_percent;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct etb_reg
|
struct etb_reg {
|
||||||
{
|
|
||||||
uint32_t addr;
|
uint32_t addr;
|
||||||
struct etb *etb;
|
struct etb *etb;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern struct etm_capture_driver etb_capture_driver;
|
extern struct etm_capture_driver etb_capture_driver;
|
||||||
|
|
||||||
struct reg_cache* etb_build_reg_cache(struct etb *etb);
|
struct reg_cache *etb_build_reg_cache(struct etb *etb);
|
||||||
|
|
||||||
#endif /* ETB_H */
|
#endif /* ETB_H */
|
||||||
|
|
735
src/target/etm.c
735
src/target/etm.c
File diff suppressed because it is too large
Load Diff
|
@ -20,6 +20,7 @@
|
||||||
* Free Software Foundation, Inc., *
|
* Free Software Foundation, Inc., *
|
||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#ifndef ETM_H
|
#ifndef ETM_H
|
||||||
#define ETM_H
|
#define ETM_H
|
||||||
|
|
||||||
|
@ -29,8 +30,7 @@
|
||||||
struct image;
|
struct image;
|
||||||
|
|
||||||
/* ETM registers (JTAG protocol) */
|
/* ETM registers (JTAG protocol) */
|
||||||
enum
|
enum {
|
||||||
{
|
|
||||||
ETM_CTRL = 0x00,
|
ETM_CTRL = 0x00,
|
||||||
ETM_CONFIG = 0x01,
|
ETM_CONFIG = 0x01,
|
||||||
ETM_TRIG_EVENT = 0x02,
|
ETM_TRIG_EVENT = 0x02,
|
||||||
|
@ -71,8 +71,7 @@ enum
|
||||||
ETM_ID = 0x79,
|
ETM_ID = 0x79,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct etm_reg
|
struct etm_reg {
|
||||||
{
|
|
||||||
uint32_t value;
|
uint32_t value;
|
||||||
const struct etm_reg_info *reg_info;
|
const struct etm_reg_info *reg_info;
|
||||||
struct arm_jtag *jtag_info;
|
struct arm_jtag *jtag_info;
|
||||||
|
@ -84,8 +83,7 @@ struct etm_reg
|
||||||
*
|
*
|
||||||
* NOTE that these have evolved since the ~v1.3 defns ...
|
* NOTE that these have evolved since the ~v1.3 defns ...
|
||||||
*/
|
*/
|
||||||
enum
|
enum {
|
||||||
{
|
|
||||||
ETM_CTRL_POWERDOWN = (1 << 0),
|
ETM_CTRL_POWERDOWN = (1 << 0),
|
||||||
ETM_CTRL_MONITOR_CPRT = (1 << 1),
|
ETM_CTRL_MONITOR_CPRT = (1 << 1),
|
||||||
|
|
||||||
|
@ -118,7 +116,7 @@ enum
|
||||||
ETM_PORT_HALF_CLOCK = (1 << 13),
|
ETM_PORT_HALF_CLOCK = (1 << 13),
|
||||||
ETM_PORT_CLOCK_MASK = (1 << 13),
|
ETM_PORT_CLOCK_MASK = (1 << 13),
|
||||||
|
|
||||||
// bits 15:14 == context ID size used in tracing
|
/* bits 15:14 == context ID size used in tracing */
|
||||||
ETM_CTRL_CONTEXTID_NONE = (0 << 14),
|
ETM_CTRL_CONTEXTID_NONE = (0 << 14),
|
||||||
ETM_CTRL_CONTEXTID_8 = (1 << 14),
|
ETM_CTRL_CONTEXTID_8 = (1 << 14),
|
||||||
ETM_CTRL_CONTEXTID_16 = (2 << 14),
|
ETM_CTRL_CONTEXTID_16 = (2 << 14),
|
||||||
|
@ -131,14 +129,13 @@ enum
|
||||||
ETM_PORT_DEMUXED = (2 << 16),
|
ETM_PORT_DEMUXED = (2 << 16),
|
||||||
ETM_PORT_MODE_MASK = (3 << 16),
|
ETM_PORT_MODE_MASK = (3 << 16),
|
||||||
|
|
||||||
// bits 31:18 defined in v3.0 and later (e.g. ARM11+)
|
/* bits 31:18 defined in v3.0 and later (e.g. ARM11+) */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* forward-declare ETM context */
|
/* forward-declare ETM context */
|
||||||
struct etm_context;
|
struct etm_context;
|
||||||
|
|
||||||
struct etm_capture_driver
|
struct etm_capture_driver {
|
||||||
{
|
|
||||||
const char *name;
|
const char *name;
|
||||||
const struct command_registration *commands;
|
const struct command_registration *commands;
|
||||||
int (*init)(struct etm_context *etm_ctx);
|
int (*init)(struct etm_context *etm_ctx);
|
||||||
|
@ -148,14 +145,12 @@ struct etm_capture_driver
|
||||||
int (*stop_capture)(struct etm_context *etm_ctx);
|
int (*stop_capture)(struct etm_context *etm_ctx);
|
||||||
};
|
};
|
||||||
|
|
||||||
enum
|
enum {
|
||||||
{
|
|
||||||
ETMV1_TRACESYNC_CYCLE = 0x1,
|
ETMV1_TRACESYNC_CYCLE = 0x1,
|
||||||
ETMV1_TRIGGER_CYCLE = 0x2,
|
ETMV1_TRIGGER_CYCLE = 0x2,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct etmv1_trace_data
|
struct etmv1_trace_data {
|
||||||
{
|
|
||||||
uint8_t pipestat; /* bits 0-2 pipeline status */
|
uint8_t pipestat; /* bits 0-2 pipeline status */
|
||||||
uint16_t packet; /* packet data (4, 8 or 16 bit) */
|
uint16_t packet; /* packet data (4, 8 or 16 bit) */
|
||||||
int flags; /* ETMV1_TRACESYNC_CYCLE, ETMV1_TRIGGER_CYCLE */
|
int flags; /* ETMV1_TRACESYNC_CYCLE, ETMV1_TRIGGER_CYCLE */
|
||||||
|
@ -166,8 +161,7 @@ struct etmv1_trace_data
|
||||||
* this will have to be split into version independent elements
|
* this will have to be split into version independent elements
|
||||||
* and a version specific part
|
* and a version specific part
|
||||||
*/
|
*/
|
||||||
struct etm_context
|
struct etm_context {
|
||||||
{
|
|
||||||
struct target *target; /* target this ETM is connected to */
|
struct target *target; /* target this ETM is connected to */
|
||||||
struct reg_cache *reg_cache; /* ETM register cache */
|
struct reg_cache *reg_cache; /* ETM register cache */
|
||||||
struct etm_capture_driver *capture_driver; /* driver used to access ETM data */
|
struct etm_capture_driver *capture_driver; /* driver used to access ETM data */
|
||||||
|
@ -194,8 +188,7 @@ struct etm_context
|
||||||
};
|
};
|
||||||
|
|
||||||
/* PIPESTAT values */
|
/* PIPESTAT values */
|
||||||
typedef enum
|
typedef enum {
|
||||||
{
|
|
||||||
STAT_IE = 0x0,
|
STAT_IE = 0x0,
|
||||||
STAT_ID = 0x1,
|
STAT_ID = 0x1,
|
||||||
STAT_IN = 0x2,
|
STAT_IN = 0x2,
|
||||||
|
@ -207,8 +200,7 @@ typedef enum
|
||||||
} etmv1_pipestat_t;
|
} etmv1_pipestat_t;
|
||||||
|
|
||||||
/* branch reason values */
|
/* branch reason values */
|
||||||
typedef enum
|
typedef enum {
|
||||||
{
|
|
||||||
BR_NORMAL = 0x0, /* Normal PC change : periodic synchro (ETMv1.1) */
|
BR_NORMAL = 0x0, /* Normal PC change : periodic synchro (ETMv1.1) */
|
||||||
BR_ENABLE = 0x1, /* Trace has been enabled */
|
BR_ENABLE = 0x1, /* Trace has been enabled */
|
||||||
BR_RESTART = 0x2, /* Trace restarted after a FIFO overflow */
|
BR_RESTART = 0x2, /* Trace restarted after a FIFO overflow */
|
||||||
|
@ -219,7 +211,7 @@ typedef enum
|
||||||
BR_RSVD7 = 0x7, /* reserved */
|
BR_RSVD7 = 0x7, /* reserved */
|
||||||
} etmv1_branch_reason_t;
|
} etmv1_branch_reason_t;
|
||||||
|
|
||||||
struct reg_cache* etm_build_reg_cache(struct target *target,
|
struct reg_cache *etm_build_reg_cache(struct target *target,
|
||||||
struct arm_jtag *jtag_info, struct etm_context *etm_ctx);
|
struct arm_jtag *jtag_info, struct etm_context *etm_ctx);
|
||||||
|
|
||||||
int etm_setup(struct target *target);
|
int etm_setup(struct target *target);
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
* Free Software Foundation, Inc., *
|
* Free Software Foundation, Inc., *
|
||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -24,7 +25,6 @@
|
||||||
#include "arm.h"
|
#include "arm.h"
|
||||||
#include "etm_dummy.h"
|
#include "etm_dummy.h"
|
||||||
|
|
||||||
|
|
||||||
COMMAND_HANDLER(handle_etm_dummy_config_command)
|
COMMAND_HANDLER(handle_etm_dummy_config_command)
|
||||||
{
|
{
|
||||||
struct target *target;
|
struct target *target;
|
||||||
|
@ -32,25 +32,20 @@ COMMAND_HANDLER(handle_etm_dummy_config_command)
|
||||||
|
|
||||||
target = get_target(CMD_ARGV[0]);
|
target = get_target(CMD_ARGV[0]);
|
||||||
|
|
||||||
if (!target)
|
if (!target) {
|
||||||
{
|
|
||||||
LOG_ERROR("target '%s' not defined", CMD_ARGV[0]);
|
LOG_ERROR("target '%s' not defined", CMD_ARGV[0]);
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
arm = target_to_arm(target);
|
arm = target_to_arm(target);
|
||||||
if (!is_arm(arm))
|
if (!is_arm(arm)) {
|
||||||
{
|
|
||||||
command_print(CMD_CTX, "target '%s' isn't an ARM", CMD_ARGV[0]);
|
command_print(CMD_CTX, "target '%s' isn't an ARM", CMD_ARGV[0]);
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (arm->etm)
|
if (arm->etm)
|
||||||
{
|
|
||||||
arm->etm->capture_driver_priv = NULL;
|
arm->etm->capture_driver_priv = NULL;
|
||||||
}
|
else {
|
||||||
else
|
|
||||||
{
|
|
||||||
LOG_ERROR("target has no ETM defined, ETM dummy left unconfigured");
|
LOG_ERROR("target has no ETM defined, ETM dummy left unconfigured");
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
@ -102,8 +97,7 @@ static int etm_dummy_stop_capture(struct etm_context *etm_ctx)
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct etm_capture_driver etm_dummy_capture_driver =
|
struct etm_capture_driver etm_dummy_capture_driver = {
|
||||||
{
|
|
||||||
.name = "dummy",
|
.name = "dummy",
|
||||||
.commands = etm_dummy_command_handlers,
|
.commands = etm_dummy_command_handlers,
|
||||||
.init = etm_dummy_init,
|
.init = etm_dummy_init,
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
* Free Software Foundation, Inc., *
|
* Free Software Foundation, Inc., *
|
||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#ifndef ETM_DUMMY_H
|
#ifndef ETM_DUMMY_H
|
||||||
#define ETM_DUMMY_H
|
#define ETM_DUMMY_H
|
||||||
|
|
||||||
|
|
|
@ -41,7 +41,7 @@ static void fa526_change_to_arm(struct target *target, uint32_t *r0, uint32_t *p
|
||||||
}
|
}
|
||||||
|
|
||||||
static void fa526_read_core_regs(struct target *target,
|
static void fa526_read_core_regs(struct target *target,
|
||||||
uint32_t mask, uint32_t* core_regs[16])
|
uint32_t mask, uint32_t *core_regs[16])
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
|
struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
|
||||||
|
@ -59,8 +59,7 @@ static void fa526_read_core_regs(struct target *target,
|
||||||
/* fetch NOP, STM in EXECUTE stage (1st cycle) */
|
/* fetch NOP, STM in EXECUTE stage (1st cycle) */
|
||||||
arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
|
||||||
|
|
||||||
for (i = 0; i <= 15; i++)
|
for (i = 0; i <= 15; i++) {
|
||||||
{
|
|
||||||
if (mask & (1 << i))
|
if (mask & (1 << i))
|
||||||
/* nothing fetched, STM in MEMORY (i'th cycle) */
|
/* nothing fetched, STM in MEMORY (i'th cycle) */
|
||||||
arm9tdmi_clock_data_in(jtag_info, core_regs[i]);
|
arm9tdmi_clock_data_in(jtag_info, core_regs[i]);
|
||||||
|
@ -68,7 +67,7 @@ static void fa526_read_core_regs(struct target *target,
|
||||||
}
|
}
|
||||||
|
|
||||||
static void fa526_read_core_regs_target_buffer(struct target *target,
|
static void fa526_read_core_regs_target_buffer(struct target *target,
|
||||||
uint32_t mask, void* buffer, int size)
|
uint32_t mask, void *buffer, int size)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
|
struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
|
||||||
|
@ -90,12 +89,10 @@ static void fa526_read_core_regs_target_buffer(struct target *target,
|
||||||
/* fetch NOP, STM in EXECUTE stage (1st cycle) */
|
/* fetch NOP, STM in EXECUTE stage (1st cycle) */
|
||||||
arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
|
||||||
|
|
||||||
for (i = 0; i <= 15; i++)
|
for (i = 0; i <= 15; i++) {
|
||||||
{
|
|
||||||
if (mask & (1 << i))
|
if (mask & (1 << i))
|
||||||
/* nothing fetched, STM in MEMORY (i'th cycle) */
|
/* nothing fetched, STM in MEMORY (i'th cycle) */
|
||||||
switch (size)
|
switch (size) {
|
||||||
{
|
|
||||||
case 4:
|
case 4:
|
||||||
arm9tdmi_clock_data_in_endianness(jtag_info, buf_u32++, 4, be);
|
arm9tdmi_clock_data_in_endianness(jtag_info, buf_u32++, 4, be);
|
||||||
break;
|
break;
|
||||||
|
@ -188,8 +185,7 @@ static void fa526_write_xpsr_im8(struct target *target,
|
||||||
arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
|
||||||
|
|
||||||
/* rot == 4 writes flags, which takes only one cycle */
|
/* rot == 4 writes flags, which takes only one cycle */
|
||||||
if (rot != 4)
|
if (rot != 4) {
|
||||||
{
|
|
||||||
/* nothing fetched, MSR in EXECUTE (2) */
|
/* nothing fetched, MSR in EXECUTE (2) */
|
||||||
arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
|
||||||
/* nothing fetched, MSR in EXECUTE (3) */
|
/* nothing fetched, MSR in EXECUTE (3) */
|
||||||
|
@ -216,8 +212,7 @@ static void fa526_write_core_regs(struct target *target,
|
||||||
/* fetch NOP, LDM in EXECUTE stage (1st cycle) */
|
/* fetch NOP, LDM in EXECUTE stage (1st cycle) */
|
||||||
arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
|
||||||
|
|
||||||
for (i = 0; i <= 15; i++)
|
for (i = 0; i <= 15; i++) {
|
||||||
{
|
|
||||||
if (mask & (1 << i))
|
if (mask & (1 << i))
|
||||||
/* nothing fetched, LDM still in EXECUTE (1 + i cycle) */
|
/* nothing fetched, LDM still in EXECUTE (1 + i cycle) */
|
||||||
arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, core_regs[i], NULL, 0);
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, core_regs[i], NULL, 0);
|
||||||
|
@ -346,14 +341,13 @@ static int fa526_init_arch_info(struct target *target,
|
||||||
|
|
||||||
static int fa526_target_create(struct target *target, Jim_Interp *interp)
|
static int fa526_target_create(struct target *target, Jim_Interp *interp)
|
||||||
{
|
{
|
||||||
struct arm920t_common *arm920t = calloc(1,sizeof(struct arm920t_common));
|
struct arm920t_common *arm920t = calloc(1, sizeof(struct arm920t_common));
|
||||||
|
|
||||||
return fa526_init_arch_info(target, arm920t, target->tap);
|
return fa526_init_arch_info(target, arm920t, target->tap);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Holds methods for FA526 targets. */
|
/** Holds methods for FA526 targets. */
|
||||||
struct target_type fa526_target =
|
struct target_type fa526_target = {
|
||||||
{
|
|
||||||
.name = "fa526",
|
.name = "fa526",
|
||||||
|
|
||||||
.poll = arm7_9_poll,
|
.poll = arm7_9_poll,
|
||||||
|
|
|
@ -58,7 +58,6 @@
|
||||||
#include "register.h"
|
#include "register.h"
|
||||||
#include "arm_opcodes.h"
|
#include "arm_opcodes.h"
|
||||||
|
|
||||||
|
|
||||||
static int feroceon_assert_reset(struct target *target)
|
static int feroceon_assert_reset(struct target *target)
|
||||||
{
|
{
|
||||||
struct arm *arm = target->arch_info;
|
struct arm *arm = target->arch_info;
|
||||||
|
@ -160,7 +159,7 @@ static void feroceon_change_to_arm(struct target *target, uint32_t *r0,
|
||||||
}
|
}
|
||||||
|
|
||||||
static void feroceon_read_core_regs(struct target *target,
|
static void feroceon_read_core_regs(struct target *target,
|
||||||
uint32_t mask, uint32_t* core_regs[16])
|
uint32_t mask, uint32_t *core_regs[16])
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
struct arm *arm = target->arch_info;
|
struct arm *arm = target->arch_info;
|
||||||
|
@ -180,7 +179,7 @@ static void feroceon_read_core_regs(struct target *target,
|
||||||
}
|
}
|
||||||
|
|
||||||
static void feroceon_read_core_regs_target_buffer(struct target *target,
|
static void feroceon_read_core_regs_target_buffer(struct target *target,
|
||||||
uint32_t mask, void* buffer, int size)
|
uint32_t mask, void *buffer, int size)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
struct arm *arm = target->arch_info;
|
struct arm *arm = target->arch_info;
|
||||||
|
@ -195,11 +194,9 @@ static void feroceon_read_core_regs_target_buffer(struct target *target,
|
||||||
arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
|
||||||
arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
|
||||||
|
|
||||||
for (i = 0; i <= 15; i++)
|
for (i = 0; i <= 15; i++) {
|
||||||
{
|
|
||||||
if (mask & (1 << i)) {
|
if (mask & (1 << i)) {
|
||||||
switch (size)
|
switch (size) {
|
||||||
{
|
|
||||||
case 4:
|
case 4:
|
||||||
arm9tdmi_clock_data_in_endianness(jtag_info, buf_u32++, 4, be);
|
arm9tdmi_clock_data_in_endianness(jtag_info, buf_u32++, 4, be);
|
||||||
break;
|
break;
|
||||||
|
@ -350,7 +347,7 @@ static void feroceon_branch_resume_thumb(struct target *target)
|
||||||
arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
|
||||||
arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
|
||||||
|
|
||||||
arm9tdmi_clock_out(jtag_info, 0xE28F0001, 0, NULL, 0); // add r0,pc,#1
|
arm9tdmi_clock_out(jtag_info, 0xE28F0001, 0, NULL, 0); /* add r0,pc,#1 */
|
||||||
arm9tdmi_clock_out(jtag_info, ARMV4_5_BX(0), 0, NULL, 0);
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_BX(0), 0, NULL, 0);
|
||||||
arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
|
||||||
arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
|
||||||
|
@ -452,9 +449,7 @@ static int feroceon_examine_debug_reason(struct target *target)
|
||||||
{
|
{
|
||||||
/* the MOE is not implemented */
|
/* the MOE is not implemented */
|
||||||
if (target->debug_reason != DBG_REASON_SINGLESTEP)
|
if (target->debug_reason != DBG_REASON_SINGLESTEP)
|
||||||
{
|
|
||||||
target->debug_reason = DBG_REASON_DBGRQ;
|
target->debug_reason = DBG_REASON_DBGRQ;
|
||||||
}
|
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
@ -473,8 +468,7 @@ static int feroceon_bulk_write_memory(struct target *target,
|
||||||
* We can't use the dcc flow control bits, so let's transfer data
|
* We can't use the dcc flow control bits, so let's transfer data
|
||||||
* with 31 bits and flip the MSB each time a new data word is sent.
|
* with 31 bits and flip the MSB each time a new data word is sent.
|
||||||
*/
|
*/
|
||||||
static uint32_t dcc_code[] =
|
static uint32_t dcc_code[] = {
|
||||||
{
|
|
||||||
0xee115e10, /* 3: mrc p14, 0, r5, c1, c0, 0 */
|
0xee115e10, /* 3: mrc p14, 0, r5, c1, c0, 0 */
|
||||||
0xe3a0301e, /* 1: mov r3, #30 */
|
0xe3a0301e, /* 1: mov r3, #30 */
|
||||||
0xe3a04002, /* mov r4, #2 */
|
0xe3a04002, /* mov r4, #2 */
|
||||||
|
@ -503,13 +497,11 @@ static int feroceon_bulk_write_memory(struct target *target,
|
||||||
return target_write_memory(target, address, 4, count, buffer);
|
return target_write_memory(target, address, 4, count, buffer);
|
||||||
|
|
||||||
/* regrab previously allocated working_area, or allocate a new one */
|
/* regrab previously allocated working_area, or allocate a new one */
|
||||||
if (!arm7_9->dcc_working_area)
|
if (!arm7_9->dcc_working_area) {
|
||||||
{
|
|
||||||
uint8_t dcc_code_buf[dcc_size];
|
uint8_t dcc_code_buf[dcc_size];
|
||||||
|
|
||||||
/* make sure we have a working area */
|
/* make sure we have a working area */
|
||||||
if (target_alloc_working_area(target, dcc_size, &arm7_9->dcc_working_area) != ERROR_OK)
|
if (target_alloc_working_area(target, dcc_size, &arm7_9->dcc_working_area) != ERROR_OK) {
|
||||||
{
|
|
||||||
LOG_INFO("no working area available, falling back to memory writes");
|
LOG_INFO("no working area available, falling back to memory writes");
|
||||||
return target_write_memory(target, address, 4, count, buffer);
|
return target_write_memory(target, address, 4, count, buffer);
|
||||||
}
|
}
|
||||||
|
@ -519,10 +511,10 @@ static int feroceon_bulk_write_memory(struct target *target,
|
||||||
target_buffer_set_u32(target, dcc_code_buf + i*4, dcc_code[i]);
|
target_buffer_set_u32(target, dcc_code_buf + i*4, dcc_code[i]);
|
||||||
|
|
||||||
/* write DCC code to working area */
|
/* write DCC code to working area */
|
||||||
if ((retval = target_write_memory(target, arm7_9->dcc_working_area->address, 4, dcc_size/4, dcc_code_buf)) != ERROR_OK)
|
retval = target_write_memory(target,
|
||||||
{
|
arm7_9->dcc_working_area->address, 4, dcc_size/4, dcc_code_buf);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* backup clobbered processor state */
|
/* backup clobbered processor state */
|
||||||
|
@ -543,14 +535,12 @@ static int feroceon_bulk_write_memory(struct target *target,
|
||||||
x = 0;
|
x = 0;
|
||||||
flip = 0;
|
flip = 0;
|
||||||
shift = 1;
|
shift = 1;
|
||||||
for (i = 0; i < count; i++)
|
for (i = 0; i < count; i++) {
|
||||||
{
|
|
||||||
uint32_t y = target_buffer_get_u32(target, buffer);
|
uint32_t y = target_buffer_get_u32(target, buffer);
|
||||||
uint32_t z = (x >> 1) | (y >> shift) | (flip ^= 0x80000000);
|
uint32_t z = (x >> 1) | (y >> shift) | (flip ^= 0x80000000);
|
||||||
embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_COMMS_DATA], z);
|
embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_COMMS_DATA], z);
|
||||||
x = y << (32 - shift);
|
x = y << (32 - shift);
|
||||||
if (++shift >= 32 || i + 1 >= count)
|
if (++shift >= 32 || i + 1 >= count) {
|
||||||
{
|
|
||||||
z = (x >> 1) | (flip ^= 0x80000000);
|
z = (x >> 1) | (flip ^= 0x80000000);
|
||||||
embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_COMMS_DATA], z);
|
embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_COMMS_DATA], z);
|
||||||
x = 0;
|
x = 0;
|
||||||
|
@ -563,20 +553,19 @@ static int feroceon_bulk_write_memory(struct target *target,
|
||||||
if (retval == ERROR_OK)
|
if (retval == ERROR_OK)
|
||||||
retval = target_wait_state(target, TARGET_HALTED, 500);
|
retval = target_wait_state(target, TARGET_HALTED, 500);
|
||||||
if (retval == ERROR_OK) {
|
if (retval == ERROR_OK) {
|
||||||
uint32_t endaddress =
|
uint32_t endaddress =
|
||||||
buf_get_u32(arm->core_cache->reg_list[0].value, 0, 32);
|
buf_get_u32(arm->core_cache->reg_list[0].value, 0, 32);
|
||||||
if (endaddress != address + count*4) {
|
if (endaddress != address + count*4) {
|
||||||
LOG_ERROR("DCC write failed,"
|
LOG_ERROR("DCC write failed,"
|
||||||
" expected end address 0x%08" PRIx32
|
" expected end address 0x%08" PRIx32
|
||||||
" got 0x%0" PRIx32 "",
|
" got 0x%0" PRIx32 "",
|
||||||
address + count*4, endaddress);
|
address + count*4, endaddress);
|
||||||
retval = ERROR_FAIL;
|
retval = ERROR_FAIL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* restore target state */
|
/* restore target state */
|
||||||
for (i = 0; i <= 5; i++)
|
for (i = 0; i <= 5; i++) {
|
||||||
{
|
|
||||||
buf_set_u32(arm->core_cache->reg_list[i].value, 0, 32, save[i]);
|
buf_set_u32(arm->core_cache->reg_list[i].value, 0, 32, save[i]);
|
||||||
arm->core_cache->reg_list[i].valid = 1;
|
arm->core_cache->reg_list[i].valid = 1;
|
||||||
arm->core_cache->reg_list[i].dirty = 1;
|
arm->core_cache->reg_list[i].dirty = 1;
|
||||||
|
@ -631,7 +620,7 @@ static void feroceon_common_setup(struct target *target)
|
||||||
|
|
||||||
static int feroceon_target_create(struct target *target, Jim_Interp *interp)
|
static int feroceon_target_create(struct target *target, Jim_Interp *interp)
|
||||||
{
|
{
|
||||||
struct arm926ejs_common *arm926ejs = calloc(1,sizeof(struct arm926ejs_common));
|
struct arm926ejs_common *arm926ejs = calloc(1, sizeof(struct arm926ejs_common));
|
||||||
|
|
||||||
arm926ejs_init_arch_info(target, arm926ejs, target->tap);
|
arm926ejs_init_arch_info(target, arm926ejs, target->tap);
|
||||||
feroceon_common_setup(target);
|
feroceon_common_setup(target);
|
||||||
|
@ -645,7 +634,7 @@ static int feroceon_target_create(struct target *target, Jim_Interp *interp)
|
||||||
|
|
||||||
static int dragonite_target_create(struct target *target, Jim_Interp *interp)
|
static int dragonite_target_create(struct target *target, Jim_Interp *interp)
|
||||||
{
|
{
|
||||||
struct arm966e_common *arm966e = calloc(1,sizeof(struct arm966e_common));
|
struct arm966e_common *arm966e = calloc(1, sizeof(struct arm966e_common));
|
||||||
|
|
||||||
arm966e_init_arch_info(target, arm966e, target->tap);
|
arm966e_init_arch_info(target, arm966e, target->tap);
|
||||||
feroceon_common_setup(target);
|
feroceon_common_setup(target);
|
||||||
|
@ -687,8 +676,7 @@ static int feroceon_examine(struct target *target)
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct target_type feroceon_target =
|
struct target_type feroceon_target = {
|
||||||
{
|
|
||||||
.name = "feroceon",
|
.name = "feroceon",
|
||||||
|
|
||||||
.poll = arm7_9_poll,
|
.poll = arm7_9_poll,
|
||||||
|
@ -726,8 +714,7 @@ struct target_type feroceon_target =
|
||||||
.examine = feroceon_examine,
|
.examine = feroceon_examine,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct target_type dragonite_target =
|
struct target_type dragonite_target = {
|
||||||
{
|
|
||||||
.name = "dragonite",
|
.name = "dragonite",
|
||||||
|
|
||||||
.poll = arm7_9_poll,
|
.poll = arm7_9_poll,
|
||||||
|
@ -764,4 +751,3 @@ struct target_type dragonite_target =
|
||||||
.init_target = feroceon_init_target,
|
.init_target = feroceon_init_target,
|
||||||
.examine = feroceon_examine,
|
.examine = feroceon_examine,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -23,6 +23,7 @@
|
||||||
* Free Software Foundation, Inc., *
|
* Free Software Foundation, Inc., *
|
||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#ifndef IMAGE_H
|
#ifndef IMAGE_H
|
||||||
#define IMAGE_H
|
#define IMAGE_H
|
||||||
|
|
||||||
|
@ -37,8 +38,7 @@
|
||||||
|
|
||||||
#define IMAGE_MEMORY_CACHE_SIZE (2048)
|
#define IMAGE_MEMORY_CACHE_SIZE (2048)
|
||||||
|
|
||||||
enum image_type
|
enum image_type {
|
||||||
{
|
|
||||||
IMAGE_BINARY, /* plain binary */
|
IMAGE_BINARY, /* plain binary */
|
||||||
IMAGE_IHEX, /* intel hex-record format */
|
IMAGE_IHEX, /* intel hex-record format */
|
||||||
IMAGE_MEMORY, /* target-memory pseudo-image */
|
IMAGE_MEMORY, /* target-memory pseudo-image */
|
||||||
|
@ -47,16 +47,14 @@ enum image_type
|
||||||
IMAGE_BUILDER, /* when building a new image */
|
IMAGE_BUILDER, /* when building a new image */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct imagesection
|
struct imagesection {
|
||||||
{
|
|
||||||
uint32_t base_address;
|
uint32_t base_address;
|
||||||
uint32_t size;
|
uint32_t size;
|
||||||
int flags;
|
int flags;
|
||||||
void *private; /* private data */
|
void *private; /* private data */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct image
|
struct image {
|
||||||
{
|
|
||||||
enum image_type type; /* image type (plain, ihex, ...) */
|
enum image_type type; /* image type (plain, ihex, ...) */
|
||||||
void *type_private; /* type private data */
|
void *type_private; /* type private data */
|
||||||
int num_sections; /* number of sections contained in the image */
|
int num_sections; /* number of sections contained in the image */
|
||||||
|
@ -67,26 +65,22 @@ struct image
|
||||||
uint32_t start_address; /* start address, if one is set */
|
uint32_t start_address; /* start address, if one is set */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct image_binary
|
struct image_binary {
|
||||||
{
|
|
||||||
struct fileio fileio;
|
struct fileio fileio;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct image_ihex
|
struct image_ihex {
|
||||||
{
|
|
||||||
struct fileio fileio;
|
struct fileio fileio;
|
||||||
uint8_t *buffer;
|
uint8_t *buffer;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct image_memory
|
struct image_memory {
|
||||||
{
|
|
||||||
struct target *target;
|
struct target *target;
|
||||||
uint8_t *cache;
|
uint8_t *cache;
|
||||||
uint32_t cache_address;
|
uint32_t cache_address;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct image_elf
|
struct image_elf {
|
||||||
{
|
|
||||||
struct fileio fileio;
|
struct fileio fileio;
|
||||||
Elf32_Ehdr *header;
|
Elf32_Ehdr *header;
|
||||||
Elf32_Phdr *segments;
|
Elf32_Phdr *segments;
|
||||||
|
@ -94,8 +88,7 @@ struct image_elf
|
||||||
uint8_t endianness;
|
uint8_t endianness;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct image_mot
|
struct image_mot {
|
||||||
{
|
|
||||||
struct fileio fileio;
|
struct fileio fileio;
|
||||||
uint8_t *buffer;
|
uint8_t *buffer;
|
||||||
};
|
};
|
||||||
|
@ -108,8 +101,8 @@ void image_close(struct image *image);
|
||||||
int image_add_section(struct image *image, uint32_t base, uint32_t size,
|
int image_add_section(struct image *image, uint32_t base, uint32_t size,
|
||||||
int flags, uint8_t *data);
|
int flags, uint8_t *data);
|
||||||
|
|
||||||
int image_calculate_checksum(uint8_t* buffer, uint32_t nbytes,
|
int image_calculate_checksum(uint8_t *buffer, uint32_t nbytes,
|
||||||
uint32_t* checksum);
|
uint32_t *checksum);
|
||||||
|
|
||||||
#define ERROR_IMAGE_FORMAT_ERROR (-1400)
|
#define ERROR_IMAGE_FORMAT_ERROR (-1400)
|
||||||
#define ERROR_IMAGE_TYPE_UNKNOWN (-1401)
|
#define ERROR_IMAGE_TYPE_UNKNOWN (-1401)
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
* Free Software Foundation, Inc., *
|
* Free Software Foundation, Inc., *
|
||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -34,8 +35,7 @@
|
||||||
#include "algorithm.h"
|
#include "algorithm.h"
|
||||||
#include "register.h"
|
#include "register.h"
|
||||||
|
|
||||||
static char* mips32_core_reg_list[] =
|
static char *mips32_core_reg_list[] = {
|
||||||
{
|
|
||||||
"zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
|
"zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
|
||||||
"t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
|
"t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
|
||||||
"s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
|
"s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
|
||||||
|
@ -43,13 +43,11 @@ static char* mips32_core_reg_list[] =
|
||||||
"status", "lo", "hi", "badvaddr", "cause", "pc"
|
"status", "lo", "hi", "badvaddr", "cause", "pc"
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char *mips_isa_strings[] =
|
static const char *mips_isa_strings[] = {
|
||||||
{
|
|
||||||
"MIPS32", "MIPS16e"
|
"MIPS32", "MIPS16e"
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct mips32_core_reg mips32_core_reg_list_arch_info[MIPS32NUMCOREREGS] =
|
static struct mips32_core_reg mips32_core_reg_list_arch_info[MIPS32NUMCOREREGS] = {
|
||||||
{
|
|
||||||
{0, NULL, NULL},
|
{0, NULL, NULL},
|
||||||
{1, NULL, NULL},
|
{1, NULL, NULL},
|
||||||
{2, NULL, NULL},
|
{2, NULL, NULL},
|
||||||
|
@ -94,12 +92,11 @@ static struct mips32_core_reg mips32_core_reg_list_arch_info[MIPS32NUMCOREREGS]
|
||||||
/* number of mips dummy fp regs fp0 - fp31 + fsr and fir
|
/* number of mips dummy fp regs fp0 - fp31 + fsr and fir
|
||||||
* we also add 18 unknown registers to handle gdb requests */
|
* we also add 18 unknown registers to handle gdb requests */
|
||||||
|
|
||||||
#define MIPS32NUMFPREGS 34 + 18
|
#define MIPS32NUMFPREGS (34 + 18)
|
||||||
|
|
||||||
static uint8_t mips32_gdb_dummy_fp_value[] = {0, 0, 0, 0};
|
static uint8_t mips32_gdb_dummy_fp_value[] = {0, 0, 0, 0};
|
||||||
|
|
||||||
static struct reg mips32_gdb_dummy_fp_reg =
|
static struct reg mips32_gdb_dummy_fp_reg = {
|
||||||
{
|
|
||||||
.name = "GDB dummy floating-point register",
|
.name = "GDB dummy floating-point register",
|
||||||
.value = mips32_gdb_dummy_fp_value,
|
.value = mips32_gdb_dummy_fp_value,
|
||||||
.dirty = 0,
|
.dirty = 0,
|
||||||
|
@ -116,9 +113,7 @@ static int mips32_get_core_reg(struct reg *reg)
|
||||||
struct mips32_common *mips32_target = target_to_mips32(target);
|
struct mips32_common *mips32_target = target_to_mips32(target);
|
||||||
|
|
||||||
if (target->state != TARGET_HALTED)
|
if (target->state != TARGET_HALTED)
|
||||||
{
|
|
||||||
return ERROR_TARGET_NOT_HALTED;
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
}
|
|
||||||
|
|
||||||
retval = mips32_target->read_core_reg(target, mips32_reg->num);
|
retval = mips32_target->read_core_reg(target, mips32_reg->num);
|
||||||
|
|
||||||
|
@ -132,9 +127,7 @@ static int mips32_set_core_reg(struct reg *reg, uint8_t *buf)
|
||||||
uint32_t value = buf_get_u32(buf, 0, 32);
|
uint32_t value = buf_get_u32(buf, 0, 32);
|
||||||
|
|
||||||
if (target->state != TARGET_HALTED)
|
if (target->state != TARGET_HALTED)
|
||||||
{
|
|
||||||
return ERROR_TARGET_NOT_HALTED;
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
}
|
|
||||||
|
|
||||||
buf_set_u32(reg->value, 0, 32, value);
|
buf_set_u32(reg->value, 0, 32, value);
|
||||||
reg->dirty = 1;
|
reg->dirty = 1;
|
||||||
|
@ -188,18 +181,14 @@ int mips32_get_gdb_reg_list(struct target *target, struct reg **reg_list[], int
|
||||||
|
|
||||||
/* include floating point registers */
|
/* include floating point registers */
|
||||||
*reg_list_size = MIPS32NUMCOREREGS + MIPS32NUMFPREGS;
|
*reg_list_size = MIPS32NUMCOREREGS + MIPS32NUMFPREGS;
|
||||||
*reg_list = malloc(sizeof(struct reg*) * (*reg_list_size));
|
*reg_list = malloc(sizeof(struct reg *) * (*reg_list_size));
|
||||||
|
|
||||||
for (i = 0; i < MIPS32NUMCOREREGS; i++)
|
for (i = 0; i < MIPS32NUMCOREREGS; i++)
|
||||||
{
|
|
||||||
(*reg_list)[i] = &mips32->core_cache->reg_list[i];
|
(*reg_list)[i] = &mips32->core_cache->reg_list[i];
|
||||||
}
|
|
||||||
|
|
||||||
/* add dummy floating points regs */
|
/* add dummy floating points regs */
|
||||||
for (i = MIPS32NUMCOREREGS; i < (MIPS32NUMCOREREGS + MIPS32NUMFPREGS); i++)
|
for (i = MIPS32NUMCOREREGS; i < (MIPS32NUMCOREREGS + MIPS32NUMFPREGS); i++)
|
||||||
{
|
|
||||||
(*reg_list)[i] = &mips32_gdb_dummy_fp_reg;
|
(*reg_list)[i] = &mips32_gdb_dummy_fp_reg;
|
||||||
}
|
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
@ -215,12 +204,9 @@ int mips32_save_context(struct target *target)
|
||||||
/* read core registers */
|
/* read core registers */
|
||||||
mips32_pracc_read_regs(ejtag_info, mips32->core_regs);
|
mips32_pracc_read_regs(ejtag_info, mips32->core_regs);
|
||||||
|
|
||||||
for (i = 0; i < MIPS32NUMCOREREGS; i++)
|
for (i = 0; i < MIPS32NUMCOREREGS; i++) {
|
||||||
{
|
|
||||||
if (!mips32->core_cache->reg_list[i].valid)
|
if (!mips32->core_cache->reg_list[i].valid)
|
||||||
{
|
|
||||||
mips32->read_core_reg(target, i);
|
mips32->read_core_reg(target, i);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
|
@ -234,12 +220,9 @@ int mips32_restore_context(struct target *target)
|
||||||
struct mips32_common *mips32 = target_to_mips32(target);
|
struct mips32_common *mips32 = target_to_mips32(target);
|
||||||
struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
|
struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
|
||||||
|
|
||||||
for (i = 0; i < MIPS32NUMCOREREGS; i++)
|
for (i = 0; i < MIPS32NUMCOREREGS; i++) {
|
||||||
{
|
|
||||||
if (mips32->core_cache->reg_list[i].dirty)
|
if (mips32->core_cache->reg_list[i].dirty)
|
||||||
{
|
|
||||||
mips32->write_core_reg(target, i);
|
mips32->write_core_reg(target, i);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* write core regs */
|
/* write core regs */
|
||||||
|
@ -287,8 +270,7 @@ struct reg_cache *mips32_build_reg_cache(struct target *target)
|
||||||
(*cache_p) = cache;
|
(*cache_p) = cache;
|
||||||
mips32->core_cache = cache;
|
mips32->core_cache = cache;
|
||||||
|
|
||||||
for (i = 0; i < num_regs; i++)
|
for (i = 0; i < num_regs; i++) {
|
||||||
{
|
|
||||||
arch_info[i] = mips32_core_reg_list_arch_info[i];
|
arch_info[i] = mips32_core_reg_list_arch_info[i];
|
||||||
arch_info[i].target = target;
|
arch_info[i].target = target;
|
||||||
arch_info[i].mips32_common = mips32;
|
arch_info[i].mips32_common = mips32;
|
||||||
|
@ -329,27 +311,24 @@ static int mips32_run_and_wait(struct target *target, uint32_t entry_point,
|
||||||
int retval;
|
int retval;
|
||||||
/* This code relies on the target specific resume() and poll()->debug_entry()
|
/* This code relies on the target specific resume() and poll()->debug_entry()
|
||||||
* sequence to write register values to the processor and the read them back */
|
* sequence to write register values to the processor and the read them back */
|
||||||
if ((retval = target_resume(target, 0, entry_point, 0, 1)) != ERROR_OK)
|
retval = target_resume(target, 0, entry_point, 0, 1);
|
||||||
{
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
|
||||||
|
|
||||||
retval = target_wait_state(target, TARGET_HALTED, timeout_ms);
|
retval = target_wait_state(target, TARGET_HALTED, timeout_ms);
|
||||||
/* If the target fails to halt due to the breakpoint, force a halt */
|
/* If the target fails to halt due to the breakpoint, force a halt */
|
||||||
if (retval != ERROR_OK || target->state != TARGET_HALTED)
|
if (retval != ERROR_OK || target->state != TARGET_HALTED) {
|
||||||
{
|
retval = target_halt(target);
|
||||||
if ((retval = target_halt(target)) != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
if ((retval = target_wait_state(target, TARGET_HALTED, 500)) != ERROR_OK)
|
retval = target_wait_state(target, TARGET_HALTED, 500);
|
||||||
{
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
|
||||||
return ERROR_TARGET_TIMEOUT;
|
return ERROR_TARGET_TIMEOUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
pc = buf_get_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 32);
|
pc = buf_get_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 32);
|
||||||
if (exit_point && (pc != exit_point))
|
if (exit_point && (pc != exit_point)) {
|
||||||
{
|
|
||||||
LOG_DEBUG("failed algorithm halted at 0x%" PRIx32 " ", pc);
|
LOG_DEBUG("failed algorithm halted at 0x%" PRIx32 " ", pc);
|
||||||
return ERROR_TARGET_TIMEOUT;
|
return ERROR_TARGET_TIMEOUT;
|
||||||
}
|
}
|
||||||
|
@ -375,47 +354,39 @@ int mips32_run_algorithm(struct target *target, int num_mem_params,
|
||||||
/* NOTE: mips32_run_algorithm requires that each algorithm uses a software breakpoint
|
/* NOTE: mips32_run_algorithm requires that each algorithm uses a software breakpoint
|
||||||
* at the exit point */
|
* at the exit point */
|
||||||
|
|
||||||
if (mips32->common_magic != MIPS32_COMMON_MAGIC)
|
if (mips32->common_magic != MIPS32_COMMON_MAGIC) {
|
||||||
{
|
|
||||||
LOG_ERROR("current target isn't a MIPS32 target");
|
LOG_ERROR("current target isn't a MIPS32 target");
|
||||||
return ERROR_TARGET_INVALID;
|
return ERROR_TARGET_INVALID;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (target->state != TARGET_HALTED)
|
if (target->state != TARGET_HALTED) {
|
||||||
{
|
|
||||||
LOG_WARNING("target not halted");
|
LOG_WARNING("target not halted");
|
||||||
return ERROR_TARGET_NOT_HALTED;
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* refresh core register cache */
|
/* refresh core register cache */
|
||||||
for (i = 0; i < MIPS32NUMCOREREGS; i++)
|
for (i = 0; i < MIPS32NUMCOREREGS; i++) {
|
||||||
{
|
|
||||||
if (!mips32->core_cache->reg_list[i].valid)
|
if (!mips32->core_cache->reg_list[i].valid)
|
||||||
mips32->read_core_reg(target, i);
|
mips32->read_core_reg(target, i);
|
||||||
context[i] = buf_get_u32(mips32->core_cache->reg_list[i].value, 0, 32);
|
context[i] = buf_get_u32(mips32->core_cache->reg_list[i].value, 0, 32);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < num_mem_params; i++)
|
for (i = 0; i < num_mem_params; i++) {
|
||||||
{
|
retval = target_write_buffer(target, mem_params[i].address,
|
||||||
if ((retval = target_write_buffer(target, mem_params[i].address,
|
mem_params[i].size, mem_params[i].value);
|
||||||
mem_params[i].size, mem_params[i].value)) != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
{
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < num_reg_params; i++)
|
for (i = 0; i < num_reg_params; i++) {
|
||||||
{
|
|
||||||
struct reg *reg = register_get_by_name(mips32->core_cache, reg_params[i].reg_name, 0);
|
struct reg *reg = register_get_by_name(mips32->core_cache, reg_params[i].reg_name, 0);
|
||||||
|
|
||||||
if (!reg)
|
if (!reg) {
|
||||||
{
|
|
||||||
LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name);
|
LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name);
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (reg->size != reg_params[i].size)
|
if (reg->size != reg_params[i].size) {
|
||||||
{
|
|
||||||
LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size",
|
LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size",
|
||||||
reg_params[i].reg_name);
|
reg_params[i].reg_name);
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
|
@ -431,31 +402,24 @@ int mips32_run_algorithm(struct target *target, int num_mem_params,
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
for (i = 0; i < num_mem_params; i++)
|
for (i = 0; i < num_mem_params; i++) {
|
||||||
{
|
if (mem_params[i].direction != PARAM_OUT) {
|
||||||
if (mem_params[i].direction != PARAM_OUT)
|
retval = target_read_buffer(target, mem_params[i].address, mem_params[i].size,
|
||||||
{
|
mem_params[i].value);
|
||||||
if ((retval = target_read_buffer(target, mem_params[i].address, mem_params[i].size,
|
if (retval != ERROR_OK)
|
||||||
mem_params[i].value)) != ERROR_OK)
|
|
||||||
{
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < num_reg_params; i++)
|
for (i = 0; i < num_reg_params; i++) {
|
||||||
{
|
if (reg_params[i].direction != PARAM_OUT) {
|
||||||
if (reg_params[i].direction != PARAM_OUT)
|
|
||||||
{
|
|
||||||
struct reg *reg = register_get_by_name(mips32->core_cache, reg_params[i].reg_name, 0);
|
struct reg *reg = register_get_by_name(mips32->core_cache, reg_params[i].reg_name, 0);
|
||||||
if (!reg)
|
if (!reg) {
|
||||||
{
|
|
||||||
LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name);
|
LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name);
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (reg->size != reg_params[i].size)
|
if (reg->size != reg_params[i].size) {
|
||||||
{
|
|
||||||
LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size",
|
LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size",
|
||||||
reg_params[i].reg_name);
|
reg_params[i].reg_name);
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
|
@ -466,12 +430,10 @@ int mips32_run_algorithm(struct target *target, int num_mem_params,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* restore everything we saved before */
|
/* restore everything we saved before */
|
||||||
for (i = 0; i < MIPS32NUMCOREREGS; i++)
|
for (i = 0; i < MIPS32NUMCOREREGS; i++) {
|
||||||
{
|
|
||||||
uint32_t regvalue;
|
uint32_t regvalue;
|
||||||
regvalue = buf_get_u32(mips32->core_cache->reg_list[i].value, 0, 32);
|
regvalue = buf_get_u32(mips32->core_cache->reg_list[i].value, 0, 32);
|
||||||
if (regvalue != context[i])
|
if (regvalue != context[i]) {
|
||||||
{
|
|
||||||
LOG_DEBUG("restoring register %s with value 0x%8.8" PRIx32,
|
LOG_DEBUG("restoring register %s with value 0x%8.8" PRIx32,
|
||||||
mips32->core_cache->reg_list[i].name, context[i]);
|
mips32->core_cache->reg_list[i].name, context[i]);
|
||||||
buf_set_u32(mips32->core_cache->reg_list[i].value,
|
buf_set_u32(mips32->core_cache->reg_list[i].value,
|
||||||
|
@ -490,8 +452,7 @@ int mips32_examine(struct target *target)
|
||||||
{
|
{
|
||||||
struct mips32_common *mips32 = target_to_mips32(target);
|
struct mips32_common *mips32 = target_to_mips32(target);
|
||||||
|
|
||||||
if (!target_was_examined(target))
|
if (!target_was_examined(target)) {
|
||||||
{
|
|
||||||
target_set_examined(target);
|
target_set_examined(target);
|
||||||
|
|
||||||
/* we will configure later */
|
/* we will configure later */
|
||||||
|
@ -517,53 +478,50 @@ int mips32_configure_break_unit(struct target *target)
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
|
|
||||||
/* get info about breakpoint support */
|
/* get info about breakpoint support */
|
||||||
if ((retval = target_read_u32(target, EJTAG_DCR, &dcr)) != ERROR_OK)
|
retval = target_read_u32(target, EJTAG_DCR, &dcr);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
if (dcr & EJTAG_DCR_IB)
|
if (dcr & EJTAG_DCR_IB) {
|
||||||
{
|
|
||||||
/* get number of inst breakpoints */
|
/* get number of inst breakpoints */
|
||||||
if ((retval = target_read_u32(target, EJTAG_IBS, &bpinfo)) != ERROR_OK)
|
retval = target_read_u32(target, EJTAG_IBS, &bpinfo);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
mips32->num_inst_bpoints = (bpinfo >> 24) & 0x0F;
|
mips32->num_inst_bpoints = (bpinfo >> 24) & 0x0F;
|
||||||
mips32->num_inst_bpoints_avail = mips32->num_inst_bpoints;
|
mips32->num_inst_bpoints_avail = mips32->num_inst_bpoints;
|
||||||
mips32->inst_break_list = calloc(mips32->num_inst_bpoints, sizeof(struct mips32_comparator));
|
mips32->inst_break_list = calloc(mips32->num_inst_bpoints, sizeof(struct mips32_comparator));
|
||||||
for (i = 0; i < mips32->num_inst_bpoints; i++)
|
for (i = 0; i < mips32->num_inst_bpoints; i++)
|
||||||
{
|
|
||||||
mips32->inst_break_list[i].reg_address = EJTAG_IBA1 + (0x100 * i);
|
mips32->inst_break_list[i].reg_address = EJTAG_IBA1 + (0x100 * i);
|
||||||
}
|
|
||||||
|
|
||||||
/* clear IBIS reg */
|
/* clear IBIS reg */
|
||||||
if ((retval = target_write_u32(target, EJTAG_IBS, 0)) != ERROR_OK)
|
retval = target_write_u32(target, EJTAG_IBS, 0);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dcr & EJTAG_DCR_DB)
|
if (dcr & EJTAG_DCR_DB) {
|
||||||
{
|
|
||||||
/* get number of data breakpoints */
|
/* get number of data breakpoints */
|
||||||
if ((retval = target_read_u32(target, EJTAG_DBS, &bpinfo)) != ERROR_OK)
|
retval = target_read_u32(target, EJTAG_DBS, &bpinfo);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
mips32->num_data_bpoints = (bpinfo >> 24) & 0x0F;
|
mips32->num_data_bpoints = (bpinfo >> 24) & 0x0F;
|
||||||
mips32->num_data_bpoints_avail = mips32->num_data_bpoints;
|
mips32->num_data_bpoints_avail = mips32->num_data_bpoints;
|
||||||
mips32->data_break_list = calloc(mips32->num_data_bpoints, sizeof(struct mips32_comparator));
|
mips32->data_break_list = calloc(mips32->num_data_bpoints, sizeof(struct mips32_comparator));
|
||||||
for (i = 0; i < mips32->num_data_bpoints; i++)
|
for (i = 0; i < mips32->num_data_bpoints; i++)
|
||||||
{
|
|
||||||
mips32->data_break_list[i].reg_address = EJTAG_DBA1 + (0x100 * i);
|
mips32->data_break_list[i].reg_address = EJTAG_DBA1 + (0x100 * i);
|
||||||
}
|
|
||||||
|
|
||||||
/* clear DBIS reg */
|
/* clear DBIS reg */
|
||||||
if ((retval = target_write_u32(target, EJTAG_DBS, 0)) != ERROR_OK)
|
retval = target_write_u32(target, EJTAG_DBS, 0);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* check if target endianness settings matches debug control register */
|
/* check if target endianness settings matches debug control register */
|
||||||
if ( ( (dcr & EJTAG_DCR_ENM) && (target->endianness == TARGET_LITTLE_ENDIAN) ) ||
|
if (((dcr & EJTAG_DCR_ENM) && (target->endianness == TARGET_LITTLE_ENDIAN)) ||
|
||||||
( !(dcr & EJTAG_DCR_ENM) && (target->endianness == TARGET_BIG_ENDIAN) ) )
|
(!(dcr & EJTAG_DCR_ENM) && (target->endianness == TARGET_BIG_ENDIAN)))
|
||||||
{
|
|
||||||
LOG_WARNING("DCR endianness settings does not match target settings");
|
LOG_WARNING("DCR endianness settings does not match target settings");
|
||||||
}
|
|
||||||
|
|
||||||
LOG_DEBUG("DCR 0x%" PRIx32 " numinst %i numdata %i", dcr, mips32->num_inst_bpoints,
|
LOG_DEBUG("DCR 0x%" PRIx32 " numinst %i numdata %i", dcr, mips32->num_inst_bpoints,
|
||||||
mips32->num_data_bpoints);
|
mips32->num_data_bpoints);
|
||||||
|
@ -580,31 +538,27 @@ int mips32_enable_interrupts(struct target *target, int enable)
|
||||||
uint32_t dcr;
|
uint32_t dcr;
|
||||||
|
|
||||||
/* read debug control register */
|
/* read debug control register */
|
||||||
if ((retval = target_read_u32(target, EJTAG_DCR, &dcr)) != ERROR_OK)
|
retval = target_read_u32(target, EJTAG_DCR, &dcr);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
if (enable)
|
if (enable) {
|
||||||
{
|
if (!(dcr & EJTAG_DCR_INTE)) {
|
||||||
if (!(dcr & EJTAG_DCR_INTE))
|
|
||||||
{
|
|
||||||
/* enable interrupts */
|
/* enable interrupts */
|
||||||
dcr |= EJTAG_DCR_INTE;
|
dcr |= EJTAG_DCR_INTE;
|
||||||
update = 1;
|
update = 1;
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
if (dcr & EJTAG_DCR_INTE) {
|
||||||
{
|
|
||||||
if (dcr & EJTAG_DCR_INTE)
|
|
||||||
{
|
|
||||||
/* disable interrupts */
|
/* disable interrupts */
|
||||||
dcr &= ~EJTAG_DCR_INTE;
|
dcr &= ~EJTAG_DCR_INTE;
|
||||||
update = 1;
|
update = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (update)
|
if (update) {
|
||||||
{
|
retval = target_write_u32(target, EJTAG_DCR, dcr);
|
||||||
if ((retval = target_write_u32(target, EJTAG_DCR, dcr)) != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -612,7 +566,7 @@ int mips32_enable_interrupts(struct target *target, int enable)
|
||||||
}
|
}
|
||||||
|
|
||||||
int mips32_checksum_memory(struct target *target, uint32_t address,
|
int mips32_checksum_memory(struct target *target, uint32_t address,
|
||||||
uint32_t count, uint32_t* checksum)
|
uint32_t count, uint32_t *checksum)
|
||||||
{
|
{
|
||||||
struct working_area *crc_algorithm;
|
struct working_area *crc_algorithm;
|
||||||
struct reg_param reg_params[2];
|
struct reg_param reg_params[2];
|
||||||
|
@ -622,9 +576,8 @@ int mips32_checksum_memory(struct target *target, uint32_t address,
|
||||||
|
|
||||||
/* see contib/loaders/checksum/mips32.s for src */
|
/* see contib/loaders/checksum/mips32.s for src */
|
||||||
|
|
||||||
static const uint32_t mips_crc_code[] =
|
static const uint32_t mips_crc_code[] = {
|
||||||
{
|
0x248C0000, /* addiu $t4, $a0, 0 */
|
||||||
0x248C0000, /* addiu $t4, $a0, 0 */
|
|
||||||
0x24AA0000, /* addiu $t2, $a1, 0 */
|
0x24AA0000, /* addiu $t2, $a1, 0 */
|
||||||
0x2404FFFF, /* addiu $a0, $zero, 0xffffffff */
|
0x2404FFFF, /* addiu $a0, $zero, 0xffffffff */
|
||||||
0x10000010, /* beq $zero, $zero, ncomp */
|
0x10000010, /* beq $zero, $zero, ncomp */
|
||||||
|
@ -654,9 +607,7 @@ int mips32_checksum_memory(struct target *target, uint32_t address,
|
||||||
|
|
||||||
/* make sure we have a working area */
|
/* make sure we have a working area */
|
||||||
if (target_alloc_working_area(target, sizeof(mips_crc_code), &crc_algorithm) != ERROR_OK)
|
if (target_alloc_working_area(target, sizeof(mips_crc_code), &crc_algorithm) != ERROR_OK)
|
||||||
{
|
|
||||||
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
|
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
|
||||||
}
|
|
||||||
|
|
||||||
/* convert flash writing code into a buffer in target endianness */
|
/* convert flash writing code into a buffer in target endianness */
|
||||||
for (i = 0; i < ARRAY_SIZE(mips_crc_code); i++)
|
for (i = 0; i < ARRAY_SIZE(mips_crc_code); i++)
|
||||||
|
@ -673,10 +624,10 @@ int mips32_checksum_memory(struct target *target, uint32_t address,
|
||||||
|
|
||||||
int timeout = 20000 * (1 + (count / (1024 * 1024)));
|
int timeout = 20000 * (1 + (count / (1024 * 1024)));
|
||||||
|
|
||||||
if ((retval = target_run_algorithm(target, 0, NULL, 2, reg_params,
|
retval = target_run_algorithm(target, 0, NULL, 2, reg_params,
|
||||||
crc_algorithm->address, crc_algorithm->address + (sizeof(mips_crc_code)-4), timeout,
|
crc_algorithm->address, crc_algorithm->address + (sizeof(mips_crc_code)-4), timeout,
|
||||||
&mips32_info)) != ERROR_OK)
|
&mips32_info);
|
||||||
{
|
if (retval != ERROR_OK) {
|
||||||
destroy_reg_param(®_params[0]);
|
destroy_reg_param(®_params[0]);
|
||||||
destroy_reg_param(®_params[1]);
|
destroy_reg_param(®_params[1]);
|
||||||
target_free_working_area(target, crc_algorithm);
|
target_free_working_area(target, crc_algorithm);
|
||||||
|
@ -695,7 +646,7 @@ int mips32_checksum_memory(struct target *target, uint32_t address,
|
||||||
|
|
||||||
/** Checks whether a memory region is zeroed. */
|
/** Checks whether a memory region is zeroed. */
|
||||||
int mips32_blank_check_memory(struct target *target,
|
int mips32_blank_check_memory(struct target *target,
|
||||||
uint32_t address, uint32_t count, uint32_t* blank)
|
uint32_t address, uint32_t count, uint32_t *blank)
|
||||||
{
|
{
|
||||||
struct working_area *erase_check_algorithm;
|
struct working_area *erase_check_algorithm;
|
||||||
struct reg_param reg_params[3];
|
struct reg_param reg_params[3];
|
||||||
|
@ -703,8 +654,7 @@ int mips32_blank_check_memory(struct target *target,
|
||||||
int retval;
|
int retval;
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
|
|
||||||
static const uint32_t erase_check_code[] =
|
static const uint32_t erase_check_code[] = {
|
||||||
{
|
|
||||||
/* nbyte: */
|
/* nbyte: */
|
||||||
0x80880000, /* lb $t0, ($a0) */
|
0x80880000, /* lb $t0, ($a0) */
|
||||||
0x00C83024, /* and $a2, $a2, $t0 */
|
0x00C83024, /* and $a2, $a2, $t0 */
|
||||||
|
@ -716,13 +666,10 @@ int mips32_blank_check_memory(struct target *target,
|
||||||
|
|
||||||
/* make sure we have a working area */
|
/* make sure we have a working area */
|
||||||
if (target_alloc_working_area(target, sizeof(erase_check_code), &erase_check_algorithm) != ERROR_OK)
|
if (target_alloc_working_area(target, sizeof(erase_check_code), &erase_check_algorithm) != ERROR_OK)
|
||||||
{
|
|
||||||
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
|
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
|
||||||
}
|
|
||||||
|
|
||||||
/* convert flash writing code into a buffer in target endianness */
|
/* convert flash writing code into a buffer in target endianness */
|
||||||
for (i = 0; i < ARRAY_SIZE(erase_check_code); i++)
|
for (i = 0; i < ARRAY_SIZE(erase_check_code); i++) {
|
||||||
{
|
|
||||||
target_write_u32(target, erase_check_algorithm->address + i*sizeof(uint32_t),
|
target_write_u32(target, erase_check_algorithm->address + i*sizeof(uint32_t),
|
||||||
erase_check_code[i]);
|
erase_check_code[i]);
|
||||||
}
|
}
|
||||||
|
@ -739,11 +686,11 @@ int mips32_blank_check_memory(struct target *target,
|
||||||
init_reg_param(®_params[2], "a2", 32, PARAM_IN_OUT);
|
init_reg_param(®_params[2], "a2", 32, PARAM_IN_OUT);
|
||||||
buf_set_u32(reg_params[2].value, 0, 32, 0xff);
|
buf_set_u32(reg_params[2].value, 0, 32, 0xff);
|
||||||
|
|
||||||
if ((retval = target_run_algorithm(target, 0, NULL, 3, reg_params,
|
retval = target_run_algorithm(target, 0, NULL, 3, reg_params,
|
||||||
erase_check_algorithm->address,
|
erase_check_algorithm->address,
|
||||||
erase_check_algorithm->address + (sizeof(erase_check_code)-2),
|
erase_check_algorithm->address + (sizeof(erase_check_code)-2),
|
||||||
10000, &mips32_info)) != ERROR_OK)
|
10000, &mips32_info);
|
||||||
{
|
if (retval != ERROR_OK) {
|
||||||
destroy_reg_param(®_params[0]);
|
destroy_reg_param(®_params[0]);
|
||||||
destroy_reg_param(®_params[1]);
|
destroy_reg_param(®_params[1]);
|
||||||
destroy_reg_param(®_params[2]);
|
destroy_reg_param(®_params[2]);
|
||||||
|
@ -788,48 +735,40 @@ COMMAND_HANDLER(mips32_handle_cp0_command)
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
if (target->state != TARGET_HALTED)
|
if (target->state != TARGET_HALTED) {
|
||||||
{
|
|
||||||
command_print(CMD_CTX, "target must be stopped for \"%s\" command", CMD_NAME);
|
command_print(CMD_CTX, "target must be stopped for \"%s\" command", CMD_NAME);
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* two or more argument, access a single register/select (write if third argument is given) */
|
/* two or more argument, access a single register/select (write if third argument is given) */
|
||||||
if (CMD_ARGC < 2)
|
if (CMD_ARGC < 2)
|
||||||
{
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
else {
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
uint32_t cp0_reg, cp0_sel;
|
uint32_t cp0_reg, cp0_sel;
|
||||||
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], cp0_reg);
|
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], cp0_reg);
|
||||||
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], cp0_sel);
|
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], cp0_sel);
|
||||||
|
|
||||||
if (CMD_ARGC == 2)
|
if (CMD_ARGC == 2) {
|
||||||
{
|
|
||||||
uint32_t value;
|
uint32_t value;
|
||||||
|
|
||||||
if ((retval = mips32_cp0_read(ejtag_info, &value, cp0_reg, cp0_sel)) != ERROR_OK)
|
retval = mips32_cp0_read(ejtag_info, &value, cp0_reg, cp0_sel);
|
||||||
{
|
if (retval != ERROR_OK) {
|
||||||
command_print(CMD_CTX,
|
command_print(CMD_CTX,
|
||||||
"couldn't access reg %" PRIi32,
|
"couldn't access reg %" PRIi32,
|
||||||
cp0_reg);
|
cp0_reg);
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
if ((retval = jtag_execute_queue()) != ERROR_OK)
|
retval = jtag_execute_queue();
|
||||||
{
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
|
||||||
|
|
||||||
command_print(CMD_CTX, "cp0 reg %" PRIi32 ", select %" PRIi32 ": %8.8" PRIx32,
|
command_print(CMD_CTX, "cp0 reg %" PRIi32 ", select %" PRIi32 ": %8.8" PRIx32,
|
||||||
cp0_reg, cp0_sel, value);
|
cp0_reg, cp0_sel, value);
|
||||||
}
|
} else if (CMD_ARGC == 3) {
|
||||||
else if (CMD_ARGC == 3)
|
|
||||||
{
|
|
||||||
uint32_t value;
|
uint32_t value;
|
||||||
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], value);
|
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], value);
|
||||||
if ((retval = mips32_cp0_write(ejtag_info, value, cp0_reg, cp0_sel)) != ERROR_OK)
|
retval = mips32_cp0_write(ejtag_info, value, cp0_reg, cp0_sel);
|
||||||
{
|
if (retval != ERROR_OK) {
|
||||||
command_print(CMD_CTX,
|
command_print(CMD_CTX,
|
||||||
"couldn't access cp0 reg %" PRIi32 ", select %" PRIi32,
|
"couldn't access cp0 reg %" PRIi32 ", select %" PRIi32,
|
||||||
cp0_reg, cp0_sel);
|
cp0_reg, cp0_sel);
|
||||||
|
@ -864,4 +803,3 @@ const struct command_registration mips32_command_handlers[] = {
|
||||||
},
|
},
|
||||||
COMMAND_REGISTRATION_DONE
|
COMMAND_REGISTRATION_DONE
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -64,27 +64,23 @@
|
||||||
#define MIPS32_ARCH_REL2 0x1
|
#define MIPS32_ARCH_REL2 0x1
|
||||||
|
|
||||||
/* offsets into mips32 core register cache */
|
/* offsets into mips32 core register cache */
|
||||||
enum
|
enum {
|
||||||
{
|
|
||||||
MIPS32_PC = 37,
|
MIPS32_PC = 37,
|
||||||
MIPS32NUMCOREREGS
|
MIPS32NUMCOREREGS
|
||||||
};
|
};
|
||||||
|
|
||||||
enum mips32_isa_mode
|
enum mips32_isa_mode {
|
||||||
{
|
|
||||||
MIPS32_ISA_MIPS32 = 0,
|
MIPS32_ISA_MIPS32 = 0,
|
||||||
MIPS32_ISA_MIPS16E = 1,
|
MIPS32_ISA_MIPS16E = 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct mips32_comparator
|
struct mips32_comparator {
|
||||||
{
|
|
||||||
int used;
|
int used;
|
||||||
uint32_t bp_value;
|
uint32_t bp_value;
|
||||||
uint32_t reg_address;
|
uint32_t reg_address;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct mips32_common
|
struct mips32_common {
|
||||||
{
|
|
||||||
uint32_t common_magic;
|
uint32_t common_magic;
|
||||||
void *arch_info;
|
void *arch_info;
|
||||||
struct reg_cache *core_cache;
|
struct reg_cache *core_cache;
|
||||||
|
@ -114,15 +110,13 @@ target_to_mips32(struct target *target)
|
||||||
return target->arch_info;
|
return target->arch_info;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct mips32_core_reg
|
struct mips32_core_reg {
|
||||||
{
|
|
||||||
uint32_t num;
|
uint32_t num;
|
||||||
struct target *target;
|
struct target *target;
|
||||||
struct mips32_common *mips32_common;
|
struct mips32_common *mips32_common;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct mips32_algorithm
|
struct mips32_algorithm {
|
||||||
{
|
|
||||||
int common_magic;
|
int common_magic;
|
||||||
enum mips32_isa_mode isa_mode;
|
enum mips32_isa_mode isa_mode;
|
||||||
};
|
};
|
||||||
|
@ -164,9 +158,11 @@ struct mips32_algorithm
|
||||||
#define MIPS32_COP0_MF 0x00
|
#define MIPS32_COP0_MF 0x00
|
||||||
#define MIPS32_COP0_MT 0x04
|
#define MIPS32_COP0_MT 0x04
|
||||||
|
|
||||||
#define MIPS32_R_INST(opcode, rs, rt, rd, shamt, funct) (((opcode) << 26) |((rs) << 21) | ((rt) << 16) | ((rd) << 11)| ((shamt) << 6) | (funct))
|
#define MIPS32_R_INST(opcode, rs, rt, rd, shamt, funct) \
|
||||||
#define MIPS32_I_INST(opcode, rs, rt, immd) (((opcode) << 26) |((rs) << 21) | ((rt) << 16) | (immd))
|
(((opcode) << 26) | ((rs) << 21) | ((rt) << 16) | ((rd) << 11) | ((shamt) << 6) | (funct))
|
||||||
#define MIPS32_J_INST(opcode, addr) (((opcode) << 26) |(addr))
|
#define MIPS32_I_INST(opcode, rs, rt, immd) \
|
||||||
|
(((opcode) << 26) | ((rs) << 21) | ((rt) << 16) | (immd))
|
||||||
|
#define MIPS32_J_INST(opcode, addr) (((opcode) << 26) | (addr))
|
||||||
|
|
||||||
#define MIPS32_NOP 0
|
#define MIPS32_NOP 0
|
||||||
#define MIPS32_ADDI(tar, src, val) MIPS32_I_INST(MIPS32_OP_ADDI, src, tar, val)
|
#define MIPS32_ADDI(tar, src, val) MIPS32_I_INST(MIPS32_OP_ADDI, src, tar, val)
|
||||||
|
@ -176,7 +172,7 @@ struct mips32_algorithm
|
||||||
#define MIPS32_B(off) MIPS32_BEQ(0, 0, off)
|
#define MIPS32_B(off) MIPS32_BEQ(0, 0, off)
|
||||||
#define MIPS32_BEQ(src, tar, off) MIPS32_I_INST(MIPS32_OP_BEQ, src, tar, off)
|
#define MIPS32_BEQ(src, tar, off) MIPS32_I_INST(MIPS32_OP_BEQ, src, tar, off)
|
||||||
#define MIPS32_BGTZ(reg, off) MIPS32_I_INST(MIPS32_OP_BGTZ, reg, 0, off)
|
#define MIPS32_BGTZ(reg, off) MIPS32_I_INST(MIPS32_OP_BGTZ, reg, 0, off)
|
||||||
#define MIPS32_BNE(src,tar,off) MIPS32_I_INST(MIPS32_OP_BNE, src, tar, off)
|
#define MIPS32_BNE(src, tar, off) MIPS32_I_INST(MIPS32_OP_BNE, src, tar, off)
|
||||||
#define MIPS32_CACHE(op, off, base) MIPS32_I_INST(MIPS32_OP_CACHE, base, op, off)
|
#define MIPS32_CACHE(op, off, base) MIPS32_I_INST(MIPS32_OP_CACHE, base, op, off)
|
||||||
#define MIPS32_JR(reg) MIPS32_R_INST(0, reg, 0, 0, 0, MIPS32_OP_JR)
|
#define MIPS32_JR(reg) MIPS32_R_INST(0, reg, 0, 0, 0, MIPS32_OP_JR)
|
||||||
#define MIPS32_MFC0(gpr, cpr, sel) MIPS32_R_INST(MIPS32_OP_COP0, MIPS32_COP0_MF, gpr, cpr, 0, sel)
|
#define MIPS32_MFC0(gpr, cpr, sel) MIPS32_R_INST(MIPS32_OP_COP0, MIPS32_COP0_MF, gpr, cpr, 0, sel)
|
||||||
|
@ -245,8 +241,8 @@ int mips32_register_commands(struct command_context *cmd_ctx);
|
||||||
int mips32_get_gdb_reg_list(struct target *target,
|
int mips32_get_gdb_reg_list(struct target *target,
|
||||||
struct reg **reg_list[], int *reg_list_size);
|
struct reg **reg_list[], int *reg_list_size);
|
||||||
int mips32_checksum_memory(struct target *target, uint32_t address,
|
int mips32_checksum_memory(struct target *target, uint32_t address,
|
||||||
uint32_t count, uint32_t* checksum);
|
uint32_t count, uint32_t *checksum);
|
||||||
int mips32_blank_check_memory(struct target *target,
|
int mips32_blank_check_memory(struct target *target,
|
||||||
uint32_t address, uint32_t count, uint32_t* blank);
|
uint32_t address, uint32_t count, uint32_t *blank);
|
||||||
|
|
||||||
#endif /*MIPS32_H*/
|
#endif /*MIPS32_H*/
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
* Free Software Foundation, Inc., *
|
* Free Software Foundation, Inc., *
|
||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -84,13 +85,11 @@ begin_ejtag_dma_read:
|
||||||
mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL);
|
mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL);
|
||||||
ejtag_ctrl = ejtag_info->ejtag_ctrl;
|
ejtag_ctrl = ejtag_info->ejtag_ctrl;
|
||||||
mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
|
mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
|
||||||
if (ejtag_ctrl & EJTAG_CTRL_DERR)
|
if (ejtag_ctrl & EJTAG_CTRL_DERR) {
|
||||||
{
|
|
||||||
if (retries--) {
|
if (retries--) {
|
||||||
LOG_ERROR("DMA Read Addr = %08" PRIx32 " Data = ERROR ON READ (retrying)", addr);
|
LOG_ERROR("DMA Read Addr = %08" PRIx32 " Data = ERROR ON READ (retrying)", addr);
|
||||||
goto begin_ejtag_dma_read;
|
goto begin_ejtag_dma_read;
|
||||||
}
|
} else
|
||||||
else
|
|
||||||
LOG_ERROR("DMA Read Addr = %08" PRIx32 " Data = ERROR ON READ", addr);
|
LOG_ERROR("DMA Read Addr = %08" PRIx32 " Data = ERROR ON READ", addr);
|
||||||
return ERROR_JTAG_DEVICE_ERROR;
|
return ERROR_JTAG_DEVICE_ERROR;
|
||||||
}
|
}
|
||||||
|
@ -113,7 +112,8 @@ begin_ejtag_dma_read_h:
|
||||||
|
|
||||||
/* Initiate DMA Read & set DSTRT */
|
/* Initiate DMA Read & set DSTRT */
|
||||||
mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL);
|
mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL);
|
||||||
ejtag_ctrl = EJTAG_CTRL_DMAACC | EJTAG_CTRL_DRWN | EJTAG_CTRL_DMA_HALFWORD | EJTAG_CTRL_DSTRT | ejtag_info->ejtag_ctrl;
|
ejtag_ctrl = EJTAG_CTRL_DMAACC | EJTAG_CTRL_DRWN | EJTAG_CTRL_DMA_HALFWORD |
|
||||||
|
EJTAG_CTRL_DSTRT | ejtag_info->ejtag_ctrl;
|
||||||
mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
|
mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
|
||||||
|
|
||||||
/* Wait for DSTRT to Clear */
|
/* Wait for DSTRT to Clear */
|
||||||
|
@ -130,13 +130,11 @@ begin_ejtag_dma_read_h:
|
||||||
mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL);
|
mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL);
|
||||||
ejtag_ctrl = ejtag_info->ejtag_ctrl;
|
ejtag_ctrl = ejtag_info->ejtag_ctrl;
|
||||||
mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
|
mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
|
||||||
if (ejtag_ctrl & EJTAG_CTRL_DERR)
|
if (ejtag_ctrl & EJTAG_CTRL_DERR) {
|
||||||
{
|
|
||||||
if (retries--) {
|
if (retries--) {
|
||||||
LOG_ERROR("DMA Read Addr = %08" PRIx32 " Data = ERROR ON READ (retrying)", addr);
|
LOG_ERROR("DMA Read Addr = %08" PRIx32 " Data = ERROR ON READ (retrying)", addr);
|
||||||
goto begin_ejtag_dma_read_h;
|
goto begin_ejtag_dma_read_h;
|
||||||
}
|
} else
|
||||||
else
|
|
||||||
LOG_ERROR("DMA Read Addr = %08" PRIx32 " Data = ERROR ON READ", addr);
|
LOG_ERROR("DMA Read Addr = %08" PRIx32 " Data = ERROR ON READ", addr);
|
||||||
return ERROR_JTAG_DEVICE_ERROR;
|
return ERROR_JTAG_DEVICE_ERROR;
|
||||||
}
|
}
|
||||||
|
@ -182,13 +180,11 @@ begin_ejtag_dma_read_b:
|
||||||
mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL);
|
mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL);
|
||||||
ejtag_ctrl = ejtag_info->ejtag_ctrl;
|
ejtag_ctrl = ejtag_info->ejtag_ctrl;
|
||||||
mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
|
mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
|
||||||
if (ejtag_ctrl & EJTAG_CTRL_DERR)
|
if (ejtag_ctrl & EJTAG_CTRL_DERR) {
|
||||||
{
|
|
||||||
if (retries--) {
|
if (retries--) {
|
||||||
LOG_ERROR("DMA Read Addr = %08" PRIx32 " Data = ERROR ON READ (retrying)", addr);
|
LOG_ERROR("DMA Read Addr = %08" PRIx32 " Data = ERROR ON READ (retrying)", addr);
|
||||||
goto begin_ejtag_dma_read_b;
|
goto begin_ejtag_dma_read_b;
|
||||||
}
|
} else
|
||||||
else
|
|
||||||
LOG_ERROR("DMA Read Addr = %08" PRIx32 " Data = ERROR ON READ", addr);
|
LOG_ERROR("DMA Read Addr = %08" PRIx32 " Data = ERROR ON READ", addr);
|
||||||
return ERROR_JTAG_DEVICE_ERROR;
|
return ERROR_JTAG_DEVICE_ERROR;
|
||||||
}
|
}
|
||||||
|
@ -245,13 +241,11 @@ begin_ejtag_dma_write:
|
||||||
mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL);
|
mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL);
|
||||||
ejtag_ctrl = ejtag_info->ejtag_ctrl;
|
ejtag_ctrl = ejtag_info->ejtag_ctrl;
|
||||||
mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
|
mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
|
||||||
if (ejtag_ctrl & EJTAG_CTRL_DERR)
|
if (ejtag_ctrl & EJTAG_CTRL_DERR) {
|
||||||
{
|
|
||||||
if (retries--) {
|
if (retries--) {
|
||||||
LOG_ERROR("DMA Write Addr = %08" PRIx32 " Data = ERROR ON WRITE (retrying)", addr);
|
LOG_ERROR("DMA Write Addr = %08" PRIx32 " Data = ERROR ON WRITE (retrying)", addr);
|
||||||
goto begin_ejtag_dma_write;
|
goto begin_ejtag_dma_write;
|
||||||
}
|
} else
|
||||||
else
|
|
||||||
LOG_ERROR("DMA Write Addr = %08" PRIx32 " Data = ERROR ON WRITE", addr);
|
LOG_ERROR("DMA Write Addr = %08" PRIx32 " Data = ERROR ON WRITE", addr);
|
||||||
return ERROR_JTAG_DEVICE_ERROR;
|
return ERROR_JTAG_DEVICE_ERROR;
|
||||||
}
|
}
|
||||||
|
@ -296,13 +290,11 @@ begin_ejtag_dma_write_h:
|
||||||
mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL);
|
mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL);
|
||||||
ejtag_ctrl = ejtag_info->ejtag_ctrl;
|
ejtag_ctrl = ejtag_info->ejtag_ctrl;
|
||||||
mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
|
mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
|
||||||
if (ejtag_ctrl & EJTAG_CTRL_DERR)
|
if (ejtag_ctrl & EJTAG_CTRL_DERR) {
|
||||||
{
|
|
||||||
if (retries--) {
|
if (retries--) {
|
||||||
LOG_ERROR("DMA Write Addr = %08" PRIx32 " Data = ERROR ON WRITE (retrying)", addr);
|
LOG_ERROR("DMA Write Addr = %08" PRIx32 " Data = ERROR ON WRITE (retrying)", addr);
|
||||||
goto begin_ejtag_dma_write_h;
|
goto begin_ejtag_dma_write_h;
|
||||||
}
|
} else
|
||||||
else
|
|
||||||
LOG_ERROR("DMA Write Addr = %08" PRIx32 " Data = ERROR ON WRITE", addr);
|
LOG_ERROR("DMA Write Addr = %08" PRIx32 " Data = ERROR ON WRITE", addr);
|
||||||
return ERROR_JTAG_DEVICE_ERROR;
|
return ERROR_JTAG_DEVICE_ERROR;
|
||||||
}
|
}
|
||||||
|
@ -348,13 +340,11 @@ begin_ejtag_dma_write_b:
|
||||||
mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL);
|
mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL);
|
||||||
ejtag_ctrl = ejtag_info->ejtag_ctrl;
|
ejtag_ctrl = ejtag_info->ejtag_ctrl;
|
||||||
mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
|
mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
|
||||||
if (ejtag_ctrl & EJTAG_CTRL_DERR)
|
if (ejtag_ctrl & EJTAG_CTRL_DERR) {
|
||||||
{
|
|
||||||
if (retries--) {
|
if (retries--) {
|
||||||
LOG_ERROR("DMA Write Addr = %08" PRIx32 " Data = ERROR ON WRITE (retrying)", addr);
|
LOG_ERROR("DMA Write Addr = %08" PRIx32 " Data = ERROR ON WRITE (retrying)", addr);
|
||||||
goto begin_ejtag_dma_write_b;
|
goto begin_ejtag_dma_write_b;
|
||||||
}
|
} else
|
||||||
else
|
|
||||||
LOG_ERROR("DMA Write Addr = %08" PRIx32 " Data = ERROR ON WRITE", addr);
|
LOG_ERROR("DMA Write Addr = %08" PRIx32 " Data = ERROR ON WRITE", addr);
|
||||||
return ERROR_JTAG_DEVICE_ERROR;
|
return ERROR_JTAG_DEVICE_ERROR;
|
||||||
}
|
}
|
||||||
|
@ -364,14 +354,13 @@ begin_ejtag_dma_write_b:
|
||||||
|
|
||||||
int mips32_dmaacc_read_mem(struct mips_ejtag *ejtag_info, uint32_t addr, int size, int count, void *buf)
|
int mips32_dmaacc_read_mem(struct mips_ejtag *ejtag_info, uint32_t addr, int size, int count, void *buf)
|
||||||
{
|
{
|
||||||
switch (size)
|
switch (size) {
|
||||||
{
|
|
||||||
case 1:
|
case 1:
|
||||||
return mips32_dmaacc_read_mem8(ejtag_info, addr, count, (uint8_t*)buf);
|
return mips32_dmaacc_read_mem8(ejtag_info, addr, count, (uint8_t *)buf);
|
||||||
case 2:
|
case 2:
|
||||||
return mips32_dmaacc_read_mem16(ejtag_info, addr, count, (uint16_t*)buf);
|
return mips32_dmaacc_read_mem16(ejtag_info, addr, count, (uint16_t *)buf);
|
||||||
case 4:
|
case 4:
|
||||||
return mips32_dmaacc_read_mem32(ejtag_info, addr, count, (uint32_t*)buf);
|
return mips32_dmaacc_read_mem32(ejtag_info, addr, count, (uint32_t *)buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
|
@ -383,7 +372,8 @@ static int mips32_dmaacc_read_mem32(struct mips_ejtag *ejtag_info, uint32_t addr
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
for (i = 0; i < count; i++) {
|
for (i = 0; i < count; i++) {
|
||||||
if ((retval = ejtag_dma_read(ejtag_info, addr + i*sizeof(*buf), &buf[i])) != ERROR_OK)
|
retval = ejtag_dma_read(ejtag_info, addr + i * sizeof(*buf), &buf[i]);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -396,7 +386,8 @@ static int mips32_dmaacc_read_mem16(struct mips_ejtag *ejtag_info, uint32_t addr
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
for (i = 0; i < count; i++) {
|
for (i = 0; i < count; i++) {
|
||||||
if ((retval = ejtag_dma_read_h(ejtag_info, addr + i*sizeof(*buf), &buf[i])) != ERROR_OK)
|
retval = ejtag_dma_read_h(ejtag_info, addr + i * sizeof(*buf), &buf[i]);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -409,7 +400,8 @@ static int mips32_dmaacc_read_mem8(struct mips_ejtag *ejtag_info, uint32_t addr,
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
for (i = 0; i < count; i++) {
|
for (i = 0; i < count; i++) {
|
||||||
if ((retval = ejtag_dma_read_b(ejtag_info, addr + i*sizeof(*buf), &buf[i])) != ERROR_OK)
|
retval = ejtag_dma_read_b(ejtag_info, addr + i * sizeof(*buf), &buf[i]);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -418,14 +410,13 @@ static int mips32_dmaacc_read_mem8(struct mips_ejtag *ejtag_info, uint32_t addr,
|
||||||
|
|
||||||
int mips32_dmaacc_write_mem(struct mips_ejtag *ejtag_info, uint32_t addr, int size, int count, void *buf)
|
int mips32_dmaacc_write_mem(struct mips_ejtag *ejtag_info, uint32_t addr, int size, int count, void *buf)
|
||||||
{
|
{
|
||||||
switch (size)
|
switch (size) {
|
||||||
{
|
|
||||||
case 1:
|
case 1:
|
||||||
return mips32_dmaacc_write_mem8(ejtag_info, addr, count, (uint8_t*)buf);
|
return mips32_dmaacc_write_mem8(ejtag_info, addr, count, (uint8_t *)buf);
|
||||||
case 2:
|
case 2:
|
||||||
return mips32_dmaacc_write_mem16(ejtag_info, addr, count,(uint16_t*)buf);
|
return mips32_dmaacc_write_mem16(ejtag_info, addr, count, (uint16_t *)buf);
|
||||||
case 4:
|
case 4:
|
||||||
return mips32_dmaacc_write_mem32(ejtag_info, addr, count, (uint32_t*)buf);
|
return mips32_dmaacc_write_mem32(ejtag_info, addr, count, (uint32_t *)buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
|
@ -437,7 +428,8 @@ static int mips32_dmaacc_write_mem32(struct mips_ejtag *ejtag_info, uint32_t add
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
for (i = 0; i < count; i++) {
|
for (i = 0; i < count; i++) {
|
||||||
if ((retval = ejtag_dma_write(ejtag_info, addr + i*sizeof(*buf), buf[i])) != ERROR_OK)
|
retval = ejtag_dma_write(ejtag_info, addr + i * sizeof(*buf), buf[i]);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -450,7 +442,8 @@ static int mips32_dmaacc_write_mem16(struct mips_ejtag *ejtag_info, uint32_t add
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
for (i = 0; i < count; i++) {
|
for (i = 0; i < count; i++) {
|
||||||
if ((retval = ejtag_dma_write_h(ejtag_info, addr + i*sizeof(*buf), buf[i])) != ERROR_OK)
|
retval = ejtag_dma_write_h(ejtag_info, addr + i * sizeof(*buf), buf[i]);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -463,7 +456,8 @@ static int mips32_dmaacc_write_mem8(struct mips_ejtag *ejtag_info, uint32_t addr
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
for (i = 0; i < count; i++) {
|
for (i = 0; i < count; i++) {
|
||||||
if ((retval = ejtag_dma_write_b(ejtag_info, addr + i*sizeof(*buf), buf[i])) != ERROR_OK)
|
retval = ejtag_dma_write_b(ejtag_info, addr + i * sizeof(*buf), buf[i]);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
* Free Software Foundation, Inc., *
|
* Free Software Foundation, Inc., *
|
||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#ifndef MIPS32_DMAACC_H
|
#ifndef MIPS32_DMAACC_H
|
||||||
#define MIPS32_DMAACC_H
|
#define MIPS32_DMAACC_H
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -22,6 +22,7 @@
|
||||||
* Free Software Foundation, Inc., *
|
* Free Software Foundation, Inc., *
|
||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#ifndef MIPS32_PRACC_H
|
#ifndef MIPS32_PRACC_H
|
||||||
#define MIPS32_PRACC_H
|
#define MIPS32_PRACC_H
|
||||||
|
|
||||||
|
@ -71,7 +72,7 @@ int mips32_pracc_exec(struct mips_ejtag *ejtag_info, int code_len, const uint32_
|
||||||
* @return ERROR_OK on Sucess, ERROR_FAIL otherwise
|
* @return ERROR_OK on Sucess, ERROR_FAIL otherwise
|
||||||
*/
|
*/
|
||||||
int mips32_cp0_read(struct mips_ejtag *ejtag_info,
|
int mips32_cp0_read(struct mips_ejtag *ejtag_info,
|
||||||
uint32_t *val, uint32_t cp0_reg, uint32_t cp0_sel);
|
uint32_t *val, uint32_t cp0_reg, uint32_t cp0_sel);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \b mips32_cp0_write
|
* \b mips32_cp0_write
|
||||||
|
@ -87,6 +88,6 @@ int mips32_cp0_read(struct mips_ejtag *ejtag_info,
|
||||||
* @return ERROR_OK on Sucess, ERROR_FAIL otherwise
|
* @return ERROR_OK on Sucess, ERROR_FAIL otherwise
|
||||||
*/
|
*/
|
||||||
int mips32_cp0_write(struct mips_ejtag *ejtag_info,
|
int mips32_cp0_write(struct mips_ejtag *ejtag_info,
|
||||||
uint32_t val, uint32_t cp0_reg, uint32_t cp0_sel);
|
uint32_t val, uint32_t cp0_reg, uint32_t cp0_sel);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
* Free Software Foundation, Inc., *
|
* Free Software Foundation, Inc., *
|
||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -35,8 +36,7 @@ void mips_ejtag_set_instr(struct mips_ejtag *ejtag_info, int new_instr)
|
||||||
tap = ejtag_info->tap;
|
tap = ejtag_info->tap;
|
||||||
assert(tap != NULL);
|
assert(tap != NULL);
|
||||||
|
|
||||||
if (buf_get_u32(tap->cur_instr, 0, tap->ir_length) != (uint32_t)new_instr)
|
if (buf_get_u32(tap->cur_instr, 0, tap->ir_length) != (uint32_t)new_instr) {
|
||||||
{
|
|
||||||
struct scan_field field;
|
struct scan_field field;
|
||||||
uint8_t t[4];
|
uint8_t t[4];
|
||||||
|
|
||||||
|
@ -63,8 +63,8 @@ int mips_ejtag_get_idcode(struct mips_ejtag *ejtag_info, uint32_t *idcode)
|
||||||
jtag_add_dr_scan(ejtag_info->tap, 1, &field, TAP_IDLE);
|
jtag_add_dr_scan(ejtag_info->tap, 1, &field, TAP_IDLE);
|
||||||
|
|
||||||
int retval;
|
int retval;
|
||||||
if ((retval = jtag_execute_queue()) != ERROR_OK)
|
retval = jtag_execute_queue();
|
||||||
{
|
if (retval != ERROR_OK) {
|
||||||
LOG_ERROR("register read failed");
|
LOG_ERROR("register read failed");
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
@ -88,8 +88,8 @@ static int mips_ejtag_get_impcode(struct mips_ejtag *ejtag_info, uint32_t *impco
|
||||||
jtag_add_dr_scan(ejtag_info->tap, 1, &field, TAP_IDLE);
|
jtag_add_dr_scan(ejtag_info->tap, 1, &field, TAP_IDLE);
|
||||||
|
|
||||||
int retval;
|
int retval;
|
||||||
if ((retval = jtag_execute_queue()) != ERROR_OK)
|
retval = jtag_execute_queue();
|
||||||
{
|
if (retval != ERROR_OK) {
|
||||||
LOG_ERROR("register read failed");
|
LOG_ERROR("register read failed");
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
@ -116,8 +116,8 @@ int mips_ejtag_drscan_32(struct mips_ejtag *ejtag_info, uint32_t *data)
|
||||||
|
|
||||||
jtag_add_dr_scan(tap, 1, &field, TAP_IDLE);
|
jtag_add_dr_scan(tap, 1, &field, TAP_IDLE);
|
||||||
|
|
||||||
if ((retval = jtag_execute_queue()) != ERROR_OK)
|
retval = jtag_execute_queue();
|
||||||
{
|
if (retval != ERROR_OK) {
|
||||||
LOG_ERROR("register read failed");
|
LOG_ERROR("register read failed");
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
@ -164,8 +164,8 @@ int mips_ejtag_drscan_8(struct mips_ejtag *ejtag_info, uint32_t *data)
|
||||||
|
|
||||||
jtag_add_dr_scan(tap, 1, &field, TAP_IDLE);
|
jtag_add_dr_scan(tap, 1, &field, TAP_IDLE);
|
||||||
|
|
||||||
if ((retval = jtag_execute_queue()) != ERROR_OK)
|
retval = jtag_execute_queue();
|
||||||
{
|
if (retval != ERROR_OK) {
|
||||||
LOG_ERROR("register read failed");
|
LOG_ERROR("register read failed");
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
@ -193,12 +193,12 @@ void mips_ejtag_drscan_8_out(struct mips_ejtag *ejtag_info, uint8_t data)
|
||||||
static int mips_ejtag_step_enable(struct mips_ejtag *ejtag_info)
|
static int mips_ejtag_step_enable(struct mips_ejtag *ejtag_info)
|
||||||
{
|
{
|
||||||
static const uint32_t code[] = {
|
static const uint32_t code[] = {
|
||||||
MIPS32_MTC0(1,31,0), /* move $1 to COP0 DeSave */
|
MIPS32_MTC0(1, 31, 0), /* move $1 to COP0 DeSave */
|
||||||
MIPS32_MFC0(1,23,0), /* move COP0 Debug to $1 */
|
MIPS32_MFC0(1, 23, 0), /* move COP0 Debug to $1 */
|
||||||
MIPS32_ORI(1,1,0x0100), /* set SSt bit in debug reg */
|
MIPS32_ORI(1, 1, 0x0100), /* set SSt bit in debug reg */
|
||||||
MIPS32_MTC0(1,23,0), /* move $1 to COP0 Debug */
|
MIPS32_MTC0(1, 23, 0), /* move $1 to COP0 Debug */
|
||||||
MIPS32_B(NEG16(5)),
|
MIPS32_B(NEG16(5)),
|
||||||
MIPS32_MFC0(1,31,0), /* move COP0 DeSave to $1 */
|
MIPS32_MFC0(1, 31, 0), /* move COP0 DeSave to $1 */
|
||||||
};
|
};
|
||||||
|
|
||||||
return mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code,
|
return mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code,
|
||||||
|
@ -208,20 +208,20 @@ static int mips_ejtag_step_enable(struct mips_ejtag *ejtag_info)
|
||||||
static int mips_ejtag_step_disable(struct mips_ejtag *ejtag_info)
|
static int mips_ejtag_step_disable(struct mips_ejtag *ejtag_info)
|
||||||
{
|
{
|
||||||
static const uint32_t code[] = {
|
static const uint32_t code[] = {
|
||||||
MIPS32_MTC0(15,31,0), /* move $15 to COP0 DeSave */
|
MIPS32_MTC0(15, 31, 0), /* move $15 to COP0 DeSave */
|
||||||
MIPS32_LUI(15,UPPER16(MIPS32_PRACC_STACK)), /* $15 = MIPS32_PRACC_STACK */
|
MIPS32_LUI(15, UPPER16(MIPS32_PRACC_STACK)), /* $15 = MIPS32_PRACC_STACK */
|
||||||
MIPS32_ORI(15,15,LOWER16(MIPS32_PRACC_STACK)),
|
MIPS32_ORI(15, 15, LOWER16(MIPS32_PRACC_STACK)),
|
||||||
MIPS32_SW(1,0,15), /* sw $1,($15) */
|
MIPS32_SW(1, 0, 15), /* sw $1,($15) */
|
||||||
MIPS32_SW(2,0,15), /* sw $2,($15) */
|
MIPS32_SW(2, 0, 15), /* sw $2,($15) */
|
||||||
MIPS32_MFC0(1,23,0), /* move COP0 Debug to $1 */
|
MIPS32_MFC0(1, 23, 0), /* move COP0 Debug to $1 */
|
||||||
MIPS32_LUI(2,0xFFFF), /* $2 = 0xfffffeff */
|
MIPS32_LUI(2, 0xFFFF), /* $2 = 0xfffffeff */
|
||||||
MIPS32_ORI(2,2,0xFEFF),
|
MIPS32_ORI(2, 2, 0xFEFF),
|
||||||
MIPS32_AND(1,1,2),
|
MIPS32_AND(1, 1, 2),
|
||||||
MIPS32_MTC0(1,23,0), /* move $1 to COP0 Debug */
|
MIPS32_MTC0(1, 23, 0), /* move $1 to COP0 Debug */
|
||||||
MIPS32_LW(2,0,15),
|
MIPS32_LW(2, 0, 15),
|
||||||
MIPS32_LW(1,0,15),
|
MIPS32_LW(1, 0, 15),
|
||||||
MIPS32_B(NEG16(13)),
|
MIPS32_B(NEG16(13)),
|
||||||
MIPS32_MFC0(15,31,0), /* move COP0 DeSave to $15 */
|
MIPS32_MFC0(15, 31, 0), /* move COP0 DeSave to $15 */
|
||||||
};
|
};
|
||||||
|
|
||||||
return mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code,
|
return mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code,
|
||||||
|
@ -248,8 +248,7 @@ int mips_ejtag_enter_debug(struct mips_ejtag *ejtag_info)
|
||||||
ejtag_ctrl = ejtag_info->ejtag_ctrl;
|
ejtag_ctrl = ejtag_info->ejtag_ctrl;
|
||||||
mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
|
mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
|
||||||
LOG_DEBUG("ejtag_ctrl: 0x%8.8" PRIx32 "", ejtag_ctrl);
|
LOG_DEBUG("ejtag_ctrl: 0x%8.8" PRIx32 "", ejtag_ctrl);
|
||||||
if ((ejtag_ctrl & EJTAG_CTRL_BRKST) == 0)
|
if ((ejtag_ctrl & EJTAG_CTRL_BRKST) == 0) {
|
||||||
{
|
|
||||||
LOG_ERROR("Failed to enter Debug Mode!");
|
LOG_ERROR("Failed to enter Debug Mode!");
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
@ -270,19 +269,19 @@ int mips_ejtag_read_debug(struct mips_ejtag *ejtag_info, uint32_t* debug_reg)
|
||||||
{
|
{
|
||||||
/* read ejtag ECR */
|
/* read ejtag ECR */
|
||||||
static const uint32_t code[] = {
|
static const uint32_t code[] = {
|
||||||
MIPS32_MTC0(15,31,0), /* move $15 to COP0 DeSave */
|
MIPS32_MTC0(15, 31, 0), /* move $15 to COP0 DeSave */
|
||||||
MIPS32_LUI(15,UPPER16(MIPS32_PRACC_STACK)), /* $15 = MIPS32_PRACC_STACK */
|
MIPS32_LUI(15, UPPER16(MIPS32_PRACC_STACK)), /* $15 = MIPS32_PRACC_STACK */
|
||||||
MIPS32_ORI(15,15,LOWER16(MIPS32_PRACC_STACK)),
|
MIPS32_ORI(15, 15, LOWER16(MIPS32_PRACC_STACK)),
|
||||||
MIPS32_SW(1,0,15), /* sw $1,($15) */
|
MIPS32_SW(1, 0, 15), /* sw $1,($15) */
|
||||||
MIPS32_SW(2,0,15), /* sw $2,($15) */
|
MIPS32_SW(2, 0, 15), /* sw $2,($15) */
|
||||||
MIPS32_LUI(1,UPPER16(MIPS32_PRACC_PARAM_OUT)), /* $1 = MIPS32_PRACC_PARAM_OUT */
|
MIPS32_LUI(1, UPPER16(MIPS32_PRACC_PARAM_OUT)), /* $1 = MIPS32_PRACC_PARAM_OUT */
|
||||||
MIPS32_ORI(1,1,LOWER16(MIPS32_PRACC_PARAM_OUT)),
|
MIPS32_ORI(1, 1, LOWER16(MIPS32_PRACC_PARAM_OUT)),
|
||||||
MIPS32_MFC0(2,23,0), /* move COP0 Debug to $2 */
|
MIPS32_MFC0(2, 23, 0), /* move COP0 Debug to $2 */
|
||||||
MIPS32_SW(2,0,1),
|
MIPS32_SW(2, 0, 1),
|
||||||
MIPS32_LW(2,0,15),
|
MIPS32_LW(2, 0, 15),
|
||||||
MIPS32_LW(1,0,15),
|
MIPS32_LW(1, 0, 15),
|
||||||
MIPS32_B(NEG16(12)),
|
MIPS32_B(NEG16(12)),
|
||||||
MIPS32_MFC0(15,31,0), /* move COP0 DeSave to $15 */
|
MIPS32_MFC0(15, 31, 0), /* move COP0 DeSave to $15 */
|
||||||
};
|
};
|
||||||
|
|
||||||
return mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code,
|
return mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code,
|
||||||
|
@ -302,8 +301,7 @@ int mips_ejtag_init(struct mips_ejtag *ejtag_info)
|
||||||
/* get ejtag version */
|
/* get ejtag version */
|
||||||
ejtag_version = ((ejtag_info->impcode >> 29) & 0x07);
|
ejtag_version = ((ejtag_info->impcode >> 29) & 0x07);
|
||||||
|
|
||||||
switch (ejtag_version)
|
switch (ejtag_version) {
|
||||||
{
|
|
||||||
case 0:
|
case 0:
|
||||||
LOG_DEBUG("EJTAG: Version 1 or 2.0 Detected");
|
LOG_DEBUG("EJTAG: Version 1 or 2.0 Detected");
|
||||||
break;
|
break;
|
||||||
|
@ -359,19 +357,15 @@ int mips_ejtag_fastdata_scan(struct mips_ejtag *ejtag_info, int write_t, uint32_
|
||||||
fields[1].num_bits = 32;
|
fields[1].num_bits = 32;
|
||||||
fields[1].out_value = t;
|
fields[1].out_value = t;
|
||||||
|
|
||||||
if (write_t)
|
if (write_t) {
|
||||||
{
|
|
||||||
fields[1].in_value = NULL;
|
fields[1].in_value = NULL;
|
||||||
buf_set_u32(t, 0, 32, *data);
|
buf_set_u32(t, 0, 32, *data);
|
||||||
}
|
} else
|
||||||
else
|
|
||||||
{
|
|
||||||
fields[1].in_value = (void *) data;
|
fields[1].in_value = (void *) data;
|
||||||
}
|
|
||||||
|
|
||||||
jtag_add_dr_scan(tap, 2, fields, TAP_IDLE);
|
jtag_add_dr_scan(tap, 2, fields, TAP_IDLE);
|
||||||
|
|
||||||
if ( (!write_t) && (data) )
|
if (!write_t && data)
|
||||||
jtag_add_callback(mips_le_to_h_u32,
|
jtag_add_callback(mips_le_to_h_u32,
|
||||||
(jtag_callback_data_t) data);
|
(jtag_callback_data_t) data);
|
||||||
|
|
||||||
|
|
|
@ -122,8 +122,7 @@
|
||||||
#define EJTAG_DBCn_BLM_SHIFT 4
|
#define EJTAG_DBCn_BLM_SHIFT 4
|
||||||
#define EJTAG_DBCn_BE (1 << 0)
|
#define EJTAG_DBCn_BE (1 << 0)
|
||||||
|
|
||||||
struct mips_ejtag
|
struct mips_ejtag {
|
||||||
{
|
|
||||||
struct jtag_tap *tap;
|
struct jtag_tap *tap;
|
||||||
uint32_t impcode;
|
uint32_t impcode;
|
||||||
uint32_t idcode;
|
uint32_t idcode;
|
||||||
|
@ -146,7 +145,7 @@ int mips_ejtag_init(struct mips_ejtag *ejtag_info);
|
||||||
int mips_ejtag_config_step(struct mips_ejtag *ejtag_info, int enable_step);
|
int mips_ejtag_config_step(struct mips_ejtag *ejtag_info, int enable_step);
|
||||||
int mips_ejtag_read_debug(struct mips_ejtag *ejtag_info, uint32_t* debug_reg);
|
int mips_ejtag_read_debug(struct mips_ejtag *ejtag_info, uint32_t* debug_reg);
|
||||||
|
|
||||||
static __inline__ void mips_le_to_h_u32(jtag_callback_data_t arg)
|
static inline void mips_le_to_h_u32(jtag_callback_data_t arg)
|
||||||
{
|
{
|
||||||
uint8_t *in = (uint8_t *)arg;
|
uint8_t *in = (uint8_t *)arg;
|
||||||
*((uint32_t *)arg) = le_to_h_u32(in);
|
*((uint32_t *)arg) = le_to_h_u32(in);
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
* Free Software Foundation, Inc., *
|
* Free Software Foundation, Inc., *
|
||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -48,26 +49,27 @@ static int mips_m4k_examine_debug_reason(struct target *target)
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
if ((target->debug_reason != DBG_REASON_DBGRQ)
|
if ((target->debug_reason != DBG_REASON_DBGRQ)
|
||||||
&& (target->debug_reason != DBG_REASON_SINGLESTEP))
|
&& (target->debug_reason != DBG_REASON_SINGLESTEP)) {
|
||||||
{
|
|
||||||
/* get info about inst breakpoint support */
|
/* get info about inst breakpoint support */
|
||||||
if ((retval = target_read_u32(target, EJTAG_IBS, &break_status)) != ERROR_OK)
|
retval = target_read_u32(target, EJTAG_IBS, &break_status);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
if (break_status & 0x1f)
|
if (break_status & 0x1f) {
|
||||||
{
|
|
||||||
/* we have halted on a breakpoint */
|
/* we have halted on a breakpoint */
|
||||||
if ((retval = target_write_u32(target, EJTAG_IBS, 0)) != ERROR_OK)
|
retval = target_write_u32(target, EJTAG_IBS, 0);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
target->debug_reason = DBG_REASON_BREAKPOINT;
|
target->debug_reason = DBG_REASON_BREAKPOINT;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* get info about data breakpoint support */
|
/* get info about data breakpoint support */
|
||||||
if ((retval = target_read_u32(target, EJTAG_DBS, &break_status)) != ERROR_OK)
|
retval = target_read_u32(target, EJTAG_DBS, &break_status);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
if (break_status & 0x1f)
|
if (break_status & 0x1f) {
|
||||||
{
|
|
||||||
/* we have halted on a breakpoint */
|
/* we have halted on a breakpoint */
|
||||||
if ((retval = target_write_u32(target, EJTAG_DBS, 0)) != ERROR_OK)
|
retval = target_write_u32(target, EJTAG_DBS, 0);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
target->debug_reason = DBG_REASON_WATCHPOINT;
|
target->debug_reason = DBG_REASON_WATCHPOINT;
|
||||||
}
|
}
|
||||||
|
@ -92,8 +94,7 @@ static int mips_m4k_debug_entry(struct target *target)
|
||||||
mips_m4k_examine_debug_reason(target);
|
mips_m4k_examine_debug_reason(target);
|
||||||
|
|
||||||
/* clear single step if active */
|
/* clear single step if active */
|
||||||
if (debug_reg & EJTAG_DEBUG_DSS)
|
if (debug_reg & EJTAG_DEBUG_DSS) {
|
||||||
{
|
|
||||||
/* stopped due to single step - clear step bit */
|
/* stopped due to single step - clear step bit */
|
||||||
mips_ejtag_config_step(ejtag_info, 0);
|
mips_ejtag_config_step(ejtag_info, 0);
|
||||||
}
|
}
|
||||||
|
@ -103,9 +104,8 @@ static int mips_m4k_debug_entry(struct target *target)
|
||||||
/* default to mips32 isa, it will be changed below if required */
|
/* default to mips32 isa, it will be changed below if required */
|
||||||
mips32->isa_mode = MIPS32_ISA_MIPS32;
|
mips32->isa_mode = MIPS32_ISA_MIPS32;
|
||||||
|
|
||||||
if (ejtag_info->impcode & EJTAG_IMP_MIPS16) {
|
if (ejtag_info->impcode & EJTAG_IMP_MIPS16)
|
||||||
mips32->isa_mode = buf_get_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 1);
|
mips32->isa_mode = buf_get_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 1);
|
||||||
}
|
|
||||||
|
|
||||||
LOG_DEBUG("entered debug state at PC 0x%" PRIx32 ", target->state: %s",
|
LOG_DEBUG("entered debug state at PC 0x%" PRIx32 ", target->state: %s",
|
||||||
buf_get_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 32),
|
buf_get_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 32),
|
||||||
|
@ -129,8 +129,7 @@ static int mips_m4k_poll(struct target *target)
|
||||||
|
|
||||||
/* clear this bit before handling polling
|
/* clear this bit before handling polling
|
||||||
* as after reset registers will read zero */
|
* as after reset registers will read zero */
|
||||||
if (ejtag_ctrl & EJTAG_CTRL_ROCC)
|
if (ejtag_ctrl & EJTAG_CTRL_ROCC) {
|
||||||
{
|
|
||||||
/* we have detected a reset, clear flag
|
/* we have detected a reset, clear flag
|
||||||
* otherwise ejtag will not work */
|
* otherwise ejtag will not work */
|
||||||
ejtag_ctrl = ejtag_info->ejtag_ctrl & ~EJTAG_CTRL_ROCC;
|
ejtag_ctrl = ejtag_info->ejtag_ctrl & ~EJTAG_CTRL_ROCC;
|
||||||
|
@ -143,35 +142,30 @@ static int mips_m4k_poll(struct target *target)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* check for processor halted */
|
/* check for processor halted */
|
||||||
if (ejtag_ctrl & EJTAG_CTRL_BRKST)
|
if (ejtag_ctrl & EJTAG_CTRL_BRKST) {
|
||||||
{
|
if ((target->state == TARGET_RUNNING) || (target->state == TARGET_RESET)) {
|
||||||
if ((target->state == TARGET_RUNNING) || (target->state == TARGET_RESET))
|
|
||||||
{
|
|
||||||
mips_ejtag_set_instr(ejtag_info, EJTAG_INST_NORMALBOOT);
|
mips_ejtag_set_instr(ejtag_info, EJTAG_INST_NORMALBOOT);
|
||||||
|
|
||||||
target->state = TARGET_HALTED;
|
target->state = TARGET_HALTED;
|
||||||
|
|
||||||
if ((retval = mips_m4k_debug_entry(target)) != ERROR_OK)
|
retval = mips_m4k_debug_entry(target);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
target_call_event_callbacks(target, TARGET_EVENT_HALTED);
|
target_call_event_callbacks(target, TARGET_EVENT_HALTED);
|
||||||
}
|
} else if (target->state == TARGET_DEBUG_RUNNING) {
|
||||||
else if (target->state == TARGET_DEBUG_RUNNING)
|
|
||||||
{
|
|
||||||
target->state = TARGET_HALTED;
|
target->state = TARGET_HALTED;
|
||||||
|
|
||||||
if ((retval = mips_m4k_debug_entry(target)) != ERROR_OK)
|
retval = mips_m4k_debug_entry(target);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
target_call_event_callbacks(target, TARGET_EVENT_DEBUG_HALTED);
|
target_call_event_callbacks(target, TARGET_EVENT_DEBUG_HALTED);
|
||||||
}
|
}
|
||||||
}
|
} else
|
||||||
else
|
|
||||||
{
|
|
||||||
target->state = TARGET_RUNNING;
|
target->state = TARGET_RUNNING;
|
||||||
}
|
|
||||||
|
|
||||||
// LOG_DEBUG("ctrl = 0x%08X", ejtag_ctrl);
|
/* LOG_DEBUG("ctrl = 0x%08X", ejtag_ctrl); */
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
@ -181,29 +175,21 @@ static int mips_m4k_halt(struct target *target)
|
||||||
struct mips32_common *mips32 = target_to_mips32(target);
|
struct mips32_common *mips32 = target_to_mips32(target);
|
||||||
struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
|
struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
|
||||||
|
|
||||||
LOG_DEBUG("target->state: %s",
|
LOG_DEBUG("target->state: %s", target_state_name(target));
|
||||||
target_state_name(target));
|
|
||||||
|
|
||||||
if (target->state == TARGET_HALTED)
|
if (target->state == TARGET_HALTED) {
|
||||||
{
|
|
||||||
LOG_DEBUG("target was already halted");
|
LOG_DEBUG("target was already halted");
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (target->state == TARGET_UNKNOWN)
|
if (target->state == TARGET_UNKNOWN)
|
||||||
{
|
|
||||||
LOG_WARNING("target was in unknown state when halt was requested");
|
LOG_WARNING("target was in unknown state when halt was requested");
|
||||||
}
|
|
||||||
|
|
||||||
if (target->state == TARGET_RESET)
|
if (target->state == TARGET_RESET) {
|
||||||
{
|
if ((jtag_get_reset_config() & RESET_SRST_PULLS_TRST) && jtag_get_srst()) {
|
||||||
if ((jtag_get_reset_config() & RESET_SRST_PULLS_TRST) && jtag_get_srst())
|
|
||||||
{
|
|
||||||
LOG_ERROR("can't request a halt while in reset if nSRST pulls nTRST");
|
LOG_ERROR("can't request a halt while in reset if nSRST pulls nTRST");
|
||||||
return ERROR_TARGET_FAILURE;
|
return ERROR_TARGET_FAILURE;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
/* we came here in a reset_halt or reset_init sequence
|
/* we came here in a reset_halt or reset_init sequence
|
||||||
* debug entry was already prepared in mips32_prepare_reset_halt()
|
* debug entry was already prepared in mips32_prepare_reset_halt()
|
||||||
*/
|
*/
|
||||||
|
@ -235,32 +221,20 @@ static int mips_m4k_assert_reset(struct target *target)
|
||||||
if (!(jtag_reset_config & RESET_HAS_SRST))
|
if (!(jtag_reset_config & RESET_HAS_SRST))
|
||||||
assert_srst = 0;
|
assert_srst = 0;
|
||||||
|
|
||||||
if (target->reset_halt)
|
if (target->reset_halt) {
|
||||||
{
|
|
||||||
/* use hardware to catch reset */
|
/* use hardware to catch reset */
|
||||||
mips_ejtag_set_instr(ejtag_info, EJTAG_INST_EJTAGBOOT);
|
mips_ejtag_set_instr(ejtag_info, EJTAG_INST_EJTAGBOOT);
|
||||||
}
|
} else
|
||||||
else
|
|
||||||
{
|
|
||||||
mips_ejtag_set_instr(ejtag_info, EJTAG_INST_NORMALBOOT);
|
mips_ejtag_set_instr(ejtag_info, EJTAG_INST_NORMALBOOT);
|
||||||
}
|
|
||||||
|
|
||||||
if (assert_srst)
|
if (assert_srst) {
|
||||||
{
|
|
||||||
/* here we should issue a srst only, but we may have to assert trst as well */
|
/* here we should issue a srst only, but we may have to assert trst as well */
|
||||||
if (jtag_reset_config & RESET_SRST_PULLS_TRST)
|
if (jtag_reset_config & RESET_SRST_PULLS_TRST)
|
||||||
{
|
|
||||||
jtag_add_reset(1, 1);
|
jtag_add_reset(1, 1);
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
jtag_add_reset(0, 1);
|
jtag_add_reset(0, 1);
|
||||||
}
|
} else {
|
||||||
}
|
if (mips_m4k->is_pic32mx) {
|
||||||
else
|
|
||||||
{
|
|
||||||
if (mips_m4k->is_pic32mx)
|
|
||||||
{
|
|
||||||
LOG_DEBUG("Using MTAP reset to reset processor...");
|
LOG_DEBUG("Using MTAP reset to reset processor...");
|
||||||
|
|
||||||
/* use microchip specific MTAP reset */
|
/* use microchip specific MTAP reset */
|
||||||
|
@ -270,9 +244,7 @@ static int mips_m4k_assert_reset(struct target *target)
|
||||||
mips_ejtag_drscan_8_out(ejtag_info, MCHP_ASERT_RST);
|
mips_ejtag_drscan_8_out(ejtag_info, MCHP_ASERT_RST);
|
||||||
mips_ejtag_drscan_8_out(ejtag_info, MCHP_DE_ASSERT_RST);
|
mips_ejtag_drscan_8_out(ejtag_info, MCHP_DE_ASSERT_RST);
|
||||||
mips_ejtag_set_instr(ejtag_info, MTAP_SW_ETAP);
|
mips_ejtag_set_instr(ejtag_info, MTAP_SW_ETAP);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
/* use ejtag reset - not supported by all cores */
|
/* use ejtag reset - not supported by all cores */
|
||||||
uint32_t ejtag_ctrl = ejtag_info->ejtag_ctrl | EJTAG_CTRL_PRRST | EJTAG_CTRL_PERRST;
|
uint32_t ejtag_ctrl = ejtag_info->ejtag_ctrl | EJTAG_CTRL_PRRST | EJTAG_CTRL_PERRST;
|
||||||
LOG_DEBUG("Using EJTAG reset (PRRST) to reset processor...");
|
LOG_DEBUG("Using EJTAG reset (PRRST) to reset processor...");
|
||||||
|
@ -286,10 +258,9 @@ static int mips_m4k_assert_reset(struct target *target)
|
||||||
|
|
||||||
register_cache_invalidate(mips_m4k->mips32.core_cache);
|
register_cache_invalidate(mips_m4k->mips32.core_cache);
|
||||||
|
|
||||||
if (target->reset_halt)
|
if (target->reset_halt) {
|
||||||
{
|
int retval = target_halt(target);
|
||||||
int retval;
|
if (retval != ERROR_OK)
|
||||||
if ((retval = target_halt(target)) != ERROR_OK)
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -298,8 +269,7 @@ static int mips_m4k_assert_reset(struct target *target)
|
||||||
|
|
||||||
static int mips_m4k_deassert_reset(struct target *target)
|
static int mips_m4k_deassert_reset(struct target *target)
|
||||||
{
|
{
|
||||||
LOG_DEBUG("target->state: %s",
|
LOG_DEBUG("target->state: %s", target_state_name(target));
|
||||||
target_state_name(target));
|
|
||||||
|
|
||||||
/* deassert reset lines */
|
/* deassert reset lines */
|
||||||
jtag_add_reset(0, 0);
|
jtag_add_reset(0, 0);
|
||||||
|
@ -340,41 +310,36 @@ static int mips_m4k_resume(struct target *target, int current,
|
||||||
struct breakpoint *breakpoint = NULL;
|
struct breakpoint *breakpoint = NULL;
|
||||||
uint32_t resume_pc;
|
uint32_t resume_pc;
|
||||||
|
|
||||||
if (target->state != TARGET_HALTED)
|
if (target->state != TARGET_HALTED) {
|
||||||
{
|
|
||||||
LOG_WARNING("target not halted");
|
LOG_WARNING("target not halted");
|
||||||
return ERROR_TARGET_NOT_HALTED;
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!debug_execution)
|
if (!debug_execution) {
|
||||||
{
|
|
||||||
target_free_all_working_areas(target);
|
target_free_all_working_areas(target);
|
||||||
mips_m4k_enable_breakpoints(target);
|
mips_m4k_enable_breakpoints(target);
|
||||||
mips_m4k_enable_watchpoints(target);
|
mips_m4k_enable_watchpoints(target);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* current = 1: continue on current pc, otherwise continue at <address> */
|
/* current = 1: continue on current pc, otherwise continue at <address> */
|
||||||
if (!current)
|
if (!current) {
|
||||||
{
|
|
||||||
buf_set_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 32, address);
|
buf_set_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 32, address);
|
||||||
mips32->core_cache->reg_list[MIPS32_PC].dirty = 1;
|
mips32->core_cache->reg_list[MIPS32_PC].dirty = 1;
|
||||||
mips32->core_cache->reg_list[MIPS32_PC].valid = 1;
|
mips32->core_cache->reg_list[MIPS32_PC].valid = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ejtag_info->impcode & EJTAG_IMP_MIPS16) {
|
if (ejtag_info->impcode & EJTAG_IMP_MIPS16)
|
||||||
buf_set_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 1, mips32->isa_mode);
|
buf_set_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 1, mips32->isa_mode);
|
||||||
}
|
|
||||||
|
|
||||||
resume_pc = buf_get_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 32);
|
resume_pc = buf_get_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 32);
|
||||||
|
|
||||||
mips32_restore_context(target);
|
mips32_restore_context(target);
|
||||||
|
|
||||||
/* the front-end may request us not to handle breakpoints */
|
/* the front-end may request us not to handle breakpoints */
|
||||||
if (handle_breakpoints)
|
if (handle_breakpoints) {
|
||||||
{
|
|
||||||
/* Single step past breakpoint at current address */
|
/* Single step past breakpoint at current address */
|
||||||
if ((breakpoint = breakpoint_find(target, resume_pc)))
|
breakpoint = breakpoint_find(target, resume_pc);
|
||||||
{
|
if (breakpoint) {
|
||||||
LOG_DEBUG("unset breakpoint at 0x%8.8" PRIx32 "", breakpoint->address);
|
LOG_DEBUG("unset breakpoint at 0x%8.8" PRIx32 "", breakpoint->address);
|
||||||
mips_m4k_unset_breakpoint(target, breakpoint);
|
mips_m4k_unset_breakpoint(target, breakpoint);
|
||||||
mips_m4k_single_step_core(target);
|
mips_m4k_single_step_core(target);
|
||||||
|
@ -392,14 +357,11 @@ static int mips_m4k_resume(struct target *target, int current,
|
||||||
/* registers are now invalid */
|
/* registers are now invalid */
|
||||||
register_cache_invalidate(mips32->core_cache);
|
register_cache_invalidate(mips32->core_cache);
|
||||||
|
|
||||||
if (!debug_execution)
|
if (!debug_execution) {
|
||||||
{
|
|
||||||
target->state = TARGET_RUNNING;
|
target->state = TARGET_RUNNING;
|
||||||
target_call_event_callbacks(target, TARGET_EVENT_RESUMED);
|
target_call_event_callbacks(target, TARGET_EVENT_RESUMED);
|
||||||
LOG_DEBUG("target resumed at 0x%" PRIx32 "", resume_pc);
|
LOG_DEBUG("target resumed at 0x%" PRIx32 "", resume_pc);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
target->state = TARGET_DEBUG_RUNNING;
|
target->state = TARGET_DEBUG_RUNNING;
|
||||||
target_call_event_callbacks(target, TARGET_EVENT_DEBUG_RESUMED);
|
target_call_event_callbacks(target, TARGET_EVENT_DEBUG_RESUMED);
|
||||||
LOG_DEBUG("target debug resumed at 0x%" PRIx32 "", resume_pc);
|
LOG_DEBUG("target debug resumed at 0x%" PRIx32 "", resume_pc);
|
||||||
|
@ -416,15 +378,13 @@ static int mips_m4k_step(struct target *target, int current,
|
||||||
struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
|
struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
|
||||||
struct breakpoint *breakpoint = NULL;
|
struct breakpoint *breakpoint = NULL;
|
||||||
|
|
||||||
if (target->state != TARGET_HALTED)
|
if (target->state != TARGET_HALTED) {
|
||||||
{
|
|
||||||
LOG_WARNING("target not halted");
|
LOG_WARNING("target not halted");
|
||||||
return ERROR_TARGET_NOT_HALTED;
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* current = 1: continue on current pc, otherwise continue at <address> */
|
/* current = 1: continue on current pc, otherwise continue at <address> */
|
||||||
if (!current)
|
if (!current) {
|
||||||
{
|
|
||||||
buf_set_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 32, address);
|
buf_set_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 32, address);
|
||||||
mips32->core_cache->reg_list[MIPS32_PC].dirty = 1;
|
mips32->core_cache->reg_list[MIPS32_PC].dirty = 1;
|
||||||
mips32->core_cache->reg_list[MIPS32_PC].valid = 1;
|
mips32->core_cache->reg_list[MIPS32_PC].valid = 1;
|
||||||
|
@ -473,8 +433,7 @@ static void mips_m4k_enable_breakpoints(struct target *target)
|
||||||
struct breakpoint *breakpoint = target->breakpoints;
|
struct breakpoint *breakpoint = target->breakpoints;
|
||||||
|
|
||||||
/* set any pending breakpoints */
|
/* set any pending breakpoints */
|
||||||
while (breakpoint)
|
while (breakpoint) {
|
||||||
{
|
|
||||||
if (breakpoint->set == 0)
|
if (breakpoint->set == 0)
|
||||||
mips_m4k_set_breakpoint(target, breakpoint);
|
mips_m4k_set_breakpoint(target, breakpoint);
|
||||||
breakpoint = breakpoint->next;
|
breakpoint = breakpoint->next;
|
||||||
|
@ -485,85 +444,72 @@ static int mips_m4k_set_breakpoint(struct target *target,
|
||||||
struct breakpoint *breakpoint)
|
struct breakpoint *breakpoint)
|
||||||
{
|
{
|
||||||
struct mips32_common *mips32 = target_to_mips32(target);
|
struct mips32_common *mips32 = target_to_mips32(target);
|
||||||
struct mips32_comparator * comparator_list = mips32->inst_break_list;
|
struct mips32_comparator *comparator_list = mips32->inst_break_list;
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
if (breakpoint->set)
|
if (breakpoint->set) {
|
||||||
{
|
|
||||||
LOG_WARNING("breakpoint already set");
|
LOG_WARNING("breakpoint already set");
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (breakpoint->type == BKPT_HARD)
|
if (breakpoint->type == BKPT_HARD) {
|
||||||
{
|
|
||||||
int bp_num = 0;
|
int bp_num = 0;
|
||||||
|
|
||||||
while (comparator_list[bp_num].used && (bp_num < mips32->num_inst_bpoints))
|
while (comparator_list[bp_num].used && (bp_num < mips32->num_inst_bpoints))
|
||||||
bp_num++;
|
bp_num++;
|
||||||
if (bp_num >= mips32->num_inst_bpoints)
|
if (bp_num >= mips32->num_inst_bpoints) {
|
||||||
{
|
|
||||||
LOG_ERROR("Can not find free FP Comparator(bpid: %d)",
|
LOG_ERROR("Can not find free FP Comparator(bpid: %d)",
|
||||||
breakpoint->unique_id );
|
breakpoint->unique_id);
|
||||||
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
|
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
|
||||||
}
|
}
|
||||||
breakpoint->set = bp_num + 1;
|
breakpoint->set = bp_num + 1;
|
||||||
comparator_list[bp_num].used = 1;
|
comparator_list[bp_num].used = 1;
|
||||||
comparator_list[bp_num].bp_value = breakpoint->address;
|
comparator_list[bp_num].bp_value = breakpoint->address;
|
||||||
target_write_u32(target, comparator_list[bp_num].reg_address, comparator_list[bp_num].bp_value);
|
target_write_u32(target, comparator_list[bp_num].reg_address,
|
||||||
|
comparator_list[bp_num].bp_value);
|
||||||
target_write_u32(target, comparator_list[bp_num].reg_address + 0x08, 0x00000000);
|
target_write_u32(target, comparator_list[bp_num].reg_address + 0x08, 0x00000000);
|
||||||
target_write_u32(target, comparator_list[bp_num].reg_address + 0x18, 1);
|
target_write_u32(target, comparator_list[bp_num].reg_address + 0x18, 1);
|
||||||
LOG_DEBUG("bpid: %d, bp_num %i bp_value 0x%" PRIx32 "",
|
LOG_DEBUG("bpid: %d, bp_num %i bp_value 0x%" PRIx32 "",
|
||||||
breakpoint->unique_id,
|
breakpoint->unique_id,
|
||||||
bp_num, comparator_list[bp_num].bp_value);
|
bp_num, comparator_list[bp_num].bp_value);
|
||||||
}
|
} else if (breakpoint->type == BKPT_SOFT) {
|
||||||
else if (breakpoint->type == BKPT_SOFT)
|
LOG_DEBUG("bpid: %d", breakpoint->unique_id);
|
||||||
{
|
if (breakpoint->length == 4) {
|
||||||
LOG_DEBUG("bpid: %d", breakpoint->unique_id );
|
|
||||||
if (breakpoint->length == 4)
|
|
||||||
{
|
|
||||||
uint32_t verify = 0xffffffff;
|
uint32_t verify = 0xffffffff;
|
||||||
|
|
||||||
if ((retval = target_read_memory(target, breakpoint->address, breakpoint->length, 1,
|
retval = target_read_memory(target, breakpoint->address, breakpoint->length, 1,
|
||||||
breakpoint->orig_instr)) != ERROR_OK)
|
breakpoint->orig_instr);
|
||||||
{
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
retval = target_write_u32(target, breakpoint->address, MIPS32_SDBBP);
|
||||||
if ((retval = target_write_u32(target, breakpoint->address, MIPS32_SDBBP)) != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
{
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
|
||||||
|
|
||||||
if ((retval = target_read_u32(target, breakpoint->address, &verify)) != ERROR_OK)
|
retval = target_read_u32(target, breakpoint->address, &verify);
|
||||||
{
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
if (verify != MIPS32_SDBBP) {
|
||||||
if (verify != MIPS32_SDBBP)
|
LOG_ERROR("Unable to set 32bit breakpoint at address %08" PRIx32
|
||||||
{
|
" - check that memory is read/writable", breakpoint->address);
|
||||||
LOG_ERROR("Unable to set 32bit breakpoint at address %08" PRIx32 " - check that memory is read/writable", breakpoint->address);
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
uint16_t verify = 0xffff;
|
uint16_t verify = 0xffff;
|
||||||
|
|
||||||
if ((retval = target_read_memory(target, breakpoint->address, breakpoint->length, 1,
|
retval = target_read_memory(target, breakpoint->address, breakpoint->length, 1,
|
||||||
breakpoint->orig_instr)) != ERROR_OK)
|
breakpoint->orig_instr);
|
||||||
{
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
retval = target_write_u16(target, breakpoint->address, MIPS16_SDBBP);
|
||||||
if ((retval = target_write_u16(target, breakpoint->address, MIPS16_SDBBP)) != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
{
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
|
||||||
|
|
||||||
if ((retval = target_read_u16(target, breakpoint->address, &verify)) != ERROR_OK)
|
retval = target_read_u16(target, breakpoint->address, &verify);
|
||||||
{
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
if (verify != MIPS16_SDBBP) {
|
||||||
if (verify != MIPS16_SDBBP)
|
LOG_ERROR("Unable to set 16bit breakpoint at address %08" PRIx32
|
||||||
{
|
" - check that memory is read/writable", breakpoint->address);
|
||||||
LOG_ERROR("Unable to set 16bit breakpoint at address %08" PRIx32 " - check that memory is read/writable", breakpoint->address);
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -582,43 +528,36 @@ static int mips_m4k_unset_breakpoint(struct target *target,
|
||||||
struct mips32_comparator *comparator_list = mips32->inst_break_list;
|
struct mips32_comparator *comparator_list = mips32->inst_break_list;
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
if (!breakpoint->set)
|
if (!breakpoint->set) {
|
||||||
{
|
|
||||||
LOG_WARNING("breakpoint not set");
|
LOG_WARNING("breakpoint not set");
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (breakpoint->type == BKPT_HARD)
|
if (breakpoint->type == BKPT_HARD) {
|
||||||
{
|
|
||||||
int bp_num = breakpoint->set - 1;
|
int bp_num = breakpoint->set - 1;
|
||||||
if ((bp_num < 0) || (bp_num >= mips32->num_inst_bpoints))
|
if ((bp_num < 0) || (bp_num >= mips32->num_inst_bpoints)) {
|
||||||
{
|
|
||||||
LOG_DEBUG("Invalid FP Comparator number in breakpoint (bpid: %d)",
|
LOG_DEBUG("Invalid FP Comparator number in breakpoint (bpid: %d)",
|
||||||
breakpoint->unique_id);
|
breakpoint->unique_id);
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
LOG_DEBUG("bpid: %d - releasing hw: %d",
|
LOG_DEBUG("bpid: %d - releasing hw: %d",
|
||||||
breakpoint->unique_id,
|
breakpoint->unique_id,
|
||||||
bp_num );
|
bp_num);
|
||||||
comparator_list[bp_num].used = 0;
|
comparator_list[bp_num].used = 0;
|
||||||
comparator_list[bp_num].bp_value = 0;
|
comparator_list[bp_num].bp_value = 0;
|
||||||
target_write_u32(target, comparator_list[bp_num].reg_address + 0x18, 0);
|
target_write_u32(target, comparator_list[bp_num].reg_address + 0x18, 0);
|
||||||
|
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
/* restore original instruction (kept in target endianness) */
|
/* restore original instruction (kept in target endianness) */
|
||||||
LOG_DEBUG("bpid: %d", breakpoint->unique_id);
|
LOG_DEBUG("bpid: %d", breakpoint->unique_id);
|
||||||
if (breakpoint->length == 4)
|
if (breakpoint->length == 4) {
|
||||||
{
|
|
||||||
uint32_t current_instr;
|
uint32_t current_instr;
|
||||||
|
|
||||||
/* check that user program has not modified breakpoint instruction */
|
/* check that user program has not modified breakpoint instruction */
|
||||||
if ((retval = target_read_memory(target, breakpoint->address, 4, 1,
|
retval = target_read_memory(target, breakpoint->address, 4, 1,
|
||||||
(uint8_t*)¤t_instr)) != ERROR_OK)
|
(uint8_t *)¤t_instr);
|
||||||
{
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* target_read_memory() gets us data in _target_ endianess.
|
* target_read_memory() gets us data in _target_ endianess.
|
||||||
|
@ -627,33 +566,26 @@ static int mips_m4k_unset_breakpoint(struct target *target,
|
||||||
*/
|
*/
|
||||||
current_instr = target_buffer_get_u32(target, (uint8_t *)¤t_instr);
|
current_instr = target_buffer_get_u32(target, (uint8_t *)¤t_instr);
|
||||||
|
|
||||||
if (current_instr == MIPS32_SDBBP)
|
if (current_instr == MIPS32_SDBBP) {
|
||||||
{
|
retval = target_write_memory(target, breakpoint->address, 4, 1,
|
||||||
if ((retval = target_write_memory(target, breakpoint->address, 4, 1,
|
breakpoint->orig_instr);
|
||||||
breakpoint->orig_instr)) != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
{
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
uint16_t current_instr;
|
uint16_t current_instr;
|
||||||
|
|
||||||
/* check that user program has not modified breakpoint instruction */
|
/* check that user program has not modified breakpoint instruction */
|
||||||
if ((retval = target_read_memory(target, breakpoint->address, 2, 1,
|
retval = target_read_memory(target, breakpoint->address, 2, 1,
|
||||||
(uint8_t*)¤t_instr)) != ERROR_OK)
|
(uint8_t *)¤t_instr);
|
||||||
{
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
|
||||||
current_instr = target_buffer_get_u16(target, (uint8_t *)¤t_instr);
|
current_instr = target_buffer_get_u16(target, (uint8_t *)¤t_instr);
|
||||||
if (current_instr == MIPS16_SDBBP)
|
if (current_instr == MIPS16_SDBBP) {
|
||||||
{
|
retval = target_write_memory(target, breakpoint->address, 2, 1,
|
||||||
if ((retval = target_write_memory(target, breakpoint->address, 2, 1,
|
breakpoint->orig_instr);
|
||||||
breakpoint->orig_instr)) != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
{
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -666,10 +598,8 @@ static int mips_m4k_add_breakpoint(struct target *target, struct breakpoint *bre
|
||||||
{
|
{
|
||||||
struct mips32_common *mips32 = target_to_mips32(target);
|
struct mips32_common *mips32 = target_to_mips32(target);
|
||||||
|
|
||||||
if (breakpoint->type == BKPT_HARD)
|
if (breakpoint->type == BKPT_HARD) {
|
||||||
{
|
if (mips32->num_inst_bpoints_avail < 1) {
|
||||||
if (mips32->num_inst_bpoints_avail < 1)
|
|
||||||
{
|
|
||||||
LOG_INFO("no hardware breakpoint available");
|
LOG_INFO("no hardware breakpoint available");
|
||||||
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
|
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
|
||||||
}
|
}
|
||||||
|
@ -686,16 +616,13 @@ static int mips_m4k_remove_breakpoint(struct target *target,
|
||||||
/* get pointers to arch-specific information */
|
/* get pointers to arch-specific information */
|
||||||
struct mips32_common *mips32 = target_to_mips32(target);
|
struct mips32_common *mips32 = target_to_mips32(target);
|
||||||
|
|
||||||
if (target->state != TARGET_HALTED)
|
if (target->state != TARGET_HALTED) {
|
||||||
{
|
|
||||||
LOG_WARNING("target not halted");
|
LOG_WARNING("target not halted");
|
||||||
return ERROR_TARGET_NOT_HALTED;
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (breakpoint->set)
|
if (breakpoint->set)
|
||||||
{
|
|
||||||
mips_m4k_unset_breakpoint(target, breakpoint);
|
mips_m4k_unset_breakpoint(target, breakpoint);
|
||||||
}
|
|
||||||
|
|
||||||
if (breakpoint->type == BKPT_HARD)
|
if (breakpoint->type == BKPT_HARD)
|
||||||
mips32->num_inst_bpoints_avail++;
|
mips32->num_inst_bpoints_avail++;
|
||||||
|
@ -715,36 +642,31 @@ static int mips_m4k_set_watchpoint(struct target *target,
|
||||||
* condition evaluation
|
* condition evaluation
|
||||||
*/
|
*/
|
||||||
int enable = EJTAG_DBCn_NOSB | EJTAG_DBCn_NOLB | EJTAG_DBCn_BE |
|
int enable = EJTAG_DBCn_NOSB | EJTAG_DBCn_NOLB | EJTAG_DBCn_BE |
|
||||||
(0xff << EJTAG_DBCn_BLM_SHIFT);
|
(0xff << EJTAG_DBCn_BLM_SHIFT);
|
||||||
|
|
||||||
if (watchpoint->set)
|
if (watchpoint->set) {
|
||||||
{
|
|
||||||
LOG_WARNING("watchpoint already set");
|
LOG_WARNING("watchpoint already set");
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
while(comparator_list[wp_num].used && (wp_num < mips32->num_data_bpoints))
|
while (comparator_list[wp_num].used && (wp_num < mips32->num_data_bpoints))
|
||||||
wp_num++;
|
wp_num++;
|
||||||
if (wp_num >= mips32->num_data_bpoints)
|
if (wp_num >= mips32->num_data_bpoints) {
|
||||||
{
|
|
||||||
LOG_ERROR("Can not find free FP Comparator");
|
LOG_ERROR("Can not find free FP Comparator");
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (watchpoint->length != 4)
|
if (watchpoint->length != 4) {
|
||||||
{
|
|
||||||
LOG_ERROR("Only watchpoints of length 4 are supported");
|
LOG_ERROR("Only watchpoints of length 4 are supported");
|
||||||
return ERROR_TARGET_UNALIGNED_ACCESS;
|
return ERROR_TARGET_UNALIGNED_ACCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (watchpoint->address % 4)
|
if (watchpoint->address % 4) {
|
||||||
{
|
|
||||||
LOG_ERROR("Watchpoints address should be word aligned");
|
LOG_ERROR("Watchpoints address should be word aligned");
|
||||||
return ERROR_TARGET_UNALIGNED_ACCESS;
|
return ERROR_TARGET_UNALIGNED_ACCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (watchpoint->rw)
|
switch (watchpoint->rw) {
|
||||||
{
|
|
||||||
case WPT_READ:
|
case WPT_READ:
|
||||||
enable &= ~EJTAG_DBCn_NOLB;
|
enable &= ~EJTAG_DBCn_NOLB;
|
||||||
break;
|
break;
|
||||||
|
@ -778,15 +700,13 @@ static int mips_m4k_unset_watchpoint(struct target *target,
|
||||||
struct mips32_common *mips32 = target_to_mips32(target);
|
struct mips32_common *mips32 = target_to_mips32(target);
|
||||||
struct mips32_comparator *comparator_list = mips32->data_break_list;
|
struct mips32_comparator *comparator_list = mips32->data_break_list;
|
||||||
|
|
||||||
if (!watchpoint->set)
|
if (!watchpoint->set) {
|
||||||
{
|
|
||||||
LOG_WARNING("watchpoint not set");
|
LOG_WARNING("watchpoint not set");
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int wp_num = watchpoint->set - 1;
|
int wp_num = watchpoint->set - 1;
|
||||||
if ((wp_num < 0) || (wp_num >= mips32->num_data_bpoints))
|
if ((wp_num < 0) || (wp_num >= mips32->num_data_bpoints)) {
|
||||||
{
|
|
||||||
LOG_DEBUG("Invalid FP Comparator number in watchpoint");
|
LOG_DEBUG("Invalid FP Comparator number in watchpoint");
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
@ -802,8 +722,7 @@ static int mips_m4k_add_watchpoint(struct target *target, struct watchpoint *wat
|
||||||
{
|
{
|
||||||
struct mips32_common *mips32 = target_to_mips32(target);
|
struct mips32_common *mips32 = target_to_mips32(target);
|
||||||
|
|
||||||
if (mips32->num_data_bpoints_avail < 1)
|
if (mips32->num_data_bpoints_avail < 1) {
|
||||||
{
|
|
||||||
LOG_INFO("no hardware watchpoints available");
|
LOG_INFO("no hardware watchpoints available");
|
||||||
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
|
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
|
||||||
}
|
}
|
||||||
|
@ -820,16 +739,13 @@ static int mips_m4k_remove_watchpoint(struct target *target,
|
||||||
/* get pointers to arch-specific information */
|
/* get pointers to arch-specific information */
|
||||||
struct mips32_common *mips32 = target_to_mips32(target);
|
struct mips32_common *mips32 = target_to_mips32(target);
|
||||||
|
|
||||||
if (target->state != TARGET_HALTED)
|
if (target->state != TARGET_HALTED) {
|
||||||
{
|
|
||||||
LOG_WARNING("target not halted");
|
LOG_WARNING("target not halted");
|
||||||
return ERROR_TARGET_NOT_HALTED;
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (watchpoint->set)
|
if (watchpoint->set)
|
||||||
{
|
|
||||||
mips_m4k_unset_watchpoint(target, watchpoint);
|
mips_m4k_unset_watchpoint(target, watchpoint);
|
||||||
}
|
|
||||||
|
|
||||||
mips32->num_data_bpoints_avail++;
|
mips32->num_data_bpoints_avail++;
|
||||||
|
|
||||||
|
@ -841,8 +757,7 @@ static void mips_m4k_enable_watchpoints(struct target *target)
|
||||||
struct watchpoint *watchpoint = target->watchpoints;
|
struct watchpoint *watchpoint = target->watchpoints;
|
||||||
|
|
||||||
/* set any pending watchpoints */
|
/* set any pending watchpoints */
|
||||||
while (watchpoint)
|
while (watchpoint) {
|
||||||
{
|
|
||||||
if (watchpoint->set == 0)
|
if (watchpoint->set == 0)
|
||||||
mips_m4k_set_watchpoint(target, watchpoint);
|
mips_m4k_set_watchpoint(target, watchpoint);
|
||||||
watchpoint = watchpoint->next;
|
watchpoint = watchpoint->next;
|
||||||
|
@ -855,10 +770,10 @@ static int mips_m4k_read_memory(struct target *target, uint32_t address,
|
||||||
struct mips32_common *mips32 = target_to_mips32(target);
|
struct mips32_common *mips32 = target_to_mips32(target);
|
||||||
struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
|
struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
|
||||||
|
|
||||||
LOG_DEBUG("address: 0x%8.8" PRIx32 ", size: 0x%8.8" PRIx32 ", count: 0x%8.8" PRIx32 "", address, size, count);
|
LOG_DEBUG("address: 0x%8.8" PRIx32 ", size: 0x%8.8" PRIx32 ", count: 0x%8.8" PRIx32 "",
|
||||||
|
address, size, count);
|
||||||
|
|
||||||
if (target->state != TARGET_HALTED)
|
if (target->state != TARGET_HALTED) {
|
||||||
{
|
|
||||||
LOG_WARNING("target not halted");
|
LOG_WARNING("target not halted");
|
||||||
return ERROR_TARGET_NOT_HALTED;
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
}
|
}
|
||||||
|
@ -873,19 +788,14 @@ static int mips_m4k_read_memory(struct target *target, uint32_t address,
|
||||||
/* since we don't know if buffer is aligned, we allocate new mem that is always aligned */
|
/* since we don't know if buffer is aligned, we allocate new mem that is always aligned */
|
||||||
void *t = NULL;
|
void *t = NULL;
|
||||||
|
|
||||||
if (size > 1)
|
if (size > 1) {
|
||||||
{
|
|
||||||
t = malloc(count * size * sizeof(uint8_t));
|
t = malloc(count * size * sizeof(uint8_t));
|
||||||
if (t == NULL)
|
if (t == NULL) {
|
||||||
{
|
|
||||||
LOG_ERROR("Out of memory");
|
LOG_ERROR("Out of memory");
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
}
|
} else
|
||||||
else
|
|
||||||
{
|
|
||||||
t = buffer;
|
t = buffer;
|
||||||
}
|
|
||||||
|
|
||||||
/* if noDMA off, use DMAACC mode for memory read */
|
/* if noDMA off, use DMAACC mode for memory read */
|
||||||
int retval;
|
int retval;
|
||||||
|
@ -896,15 +806,13 @@ static int mips_m4k_read_memory(struct target *target, uint32_t address,
|
||||||
|
|
||||||
/* mips32_..._read_mem with size 4/2 returns uint32_t/uint16_t in host */
|
/* mips32_..._read_mem with size 4/2 returns uint32_t/uint16_t in host */
|
||||||
/* endianness, but byte array should represent target endianness */
|
/* endianness, but byte array should represent target endianness */
|
||||||
if (ERROR_OK == retval)
|
if (ERROR_OK == retval) {
|
||||||
{
|
switch (size) {
|
||||||
switch(size)
|
|
||||||
{
|
|
||||||
case 4:
|
case 4:
|
||||||
target_buffer_set_u32_array(target,buffer,count,t);
|
target_buffer_set_u32_array(target, buffer, count, t);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
target_buffer_set_u16_array(target,buffer,count,t);
|
target_buffer_set_u16_array(target, buffer, count, t);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -924,8 +832,7 @@ static int mips_m4k_write_memory(struct target *target, uint32_t address,
|
||||||
LOG_DEBUG("address: 0x%8.8" PRIx32 ", size: 0x%8.8" PRIx32 ", count: 0x%8.8" PRIx32 "",
|
LOG_DEBUG("address: 0x%8.8" PRIx32 ", size: 0x%8.8" PRIx32 ", count: 0x%8.8" PRIx32 "",
|
||||||
address, size, count);
|
address, size, count);
|
||||||
|
|
||||||
if (target->state != TARGET_HALTED)
|
if (target->state != TARGET_HALTED) {
|
||||||
{
|
|
||||||
LOG_WARNING("target not halted");
|
LOG_WARNING("target not halted");
|
||||||
return ERROR_TARGET_NOT_HALTED;
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
}
|
}
|
||||||
|
@ -939,24 +846,21 @@ static int mips_m4k_write_memory(struct target *target, uint32_t address,
|
||||||
|
|
||||||
/** correct endianess if we have word or hword access */
|
/** correct endianess if we have word or hword access */
|
||||||
void *t = NULL;
|
void *t = NULL;
|
||||||
if (size > 1)
|
if (size > 1) {
|
||||||
{
|
|
||||||
/* mips32_..._write_mem with size 4/2 requires uint32_t/uint16_t in host */
|
/* mips32_..._write_mem with size 4/2 requires uint32_t/uint16_t in host */
|
||||||
/* endianness, but byte array represents target endianness */
|
/* endianness, but byte array represents target endianness */
|
||||||
t = malloc(count * size * sizeof(uint8_t));
|
t = malloc(count * size * sizeof(uint8_t));
|
||||||
if (t == NULL)
|
if (t == NULL) {
|
||||||
{
|
|
||||||
LOG_ERROR("Out of memory");
|
LOG_ERROR("Out of memory");
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch(size)
|
switch (size) {
|
||||||
{
|
|
||||||
case 4:
|
case 4:
|
||||||
target_buffer_get_u32_array(target,buffer,count,(uint32_t*)t);
|
target_buffer_get_u32_array(target, buffer, count, (uint32_t *)t);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
target_buffer_get_u16_array(target,buffer,count,(uint16_t*)t);
|
target_buffer_get_u16_array(target, buffer, count, (uint16_t *)t);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
buffer = t;
|
buffer = t;
|
||||||
|
@ -1016,15 +920,13 @@ static int mips_m4k_examine(struct target *target)
|
||||||
struct mips_ejtag *ejtag_info = &mips_m4k->mips32.ejtag_info;
|
struct mips_ejtag *ejtag_info = &mips_m4k->mips32.ejtag_info;
|
||||||
uint32_t idcode = 0;
|
uint32_t idcode = 0;
|
||||||
|
|
||||||
if (!target_was_examined(target))
|
if (!target_was_examined(target)) {
|
||||||
{
|
|
||||||
retval = mips_ejtag_get_idcode(ejtag_info, &idcode);
|
retval = mips_ejtag_get_idcode(ejtag_info, &idcode);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
ejtag_info->idcode = idcode;
|
ejtag_info->idcode = idcode;
|
||||||
|
|
||||||
if (((idcode >> 1) & 0x7FF) == 0x29)
|
if (((idcode >> 1) & 0x7FF) == 0x29) {
|
||||||
{
|
|
||||||
/* we are using a pic32mx so select ejtag port
|
/* we are using a pic32mx so select ejtag port
|
||||||
* as it is not selected by default */
|
* as it is not selected by default */
|
||||||
mips_ejtag_set_instr(ejtag_info, MTAP_SW_ETAP);
|
mips_ejtag_set_instr(ejtag_info, MTAP_SW_ETAP);
|
||||||
|
@ -1034,10 +936,12 @@ static int mips_m4k_examine(struct target *target)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* init rest of ejtag interface */
|
/* init rest of ejtag interface */
|
||||||
if ((retval = mips_ejtag_init(ejtag_info)) != ERROR_OK)
|
retval = mips_ejtag_init(ejtag_info);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
if ((retval = mips32_examine(target)) != ERROR_OK)
|
retval = mips32_examine(target);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
|
@ -1053,8 +957,7 @@ static int mips_m4k_bulk_write_memory(struct target *target, uint32_t address,
|
||||||
|
|
||||||
LOG_DEBUG("address: 0x%8.8" PRIx32 ", count: 0x%8.8" PRIx32 "", address, count);
|
LOG_DEBUG("address: 0x%8.8" PRIx32 ", count: 0x%8.8" PRIx32 "", address, count);
|
||||||
|
|
||||||
if (target->state != TARGET_HALTED)
|
if (target->state != TARGET_HALTED) {
|
||||||
{
|
|
||||||
LOG_WARNING("target not halted");
|
LOG_WARNING("target not halted");
|
||||||
return ERROR_TARGET_NOT_HALTED;
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
}
|
}
|
||||||
|
@ -1063,8 +966,7 @@ static int mips_m4k_bulk_write_memory(struct target *target, uint32_t address,
|
||||||
if (address & 0x3u)
|
if (address & 0x3u)
|
||||||
return ERROR_TARGET_UNALIGNED_ACCESS;
|
return ERROR_TARGET_UNALIGNED_ACCESS;
|
||||||
|
|
||||||
if (mips32->fast_data_area == NULL)
|
if (mips32->fast_data_area == NULL) {
|
||||||
{
|
|
||||||
/* Get memory for block write handler
|
/* Get memory for block write handler
|
||||||
* we preserve this area between calls and gain a speed increase
|
* we preserve this area between calls and gain a speed increase
|
||||||
* of about 3kb/sec when writing flash
|
* of about 3kb/sec when writing flash
|
||||||
|
@ -1072,8 +974,7 @@ static int mips_m4k_bulk_write_memory(struct target *target, uint32_t address,
|
||||||
retval = target_alloc_working_area(target,
|
retval = target_alloc_working_area(target,
|
||||||
MIPS32_FASTDATA_HANDLER_SIZE,
|
MIPS32_FASTDATA_HANDLER_SIZE,
|
||||||
&mips32->fast_data_area);
|
&mips32->fast_data_area);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK) {
|
||||||
{
|
|
||||||
LOG_WARNING("No working area available, falling back to non-bulk write");
|
LOG_WARNING("No working area available, falling back to non-bulk write");
|
||||||
return mips_m4k_write_memory(target, address, 4, count, buffer);
|
return mips_m4k_write_memory(target, address, 4, count, buffer);
|
||||||
}
|
}
|
||||||
|
@ -1086,13 +987,12 @@ static int mips_m4k_bulk_write_memory(struct target *target, uint32_t address,
|
||||||
/* but byte array represents target endianness */
|
/* but byte array represents target endianness */
|
||||||
uint32_t *t = NULL;
|
uint32_t *t = NULL;
|
||||||
t = malloc(count * sizeof(uint32_t));
|
t = malloc(count * sizeof(uint32_t));
|
||||||
if (t == NULL)
|
if (t == NULL) {
|
||||||
{
|
|
||||||
LOG_ERROR("Out of memory");
|
LOG_ERROR("Out of memory");
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
target_buffer_get_u32_array(target,buffer,count,t);
|
target_buffer_get_u32_array(target, buffer, count, t);
|
||||||
|
|
||||||
retval = mips32_pracc_fastdata_xfer(ejtag_info, mips32->fast_data_area, write_t, address,
|
retval = mips32_pracc_fastdata_xfer(ejtag_info, mips32->fast_data_area, write_t, address,
|
||||||
count, t);
|
count, t);
|
||||||
|
@ -1100,8 +1000,7 @@ static int mips_m4k_bulk_write_memory(struct target *target, uint32_t address,
|
||||||
if (t != NULL)
|
if (t != NULL)
|
||||||
free(t);
|
free(t);
|
||||||
|
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK) {
|
||||||
{
|
|
||||||
/* FASTDATA access failed, try normal memory write */
|
/* FASTDATA access failed, try normal memory write */
|
||||||
LOG_DEBUG("Fastdata access Failed, falling back to non-bulk write");
|
LOG_DEBUG("Fastdata access Failed, falling back to non-bulk write");
|
||||||
retval = mips_m4k_write_memory(target, address, 4, count, buffer);
|
retval = mips_m4k_write_memory(target, address, 4, count, buffer);
|
||||||
|
@ -1131,48 +1030,40 @@ COMMAND_HANDLER(mips_m4k_handle_cp0_command)
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
if (target->state != TARGET_HALTED)
|
if (target->state != TARGET_HALTED) {
|
||||||
{
|
|
||||||
command_print(CMD_CTX, "target must be stopped for \"%s\" command", CMD_NAME);
|
command_print(CMD_CTX, "target must be stopped for \"%s\" command", CMD_NAME);
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* two or more argument, access a single register/select (write if third argument is given) */
|
/* two or more argument, access a single register/select (write if third argument is given) */
|
||||||
if (CMD_ARGC < 2)
|
if (CMD_ARGC < 2)
|
||||||
{
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
else {
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
uint32_t cp0_reg, cp0_sel;
|
uint32_t cp0_reg, cp0_sel;
|
||||||
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], cp0_reg);
|
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], cp0_reg);
|
||||||
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], cp0_sel);
|
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], cp0_sel);
|
||||||
|
|
||||||
if (CMD_ARGC == 2)
|
if (CMD_ARGC == 2) {
|
||||||
{
|
|
||||||
uint32_t value;
|
uint32_t value;
|
||||||
|
|
||||||
if ((retval = mips32_cp0_read(ejtag_info, &value, cp0_reg, cp0_sel)) != ERROR_OK)
|
retval = mips32_cp0_read(ejtag_info, &value, cp0_reg, cp0_sel);
|
||||||
{
|
if (retval != ERROR_OK) {
|
||||||
command_print(CMD_CTX,
|
command_print(CMD_CTX,
|
||||||
"couldn't access reg %" PRIi32,
|
"couldn't access reg %" PRIi32,
|
||||||
cp0_reg);
|
cp0_reg);
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
if ((retval = jtag_execute_queue()) != ERROR_OK)
|
retval = jtag_execute_queue();
|
||||||
{
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
|
||||||
|
|
||||||
command_print(CMD_CTX, "cp0 reg %" PRIi32 ", select %" PRIi32 ": %8.8" PRIx32,
|
command_print(CMD_CTX, "cp0 reg %" PRIi32 ", select %" PRIi32 ": %8.8" PRIx32,
|
||||||
cp0_reg, cp0_sel, value);
|
cp0_reg, cp0_sel, value);
|
||||||
}
|
} else if (CMD_ARGC == 3) {
|
||||||
else if (CMD_ARGC == 3)
|
|
||||||
{
|
|
||||||
uint32_t value;
|
uint32_t value;
|
||||||
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], value);
|
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], value);
|
||||||
if ((retval = mips32_cp0_write(ejtag_info, value, cp0_reg, cp0_sel)) != ERROR_OK)
|
retval = mips32_cp0_write(ejtag_info, value, cp0_reg, cp0_sel);
|
||||||
{
|
if (retval != ERROR_OK) {
|
||||||
command_print(CMD_CTX,
|
command_print(CMD_CTX,
|
||||||
"couldn't access cp0 reg %" PRIi32 ", select %" PRIi32,
|
"couldn't access cp0 reg %" PRIi32 ", select %" PRIi32,
|
||||||
cp0_reg, cp0_sel);
|
cp0_reg, cp0_sel);
|
||||||
|
@ -1211,8 +1102,7 @@ const struct command_registration mips_m4k_command_handlers[] = {
|
||||||
COMMAND_REGISTRATION_DONE
|
COMMAND_REGISTRATION_DONE
|
||||||
};
|
};
|
||||||
|
|
||||||
struct target_type mips_m4k_target =
|
struct target_type mips_m4k_target = {
|
||||||
{
|
|
||||||
.name = "mips_m4k",
|
.name = "mips_m4k",
|
||||||
|
|
||||||
.poll = mips_m4k_poll,
|
.poll = mips_m4k_poll,
|
||||||
|
|
|
@ -32,8 +32,7 @@ struct target;
|
||||||
|
|
||||||
#define MIPSM4K_COMMON_MAGIC 0xB321B321
|
#define MIPSM4K_COMMON_MAGIC 0xB321B321
|
||||||
|
|
||||||
struct mips_m4k_common
|
struct mips_m4k_common {
|
||||||
{
|
|
||||||
uint32_t common_magic;
|
uint32_t common_magic;
|
||||||
bool is_pic32mx;
|
bool is_pic32mx;
|
||||||
struct mips32_common mips32;
|
struct mips32_common mips32;
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
* Free Software Foundation, Inc., *
|
* Free Software Foundation, Inc., *
|
||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -30,7 +31,6 @@
|
||||||
* https://lists.berlios.de/pipermail/openocd-development/2007-September/000336.html
|
* https://lists.berlios.de/pipermail/openocd-development/2007-September/000336.html
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
static int oocd_trace_read_reg(struct oocd_trace *oocd_trace, int reg, uint32_t *value)
|
static int oocd_trace_read_reg(struct oocd_trace *oocd_trace, int reg, uint32_t *value)
|
||||||
{
|
{
|
||||||
size_t bytes_written, bytes_read, bytes_to_read;
|
size_t bytes_written, bytes_read, bytes_to_read;
|
||||||
|
@ -40,9 +40,8 @@ static int oocd_trace_read_reg(struct oocd_trace *oocd_trace, int reg, uint32_t
|
||||||
bytes_written = write(oocd_trace->tty_fd, &cmd, 1);
|
bytes_written = write(oocd_trace->tty_fd, &cmd, 1);
|
||||||
|
|
||||||
bytes_to_read = 4;
|
bytes_to_read = 4;
|
||||||
while (bytes_to_read > 0)
|
while (bytes_to_read > 0) {
|
||||||
{
|
bytes_read = read(oocd_trace->tty_fd, ((uint8_t *)value) + 4 - bytes_to_read, bytes_to_read);
|
||||||
bytes_read = read(oocd_trace->tty_fd, ((uint8_t*)value) + 4 - bytes_to_read, bytes_to_read);
|
|
||||||
bytes_to_read -= bytes_read;
|
bytes_to_read -= bytes_read;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,13 +80,11 @@ static int oocd_trace_read_memory(struct oocd_trace *oocd_trace, uint8_t *data,
|
||||||
bytes_written = write(oocd_trace->tty_fd, &cmd, 1);
|
bytes_written = write(oocd_trace->tty_fd, &cmd, 1);
|
||||||
|
|
||||||
bytes_to_read = size * 16;
|
bytes_to_read = size * 16;
|
||||||
while (bytes_to_read > 0)
|
while (bytes_to_read > 0) {
|
||||||
{
|
bytes_read = read(oocd_trace->tty_fd,
|
||||||
if ((bytes_read = read(oocd_trace->tty_fd,
|
((uint8_t *)data) + (size * 16) - bytes_to_read, bytes_to_read);
|
||||||
((uint8_t*)data) + (size * 16) - bytes_to_read, bytes_to_read)) < 0)
|
if (bytes_read < 0)
|
||||||
{
|
|
||||||
LOG_DEBUG("read() returned %zi (%s)", bytes_read, strerror(errno));
|
LOG_DEBUG("read() returned %zi (%s)", bytes_read, strerror(errno));
|
||||||
}
|
|
||||||
else
|
else
|
||||||
bytes_to_read -= bytes_read;
|
bytes_to_read -= bytes_read;
|
||||||
}
|
}
|
||||||
|
@ -103,8 +100,7 @@ static int oocd_trace_init(struct etm_context *etm_ctx)
|
||||||
|
|
||||||
oocd_trace->tty_fd = open(oocd_trace->tty, O_RDWR | O_NOCTTY | O_NONBLOCK);
|
oocd_trace->tty_fd = open(oocd_trace->tty, O_RDWR | O_NOCTTY | O_NONBLOCK);
|
||||||
|
|
||||||
if (oocd_trace->tty_fd < 0)
|
if (oocd_trace->tty_fd < 0) {
|
||||||
{
|
|
||||||
LOG_ERROR("can't open tty");
|
LOG_ERROR("can't open tty");
|
||||||
return ERROR_ETM_CAPTURE_INIT_FAILED;
|
return ERROR_ETM_CAPTURE_INIT_FAILED;
|
||||||
}
|
}
|
||||||
|
@ -134,10 +130,11 @@ static int oocd_trace_init(struct etm_context *etm_ctx)
|
||||||
|
|
||||||
/* occasionally one bogus character is left in the input buffer
|
/* occasionally one bogus character is left in the input buffer
|
||||||
* read up any leftover characters to ensure communication is in sync */
|
* read up any leftover characters to ensure communication is in sync */
|
||||||
while ((bytes_read = read(oocd_trace->tty_fd, trash, sizeof(trash))) > 0)
|
do {
|
||||||
{
|
bytes_read = read(oocd_trace->tty_fd, trash, sizeof(trash));
|
||||||
LOG_DEBUG("%zi bytes read", bytes_read);
|
if (bytes_read)
|
||||||
};
|
LOG_DEBUG("%zi bytes read", bytes_read);
|
||||||
|
} while (bytes_read > 0);
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
@ -151,11 +148,8 @@ static trace_status_t oocd_trace_status(struct etm_context *etm_ctx)
|
||||||
|
|
||||||
/* if tracing is currently idle, return this information */
|
/* if tracing is currently idle, return this information */
|
||||||
if (etm_ctx->capture_status == TRACE_IDLE)
|
if (etm_ctx->capture_status == TRACE_IDLE)
|
||||||
{
|
|
||||||
return etm_ctx->capture_status;
|
return etm_ctx->capture_status;
|
||||||
}
|
else if (etm_ctx->capture_status & TRACE_RUNNING) {
|
||||||
else if (etm_ctx->capture_status & TRACE_RUNNING)
|
|
||||||
{
|
|
||||||
/* check Full bit to identify an overflow */
|
/* check Full bit to identify an overflow */
|
||||||
if (status & 0x4)
|
if (status & 0x4)
|
||||||
etm_ctx->capture_status |= TRACE_OVERFLOWED;
|
etm_ctx->capture_status |= TRACE_OVERFLOWED;
|
||||||
|
@ -164,8 +158,7 @@ static trace_status_t oocd_trace_status(struct etm_context *etm_ctx)
|
||||||
if (status & 0x2)
|
if (status & 0x2)
|
||||||
etm_ctx->capture_status |= TRACE_TRIGGERED;
|
etm_ctx->capture_status |= TRACE_TRIGGERED;
|
||||||
|
|
||||||
if (status & 0x1)
|
if (status & 0x1) {
|
||||||
{
|
|
||||||
etm_ctx->capture_status &= ~TRACE_RUNNING;
|
etm_ctx->capture_status &= ~TRACE_RUNNING;
|
||||||
etm_ctx->capture_status |= TRACE_COMPLETED;
|
etm_ctx->capture_status |= TRACE_COMPLETED;
|
||||||
}
|
}
|
||||||
|
@ -202,26 +195,20 @@ static int oocd_trace_read_trace(struct etm_context *etm_ctx)
|
||||||
oocd_trace_read_memory(oocd_trace, trace_data, first_frame, num_frames);
|
oocd_trace_read_memory(oocd_trace, trace_data, first_frame, num_frames);
|
||||||
|
|
||||||
if (etm_ctx->trace_depth > 0)
|
if (etm_ctx->trace_depth > 0)
|
||||||
{
|
|
||||||
free(etm_ctx->trace_data);
|
free(etm_ctx->trace_data);
|
||||||
}
|
|
||||||
|
|
||||||
etm_ctx->trace_depth = num_frames * 16;
|
etm_ctx->trace_depth = num_frames * 16;
|
||||||
etm_ctx->trace_data = malloc(sizeof(struct etmv1_trace_data) * etm_ctx->trace_depth);
|
etm_ctx->trace_data = malloc(sizeof(struct etmv1_trace_data) * etm_ctx->trace_depth);
|
||||||
|
|
||||||
for (i = 0; i < num_frames * 16; i++)
|
for (i = 0; i < num_frames * 16; i++) {
|
||||||
{
|
|
||||||
etm_ctx->trace_data[i].pipestat = (trace_data[i] & 0x7);
|
etm_ctx->trace_data[i].pipestat = (trace_data[i] & 0x7);
|
||||||
etm_ctx->trace_data[i].packet = (trace_data[i] & 0x78) >> 3;
|
etm_ctx->trace_data[i].packet = (trace_data[i] & 0x78) >> 3;
|
||||||
etm_ctx->trace_data[i].flags = 0;
|
etm_ctx->trace_data[i].flags = 0;
|
||||||
|
|
||||||
if ((trace_data[i] & 0x80) >> 7)
|
if ((trace_data[i] & 0x80) >> 7)
|
||||||
{
|
|
||||||
etm_ctx->trace_data[i].flags |= ETMV1_TRACESYNC_CYCLE;
|
etm_ctx->trace_data[i].flags |= ETMV1_TRACESYNC_CYCLE;
|
||||||
}
|
|
||||||
|
|
||||||
if (etm_ctx->trace_data[i].pipestat == STAT_TR)
|
if (etm_ctx->trace_data[i].pipestat == STAT_TR) {
|
||||||
{
|
|
||||||
etm_ctx->trace_data[i].pipestat = etm_ctx->trace_data[i].packet & 0x7;
|
etm_ctx->trace_data[i].pipestat = etm_ctx->trace_data[i].packet & 0x7;
|
||||||
etm_ctx->trace_data[i].flags |= ETMV1_TRIGGER_CYCLE;
|
etm_ctx->trace_data[i].flags |= ETMV1_TRIGGER_CYCLE;
|
||||||
}
|
}
|
||||||
|
@ -239,16 +226,13 @@ static int oocd_trace_start_capture(struct etm_context *etm_ctx)
|
||||||
uint32_t trigger_count;
|
uint32_t trigger_count;
|
||||||
|
|
||||||
if (((etm_ctx->control & ETM_PORT_MODE_MASK) != ETM_PORT_NORMAL)
|
if (((etm_ctx->control & ETM_PORT_MODE_MASK) != ETM_PORT_NORMAL)
|
||||||
|| ((etm_ctx->control & ETM_PORT_WIDTH_MASK) != ETM_PORT_4BIT))
|
|| ((etm_ctx->control & ETM_PORT_WIDTH_MASK) != ETM_PORT_4BIT)) {
|
||||||
{
|
|
||||||
LOG_DEBUG("OpenOCD + trace only supports normal 4-bit ETM mode");
|
LOG_DEBUG("OpenOCD + trace only supports normal 4-bit ETM mode");
|
||||||
return ERROR_ETM_PORTMODE_NOT_SUPPORTED;
|
return ERROR_ETM_PORTMODE_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((etm_ctx->control & ETM_PORT_CLOCK_MASK) == ETM_PORT_HALF_CLOCK)
|
if ((etm_ctx->control & ETM_PORT_CLOCK_MASK) == ETM_PORT_HALF_CLOCK)
|
||||||
{
|
|
||||||
control |= 0x2; /* half rate clock, capture at twice the clock rate */
|
control |= 0x2; /* half rate clock, capture at twice the clock rate */
|
||||||
}
|
|
||||||
|
|
||||||
/* OpenOCD + trace holds up to 16 million samples,
|
/* OpenOCD + trace holds up to 16 million samples,
|
||||||
* but trigger counts is set in multiples of 16 */
|
* but trigger counts is set in multiples of 16 */
|
||||||
|
@ -283,20 +267,16 @@ COMMAND_HANDLER(handle_oocd_trace_config_command)
|
||||||
struct arm *arm;
|
struct arm *arm;
|
||||||
|
|
||||||
if (CMD_ARGC != 2)
|
if (CMD_ARGC != 2)
|
||||||
{
|
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
}
|
|
||||||
|
|
||||||
target = get_current_target(CMD_CTX);
|
target = get_current_target(CMD_CTX);
|
||||||
arm = target_to_arm(target);
|
arm = target_to_arm(target);
|
||||||
if (!is_arm(arm))
|
if (!is_arm(arm)) {
|
||||||
{
|
|
||||||
command_print(CMD_CTX, "current target isn't an ARM");
|
command_print(CMD_CTX, "current target isn't an ARM");
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (arm->etm)
|
if (arm->etm) {
|
||||||
{
|
|
||||||
struct oocd_trace *oocd_trace = malloc(sizeof(struct oocd_trace));
|
struct oocd_trace *oocd_trace = malloc(sizeof(struct oocd_trace));
|
||||||
|
|
||||||
arm->etm->capture_driver_priv = oocd_trace;
|
arm->etm->capture_driver_priv = oocd_trace;
|
||||||
|
@ -304,11 +284,8 @@ COMMAND_HANDLER(handle_oocd_trace_config_command)
|
||||||
|
|
||||||
/* copy name of TTY device used to communicate with OpenOCD + trace */
|
/* copy name of TTY device used to communicate with OpenOCD + trace */
|
||||||
oocd_trace->tty = strndup(CMD_ARGV[1], 256);
|
oocd_trace->tty = strndup(CMD_ARGV[1], 256);
|
||||||
}
|
} else
|
||||||
else
|
|
||||||
{
|
|
||||||
LOG_ERROR("target has no ETM defined, OpenOCD + trace left unconfigured");
|
LOG_ERROR("target has no ETM defined, OpenOCD + trace left unconfigured");
|
||||||
}
|
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
@ -323,25 +300,22 @@ COMMAND_HANDLER(handle_oocd_trace_status_command)
|
||||||
target = get_current_target(CMD_CTX);
|
target = get_current_target(CMD_CTX);
|
||||||
|
|
||||||
arm = target_to_arm(target);
|
arm = target_to_arm(target);
|
||||||
if (!is_arm(arm))
|
if (!is_arm(arm)) {
|
||||||
{
|
|
||||||
command_print(CMD_CTX, "current target isn't an ARM");
|
command_print(CMD_CTX, "current target isn't an ARM");
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!arm->etm)
|
if (!arm->etm) {
|
||||||
{
|
|
||||||
command_print(CMD_CTX, "current target doesn't have an ETM configured");
|
command_print(CMD_CTX, "current target doesn't have an ETM configured");
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strcmp(arm->etm->capture_driver->name, "oocd_trace") != 0)
|
if (strcmp(arm->etm->capture_driver->name, "oocd_trace") != 0) {
|
||||||
{
|
|
||||||
command_print(CMD_CTX, "current target's ETM capture driver isn't 'oocd_trace'");
|
command_print(CMD_CTX, "current target's ETM capture driver isn't 'oocd_trace'");
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
oocd_trace = (struct oocd_trace*)arm->etm->capture_driver_priv;
|
oocd_trace = (struct oocd_trace *)arm->etm->capture_driver_priv;
|
||||||
|
|
||||||
oocd_trace_read_reg(oocd_trace, OOCD_TRACE_STATUS, &status);
|
oocd_trace_read_reg(oocd_trace, OOCD_TRACE_STATUS, &status);
|
||||||
|
|
||||||
|
@ -364,25 +338,22 @@ COMMAND_HANDLER(handle_oocd_trace_resync_command)
|
||||||
target = get_current_target(CMD_CTX);
|
target = get_current_target(CMD_CTX);
|
||||||
|
|
||||||
arm = target_to_arm(target);
|
arm = target_to_arm(target);
|
||||||
if (!is_arm(arm))
|
if (!is_arm(arm)) {
|
||||||
{
|
|
||||||
command_print(CMD_CTX, "current target isn't an ARM");
|
command_print(CMD_CTX, "current target isn't an ARM");
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!arm->etm)
|
if (!arm->etm) {
|
||||||
{
|
|
||||||
command_print(CMD_CTX, "current target doesn't have an ETM configured");
|
command_print(CMD_CTX, "current target doesn't have an ETM configured");
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strcmp(arm->etm->capture_driver->name, "oocd_trace") != 0)
|
if (strcmp(arm->etm->capture_driver->name, "oocd_trace") != 0) {
|
||||||
{
|
|
||||||
command_print(CMD_CTX, "current target's ETM capture driver isn't 'oocd_trace'");
|
command_print(CMD_CTX, "current target's ETM capture driver isn't 'oocd_trace'");
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
oocd_trace = (struct oocd_trace*)arm->etm->capture_driver_priv;
|
oocd_trace = (struct oocd_trace *)arm->etm->capture_driver_priv;
|
||||||
|
|
||||||
cmd_array[0] = 0xf0;
|
cmd_array[0] = 0xf0;
|
||||||
|
|
||||||
|
@ -428,8 +399,7 @@ static const struct command_registration oocd_trace_command_handlers[] = {
|
||||||
COMMAND_REGISTRATION_DONE
|
COMMAND_REGISTRATION_DONE
|
||||||
};
|
};
|
||||||
|
|
||||||
struct etm_capture_driver oocd_trace_capture_driver =
|
struct etm_capture_driver oocd_trace_capture_driver = {
|
||||||
{
|
|
||||||
.name = "oocd_trace",
|
.name = "oocd_trace",
|
||||||
.commands = oocd_trace_command_handlers,
|
.commands = oocd_trace_command_handlers,
|
||||||
.init = oocd_trace_init,
|
.init = oocd_trace_init,
|
||||||
|
@ -438,5 +408,3 @@ struct etm_capture_driver oocd_trace_capture_driver =
|
||||||
.stop_capture = oocd_trace_stop_capture,
|
.stop_capture = oocd_trace_stop_capture,
|
||||||
.read_trace = oocd_trace_read_trace,
|
.read_trace = oocd_trace_read_trace,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -17,14 +17,14 @@
|
||||||
* Free Software Foundation, Inc., *
|
* Free Software Foundation, Inc., *
|
||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#ifndef OOCD_TRACE_H
|
#ifndef OOCD_TRACE_H
|
||||||
#define OOCD_TRACE_H
|
#define OOCD_TRACE_H
|
||||||
|
|
||||||
#include <termios.h>
|
#include <termios.h>
|
||||||
|
|
||||||
/* registers */
|
/* registers */
|
||||||
enum
|
enum {
|
||||||
{
|
|
||||||
OOCD_TRACE_ID = 0x7,
|
OOCD_TRACE_ID = 0x7,
|
||||||
OOCD_TRACE_ADDRESS = 0x0,
|
OOCD_TRACE_ADDRESS = 0x0,
|
||||||
OOCD_TRACE_TRIGGER_COUNTER = 0x01,
|
OOCD_TRACE_TRIGGER_COUNTER = 0x01,
|
||||||
|
@ -34,8 +34,7 @@ enum
|
||||||
};
|
};
|
||||||
|
|
||||||
/* commands */
|
/* commands */
|
||||||
enum
|
enum {
|
||||||
{
|
|
||||||
OOCD_TRACE_NOP = 0x0,
|
OOCD_TRACE_NOP = 0x0,
|
||||||
OOCD_TRACE_READ_REG = 0x10,
|
OOCD_TRACE_READ_REG = 0x10,
|
||||||
OOCD_TRACE_WRITE_REG = 0x18,
|
OOCD_TRACE_WRITE_REG = 0x18,
|
||||||
|
@ -44,8 +43,7 @@ enum
|
||||||
OOCD_TRACE_RESYNC = 0xf0,
|
OOCD_TRACE_RESYNC = 0xf0,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct oocd_trace
|
struct oocd_trace {
|
||||||
{
|
|
||||||
struct etm_context *etm_ctx;
|
struct etm_context *etm_ctx;
|
||||||
char *tty;
|
char *tty;
|
||||||
int tty_fd;
|
int tty_fd;
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
* Free Software Foundation, Inc., *
|
* Free Software Foundation, Inc., *
|
||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -38,16 +39,14 @@
|
||||||
* may be separate registers associated with debug or trace modules.
|
* may be separate registers associated with debug or trace modules.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct reg* register_get_by_name(struct reg_cache *first,
|
struct reg *register_get_by_name(struct reg_cache *first,
|
||||||
const char *name, bool search_all)
|
const char *name, bool search_all)
|
||||||
{
|
{
|
||||||
unsigned i;
|
unsigned i;
|
||||||
struct reg_cache *cache = first;
|
struct reg_cache *cache = first;
|
||||||
|
|
||||||
while (cache)
|
while (cache) {
|
||||||
{
|
for (i = 0; i < cache->num_regs; i++) {
|
||||||
for (i = 0; i < cache->num_regs; i++)
|
|
||||||
{
|
|
||||||
if (strcmp(cache->reg_list[i].name, name) == 0)
|
if (strcmp(cache->reg_list[i].name, name) == 0)
|
||||||
return &(cache->reg_list[i]);
|
return &(cache->reg_list[i]);
|
||||||
}
|
}
|
||||||
|
@ -61,7 +60,7 @@ struct reg* register_get_by_name(struct reg_cache *first,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct reg_cache** register_get_last_cache_p(struct reg_cache **first)
|
struct reg_cache **register_get_last_cache_p(struct reg_cache **first)
|
||||||
{
|
{
|
||||||
struct reg_cache **cache_p = first;
|
struct reg_cache **cache_p = first;
|
||||||
|
|
||||||
|
|
|
@ -20,13 +20,13 @@
|
||||||
* Free Software Foundation, Inc., *
|
* Free Software Foundation, Inc., *
|
||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#ifndef REGISTER_H
|
#ifndef REGISTER_H
|
||||||
#define REGISTER_H
|
#define REGISTER_H
|
||||||
|
|
||||||
struct target;
|
struct target;
|
||||||
|
|
||||||
struct reg
|
struct reg {
|
||||||
{
|
|
||||||
const char *name;
|
const char *name;
|
||||||
void *value;
|
void *value;
|
||||||
bool dirty;
|
bool dirty;
|
||||||
|
@ -36,23 +36,21 @@ struct reg
|
||||||
const struct reg_arch_type *type;
|
const struct reg_arch_type *type;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct reg_cache
|
struct reg_cache {
|
||||||
{
|
|
||||||
const char *name;
|
const char *name;
|
||||||
struct reg_cache *next;
|
struct reg_cache *next;
|
||||||
struct reg *reg_list;
|
struct reg *reg_list;
|
||||||
unsigned num_regs;
|
unsigned num_regs;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct reg_arch_type
|
struct reg_arch_type {
|
||||||
{
|
|
||||||
int (*get)(struct reg *reg);
|
int (*get)(struct reg *reg);
|
||||||
int (*set)(struct reg *reg, uint8_t *buf);
|
int (*set)(struct reg *reg, uint8_t *buf);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct reg* register_get_by_name(struct reg_cache *first,
|
struct reg *register_get_by_name(struct reg_cache *first,
|
||||||
const char *name, bool search_all);
|
const char *name, bool search_all);
|
||||||
struct reg_cache** register_get_last_cache_p(struct reg_cache **first);
|
struct reg_cache **register_get_last_cache_p(struct reg_cache **first);
|
||||||
void register_cache_invalidate(struct reg_cache *cache);
|
void register_cache_invalidate(struct reg_cache *cache);
|
||||||
|
|
||||||
void register_init_dummy(struct reg *reg);
|
void register_init_dummy(struct reg *reg);
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
* Free Software Foundation, Inc., *
|
* Free Software Foundation, Inc., *
|
||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -29,7 +30,6 @@
|
||||||
#include "server/gdb_server.h"
|
#include "server/gdb_server.h"
|
||||||
#include "smp.h"
|
#include "smp.h"
|
||||||
|
|
||||||
|
|
||||||
/* implementation of new packet in gdb interface for smp feature */
|
/* implementation of new packet in gdb interface for smp feature */
|
||||||
/* */
|
/* */
|
||||||
/* j : smp status request */
|
/* j : smp status request */
|
||||||
|
@ -53,9 +53,8 @@
|
||||||
/* Another way to test this packet is the usage of maintenance packet */
|
/* Another way to test this packet is the usage of maintenance packet */
|
||||||
/* maint packet Jc01 */
|
/* maint packet Jc01 */
|
||||||
/* maint packet jc */
|
/* maint packet jc */
|
||||||
|
|
||||||
static const char DIGITS[16] = "0123456789abcdef";
|
|
||||||
|
|
||||||
|
static const char DIGITS[16] = "0123456789abcdef";
|
||||||
|
|
||||||
/* packet j :smp status request */
|
/* packet j :smp status request */
|
||||||
int gdb_read_smp_packet(struct connection *connection,
|
int gdb_read_smp_packet(struct connection *connection,
|
||||||
|
@ -66,15 +65,12 @@ int gdb_read_smp_packet(struct connection *connection,
|
||||||
uint8_t *buffer;
|
uint8_t *buffer;
|
||||||
char *hex_buffer;
|
char *hex_buffer;
|
||||||
int retval = ERROR_OK;
|
int retval = ERROR_OK;
|
||||||
if (target->smp)
|
if (target->smp) {
|
||||||
{
|
if (strstr(packet, "jc")) {
|
||||||
if (strstr(packet, "jc"))
|
|
||||||
{
|
|
||||||
hex_buffer = malloc(len * 2 + 1);
|
hex_buffer = malloc(len * 2 + 1);
|
||||||
buffer = (uint8_t *)&target->gdb_service->core[0];
|
buffer = (uint8_t *)&target->gdb_service->core[0];
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
for (i = 0; i < 4; i++)
|
for (i = 0; i < 4; i++) {
|
||||||
{
|
|
||||||
uint8_t t = buffer[i];
|
uint8_t t = buffer[i];
|
||||||
hex_buffer[2 * i] = DIGITS[(t >> 4) & 0xf];
|
hex_buffer[2 * i] = DIGITS[(t >> 4) & 0xf];
|
||||||
hex_buffer[2 * i + 1] = DIGITS[t & 0xf];
|
hex_buffer[2 * i + 1] = DIGITS[t & 0xf];
|
||||||
|
@ -84,9 +80,8 @@ int gdb_read_smp_packet(struct connection *connection,
|
||||||
|
|
||||||
free(hex_buffer);
|
free(hex_buffer);
|
||||||
}
|
}
|
||||||
}
|
} else
|
||||||
else
|
retval = gdb_put_packet(connection, "E01", 3);
|
||||||
retval = gdb_put_packet(connection,"E01",3);
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -100,20 +95,15 @@ int gdb_write_smp_packet(struct connection *connection,
|
||||||
int retval = ERROR_OK;
|
int retval = ERROR_OK;
|
||||||
|
|
||||||
/* skip command character */
|
/* skip command character */
|
||||||
if (target->smp)
|
if (target->smp) {
|
||||||
{
|
if (strstr(packet, "Jc")) {
|
||||||
if (strstr(packet, "Jc"))
|
packet += 2;
|
||||||
{
|
|
||||||
packet+=2;
|
|
||||||
coreid = strtoul(packet, &separator, 16);
|
coreid = strtoul(packet, &separator, 16);
|
||||||
target->gdb_service->core[1] = coreid;
|
target->gdb_service->core[1] = coreid;
|
||||||
retval = gdb_put_packet(connection, "OK", 2);
|
retval = gdb_put_packet(connection, "OK", 2);
|
||||||
}
|
}
|
||||||
}
|
} else
|
||||||
else
|
retval = gdb_put_packet(connection, "E01", 3);
|
||||||
{
|
|
||||||
retval = gdb_put_packet(connection,"E01",3);
|
|
||||||
}
|
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,9 @@
|
||||||
* Free Software Foundation, Inc., *
|
* Free Software Foundation, Inc., *
|
||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#include "server/server.h"
|
#include "server/server.h"
|
||||||
|
|
||||||
int gdb_read_smp_packet(struct connection *connection,
|
int gdb_read_smp_packet(struct connection *connection,
|
||||||
char *packet, int packet_size);
|
char *packet, int packet_size);
|
||||||
int gdb_write_smp_packet(struct connection *connection,
|
int gdb_write_smp_packet(struct connection *connection,
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
* Free Software Foundation, Inc., *
|
* Free Software Foundation, Inc., *
|
||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -42,8 +43,8 @@ static inline struct stlink_interface_s *target_to_stlink(struct target *target)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int stm32_stlink_load_core_reg_u32(struct target *target,
|
static int stm32_stlink_load_core_reg_u32(struct target *target,
|
||||||
enum armv7m_regtype type,
|
enum armv7m_regtype type,
|
||||||
uint32_t num, uint32_t *value)
|
uint32_t num, uint32_t *value)
|
||||||
{
|
{
|
||||||
int retval;
|
int retval;
|
||||||
struct stlink_interface_s *stlink_if = target_to_stlink(target);
|
struct stlink_interface_s *stlink_if = target_to_stlink(target);
|
||||||
|
@ -57,8 +58,7 @@ static int stm32_stlink_load_core_reg_u32(struct target *target,
|
||||||
switch (num) {
|
switch (num) {
|
||||||
case 0 ... 18:
|
case 0 ... 18:
|
||||||
/* read a normal core register */
|
/* read a normal core register */
|
||||||
retval =
|
retval = stlink_if->layout->api->read_reg(stlink_if->fd, num, value);
|
||||||
stlink_if->layout->api->read_reg(stlink_if->fd, num, value);
|
|
||||||
|
|
||||||
if (retval != ERROR_OK) {
|
if (retval != ERROR_OK) {
|
||||||
LOG_ERROR("JTAG failure %i", retval);
|
LOG_ERROR("JTAG failure %i", retval);
|
||||||
|
@ -76,8 +76,7 @@ static int stm32_stlink_load_core_reg_u32(struct target *target,
|
||||||
* in one Debug Core register. So say r0 and r2 docs;
|
* in one Debug Core register. So say r0 and r2 docs;
|
||||||
* it was removed from r1 docs, but still works.
|
* it was removed from r1 docs, but still works.
|
||||||
*/
|
*/
|
||||||
retval =
|
retval = stlink_if->layout->api->read_reg(stlink_if->fd, 20, value);
|
||||||
stlink_if->layout->api->read_reg(stlink_if->fd, 20, value);
|
|
||||||
|
|
||||||
switch (num) {
|
switch (num) {
|
||||||
case ARMV7M_PRIMASK:
|
case ARMV7M_PRIMASK:
|
||||||
|
@ -109,8 +108,8 @@ static int stm32_stlink_load_core_reg_u32(struct target *target,
|
||||||
}
|
}
|
||||||
|
|
||||||
static int stm32_stlink_store_core_reg_u32(struct target *target,
|
static int stm32_stlink_store_core_reg_u32(struct target *target,
|
||||||
enum armv7m_regtype type,
|
enum armv7m_regtype type,
|
||||||
uint32_t num, uint32_t value)
|
uint32_t num, uint32_t value)
|
||||||
{
|
{
|
||||||
int retval;
|
int retval;
|
||||||
uint32_t reg;
|
uint32_t reg;
|
||||||
|
@ -231,7 +230,7 @@ static int stm32_stlink_init_target(struct command_context *cmd_ctx,
|
||||||
}
|
}
|
||||||
|
|
||||||
static int stm32_stlink_target_create(struct target *target,
|
static int stm32_stlink_target_create(struct target *target,
|
||||||
Jim_Interp *interp)
|
Jim_Interp *interp)
|
||||||
{
|
{
|
||||||
LOG_DEBUG("%s", __func__);
|
LOG_DEBUG("%s", __func__);
|
||||||
|
|
||||||
|
@ -467,10 +466,8 @@ static int stm32_stlink_halt(struct target *target)
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (target->state == TARGET_UNKNOWN) {
|
if (target->state == TARGET_UNKNOWN)
|
||||||
LOG_WARNING
|
LOG_WARNING("target was in unknown state when halt was requested");
|
||||||
("target was in unknown state when halt was requested");
|
|
||||||
}
|
|
||||||
|
|
||||||
res = stlink_if->layout->api->halt(stlink_if->fd);
|
res = stlink_if->layout->api->halt(stlink_if->fd);
|
||||||
|
|
||||||
|
@ -483,8 +480,8 @@ static int stm32_stlink_halt(struct target *target)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int stm32_stlink_resume(struct target *target, int current,
|
static int stm32_stlink_resume(struct target *target, int current,
|
||||||
uint32_t address, int handle_breakpoints,
|
uint32_t address, int handle_breakpoints,
|
||||||
int debug_execution)
|
int debug_execution)
|
||||||
{
|
{
|
||||||
int res;
|
int res;
|
||||||
struct stlink_interface_s *stlink_if = target_to_stlink(target);
|
struct stlink_interface_s *stlink_if = target_to_stlink(target);
|
||||||
|
@ -494,7 +491,7 @@ static int stm32_stlink_resume(struct target *target, int current,
|
||||||
struct reg *pc;
|
struct reg *pc;
|
||||||
|
|
||||||
LOG_DEBUG("%s %d %x %d %d", __func__, current, address,
|
LOG_DEBUG("%s %d %x %d %d", __func__, current, address,
|
||||||
handle_breakpoints, debug_execution);
|
handle_breakpoints, debug_execution);
|
||||||
|
|
||||||
if (target->state != TARGET_HALTED) {
|
if (target->state != TARGET_HALTED) {
|
||||||
LOG_WARNING("target not halted");
|
LOG_WARNING("target not halted");
|
||||||
|
@ -526,8 +523,8 @@ static int stm32_stlink_resume(struct target *target, int current,
|
||||||
breakpoint = breakpoint_find(target, resume_pc);
|
breakpoint = breakpoint_find(target, resume_pc);
|
||||||
if (breakpoint) {
|
if (breakpoint) {
|
||||||
LOG_DEBUG("unset breakpoint at 0x%8.8" PRIx32 " (ID: %d)",
|
LOG_DEBUG("unset breakpoint at 0x%8.8" PRIx32 " (ID: %d)",
|
||||||
breakpoint->address,
|
breakpoint->address,
|
||||||
breakpoint->unique_id);
|
breakpoint->unique_id);
|
||||||
cortex_m3_unset_breakpoint(target, breakpoint);
|
cortex_m3_unset_breakpoint(target, breakpoint);
|
||||||
|
|
||||||
res = stlink_if->layout->api->step(stlink_if->fd);
|
res = stlink_if->layout->api->step(stlink_if->fd);
|
||||||
|
@ -552,7 +549,7 @@ static int stm32_stlink_resume(struct target *target, int current,
|
||||||
}
|
}
|
||||||
|
|
||||||
static int stm32_stlink_step(struct target *target, int current,
|
static int stm32_stlink_step(struct target *target, int current,
|
||||||
uint32_t address, int handle_breakpoints)
|
uint32_t address, int handle_breakpoints)
|
||||||
{
|
{
|
||||||
int res;
|
int res;
|
||||||
struct stlink_interface_s *stlink_if = target_to_stlink(target);
|
struct stlink_interface_s *stlink_if = target_to_stlink(target);
|
||||||
|
@ -613,8 +610,8 @@ static int stm32_stlink_step(struct target *target, int current,
|
||||||
}
|
}
|
||||||
|
|
||||||
static int stm32_stlink_read_memory(struct target *target, uint32_t address,
|
static int stm32_stlink_read_memory(struct target *target, uint32_t address,
|
||||||
uint32_t size, uint32_t count,
|
uint32_t size, uint32_t count,
|
||||||
uint8_t *buffer)
|
uint8_t *buffer)
|
||||||
{
|
{
|
||||||
int res;
|
int res;
|
||||||
uint32_t buffer_threshold = 128;
|
uint32_t buffer_threshold = 128;
|
||||||
|
@ -644,13 +641,11 @@ static int stm32_stlink_read_memory(struct target *target, uint32_t address,
|
||||||
c = count;
|
c = count;
|
||||||
|
|
||||||
if (size != 4)
|
if (size != 4)
|
||||||
res =
|
res = stlink_if->layout->api->read_mem8(stlink_if->fd,
|
||||||
stlink_if->layout->api->read_mem8(stlink_if->fd, address,
|
address, c, dst);
|
||||||
c, dst);
|
|
||||||
else
|
else
|
||||||
res =
|
res = stlink_if->layout->api->read_mem32(stlink_if->fd,
|
||||||
stlink_if->layout->api->read_mem32(stlink_if->fd, address,
|
address, c, (uint32_t *)dst);
|
||||||
c, (uint32_t *)dst);
|
|
||||||
|
|
||||||
if (res != ERROR_OK)
|
if (res != ERROR_OK)
|
||||||
return res;
|
return res;
|
||||||
|
@ -664,8 +659,8 @@ static int stm32_stlink_read_memory(struct target *target, uint32_t address,
|
||||||
}
|
}
|
||||||
|
|
||||||
static int stm32_stlink_write_memory(struct target *target, uint32_t address,
|
static int stm32_stlink_write_memory(struct target *target, uint32_t address,
|
||||||
uint32_t size, uint32_t count,
|
uint32_t size, uint32_t count,
|
||||||
const uint8_t *buffer)
|
const uint8_t *buffer)
|
||||||
{
|
{
|
||||||
int res;
|
int res;
|
||||||
uint32_t buffer_threshold = 128;
|
uint32_t buffer_threshold = 128;
|
||||||
|
@ -695,13 +690,11 @@ static int stm32_stlink_write_memory(struct target *target, uint32_t address,
|
||||||
c = count;
|
c = count;
|
||||||
|
|
||||||
if (size != 4)
|
if (size != 4)
|
||||||
res =
|
res = stlink_if->layout->api->write_mem8(stlink_if->fd,
|
||||||
stlink_if->layout->api->write_mem8(stlink_if->fd, address,
|
address, c, dst);
|
||||||
c, dst);
|
|
||||||
else
|
else
|
||||||
res =
|
res = stlink_if->layout->api->write_mem32(stlink_if->fd,
|
||||||
stlink_if->layout->api->write_mem32(stlink_if->fd, address,
|
address, c, (uint32_t *)dst);
|
||||||
c, (uint32_t *)dst);
|
|
||||||
|
|
||||||
if (res != ERROR_OK)
|
if (res != ERROR_OK)
|
||||||
return res;
|
return res;
|
||||||
|
@ -715,8 +708,8 @@ static int stm32_stlink_write_memory(struct target *target, uint32_t address,
|
||||||
}
|
}
|
||||||
|
|
||||||
static int stm32_stlink_bulk_write_memory(struct target *target,
|
static int stm32_stlink_bulk_write_memory(struct target *target,
|
||||||
uint32_t address, uint32_t count,
|
uint32_t address, uint32_t count,
|
||||||
const uint8_t *buffer)
|
const uint8_t *buffer)
|
||||||
{
|
{
|
||||||
return stm32_stlink_write_memory(target, address, 4, count, buffer);
|
return stm32_stlink_write_memory(target, address, 4, count, buffer);
|
||||||
}
|
}
|
||||||
|
|
1436
src/target/target.c
1436
src/target/target.c
File diff suppressed because it is too large
Load Diff
|
@ -29,6 +29,7 @@
|
||||||
* Free Software Foundation, Inc., *
|
* Free Software Foundation, Inc., *
|
||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#ifndef TARGET_H
|
#ifndef TARGET_H
|
||||||
#define TARGET_H
|
#define TARGET_H
|
||||||
|
|
||||||
|
@ -57,8 +58,7 @@ struct target_list;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
enum target_state
|
enum target_state {
|
||||||
{
|
|
||||||
TARGET_UNKNOWN = 0,
|
TARGET_UNKNOWN = 0,
|
||||||
TARGET_RUNNING = 1,
|
TARGET_RUNNING = 1,
|
||||||
TARGET_HALTED = 2,
|
TARGET_HALTED = 2,
|
||||||
|
@ -71,16 +71,14 @@ enum nvp_assert {
|
||||||
NVP_ASSERT,
|
NVP_ASSERT,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum target_reset_mode
|
enum target_reset_mode {
|
||||||
{
|
|
||||||
RESET_UNKNOWN = 0,
|
RESET_UNKNOWN = 0,
|
||||||
RESET_RUN = 1, /* reset and let target run */
|
RESET_RUN = 1, /* reset and let target run */
|
||||||
RESET_HALT = 2, /* reset and halt target out of reset */
|
RESET_HALT = 2, /* reset and halt target out of reset */
|
||||||
RESET_INIT = 3, /* reset and halt target out of reset, then run init script */
|
RESET_INIT = 3, /* reset and halt target out of reset, then run init script */
|
||||||
};
|
};
|
||||||
|
|
||||||
enum target_debug_reason
|
enum target_debug_reason {
|
||||||
{
|
|
||||||
DBG_REASON_DBGRQ = 0,
|
DBG_REASON_DBGRQ = 0,
|
||||||
DBG_REASON_BREAKPOINT = 1,
|
DBG_REASON_BREAKPOINT = 1,
|
||||||
DBG_REASON_WATCHPOINT = 2,
|
DBG_REASON_WATCHPOINT = 2,
|
||||||
|
@ -90,14 +88,12 @@ enum target_debug_reason
|
||||||
DBG_REASON_UNDEFINED = 6
|
DBG_REASON_UNDEFINED = 6
|
||||||
};
|
};
|
||||||
|
|
||||||
enum target_endianness
|
enum target_endianness {
|
||||||
{
|
|
||||||
TARGET_ENDIAN_UNKNOWN = 0,
|
TARGET_ENDIAN_UNKNOWN = 0,
|
||||||
TARGET_BIG_ENDIAN = 1, TARGET_LITTLE_ENDIAN = 2
|
TARGET_BIG_ENDIAN = 1, TARGET_LITTLE_ENDIAN = 2
|
||||||
};
|
};
|
||||||
|
|
||||||
struct working_area
|
struct working_area {
|
||||||
{
|
|
||||||
uint32_t address;
|
uint32_t address;
|
||||||
uint32_t size;
|
uint32_t size;
|
||||||
bool free;
|
bool free;
|
||||||
|
@ -105,26 +101,23 @@ struct working_area
|
||||||
struct working_area **user;
|
struct working_area **user;
|
||||||
struct working_area *next;
|
struct working_area *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct gdb_service
|
struct gdb_service {
|
||||||
{
|
|
||||||
struct target *target;
|
struct target *target;
|
||||||
/* field for smp display */
|
/* field for smp display */
|
||||||
/* element 0 coreid currently displayed ( 1 till n) */
|
/* element 0 coreid currently displayed ( 1 till n) */
|
||||||
/* element 1 coreid to be displayed at next resume 1 till n 0 means resume
|
/* element 1 coreid to be displayed at next resume 1 till n 0 means resume
|
||||||
* all cores
|
* all cores core displayed */
|
||||||
core displayed */
|
|
||||||
int32_t core[2];
|
int32_t core[2];
|
||||||
};
|
};
|
||||||
|
|
||||||
// target_type.h contains the full definitionof struct targe_type
|
/* target_type.h contains the full definitionof struct targe_type */
|
||||||
struct target
|
struct target {
|
||||||
{
|
struct target_type *type; /* target type definition (name, access functions) */
|
||||||
struct target_type *type; /* target type definition (name, access functions) */
|
|
||||||
const char *cmd_name; /* tcl Name of target */
|
const char *cmd_name; /* tcl Name of target */
|
||||||
int target_number; /* DO NOT USE! field to be removed in 2010 */
|
int target_number; /* DO NOT USE! field to be removed in 2010 */
|
||||||
struct jtag_tap *tap; /* where on the jtag chain is this */
|
struct jtag_tap *tap; /* where on the jtag chain is this */
|
||||||
int32_t coreid; /* which device on the TAP? */
|
int32_t coreid; /* which device on the TAP? */
|
||||||
const char *variant; /* what variant of this chip is it? */
|
const char *variant; /* what variant of this chip is it? */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -146,25 +139,25 @@ struct target
|
||||||
struct target_event_action *event_action;
|
struct target_event_action *event_action;
|
||||||
|
|
||||||
int reset_halt; /* attempt resetting the CPU into the halted mode? */
|
int reset_halt; /* attempt resetting the CPU into the halted mode? */
|
||||||
uint32_t working_area; /* working area (initialized RAM). Evaluated
|
uint32_t working_area; /* working area (initialized RAM). Evaluated
|
||||||
* upon first allocation from virtual/physical address. */
|
* upon first allocation from virtual/physical address. */
|
||||||
bool working_area_virt_spec; /* virtual address specified? */
|
bool working_area_virt_spec; /* virtual address specified? */
|
||||||
uint32_t working_area_virt; /* virtual address */
|
uint32_t working_area_virt; /* virtual address */
|
||||||
bool working_area_phys_spec; /* virtual address specified? */
|
bool working_area_phys_spec; /* virtual address specified? */
|
||||||
uint32_t working_area_phys; /* physical address */
|
uint32_t working_area_phys; /* physical address */
|
||||||
uint32_t working_area_size; /* size in bytes */
|
uint32_t working_area_size; /* size in bytes */
|
||||||
uint32_t backup_working_area; /* whether the content of the working area has to be preserved */
|
uint32_t backup_working_area; /* whether the content of the working area has to be preserved */
|
||||||
struct working_area *working_areas;/* list of allocated working areas */
|
struct working_area *working_areas;/* list of allocated working areas */
|
||||||
enum target_debug_reason debug_reason;/* reason why the target entered debug state */
|
enum target_debug_reason debug_reason;/* reason why the target entered debug state */
|
||||||
enum target_endianness endianness; /* target endianness */
|
enum target_endianness endianness; /* target endianness */
|
||||||
// also see: target_state_name()
|
/* also see: target_state_name() */
|
||||||
enum target_state state; /* the current backend-state (running, halted, ...) */
|
enum target_state state; /* the current backend-state (running, halted, ...) */
|
||||||
struct reg_cache *reg_cache; /* the first register cache of the target (core regs) */
|
struct reg_cache *reg_cache; /* the first register cache of the target (core regs) */
|
||||||
struct breakpoint *breakpoints; /* list of breakpoints */
|
struct breakpoint *breakpoints; /* list of breakpoints */
|
||||||
struct watchpoint *watchpoints; /* list of watchpoints */
|
struct watchpoint *watchpoints; /* list of watchpoints */
|
||||||
struct trace *trace_info; /* generic trace information */
|
struct trace *trace_info; /* generic trace information */
|
||||||
struct debug_msg_receiver *dbgmsg;/* list of debug message receivers */
|
struct debug_msg_receiver *dbgmsg; /* list of debug message receivers */
|
||||||
uint32_t dbg_msg_enabled; /* debug message status */
|
uint32_t dbg_msg_enabled; /* debug message status */
|
||||||
void *arch_info; /* architecture specific information */
|
void *arch_info; /* architecture specific information */
|
||||||
struct target *next; /* next target in list */
|
struct target *next; /* next target in list */
|
||||||
|
|
||||||
|
@ -175,13 +168,13 @@ struct target
|
||||||
|
|
||||||
bool dbgbase_set; /* By default the debug base is not set */
|
bool dbgbase_set; /* By default the debug base is not set */
|
||||||
uint32_t dbgbase; /* Really a Cortex-A specific option, but there is no
|
uint32_t dbgbase; /* Really a Cortex-A specific option, but there is no
|
||||||
system in place to support target specific options
|
system in place to support target specific options
|
||||||
currently. */
|
currently. */
|
||||||
struct rtos *rtos; /* Instance of Real Time Operating System support */
|
struct rtos *rtos; /* Instance of Real Time Operating System support */
|
||||||
bool rtos_auto_detect; /* A flag that indicates that the RTOS has been specified as "auto"
|
bool rtos_auto_detect; /* A flag that indicates that the RTOS has been specified as "auto"
|
||||||
* and must be detected when symbols are offered */
|
* and must be detected when symbols are offered */
|
||||||
|
|
||||||
int smp; /* add some target attributes for smp support */
|
int smp; /* add some target attributes for smp support */
|
||||||
struct target_list *head;
|
struct target_list *head;
|
||||||
/* the gdb service is there in case of smp , we have only one gdb server
|
/* the gdb service is there in case of smp , we have only one gdb server
|
||||||
* for all smp target
|
* for all smp target
|
||||||
|
@ -190,7 +183,6 @@ struct target
|
||||||
struct gdb_service *gdb_service;
|
struct gdb_service *gdb_service;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
struct target_list {
|
struct target_list {
|
||||||
struct target *target;
|
struct target *target;
|
||||||
struct target_list *next;
|
struct target_list *next;
|
||||||
|
@ -204,8 +196,7 @@ static inline const char *target_name(struct target *target)
|
||||||
|
|
||||||
const char *debug_reason_name(struct target *t);
|
const char *debug_reason_name(struct target *t);
|
||||||
|
|
||||||
enum target_event
|
enum target_event {
|
||||||
{
|
|
||||||
/* LD historical names
|
/* LD historical names
|
||||||
* - Prior to the great TCL change
|
* - Prior to the great TCL change
|
||||||
* - June/July/Aug 2008
|
* - June/July/Aug 2008
|
||||||
|
@ -269,15 +260,13 @@ struct target_event_action {
|
||||||
|
|
||||||
bool target_has_event_action(struct target *target, enum target_event event);
|
bool target_has_event_action(struct target *target, enum target_event event);
|
||||||
|
|
||||||
struct target_event_callback
|
struct target_event_callback {
|
||||||
{
|
|
||||||
int (*callback)(struct target *target, enum target_event event, void *priv);
|
int (*callback)(struct target *target, enum target_event event, void *priv);
|
||||||
void *priv;
|
void *priv;
|
||||||
struct target_event_callback *next;
|
struct target_event_callback *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct target_timer_callback
|
struct target_timer_callback {
|
||||||
{
|
|
||||||
int (*callback)(void *priv);
|
int (*callback)(void *priv);
|
||||||
int time_ms;
|
int time_ms;
|
||||||
int periodic;
|
int periodic;
|
||||||
|
@ -291,11 +280,11 @@ int target_examine(void);
|
||||||
|
|
||||||
int target_register_event_callback(
|
int target_register_event_callback(
|
||||||
int (*callback)(struct target *target,
|
int (*callback)(struct target *target,
|
||||||
enum target_event event, void *priv),
|
enum target_event event, void *priv),
|
||||||
void *priv);
|
void *priv);
|
||||||
int target_unregister_event_callback(
|
int target_unregister_event_callback(
|
||||||
int (*callback)(struct target *target,
|
int (*callback)(struct target *target,
|
||||||
enum target_event event, void *priv),
|
enum target_event event, void *priv),
|
||||||
void *priv);
|
void *priv);
|
||||||
/* Poll the status of the target, detect any error conditions and report them.
|
/* Poll the status of the target, detect any error conditions and report them.
|
||||||
*
|
*
|
||||||
|
@ -329,7 +318,7 @@ int target_call_timer_callbacks(void);
|
||||||
*/
|
*/
|
||||||
int target_call_timer_callbacks_now(void);
|
int target_call_timer_callbacks_now(void);
|
||||||
|
|
||||||
struct target* get_current_target(struct command_context *cmd_ctx);
|
struct target *get_current_target(struct command_context *cmd_ctx);
|
||||||
struct target *get_target(const char *id);
|
struct target *get_target(const char *id);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -348,14 +337,14 @@ const char *target_type_name(struct target *target);
|
||||||
*/
|
*/
|
||||||
int target_examine_one(struct target *target);
|
int target_examine_one(struct target *target);
|
||||||
|
|
||||||
/// @returns @c true if target_set_examined() has been called.
|
/** @returns @c true if target_set_examined() has been called. */
|
||||||
static inline bool target_was_examined(struct target *target)
|
static inline bool target_was_examined(struct target *target)
|
||||||
{
|
{
|
||||||
return target->examined;
|
return target->examined;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets the @c examined flag for the given target.
|
/** Sets the @c examined flag for the given target. */
|
||||||
/// Use in target->type->examine() after one-time setup is done.
|
/** Use in target->type->examine() after one-time setup is done. */
|
||||||
static inline void target_set_examined(struct target *target)
|
static inline void target_set_examined(struct target *target)
|
||||||
{
|
{
|
||||||
target->examined = true;
|
target->examined = true;
|
||||||
|
@ -520,13 +509,13 @@ int target_write_buffer(struct target *target,
|
||||||
int target_read_buffer(struct target *target,
|
int target_read_buffer(struct target *target,
|
||||||
uint32_t address, uint32_t size, uint8_t *buffer);
|
uint32_t address, uint32_t size, uint8_t *buffer);
|
||||||
int target_checksum_memory(struct target *target,
|
int target_checksum_memory(struct target *target,
|
||||||
uint32_t address, uint32_t size, uint32_t* crc);
|
uint32_t address, uint32_t size, uint32_t *crc);
|
||||||
int target_blank_check_memory(struct target *target,
|
int target_blank_check_memory(struct target *target,
|
||||||
uint32_t address, uint32_t size, uint32_t* blank);
|
uint32_t address, uint32_t size, uint32_t *blank);
|
||||||
int target_wait_state(struct target *target, enum target_state state, int ms);
|
int target_wait_state(struct target *target, enum target_state state, int ms);
|
||||||
|
|
||||||
/** Return the *name* of this targets current state */
|
/** Return the *name* of this targets current state */
|
||||||
const char *target_state_name( struct target *target );
|
const char *target_state_name(struct target *target);
|
||||||
|
|
||||||
/* DANGER!!!!!
|
/* DANGER!!!!!
|
||||||
*
|
*
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue