stlink: better handle target reset/events
This makes the stlink target use the std armv7m_arch_state giving consistent OpenOCD output. Added debug entry handler so we get debug entry reason. Change-Id: Ia3c1380fd5033a8e541b0d45a7c3559f1b05957d Signed-off-by: Spencer Oliver <spen@spen-soft.co.uk> Reviewed-on: http://openocd.zylin.com/379 Tested-by: jenkins
This commit is contained in:
parent
c527882121
commit
7f1ab30b88
|
@ -2,6 +2,9 @@
|
|||
* Copyright (C) 2011 by Mathias Kuester *
|
||||
* Mathias Kuester <kesmtp@freenet.de> *
|
||||
* *
|
||||
* Copyright (C) 2011 by Spencer Oliver *
|
||||
* spen@spen-soft.co.uk *
|
||||
* *
|
||||
* 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 *
|
||||
|
@ -187,6 +190,16 @@ static int stm32_stlink_store_core_reg_u32(struct target *target,
|
|||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int stm32_stlink_examine_debug_reason(struct target *target)
|
||||
{
|
||||
if ((target->debug_reason != DBG_REASON_DBGRQ)
|
||||
&& (target->debug_reason != DBG_REASON_SINGLESTEP)) {
|
||||
target->debug_reason = DBG_REASON_BREAKPOINT;
|
||||
}
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int stm32_stlink_init_arch_info(struct target *target,
|
||||
struct cortex_m3_common *cortex_m3,
|
||||
struct jtag_tap *tap)
|
||||
|
@ -201,6 +214,8 @@ static int stm32_stlink_init_arch_info(struct target *target,
|
|||
armv7m->load_core_reg_u32 = stm32_stlink_load_core_reg_u32;
|
||||
armv7m->store_core_reg_u32 = stm32_stlink_store_core_reg_u32;
|
||||
|
||||
armv7m->examine_debug_reason = stm32_stlink_examine_debug_reason;
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
|
@ -229,8 +244,6 @@ static int stm32_stlink_target_create(struct target *target,
|
|||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int stm32_stlink_poll(struct target *target);
|
||||
|
||||
static int stm32_stlink_examine(struct target *target)
|
||||
{
|
||||
int retval, i;
|
||||
|
@ -248,8 +261,6 @@ static int stm32_stlink_examine(struct target *target)
|
|||
if (!target_was_examined(target)) {
|
||||
target_set_examined(target);
|
||||
|
||||
stm32_stlink_poll(target);
|
||||
|
||||
LOG_INFO("IDCODE %x", target->tap->idcode);
|
||||
|
||||
/* Read from Device Identification Registers */
|
||||
|
@ -296,8 +307,9 @@ static int stm32_stlink_examine(struct target *target)
|
|||
static int stm32_stlink_load_context(struct target *target)
|
||||
{
|
||||
struct armv7m_common *armv7m = target_to_armv7m(target);
|
||||
int num_regs = armv7m->core_cache->num_regs;
|
||||
|
||||
for (unsigned i = 0; i < 23; i++) {
|
||||
for (int i = 0; i < num_regs; i++) {
|
||||
if (!armv7m->core_cache->reg_list[i].valid)
|
||||
armv7m->read_core_reg(target, i);
|
||||
}
|
||||
|
@ -305,6 +317,57 @@ static int stm32_stlink_load_context(struct target *target)
|
|||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int stlink_debug_entry(struct target *target)
|
||||
{
|
||||
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;
|
||||
|
||||
stm32_stlink_load_context(target);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
LOG_DEBUG("entered debug state in core mode: %s at PC 0x%" PRIx32 ", target->state: %s",
|
||||
armv7m_mode_strings[armv7m->core_mode],
|
||||
*(uint32_t *)(arm->pc->value),
|
||||
target_state_name(target));
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int stm32_stlink_poll(struct target *target)
|
||||
{
|
||||
enum target_state state;
|
||||
|
@ -314,8 +377,7 @@ static int stm32_stlink_poll(struct target *target)
|
|||
state = stlink_if->layout->api->state(stlink_if->fd);
|
||||
|
||||
if (state == TARGET_UNKNOWN) {
|
||||
LOG_ERROR
|
||||
("jtag status contains invalid mode value - communication failure");
|
||||
LOG_ERROR("jtag status contains invalid mode value - communication failure");
|
||||
return ERROR_TARGET_FAILURE;
|
||||
}
|
||||
|
||||
|
@ -323,23 +385,17 @@ static int stm32_stlink_poll(struct target *target)
|
|||
return ERROR_OK;
|
||||
|
||||
if (state == TARGET_HALTED) {
|
||||
target_call_event_callbacks(target, TARGET_EVENT_DEBUG_HALTED);
|
||||
target->state = state;
|
||||
|
||||
stm32_stlink_load_context(target);
|
||||
stlink_debug_entry(target);
|
||||
|
||||
LOG_INFO("halted: PC: 0x%x", buf_get_u32(armv7m->arm.pc->value, 0, 32));
|
||||
target_call_event_callbacks(target, TARGET_EVENT_HALTED);
|
||||
LOG_DEBUG("halted: PC: 0x%x", buf_get_u32(armv7m->arm.pc->value, 0, 32));
|
||||
}
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int stm32_stlink_arch_state(struct target *target)
|
||||
{
|
||||
LOG_DEBUG("%s", __func__);
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int stm32_stlink_assert_reset(struct target *target)
|
||||
{
|
||||
int res;
|
||||
|
@ -361,9 +417,12 @@ static int stm32_stlink_assert_reset(struct target *target)
|
|||
/* registers are now invalid */
|
||||
register_cache_invalidate(armv7m->core_cache);
|
||||
|
||||
stm32_stlink_load_context(target);
|
||||
|
||||
target->state = TARGET_HALTED;
|
||||
if (target->reset_halt) {
|
||||
target->state = TARGET_RESET;
|
||||
target->debug_reason = DBG_REASON_DBGRQ;
|
||||
} else {
|
||||
target->state = TARGET_HALTED;
|
||||
}
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
@ -486,7 +545,7 @@ static int stm32_stlink_resume(struct target *target, int current,
|
|||
|
||||
target->state = TARGET_RUNNING;
|
||||
|
||||
target_call_event_callbacks(target, TARGET_EVENT_DEBUG_RESUMED);
|
||||
target_call_event_callbacks(target, TARGET_EVENT_RESUMED);
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
@ -545,7 +604,7 @@ static int stm32_stlink_step(struct target *target, int current,
|
|||
target->debug_reason = DBG_REASON_SINGLESTEP;
|
||||
target_call_event_callbacks(target, TARGET_EVENT_HALTED);
|
||||
|
||||
stm32_stlink_load_context(target);
|
||||
stlink_debug_entry(target);
|
||||
|
||||
LOG_INFO("halted: PC: 0x%x", buf_get_u32(armv7m->arm.pc->value, 0, 32));
|
||||
|
||||
|
@ -669,7 +728,7 @@ struct target_type stm32_stlink_target = {
|
|||
.examine = stm32_stlink_examine,
|
||||
|
||||
.poll = stm32_stlink_poll,
|
||||
.arch_state = stm32_stlink_arch_state,
|
||||
.arch_state = armv7m_arch_state,
|
||||
|
||||
.assert_reset = stm32_stlink_assert_reset,
|
||||
.deassert_reset = stm32_stlink_deassert_reset,
|
||||
|
|
Loading…
Reference in New Issue