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:
Spencer Oliver 2012-01-13 11:29:21 +00:00
parent c527882121
commit 7f1ab30b88
1 changed files with 81 additions and 22 deletions

View File

@ -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,