2011-12-17 02:51:09 -06:00
|
|
|
/***************************************************************************
|
|
|
|
* Copyright (C) 2011 by Mathias Kuester *
|
|
|
|
* Mathias Kuester <kesmtp@freenet.de> *
|
|
|
|
* *
|
2012-01-13 05:29:21 -06:00
|
|
|
* Copyright (C) 2011 by Spencer Oliver *
|
|
|
|
* spen@spen-soft.co.uk *
|
|
|
|
* *
|
2011-12-17 02:51:09 -06:00
|
|
|
* This program is free software; you can redistribute it and/or modify *
|
|
|
|
* it under the terms of the GNU General Public License as published by *
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or *
|
|
|
|
* (at your option) any later version. *
|
|
|
|
* *
|
|
|
|
* This program is distributed in the hope that it will be useful, *
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
|
|
|
* GNU General Public License for more details. *
|
|
|
|
* *
|
|
|
|
* You should have received a copy of the GNU General Public License *
|
|
|
|
* along with this program; if not, write to the *
|
|
|
|
* Free Software Foundation, Inc., *
|
|
|
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
|
|
|
***************************************************************************/
|
2012-02-05 06:03:04 -06:00
|
|
|
|
2011-12-17 02:51:09 -06:00
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
#include "config.h"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include "jtag/jtag.h"
|
2012-10-24 09:07:11 -05:00
|
|
|
#include "jtag/hla/hla_transport.h"
|
|
|
|
#include "jtag/hla/hla_interface.h"
|
|
|
|
#include "jtag/hla/hla_layout.h"
|
2011-12-17 02:51:09 -06:00
|
|
|
#include "register.h"
|
|
|
|
#include "algorithm.h"
|
|
|
|
#include "target.h"
|
|
|
|
#include "breakpoints.h"
|
|
|
|
#include "target_type.h"
|
|
|
|
#include "armv7m.h"
|
|
|
|
#include "cortex_m.h"
|
2012-02-14 09:34:03 -06:00
|
|
|
#include "arm_semihosting.h"
|
2011-12-17 02:51:09 -06:00
|
|
|
|
2012-03-10 07:34:44 -06:00
|
|
|
#define ARMV7M_SCS_DCRSR 0xe000edf4
|
|
|
|
#define ARMV7M_SCS_DCRDR 0xe000edf8
|
|
|
|
|
2012-10-24 09:07:11 -05:00
|
|
|
static inline struct hl_interface_s *target_to_adapter(struct target *target)
|
2011-12-17 02:51:09 -06:00
|
|
|
{
|
|
|
|
return target->tap->priv;
|
|
|
|
}
|
|
|
|
|
2012-10-24 09:07:11 -05:00
|
|
|
static int adapter_load_core_reg_u32(struct target *target,
|
2012-02-05 06:03:04 -06:00
|
|
|
enum armv7m_regtype type,
|
|
|
|
uint32_t num, uint32_t *value)
|
2011-12-17 02:51:09 -06:00
|
|
|
{
|
|
|
|
int retval;
|
2012-10-24 09:07:11 -05:00
|
|
|
struct hl_interface_s *adapter = target_to_adapter(target);
|
2011-12-17 02:51:09 -06:00
|
|
|
|
|
|
|
LOG_DEBUG("%s", __func__);
|
|
|
|
|
|
|
|
/* NOTE: we "know" here that the register identifiers used
|
|
|
|
* in the v7m header match the Cortex-M3 Debug Core Register
|
|
|
|
* Selector values for R0..R15, xPSR, MSP, and PSP.
|
|
|
|
*/
|
|
|
|
switch (num) {
|
|
|
|
case 0 ... 18:
|
|
|
|
/* read a normal core register */
|
2012-10-24 09:07:11 -05:00
|
|
|
retval = adapter->layout->api->read_reg(adapter->fd, num, value);
|
2011-12-17 02:51:09 -06:00
|
|
|
|
|
|
|
if (retval != ERROR_OK) {
|
|
|
|
LOG_ERROR("JTAG failure %i", retval);
|
|
|
|
return ERROR_JTAG_DEVICE_ERROR;
|
|
|
|
}
|
2012-03-10 07:34:44 -06:00
|
|
|
LOG_DEBUG("load from core reg %i value 0x%" PRIx32 "", (int)num, *value);
|
|
|
|
break;
|
|
|
|
|
2012-03-15 09:25:27 -05:00
|
|
|
case ARMV7M_FPSID:
|
|
|
|
case ARMV7M_FPEXC:
|
|
|
|
*value = 0;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ARMV7M_FPSCR:
|
2012-03-10 07:34:44 -06:00
|
|
|
/* Floating-point Status and Registers */
|
2012-03-15 09:25:27 -05:00
|
|
|
retval = target_write_u32(target, ARMV7M_SCS_DCRSR, 33);
|
2012-03-10 07:34:44 -06:00
|
|
|
if (retval != ERROR_OK)
|
|
|
|
return retval;
|
|
|
|
retval = target_read_u32(target, ARMV7M_SCS_DCRDR, value);
|
|
|
|
if (retval != ERROR_OK)
|
|
|
|
return retval;
|
|
|
|
LOG_DEBUG("load from core reg %i value 0x%" PRIx32 "", (int)num, *value);
|
2011-12-17 02:51:09 -06:00
|
|
|
break;
|
|
|
|
|
2012-03-15 09:25:27 -05:00
|
|
|
case ARMV7M_S0 ... ARMV7M_S31:
|
|
|
|
/* Floating-point Status and Registers */
|
|
|
|
retval = target_write_u32(target, ARMV7M_SCS_DCRSR, num-ARMV7M_S0+64);
|
|
|
|
if (retval != ERROR_OK)
|
|
|
|
return retval;
|
|
|
|
retval = target_read_u32(target, ARMV7M_SCS_DCRDR, value);
|
|
|
|
if (retval != ERROR_OK)
|
|
|
|
return retval;
|
|
|
|
LOG_DEBUG("load from core reg %i value 0x%" PRIx32 "", (int)num, *value);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ARMV7M_D0 ... ARMV7M_D15:
|
|
|
|
value = 0;
|
|
|
|
break;
|
|
|
|
|
2011-12-17 02:51:09 -06:00
|
|
|
case ARMV7M_PRIMASK:
|
|
|
|
case ARMV7M_BASEPRI:
|
|
|
|
case ARMV7M_FAULTMASK:
|
|
|
|
case ARMV7M_CONTROL:
|
|
|
|
/* Cortex-M3 packages these four registers as bitfields
|
|
|
|
* in one Debug Core register. So say r0 and r2 docs;
|
|
|
|
* it was removed from r1 docs, but still works.
|
|
|
|
*/
|
2012-10-24 09:07:11 -05:00
|
|
|
retval = adapter->layout->api->read_reg(adapter->fd, 20, value);
|
2012-05-22 06:33:40 -05:00
|
|
|
if (retval != ERROR_OK)
|
|
|
|
return retval;
|
2011-12-17 02:51:09 -06:00
|
|
|
|
|
|
|
switch (num) {
|
|
|
|
case ARMV7M_PRIMASK:
|
|
|
|
*value = buf_get_u32((uint8_t *) value, 0, 1);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ARMV7M_BASEPRI:
|
|
|
|
*value = buf_get_u32((uint8_t *) value, 8, 8);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ARMV7M_FAULTMASK:
|
|
|
|
*value = buf_get_u32((uint8_t *) value, 16, 1);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ARMV7M_CONTROL:
|
|
|
|
*value = buf_get_u32((uint8_t *) value, 24, 2);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
LOG_DEBUG("load from special reg %i value 0x%" PRIx32 "",
|
|
|
|
(int)num, *value);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2012-01-04 11:36:56 -06:00
|
|
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
2011-12-17 02:51:09 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
return ERROR_OK;
|
|
|
|
}
|
|
|
|
|
2012-10-24 09:07:11 -05:00
|
|
|
static int adapter_store_core_reg_u32(struct target *target,
|
2012-02-05 06:03:04 -06:00
|
|
|
enum armv7m_regtype type,
|
|
|
|
uint32_t num, uint32_t value)
|
2011-12-17 02:51:09 -06:00
|
|
|
{
|
|
|
|
int retval;
|
|
|
|
uint32_t reg;
|
|
|
|
struct armv7m_common *armv7m = target_to_armv7m(target);
|
2012-10-24 09:07:11 -05:00
|
|
|
struct hl_interface_s *adapter = target_to_adapter(target);
|
2011-12-17 02:51:09 -06:00
|
|
|
|
|
|
|
LOG_DEBUG("%s", __func__);
|
|
|
|
|
|
|
|
#ifdef ARMV7_GDB_HACKS
|
|
|
|
/* If the LR register is being modified, make sure it will put us
|
|
|
|
* in "thumb" mode, or an INVSTATE exception will occur. This is a
|
|
|
|
* hack to deal with the fact that gdb will sometimes "forge"
|
|
|
|
* return addresses, and doesn't set the LSB correctly (i.e., when
|
|
|
|
* printing expressions containing function calls, it sets LR = 0.)
|
|
|
|
* Valid exception return codes have bit 0 set too.
|
|
|
|
*/
|
|
|
|
if (num == ARMV7M_R14)
|
|
|
|
value |= 0x01;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* NOTE: we "know" here that the register identifiers used
|
|
|
|
* in the v7m header match the Cortex-M3 Debug Core Register
|
|
|
|
* Selector values for R0..R15, xPSR, MSP, and PSP.
|
|
|
|
*/
|
|
|
|
switch (num) {
|
|
|
|
case 0 ... 18:
|
2012-10-24 09:07:11 -05:00
|
|
|
retval = adapter->layout->api->write_reg(adapter->fd, num, value);
|
2011-12-17 02:51:09 -06:00
|
|
|
|
|
|
|
if (retval != ERROR_OK) {
|
|
|
|
struct reg *r;
|
|
|
|
|
|
|
|
LOG_ERROR("JTAG failure");
|
|
|
|
r = armv7m->core_cache->reg_list + num;
|
|
|
|
r->dirty = r->valid;
|
|
|
|
return ERROR_JTAG_DEVICE_ERROR;
|
|
|
|
}
|
2012-01-13 05:23:27 -06:00
|
|
|
LOG_DEBUG("write core reg %i value 0x%" PRIx32 "", (int)num, value);
|
2011-12-17 02:51:09 -06:00
|
|
|
break;
|
|
|
|
|
2012-03-15 09:25:27 -05:00
|
|
|
case ARMV7M_FPSID:
|
|
|
|
case ARMV7M_FPEXC:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ARMV7M_FPSCR:
|
2012-03-10 07:34:44 -06:00
|
|
|
/* Floating-point Status and Registers */
|
|
|
|
retval = target_write_u32(target, ARMV7M_SCS_DCRDR, value);
|
|
|
|
if (retval != ERROR_OK)
|
|
|
|
return retval;
|
2012-03-15 09:25:27 -05:00
|
|
|
retval = target_write_u32(target, ARMV7M_SCS_DCRSR, 33 | (1<<16));
|
2012-03-10 07:34:44 -06:00
|
|
|
if (retval != ERROR_OK)
|
|
|
|
return retval;
|
|
|
|
LOG_DEBUG("write core reg %i value 0x%" PRIx32 "", (int)num, value);
|
|
|
|
break;
|
|
|
|
|
2012-03-15 09:25:27 -05:00
|
|
|
case ARMV7M_S0 ... ARMV7M_S31:
|
|
|
|
/* Floating-point Status and Registers */
|
|
|
|
retval = target_write_u32(target, ARMV7M_SCS_DCRDR, value);
|
|
|
|
if (retval != ERROR_OK)
|
|
|
|
return retval;
|
|
|
|
retval = target_write_u32(target, ARMV7M_SCS_DCRSR, (num-ARMV7M_S0+64) | (1<<16));
|
|
|
|
if (retval != ERROR_OK)
|
|
|
|
return retval;
|
|
|
|
LOG_DEBUG("write core reg %i value 0x%" PRIx32 "", (int)num, value);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ARMV7M_D0 ... ARMV7M_D15:
|
|
|
|
break;
|
|
|
|
|
2011-12-17 02:51:09 -06:00
|
|
|
case ARMV7M_PRIMASK:
|
|
|
|
case ARMV7M_BASEPRI:
|
|
|
|
case ARMV7M_FAULTMASK:
|
|
|
|
case ARMV7M_CONTROL:
|
|
|
|
/* Cortex-M3 packages these four registers as bitfields
|
|
|
|
* in one Debug Core register. So say r0 and r2 docs;
|
|
|
|
* it was removed from r1 docs, but still works.
|
|
|
|
*/
|
2012-01-13 05:23:27 -06:00
|
|
|
|
2012-10-24 09:07:11 -05:00
|
|
|
adapter->layout->api->read_reg(adapter->fd, 20, ®);
|
2011-12-17 02:51:09 -06:00
|
|
|
|
|
|
|
switch (num) {
|
|
|
|
case ARMV7M_PRIMASK:
|
|
|
|
buf_set_u32((uint8_t *) ®, 0, 1, value);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ARMV7M_BASEPRI:
|
|
|
|
buf_set_u32((uint8_t *) ®, 8, 8, value);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ARMV7M_FAULTMASK:
|
|
|
|
buf_set_u32((uint8_t *) ®, 16, 1, value);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ARMV7M_CONTROL:
|
|
|
|
buf_set_u32((uint8_t *) ®, 24, 2, value);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2012-10-24 09:07:11 -05:00
|
|
|
adapter->layout->api->write_reg(adapter->fd, 20, reg);
|
2011-12-17 02:51:09 -06:00
|
|
|
|
2012-01-13 05:23:27 -06:00
|
|
|
LOG_DEBUG("write special reg %i value 0x%" PRIx32 " ", (int)num, value);
|
2011-12-17 02:51:09 -06:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2012-01-04 11:36:56 -06:00
|
|
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
2011-12-17 02:51:09 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
return ERROR_OK;
|
|
|
|
}
|
|
|
|
|
2012-10-24 09:07:11 -05:00
|
|
|
static int adapter_examine_debug_reason(struct target *target)
|
2012-01-13 05:29:21 -06:00
|
|
|
{
|
|
|
|
if ((target->debug_reason != DBG_REASON_DBGRQ)
|
|
|
|
&& (target->debug_reason != DBG_REASON_SINGLESTEP)) {
|
|
|
|
target->debug_reason = DBG_REASON_BREAKPOINT;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ERROR_OK;
|
|
|
|
}
|
|
|
|
|
2012-10-24 09:07:11 -05:00
|
|
|
static int adapter_init_arch_info(struct target *target,
|
2011-12-17 02:51:09 -06:00
|
|
|
struct cortex_m3_common *cortex_m3,
|
|
|
|
struct jtag_tap *tap)
|
|
|
|
{
|
|
|
|
struct armv7m_common *armv7m;
|
|
|
|
|
|
|
|
LOG_DEBUG("%s", __func__);
|
|
|
|
|
|
|
|
armv7m = &cortex_m3->armv7m;
|
|
|
|
armv7m_init_arch_info(target, armv7m);
|
|
|
|
|
2012-10-24 09:07:11 -05:00
|
|
|
armv7m->load_core_reg_u32 = adapter_load_core_reg_u32;
|
|
|
|
armv7m->store_core_reg_u32 = adapter_store_core_reg_u32;
|
2011-12-17 02:51:09 -06:00
|
|
|
|
2012-10-24 09:07:11 -05:00
|
|
|
armv7m->examine_debug_reason = adapter_examine_debug_reason;
|
2012-05-11 03:39:58 -05:00
|
|
|
armv7m->stlink = true;
|
2012-01-13 05:29:21 -06:00
|
|
|
|
2011-12-17 02:51:09 -06:00
|
|
|
return ERROR_OK;
|
|
|
|
}
|
|
|
|
|
2012-10-24 09:07:11 -05:00
|
|
|
static int adapter_init_target(struct command_context *cmd_ctx,
|
2011-12-17 02:51:09 -06:00
|
|
|
struct target *target)
|
|
|
|
{
|
|
|
|
LOG_DEBUG("%s", __func__);
|
|
|
|
|
|
|
|
armv7m_build_reg_cache(target);
|
|
|
|
|
|
|
|
return ERROR_OK;
|
|
|
|
}
|
|
|
|
|
2012-10-24 09:07:11 -05:00
|
|
|
static int adapter_target_create(struct target *target,
|
2012-02-05 06:03:04 -06:00
|
|
|
Jim_Interp *interp)
|
2011-12-17 02:51:09 -06:00
|
|
|
{
|
|
|
|
LOG_DEBUG("%s", __func__);
|
|
|
|
|
|
|
|
struct cortex_m3_common *cortex_m3 = calloc(1, sizeof(struct cortex_m3_common));
|
|
|
|
|
|
|
|
if (!cortex_m3)
|
2012-01-04 11:36:56 -06:00
|
|
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
2011-12-17 02:51:09 -06:00
|
|
|
|
2012-10-24 09:07:11 -05:00
|
|
|
adapter_init_arch_info(target, cortex_m3, target->tap);
|
2011-12-17 02:51:09 -06:00
|
|
|
|
|
|
|
return ERROR_OK;
|
|
|
|
}
|
|
|
|
|
2012-10-24 09:07:11 -05:00
|
|
|
static int adapter_load_context(struct target *target)
|
2011-12-17 02:51:09 -06:00
|
|
|
{
|
|
|
|
struct armv7m_common *armv7m = target_to_armv7m(target);
|
2012-01-13 05:29:21 -06:00
|
|
|
int num_regs = armv7m->core_cache->num_regs;
|
2011-12-17 02:51:09 -06:00
|
|
|
|
2012-01-13 05:29:21 -06:00
|
|
|
for (int i = 0; i < num_regs; i++) {
|
2011-12-17 02:51:09 -06:00
|
|
|
if (!armv7m->core_cache->reg_list[i].valid)
|
|
|
|
armv7m->read_core_reg(target, i);
|
|
|
|
}
|
|
|
|
|
|
|
|
return ERROR_OK;
|
|
|
|
}
|
|
|
|
|
2012-10-24 09:07:11 -05:00
|
|
|
static int adapter_debug_entry(struct target *target)
|
2012-01-13 05:29:21 -06:00
|
|
|
{
|
2012-10-24 09:07:11 -05:00
|
|
|
struct hl_interface_s *adapter = target_to_adapter(target);
|
2012-01-13 05:29:21 -06:00
|
|
|
struct armv7m_common *armv7m = target_to_armv7m(target);
|
|
|
|
struct arm *arm = &armv7m->arm;
|
|
|
|
struct reg *r;
|
|
|
|
uint32_t xPSR;
|
|
|
|
int retval;
|
|
|
|
|
|
|
|
retval = armv7m->examine_debug_reason(target);
|
|
|
|
if (retval != ERROR_OK)
|
|
|
|
return retval;
|
|
|
|
|
2012-10-24 09:07:11 -05:00
|
|
|
adapter_load_context(target);
|
2012-01-13 05:29:21 -06:00
|
|
|
|
2012-10-08 04:05:45 -05:00
|
|
|
/* make sure we clear the vector catch bit */
|
2012-10-24 09:07:11 -05:00
|
|
|
adapter->layout->api->write_debug_reg(adapter->fd, DCB_DEMCR, 0);
|
2012-10-08 04:05:45 -05:00
|
|
|
|
2012-01-13 05:29:21 -06:00
|
|
|
r = armv7m->core_cache->reg_list + ARMV7M_xPSR;
|
|
|
|
xPSR = buf_get_u32(r->value, 0, 32);
|
|
|
|
|
|
|
|
/* Are we in an exception handler */
|
|
|
|
if (xPSR & 0x1FF) {
|
|
|
|
armv7m->core_mode = ARMV7M_MODE_HANDLER;
|
|
|
|
armv7m->exception_number = (xPSR & 0x1FF);
|
|
|
|
|
|
|
|
arm->core_mode = ARM_MODE_HANDLER;
|
|
|
|
arm->map = armv7m_msp_reg_map;
|
|
|
|
} else {
|
|
|
|
unsigned control = buf_get_u32(armv7m->core_cache
|
|
|
|
->reg_list[ARMV7M_CONTROL].value, 0, 2);
|
|
|
|
|
|
|
|
/* is this thread privileged? */
|
|
|
|
armv7m->core_mode = control & 1;
|
|
|
|
arm->core_mode = armv7m->core_mode
|
|
|
|
? ARM_MODE_USER_THREAD
|
|
|
|
: ARM_MODE_THREAD;
|
|
|
|
|
|
|
|
/* which stack is it using? */
|
|
|
|
if (control & 2)
|
|
|
|
arm->map = armv7m_psp_reg_map;
|
|
|
|
else
|
|
|
|
arm->map = armv7m_msp_reg_map;
|
|
|
|
|
|
|
|
armv7m->exception_number = 0;
|
|
|
|
}
|
|
|
|
|
2012-04-05 11:07:20 -05:00
|
|
|
LOG_DEBUG("entered debug state in core mode: %s at PC 0x%08" PRIx32 ", target->state: %s",
|
2012-01-13 05:29:21 -06:00
|
|
|
armv7m_mode_strings[armv7m->core_mode],
|
|
|
|
*(uint32_t *)(arm->pc->value),
|
|
|
|
target_state_name(target));
|
|
|
|
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
2012-10-24 09:07:11 -05:00
|
|
|
static int adapter_poll(struct target *target)
|
2011-12-17 02:51:09 -06:00
|
|
|
{
|
|
|
|
enum target_state state;
|
2012-10-24 09:07:11 -05:00
|
|
|
struct hl_interface_s *adapter = target_to_adapter(target);
|
2011-12-17 02:51:09 -06:00
|
|
|
struct armv7m_common *armv7m = target_to_armv7m(target);
|
|
|
|
|
2012-10-24 09:07:11 -05:00
|
|
|
state = adapter->layout->api->state(adapter->fd);
|
2011-12-17 02:51:09 -06:00
|
|
|
|
|
|
|
if (state == TARGET_UNKNOWN) {
|
2012-01-13 05:29:21 -06:00
|
|
|
LOG_ERROR("jtag status contains invalid mode value - communication failure");
|
2011-12-17 02:51:09 -06:00
|
|
|
return ERROR_TARGET_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (target->state == state)
|
|
|
|
return ERROR_OK;
|
|
|
|
|
|
|
|
if (state == TARGET_HALTED) {
|
|
|
|
target->state = state;
|
|
|
|
|
2012-10-24 09:07:11 -05:00
|
|
|
int retval = adapter_debug_entry(target);
|
2012-02-14 09:34:03 -06:00
|
|
|
if (retval != ERROR_OK)
|
|
|
|
return retval;
|
|
|
|
|
|
|
|
if (arm_semihosting(target, &retval) != 0)
|
|
|
|
return retval;
|
2011-12-17 02:51:09 -06:00
|
|
|
|
2012-01-13 05:29:21 -06:00
|
|
|
target_call_event_callbacks(target, TARGET_EVENT_HALTED);
|
2012-04-05 11:07:20 -05:00
|
|
|
LOG_DEBUG("halted: PC: 0x%08x", buf_get_u32(armv7m->arm.pc->value, 0, 32));
|
2011-12-17 02:51:09 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
return ERROR_OK;
|
|
|
|
}
|
|
|
|
|
2012-10-24 09:07:11 -05:00
|
|
|
static int adapter_assert_reset(struct target *target)
|
2011-12-17 02:51:09 -06:00
|
|
|
{
|
2012-05-01 08:00:27 -05:00
|
|
|
int res = ERROR_OK;
|
2012-10-24 09:07:11 -05:00
|
|
|
struct hl_interface_s *adapter = target_to_adapter(target);
|
2011-12-17 02:51:09 -06:00
|
|
|
struct armv7m_common *armv7m = target_to_armv7m(target);
|
2012-04-19 09:51:14 -05:00
|
|
|
bool use_srst_fallback = true;
|
2011-12-17 02:51:09 -06:00
|
|
|
|
|
|
|
LOG_DEBUG("%s", __func__);
|
|
|
|
|
2012-04-19 09:51:14 -05:00
|
|
|
enum reset_types jtag_reset_config = jtag_get_reset_config();
|
|
|
|
|
2012-05-01 08:00:27 -05:00
|
|
|
bool srst_asserted = false;
|
|
|
|
|
|
|
|
if (jtag_reset_config & RESET_SRST_NO_GATING) {
|
|
|
|
jtag_add_reset(0, 1);
|
2012-10-24 09:07:11 -05:00
|
|
|
res = adapter->layout->api->assert_srst(adapter->fd, 0);
|
2012-05-01 08:00:27 -05:00
|
|
|
srst_asserted = true;
|
|
|
|
}
|
|
|
|
|
2012-10-24 09:07:11 -05:00
|
|
|
adapter->layout->api->write_debug_reg(adapter->fd, DCB_DHCSR, DBGKEY|C_DEBUGEN);
|
2012-10-08 04:05:45 -05:00
|
|
|
|
|
|
|
/* only set vector catch if halt is requested */
|
|
|
|
if (target->reset_halt)
|
2012-10-24 09:07:11 -05:00
|
|
|
adapter->layout->api->write_debug_reg(adapter->fd, DCB_DEMCR, VC_CORERESET);
|
2012-10-08 04:05:45 -05:00
|
|
|
else
|
2012-10-24 09:07:11 -05:00
|
|
|
adapter->layout->api->write_debug_reg(adapter->fd, DCB_DEMCR, 0);
|
2012-04-19 09:51:14 -05:00
|
|
|
|
|
|
|
if (jtag_reset_config & RESET_HAS_SRST) {
|
2012-05-01 08:00:27 -05:00
|
|
|
if (!srst_asserted) {
|
|
|
|
jtag_add_reset(0, 1);
|
2012-10-24 09:07:11 -05:00
|
|
|
res = adapter->layout->api->assert_srst(adapter->fd, 0);
|
2012-05-01 08:00:27 -05:00
|
|
|
}
|
2012-04-19 09:51:14 -05:00
|
|
|
if (res == ERROR_COMMAND_NOTFOUND)
|
|
|
|
LOG_ERROR("Hardware srst not supported, falling back to software reset");
|
|
|
|
else if (res == ERROR_OK) {
|
|
|
|
/* hardware srst supported */
|
|
|
|
use_srst_fallback = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (use_srst_fallback) {
|
2012-08-28 11:03:05 -05:00
|
|
|
/* stlink v1 api does not support hardware srst, so we use a software reset fallback */
|
2012-10-24 09:07:11 -05:00
|
|
|
adapter->layout->api->write_debug_reg(adapter->fd, NVIC_AIRCR, AIRCR_VECTKEY | AIRCR_SYSRESETREQ);
|
2012-04-19 09:51:14 -05:00
|
|
|
}
|
|
|
|
|
2012-10-24 09:07:11 -05:00
|
|
|
res = adapter->layout->api->reset(adapter->fd);
|
2011-12-17 02:51:09 -06:00
|
|
|
|
|
|
|
if (res != ERROR_OK)
|
|
|
|
return res;
|
|
|
|
|
|
|
|
/* registers are now invalid */
|
|
|
|
register_cache_invalidate(armv7m->core_cache);
|
|
|
|
|
2012-01-13 05:29:21 -06:00
|
|
|
if (target->reset_halt) {
|
|
|
|
target->state = TARGET_RESET;
|
|
|
|
target->debug_reason = DBG_REASON_DBGRQ;
|
|
|
|
} else {
|
|
|
|
target->state = TARGET_HALTED;
|
|
|
|
}
|
2011-12-17 02:51:09 -06:00
|
|
|
|
|
|
|
return ERROR_OK;
|
|
|
|
}
|
|
|
|
|
2012-10-24 09:07:11 -05:00
|
|
|
static int adapter_deassert_reset(struct target *target)
|
2011-12-17 02:51:09 -06:00
|
|
|
{
|
|
|
|
int res;
|
2012-10-24 09:07:11 -05:00
|
|
|
struct hl_interface_s *adapter = target_to_adapter(target);
|
2012-04-19 09:51:14 -05:00
|
|
|
|
|
|
|
enum reset_types jtag_reset_config = jtag_get_reset_config();
|
2011-12-17 02:51:09 -06:00
|
|
|
|
|
|
|
LOG_DEBUG("%s", __func__);
|
|
|
|
|
2012-04-19 09:51:14 -05:00
|
|
|
if (jtag_reset_config & RESET_HAS_SRST)
|
2012-10-24 09:07:11 -05:00
|
|
|
adapter->layout->api->assert_srst(adapter->fd, 1);
|
2012-04-19 09:51:14 -05:00
|
|
|
|
2011-12-17 02:51:09 -06:00
|
|
|
/* virtual deassert reset, we need it for the internal
|
|
|
|
* jtag state machine
|
|
|
|
*/
|
|
|
|
jtag_add_reset(0, 0);
|
|
|
|
|
|
|
|
if (!target->reset_halt) {
|
|
|
|
res = target_resume(target, 1, 0, 0, 0);
|
|
|
|
|
|
|
|
if (res != ERROR_OK)
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ERROR_OK;
|
|
|
|
}
|
|
|
|
|
2012-10-24 09:07:11 -05:00
|
|
|
static int adapter_soft_reset_halt(struct target *target)
|
2011-12-17 02:51:09 -06:00
|
|
|
{
|
|
|
|
LOG_DEBUG("%s", __func__);
|
|
|
|
return ERROR_OK;
|
|
|
|
}
|
|
|
|
|
2012-10-24 09:07:11 -05:00
|
|
|
static int adapter_halt(struct target *target)
|
2011-12-17 02:51:09 -06:00
|
|
|
{
|
|
|
|
int res;
|
2012-10-24 09:07:11 -05:00
|
|
|
struct hl_interface_s *adapter = target_to_adapter(target);
|
2011-12-17 02:51:09 -06:00
|
|
|
|
|
|
|
LOG_DEBUG("%s", __func__);
|
|
|
|
|
|
|
|
if (target->state == TARGET_HALTED) {
|
|
|
|
LOG_DEBUG("target was already halted");
|
|
|
|
return ERROR_OK;
|
|
|
|
}
|
|
|
|
|
2012-02-05 06:03:04 -06:00
|
|
|
if (target->state == TARGET_UNKNOWN)
|
|
|
|
LOG_WARNING("target was in unknown state when halt was requested");
|
2011-12-17 02:51:09 -06:00
|
|
|
|
2012-10-24 09:07:11 -05:00
|
|
|
res = adapter->layout->api->halt(adapter->fd);
|
2011-12-17 02:51:09 -06:00
|
|
|
|
|
|
|
if (res != ERROR_OK)
|
|
|
|
return res;
|
|
|
|
|
|
|
|
target->debug_reason = DBG_REASON_DBGRQ;
|
|
|
|
|
|
|
|
return ERROR_OK;
|
|
|
|
}
|
|
|
|
|
2012-10-24 09:07:11 -05:00
|
|
|
static int adapter_resume(struct target *target, int current,
|
2012-02-05 06:03:04 -06:00
|
|
|
uint32_t address, int handle_breakpoints,
|
|
|
|
int debug_execution)
|
2011-12-17 02:51:09 -06:00
|
|
|
{
|
|
|
|
int res;
|
2012-10-24 09:07:11 -05:00
|
|
|
struct hl_interface_s *adapter = target_to_adapter(target);
|
2011-12-17 02:51:09 -06:00
|
|
|
struct armv7m_common *armv7m = target_to_armv7m(target);
|
|
|
|
uint32_t resume_pc;
|
|
|
|
struct breakpoint *breakpoint = NULL;
|
|
|
|
struct reg *pc;
|
|
|
|
|
2012-04-05 11:07:20 -05:00
|
|
|
LOG_DEBUG("%s %d 0x%08x %d %d", __func__, current, address,
|
2012-02-05 06:03:04 -06:00
|
|
|
handle_breakpoints, debug_execution);
|
2011-12-17 02:51:09 -06:00
|
|
|
|
|
|
|
if (target->state != TARGET_HALTED) {
|
|
|
|
LOG_WARNING("target not halted");
|
|
|
|
return ERROR_TARGET_NOT_HALTED;
|
|
|
|
}
|
|
|
|
|
2012-10-25 10:37:14 -05:00
|
|
|
if (!debug_execution) {
|
|
|
|
target_free_all_working_areas(target);
|
|
|
|
cortex_m3_enable_breakpoints(target);
|
|
|
|
cortex_m3_enable_watchpoints(target);
|
|
|
|
}
|
|
|
|
|
2011-12-17 02:51:09 -06:00
|
|
|
pc = armv7m->arm.pc;
|
|
|
|
if (!current) {
|
|
|
|
buf_set_u32(pc->value, 0, 32, address);
|
|
|
|
pc->dirty = true;
|
|
|
|
pc->valid = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!breakpoint_find(target, buf_get_u32(pc->value, 0, 32))
|
|
|
|
&& !debug_execution) {
|
|
|
|
armv7m_maybe_skip_bkpt_inst(target, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
resume_pc = buf_get_u32(pc->value, 0, 32);
|
|
|
|
|
|
|
|
armv7m_restore_context(target);
|
|
|
|
|
|
|
|
/* registers are now invalid */
|
|
|
|
register_cache_invalidate(armv7m->core_cache);
|
|
|
|
|
|
|
|
/* the front-end may request us not to handle breakpoints */
|
|
|
|
if (handle_breakpoints) {
|
|
|
|
/* Single step past breakpoint at current address */
|
|
|
|
breakpoint = breakpoint_find(target, resume_pc);
|
|
|
|
if (breakpoint) {
|
|
|
|
LOG_DEBUG("unset breakpoint at 0x%8.8" PRIx32 " (ID: %d)",
|
2012-02-05 06:03:04 -06:00
|
|
|
breakpoint->address,
|
|
|
|
breakpoint->unique_id);
|
2011-12-17 02:51:09 -06:00
|
|
|
cortex_m3_unset_breakpoint(target, breakpoint);
|
|
|
|
|
2012-10-24 09:07:11 -05:00
|
|
|
res = adapter->layout->api->step(adapter->fd);
|
2011-12-17 02:51:09 -06:00
|
|
|
|
|
|
|
if (res != ERROR_OK)
|
|
|
|
return res;
|
|
|
|
|
|
|
|
cortex_m3_set_breakpoint(target, breakpoint);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-10-24 09:07:11 -05:00
|
|
|
res = adapter->layout->api->run(adapter->fd);
|
2011-12-17 02:51:09 -06:00
|
|
|
|
|
|
|
if (res != ERROR_OK)
|
|
|
|
return res;
|
|
|
|
|
|
|
|
target->state = TARGET_RUNNING;
|
2012-07-03 09:50:24 -05:00
|
|
|
target->debug_reason = DBG_REASON_NOTHALTED;
|
2011-12-17 02:51:09 -06:00
|
|
|
|
2012-01-13 05:29:21 -06:00
|
|
|
target_call_event_callbacks(target, TARGET_EVENT_RESUMED);
|
2011-12-17 02:51:09 -06:00
|
|
|
|
|
|
|
return ERROR_OK;
|
|
|
|
}
|
|
|
|
|
2012-10-24 09:07:11 -05:00
|
|
|
static int adapter_step(struct target *target, int current,
|
2012-02-05 06:03:04 -06:00
|
|
|
uint32_t address, int handle_breakpoints)
|
2011-12-17 02:51:09 -06:00
|
|
|
{
|
|
|
|
int res;
|
2012-10-24 09:07:11 -05:00
|
|
|
struct hl_interface_s *adapter = target_to_adapter(target);
|
2011-12-17 02:51:09 -06:00
|
|
|
struct armv7m_common *armv7m = target_to_armv7m(target);
|
|
|
|
struct breakpoint *breakpoint = NULL;
|
|
|
|
struct reg *pc = armv7m->arm.pc;
|
|
|
|
bool bkpt_inst_found = false;
|
|
|
|
|
|
|
|
LOG_DEBUG("%s", __func__);
|
|
|
|
|
|
|
|
if (target->state != TARGET_HALTED) {
|
|
|
|
LOG_WARNING("target not halted");
|
|
|
|
return ERROR_TARGET_NOT_HALTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!current) {
|
|
|
|
buf_set_u32(pc->value, 0, 32, address);
|
|
|
|
pc->dirty = true;
|
|
|
|
pc->valid = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t pc_value = buf_get_u32(pc->value, 0, 32);
|
|
|
|
|
|
|
|
/* the front-end may request us not to handle breakpoints */
|
|
|
|
if (handle_breakpoints) {
|
|
|
|
breakpoint = breakpoint_find(target, pc_value);
|
|
|
|
if (breakpoint)
|
|
|
|
cortex_m3_unset_breakpoint(target, breakpoint);
|
|
|
|
}
|
|
|
|
|
|
|
|
armv7m_maybe_skip_bkpt_inst(target, &bkpt_inst_found);
|
|
|
|
|
|
|
|
target->debug_reason = DBG_REASON_SINGLESTEP;
|
|
|
|
|
|
|
|
armv7m_restore_context(target);
|
|
|
|
|
|
|
|
target_call_event_callbacks(target, TARGET_EVENT_RESUMED);
|
|
|
|
|
2012-10-24 09:07:11 -05:00
|
|
|
res = adapter->layout->api->step(adapter->fd);
|
2011-12-17 02:51:09 -06:00
|
|
|
|
|
|
|
if (res != ERROR_OK)
|
|
|
|
return res;
|
|
|
|
|
|
|
|
/* registers are now invalid */
|
|
|
|
register_cache_invalidate(armv7m->core_cache);
|
|
|
|
|
|
|
|
if (breakpoint)
|
|
|
|
cortex_m3_set_breakpoint(target, breakpoint);
|
|
|
|
|
2012-10-24 09:07:11 -05:00
|
|
|
adapter_debug_entry(target);
|
2012-02-29 09:20:24 -06:00
|
|
|
target_call_event_callbacks(target, TARGET_EVENT_HALTED);
|
2011-12-17 02:51:09 -06:00
|
|
|
|
2012-04-05 11:07:20 -05:00
|
|
|
LOG_INFO("halted: PC: 0x%08x", buf_get_u32(armv7m->arm.pc->value, 0, 32));
|
2011-12-17 02:51:09 -06:00
|
|
|
|
|
|
|
return ERROR_OK;
|
|
|
|
}
|
|
|
|
|
2012-10-24 09:07:11 -05:00
|
|
|
static int adapter_read_memory(struct target *target, uint32_t address,
|
2012-02-05 06:03:04 -06:00
|
|
|
uint32_t size, uint32_t count,
|
|
|
|
uint8_t *buffer)
|
2011-12-17 02:51:09 -06:00
|
|
|
{
|
2012-11-01 06:19:29 -05:00
|
|
|
struct hl_interface_s *adapter = target_to_adapter(target);
|
2011-12-17 02:51:09 -06:00
|
|
|
int res;
|
2012-11-01 06:19:29 -05:00
|
|
|
uint32_t buffer_threshold = (adapter->param.max_buffer / 4);
|
2012-01-12 14:07:57 -06:00
|
|
|
uint32_t addr_increment = 4;
|
2011-12-17 02:51:09 -06:00
|
|
|
uint32_t c;
|
|
|
|
|
|
|
|
if (!count || !buffer)
|
2012-01-04 11:36:56 -06:00
|
|
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
2012-01-12 14:07:57 -06:00
|
|
|
|
2012-04-05 11:07:20 -05:00
|
|
|
LOG_DEBUG("%s 0x%08x %d %d", __func__, address, size, count);
|
2012-01-12 14:07:57 -06:00
|
|
|
|
|
|
|
/* prepare byte count, buffer threshold
|
|
|
|
* and address increment for none 32bit access
|
|
|
|
*/
|
2011-12-17 02:51:09 -06:00
|
|
|
if (size != 4) {
|
2012-01-12 14:07:57 -06:00
|
|
|
count *= size;
|
2012-11-01 06:19:29 -05:00
|
|
|
buffer_threshold = (adapter->param.max_buffer / 4) / 2;
|
2012-01-12 14:07:57 -06:00
|
|
|
addr_increment = 1;
|
2011-12-17 02:51:09 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
while (count) {
|
2012-01-12 14:07:57 -06:00
|
|
|
if (count > buffer_threshold)
|
|
|
|
c = buffer_threshold;
|
2011-12-17 02:51:09 -06:00
|
|
|
else
|
|
|
|
c = count;
|
|
|
|
|
2012-01-12 14:07:57 -06:00
|
|
|
if (size != 4)
|
2012-10-24 09:07:11 -05:00
|
|
|
res = adapter->layout->api->read_mem8(adapter->fd,
|
2012-02-24 14:51:48 -06:00
|
|
|
address, c, buffer);
|
2012-01-12 14:07:57 -06:00
|
|
|
else
|
2012-10-24 09:07:11 -05:00
|
|
|
res = adapter->layout->api->read_mem32(adapter->fd,
|
2012-02-24 14:51:48 -06:00
|
|
|
address, c, buffer);
|
2011-12-17 02:51:09 -06:00
|
|
|
|
|
|
|
if (res != ERROR_OK)
|
|
|
|
return res;
|
2012-01-12 14:07:57 -06:00
|
|
|
|
|
|
|
address += (c * addr_increment);
|
2012-02-24 14:51:48 -06:00
|
|
|
buffer += (c * addr_increment);
|
2011-12-17 02:51:09 -06:00
|
|
|
count -= c;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ERROR_OK;
|
|
|
|
}
|
|
|
|
|
2012-10-24 09:07:11 -05:00
|
|
|
static int adapter_write_memory(struct target *target, uint32_t address,
|
2012-02-05 06:03:04 -06:00
|
|
|
uint32_t size, uint32_t count,
|
|
|
|
const uint8_t *buffer)
|
2011-12-17 02:51:09 -06:00
|
|
|
{
|
2012-11-01 06:19:29 -05:00
|
|
|
struct hl_interface_s *adapter = target_to_adapter(target);
|
2011-12-17 02:51:09 -06:00
|
|
|
int res;
|
2012-11-01 06:19:29 -05:00
|
|
|
uint32_t buffer_threshold = (adapter->param.max_buffer / 4);
|
2012-01-12 14:07:57 -06:00
|
|
|
uint32_t addr_increment = 4;
|
2011-12-17 02:51:09 -06:00
|
|
|
uint32_t c;
|
|
|
|
|
|
|
|
if (!count || !buffer)
|
2012-01-04 11:36:56 -06:00
|
|
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
2012-01-12 14:07:57 -06:00
|
|
|
|
2012-04-05 11:07:20 -05:00
|
|
|
LOG_DEBUG("%s 0x%08x %d %d", __func__, address, size, count);
|
2012-01-12 14:07:57 -06:00
|
|
|
|
|
|
|
/* prepare byte count, buffer threshold
|
|
|
|
* and address increment for none 32bit access
|
|
|
|
*/
|
2011-12-17 02:51:09 -06:00
|
|
|
if (size != 4) {
|
2012-01-12 14:07:57 -06:00
|
|
|
count *= size;
|
2012-11-01 06:19:29 -05:00
|
|
|
buffer_threshold = (adapter->param.max_buffer / 4) / 2;
|
2012-01-12 14:07:57 -06:00
|
|
|
addr_increment = 1;
|
2011-12-17 02:51:09 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
while (count) {
|
2012-01-12 14:07:57 -06:00
|
|
|
if (count > buffer_threshold)
|
|
|
|
c = buffer_threshold;
|
2011-12-17 02:51:09 -06:00
|
|
|
else
|
|
|
|
c = count;
|
|
|
|
|
2012-01-12 14:07:57 -06:00
|
|
|
if (size != 4)
|
2012-10-24 09:07:11 -05:00
|
|
|
res = adapter->layout->api->write_mem8(adapter->fd,
|
2012-02-24 14:51:48 -06:00
|
|
|
address, c, buffer);
|
2012-01-12 14:07:57 -06:00
|
|
|
else
|
2012-10-24 09:07:11 -05:00
|
|
|
res = adapter->layout->api->write_mem32(adapter->fd,
|
2012-02-24 14:51:48 -06:00
|
|
|
address, c, buffer);
|
2011-12-17 02:51:09 -06:00
|
|
|
|
|
|
|
if (res != ERROR_OK)
|
|
|
|
return res;
|
2012-01-12 14:07:57 -06:00
|
|
|
|
|
|
|
address += (c * addr_increment);
|
2012-02-24 14:51:48 -06:00
|
|
|
buffer += (c * addr_increment);
|
2011-12-17 02:51:09 -06:00
|
|
|
count -= c;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ERROR_OK;
|
|
|
|
}
|
|
|
|
|
2012-10-24 09:07:11 -05:00
|
|
|
static int adapter_bulk_write_memory(struct target *target,
|
2012-02-05 06:03:04 -06:00
|
|
|
uint32_t address, uint32_t count,
|
|
|
|
const uint8_t *buffer)
|
2011-12-17 02:51:09 -06:00
|
|
|
{
|
2012-10-24 09:07:11 -05:00
|
|
|
return adapter_write_memory(target, address, 4, count, buffer);
|
2011-12-17 02:51:09 -06:00
|
|
|
}
|
|
|
|
|
2012-10-24 09:07:11 -05:00
|
|
|
static const struct command_registration adapter_command_handlers[] = {
|
2012-07-03 09:50:24 -05:00
|
|
|
{
|
|
|
|
.chain = arm_command_handlers,
|
|
|
|
},
|
|
|
|
COMMAND_REGISTRATION_DONE
|
|
|
|
};
|
|
|
|
|
2012-10-24 03:52:00 -05:00
|
|
|
struct target_type hla_target = {
|
|
|
|
.name = "hla_target",
|
|
|
|
.deprecated_name = "stm32_stlink",
|
2011-12-17 02:51:09 -06:00
|
|
|
|
2012-10-24 09:07:11 -05:00
|
|
|
.init_target = adapter_init_target,
|
|
|
|
.target_create = adapter_target_create,
|
2012-03-12 05:28:49 -05:00
|
|
|
.examine = cortex_m3_examine,
|
2012-10-24 09:07:11 -05:00
|
|
|
.commands = adapter_command_handlers,
|
2011-12-17 02:51:09 -06:00
|
|
|
|
2012-10-24 09:07:11 -05:00
|
|
|
.poll = adapter_poll,
|
2012-01-13 05:29:21 -06:00
|
|
|
.arch_state = armv7m_arch_state,
|
2011-12-17 02:51:09 -06:00
|
|
|
|
2012-10-24 09:07:11 -05:00
|
|
|
.assert_reset = adapter_assert_reset,
|
|
|
|
.deassert_reset = adapter_deassert_reset,
|
|
|
|
.soft_reset_halt = adapter_soft_reset_halt,
|
2011-12-17 02:51:09 -06:00
|
|
|
|
2012-10-24 09:07:11 -05:00
|
|
|
.halt = adapter_halt,
|
|
|
|
.resume = adapter_resume,
|
|
|
|
.step = adapter_step,
|
2011-12-17 02:51:09 -06:00
|
|
|
|
|
|
|
.get_gdb_reg_list = armv7m_get_gdb_reg_list,
|
|
|
|
|
2012-10-24 09:07:11 -05:00
|
|
|
.read_memory = adapter_read_memory,
|
|
|
|
.write_memory = adapter_write_memory,
|
|
|
|
.bulk_write_memory = adapter_bulk_write_memory,
|
2012-01-24 09:07:59 -06:00
|
|
|
.checksum_memory = armv7m_checksum_memory,
|
|
|
|
.blank_check_memory = armv7m_blank_check_memory,
|
2011-12-17 02:51:09 -06:00
|
|
|
|
|
|
|
.run_algorithm = armv7m_run_algorithm,
|
|
|
|
.start_algorithm = armv7m_start_algorithm,
|
|
|
|
.wait_algorithm = armv7m_wait_algorithm,
|
|
|
|
|
|
|
|
.add_breakpoint = cortex_m3_add_breakpoint,
|
|
|
|
.remove_breakpoint = cortex_m3_remove_breakpoint,
|
|
|
|
.add_watchpoint = cortex_m3_add_watchpoint,
|
|
|
|
.remove_watchpoint = cortex_m3_remove_watchpoint,
|
|
|
|
};
|