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
|
||||||
|
|
||||||
|
|
|
@ -38,7 +38,6 @@
|
||||||
#include "register.h"
|
#include "register.h"
|
||||||
#include "arm_opcodes.h"
|
#include "arm_opcodes.h"
|
||||||
|
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
#define _DEBUG_INSTRUCTION_EXECUTION_
|
#define _DEBUG_INSTRUCTION_EXECUTION_
|
||||||
#endif
|
#endif
|
||||||
|
@ -56,8 +55,7 @@ static int arm11_check_init(struct arm11_common *arm11)
|
||||||
{
|
{
|
||||||
CHECK_RETVAL(arm11_read_DSCR(arm11));
|
CHECK_RETVAL(arm11_read_DSCR(arm11));
|
||||||
|
|
||||||
if (!(arm11->dscr & DSCR_HALT_DBG_MODE))
|
if (!(arm11->dscr & DSCR_HALT_DBG_MODE)) {
|
||||||
{
|
|
||||||
LOG_DEBUG("DSCR %08x", (unsigned) arm11->dscr);
|
LOG_DEBUG("DSCR %08x", (unsigned) arm11->dscr);
|
||||||
LOG_DEBUG("Bringing target into debug mode");
|
LOG_DEBUG("Bringing target into debug mode");
|
||||||
|
|
||||||
|
@ -68,8 +66,7 @@ static int arm11_check_init(struct arm11_common *arm11)
|
||||||
|
|
||||||
arm11->simulate_reset_on_next_halt = true;
|
arm11->simulate_reset_on_next_halt = true;
|
||||||
|
|
||||||
if (arm11->dscr & DSCR_CORE_HALTED)
|
if (arm11->dscr & DSCR_CORE_HALTED) {
|
||||||
{
|
|
||||||
/** \todo TODO: this needs further scrutiny because
|
/** \todo TODO: this needs further scrutiny because
|
||||||
* arm11_debug_entry() never gets called. (WHY NOT?)
|
* arm11_debug_entry() never gets called. (WHY NOT?)
|
||||||
* As a result we don't read the actual register states from
|
* As a result we don't read the actual register states from
|
||||||
|
@ -78,9 +75,7 @@ static int arm11_check_init(struct arm11_common *arm11)
|
||||||
|
|
||||||
arm11->arm.target->state = TARGET_HALTED;
|
arm11->arm.target->state = TARGET_HALTED;
|
||||||
arm_dpm_report_dscr(arm11->arm.dpm, arm11->dscr);
|
arm_dpm_report_dscr(arm11->arm.dpm, arm11->dscr);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
arm11->arm.target->state = TARGET_RUNNING;
|
arm11->arm.target->state = TARGET_RUNNING;
|
||||||
arm11->arm.target->debug_reason = DBG_REASON_NOTHALTED;
|
arm11->arm.target->debug_reason = DBG_REASON_NOTHALTED;
|
||||||
}
|
}
|
||||||
|
@ -110,8 +105,7 @@ static int arm11_debug_entry(struct arm11_common *arm11)
|
||||||
|
|
||||||
/* maybe save wDTR (pending DCC write to debug SW, e.g. libdcc) */
|
/* maybe save wDTR (pending DCC write to debug SW, e.g. libdcc) */
|
||||||
arm11->is_wdtr_saved = !!(arm11->dscr & DSCR_DTR_TX_FULL);
|
arm11->is_wdtr_saved = !!(arm11->dscr & DSCR_DTR_TX_FULL);
|
||||||
if (arm11->is_wdtr_saved)
|
if (arm11->is_wdtr_saved) {
|
||||||
{
|
|
||||||
arm11_add_debug_SCAN_N(arm11, 0x05, ARM11_TAP_DEFAULT);
|
arm11_add_debug_SCAN_N(arm11, 0x05, ARM11_TAP_DEFAULT);
|
||||||
|
|
||||||
arm11_add_IR(arm11, ARM11_INTEST, ARM11_TAP_DEFAULT);
|
arm11_add_IR(arm11, ARM11_INTEST, ARM11_TAP_DEFAULT);
|
||||||
|
@ -123,7 +117,8 @@ static int arm11_debug_entry(struct arm11_common *arm11)
|
||||||
arm11_setup_field(arm11, 1, NULL, NULL, chain5_fields + 1);
|
arm11_setup_field(arm11, 1, NULL, NULL, chain5_fields + 1);
|
||||||
arm11_setup_field(arm11, 1, NULL, NULL, chain5_fields + 2);
|
arm11_setup_field(arm11, 1, NULL, NULL, chain5_fields + 2);
|
||||||
|
|
||||||
arm11_add_dr_scan_vc(arm11->arm.target->tap, ARRAY_SIZE(chain5_fields), chain5_fields, TAP_DRPAUSE);
|
arm11_add_dr_scan_vc(arm11->arm.target->tap, ARRAY_SIZE(
|
||||||
|
chain5_fields), chain5_fields, TAP_DRPAUSE);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -143,10 +138,9 @@ static int arm11_debug_entry(struct arm11_common *arm11)
|
||||||
/** \todo TODO: Test drain write buffer. */
|
/** \todo TODO: Test drain write buffer. */
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
while (1)
|
while (1) {
|
||||||
{
|
|
||||||
/* MRC p14,0,R0,c5,c10,0 */
|
/* MRC p14,0,R0,c5,c10,0 */
|
||||||
// arm11_run_instr_no_data1(arm11, /*0xee150e1a*/0xe320f000);
|
/* arm11_run_instr_no_data1(arm11, / *0xee150e1a* /0xe320f000); */
|
||||||
|
|
||||||
/* mcr 15, 0, r0, cr7, cr10, {4} */
|
/* mcr 15, 0, r0, cr7, cr10, {4} */
|
||||||
arm11_run_instr_no_data1(arm11, 0xee070f9a);
|
arm11_run_instr_no_data1(arm11, 0xee070f9a);
|
||||||
|
@ -155,8 +149,7 @@ static int arm11_debug_entry(struct arm11_common *arm11)
|
||||||
|
|
||||||
LOG_DEBUG("DRAIN, DSCR %08x", dscr);
|
LOG_DEBUG("DRAIN, DSCR %08x", dscr);
|
||||||
|
|
||||||
if (dscr & ARM11_DSCR_STICKY_IMPRECISE_DATA_ABORT)
|
if (dscr & ARM11_DSCR_STICKY_IMPRECISE_DATA_ABORT) {
|
||||||
{
|
|
||||||
arm11_run_instr_no_data1(arm11, 0xe320f000);
|
arm11_run_instr_no_data1(arm11, 0xe320f000);
|
||||||
|
|
||||||
dscr = arm11_read_DSCR(arm11);
|
dscr = arm11_read_DSCR(arm11);
|
||||||
|
@ -183,8 +176,7 @@ static int arm11_debug_entry(struct arm11_common *arm11)
|
||||||
|
|
||||||
/* maybe save rDTR (pending DCC read from debug SW, e.g. libdcc) */
|
/* maybe save rDTR (pending DCC read from debug SW, e.g. libdcc) */
|
||||||
arm11->is_rdtr_saved = !!(arm11->dscr & DSCR_DTR_RX_FULL);
|
arm11->is_rdtr_saved = !!(arm11->dscr & DSCR_DTR_RX_FULL);
|
||||||
if (arm11->is_rdtr_saved)
|
if (arm11->is_rdtr_saved) {
|
||||||
{
|
|
||||||
/* MRC p14,0,R0,c0,c5,0 (move rDTR -> r0 (-> wDTR -> local var)) */
|
/* MRC p14,0,R0,c0,c5,0 (move rDTR -> r0 (-> wDTR -> local var)) */
|
||||||
retval = arm11_run_instr_data_from_core_via_r0(arm11,
|
retval = arm11_run_instr_data_from_core_via_r0(arm11,
|
||||||
0xEE100E15, &arm11->saved_rdtr);
|
0xEE100E15, &arm11->saved_rdtr);
|
||||||
|
@ -196,8 +188,7 @@ static int arm11_debug_entry(struct arm11_common *arm11)
|
||||||
* be MMU and cache state to care about ...
|
* be MMU and cache state to care about ...
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (arm11->simulate_reset_on_next_halt)
|
if (arm11->simulate_reset_on_next_halt) {
|
||||||
{
|
|
||||||
arm11->simulate_reset_on_next_halt = false;
|
arm11->simulate_reset_on_next_halt = false;
|
||||||
|
|
||||||
LOG_DEBUG("Reset c1 Control Register");
|
LOG_DEBUG("Reset c1 Control Register");
|
||||||
|
@ -255,8 +246,7 @@ static int arm11_leave_debug_state(struct arm11_common *arm11, bool bpwp)
|
||||||
{
|
{
|
||||||
CHECK_RETVAL(arm11_read_DSCR(arm11));
|
CHECK_RETVAL(arm11_read_DSCR(arm11));
|
||||||
|
|
||||||
if (arm11->dscr & (DSCR_DTR_RX_FULL | DSCR_DTR_TX_FULL))
|
if (arm11->dscr & (DSCR_DTR_RX_FULL | DSCR_DTR_TX_FULL)) {
|
||||||
{
|
|
||||||
/*
|
/*
|
||||||
The wDTR/rDTR two registers that are used to send/receive data to/from
|
The wDTR/rDTR two registers that are used to send/receive data to/from
|
||||||
the core in tandem with corresponding instruction codes that are
|
the core in tandem with corresponding instruction codes that are
|
||||||
|
@ -271,8 +261,7 @@ static int arm11_leave_debug_state(struct arm11_common *arm11, bool bpwp)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* maybe restore original wDTR */
|
/* maybe restore original wDTR */
|
||||||
if (arm11->is_wdtr_saved)
|
if (arm11->is_wdtr_saved) {
|
||||||
{
|
|
||||||
retval = arm11_run_instr_data_prepare(arm11);
|
retval = arm11_run_instr_data_prepare(arm11);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
@ -301,8 +290,7 @@ static int arm11_leave_debug_state(struct arm11_common *arm11, bool bpwp)
|
||||||
CHECK_RETVAL(arm11_write_DSCR(arm11, arm11->dscr));
|
CHECK_RETVAL(arm11_write_DSCR(arm11, arm11->dscr));
|
||||||
|
|
||||||
/* maybe restore rDTR */
|
/* maybe restore rDTR */
|
||||||
if (arm11->is_rdtr_saved)
|
if (arm11->is_rdtr_saved) {
|
||||||
{
|
|
||||||
arm11_add_debug_SCAN_N(arm11, 0x05, ARM11_TAP_DEFAULT);
|
arm11_add_debug_SCAN_N(arm11, 0x05, ARM11_TAP_DEFAULT);
|
||||||
|
|
||||||
arm11_add_IR(arm11, ARM11_EXTEST, ARM11_TAP_DEFAULT);
|
arm11_add_IR(arm11, ARM11_EXTEST, ARM11_TAP_DEFAULT);
|
||||||
|
@ -317,7 +305,8 @@ static int arm11_leave_debug_state(struct arm11_common *arm11, bool bpwp)
|
||||||
arm11_setup_field(arm11, 1, &Ready, NULL, chain5_fields + 1);
|
arm11_setup_field(arm11, 1, &Ready, NULL, chain5_fields + 1);
|
||||||
arm11_setup_field(arm11, 1, &Valid, NULL, chain5_fields + 2);
|
arm11_setup_field(arm11, 1, &Valid, NULL, chain5_fields + 2);
|
||||||
|
|
||||||
arm11_add_dr_scan_vc(arm11->arm.target->tap, ARRAY_SIZE(chain5_fields), chain5_fields, TAP_DRPAUSE);
|
arm11_add_dr_scan_vc(arm11->arm.target->tap, ARRAY_SIZE(
|
||||||
|
chain5_fields), chain5_fields, TAP_DRPAUSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* now processor is ready to RESTART */
|
/* now processor is ready to RESTART */
|
||||||
|
@ -333,10 +322,8 @@ static int arm11_poll(struct target *target)
|
||||||
|
|
||||||
CHECK_RETVAL(arm11_check_init(arm11));
|
CHECK_RETVAL(arm11_check_init(arm11));
|
||||||
|
|
||||||
if (arm11->dscr & DSCR_CORE_HALTED)
|
if (arm11->dscr & DSCR_CORE_HALTED) {
|
||||||
{
|
if (target->state != TARGET_HALTED) {
|
||||||
if (target->state != TARGET_HALTED)
|
|
||||||
{
|
|
||||||
enum target_state old_state = target->state;
|
enum target_state old_state = target->state;
|
||||||
|
|
||||||
LOG_DEBUG("enter TARGET_HALTED");
|
LOG_DEBUG("enter TARGET_HALTED");
|
||||||
|
@ -349,11 +336,8 @@ static int arm11_poll(struct target *target)
|
||||||
? TARGET_EVENT_DEBUG_HALTED
|
? TARGET_EVENT_DEBUG_HALTED
|
||||||
: TARGET_EVENT_HALTED);
|
: TARGET_EVENT_HALTED);
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
if (target->state != TARGET_RUNNING && target->state != TARGET_DEBUG_RUNNING) {
|
||||||
{
|
|
||||||
if (target->state != TARGET_RUNNING && target->state != TARGET_DEBUG_RUNNING)
|
|
||||||
{
|
|
||||||
LOG_DEBUG("enter TARGET_RUNNING");
|
LOG_DEBUG("enter TARGET_RUNNING");
|
||||||
target->state = TARGET_RUNNING;
|
target->state = TARGET_RUNNING;
|
||||||
target->debug_reason = DBG_REASON_NOTHALTED;
|
target->debug_reason = DBG_REASON_NOTHALTED;
|
||||||
|
@ -397,12 +381,9 @@ static int arm11_halt(struct target *target)
|
||||||
target_state_name(target));
|
target_state_name(target));
|
||||||
|
|
||||||
if (target->state == TARGET_UNKNOWN)
|
if (target->state == TARGET_UNKNOWN)
|
||||||
{
|
|
||||||
arm11->simulate_reset_on_next_halt = true;
|
arm11->simulate_reset_on_next_halt = true;
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
@ -413,8 +394,7 @@ static int arm11_halt(struct target *target)
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
while (1)
|
while (1) {
|
||||||
{
|
|
||||||
CHECK_RETVAL(arm11_read_DSCR(arm11));
|
CHECK_RETVAL(arm11_read_DSCR(arm11));
|
||||||
|
|
||||||
if (arm11->dscr & DSCR_CORE_HALTED)
|
if (arm11->dscr & DSCR_CORE_HALTED)
|
||||||
|
@ -423,13 +403,9 @@ static int arm11_halt(struct target *target)
|
||||||
|
|
||||||
long long then = 0;
|
long long then = 0;
|
||||||
if (i == 1000)
|
if (i == 1000)
|
||||||
{
|
|
||||||
then = timeval_ms();
|
then = timeval_ms();
|
||||||
}
|
if (i >= 1000) {
|
||||||
if (i >= 1000)
|
if ((timeval_ms()-then) > 1000) {
|
||||||
{
|
|
||||||
if ((timeval_ms()-then) > 1000)
|
|
||||||
{
|
|
||||||
LOG_WARNING("Timeout (1000ms) waiting for instructions to complete");
|
LOG_WARNING("Timeout (1000ms) waiting for instructions to complete");
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
@ -443,13 +419,13 @@ static int arm11_halt(struct target *target)
|
||||||
|
|
||||||
CHECK_RETVAL(
|
CHECK_RETVAL(
|
||||||
target_call_event_callbacks(target,
|
target_call_event_callbacks(target,
|
||||||
old_state == TARGET_DEBUG_RUNNING ? TARGET_EVENT_DEBUG_HALTED : TARGET_EVENT_HALTED));
|
old_state ==
|
||||||
|
TARGET_DEBUG_RUNNING ? TARGET_EVENT_DEBUG_HALTED : TARGET_EVENT_HALTED));
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t
|
static uint32_t arm11_nextpc(struct arm11_common *arm11, int current, uint32_t address)
|
||||||
arm11_nextpc(struct arm11_common *arm11, int current, uint32_t address)
|
|
||||||
{
|
{
|
||||||
void *value = arm11->arm.pc->value;
|
void *value = arm11->arm.pc->value;
|
||||||
|
|
||||||
|
@ -464,8 +440,8 @@ arm11_nextpc(struct arm11_common *arm11, int current, uint32_t address)
|
||||||
static int arm11_resume(struct target *target, int current,
|
static int arm11_resume(struct target *target, int current,
|
||||||
uint32_t address, int handle_breakpoints, int debug_execution)
|
uint32_t address, int handle_breakpoints, int debug_execution)
|
||||||
{
|
{
|
||||||
// LOG_DEBUG("current %d address %08x handle_breakpoints %d debug_execution %d",
|
/* LOG_DEBUG("current %d address %08x handle_breakpoints %d debug_execution %d", */
|
||||||
// current, address, handle_breakpoints, debug_execution);
|
/* current, address, handle_breakpoints, debug_execution); */
|
||||||
|
|
||||||
struct arm11_common *arm11 = target_to_arm11(target);
|
struct arm11_common *arm11 = target_to_arm11(target);
|
||||||
|
|
||||||
|
@ -473,8 +449,7 @@ static int arm11_resume(struct target *target, int current,
|
||||||
target_state_name(target));
|
target_state_name(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;
|
||||||
}
|
}
|
||||||
|
@ -493,10 +468,8 @@ static int arm11_resume(struct target *target, int current,
|
||||||
if (handle_breakpoints) {
|
if (handle_breakpoints) {
|
||||||
struct breakpoint *bp;
|
struct breakpoint *bp;
|
||||||
|
|
||||||
for (bp = target->breakpoints; bp; bp = bp->next)
|
for (bp = target->breakpoints; bp; bp = bp->next) {
|
||||||
{
|
if (bp->address == address) {
|
||||||
if (bp->address == address)
|
|
||||||
{
|
|
||||||
LOG_DEBUG("must step over %08" PRIx32 "", bp->address);
|
LOG_DEBUG("must step over %08" PRIx32 "", bp->address);
|
||||||
arm11_step(target, 1, 0, 0);
|
arm11_step(target, 1, 0, 0);
|
||||||
break;
|
break;
|
||||||
|
@ -509,8 +482,7 @@ static int arm11_resume(struct target *target, int current,
|
||||||
struct breakpoint *bp;
|
struct breakpoint *bp;
|
||||||
unsigned brp_num = 0;
|
unsigned brp_num = 0;
|
||||||
|
|
||||||
for (bp = target->breakpoints; bp; bp = bp->next)
|
for (bp = target->breakpoints; bp; bp = bp->next) {
|
||||||
{
|
|
||||||
struct arm11_sc7_action brp[2];
|
struct arm11_sc7_action brp[2];
|
||||||
|
|
||||||
brp[0].write = 1;
|
brp[0].write = 1;
|
||||||
|
@ -518,7 +490,9 @@ static int arm11_resume(struct target *target, int current,
|
||||||
brp[0].value = bp->address;
|
brp[0].value = bp->address;
|
||||||
brp[1].write = 1;
|
brp[1].write = 1;
|
||||||
brp[1].address = ARM11_SC7_BCR0 + brp_num;
|
brp[1].address = ARM11_SC7_BCR0 + brp_num;
|
||||||
brp[1].value = 0x1 | (3 << 1) | (0x0F << 5) | (0 << 14) | (0 << 16) | (0 << 20) | (0 << 21);
|
brp[1].value = 0x1 |
|
||||||
|
(3 <<
|
||||||
|
1) | (0x0F << 5) | (0 << 14) | (0 << 16) | (0 << 20) | (0 << 21);
|
||||||
|
|
||||||
CHECK_RETVAL(arm11_sc7_run(arm11, brp, ARRAY_SIZE(brp)));
|
CHECK_RETVAL(arm11_sc7_run(arm11, brp, ARRAY_SIZE(brp)));
|
||||||
|
|
||||||
|
@ -540,8 +514,7 @@ static int arm11_resume(struct target *target, int current,
|
||||||
CHECK_RETVAL(jtag_execute_queue());
|
CHECK_RETVAL(jtag_execute_queue());
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
while (1)
|
while (1) {
|
||||||
{
|
|
||||||
CHECK_RETVAL(arm11_read_DSCR(arm11));
|
CHECK_RETVAL(arm11_read_DSCR(arm11));
|
||||||
|
|
||||||
LOG_DEBUG("DSCR %08x", (unsigned) arm11->dscr);
|
LOG_DEBUG("DSCR %08x", (unsigned) arm11->dscr);
|
||||||
|
@ -552,13 +525,9 @@ static int arm11_resume(struct target *target, int current,
|
||||||
|
|
||||||
long long then = 0;
|
long long then = 0;
|
||||||
if (i == 1000)
|
if (i == 1000)
|
||||||
{
|
|
||||||
then = timeval_ms();
|
then = timeval_ms();
|
||||||
}
|
if (i >= 1000) {
|
||||||
if (i >= 1000)
|
if ((timeval_ms()-then) > 1000) {
|
||||||
{
|
|
||||||
if ((timeval_ms()-then) > 1000)
|
|
||||||
{
|
|
||||||
LOG_WARNING("Timeout (1000ms) waiting for instructions to complete");
|
LOG_WARNING("Timeout (1000ms) waiting for instructions to complete");
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
@ -582,8 +551,7 @@ static int arm11_step(struct target *target, int current,
|
||||||
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_WARNING("target was not halted");
|
LOG_WARNING("target was not halted");
|
||||||
return ERROR_TARGET_NOT_HALTED;
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
}
|
}
|
||||||
|
@ -602,25 +570,20 @@ static int arm11_step(struct target *target, int current,
|
||||||
CHECK_RETVAL(arm11_read_memory_word(arm11, address, &next_instruction));
|
CHECK_RETVAL(arm11_read_memory_word(arm11, address, &next_instruction));
|
||||||
|
|
||||||
/* skip over BKPT */
|
/* skip over BKPT */
|
||||||
if ((next_instruction & 0xFFF00070) == 0xe1200070)
|
if ((next_instruction & 0xFFF00070) == 0xe1200070) {
|
||||||
{
|
|
||||||
address = arm11_nextpc(arm11, 0, address + 4);
|
address = arm11_nextpc(arm11, 0, address + 4);
|
||||||
LOG_DEBUG("Skipping BKPT %08" PRIx32, address);
|
LOG_DEBUG("Skipping BKPT %08" PRIx32, address);
|
||||||
}
|
}
|
||||||
/* skip over Wait for interrupt / Standby */
|
/* skip over Wait for interrupt / Standby
|
||||||
/* mcr 15, 0, r?, cr7, cr0, {4} */
|
* mcr 15, 0, r?, cr7, cr0, {4} */
|
||||||
else if ((next_instruction & 0xFFFF0FFF) == 0xee070f90)
|
else if ((next_instruction & 0xFFFF0FFF) == 0xee070f90) {
|
||||||
{
|
|
||||||
address = arm11_nextpc(arm11, 0, address + 4);
|
address = arm11_nextpc(arm11, 0, address + 4);
|
||||||
LOG_DEBUG("Skipping WFI %08" PRIx32, address);
|
LOG_DEBUG("Skipping WFI %08" PRIx32, address);
|
||||||
}
|
}
|
||||||
/* ignore B to self */
|
/* ignore B to self */
|
||||||
else if ((next_instruction & 0xFEFFFFFF) == 0xeafffffe)
|
else if ((next_instruction & 0xFEFFFFFF) == 0xeafffffe)
|
||||||
{
|
|
||||||
LOG_DEBUG("Not stepping jump to self");
|
LOG_DEBUG("Not stepping jump to self");
|
||||||
}
|
else {
|
||||||
else
|
|
||||||
{
|
|
||||||
/** \todo TODO: check if break-/watchpoints make any sense at all in combination
|
/** \todo TODO: check if break-/watchpoints make any sense at all in combination
|
||||||
* with this. */
|
* with this. */
|
||||||
|
|
||||||
|
@ -637,8 +600,7 @@ static int arm11_step(struct target *target, int current,
|
||||||
brp[1].write = 1;
|
brp[1].write = 1;
|
||||||
brp[1].address = ARM11_SC7_BCR0;
|
brp[1].address = ARM11_SC7_BCR0;
|
||||||
|
|
||||||
if (arm11->hardware_step)
|
if (arm11->hardware_step) {
|
||||||
{
|
|
||||||
/* Hardware single stepping ("instruction address
|
/* Hardware single stepping ("instruction address
|
||||||
* mismatch") is used if enabled. It's not quite
|
* mismatch") is used if enabled. It's not quite
|
||||||
* exactly "run one instruction"; "branch to here"
|
* exactly "run one instruction"; "branch to here"
|
||||||
|
@ -655,8 +617,7 @@ static int arm11_step(struct target *target, int current,
|
||||||
brp[1].value = 0x1 | (3 << 1) | (0x0F << 5)
|
brp[1].value = 0x1 | (3 << 1) | (0x0F << 5)
|
||||||
| (0 << 14) | (0 << 16) | (0 << 20)
|
| (0 << 14) | (0 << 16) | (0 << 20)
|
||||||
| (2 << 21);
|
| (2 << 21);
|
||||||
} else
|
} else {
|
||||||
{
|
|
||||||
/* Sets a breakpoint on the next PC, as calculated
|
/* Sets a breakpoint on the next PC, as calculated
|
||||||
* by instruction set simulation.
|
* by instruction set simulation.
|
||||||
*
|
*
|
||||||
|
@ -697,8 +658,7 @@ static int arm11_step(struct target *target, int current,
|
||||||
/* wait for halt */
|
/* wait for halt */
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
while (1)
|
while (1) {
|
||||||
{
|
|
||||||
const uint32_t mask = DSCR_CORE_RESTARTED
|
const uint32_t mask = DSCR_CORE_RESTARTED
|
||||||
| DSCR_CORE_HALTED;
|
| DSCR_CORE_HALTED;
|
||||||
|
|
||||||
|
@ -710,14 +670,11 @@ static int arm11_step(struct target *target, int current,
|
||||||
|
|
||||||
long long then = 0;
|
long long then = 0;
|
||||||
if (i == 1000)
|
if (i == 1000)
|
||||||
{
|
|
||||||
then = timeval_ms();
|
then = timeval_ms();
|
||||||
}
|
if (i >= 1000) {
|
||||||
if (i >= 1000)
|
if ((timeval_ms()-then) > 1000) {
|
||||||
{
|
LOG_WARNING(
|
||||||
if ((timeval_ms()-then) > 1000)
|
"Timeout (1000ms) waiting for instructions to complete");
|
||||||
{
|
|
||||||
LOG_WARNING("Timeout (1000ms) waiting for instructions to complete");
|
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -751,9 +708,9 @@ static int arm11_assert_reset(struct target *target)
|
||||||
CHECK_RETVAL(arm11_sc7_set_vcr(arm11, arm11->vcr | 1));
|
CHECK_RETVAL(arm11_sc7_set_vcr(arm11, arm11->vcr | 1));
|
||||||
|
|
||||||
/* Issue some kind of warm reset. */
|
/* Issue some kind of warm reset. */
|
||||||
if (target_has_event_action(target, TARGET_EVENT_RESET_ASSERT)) {
|
if (target_has_event_action(target, TARGET_EVENT_RESET_ASSERT))
|
||||||
target_handle_event(target, TARGET_EVENT_RESET_ASSERT);
|
target_handle_event(target, TARGET_EVENT_RESET_ASSERT);
|
||||||
} else if (jtag_get_reset_config() & RESET_HAS_SRST) {
|
else if (jtag_get_reset_config() & RESET_HAS_SRST) {
|
||||||
/* REVISIT handle "pulls" cases, if there's
|
/* REVISIT handle "pulls" cases, if there's
|
||||||
* hardware that needs them to work.
|
* hardware that needs them to work.
|
||||||
*/
|
*/
|
||||||
|
@ -801,7 +758,8 @@ static int arm11_deassert_reset(struct target *target)
|
||||||
if (target->state != TARGET_HALTED) {
|
if (target->state != TARGET_HALTED) {
|
||||||
LOG_WARNING("%s: ran after reset and before halt ...",
|
LOG_WARNING("%s: ran after reset and before halt ...",
|
||||||
target_name(target));
|
target_name(target));
|
||||||
if ((retval = target_halt(target)) != ERROR_OK)
|
retval = target_halt(target);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -832,16 +790,19 @@ static int arm11_read_memory_inner(struct target *target,
|
||||||
uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer,
|
uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer,
|
||||||
bool arm11_config_memrw_no_increment)
|
bool arm11_config_memrw_no_increment)
|
||||||
{
|
{
|
||||||
/** \todo TODO: check if buffer cast to uint32_t* and uint16_t* might cause alignment problems */
|
/** \todo TODO: check if buffer cast to uint32_t* and uint16_t* might cause alignment
|
||||||
|
*problems */
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
if (target->state != TARGET_HALTED)
|
if (target->state != TARGET_HALTED) {
|
||||||
{
|
|
||||||
LOG_WARNING("target was not halted");
|
LOG_WARNING("target was not halted");
|
||||||
return ERROR_TARGET_NOT_HALTED;
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_DEBUG("ADDR %08" PRIx32 " SIZE %08" PRIx32 " COUNT %08" PRIx32 "", address, size, count);
|
LOG_DEBUG("ADDR %08" PRIx32 " SIZE %08" PRIx32 " COUNT %08" PRIx32 "",
|
||||||
|
address,
|
||||||
|
size,
|
||||||
|
count);
|
||||||
|
|
||||||
struct arm11_common *arm11 = target_to_arm11(target);
|
struct arm11_common *arm11 = target_to_arm11(target);
|
||||||
|
|
||||||
|
@ -854,13 +815,11 @@ static int arm11_read_memory_inner(struct target *target,
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
switch (size)
|
switch (size) {
|
||||||
{
|
|
||||||
case 1:
|
case 1:
|
||||||
arm11->arm.core_cache->reg_list[1].dirty = true;
|
arm11->arm.core_cache->reg_list[1].dirty = true;
|
||||||
|
|
||||||
for (size_t i = 0; i < count; i++)
|
for (size_t i = 0; i < count; i++) {
|
||||||
{
|
|
||||||
/* ldrb r1, [r0], #1 */
|
/* ldrb r1, [r0], #1 */
|
||||||
/* ldrb r1, [r0] */
|
/* ldrb r1, [r0] */
|
||||||
CHECK_RETVAL(arm11_run_instr_no_data1(arm11,
|
CHECK_RETVAL(arm11_run_instr_no_data1(arm11,
|
||||||
|
@ -879,8 +838,7 @@ static int arm11_read_memory_inner(struct target *target,
|
||||||
{
|
{
|
||||||
arm11->arm.core_cache->reg_list[1].dirty = true;
|
arm11->arm.core_cache->reg_list[1].dirty = true;
|
||||||
|
|
||||||
for (size_t i = 0; i < count; i++)
|
for (size_t i = 0; i < count; i++) {
|
||||||
{
|
|
||||||
/* ldrh r1, [r0], #2 */
|
/* ldrh r1, [r0], #2 */
|
||||||
CHECK_RETVAL(arm11_run_instr_no_data1(arm11,
|
CHECK_RETVAL(arm11_run_instr_no_data1(arm11,
|
||||||
!arm11_config_memrw_no_increment ? 0xe0d010b2 : 0xe1d010b0));
|
!arm11_config_memrw_no_increment ? 0xe0d010b2 : 0xe1d010b0));
|
||||||
|
@ -913,7 +871,11 @@ static int arm11_read_memory_inner(struct target *target,
|
||||||
return arm11_run_instr_data_finish(arm11);
|
return arm11_run_instr_data_finish(arm11);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int arm11_read_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer)
|
static int arm11_read_memory(struct target *target,
|
||||||
|
uint32_t address,
|
||||||
|
uint32_t size,
|
||||||
|
uint32_t count,
|
||||||
|
uint8_t *buffer)
|
||||||
{
|
{
|
||||||
return arm11_read_memory_inner(target, address, size, count, buffer, false);
|
return arm11_read_memory_inner(target, address, size, count, buffer, false);
|
||||||
}
|
}
|
||||||
|
@ -930,13 +892,15 @@ static int arm11_write_memory_inner(struct target *target,
|
||||||
{
|
{
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
if (target->state != TARGET_HALTED)
|
if (target->state != TARGET_HALTED) {
|
||||||
{
|
|
||||||
LOG_WARNING("target was not halted");
|
LOG_WARNING("target was not halted");
|
||||||
return ERROR_TARGET_NOT_HALTED;
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_DEBUG("ADDR %08" PRIx32 " SIZE %08" PRIx32 " COUNT %08" PRIx32 "", address, size, count);
|
LOG_DEBUG("ADDR %08" PRIx32 " SIZE %08" PRIx32 " COUNT %08" PRIx32 "",
|
||||||
|
address,
|
||||||
|
size,
|
||||||
|
count);
|
||||||
|
|
||||||
struct arm11_common *arm11 = target_to_arm11(target);
|
struct arm11_common *arm11 = target_to_arm11(target);
|
||||||
|
|
||||||
|
@ -944,8 +908,8 @@ static int arm11_write_memory_inner(struct target *target,
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
/* load r0 with buffer address */
|
/* load r0 with buffer address
|
||||||
/* MRC p14,0,r0,c0,c5,0 */
|
* MRC p14,0,r0,c0,c5,0 */
|
||||||
retval = arm11_run_instr_data_to_core1(arm11, 0xee100e15, address);
|
retval = arm11_run_instr_data_to_core1(arm11, 0xee100e15, address);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
@ -959,14 +923,12 @@ static int arm11_write_memory_inner(struct target *target,
|
||||||
*/
|
*/
|
||||||
bool burst = arm11->memwrite_burst && (count > 1);
|
bool burst = arm11->memwrite_burst && (count > 1);
|
||||||
|
|
||||||
switch (size)
|
switch (size) {
|
||||||
{
|
|
||||||
case 1:
|
case 1:
|
||||||
{
|
{
|
||||||
arm11->arm.core_cache->reg_list[1].dirty = true;
|
arm11->arm.core_cache->reg_list[1].dirty = true;
|
||||||
|
|
||||||
for (size_t i = 0; i < count; i++)
|
for (size_t i = 0; i < count; i++) {
|
||||||
{
|
|
||||||
/* load r1 from DCC with byte data */
|
/* load r1 from DCC with byte data */
|
||||||
/* MRC p14,0,r1,c0,c5,0 */
|
/* MRC p14,0,r1,c0,c5,0 */
|
||||||
retval = arm11_run_instr_data_to_core1(arm11, 0xee101e15, *buffer++);
|
retval = arm11_run_instr_data_to_core1(arm11, 0xee101e15, *buffer++);
|
||||||
|
@ -977,9 +939,7 @@ static int arm11_write_memory_inner(struct target *target,
|
||||||
/* strb r1, [r0], #1 */
|
/* strb r1, [r0], #1 */
|
||||||
/* strb r1, [r0] */
|
/* strb r1, [r0] */
|
||||||
retval = arm11_run_instr_no_data1(arm11,
|
retval = arm11_run_instr_no_data1(arm11,
|
||||||
!no_increment
|
!no_increment ? 0xe4c01001 : 0xe5c01000);
|
||||||
? 0xe4c01001
|
|
||||||
: 0xe5c01000);
|
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
@ -991,8 +951,7 @@ static int arm11_write_memory_inner(struct target *target,
|
||||||
{
|
{
|
||||||
arm11->arm.core_cache->reg_list[1].dirty = true;
|
arm11->arm.core_cache->reg_list[1].dirty = true;
|
||||||
|
|
||||||
for (size_t i = 0; i < count; i++)
|
for (size_t i = 0; i < count; i++) {
|
||||||
{
|
|
||||||
uint16_t value;
|
uint16_t value;
|
||||||
memcpy(&value, buffer + i * sizeof(uint16_t), sizeof(uint16_t));
|
memcpy(&value, buffer + i * sizeof(uint16_t), sizeof(uint16_t));
|
||||||
|
|
||||||
|
@ -1006,9 +965,7 @@ static int arm11_write_memory_inner(struct target *target,
|
||||||
/* strh r1, [r0], #2 */
|
/* strh r1, [r0], #2 */
|
||||||
/* strh r1, [r0] */
|
/* strh r1, [r0] */
|
||||||
retval = arm11_run_instr_no_data1(arm11,
|
retval = arm11_run_instr_no_data1(arm11,
|
||||||
!no_increment
|
!no_increment ? 0xe0c010b2 : 0xe1c010b0);
|
||||||
? 0xe0c010b2
|
|
||||||
: 0xe1c010b0);
|
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
@ -1023,7 +980,7 @@ static int arm11_write_memory_inner(struct target *target,
|
||||||
uint32_t instr = !no_increment ? 0xeca05e01 : 0xed805e00;
|
uint32_t instr = !no_increment ? 0xeca05e01 : 0xed805e00;
|
||||||
|
|
||||||
/** \todo TODO: buffer cast to uint32_t* causes alignment warnings */
|
/** \todo TODO: buffer cast to uint32_t* causes alignment warnings */
|
||||||
uint32_t *words = (uint32_t*)(void *)buffer;
|
uint32_t *words = (uint32_t *)(void *)buffer;
|
||||||
|
|
||||||
/* "burst" here just means trusting each instruction executes
|
/* "burst" here just means trusting each instruction executes
|
||||||
* fully before we run the next one: per-word roundtrips, to
|
* fully before we run the next one: per-word roundtrips, to
|
||||||
|
@ -1043,8 +1000,7 @@ static int arm11_write_memory_inner(struct target *target,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* r0 verification */
|
/* r0 verification */
|
||||||
if (!no_increment)
|
if (!no_increment) {
|
||||||
{
|
|
||||||
uint32_t r0;
|
uint32_t r0;
|
||||||
|
|
||||||
/* MCR p14,0,R0,c0,c5,0 */
|
/* MCR p14,0,R0,c0,c5,0 */
|
||||||
|
@ -1052,15 +1008,16 @@ static int arm11_write_memory_inner(struct target *target,
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
if (address + size * count != r0)
|
if (address + size * count != r0) {
|
||||||
{
|
|
||||||
LOG_ERROR("Data transfer failed. Expected end "
|
LOG_ERROR("Data transfer failed. Expected end "
|
||||||
"address 0x%08x, got 0x%08x",
|
"address 0x%08x, got 0x%08x",
|
||||||
(unsigned) (address + size * count),
|
(unsigned) (address + size * count),
|
||||||
(unsigned) r0);
|
(unsigned) r0);
|
||||||
|
|
||||||
if (burst)
|
if (burst)
|
||||||
LOG_ERROR("use 'arm11 memwrite burst disable' to disable fast burst mode");
|
LOG_ERROR(
|
||||||
|
"use 'arm11 memwrite burst disable' to disable fast burst mode");
|
||||||
|
|
||||||
|
|
||||||
if (arm11->memwrite_error_fatal)
|
if (arm11->memwrite_error_fatal)
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
|
@ -1085,8 +1042,7 @@ static int arm11_write_memory(struct target *target,
|
||||||
static int arm11_bulk_write_memory(struct target *target,
|
static int arm11_bulk_write_memory(struct target *target,
|
||||||
uint32_t address, uint32_t count, const uint8_t *buffer)
|
uint32_t address, uint32_t count, const uint8_t *buffer)
|
||||||
{
|
{
|
||||||
if (target->state != TARGET_HALTED)
|
if (target->state != TARGET_HALTED) {
|
||||||
{
|
|
||||||
LOG_WARNING("target was not halted");
|
LOG_WARNING("target was not halted");
|
||||||
return ERROR_TARGET_NOT_HALTED;
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
}
|
}
|
||||||
|
@ -1103,21 +1059,18 @@ static int arm11_add_breakpoint(struct target *target,
|
||||||
struct arm11_common *arm11 = target_to_arm11(target);
|
struct arm11_common *arm11 = target_to_arm11(target);
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
if (breakpoint->type == BKPT_SOFT)
|
if (breakpoint->type == BKPT_SOFT) {
|
||||||
{
|
|
||||||
LOG_INFO("sw breakpoint requested, but software breakpoints not enabled");
|
LOG_INFO("sw breakpoint requested, but software breakpoints not enabled");
|
||||||
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
|
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!arm11->free_brps)
|
if (!arm11->free_brps) {
|
||||||
{
|
|
||||||
LOG_DEBUG("no breakpoint unit available for hardware breakpoint");
|
LOG_DEBUG("no breakpoint unit available for hardware breakpoint");
|
||||||
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
|
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (breakpoint->length != 4)
|
if (breakpoint->length != 4) {
|
||||||
{
|
|
||||||
LOG_DEBUG("only breakpoints of four bytes length supported");
|
LOG_DEBUG("only breakpoints of four bytes length supported");
|
||||||
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
|
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
|
||||||
}
|
}
|
||||||
|
@ -1144,8 +1097,7 @@ static int arm11_target_create(struct target *target, Jim_Interp *interp)
|
||||||
if (target->tap == NULL)
|
if (target->tap == NULL)
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
|
|
||||||
if (target->tap->ir_length != 5)
|
if (target->tap->ir_length != 5) {
|
||||||
{
|
|
||||||
LOG_ERROR("'target arm11' expects IR LENGTH = 5");
|
LOG_ERROR("'target arm11' expects IR LENGTH = 5");
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
}
|
}
|
||||||
|
@ -1207,13 +1159,13 @@ static int arm11_examine(struct target *target)
|
||||||
arm11_setup_field(arm11, 32, NULL, &didr, chain0_fields + 0);
|
arm11_setup_field(arm11, 32, NULL, &didr, chain0_fields + 0);
|
||||||
arm11_setup_field(arm11, 8, NULL, &implementor, chain0_fields + 1);
|
arm11_setup_field(arm11, 8, NULL, &implementor, chain0_fields + 1);
|
||||||
|
|
||||||
arm11_add_dr_scan_vc(arm11->arm.target->tap, ARRAY_SIZE(chain0_fields), chain0_fields, TAP_IDLE);
|
arm11_add_dr_scan_vc(arm11->arm.target->tap, ARRAY_SIZE(
|
||||||
|
chain0_fields), chain0_fields, TAP_IDLE);
|
||||||
|
|
||||||
CHECK_RETVAL(jtag_execute_queue());
|
CHECK_RETVAL(jtag_execute_queue());
|
||||||
|
|
||||||
/* assume the manufacturer id is ok; check the part # */
|
/* assume the manufacturer id is ok; check the part # */
|
||||||
switch ((device_id >> 12) & 0xFFFF)
|
switch ((device_id >> 12) & 0xFFFF) {
|
||||||
{
|
|
||||||
case 0x7B36:
|
case 0x7B36:
|
||||||
type = "ARM1136";
|
type = "ARM1136";
|
||||||
break;
|
break;
|
||||||
|
@ -1280,9 +1232,8 @@ static int arm11_examine(struct target *target)
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#define ARM11_BOOL_WRAPPER(name, print_name) \
|
#define ARM11_BOOL_WRAPPER(name, print_name) \
|
||||||
COMMAND_HANDLER(arm11_handle_bool_##name) \
|
COMMAND_HANDLER(arm11_handle_bool_ ## name) \
|
||||||
{ \
|
{ \
|
||||||
struct target *target = get_current_target(CMD_CTX); \
|
struct target *target = get_current_target(CMD_CTX); \
|
||||||
struct arm11_common *arm11 = target_to_arm11(target); \
|
struct arm11_common *arm11 = target_to_arm11(target); \
|
||||||
|
|
|
@ -33,22 +33,20 @@
|
||||||
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. */
|
||||||
|
@ -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,8 +92,7 @@ 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,
|
||||||
|
@ -107,8 +103,7 @@ enum arm11_instructions
|
||||||
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,
|
||||||
|
|
|
@ -30,9 +30,11 @@
|
||||||
#include <helper/time_support.h>
|
#include <helper/time_support.h>
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
#define JTAG_DEBUG(expr ...) do { if (1) LOG_DEBUG(expr); } while (0)
|
#define JTAG_DEBUG(expr ...) do { if (1) \
|
||||||
|
LOG_DEBUG(expr); } while (0)
|
||||||
#else
|
#else
|
||||||
#define JTAG_DEBUG(expr ...) do { if (0) LOG_DEBUG(expr); } while (0)
|
#define JTAG_DEBUG(expr ...) do { if (0) \
|
||||||
|
LOG_DEBUG(expr); } while (0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -42,24 +44,22 @@ behavior of the FTDI driver IIRC was to go via RTI.
|
||||||
Conversely there may be other places in this code where the ARM11 code relies
|
Conversely there may be other places in this code where the ARM11 code relies
|
||||||
on the driver to hit through RTI when coming from Update-?R.
|
on the driver to hit through RTI when coming from Update-?R.
|
||||||
*/
|
*/
|
||||||
static const tap_state_t arm11_move_pi_to_si_via_ci[] =
|
static const tap_state_t arm11_move_pi_to_si_via_ci[] = {
|
||||||
{
|
|
||||||
TAP_IREXIT2, TAP_IRUPDATE, TAP_DRSELECT, TAP_IRSELECT, TAP_IRCAPTURE, TAP_IRSHIFT
|
TAP_IREXIT2, TAP_IRUPDATE, TAP_DRSELECT, TAP_IRSELECT, TAP_IRCAPTURE, TAP_IRSHIFT
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/* REVISIT no error handling here! */
|
/* REVISIT no error handling here! */
|
||||||
static void arm11_add_ir_scan_vc(struct jtag_tap *tap, struct scan_field *fields,
|
static void arm11_add_ir_scan_vc(struct jtag_tap *tap, struct scan_field *fields,
|
||||||
tap_state_t state)
|
tap_state_t state)
|
||||||
{
|
{
|
||||||
if (cmd_queue_cur_state == TAP_IRPAUSE)
|
if (cmd_queue_cur_state == TAP_IRPAUSE)
|
||||||
jtag_add_pathmove(ARRAY_SIZE(arm11_move_pi_to_si_via_ci), arm11_move_pi_to_si_via_ci);
|
jtag_add_pathmove(ARRAY_SIZE(arm11_move_pi_to_si_via_ci),
|
||||||
|
arm11_move_pi_to_si_via_ci);
|
||||||
|
|
||||||
jtag_add_ir_scan(tap, fields, state);
|
jtag_add_ir_scan(tap, fields, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const tap_state_t arm11_move_pd_to_sd_via_cd[] =
|
static const tap_state_t arm11_move_pd_to_sd_via_cd[] = {
|
||||||
{
|
|
||||||
TAP_DREXIT2, TAP_DRUPDATE, TAP_DRSELECT, TAP_DRCAPTURE, TAP_DRSHIFT
|
TAP_DREXIT2, TAP_DRUPDATE, TAP_DRSELECT, TAP_DRCAPTURE, TAP_DRSHIFT
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -68,7 +68,8 @@ void arm11_add_dr_scan_vc(struct jtag_tap *tap, int num_fields, struct scan_fiel
|
||||||
tap_state_t state)
|
tap_state_t state)
|
||||||
{
|
{
|
||||||
if (cmd_queue_cur_state == TAP_DRPAUSE)
|
if (cmd_queue_cur_state == TAP_DRPAUSE)
|
||||||
jtag_add_pathmove(ARRAY_SIZE(arm11_move_pd_to_sd_via_cd), arm11_move_pd_to_sd_via_cd);
|
jtag_add_pathmove(ARRAY_SIZE(arm11_move_pd_to_sd_via_cd),
|
||||||
|
arm11_move_pd_to_sd_via_cd);
|
||||||
|
|
||||||
jtag_add_dr_scan(tap, num_fields, fields, state);
|
jtag_add_dr_scan(tap, num_fields, fields, state);
|
||||||
}
|
}
|
||||||
|
@ -133,12 +134,11 @@ static const char *arm11_ir_to_string(uint8_t ir)
|
||||||
*
|
*
|
||||||
* \remarks This adds to the JTAG command queue but does \em not execute it.
|
* \remarks This adds to the JTAG command queue but does \em not execute it.
|
||||||
*/
|
*/
|
||||||
void arm11_add_IR(struct arm11_common * arm11, uint8_t instr, tap_state_t state)
|
void arm11_add_IR(struct arm11_common *arm11, uint8_t instr, tap_state_t state)
|
||||||
{
|
{
|
||||||
struct jtag_tap *tap = arm11->arm.target->tap;
|
struct jtag_tap *tap = arm11->arm.target->tap;
|
||||||
|
|
||||||
if (buf_get_u32(tap->cur_instr, 0, 5) == instr)
|
if (buf_get_u32(tap->cur_instr, 0, 5) == instr) {
|
||||||
{
|
|
||||||
JTAG_DEBUG("IR <= 0x%02x SKIPPED", instr);
|
JTAG_DEBUG("IR <= 0x%02x SKIPPED", instr);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -149,7 +149,9 @@ void arm11_add_IR(struct arm11_common * arm11, uint8_t instr, tap_state_t state)
|
||||||
|
|
||||||
arm11_setup_field(arm11, 5, &instr, NULL, &field);
|
arm11_setup_field(arm11, 5, &instr, NULL, &field);
|
||||||
|
|
||||||
arm11_add_ir_scan_vc(arm11->arm.target->tap, &field, state == ARM11_TAP_DEFAULT ? TAP_IRPAUSE : state);
|
arm11_add_ir_scan_vc(arm11->arm.target->tap,
|
||||||
|
&field,
|
||||||
|
state == ARM11_TAP_DEFAULT ? TAP_IRPAUSE : state);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Verify data shifted out from Scan Chain Register (SCREG). */
|
/** Verify data shifted out from Scan Chain Register (SCREG). */
|
||||||
|
@ -158,8 +160,7 @@ static void arm11_in_handler_SCAN_N(uint8_t *in_value)
|
||||||
/* Don't expect JTAG layer to modify bits we didn't ask it to read */
|
/* Don't expect JTAG layer to modify bits we didn't ask it to read */
|
||||||
uint8_t v = *in_value & 0x1F;
|
uint8_t v = *in_value & 0x1F;
|
||||||
|
|
||||||
if (v != 0x10)
|
if (v != 0x10) {
|
||||||
{
|
|
||||||
LOG_ERROR("'arm11 target' JTAG error SCREG OUT 0x%02x", v);
|
LOG_ERROR("'arm11 target' JTAG error SCREG OUT 0x%02x", v);
|
||||||
jtag_set_error(ERROR_FAIL);
|
jtag_set_error(ERROR_FAIL);
|
||||||
}
|
}
|
||||||
|
@ -200,10 +201,10 @@ int arm11_add_debug_SCAN_N(struct arm11_common *arm11,
|
||||||
* but leaves its actual value unchanged.
|
* but leaves its actual value unchanged.
|
||||||
*/
|
*/
|
||||||
#if 0
|
#if 0
|
||||||
// FIX!!! the optimization below is broken because we do not
|
/* FIX!!! the optimization below is broken because we do not */
|
||||||
// invalidate the cur_scan_chain upon a TRST/TMS. See arm_jtag.c
|
/* invalidate the cur_scan_chain upon a TRST/TMS. See arm_jtag.c */
|
||||||
// for example on how to invalidate cur_scan_chain. Tested patches gladly
|
/* for example on how to invalidate cur_scan_chain. Tested patches gladly */
|
||||||
// accepted!
|
/* accepted! */
|
||||||
if (arm11->jtag_info.cur_scan_chain == chain) {
|
if (arm11->jtag_info.cur_scan_chain == chain) {
|
||||||
JTAG_DEBUG("SCREG <= %d SKIPPED", chain);
|
JTAG_DEBUG("SCREG <= %d SKIPPED", chain);
|
||||||
return jtag_add_statemove((state == ARM11_TAP_DEFAULT)
|
return jtag_add_statemove((state == ARM11_TAP_DEFAULT)
|
||||||
|
@ -219,7 +220,10 @@ int arm11_add_debug_SCAN_N(struct arm11_common *arm11,
|
||||||
uint8_t tmp[1];
|
uint8_t tmp[1];
|
||||||
arm11_setup_field(arm11, 5, &chain, &tmp, &field);
|
arm11_setup_field(arm11, 5, &chain, &tmp, &field);
|
||||||
|
|
||||||
arm11_add_dr_scan_vc(arm11->arm.target->tap, 1, &field, state == ARM11_TAP_DEFAULT ? TAP_DRPAUSE : state);
|
arm11_add_dr_scan_vc(arm11->arm.target->tap,
|
||||||
|
1,
|
||||||
|
&field,
|
||||||
|
state == ARM11_TAP_DEFAULT ? TAP_DRPAUSE : state);
|
||||||
|
|
||||||
jtag_execute_queue_noclear();
|
jtag_execute_queue_noclear();
|
||||||
|
|
||||||
|
@ -248,8 +252,8 @@ int arm11_add_debug_SCAN_N(struct arm11_common *arm11,
|
||||||
* is properly set up. Depending on the instruction, you may also need
|
* is properly set up. Depending on the instruction, you may also need
|
||||||
* to ensure that the rDTR is ready before that Run-Test/Idle state.
|
* to ensure that the rDTR is ready before that Run-Test/Idle state.
|
||||||
*/
|
*/
|
||||||
static void arm11_add_debug_INST(struct arm11_common * arm11,
|
static void arm11_add_debug_INST(struct arm11_common *arm11,
|
||||||
uint32_t inst, uint8_t * flag, tap_state_t state)
|
uint32_t inst, uint8_t *flag, tap_state_t state)
|
||||||
{
|
{
|
||||||
JTAG_DEBUG("INST <= 0x%08x", (unsigned) inst);
|
JTAG_DEBUG("INST <= 0x%08x", (unsigned) inst);
|
||||||
|
|
||||||
|
@ -309,7 +313,7 @@ int arm11_read_DSCR(struct arm11_common *arm11)
|
||||||
*
|
*
|
||||||
* \remarks This is a stand-alone function that executes the JTAG command queue.
|
* \remarks This is a stand-alone function that executes the JTAG command queue.
|
||||||
*/
|
*/
|
||||||
int arm11_write_DSCR(struct arm11_common * arm11, uint32_t dscr)
|
int arm11_write_DSCR(struct arm11_common *arm11, uint32_t dscr)
|
||||||
{
|
{
|
||||||
int retval;
|
int retval;
|
||||||
retval = arm11_add_debug_SCAN_N(arm11, 0x01, ARM11_TAP_DEFAULT);
|
retval = arm11_add_debug_SCAN_N(arm11, 0x01, ARM11_TAP_DEFAULT);
|
||||||
|
@ -349,7 +353,7 @@ int arm11_write_DSCR(struct arm11_common * arm11, uint32_t dscr)
|
||||||
* \param arm11 Target state variable.
|
* \param arm11 Target state variable.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
int arm11_run_instr_data_prepare(struct arm11_common * arm11)
|
int arm11_run_instr_data_prepare(struct arm11_common *arm11)
|
||||||
{
|
{
|
||||||
return arm11_add_debug_SCAN_N(arm11, 0x05, ARM11_TAP_DEFAULT);
|
return arm11_add_debug_SCAN_N(arm11, 0x05, ARM11_TAP_DEFAULT);
|
||||||
}
|
}
|
||||||
|
@ -368,13 +372,11 @@ int arm11_run_instr_data_prepare(struct arm11_common * arm11)
|
||||||
* \param arm11 Target state variable.
|
* \param arm11 Target state variable.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
int arm11_run_instr_data_finish(struct arm11_common * arm11)
|
int arm11_run_instr_data_finish(struct arm11_common *arm11)
|
||||||
{
|
{
|
||||||
return arm11_add_debug_SCAN_N(arm11, 0x00, ARM11_TAP_DEFAULT);
|
return arm11_add_debug_SCAN_N(arm11, 0x00, ARM11_TAP_DEFAULT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Execute one or more instructions via ITR.
|
* Execute one or more instructions via ITR.
|
||||||
* Caller guarantees that processor is in debug state, that DSCR_ITR_EN
|
* Caller guarantees that processor is in debug state, that DSCR_ITR_EN
|
||||||
|
@ -389,18 +391,16 @@ int arm11_run_instr_data_finish(struct arm11_common * arm11)
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static
|
static
|
||||||
int arm11_run_instr_no_data(struct arm11_common * arm11,
|
int arm11_run_instr_no_data(struct arm11_common *arm11,
|
||||||
uint32_t * opcode, size_t count)
|
uint32_t *opcode, size_t count)
|
||||||
{
|
{
|
||||||
arm11_add_IR(arm11, ARM11_ITRSEL, ARM11_TAP_DEFAULT);
|
arm11_add_IR(arm11, ARM11_ITRSEL, ARM11_TAP_DEFAULT);
|
||||||
|
|
||||||
while (count--)
|
while (count--) {
|
||||||
{
|
|
||||||
arm11_add_debug_INST(arm11, *opcode++, NULL, TAP_IDLE);
|
arm11_add_debug_INST(arm11, *opcode++, NULL, TAP_IDLE);
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
while (1)
|
while (1) {
|
||||||
{
|
|
||||||
uint8_t flag;
|
uint8_t flag;
|
||||||
|
|
||||||
arm11_add_debug_INST(arm11, 0, &flag, count ? TAP_IDLE : TAP_DRPAUSE);
|
arm11_add_debug_INST(arm11, 0, &flag, count ? TAP_IDLE : TAP_DRPAUSE);
|
||||||
|
@ -413,14 +413,11 @@ int arm11_run_instr_no_data(struct arm11_common * arm11,
|
||||||
long long then = 0;
|
long long then = 0;
|
||||||
|
|
||||||
if (i == 1000)
|
if (i == 1000)
|
||||||
{
|
|
||||||
then = timeval_ms();
|
then = timeval_ms();
|
||||||
}
|
if (i >= 1000) {
|
||||||
if (i >= 1000)
|
if ((timeval_ms()-then) > 1000) {
|
||||||
{
|
LOG_WARNING(
|
||||||
if ((timeval_ms()-then) > 1000)
|
"Timeout (1000ms) waiting for instructions to complete");
|
||||||
{
|
|
||||||
LOG_WARNING("Timeout (1000ms) waiting for instructions to complete");
|
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -440,7 +437,7 @@ int arm11_run_instr_no_data(struct arm11_common * arm11,
|
||||||
* \param opcode ARM opcode
|
* \param opcode ARM opcode
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
int arm11_run_instr_no_data1(struct arm11_common * arm11, uint32_t opcode)
|
int arm11_run_instr_no_data1(struct arm11_common *arm11, uint32_t opcode)
|
||||||
{
|
{
|
||||||
return arm11_run_instr_no_data(arm11, &opcode, 1);
|
return arm11_run_instr_no_data(arm11, &opcode, 1);
|
||||||
}
|
}
|
||||||
|
@ -463,7 +460,10 @@ int arm11_run_instr_no_data1(struct arm11_common * arm11, uint32_t opcode)
|
||||||
* \param count Number of data words and instruction repetitions
|
* \param count Number of data words and instruction repetitions
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
int arm11_run_instr_data_to_core(struct arm11_common * arm11, uint32_t opcode, uint32_t * data, size_t count)
|
int arm11_run_instr_data_to_core(struct arm11_common *arm11,
|
||||||
|
uint32_t opcode,
|
||||||
|
uint32_t *data,
|
||||||
|
size_t count)
|
||||||
{
|
{
|
||||||
arm11_add_IR(arm11, ARM11_ITRSEL, ARM11_TAP_DEFAULT);
|
arm11_add_IR(arm11, ARM11_ITRSEL, ARM11_TAP_DEFAULT);
|
||||||
|
|
||||||
|
@ -481,14 +481,13 @@ int arm11_run_instr_data_to_core(struct arm11_common * arm11, uint32_t opcode, u
|
||||||
arm11_setup_field(arm11, 1, NULL, &Ready, chain5_fields + 1);
|
arm11_setup_field(arm11, 1, NULL, &Ready, chain5_fields + 1);
|
||||||
arm11_setup_field(arm11, 1, NULL, &nRetry, chain5_fields + 2);
|
arm11_setup_field(arm11, 1, NULL, &nRetry, chain5_fields + 2);
|
||||||
|
|
||||||
while (count--)
|
while (count--) {
|
||||||
{
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
do
|
do {
|
||||||
{
|
|
||||||
Data = *data;
|
Data = *data;
|
||||||
|
|
||||||
arm11_add_dr_scan_vc(arm11->arm.target->tap, ARRAY_SIZE(chain5_fields), chain5_fields, TAP_IDLE);
|
arm11_add_dr_scan_vc(arm11->arm.target->tap, ARRAY_SIZE(
|
||||||
|
chain5_fields), chain5_fields, TAP_IDLE);
|
||||||
|
|
||||||
CHECK_RETVAL(jtag_execute_queue());
|
CHECK_RETVAL(jtag_execute_queue());
|
||||||
|
|
||||||
|
@ -497,21 +496,17 @@ int arm11_run_instr_data_to_core(struct arm11_common * arm11, uint32_t opcode, u
|
||||||
long long then = 0;
|
long long then = 0;
|
||||||
|
|
||||||
if (i == 1000)
|
if (i == 1000)
|
||||||
{
|
|
||||||
then = timeval_ms();
|
then = timeval_ms();
|
||||||
}
|
if (i >= 1000) {
|
||||||
if (i >= 1000)
|
if ((timeval_ms()-then) > 1000) {
|
||||||
{
|
LOG_WARNING(
|
||||||
if ((timeval_ms()-then) > 1000)
|
"Timeout (1000ms) waiting for instructions to complete");
|
||||||
{
|
|
||||||
LOG_WARNING("Timeout (1000ms) waiting for instructions to complete");
|
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
i++;
|
i++;
|
||||||
}
|
} while (!Ready);
|
||||||
while (!Ready);
|
|
||||||
|
|
||||||
data++;
|
data++;
|
||||||
}
|
}
|
||||||
|
@ -519,11 +514,11 @@ int arm11_run_instr_data_to_core(struct arm11_common * arm11, uint32_t opcode, u
|
||||||
arm11_add_IR(arm11, ARM11_INTEST, ARM11_TAP_DEFAULT);
|
arm11_add_IR(arm11, ARM11_INTEST, ARM11_TAP_DEFAULT);
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
do
|
do {
|
||||||
{
|
|
||||||
Data = 0;
|
Data = 0;
|
||||||
|
|
||||||
arm11_add_dr_scan_vc(arm11->arm.target->tap, ARRAY_SIZE(chain5_fields), chain5_fields, TAP_DRPAUSE);
|
arm11_add_dr_scan_vc(arm11->arm.target->tap, ARRAY_SIZE(
|
||||||
|
chain5_fields), chain5_fields, TAP_DRPAUSE);
|
||||||
|
|
||||||
CHECK_RETVAL(jtag_execute_queue());
|
CHECK_RETVAL(jtag_execute_queue());
|
||||||
|
|
||||||
|
@ -533,21 +528,16 @@ int arm11_run_instr_data_to_core(struct arm11_common * arm11, uint32_t opcode, u
|
||||||
long long then = 0;
|
long long then = 0;
|
||||||
|
|
||||||
if (i == 1000)
|
if (i == 1000)
|
||||||
{
|
|
||||||
then = timeval_ms();
|
then = timeval_ms();
|
||||||
}
|
if (i >= 1000) {
|
||||||
if (i >= 1000)
|
if ((timeval_ms()-then) > 1000) {
|
||||||
{
|
|
||||||
if ((timeval_ms()-then) > 1000)
|
|
||||||
{
|
|
||||||
LOG_WARNING("Timeout (1000ms) waiting for instructions to complete");
|
LOG_WARNING("Timeout (1000ms) waiting for instructions to complete");
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
i++;
|
i++;
|
||||||
}
|
} while (!Ready);
|
||||||
while (!Ready);
|
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
@ -569,16 +559,19 @@ int arm11_run_instr_data_to_core(struct arm11_common * arm11, uint32_t opcode, u
|
||||||
* https://lists.berlios.de/pipermail/openocd-development/2009-July/009698.html
|
* https://lists.berlios.de/pipermail/openocd-development/2009-July/009698.html
|
||||||
* https://lists.berlios.de/pipermail/openocd-development/2009-August/009865.html
|
* https://lists.berlios.de/pipermail/openocd-development/2009-August/009865.html
|
||||||
*/
|
*/
|
||||||
static const tap_state_t arm11_MOVE_DRPAUSE_IDLE_DRPAUSE_with_delay[] =
|
static const tap_state_t arm11_MOVE_DRPAUSE_IDLE_DRPAUSE_with_delay[] = {
|
||||||
{
|
TAP_DREXIT2, TAP_DRUPDATE, TAP_IDLE, TAP_IDLE, TAP_IDLE, TAP_DRSELECT, TAP_DRCAPTURE,
|
||||||
TAP_DREXIT2, TAP_DRUPDATE, TAP_IDLE, TAP_IDLE, TAP_IDLE, TAP_DRSELECT, TAP_DRCAPTURE, TAP_DRSHIFT
|
TAP_DRSHIFT
|
||||||
};
|
};
|
||||||
|
|
||||||
/* This inner loop can be implemented by the minidriver, oftentimes in hardware... The
|
/* This inner loop can be implemented by the minidriver, oftentimes in hardware... The
|
||||||
* minidriver can call the default implementation as a fallback or implement it
|
* minidriver can call the default implementation as a fallback or implement it
|
||||||
* from scratch.
|
* from scratch.
|
||||||
*/
|
*/
|
||||||
int arm11_run_instr_data_to_core_noack_inner_default(struct jtag_tap * tap, uint32_t opcode, uint32_t * data, size_t count)
|
int arm11_run_instr_data_to_core_noack_inner_default(struct jtag_tap *tap,
|
||||||
|
uint32_t opcode,
|
||||||
|
uint32_t *data,
|
||||||
|
size_t count)
|
||||||
{
|
{
|
||||||
struct scan_field chain5_fields[3];
|
struct scan_field chain5_fields[3];
|
||||||
|
|
||||||
|
@ -599,44 +592,35 @@ int arm11_run_instr_data_to_core_noack_inner_default(struct jtag_tap * tap, uint
|
||||||
unsigned bytes = sizeof(*Readies)*readiesNum;
|
unsigned bytes = sizeof(*Readies)*readiesNum;
|
||||||
|
|
||||||
Readies = (uint8_t *) malloc(bytes);
|
Readies = (uint8_t *) malloc(bytes);
|
||||||
if (Readies == NULL)
|
if (Readies == NULL) {
|
||||||
{
|
|
||||||
LOG_ERROR("Out of memory allocating %u bytes", bytes);
|
LOG_ERROR("Out of memory allocating %u bytes", bytes);
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t * ReadyPos = Readies;
|
uint8_t *ReadyPos = Readies;
|
||||||
while (count--)
|
while (count--) {
|
||||||
{
|
|
||||||
chain5_fields[0].out_value = (void *)(data++);
|
chain5_fields[0].out_value = (void *)(data++);
|
||||||
chain5_fields[1].in_value = ReadyPos++;
|
chain5_fields[1].in_value = ReadyPos++;
|
||||||
|
|
||||||
if (count > 0)
|
if (count > 0) {
|
||||||
{
|
jtag_add_dr_scan(tap, ARRAY_SIZE(chain5_fields), chain5_fields,
|
||||||
jtag_add_dr_scan(tap, ARRAY_SIZE(chain5_fields), chain5_fields, TAP_DRPAUSE);
|
TAP_DRPAUSE);
|
||||||
jtag_add_pathmove(ARRAY_SIZE(arm11_MOVE_DRPAUSE_IDLE_DRPAUSE_with_delay),
|
jtag_add_pathmove(ARRAY_SIZE(arm11_MOVE_DRPAUSE_IDLE_DRPAUSE_with_delay),
|
||||||
arm11_MOVE_DRPAUSE_IDLE_DRPAUSE_with_delay);
|
arm11_MOVE_DRPAUSE_IDLE_DRPAUSE_with_delay);
|
||||||
} else
|
} else
|
||||||
{
|
|
||||||
jtag_add_dr_scan(tap, ARRAY_SIZE(chain5_fields), chain5_fields, TAP_IDLE);
|
jtag_add_dr_scan(tap, ARRAY_SIZE(chain5_fields), chain5_fields, TAP_IDLE);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
int retval = jtag_execute_queue();
|
int retval = jtag_execute_queue();
|
||||||
if (retval == ERROR_OK)
|
if (retval == ERROR_OK) {
|
||||||
{
|
|
||||||
unsigned error_count = 0;
|
unsigned error_count = 0;
|
||||||
|
|
||||||
for (size_t i = 0; i < readiesNum; i++)
|
for (size_t i = 0; i < readiesNum; i++) {
|
||||||
{
|
|
||||||
if (Readies[i] != 1)
|
if (Readies[i] != 1)
|
||||||
{
|
|
||||||
error_count++;
|
error_count++;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (error_count > 0 )
|
if (error_count > 0) {
|
||||||
{
|
|
||||||
LOG_ERROR("%u words out of %u not transferred",
|
LOG_ERROR("%u words out of %u not transferred",
|
||||||
error_count, readiesNum);
|
error_count, readiesNum);
|
||||||
retval = ERROR_FAIL;
|
retval = ERROR_FAIL;
|
||||||
|
@ -647,10 +631,16 @@ int arm11_run_instr_data_to_core_noack_inner_default(struct jtag_tap * tap, uint
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
int arm11_run_instr_data_to_core_noack_inner(struct jtag_tap * tap, uint32_t opcode, uint32_t * data, size_t count);
|
int arm11_run_instr_data_to_core_noack_inner(struct jtag_tap *tap,
|
||||||
|
uint32_t opcode,
|
||||||
|
uint32_t *data,
|
||||||
|
size_t count);
|
||||||
|
|
||||||
#ifndef HAVE_JTAG_MINIDRIVER_H
|
#ifndef HAVE_JTAG_MINIDRIVER_H
|
||||||
int arm11_run_instr_data_to_core_noack_inner(struct jtag_tap * tap, uint32_t opcode, uint32_t * data, size_t count)
|
int arm11_run_instr_data_to_core_noack_inner(struct jtag_tap *tap,
|
||||||
|
uint32_t opcode,
|
||||||
|
uint32_t *data,
|
||||||
|
size_t count)
|
||||||
{
|
{
|
||||||
return arm11_run_instr_data_to_core_noack_inner_default(tap, opcode, data, count);
|
return arm11_run_instr_data_to_core_noack_inner_default(tap, opcode, data, count);
|
||||||
}
|
}
|
||||||
|
@ -675,7 +665,10 @@ int arm11_run_instr_data_to_core_noack_inner(struct jtag_tap * tap, uint32_t opc
|
||||||
* \param count Number of data words and instruction repetitions
|
* \param count Number of data words and instruction repetitions
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
int arm11_run_instr_data_to_core_noack(struct arm11_common * arm11, uint32_t opcode, uint32_t * data, size_t count)
|
int arm11_run_instr_data_to_core_noack(struct arm11_common *arm11,
|
||||||
|
uint32_t opcode,
|
||||||
|
uint32_t *data,
|
||||||
|
size_t count)
|
||||||
{
|
{
|
||||||
arm11_add_IR(arm11, ARM11_ITRSEL, ARM11_TAP_DEFAULT);
|
arm11_add_IR(arm11, ARM11_ITRSEL, ARM11_TAP_DEFAULT);
|
||||||
|
|
||||||
|
@ -683,7 +676,10 @@ int arm11_run_instr_data_to_core_noack(struct arm11_common * arm11, uint32_t opc
|
||||||
|
|
||||||
arm11_add_IR(arm11, ARM11_EXTEST, ARM11_TAP_DEFAULT);
|
arm11_add_IR(arm11, ARM11_EXTEST, ARM11_TAP_DEFAULT);
|
||||||
|
|
||||||
int retval = arm11_run_instr_data_to_core_noack_inner(arm11->arm.target->tap, opcode, data, count);
|
int retval = arm11_run_instr_data_to_core_noack_inner(arm11->arm.target->tap,
|
||||||
|
opcode,
|
||||||
|
data,
|
||||||
|
count);
|
||||||
|
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
@ -692,20 +688,31 @@ int arm11_run_instr_data_to_core_noack(struct arm11_common * arm11, uint32_t opc
|
||||||
|
|
||||||
struct scan_field chain5_fields[3];
|
struct scan_field chain5_fields[3];
|
||||||
|
|
||||||
arm11_setup_field(arm11, 32, NULL/*&Data*/, NULL, chain5_fields + 0);
|
arm11_setup_field(arm11,
|
||||||
arm11_setup_field(arm11, 1, NULL, NULL /*&Ready*/, chain5_fields + 1);
|
32,
|
||||||
arm11_setup_field(arm11, 1, NULL, NULL, chain5_fields + 2);
|
NULL /*&Data*/,
|
||||||
|
NULL,
|
||||||
|
chain5_fields + 0);
|
||||||
|
arm11_setup_field(arm11,
|
||||||
|
1,
|
||||||
|
NULL,
|
||||||
|
NULL /*&Ready*/,
|
||||||
|
chain5_fields + 1);
|
||||||
|
arm11_setup_field(arm11,
|
||||||
|
1,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
chain5_fields + 2);
|
||||||
|
|
||||||
uint8_t ready_flag;
|
uint8_t ready_flag;
|
||||||
chain5_fields[1].in_value = &ready_flag;
|
chain5_fields[1].in_value = &ready_flag;
|
||||||
|
|
||||||
arm11_add_dr_scan_vc(arm11->arm.target->tap, ARRAY_SIZE(chain5_fields), chain5_fields, TAP_DRPAUSE);
|
arm11_add_dr_scan_vc(arm11->arm.target->tap, ARRAY_SIZE(
|
||||||
|
chain5_fields), chain5_fields, TAP_DRPAUSE);
|
||||||
|
|
||||||
retval = jtag_execute_queue();
|
retval = jtag_execute_queue();
|
||||||
if (retval == ERROR_OK)
|
if (retval == ERROR_OK) {
|
||||||
{
|
if (ready_flag != 1) {
|
||||||
if (ready_flag != 1)
|
|
||||||
{
|
|
||||||
LOG_ERROR("last word not transferred");
|
LOG_ERROR("last word not transferred");
|
||||||
retval = ERROR_FAIL;
|
retval = ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
@ -726,7 +733,7 @@ int arm11_run_instr_data_to_core_noack(struct arm11_common * arm11, uint32_t opc
|
||||||
* \param data Data word to be passed to the core via DTR
|
* \param data Data word to be passed to the core via DTR
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
int arm11_run_instr_data_to_core1(struct arm11_common * arm11, uint32_t opcode, uint32_t data)
|
int arm11_run_instr_data_to_core1(struct arm11_common *arm11, uint32_t opcode, uint32_t data)
|
||||||
{
|
{
|
||||||
return arm11_run_instr_data_to_core(arm11, opcode, &data, 1);
|
return arm11_run_instr_data_to_core(arm11, opcode, &data, 1);
|
||||||
}
|
}
|
||||||
|
@ -749,7 +756,10 @@ int arm11_run_instr_data_to_core1(struct arm11_common * arm11, uint32_t opcode,
|
||||||
* \param count Number of data words and instruction repetitions
|
* \param count Number of data words and instruction repetitions
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
int arm11_run_instr_data_from_core(struct arm11_common * arm11, uint32_t opcode, uint32_t * data, size_t count)
|
int arm11_run_instr_data_from_core(struct arm11_common *arm11,
|
||||||
|
uint32_t opcode,
|
||||||
|
uint32_t *data,
|
||||||
|
size_t count)
|
||||||
{
|
{
|
||||||
arm11_add_IR(arm11, ARM11_ITRSEL, ARM11_TAP_DEFAULT);
|
arm11_add_IR(arm11, ARM11_ITRSEL, ARM11_TAP_DEFAULT);
|
||||||
|
|
||||||
|
@ -767,12 +777,12 @@ int arm11_run_instr_data_from_core(struct arm11_common * arm11, uint32_t opcode,
|
||||||
arm11_setup_field(arm11, 1, NULL, &Ready, chain5_fields + 1);
|
arm11_setup_field(arm11, 1, NULL, &Ready, chain5_fields + 1);
|
||||||
arm11_setup_field(arm11, 1, NULL, &nRetry, chain5_fields + 2);
|
arm11_setup_field(arm11, 1, NULL, &nRetry, chain5_fields + 2);
|
||||||
|
|
||||||
while (count--)
|
while (count--) {
|
||||||
{
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
do
|
do {
|
||||||
{
|
arm11_add_dr_scan_vc(arm11->arm.target->tap, ARRAY_SIZE(
|
||||||
arm11_add_dr_scan_vc(arm11->arm.target->tap, ARRAY_SIZE(chain5_fields), chain5_fields, count ? TAP_IDLE : TAP_DRPAUSE);
|
chain5_fields), chain5_fields,
|
||||||
|
count ? TAP_IDLE : TAP_DRPAUSE);
|
||||||
|
|
||||||
CHECK_RETVAL(jtag_execute_queue());
|
CHECK_RETVAL(jtag_execute_queue());
|
||||||
|
|
||||||
|
@ -782,21 +792,17 @@ int arm11_run_instr_data_from_core(struct arm11_common * arm11, uint32_t opcode,
|
||||||
long long then = 0;
|
long long then = 0;
|
||||||
|
|
||||||
if (i == 1000)
|
if (i == 1000)
|
||||||
{
|
|
||||||
then = timeval_ms();
|
then = timeval_ms();
|
||||||
}
|
if (i >= 1000) {
|
||||||
if (i >= 1000)
|
if ((timeval_ms()-then) > 1000) {
|
||||||
{
|
LOG_WARNING(
|
||||||
if ((timeval_ms()-then) > 1000)
|
"Timeout (1000ms) waiting for instructions to complete");
|
||||||
{
|
|
||||||
LOG_WARNING("Timeout (1000ms) waiting for instructions to complete");
|
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
i++;
|
i++;
|
||||||
}
|
} while (!Ready);
|
||||||
while (!Ready);
|
|
||||||
|
|
||||||
*data++ = Data;
|
*data++ = Data;
|
||||||
}
|
}
|
||||||
|
@ -816,7 +822,9 @@ int arm11_run_instr_data_from_core(struct arm11_common * arm11, uint32_t opcode,
|
||||||
* \param data Pointer to a data word that receives the value from r0 after \p opcode was executed.
|
* \param data Pointer to a data word that receives the value from r0 after \p opcode was executed.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
int arm11_run_instr_data_from_core_via_r0(struct arm11_common * arm11, uint32_t opcode, uint32_t * data)
|
int arm11_run_instr_data_from_core_via_r0(struct arm11_common *arm11,
|
||||||
|
uint32_t opcode,
|
||||||
|
uint32_t *data)
|
||||||
{
|
{
|
||||||
int retval;
|
int retval;
|
||||||
retval = arm11_run_instr_no_data1(arm11, opcode);
|
retval = arm11_run_instr_no_data1(arm11, opcode);
|
||||||
|
@ -841,7 +849,7 @@ int arm11_run_instr_data_from_core_via_r0(struct arm11_common * arm11, uint32_t
|
||||||
* \param data Data word that will be written to r0 before \p opcode is executed
|
* \param data Data word that will be written to r0 before \p opcode is executed
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
int arm11_run_instr_data_to_core_via_r0(struct arm11_common * arm11, uint32_t opcode, uint32_t data)
|
int arm11_run_instr_data_to_core_via_r0(struct arm11_common *arm11, uint32_t opcode, uint32_t data)
|
||||||
{
|
{
|
||||||
int retval;
|
int retval;
|
||||||
/* MRC p14,0,r0,c0,c5,0 */
|
/* MRC p14,0,r0,c0,c5,0 */
|
||||||
|
@ -865,7 +873,7 @@ int arm11_run_instr_data_to_core_via_r0(struct arm11_common * arm11, uint32_t op
|
||||||
* \param count Number of instructions in the list.
|
* \param count Number of instructions in the list.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
int arm11_sc7_run(struct arm11_common * arm11, struct arm11_sc7_action * actions, size_t count)
|
int arm11_sc7_run(struct arm11_common *arm11, struct arm11_sc7_action *actions, size_t count)
|
||||||
{
|
{
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
|
@ -888,16 +896,12 @@ int arm11_sc7_run(struct arm11_common * arm11, struct arm11_sc7_action * actions
|
||||||
arm11_setup_field(arm11, 32, &DataOut, &DataIn, chain7_fields + 1);
|
arm11_setup_field(arm11, 32, &DataOut, &DataIn, chain7_fields + 1);
|
||||||
arm11_setup_field(arm11, 7, &AddressOut, &AddressIn, chain7_fields + 2);
|
arm11_setup_field(arm11, 7, &AddressOut, &AddressIn, chain7_fields + 2);
|
||||||
|
|
||||||
for (size_t i = 0; i < count + 1; i++)
|
for (size_t i = 0; i < count + 1; i++) {
|
||||||
{
|
if (i < count) {
|
||||||
if (i < count)
|
|
||||||
{
|
|
||||||
nRW = actions[i].write ? 1 : 0;
|
nRW = actions[i].write ? 1 : 0;
|
||||||
DataOut = actions[i].value;
|
DataOut = actions[i].value;
|
||||||
AddressOut = actions[i].address;
|
AddressOut = actions[i].address;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
nRW = 1;
|
nRW = 1;
|
||||||
DataOut = 0;
|
DataOut = 0;
|
||||||
AddressOut = 0;
|
AddressOut = 0;
|
||||||
|
@ -905,8 +909,7 @@ int arm11_sc7_run(struct arm11_common * arm11, struct arm11_sc7_action * actions
|
||||||
|
|
||||||
/* Timeout here so we don't get stuck. */
|
/* Timeout here so we don't get stuck. */
|
||||||
int i_n = 0;
|
int i_n = 0;
|
||||||
while (1)
|
while (1) {
|
||||||
{
|
|
||||||
JTAG_DEBUG("SC7 <= c%-3d Data %08x %s",
|
JTAG_DEBUG("SC7 <= c%-3d Data %08x %s",
|
||||||
(unsigned) AddressOut,
|
(unsigned) AddressOut,
|
||||||
(unsigned) DataOut,
|
(unsigned) DataOut,
|
||||||
|
@ -924,14 +927,11 @@ int arm11_sc7_run(struct arm11_common * arm11, struct arm11_sc7_action * actions
|
||||||
long long then = 0;
|
long long then = 0;
|
||||||
|
|
||||||
if (i_n == 1000)
|
if (i_n == 1000)
|
||||||
{
|
|
||||||
then = timeval_ms();
|
then = timeval_ms();
|
||||||
}
|
if (i_n >= 1000) {
|
||||||
if (i_n >= 1000)
|
if ((timeval_ms()-then) > 1000) {
|
||||||
{
|
LOG_WARNING(
|
||||||
if ((timeval_ms()-then) > 1000)
|
"Timeout (1000ms) waiting for instructions to complete");
|
||||||
{
|
|
||||||
LOG_WARNING("Timeout (1000ms) waiting for instructions to complete");
|
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -942,26 +942,18 @@ int arm11_sc7_run(struct arm11_common * arm11, struct arm11_sc7_action * actions
|
||||||
if (!nRW)
|
if (!nRW)
|
||||||
JTAG_DEBUG("SC7 => Data %08x", (unsigned) DataIn);
|
JTAG_DEBUG("SC7 => Data %08x", (unsigned) DataIn);
|
||||||
|
|
||||||
if (i > 0)
|
if (i > 0) {
|
||||||
{
|
|
||||||
if (actions[i - 1].address != AddressIn)
|
if (actions[i - 1].address != AddressIn)
|
||||||
{
|
|
||||||
LOG_WARNING("Scan chain 7 shifted out unexpected address");
|
LOG_WARNING("Scan chain 7 shifted out unexpected address");
|
||||||
}
|
|
||||||
|
|
||||||
if (!actions[i - 1].write)
|
if (!actions[i - 1].write)
|
||||||
{
|
|
||||||
actions[i - 1].value = DataIn;
|
actions[i - 1].value = DataIn;
|
||||||
}
|
else {
|
||||||
else
|
|
||||||
{
|
|
||||||
if (actions[i - 1].value != DataIn)
|
if (actions[i - 1].value != DataIn)
|
||||||
{
|
|
||||||
LOG_WARNING("Scan chain 7 shifted out unexpected data");
|
LOG_WARNING("Scan chain 7 shifted out unexpected data");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -970,14 +962,13 @@ int arm11_sc7_run(struct arm11_common * arm11, struct arm11_sc7_action * actions
|
||||||
* \param arm11 Target state variable.
|
* \param arm11 Target state variable.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
int arm11_sc7_clear_vbw(struct arm11_common * arm11)
|
int arm11_sc7_clear_vbw(struct arm11_common *arm11)
|
||||||
{
|
{
|
||||||
size_t clear_bw_size = arm11->brp + 1;
|
size_t clear_bw_size = arm11->brp + 1;
|
||||||
struct arm11_sc7_action *clear_bw = malloc(sizeof(struct arm11_sc7_action) * clear_bw_size);
|
struct arm11_sc7_action *clear_bw = malloc(sizeof(struct arm11_sc7_action) * clear_bw_size);
|
||||||
struct arm11_sc7_action * pos = clear_bw;
|
struct arm11_sc7_action *pos = clear_bw;
|
||||||
|
|
||||||
for (size_t i = 0; i < clear_bw_size; i++)
|
for (size_t i = 0; i < clear_bw_size; i++) {
|
||||||
{
|
|
||||||
clear_bw[i].write = true;
|
clear_bw[i].write = true;
|
||||||
clear_bw[i].value = 0;
|
clear_bw[i].value = 0;
|
||||||
}
|
}
|
||||||
|
@ -990,7 +981,7 @@ int arm11_sc7_clear_vbw(struct arm11_common * arm11)
|
||||||
int retval;
|
int retval;
|
||||||
retval = arm11_sc7_run(arm11, clear_bw, clear_bw_size);
|
retval = arm11_sc7_run(arm11, clear_bw, clear_bw_size);
|
||||||
|
|
||||||
free (clear_bw);
|
free(clear_bw);
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
@ -1000,7 +991,7 @@ int arm11_sc7_clear_vbw(struct arm11_common * arm11)
|
||||||
* \param arm11 Target state variable.
|
* \param arm11 Target state variable.
|
||||||
* \param value Value to be written
|
* \param value Value to be written
|
||||||
*/
|
*/
|
||||||
int arm11_sc7_set_vcr(struct arm11_common * arm11, uint32_t value)
|
int arm11_sc7_set_vcr(struct arm11_common *arm11, uint32_t value)
|
||||||
{
|
{
|
||||||
struct arm11_sc7_action set_vcr;
|
struct arm11_sc7_action set_vcr;
|
||||||
|
|
||||||
|
@ -1011,8 +1002,6 @@ int arm11_sc7_set_vcr(struct arm11_common * arm11, uint32_t value)
|
||||||
return arm11_sc7_run(arm11, &set_vcr, 1);
|
return arm11_sc7_run(arm11, &set_vcr, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/** Read word from address
|
/** Read word from address
|
||||||
*
|
*
|
||||||
* \param arm11 Target state variable.
|
* \param arm11 Target state variable.
|
||||||
|
@ -1020,7 +1009,7 @@ int arm11_sc7_set_vcr(struct arm11_common * arm11, uint32_t value)
|
||||||
* \param result Pointer where to store result
|
* \param result Pointer where to store result
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
int arm11_read_memory_word(struct arm11_common * arm11, uint32_t address, uint32_t * result)
|
int arm11_read_memory_word(struct arm11_common *arm11, uint32_t address, uint32_t *result)
|
||||||
{
|
{
|
||||||
int retval;
|
int retval;
|
||||||
retval = arm11_run_instr_data_prepare(arm11);
|
retval = arm11_run_instr_data_prepare(arm11);
|
||||||
|
@ -1036,7 +1025,6 @@ int arm11_read_memory_word(struct arm11_common * arm11, uint32_t address, uint32
|
||||||
return arm11_run_instr_data_finish(arm11);
|
return arm11_run_instr_data_finish(arm11);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
@ -28,7 +29,6 @@
|
||||||
#include "register.h"
|
#include "register.h"
|
||||||
#include "arm_opcodes.h"
|
#include "arm_opcodes.h"
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* For information about the ARM920T, see ARM DDI 0151C especially
|
* For information about the ARM920T, see ARM DDI 0151C especially
|
||||||
* Chapter 9 about debug support, which shows how to manipulate each
|
* Chapter 9 about debug support, which shows how to manipulate each
|
||||||
|
@ -234,8 +234,8 @@ static int arm920t_execute_cp15(struct target *target, uint32_t cp15_opcode,
|
||||||
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) {
|
||||||
LOG_ERROR("failed executing JTAG queue");
|
LOG_ERROR("failed executing JTAG queue");
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
@ -247,7 +247,7 @@ static int arm920t_read_cp15_interpreted(struct target *target,
|
||||||
uint32_t cp15_opcode, uint32_t address, uint32_t *value)
|
uint32_t cp15_opcode, uint32_t address, uint32_t *value)
|
||||||
{
|
{
|
||||||
struct arm *arm = target_to_arm(target);
|
struct arm *arm = target_to_arm(target);
|
||||||
uint32_t* regs_p[1];
|
uint32_t *regs_p[1];
|
||||||
uint32_t regs[2];
|
uint32_t regs[2];
|
||||||
uint32_t cp15c15 = 0x0;
|
uint32_t cp15c15 = 0x0;
|
||||||
struct reg *r = arm->core_cache->reg_list;
|
struct reg *r = arm->core_cache->reg_list;
|
||||||
|
@ -280,8 +280,7 @@ static int arm920t_read_cp15_interpreted(struct target *target,
|
||||||
cp15_opcode, address, *value);
|
cp15_opcode, address, *value);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
@ -325,8 +324,7 @@ int arm920t_write_cp15_interpreted(struct target *target,
|
||||||
cp15_opcode, value, address);
|
cp15_opcode, value, address);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
@ -337,22 +335,23 @@ int arm920t_write_cp15_interpreted(struct target *target,
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
// EXPORTED to FA256
|
/* EXPORTED to FA256 */
|
||||||
int arm920t_get_ttb(struct target *target, uint32_t *result)
|
int arm920t_get_ttb(struct target *target, uint32_t *result)
|
||||||
{
|
{
|
||||||
int retval;
|
int retval;
|
||||||
uint32_t ttb = 0x0;
|
uint32_t ttb = 0x0;
|
||||||
|
|
||||||
if ((retval = arm920t_read_cp15_interpreted(target,
|
retval = arm920t_read_cp15_interpreted(target,
|
||||||
/* FIXME use opcode macro */
|
/* FIXME use opcode macro */
|
||||||
0xeebf0f51, 0x0, &ttb)) != ERROR_OK)
|
0xeebf0f51, 0x0, &ttb);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
*result = ttb;
|
*result = ttb;
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
// EXPORTED to FA256
|
/* EXPORTED to FA256 */
|
||||||
int arm920t_disable_mmu_caches(struct target *target, int mmu,
|
int arm920t_disable_mmu_caches(struct target *target, int mmu,
|
||||||
int d_u_cache, int i_cache)
|
int d_u_cache, int i_cache)
|
||||||
{
|
{
|
||||||
|
@ -380,7 +379,7 @@ int arm920t_disable_mmu_caches(struct target *target, int mmu,
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
// EXPORTED to FA256
|
/* EXPORTED to FA256 */
|
||||||
int arm920t_enable_mmu_caches(struct target *target, int mmu,
|
int arm920t_enable_mmu_caches(struct target *target, int mmu,
|
||||||
int d_u_cache, int i_cache)
|
int d_u_cache, int i_cache)
|
||||||
{
|
{
|
||||||
|
@ -408,7 +407,7 @@ int arm920t_enable_mmu_caches(struct target *target, int mmu,
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
// EXPORTED to FA256
|
/* EXPORTED to FA256 */
|
||||||
int arm920t_post_debug_entry(struct target *target)
|
int arm920t_post_debug_entry(struct target *target)
|
||||||
{
|
{
|
||||||
uint32_t cp15c15;
|
uint32_t cp15c15;
|
||||||
|
@ -425,8 +424,7 @@ int arm920t_post_debug_entry(struct target *target)
|
||||||
return retval;
|
return retval;
|
||||||
LOG_DEBUG("cp15_control_reg: %8.8" PRIx32, arm920t->cp15_control_reg);
|
LOG_DEBUG("cp15_control_reg: %8.8" PRIx32, arm920t->cp15_control_reg);
|
||||||
|
|
||||||
if (arm920t->armv4_5_mmu.armv4_5_cache.ctype == -1)
|
if (arm920t->armv4_5_mmu.armv4_5_cache.ctype == -1) {
|
||||||
{
|
|
||||||
uint32_t cache_type_reg;
|
uint32_t cache_type_reg;
|
||||||
/* identify caches */
|
/* identify caches */
|
||||||
retval = arm920t_read_cp15_physical(target,
|
retval = arm920t_read_cp15_physical(target,
|
||||||
|
@ -447,8 +445,8 @@ int arm920t_post_debug_entry(struct target *target)
|
||||||
arm920t->armv4_5_mmu.armv4_5_cache.i_cache_enabled =
|
arm920t->armv4_5_mmu.armv4_5_cache.i_cache_enabled =
|
||||||
(arm920t->cp15_control_reg & 0x1000U) ? 1 : 0;
|
(arm920t->cp15_control_reg & 0x1000U) ? 1 : 0;
|
||||||
|
|
||||||
/* save i/d fault status and address register */
|
/* save i/d fault status and address register
|
||||||
/* FIXME use opcode macros */
|
* FIXME use opcode macros */
|
||||||
retval = arm920t_read_cp15_interpreted(target, 0xee150f10, 0x0, &arm920t->d_fsr);
|
retval = arm920t_read_cp15_interpreted(target, 0xee150f10, 0x0, &arm920t->d_fsr);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
@ -466,8 +464,7 @@ int arm920t_post_debug_entry(struct target *target)
|
||||||
", I FSR: 0x%8.8" PRIx32 ", I FAR: 0x%8.8" PRIx32,
|
", I FSR: 0x%8.8" PRIx32 ", I FAR: 0x%8.8" PRIx32,
|
||||||
arm920t->d_fsr, arm920t->d_far, arm920t->i_fsr, arm920t->i_far);
|
arm920t->d_fsr, arm920t->d_far, arm920t->i_fsr, arm920t->i_far);
|
||||||
|
|
||||||
if (arm920t->preserve_cache)
|
if (arm920t->preserve_cache) {
|
||||||
{
|
|
||||||
/* read-modify-write CP15 test state register
|
/* read-modify-write CP15 test state register
|
||||||
* to disable I/D-cache linefills */
|
* to disable I/D-cache linefills */
|
||||||
retval = arm920t_read_cp15_physical(target,
|
retval = arm920t_read_cp15_physical(target,
|
||||||
|
@ -486,7 +483,7 @@ int arm920t_post_debug_entry(struct target *target)
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
// EXPORTED to FA256
|
/* EXPORTED to FA256 */
|
||||||
void arm920t_pre_restore_context(struct target *target)
|
void arm920t_pre_restore_context(struct target *target)
|
||||||
{
|
{
|
||||||
uint32_t cp15c15;
|
uint32_t cp15c15;
|
||||||
|
@ -500,8 +497,7 @@ void arm920t_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 (arm920t->preserve_cache)
|
if (arm920t->preserve_cache) {
|
||||||
{
|
|
||||||
arm920t_read_cp15_physical(target,
|
arm920t_read_cp15_physical(target,
|
||||||
CP15PHYS_TESTSTATE, &cp15c15);
|
CP15PHYS_TESTSTATE, &cp15c15);
|
||||||
jtag_execute_queue();
|
jtag_execute_queue();
|
||||||
|
@ -527,15 +523,13 @@ static int arm920t_verify_pointer(struct command_context *cmd_ctx,
|
||||||
/** Logs summary of ARM920 state for a halted target. */
|
/** Logs summary of ARM920 state for a halted target. */
|
||||||
int arm920t_arch_state(struct target *target)
|
int arm920t_arch_state(struct target *target)
|
||||||
{
|
{
|
||||||
static const char *state[] =
|
static const char *state[] = {
|
||||||
{
|
|
||||||
"disabled", "enabled"
|
"disabled", "enabled"
|
||||||
};
|
};
|
||||||
|
|
||||||
struct arm920t_common *arm920t = target_to_arm920(target);
|
struct arm920t_common *arm920t = target_to_arm920(target);
|
||||||
|
|
||||||
if (arm920t->common_magic != ARM920T_COMMON_MAGIC)
|
if (arm920t->common_magic != ARM920T_COMMON_MAGIC) {
|
||||||
{
|
|
||||||
LOG_ERROR("BUG: %s", arm920_not);
|
LOG_ERROR("BUG: %s", arm920_not);
|
||||||
return ERROR_TARGET_INVALID;
|
return ERROR_TARGET_INVALID;
|
||||||
}
|
}
|
||||||
|
@ -607,7 +601,6 @@ static int arm920t_write_phys_memory(struct target *target,
|
||||||
address, size, count, buffer);
|
address, size, count, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** 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 arm920t_write_memory(struct target *target, uint32_t address,
|
int arm920t_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)
|
||||||
|
@ -624,8 +617,7 @@ int arm920t_write_memory(struct target *target, uint32_t address,
|
||||||
* 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 (arm920t->armv4_5_mmu.mmu_enabled && (count == 1) &&
|
if (arm920t->armv4_5_mmu.mmu_enabled && (count == 1) &&
|
||||||
((size==2) || (size==4)))
|
((size == 2) || (size == 4))) {
|
||||||
{
|
|
||||||
/* special case the handling of single word writes to
|
/* special case the handling of single word writes to
|
||||||
* bypass MMU, to allow implementation of breakpoints
|
* bypass MMU, to allow implementation of breakpoints
|
||||||
* in memory marked read only
|
* in memory marked read only
|
||||||
|
@ -642,10 +634,8 @@ int arm920t_write_memory(struct target *target, uint32_t address,
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
if (arm920t->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled)
|
if (arm920t->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled) {
|
||||||
{
|
if (cb & 0x1) {
|
||||||
if (cb & 0x1)
|
|
||||||
{
|
|
||||||
LOG_DEBUG("D-Cache buffered, "
|
LOG_DEBUG("D-Cache buffered, "
|
||||||
"drain write buffer");
|
"drain write buffer");
|
||||||
/*
|
/*
|
||||||
|
@ -660,8 +650,7 @@ int arm920t_write_memory(struct target *target, uint32_t address,
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cb == 0x3)
|
if (cb == 0x3) {
|
||||||
{
|
|
||||||
/*
|
/*
|
||||||
* Write back memory ? -> clean cache
|
* Write back memory ? -> clean cache
|
||||||
*
|
*
|
||||||
|
@ -689,8 +678,7 @@ int arm920t_write_memory(struct target *target, uint32_t address,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Cached ? */
|
/* Cached ? */
|
||||||
if (cb & 0x2)
|
if (cb & 0x2) {
|
||||||
{
|
|
||||||
/*
|
/*
|
||||||
* Cached ? -> Invalidate data cache using MVA
|
* Cached ? -> Invalidate data cache using MVA
|
||||||
*
|
*
|
||||||
|
@ -715,10 +703,9 @@ int arm920t_write_memory(struct target *target, uint32_t address,
|
||||||
count, buffer);
|
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,
|
if (retval != ERROR_OK)
|
||||||
size, count, buffer)) != ERROR_OK)
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -726,10 +713,8 @@ int arm920t_write_memory(struct target *target, uint32_t address,
|
||||||
* the DCache is forced to write-through,
|
* the DCache is forced to write-through,
|
||||||
* so we don't have to clean it here
|
* so we don't have to clean it here
|
||||||
*/
|
*/
|
||||||
if (arm920t->armv4_5_mmu.armv4_5_cache.i_cache_enabled)
|
if (arm920t->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
|
||||||
* mcr 15, 0, r0, cr7, cr5, {1}
|
* mcr 15, 0, r0, cr7, cr5, {1}
|
||||||
*/
|
*/
|
||||||
|
@ -740,9 +725,7 @@ int arm920t_write_memory(struct target *target, uint32_t address,
|
||||||
0x0, address & cache_mask);
|
0x0, address & cache_mask);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
/* invalidate ICache
|
/* invalidate ICache
|
||||||
* mcr 15, 0, r0, cr7, cr5, {0}
|
* mcr 15, 0, r0, cr7, cr5, {0}
|
||||||
*/
|
*/
|
||||||
|
@ -757,7 +740,7 @@ int arm920t_write_memory(struct target *target, uint32_t address,
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
// EXPORTED to FA256
|
/* EXPORTED to FA256 */
|
||||||
int arm920t_soft_reset_halt(struct target *target)
|
int arm920t_soft_reset_halt(struct target *target)
|
||||||
{
|
{
|
||||||
int retval = ERROR_OK;
|
int retval = ERROR_OK;
|
||||||
|
@ -766,38 +749,27 @@ int arm920t_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 >= 3) {
|
||||||
if (debug_level >= 3)
|
|
||||||
{
|
|
||||||
/* 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;
|
||||||
}
|
}
|
||||||
|
@ -877,7 +849,7 @@ static int arm920t_target_create(struct target *target, Jim_Interp *interp)
|
||||||
{
|
{
|
||||||
struct arm920t_common *arm920t;
|
struct arm920t_common *arm920t;
|
||||||
|
|
||||||
arm920t = calloc(1,sizeof(struct arm920t_common));
|
arm920t = calloc(1, sizeof(struct arm920t_common));
|
||||||
return arm920t_init_arch_info(target, arm920t, target->tap);
|
return arm920t_init_arch_info(target, arm920t, target->tap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -903,12 +875,10 @@ COMMAND_HANDLER(arm920t_handle_read_cache_command)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
if (CMD_ARGC != 1)
|
if (CMD_ARGC != 1)
|
||||||
{
|
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
}
|
|
||||||
|
|
||||||
if ((output = fopen(CMD_ARGV[0], "w")) == NULL)
|
output = fopen(CMD_ARGV[0], "w");
|
||||||
{
|
if (output == NULL) {
|
||||||
LOG_DEBUG("error opening cache content file");
|
LOG_DEBUG("error opening cache content file");
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
@ -918,10 +888,9 @@ COMMAND_HANDLER(arm920t_handle_read_cache_command)
|
||||||
|
|
||||||
/* disable MMU and Caches */
|
/* disable MMU and Caches */
|
||||||
arm920t_read_cp15_physical(target, CP15PHYS_CTRL, &cp15_ctrl);
|
arm920t_read_cp15_physical(target, CP15PHYS_CTRL, &cp15_ctrl);
|
||||||
if ((retval = jtag_execute_queue()) != ERROR_OK)
|
retval = jtag_execute_queue();
|
||||||
{
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
|
||||||
cp15_ctrl_saved = cp15_ctrl;
|
cp15_ctrl_saved = cp15_ctrl;
|
||||||
cp15_ctrl &= ~(ARMV4_5_MMU_ENABLED
|
cp15_ctrl &= ~(ARMV4_5_MMU_ENABLED
|
||||||
| ARMV4_5_D_U_CACHE_ENABLED | ARMV4_5_I_CACHE_ENABLED);
|
| ARMV4_5_D_U_CACHE_ENABLED | ARMV4_5_I_CACHE_ENABLED);
|
||||||
|
@ -937,8 +906,7 @@ COMMAND_HANDLER(arm920t_handle_read_cache_command)
|
||||||
/* go through segments 0 to nsets (8 on ARM920T, 4 on ARM922T) */
|
/* go through segments 0 to nsets (8 on ARM920T, 4 on ARM922T) */
|
||||||
for (segment = 0;
|
for (segment = 0;
|
||||||
segment < arm920t->armv4_5_mmu.armv4_5_cache.d_u_size.nsets;
|
segment < arm920t->armv4_5_mmu.armv4_5_cache.d_u_size.nsets;
|
||||||
segment++)
|
segment++) {
|
||||||
{
|
|
||||||
fprintf(output, "\nsegment: %i\n----------", segment);
|
fprintf(output, "\nsegment: %i\n----------", segment);
|
||||||
|
|
||||||
/* Ra: r0 = SBZ(31:8):segment(7:5):SBZ(4:0) */
|
/* Ra: r0 = SBZ(31:8):segment(7:5):SBZ(4:0) */
|
||||||
|
@ -952,7 +920,7 @@ COMMAND_HANDLER(arm920t_handle_read_cache_command)
|
||||||
|
|
||||||
/* D CAM Read, loads current victim into C15.C.D.Ind */
|
/* D CAM Read, loads current victim into C15.C.D.Ind */
|
||||||
arm920t_execute_cp15(target,
|
arm920t_execute_cp15(target,
|
||||||
ARMV4_5_MCR(15,2,0,15,6,2), ARMV4_5_LDR(1, 0));
|
ARMV4_5_MCR(15, 2, 0, 15, 6, 2), ARMV4_5_LDR(1, 0));
|
||||||
|
|
||||||
/* read current victim */
|
/* read current victim */
|
||||||
arm920t_read_cp15_physical(target,
|
arm920t_read_cp15_physical(target,
|
||||||
|
@ -963,8 +931,7 @@ COMMAND_HANDLER(arm920t_handle_read_cache_command)
|
||||||
arm920t_write_cp15_physical(target,
|
arm920t_write_cp15_physical(target,
|
||||||
CP15PHYS_TESTSTATE, cp15c15);
|
CP15PHYS_TESTSTATE, cp15c15);
|
||||||
|
|
||||||
for (index_t = 0; index_t < 64; index_t++)
|
for (index_t = 0; index_t < 64; index_t++) {
|
||||||
{
|
|
||||||
/* Ra:
|
/* Ra:
|
||||||
* r0 = index(31:26):SBZ(25:8):segment(7:5):SBZ(4:0)
|
* r0 = index(31:26):SBZ(25:8):segment(7:5):SBZ(4:0)
|
||||||
*/
|
*/
|
||||||
|
@ -978,16 +945,16 @@ COMMAND_HANDLER(arm920t_handle_read_cache_command)
|
||||||
|
|
||||||
/* Write DCache victim */
|
/* Write DCache victim */
|
||||||
arm920t_execute_cp15(target,
|
arm920t_execute_cp15(target,
|
||||||
ARMV4_5_MCR(15,0,0,9,1,0), ARMV4_5_LDR(1, 0));
|
ARMV4_5_MCR(15, 0, 0, 9, 1, 0), ARMV4_5_LDR(1, 0));
|
||||||
|
|
||||||
/* Read D RAM */
|
/* Read D RAM */
|
||||||
arm920t_execute_cp15(target,
|
arm920t_execute_cp15(target,
|
||||||
ARMV4_5_MCR(15,2,0,15,10,2),
|
ARMV4_5_MCR(15, 2, 0, 15, 10, 2),
|
||||||
ARMV4_5_LDMIA(0, 0x1fe, 0, 0));
|
ARMV4_5_LDMIA(0, 0x1fe, 0, 0));
|
||||||
|
|
||||||
/* Read D CAM */
|
/* Read D CAM */
|
||||||
arm920t_execute_cp15(target,
|
arm920t_execute_cp15(target,
|
||||||
ARMV4_5_MCR(15,2,0,15,6,2),
|
ARMV4_5_MCR(15, 2, 0, 15, 6, 2),
|
||||||
ARMV4_5_LDR(9, 0));
|
ARMV4_5_LDR(9, 0));
|
||||||
|
|
||||||
/* clear interpret mode */
|
/* clear interpret mode */
|
||||||
|
@ -997,10 +964,9 @@ COMMAND_HANDLER(arm920t_handle_read_cache_command)
|
||||||
|
|
||||||
/* read D RAM and CAM content */
|
/* read D RAM and CAM content */
|
||||||
arm9tdmi_read_core_regs(target, 0x3fe, regs_p);
|
arm9tdmi_read_core_regs(target, 0x3fe, regs_p);
|
||||||
if ((retval = jtag_execute_queue()) != ERROR_OK)
|
retval = jtag_execute_queue();
|
||||||
{
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
|
||||||
|
|
||||||
/* mask LFSR[6] */
|
/* mask LFSR[6] */
|
||||||
regs[9] &= 0xfffffffe;
|
regs[9] &= 0xfffffffe;
|
||||||
|
@ -1009,8 +975,7 @@ COMMAND_HANDLER(arm920t_handle_read_cache_command)
|
||||||
segment, index_t, regs[9],
|
segment, index_t, regs[9],
|
||||||
(regs[9] & 0x10) ? "valid" : "invalid");
|
(regs[9] & 0x10) ? "valid" : "invalid");
|
||||||
|
|
||||||
for (i = 1; i < 9; i++)
|
for (i = 1; i < 9; i++) {
|
||||||
{
|
|
||||||
fprintf(output, "%i: 0x%8.8" PRIx32 "\n",
|
fprintf(output, "%i: 0x%8.8" PRIx32 "\n",
|
||||||
i-1, regs[i]);
|
i-1, regs[i]);
|
||||||
}
|
}
|
||||||
|
@ -1028,7 +993,7 @@ COMMAND_HANDLER(arm920t_handle_read_cache_command)
|
||||||
|
|
||||||
/* Write DCache victim */
|
/* Write DCache victim */
|
||||||
arm920t_execute_cp15(target,
|
arm920t_execute_cp15(target,
|
||||||
ARMV4_5_MCR(15,0,0,9,1,0), ARMV4_5_LDR(1, 0));
|
ARMV4_5_MCR(15, 0, 0, 9, 1, 0), ARMV4_5_LDR(1, 0));
|
||||||
|
|
||||||
/* clear interpret mode */
|
/* clear interpret mode */
|
||||||
cp15c15 &= ~0x1;
|
cp15c15 &= ~0x1;
|
||||||
|
@ -1042,8 +1007,7 @@ COMMAND_HANDLER(arm920t_handle_read_cache_command)
|
||||||
/* go through segments 0 to nsets (8 on ARM920T, 4 on ARM922T) */
|
/* go through segments 0 to nsets (8 on ARM920T, 4 on ARM922T) */
|
||||||
for (segment = 0;
|
for (segment = 0;
|
||||||
segment < arm920t->armv4_5_mmu.armv4_5_cache.d_u_size.nsets;
|
segment < arm920t->armv4_5_mmu.armv4_5_cache.d_u_size.nsets;
|
||||||
segment++)
|
segment++) {
|
||||||
{
|
|
||||||
fprintf(output, "segment: %i\n----------", segment);
|
fprintf(output, "segment: %i\n----------", segment);
|
||||||
|
|
||||||
/* Ra: r0 = SBZ(31:8):segment(7:5):SBZ(4:0) */
|
/* Ra: r0 = SBZ(31:8):segment(7:5):SBZ(4:0) */
|
||||||
|
@ -1057,7 +1021,7 @@ COMMAND_HANDLER(arm920t_handle_read_cache_command)
|
||||||
|
|
||||||
/* I CAM Read, loads current victim into C15.C.I.Ind */
|
/* I CAM Read, loads current victim into C15.C.I.Ind */
|
||||||
arm920t_execute_cp15(target,
|
arm920t_execute_cp15(target,
|
||||||
ARMV4_5_MCR(15,2,0,15,5,2), ARMV4_5_LDR(1, 0));
|
ARMV4_5_MCR(15, 2, 0, 15, 5, 2), ARMV4_5_LDR(1, 0));
|
||||||
|
|
||||||
/* read current victim */
|
/* read current victim */
|
||||||
arm920t_read_cp15_physical(target, CP15PHYS_ICACHE_IDX,
|
arm920t_read_cp15_physical(target, CP15PHYS_ICACHE_IDX,
|
||||||
|
@ -1068,8 +1032,7 @@ COMMAND_HANDLER(arm920t_handle_read_cache_command)
|
||||||
arm920t_write_cp15_physical(target,
|
arm920t_write_cp15_physical(target,
|
||||||
CP15PHYS_TESTSTATE, cp15c15);
|
CP15PHYS_TESTSTATE, cp15c15);
|
||||||
|
|
||||||
for (index_t = 0; index_t < 64; index_t++)
|
for (index_t = 0; index_t < 64; index_t++) {
|
||||||
{
|
|
||||||
/* Ra:
|
/* Ra:
|
||||||
* r0 = index(31:26):SBZ(25:8):segment(7:5):SBZ(4:0)
|
* r0 = index(31:26):SBZ(25:8):segment(7:5):SBZ(4:0)
|
||||||
*/
|
*/
|
||||||
|
@ -1083,16 +1046,16 @@ COMMAND_HANDLER(arm920t_handle_read_cache_command)
|
||||||
|
|
||||||
/* Write ICache victim */
|
/* Write ICache victim */
|
||||||
arm920t_execute_cp15(target,
|
arm920t_execute_cp15(target,
|
||||||
ARMV4_5_MCR(15,0,0,9,1,1), ARMV4_5_LDR(1, 0));
|
ARMV4_5_MCR(15, 0, 0, 9, 1, 1), ARMV4_5_LDR(1, 0));
|
||||||
|
|
||||||
/* Read I RAM */
|
/* Read I RAM */
|
||||||
arm920t_execute_cp15(target,
|
arm920t_execute_cp15(target,
|
||||||
ARMV4_5_MCR(15,2,0,15,9,2),
|
ARMV4_5_MCR(15, 2, 0, 15, 9, 2),
|
||||||
ARMV4_5_LDMIA(0, 0x1fe, 0, 0));
|
ARMV4_5_LDMIA(0, 0x1fe, 0, 0));
|
||||||
|
|
||||||
/* Read I CAM */
|
/* Read I CAM */
|
||||||
arm920t_execute_cp15(target,
|
arm920t_execute_cp15(target,
|
||||||
ARMV4_5_MCR(15,2,0,15,5,2),
|
ARMV4_5_MCR(15, 2, 0, 15, 5, 2),
|
||||||
ARMV4_5_LDR(9, 0));
|
ARMV4_5_LDR(9, 0));
|
||||||
|
|
||||||
/* clear interpret mode */
|
/* clear interpret mode */
|
||||||
|
@ -1102,10 +1065,9 @@ COMMAND_HANDLER(arm920t_handle_read_cache_command)
|
||||||
|
|
||||||
/* read I RAM and CAM content */
|
/* read I RAM and CAM content */
|
||||||
arm9tdmi_read_core_regs(target, 0x3fe, regs_p);
|
arm9tdmi_read_core_regs(target, 0x3fe, regs_p);
|
||||||
if ((retval = jtag_execute_queue()) != ERROR_OK)
|
retval = jtag_execute_queue();
|
||||||
{
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
|
||||||
|
|
||||||
/* mask LFSR[6] */
|
/* mask LFSR[6] */
|
||||||
regs[9] &= 0xfffffffe;
|
regs[9] &= 0xfffffffe;
|
||||||
|
@ -1114,8 +1076,7 @@ COMMAND_HANDLER(arm920t_handle_read_cache_command)
|
||||||
segment, index_t, regs[9],
|
segment, index_t, regs[9],
|
||||||
(regs[9] & 0x10) ? "valid" : "invalid");
|
(regs[9] & 0x10) ? "valid" : "invalid");
|
||||||
|
|
||||||
for (i = 1; i < 9; i++)
|
for (i = 1; i < 9; i++) {
|
||||||
{
|
|
||||||
fprintf(output, "%i: 0x%8.8" PRIx32 "\n",
|
fprintf(output, "%i: 0x%8.8" PRIx32 "\n",
|
||||||
i-1, regs[i]);
|
i-1, regs[i]);
|
||||||
}
|
}
|
||||||
|
@ -1132,7 +1093,7 @@ COMMAND_HANDLER(arm920t_handle_read_cache_command)
|
||||||
|
|
||||||
/* Write ICache victim */
|
/* Write ICache victim */
|
||||||
arm920t_execute_cp15(target,
|
arm920t_execute_cp15(target,
|
||||||
ARMV4_5_MCR(15,0,0,9,1,1), ARMV4_5_LDR(1, 0));
|
ARMV4_5_MCR(15, 0, 0, 9, 1, 1), ARMV4_5_LDR(1, 0));
|
||||||
|
|
||||||
/* clear interpret mode */
|
/* clear interpret mode */
|
||||||
cp15c15 &= ~0x1;
|
cp15c15 &= ~0x1;
|
||||||
|
@ -1148,8 +1109,7 @@ COMMAND_HANDLER(arm920t_handle_read_cache_command)
|
||||||
|
|
||||||
fclose(output);
|
fclose(output);
|
||||||
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
@ -1197,12 +1157,10 @@ COMMAND_HANDLER(arm920t_handle_read_mmu_command)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
if (CMD_ARGC != 1)
|
if (CMD_ARGC != 1)
|
||||||
{
|
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
}
|
|
||||||
|
|
||||||
if ((output = fopen(CMD_ARGV[0], "w")) == NULL)
|
output = fopen(CMD_ARGV[0], "w");
|
||||||
{
|
if (output == NULL) {
|
||||||
LOG_DEBUG("error opening mmu content file");
|
LOG_DEBUG("error opening mmu content file");
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
@ -1212,10 +1170,9 @@ COMMAND_HANDLER(arm920t_handle_read_mmu_command)
|
||||||
|
|
||||||
/* disable MMU and Caches */
|
/* disable MMU and Caches */
|
||||||
arm920t_read_cp15_physical(target, CP15PHYS_CTRL, &cp15_ctrl);
|
arm920t_read_cp15_physical(target, CP15PHYS_CTRL, &cp15_ctrl);
|
||||||
if ((retval = jtag_execute_queue()) != ERROR_OK)
|
retval = jtag_execute_queue();
|
||||||
{
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
|
||||||
cp15_ctrl_saved = cp15_ctrl;
|
cp15_ctrl_saved = cp15_ctrl;
|
||||||
cp15_ctrl &= ~(ARMV4_5_MMU_ENABLED
|
cp15_ctrl &= ~(ARMV4_5_MMU_ENABLED
|
||||||
| ARMV4_5_D_U_CACHE_ENABLED | ARMV4_5_I_CACHE_ENABLED);
|
| ARMV4_5_D_U_CACHE_ENABLED | ARMV4_5_I_CACHE_ENABLED);
|
||||||
|
@ -1223,10 +1180,9 @@ COMMAND_HANDLER(arm920t_handle_read_mmu_command)
|
||||||
|
|
||||||
/* read CP15 test state register */
|
/* read CP15 test state register */
|
||||||
arm920t_read_cp15_physical(target, CP15PHYS_TESTSTATE, &cp15c15);
|
arm920t_read_cp15_physical(target, CP15PHYS_TESTSTATE, &cp15c15);
|
||||||
if ((retval = jtag_execute_queue()) != ERROR_OK)
|
retval = jtag_execute_queue();
|
||||||
{
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
|
||||||
|
|
||||||
/* prepare reading D TLB content
|
/* prepare reading D TLB content
|
||||||
* */
|
* */
|
||||||
|
@ -1237,7 +1193,7 @@ COMMAND_HANDLER(arm920t_handle_read_mmu_command)
|
||||||
|
|
||||||
/* Read D TLB lockdown */
|
/* Read D TLB lockdown */
|
||||||
arm920t_execute_cp15(target,
|
arm920t_execute_cp15(target,
|
||||||
ARMV4_5_MRC(15,0,0,10,0,0), ARMV4_5_LDR(1, 0));
|
ARMV4_5_MRC(15, 0, 0, 10, 0, 0), ARMV4_5_LDR(1, 0));
|
||||||
|
|
||||||
/* clear interpret mode */
|
/* clear interpret mode */
|
||||||
cp15c15 &= ~0x1;
|
cp15c15 &= ~0x1;
|
||||||
|
@ -1245,14 +1201,12 @@ COMMAND_HANDLER(arm920t_handle_read_mmu_command)
|
||||||
|
|
||||||
/* read D TLB lockdown stored to r1 */
|
/* read D TLB lockdown stored to r1 */
|
||||||
arm9tdmi_read_core_regs(target, 0x2, regs_p);
|
arm9tdmi_read_core_regs(target, 0x2, regs_p);
|
||||||
if ((retval = jtag_execute_queue()) != ERROR_OK)
|
retval = jtag_execute_queue();
|
||||||
{
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
|
||||||
Dlockdown = regs[1];
|
Dlockdown = regs[1];
|
||||||
|
|
||||||
for (victim = 0; victim < 64; victim += 8)
|
for (victim = 0; victim < 64; victim += 8) {
|
||||||
{
|
|
||||||
/* new lockdown value: base[31:26]:victim[25:20]:SBZ[19:1]:p[0]
|
/* new lockdown value: base[31:26]:victim[25:20]:SBZ[19:1]:p[0]
|
||||||
* base remains unchanged, victim goes through entries 0 to 63
|
* base remains unchanged, victim goes through entries 0 to 63
|
||||||
*/
|
*/
|
||||||
|
@ -1266,12 +1220,12 @@ COMMAND_HANDLER(arm920t_handle_read_mmu_command)
|
||||||
|
|
||||||
/* Write D TLB lockdown */
|
/* Write D TLB lockdown */
|
||||||
arm920t_execute_cp15(target,
|
arm920t_execute_cp15(target,
|
||||||
ARMV4_5_MCR(15,0,0,10,0,0),
|
ARMV4_5_MCR(15, 0, 0, 10, 0, 0),
|
||||||
ARMV4_5_STR(1, 0));
|
ARMV4_5_STR(1, 0));
|
||||||
|
|
||||||
/* Read D TLB CAM */
|
/* Read D TLB CAM */
|
||||||
arm920t_execute_cp15(target,
|
arm920t_execute_cp15(target,
|
||||||
ARMV4_5_MCR(15,4,0,15,6,4),
|
ARMV4_5_MCR(15, 4, 0, 15, 6, 4),
|
||||||
ARMV4_5_LDMIA(0, 0x3fc, 0, 0));
|
ARMV4_5_LDMIA(0, 0x3fc, 0, 0));
|
||||||
|
|
||||||
/* clear interpret mode */
|
/* clear interpret mode */
|
||||||
|
@ -1281,17 +1235,15 @@ COMMAND_HANDLER(arm920t_handle_read_mmu_command)
|
||||||
|
|
||||||
/* read D TLB CAM content stored to r2-r9 */
|
/* read D TLB CAM content stored to r2-r9 */
|
||||||
arm9tdmi_read_core_regs(target, 0x3fc, regs_p);
|
arm9tdmi_read_core_regs(target, 0x3fc, regs_p);
|
||||||
if ((retval = jtag_execute_queue()) != ERROR_OK)
|
retval = jtag_execute_queue();
|
||||||
{
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < 8; i++)
|
for (i = 0; i < 8; i++)
|
||||||
d_tlb[victim + i].cam = regs[i + 2];
|
d_tlb[victim + i].cam = regs[i + 2];
|
||||||
}
|
}
|
||||||
|
|
||||||
for (victim = 0; victim < 64; victim++)
|
for (victim = 0; victim < 64; victim++) {
|
||||||
{
|
|
||||||
/* new lockdown value: base[31:26]:victim[25:20]:SBZ[19:1]:p[0]
|
/* new lockdown value: base[31:26]:victim[25:20]:SBZ[19:1]:p[0]
|
||||||
* base remains unchanged, victim goes through entries 0 to 63
|
* base remains unchanged, victim goes through entries 0 to 63
|
||||||
*/
|
*/
|
||||||
|
@ -1305,15 +1257,15 @@ COMMAND_HANDLER(arm920t_handle_read_mmu_command)
|
||||||
|
|
||||||
/* Write D TLB lockdown */
|
/* Write D TLB lockdown */
|
||||||
arm920t_execute_cp15(target,
|
arm920t_execute_cp15(target,
|
||||||
ARMV4_5_MCR(15,0,0,10,0,0), ARMV4_5_STR(1, 0));
|
ARMV4_5_MCR(15, 0, 0, 10, 0, 0), ARMV4_5_STR(1, 0));
|
||||||
|
|
||||||
/* Read D TLB RAM1 */
|
/* Read D TLB RAM1 */
|
||||||
arm920t_execute_cp15(target,
|
arm920t_execute_cp15(target,
|
||||||
ARMV4_5_MCR(15,4,0,15,10,4), ARMV4_5_LDR(2,0));
|
ARMV4_5_MCR(15, 4, 0, 15, 10, 4), ARMV4_5_LDR(2, 0));
|
||||||
|
|
||||||
/* Read D TLB RAM2 */
|
/* Read D TLB RAM2 */
|
||||||
arm920t_execute_cp15(target,
|
arm920t_execute_cp15(target,
|
||||||
ARMV4_5_MCR(15,4,0,15,2,5), ARMV4_5_LDR(3,0));
|
ARMV4_5_MCR(15, 4, 0, 15, 2, 5), ARMV4_5_LDR(3, 0));
|
||||||
|
|
||||||
/* clear interpret mode */
|
/* clear interpret mode */
|
||||||
cp15c15 &= ~0x1;
|
cp15c15 &= ~0x1;
|
||||||
|
@ -1322,10 +1274,9 @@ COMMAND_HANDLER(arm920t_handle_read_mmu_command)
|
||||||
|
|
||||||
/* read D TLB RAM content stored to r2 and r3 */
|
/* read D TLB RAM content stored to r2 and r3 */
|
||||||
arm9tdmi_read_core_regs(target, 0xc, regs_p);
|
arm9tdmi_read_core_regs(target, 0xc, regs_p);
|
||||||
if ((retval = jtag_execute_queue()) != ERROR_OK)
|
retval = jtag_execute_queue();
|
||||||
{
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
|
||||||
|
|
||||||
d_tlb[victim].ram1 = regs[2];
|
d_tlb[victim].ram1 = regs[2];
|
||||||
d_tlb[victim].ram2 = regs[3];
|
d_tlb[victim].ram2 = regs[3];
|
||||||
|
@ -1337,7 +1288,7 @@ COMMAND_HANDLER(arm920t_handle_read_mmu_command)
|
||||||
|
|
||||||
/* Write D TLB lockdown */
|
/* Write D TLB lockdown */
|
||||||
arm920t_execute_cp15(target,
|
arm920t_execute_cp15(target,
|
||||||
ARMV4_5_MCR(15,0,0,10,0,0), ARMV4_5_STR(1, 0));
|
ARMV4_5_MCR(15, 0, 0, 10, 0, 0), ARMV4_5_STR(1, 0));
|
||||||
|
|
||||||
/* prepare reading I TLB content
|
/* prepare reading I TLB content
|
||||||
* */
|
* */
|
||||||
|
@ -1348,7 +1299,7 @@ COMMAND_HANDLER(arm920t_handle_read_mmu_command)
|
||||||
|
|
||||||
/* Read I TLB lockdown */
|
/* Read I TLB lockdown */
|
||||||
arm920t_execute_cp15(target,
|
arm920t_execute_cp15(target,
|
||||||
ARMV4_5_MRC(15,0,0,10,0,1), ARMV4_5_LDR(1, 0));
|
ARMV4_5_MRC(15, 0, 0, 10, 0, 1), ARMV4_5_LDR(1, 0));
|
||||||
|
|
||||||
/* clear interpret mode */
|
/* clear interpret mode */
|
||||||
cp15c15 &= ~0x1;
|
cp15c15 &= ~0x1;
|
||||||
|
@ -1356,14 +1307,12 @@ COMMAND_HANDLER(arm920t_handle_read_mmu_command)
|
||||||
|
|
||||||
/* read I TLB lockdown stored to r1 */
|
/* read I TLB lockdown stored to r1 */
|
||||||
arm9tdmi_read_core_regs(target, 0x2, regs_p);
|
arm9tdmi_read_core_regs(target, 0x2, regs_p);
|
||||||
if ((retval = jtag_execute_queue()) != ERROR_OK)
|
retval = jtag_execute_queue();
|
||||||
{
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
|
||||||
Ilockdown = regs[1];
|
Ilockdown = regs[1];
|
||||||
|
|
||||||
for (victim = 0; victim < 64; victim += 8)
|
for (victim = 0; victim < 64; victim += 8) {
|
||||||
{
|
|
||||||
/* new lockdown value: base[31:26]:victim[25:20]:SBZ[19:1]:p[0]
|
/* new lockdown value: base[31:26]:victim[25:20]:SBZ[19:1]:p[0]
|
||||||
* base remains unchanged, victim goes through entries 0 to 63
|
* base remains unchanged, victim goes through entries 0 to 63
|
||||||
*/
|
*/
|
||||||
|
@ -1377,12 +1326,12 @@ COMMAND_HANDLER(arm920t_handle_read_mmu_command)
|
||||||
|
|
||||||
/* Write I TLB lockdown */
|
/* Write I TLB lockdown */
|
||||||
arm920t_execute_cp15(target,
|
arm920t_execute_cp15(target,
|
||||||
ARMV4_5_MCR(15,0,0,10,0,1),
|
ARMV4_5_MCR(15, 0, 0, 10, 0, 1),
|
||||||
ARMV4_5_STR(1, 0));
|
ARMV4_5_STR(1, 0));
|
||||||
|
|
||||||
/* Read I TLB CAM */
|
/* Read I TLB CAM */
|
||||||
arm920t_execute_cp15(target,
|
arm920t_execute_cp15(target,
|
||||||
ARMV4_5_MCR(15,4,0,15,5,4),
|
ARMV4_5_MCR(15, 4, 0, 15, 5, 4),
|
||||||
ARMV4_5_LDMIA(0, 0x3fc, 0, 0));
|
ARMV4_5_LDMIA(0, 0x3fc, 0, 0));
|
||||||
|
|
||||||
/* clear interpret mode */
|
/* clear interpret mode */
|
||||||
|
@ -1392,17 +1341,15 @@ COMMAND_HANDLER(arm920t_handle_read_mmu_command)
|
||||||
|
|
||||||
/* read I TLB CAM content stored to r2-r9 */
|
/* read I TLB CAM content stored to r2-r9 */
|
||||||
arm9tdmi_read_core_regs(target, 0x3fc, regs_p);
|
arm9tdmi_read_core_regs(target, 0x3fc, regs_p);
|
||||||
if ((retval = jtag_execute_queue()) != ERROR_OK)
|
retval = jtag_execute_queue();
|
||||||
{
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < 8; i++)
|
for (i = 0; i < 8; i++)
|
||||||
i_tlb[i + victim].cam = regs[i + 2];
|
i_tlb[i + victim].cam = regs[i + 2];
|
||||||
}
|
}
|
||||||
|
|
||||||
for (victim = 0; victim < 64; victim++)
|
for (victim = 0; victim < 64; victim++) {
|
||||||
{
|
|
||||||
/* new lockdown value: base[31:26]:victim[25:20]:SBZ[19:1]:p[0]
|
/* new lockdown value: base[31:26]:victim[25:20]:SBZ[19:1]:p[0]
|
||||||
* base remains unchanged, victim goes through entries 0 to 63
|
* base remains unchanged, victim goes through entries 0 to 63
|
||||||
*/
|
*/
|
||||||
|
@ -1416,15 +1363,15 @@ COMMAND_HANDLER(arm920t_handle_read_mmu_command)
|
||||||
|
|
||||||
/* Write I TLB lockdown */
|
/* Write I TLB lockdown */
|
||||||
arm920t_execute_cp15(target,
|
arm920t_execute_cp15(target,
|
||||||
ARMV4_5_MCR(15,0,0,10,0,1), ARMV4_5_STR(1, 0));
|
ARMV4_5_MCR(15, 0, 0, 10, 0, 1), ARMV4_5_STR(1, 0));
|
||||||
|
|
||||||
/* Read I TLB RAM1 */
|
/* Read I TLB RAM1 */
|
||||||
arm920t_execute_cp15(target,
|
arm920t_execute_cp15(target,
|
||||||
ARMV4_5_MCR(15,4,0,15,9,4), ARMV4_5_LDR(2,0));
|
ARMV4_5_MCR(15, 4, 0, 15, 9, 4), ARMV4_5_LDR(2, 0));
|
||||||
|
|
||||||
/* Read I TLB RAM2 */
|
/* Read I TLB RAM2 */
|
||||||
arm920t_execute_cp15(target,
|
arm920t_execute_cp15(target,
|
||||||
ARMV4_5_MCR(15,4,0,15,1,5), ARMV4_5_LDR(3,0));
|
ARMV4_5_MCR(15, 4, 0, 15, 1, 5), ARMV4_5_LDR(3, 0));
|
||||||
|
|
||||||
/* clear interpret mode */
|
/* clear interpret mode */
|
||||||
cp15c15 &= ~0x1;
|
cp15c15 &= ~0x1;
|
||||||
|
@ -1433,10 +1380,9 @@ COMMAND_HANDLER(arm920t_handle_read_mmu_command)
|
||||||
|
|
||||||
/* read I TLB RAM content stored to r2 and r3 */
|
/* read I TLB RAM content stored to r2 and r3 */
|
||||||
arm9tdmi_read_core_regs(target, 0xc, regs_p);
|
arm9tdmi_read_core_regs(target, 0xc, regs_p);
|
||||||
if ((retval = jtag_execute_queue()) != ERROR_OK)
|
retval = jtag_execute_queue();
|
||||||
{
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
|
||||||
|
|
||||||
i_tlb[victim].ram1 = regs[2];
|
i_tlb[victim].ram1 = regs[2];
|
||||||
i_tlb[victim].ram2 = regs[3];
|
i_tlb[victim].ram2 = regs[3];
|
||||||
|
@ -1448,15 +1394,14 @@ COMMAND_HANDLER(arm920t_handle_read_mmu_command)
|
||||||
|
|
||||||
/* Write I TLB lockdown */
|
/* Write I TLB lockdown */
|
||||||
arm920t_execute_cp15(target,
|
arm920t_execute_cp15(target,
|
||||||
ARMV4_5_MCR(15,0,0,10,0,1), ARMV4_5_STR(1, 0));
|
ARMV4_5_MCR(15, 0, 0, 10, 0, 1), ARMV4_5_STR(1, 0));
|
||||||
|
|
||||||
/* restore CP15 MMU and Cache settings */
|
/* restore CP15 MMU and Cache settings */
|
||||||
arm920t_write_cp15_physical(target, CP15PHYS_CTRL, cp15_ctrl_saved);
|
arm920t_write_cp15_physical(target, CP15PHYS_CTRL, cp15_ctrl_saved);
|
||||||
|
|
||||||
/* output data to file */
|
/* output data to file */
|
||||||
fprintf(output, "D TLB content:\n");
|
fprintf(output, "D TLB content:\n");
|
||||||
for (i = 0; i < 64; i++)
|
for (i = 0; i < 64; i++) {
|
||||||
{
|
|
||||||
fprintf(output, "%i: 0x%8.8" PRIx32 " 0x%8.8" PRIx32
|
fprintf(output, "%i: 0x%8.8" PRIx32 " 0x%8.8" PRIx32
|
||||||
" 0x%8.8" PRIx32 " %s\n",
|
" 0x%8.8" PRIx32 " %s\n",
|
||||||
i, d_tlb[i].cam, d_tlb[i].ram1, d_tlb[i].ram2,
|
i, d_tlb[i].cam, d_tlb[i].ram1, d_tlb[i].ram2,
|
||||||
|
@ -1464,8 +1409,7 @@ COMMAND_HANDLER(arm920t_handle_read_mmu_command)
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(output, "\n\nI TLB content:\n");
|
fprintf(output, "\n\nI TLB content:\n");
|
||||||
for (i = 0; i < 64; i++)
|
for (i = 0; i < 64; i++) {
|
||||||
{
|
|
||||||
fprintf(output, "%i: 0x%8.8" PRIx32 " 0x%8.8" PRIx32
|
fprintf(output, "%i: 0x%8.8" PRIx32 " 0x%8.8" PRIx32
|
||||||
" 0x%8.8" PRIx32 " %s\n",
|
" 0x%8.8" PRIx32 " %s\n",
|
||||||
i, i_tlb[i].cam, i_tlb[i].ram1, i_tlb[i].ram2,
|
i, i_tlb[i].cam, i_tlb[i].ram1, i_tlb[i].ram2,
|
||||||
|
@ -1477,8 +1421,7 @@ COMMAND_HANDLER(arm920t_handle_read_mmu_command)
|
||||||
|
|
||||||
fclose(output);
|
fclose(output);
|
||||||
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
@ -1513,8 +1456,7 @@ COMMAND_HANDLER(arm920t_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 "
|
command_print(CMD_CTX, "target must be stopped for "
|
||||||
"\"%s\" command", CMD_NAME);
|
"\"%s\" command", CMD_NAME);
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
|
@ -1523,37 +1465,30 @@ COMMAND_HANDLER(arm920t_handle_cp15_command)
|
||||||
/* one argument, read a register.
|
/* one argument, read a register.
|
||||||
* two arguments, write it.
|
* two arguments, write it.
|
||||||
*/
|
*/
|
||||||
if (CMD_ARGC >= 1)
|
if (CMD_ARGC >= 1) {
|
||||||
{
|
|
||||||
int address;
|
int address;
|
||||||
COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], address);
|
COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], address);
|
||||||
|
|
||||||
if (CMD_ARGC == 1)
|
if (CMD_ARGC == 1) {
|
||||||
{
|
|
||||||
uint32_t value;
|
uint32_t value;
|
||||||
if ((retval = arm920t_read_cp15_physical(target,
|
retval = arm920t_read_cp15_physical(target, address, &value);
|
||||||
address, &value)) != ERROR_OK)
|
if (retval != ERROR_OK) {
|
||||||
{
|
|
||||||
command_print(CMD_CTX,
|
command_print(CMD_CTX,
|
||||||
"couldn't access reg %i", address);
|
"couldn't access reg %i", 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, "%i: %8.8" PRIx32,
|
command_print(CMD_CTX, "%i: %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);
|
||||||
retval = arm920t_write_cp15_physical(target,
|
retval = arm920t_write_cp15_physical(target,
|
||||||
address, value);
|
address, value);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK) {
|
||||||
{
|
|
||||||
command_print(CMD_CTX,
|
command_print(CMD_CTX,
|
||||||
"couldn't access reg %i", address);
|
"couldn't access reg %i", address);
|
||||||
/* REVISIT why lie? "return retval"? */
|
/* REVISIT why lie? "return retval"? */
|
||||||
|
@ -1578,8 +1513,7 @@ COMMAND_HANDLER(arm920t_handle_cp15i_command)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
|
|
||||||
if (target->state != TARGET_HALTED)
|
if (target->state != TARGET_HALTED) {
|
||||||
{
|
|
||||||
command_print(CMD_CTX, "target must be stopped for "
|
command_print(CMD_CTX, "target must be stopped for "
|
||||||
"\"%s\" command", CMD_NAME);
|
"\"%s\" command", CMD_NAME);
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
|
@ -1588,18 +1522,15 @@ COMMAND_HANDLER(arm920t_handle_cp15i_command)
|
||||||
/* one argument, read a register.
|
/* one argument, read a register.
|
||||||
* two arguments, write it.
|
* two arguments, write it.
|
||||||
*/
|
*/
|
||||||
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;
|
||||||
retval = arm920t_read_cp15_interpreted(target,
|
retval = arm920t_read_cp15_interpreted(target,
|
||||||
opcode, 0x0, &value);
|
opcode, 0x0, &value);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK) {
|
||||||
{
|
|
||||||
command_print(CMD_CTX,
|
command_print(CMD_CTX,
|
||||||
"couldn't execute %8.8" PRIx32,
|
"couldn't execute %8.8" PRIx32,
|
||||||
opcode);
|
opcode);
|
||||||
|
@ -1609,15 +1540,12 @@ COMMAND_HANDLER(arm920t_handle_cp15i_command)
|
||||||
|
|
||||||
command_print(CMD_CTX, "%8.8" PRIx32 ": %8.8" PRIx32,
|
command_print(CMD_CTX, "%8.8" PRIx32 ": %8.8" PRIx32,
|
||||||
opcode, value);
|
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);
|
||||||
retval = arm920t_write_cp15_interpreted(target,
|
retval = arm920t_write_cp15_interpreted(target,
|
||||||
opcode, value, 0);
|
opcode, value, 0);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK) {
|
||||||
{
|
|
||||||
command_print(CMD_CTX,
|
command_print(CMD_CTX,
|
||||||
"couldn't execute %8.8" PRIx32,
|
"couldn't execute %8.8" PRIx32,
|
||||||
opcode);
|
opcode);
|
||||||
|
@ -1626,17 +1554,14 @@ COMMAND_HANDLER(arm920t_handle_cp15i_command)
|
||||||
}
|
}
|
||||||
command_print(CMD_CTX, "%8.8" PRIx32 ": %8.8" PRIx32,
|
command_print(CMD_CTX, "%8.8" PRIx32 ": %8.8" PRIx32,
|
||||||
opcode, value);
|
opcode, value);
|
||||||
}
|
} else if (CMD_ARGC == 3) {
|
||||||
else if (CMD_ARGC == 3)
|
|
||||||
{
|
|
||||||
uint32_t value;
|
uint32_t value;
|
||||||
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], value);
|
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], value);
|
||||||
uint32_t address;
|
uint32_t address;
|
||||||
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], address);
|
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], address);
|
||||||
retval = arm920t_write_cp15_interpreted(target,
|
retval = arm920t_write_cp15_interpreted(target,
|
||||||
opcode, value, address);
|
opcode, value, address);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK) {
|
||||||
{
|
|
||||||
command_print(CMD_CTX,
|
command_print(CMD_CTX,
|
||||||
"couldn't execute %8.8" PRIx32, opcode);
|
"couldn't execute %8.8" PRIx32, opcode);
|
||||||
/* REVISIT why lie? "return retval"? */
|
/* REVISIT why lie? "return retval"? */
|
||||||
|
@ -1645,11 +1570,8 @@ COMMAND_HANDLER(arm920t_handle_cp15i_command)
|
||||||
command_print(CMD_CTX, "%8.8" PRIx32 ": %8.8" PRIx32
|
command_print(CMD_CTX, "%8.8" PRIx32 ": %8.8" PRIx32
|
||||||
" %8.8" PRIx32, opcode, value, address);
|
" %8.8" PRIx32, opcode, value, address);
|
||||||
}
|
}
|
||||||
}
|
} else
|
||||||
else
|
|
||||||
{
|
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
}
|
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
@ -1674,8 +1596,7 @@ static int arm920t_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;
|
||||||
}
|
}
|
||||||
|
@ -1691,8 +1612,7 @@ static int arm920t_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;
|
||||||
}
|
}
|
||||||
|
@ -1758,8 +1678,7 @@ const struct command_registration arm920t_command_handlers[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Holds methods for ARM920 targets. */
|
/** Holds methods for ARM920 targets. */
|
||||||
struct target_type arm920t_target =
|
struct target_type arm920t_target = {
|
||||||
{
|
|
||||||
.name = "arm920t",
|
.name = "arm920t",
|
||||||
|
|
||||||
.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 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);
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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,8 +320,7 @@ 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;
|
||||||
}
|
}
|
||||||
|
@ -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,9 +355,7 @@ 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 */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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 */
|
||||||
|
@ -405,8 +387,7 @@ uint32_t arm946e_invalidate_dcache(struct target *target, uint32_t address,
|
||||||
|
|
||||||
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,24 +407,21 @@ 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;
|
||||||
}
|
}
|
||||||
|
@ -465,19 +442,16 @@ uint32_t arm946e_invalidate_icache(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;
|
||||||
|
|
||||||
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,16 +460,14 @@ 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;
|
||||||
}
|
}
|
||||||
|
@ -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,9 +522,7 @@ 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;
|
||||||
|
|
||||||
|
@ -569,11 +535,9 @@ int arm946e_read_memory(struct target *target, uint32_t address,
|
||||||
|
|
||||||
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,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 ARM946E_H
|
#ifndef ARM946E_H
|
||||||
#define ARM946E_H
|
#define ARM946E_H
|
||||||
|
|
||||||
|
@ -30,15 +31,13 @@
|
||||||
|
|
||||||
#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);
|
||||||
|
|
|
@ -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,20 +230,15 @@ 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
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
|
@ -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,20 +296,15 @@ 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
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
|
@ -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,7 +1183,7 @@ 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",
|
||||||
|
@ -1256,8 +1191,7 @@ static const char *class_description[16] ={
|
||||||
"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",
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
|
|
@ -145,8 +145,8 @@ static int dpm_read_reg(struct arm_dpm *dpm, struct reg *r, unsigned regnum)
|
||||||
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
|
||||||
|
@ -202,8 +202,8 @@ static int dpm_write_reg(struct arm_dpm *dpm, struct reg *r, unsigned regnum)
|
||||||
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:
|
||||||
|
@ -440,8 +440,7 @@ int arm_dpm_write_dirty_registers(struct arm_dpm *dpm, bool bpwp)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 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;
|
||||||
|
@ -915,7 +914,7 @@ void arm_dpm_report_dscr(struct arm_dpm *dpm, uint32_t dscr)
|
||||||
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:
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
@ -287,38 +246,28 @@ static int arm_simulate_step_core(struct target *target,
|
||||||
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);
|
||||||
|
@ -332,16 +281,11 @@ 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,21 +511,18 @@ 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;
|
||||||
|
@ -644,40 +537,29 @@ static int arm_simulate_step_core(struct target *target,
|
||||||
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);
|
||||||
|
@ -685,14 +567,12 @@ static int arm_simulate_step_core(struct target *target,
|
||||||
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,33 +581,28 @@ 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;
|
||||||
|
@ -742,10 +617,8 @@ static int arm_simulate_step_core(struct target *target,
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
|
@ -217,8 +217,7 @@ enum arm_mode armv4_5_number_to_mode(int number)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
||||||
},
|
},
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -555,8 +549,7 @@ 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)
|
||||||
|
@ -588,8 +581,7 @@ 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;
|
||||||
}
|
}
|
||||||
|
@ -607,7 +599,7 @@ int arm_arch_state(struct target *target)
|
||||||
}
|
}
|
||||||
|
|
||||||
#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,26 +607,23 @@ 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;
|
||||||
}
|
}
|
||||||
|
@ -673,7 +662,7 @@ COMMAND_HANDLER(handle_armv4_5_reg_command)
|
||||||
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;
|
||||||
|
|
||||||
|
@ -708,30 +697,23 @@ 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,8 +740,7 @@ 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;
|
||||||
}
|
}
|
||||||
|
@ -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) {
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -1060,14 +1037,13 @@ int arm_get_gdb_reg_list(struct target *target,
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
@ -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,8 +1133,7 @@ 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,
|
||||||
|
@ -1173,48 +1145,42 @@ int armv4_5_run_algorithm_inner(struct target *target,
|
||||||
}
|
}
|
||||||
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;
|
||||||
if (arm->core_state == ARM_STATE_ARM)
|
if (arm->core_state == ARM_STATE_ARM)
|
||||||
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,
|
||||||
|
@ -1224,18 +1190,18 @@ int armv4_5_run_algorithm_inner(struct target *target,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 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);
|
||||||
|
if (retval != ERROR_OK) {
|
||||||
LOG_ERROR("can't add HW breakpoint to terminate algorithm");
|
LOG_ERROR("can't add HW breakpoint to terminate algorithm");
|
||||||
return ERROR_TARGET_FAILURE;
|
return ERROR_TARGET_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((retval = target_resume(target, 0, entry_point, 1, 1)) != ERROR_OK)
|
|
||||||
{
|
|
||||||
return retval;
|
|
||||||
}
|
}
|
||||||
int retvaltemp;
|
|
||||||
|
retval = target_resume(target, 0, entry_point, 1, 1);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
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);
|
||||||
|
if (retvaltemp != ERROR_OK)
|
||||||
retval = retvaltemp;
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -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;
|
||||||
|
@ -38,58 +39,51 @@ int armv4_5_mmu_translate_va(struct target *target, struct armv4_5_mmu_common *a
|
||||||
|
|
||||||
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
|
||||||
|
@ -93,27 +94,26 @@ 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;
|
||||||
}
|
}
|
||||||
|
@ -132,10 +132,10 @@ int armv7a_mmu_translate_va(struct target *target, uint32_t va, uint32_t *val)
|
||||||
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,7 +222,6 @@ 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)
|
||||||
|
@ -240,17 +230,18 @@ int armv7a_mmu_translate_va_pa(struct target *target, uint32_t va,
|
||||||
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);
|
||||||
|
@ -260,40 +251,51 @@ int armv7a_mmu_translate_va_pa(struct target *target, uint32_t va,
|
||||||
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:
|
||||||
|
LOG_INFO("outer: Non-Cacheable");
|
||||||
break;
|
break;
|
||||||
case 1 : LOG_INFO("outer: Write-Back, Write-Allocate");
|
case 1:
|
||||||
|
LOG_INFO("outer: Write-Back, Write-Allocate");
|
||||||
break;
|
break;
|
||||||
case 2 : LOG_INFO("outer: Write-Through, No Write-Allocate");
|
case 2:
|
||||||
|
LOG_INFO("outer: Write-Through, No Write-Allocate");
|
||||||
break;
|
break;
|
||||||
case 3 : LOG_INFO("outer: Write-Back, no Write-Allocate");
|
case 3:
|
||||||
|
LOG_INFO("outer: Write-Back, no Write-Allocate");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
switch (INNER) {
|
switch (INNER) {
|
||||||
case 0 : LOG_INFO("inner: Non-Cacheable");
|
case 0:
|
||||||
|
LOG_INFO("inner: Non-Cacheable");
|
||||||
break;
|
break;
|
||||||
case 1 : LOG_INFO("inner: Strongly-ordered");
|
case 1:
|
||||||
|
LOG_INFO("inner: Strongly-ordered");
|
||||||
break;
|
break;
|
||||||
case 3 : LOG_INFO("inner: Device");
|
case 3:
|
||||||
|
LOG_INFO("inner: Device");
|
||||||
break;
|
break;
|
||||||
case 5 : LOG_INFO("inner: Write-Back, Write-Allocate");
|
case 5:
|
||||||
|
LOG_INFO("inner: Write-Back, Write-Allocate");
|
||||||
break;
|
break;
|
||||||
case 6 : LOG_INFO("inner: Write-Through");
|
case 6:
|
||||||
|
LOG_INFO("inner: Write-Through");
|
||||||
break;
|
break;
|
||||||
case 7 : LOG_INFO("inner: Write-Back, no Write-Allocate");
|
case 7:
|
||||||
|
LOG_INFO("inner: Write-Back, no Write-Allocate");
|
||||||
|
|
||||||
default: LOG_INFO("inner: %x ???",INNER);
|
default:
|
||||||
|
LOG_INFO("inner: %x ???", INNER);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -306,8 +308,7 @@ 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;
|
||||||
}
|
}
|
||||||
|
@ -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,58 +369,55 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -426,11 +425,10 @@ 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;
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -505,14 +497,12 @@ 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[0], base);
|
||||||
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], way);
|
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], way);
|
||||||
|
|
||||||
|
@ -522,15 +512,13 @@ switch (CMD_ARGC) {
|
||||||
default:
|
default:
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
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,7 +528,6 @@ 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)
|
||||||
{
|
{
|
||||||
|
@ -549,25 +536,25 @@ static int armv7a_read_mpidr(struct target *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:
|
||||||
|
@ -577,132 +564,143 @@ 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 =
|
||||||
|
@ -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;
|
||||||
|
@ -737,16 +733,14 @@ int armv7a_init_arch_info(struct target *target, struct armv7a_common *armv7a)
|
||||||
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
@ -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,9 +62,7 @@ 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 */
|
||||||
|
@ -79,23 +75,19 @@ struct armv7a_cache_common
|
||||||
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,
|
||||||
|
@ -149,13 +146,10 @@ 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,57 +338,57 @@ 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);
|
||||||
|
@ -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,14 +476,13 @@ 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;
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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,8 +687,7 @@ 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 */
|
||||||
|
@ -705,14 +697,15 @@ int armv7m_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_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,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
|
3,
|
||||||
|
reg_params,
|
||||||
|
erase_check_algorithm->address,
|
||||||
erase_check_algorithm->address + (sizeof(erase_check_code) - 2),
|
erase_check_algorithm->address + (sizeof(erase_check_code) - 2),
|
||||||
10000, &armv7m_info);
|
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,13 +74,10 @@ 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,13 +89,10 @@ 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 */
|
||||||
avr32_jtag_write_regs(&ap7k->jtag, ap7k->core_regs);
|
avr32_jtag_write_regs(&ap7k->jtag, ap7k->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;
|
||||||
|
@ -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;
|
||||||
|
@ -290,26 +273,19 @@ static int avr32_ap7k_halt(struct target *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;
|
||||||
|
@ -352,14 +328,12 @@ static int avr32_ap7k_resume(struct target *target, int current,
|
||||||
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);
|
||||||
|
@ -477,10 +445,12 @@ static int avr32_ap7k_read_memory(struct target *target, uint32_t address,
|
||||||
{
|
{
|
||||||
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,13 +462,14 @@ 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, (uint32_t*)(void *)buffer);
|
return avr32_jtag_read_memory32(&ap7k->jtag, address, count,
|
||||||
|
(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,
|
||||||
|
(uint16_t *)(void *)buffer);
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
return avr32_jtag_read_memory8(&ap7k->jtag, address, count, buffer);
|
return avr32_jtag_read_memory8(&ap7k->jtag, address, count, buffer);
|
||||||
|
@ -515,10 +486,12 @@ static int avr32_ap7k_write_memory(struct target *target, uint32_t address,
|
||||||
{
|
{
|
||||||
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,13 +503,14 @@ 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, (uint32_t*)(void *)buffer);
|
return avr32_jtag_write_memory32(&ap7k->jtag, address, count,
|
||||||
|
(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,
|
||||||
|
(uint16_t *)(void *)buffer);
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
return avr32_jtag_write_memory8(&ap7k->jtag, address, count, buffer);
|
return avr32_jtag_write_memory8(&ap7k->jtag, address, count, buffer);
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -622,18 +593,15 @@ int avr32_ap7k_get_gdb_reg_list(struct target *target, struct reg **reg_list[],
|
||||||
|
|
||||||
/* 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 */
|
/* add dummy floating points regs */
|
||||||
for (i = AVR32NUMCOREREGS; i < (AVR32NUMCOREREGS + AVR32NUMFPREGS); i++)
|
for (i = AVR32NUMCOREREGS; i < (AVR32NUMCOREREGS + AVR32NUMFPREGS); i++)
|
||||||
{
|
|
||||||
(*reg_list)[i] = &avr32_ap7k_gdb_dummy_fp_reg;
|
(*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;
|
||||||
}
|
}
|
||||||
|
@ -85,13 +84,12 @@ 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;
|
||||||
}
|
}
|
||||||
|
@ -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,7 +132,6 @@ 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,13 +220,12 @@ 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;
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -31,8 +32,7 @@ int avr32_jtag_read_memory32(struct avr32_jtag *jtag_info,
|
||||||
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,7 +40,7 @@ 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;
|
||||||
|
@ -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,7 +91,7 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,10 +106,9 @@ int avr32_jtag_read_memory8(struct avr32_jtag *jtag_info,
|
||||||
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;
|
||||||
|
@ -121,12 +117,10 @@ int avr32_jtag_read_memory8(struct avr32_jtag *jtag_info,
|
||||||
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;
|
||||||
|
@ -136,10 +130,9 @@ int avr32_jtag_read_memory8(struct avr32_jtag *jtag_info,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 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;
|
||||||
|
@ -157,10 +150,9 @@ int avr32_jtag_write_memory32(struct avr32_jtag *jtag_info,
|
||||||
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);
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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,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_MEM
|
#ifndef AVR32_MEM
|
||||||
#define AVR32_MEM
|
#define AVR32_MEM
|
||||||
|
|
||||||
|
@ -34,4 +35,3 @@ 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
|
||||||
|
|
|
@ -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
|
||||||
|
@ -108,7 +108,10 @@ fail:
|
||||||
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,11 +119,9 @@ 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.
|
||||||
|
@ -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);
|
||||||
|
@ -160,15 +160,18 @@ int context_breakpoint_add_internal(struct target *target, uint32_t asid, uint32
|
||||||
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
|
||||||
|
@ -178,9 +181,7 @@ int hybrid_breakpoint_add_internal(struct target *target, uint32_t address, uint
|
||||||
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(
|
||||||
|
"added %s Hybrid breakpoint at address 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 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;
|
||||||
|
@ -415,8 +398,7 @@ int watchpoint_add(struct target *target, uint32_t address, uint32_t length,
|
||||||
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
|
||||||
|
@ -459,7 +441,7 @@ 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;
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -48,8 +46,7 @@ struct breakpoint
|
||||||
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;
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
@ -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)
|
||||||
|
@ -301,8 +302,13 @@ static inline struct dsp5680xx_common *target_to_dsp5680xx(struct target
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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
|
||||||
|
* 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.
|
||||||
*
|
*
|
||||||
* @param target
|
* @param target
|
||||||
* @param buffer
|
* @param buffer
|
||||||
|
@ -316,11 +322,13 @@ 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 target
|
||||||
* @param erased
|
* @param erased
|
||||||
* @param sector This parameter is ignored because the FM does not support checking if individual sectors are erased.
|
* @param sector This parameter is ignored because the FM does not support checking if
|
||||||
|
* individual sectors are erased.
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
|
@ -328,7 +336,9 @@ 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
|
||||||
|
* on the FM. If not, then individual sectors are erased.
|
||||||
*
|
*
|
||||||
* @param target
|
* @param target
|
||||||
* @param first
|
* @param first
|
||||||
|
@ -339,7 +349,8 @@ int dsp5680xx_f_erase_check(struct target *target, uint8_t * erased,
|
||||||
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.
|
||||||
|
@ -349,7 +360,8 @@ int dsp5680xx_f_erase(struct target *target, int first, int last);
|
||||||
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
|
||||||
*
|
*
|
||||||
|
@ -359,8 +371,10 @@ 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
|
||||||
|
* the execution of this function.
|
||||||
*
|
*
|
||||||
* @param target
|
* @param 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
|
||||||
|
@ -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
|
||||||
*
|
*
|
||||||
|
@ -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 */
|
||||||
|
|
147
src/target/etb.c
147
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;
|
||||||
}
|
}
|
||||||
|
@ -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 */
|
||||||
|
|
509
src/target/etm.c
509
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,11 +511,11 @@ 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 */
|
||||||
for (i = 0; i <= 5; i++)
|
for (i = 0; i <= 5; i++)
|
||||||
|
@ -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;
|
||||||
|
@ -575,8 +565,7 @@ static int feroceon_bulk_write_memory(struct target *target,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 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,13 +204,10 @@ 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,13 +220,10 @@ 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 */
|
||||||
mips32_pracc_write_regs(ejtag_info, mips32->core_regs);
|
mips32_pracc_write_regs(ejtag_info, mips32->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,8 +576,7 @@ 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 */
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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,36 +566,29 @@ 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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
breakpoint->set = 0;
|
breakpoint->set = 0;
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
|
@ -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++;
|
||||||
|
@ -717,34 +644,29 @@ static int mips_m4k_set_watchpoint(struct target *target,
|
||||||
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));
|
||||||
|
if (bytes_read)
|
||||||
LOG_DEBUG("%zi bytes read", 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 */
|
||||||
|
@ -56,7 +56,6 @@
|
||||||
|
|
||||||
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,
|
||||||
char *packet, int packet_size)
|
char *packet, int packet_size)
|
||||||
|
@ -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
|
||||||
|
@ -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:
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
|
1418
src/target/target.c
1418
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;
|
||||||
|
@ -106,20 +102,17 @@ struct working_area
|
||||||
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 */
|
||||||
|
@ -157,13 +150,13 @@ struct target
|
||||||
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 */
|
||||||
|
@ -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;
|
||||||
|
@ -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!!!!!
|
||||||
*
|
*
|
||||||
|
|
|
@ -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
|
||||||
|
@ -35,8 +36,7 @@
|
||||||
#include "target_type.h"
|
#include "target_type.h"
|
||||||
#include "trace.h"
|
#include "trace.h"
|
||||||
|
|
||||||
|
static bool got_message;
|
||||||
static bool got_message = false;
|
|
||||||
|
|
||||||
bool target_got_message(void)
|
bool target_got_message(void)
|
||||||
{
|
{
|
||||||
|
@ -45,20 +45,19 @@ bool target_got_message(void)
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int charmsg_mode = 0;
|
static int charmsg_mode;
|
||||||
|
|
||||||
static int target_asciimsg(struct target *target, uint32_t length)
|
static int target_asciimsg(struct target *target, uint32_t length)
|
||||||
{
|
{
|
||||||
char *msg = malloc(DIV_ROUND_UP(length + 1, 4) * 4);
|
char *msg = malloc(DIV_ROUND_UP(length + 1, 4) * 4);
|
||||||
struct debug_msg_receiver *c = target->dbgmsg;
|
struct debug_msg_receiver *c = target->dbgmsg;
|
||||||
|
|
||||||
target->type->target_request_data(target, DIV_ROUND_UP(length, 4), (uint8_t*)msg);
|
target->type->target_request_data(target, DIV_ROUND_UP(length, 4), (uint8_t *)msg);
|
||||||
msg[length] = 0;
|
msg[length] = 0;
|
||||||
|
|
||||||
LOG_DEBUG("%s", msg);
|
LOG_DEBUG("%s", msg);
|
||||||
|
|
||||||
while (c)
|
while (c) {
|
||||||
{
|
|
||||||
command_print(c->cmd_ctx, "%s", msg);
|
command_print(c->cmd_ctx, "%s", msg);
|
||||||
c = c->next;
|
c = c->next;
|
||||||
}
|
}
|
||||||
|
@ -83,13 +82,11 @@ static int target_hexmsg(struct target *target, int size, uint32_t length)
|
||||||
|
|
||||||
LOG_DEBUG("size: %i, length: %i", (int)size, (int)length);
|
LOG_DEBUG("size: %i, length: %i", (int)size, (int)length);
|
||||||
|
|
||||||
target->type->target_request_data(target, DIV_ROUND_UP(length * size, 4), (uint8_t*)data);
|
target->type->target_request_data(target, DIV_ROUND_UP(length * size, 4), (uint8_t *)data);
|
||||||
|
|
||||||
line_len = 0;
|
line_len = 0;
|
||||||
for (i = 0; i < length; i++)
|
for (i = 0; i < length; i++) {
|
||||||
{
|
switch (size) {
|
||||||
switch (size)
|
|
||||||
{
|
|
||||||
case 4:
|
case 4:
|
||||||
line_len += snprintf(line + line_len, 128 - line_len, "%8.8" PRIx32 " ", le_to_h_u32(data + (4*i)));
|
line_len += snprintf(line + line_len, 128 - line_len, "%8.8" PRIx32 " ", le_to_h_u32(data + (4*i)));
|
||||||
break;
|
break;
|
||||||
|
@ -101,12 +98,10 @@ static int target_hexmsg(struct target *target, int size, uint32_t length)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((i%8 == 7) || (i == length - 1))
|
if ((i%8 == 7) || (i == length - 1)) {
|
||||||
{
|
|
||||||
LOG_DEBUG("%s", line);
|
LOG_DEBUG("%s", line);
|
||||||
|
|
||||||
while (c)
|
while (c) {
|
||||||
{
|
|
||||||
command_print(c->cmd_ctx, "%s", line);
|
command_print(c->cmd_ctx, "%s", line);
|
||||||
c = c->next;
|
c = c->next;
|
||||||
}
|
}
|
||||||
|
@ -134,20 +129,16 @@ int target_request(struct target *target, uint32_t request)
|
||||||
target_charmsg(target, target_req_cmd);
|
target_charmsg(target, target_req_cmd);
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
switch (target_req_cmd)
|
|
||||||
{
|
switch (target_req_cmd) {
|
||||||
case TARGET_REQ_TRACEMSG:
|
case TARGET_REQ_TRACEMSG:
|
||||||
trace_point(target, (request & 0xffffff00) >> 8);
|
trace_point(target, (request & 0xffffff00) >> 8);
|
||||||
break;
|
break;
|
||||||
case TARGET_REQ_DEBUGMSG:
|
case TARGET_REQ_DEBUGMSG:
|
||||||
if (((request & 0xff00) >> 8) == 0)
|
if (((request & 0xff00) >> 8) == 0)
|
||||||
{
|
|
||||||
target_asciimsg(target, (request & 0xffff0000) >> 16);
|
target_asciimsg(target, (request & 0xffff0000) >> 16);
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
target_hexmsg(target, (request & 0xff00) >> 8, (request & 0xffff0000) >> 16);
|
target_hexmsg(target, (request & 0xff00) >> 8, (request & 0xffff0000) >> 16);
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case TARGET_REQ_DEBUGCHAR:
|
case TARGET_REQ_DEBUGCHAR:
|
||||||
target_charmsg(target, (request & 0x00ff0000) >> 16);
|
target_charmsg(target, (request & 0x00ff0000) >> 16);
|
||||||
|
@ -171,8 +162,7 @@ static int add_debug_msg_receiver(struct command_context *cmd_ctx, struct target
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
|
|
||||||
/* see if there's already a list */
|
/* see if there's already a list */
|
||||||
if (*p)
|
if (*p) {
|
||||||
{
|
|
||||||
/* find end of linked list */
|
/* find end of linked list */
|
||||||
p = &target->dbgmsg;
|
p = &target->dbgmsg;
|
||||||
while ((*p)->next)
|
while ((*p)->next)
|
||||||
|
@ -191,7 +181,8 @@ static int add_debug_msg_receiver(struct command_context *cmd_ctx, struct target
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct debug_msg_receiver* find_debug_msg_receiver(struct command_context *cmd_ctx, struct target *target)
|
static struct debug_msg_receiver *find_debug_msg_receiver(struct command_context *cmd_ctx,
|
||||||
|
struct target *target)
|
||||||
{
|
{
|
||||||
int do_all_targets = 0;
|
int do_all_targets = 0;
|
||||||
|
|
||||||
|
@ -208,12 +199,9 @@ static struct debug_msg_receiver* find_debug_msg_receiver(struct command_context
|
||||||
/* so we target != null */
|
/* so we target != null */
|
||||||
struct debug_msg_receiver **p = &target->dbgmsg;
|
struct debug_msg_receiver **p = &target->dbgmsg;
|
||||||
do {
|
do {
|
||||||
while (*p)
|
while (*p) {
|
||||||
{
|
|
||||||
if ((*p)->cmd_ctx == cmd_ctx)
|
if ((*p)->cmd_ctx == cmd_ctx)
|
||||||
{
|
|
||||||
return *p;
|
return *p;
|
||||||
}
|
|
||||||
p = &((*p)->next);
|
p = &((*p)->next);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -230,8 +218,7 @@ int delete_debug_msg_receiver(struct command_context *cmd_ctx, struct target *ta
|
||||||
int do_all_targets = 0;
|
int do_all_targets = 0;
|
||||||
|
|
||||||
/* if no target has been specified search all of them */
|
/* if no target has been specified search all of them */
|
||||||
if (target == NULL)
|
if (target == NULL) {
|
||||||
{
|
|
||||||
/* if no targets haven been specified */
|
/* if no targets haven been specified */
|
||||||
if (all_targets == NULL)
|
if (all_targets == NULL)
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
|
@ -240,25 +227,20 @@ int delete_debug_msg_receiver(struct command_context *cmd_ctx, struct target *ta
|
||||||
do_all_targets = 1;
|
do_all_targets = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
do
|
do {
|
||||||
{
|
|
||||||
p = &target->dbgmsg;
|
p = &target->dbgmsg;
|
||||||
c = *p;
|
c = *p;
|
||||||
while (c)
|
while (c) {
|
||||||
{
|
|
||||||
struct debug_msg_receiver *next = c->next;
|
struct debug_msg_receiver *next = c->next;
|
||||||
if (c->cmd_ctx == cmd_ctx)
|
if (c->cmd_ctx == cmd_ctx) {
|
||||||
{
|
|
||||||
*p = next;
|
*p = next;
|
||||||
free(c);
|
free(c);
|
||||||
if (*p == NULL)
|
if (*p == NULL) {
|
||||||
{
|
|
||||||
/* disable callback */
|
/* disable callback */
|
||||||
target->dbg_msg_enabled = 0;
|
target->dbg_msg_enabled = 0;
|
||||||
}
|
}
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
} else
|
||||||
else
|
|
||||||
p = &(c->next);
|
p = &(c->next);
|
||||||
c = next;
|
c = next;
|
||||||
}
|
}
|
||||||
|
@ -279,35 +261,26 @@ COMMAND_HANDLER(handle_target_request_debugmsgs_command)
|
||||||
if (find_debug_msg_receiver(CMD_CTX, target) != NULL)
|
if (find_debug_msg_receiver(CMD_CTX, target) != NULL)
|
||||||
receiving = 1;
|
receiving = 1;
|
||||||
|
|
||||||
if (CMD_ARGC > 0)
|
if (CMD_ARGC > 0) {
|
||||||
{
|
if (!strcmp(CMD_ARGV[0], "enable") || !strcmp(CMD_ARGV[0], "charmsg")) {
|
||||||
if (!strcmp(CMD_ARGV[0], "enable") || !strcmp(CMD_ARGV[0], "charmsg"))
|
|
||||||
{
|
|
||||||
/* don't register if this command context is already receiving */
|
/* don't register if this command context is already receiving */
|
||||||
if (!receiving)
|
if (!receiving) {
|
||||||
{
|
|
||||||
receiving = 1;
|
receiving = 1;
|
||||||
add_debug_msg_receiver(CMD_CTX, target);
|
add_debug_msg_receiver(CMD_CTX, target);
|
||||||
}
|
}
|
||||||
charmsg_mode = !strcmp(CMD_ARGV[0], "charmsg");
|
charmsg_mode = !strcmp(CMD_ARGV[0], "charmsg");
|
||||||
}
|
} else if (!strcmp(CMD_ARGV[0], "disable")) {
|
||||||
else if (!strcmp(CMD_ARGV[0], "disable"))
|
|
||||||
{
|
|
||||||
/* no need to delete a receiver if none is registered */
|
/* no need to delete a receiver if none is registered */
|
||||||
if (receiving)
|
if (receiving) {
|
||||||
{
|
|
||||||
receiving = 0;
|
receiving = 0;
|
||||||
delete_debug_msg_receiver(CMD_CTX, target);
|
delete_debug_msg_receiver(CMD_CTX, target);
|
||||||
}
|
}
|
||||||
}
|
} else
|
||||||
else
|
|
||||||
{
|
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
command_print(CMD_CTX, "receiving debug messages from current target %s",
|
command_print(CMD_CTX, "receiving debug messages from current target %s",
|
||||||
(receiving) ? (charmsg_mode?"charmsg":"enabled") : "disabled");
|
(receiving) ? (charmsg_mode ? "charmsg" : "enabled") : "disabled");
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue