From 7f1ab30b8828d0105d41c912eeb7aa65e7a8fbab Mon Sep 17 00:00:00 2001 From: Spencer Oliver Date: Fri, 13 Jan 2012 11:29:21 +0000 Subject: [PATCH] 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 Reviewed-on: http://openocd.zylin.com/379 Tested-by: jenkins --- src/target/stm32_stlink.c | 103 ++++++++++++++++++++++++++++++-------- 1 file changed, 81 insertions(+), 22 deletions(-) diff --git a/src/target/stm32_stlink.c b/src/target/stm32_stlink.c index d00852c20..2493aed2b 100644 --- a/src/target/stm32_stlink.c +++ b/src/target/stm32_stlink.c @@ -2,6 +2,9 @@ * Copyright (C) 2011 by Mathias Kuester * * Mathias Kuester * * * + * 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,