armv7m: remove gdb register hacks
[openocd.git] / src / target / hla_target.c
index 8d2a4291a634e81047e56ccbd7c7ee732a49c661..2db04f8111aa6e9d5ea296550ed1eaafd501d9c7 100644 (file)
@@ -5,6 +5,8 @@
  *   Copyright (C) 2011 by Spencer Oliver                                  *
  *   spen@spen-soft.co.uk                                                  *
  *                                                                         *
+ *   revised:  4/25/13 by brent@mbari.org [DCC target request support]    *
+ *                                                                         *
  *   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     *
@@ -18,7 +20,7 @@
  *   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.             *
+ *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.           *
  ***************************************************************************/
 
 #ifdef HAVE_CONFIG_H
 #include "armv7m.h"
 #include "cortex_m.h"
 #include "arm_semihosting.h"
+#include "target_request.h"
+
+#define savedDCRDR  dbgbase  /* FIXME: using target->dbgbase to preserve DCRDR */
 
-#define ARMV7M_SCS_DCRSR       0xe000edf4
-#define ARMV7M_SCS_DCRDR       0xe000edf8
+#define ARMV7M_SCS_DCRSR       DCB_DCRSR
+#define ARMV7M_SCS_DCRDR       DCB_DCRDR
 
 static inline struct hl_interface_s *target_to_adapter(struct target *target)
 {
@@ -47,7 +52,6 @@ static inline struct hl_interface_s *target_to_adapter(struct target *target)
 }
 
 static int adapter_load_core_reg_u32(struct target *target,
-               enum armv7m_regtype type,
                uint32_t num, uint32_t *value)
 {
        int retval;
@@ -144,7 +148,6 @@ static int adapter_load_core_reg_u32(struct target *target,
 }
 
 static int adapter_store_core_reg_u32(struct target *target,
-               enum armv7m_regtype type,
                uint32_t num, uint32_t value)
 {
        int retval;
@@ -154,18 +157,6 @@ static int adapter_store_core_reg_u32(struct target *target,
 
        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.
@@ -178,7 +169,7 @@ static int adapter_store_core_reg_u32(struct target *target,
                        struct reg *r;
 
                        LOG_ERROR("JTAG failure");
-                       r = armv7m->core_cache->reg_list + num;
+                       r = armv7m->arm.core_cache->reg_list + num;
                        r->dirty = r->valid;
                        return ERROR_JTAG_DEVICE_ERROR;
                }
@@ -265,6 +256,80 @@ static int adapter_examine_debug_reason(struct target *target)
        return ERROR_OK;
 }
 
+static int hl_dcc_read(struct hl_interface_s *hl_if, uint8_t *value, uint8_t *ctrl)
+{
+       uint16_t dcrdr;
+       int retval = hl_if->layout->api->read_mem8(hl_if->fd,
+                                                               DCB_DCRDR, sizeof(dcrdr), (uint8_t *)&dcrdr);
+       if (retval == ERROR_OK) {
+           *ctrl = (uint8_t)dcrdr;
+           *value = (uint8_t)(dcrdr >> 8);
+
+           LOG_DEBUG("data 0x%x ctrl 0x%x", *value, *ctrl);
+
+           if (dcrdr & 1) {
+                       /* write ack back to software dcc register
+                        * to signify we have read data */
+                       /* atomically clear just the byte containing the busy bit */
+                       static const uint8_t zero;
+                       retval = hl_if->layout->api->write_mem8(
+                                               hl_if->fd, DCB_DCRDR, 1, &zero);
+               }
+       }
+       return retval;
+}
+
+static int hl_target_request_data(struct target *target,
+       uint32_t size, uint8_t *buffer)
+{
+       struct hl_interface_s *hl_if = target_to_adapter(target);
+       uint8_t data;
+       uint8_t ctrl;
+       uint32_t i;
+
+       for (i = 0; i < (size * 4); i++) {
+               hl_dcc_read(hl_if, &data, &ctrl);
+               buffer[i] = data;
+       }
+
+       return ERROR_OK;
+}
+
+static int hl_handle_target_request(void *priv)
+{
+       struct target *target = priv;
+       if (!target_was_examined(target))
+               return ERROR_OK;
+       struct hl_interface_s *hl_if = target_to_adapter(target);
+
+       if (!target->dbg_msg_enabled)
+               return ERROR_OK;
+
+       if (target->state == TARGET_RUNNING) {
+               uint8_t data;
+               uint8_t ctrl;
+
+               hl_dcc_read(hl_if, &data, &ctrl);
+
+               /* check if we have data */
+               if (ctrl & (1 << 0)) {
+                       uint32_t request;
+
+                       /* we assume target is quick enough */
+                       request = data;
+                       hl_dcc_read(hl_if, &data, &ctrl);
+                       request |= (data << 8);
+                       hl_dcc_read(hl_if, &data, &ctrl);
+                       request |= (data << 16);
+                       hl_dcc_read(hl_if, &data, &ctrl);
+                       request |= (data << 24);
+                       target_request(target, request);
+               }
+       }
+
+       return ERROR_OK;
+}
+
 static int adapter_init_arch_info(struct target *target,
                                       struct cortex_m3_common *cortex_m3,
                                       struct jtag_tap *tap)
@@ -282,6 +347,8 @@ static int adapter_init_arch_info(struct target *target,
        armv7m->examine_debug_reason = adapter_examine_debug_reason;
        armv7m->stlink = true;
 
+       target_register_timer_callback(hl_handle_target_request, 1, 1, target);
+
        return ERROR_OK;
 }
 
@@ -313,11 +380,13 @@ static int adapter_target_create(struct target *target,
 static int adapter_load_context(struct target *target)
 {
        struct armv7m_common *armv7m = target_to_armv7m(target);
-       int num_regs = armv7m->core_cache->num_regs;
+       int num_regs = armv7m->arm.core_cache->num_regs;
 
        for (int i = 0; i < num_regs; i++) {
-               if (!armv7m->core_cache->reg_list[i].valid)
-                       armv7m->read_core_reg(target, i);
+
+               struct reg *r = &armv7m->arm.core_cache->reg_list[i];
+               if (!r->valid)
+                       armv7m->arm.read_core_reg(target, r, i, ARM_MODE_ANY);
        }
 
        return ERROR_OK;
@@ -332,6 +401,11 @@ static int adapter_debug_entry(struct target *target)
        uint32_t xPSR;
        int retval;
 
+       /* preserve the DCRDR across halts */
+       retval = target_read_u32(target, DCB_DCRDR, &target->savedDCRDR);
+       if (retval != ERROR_OK)
+               return retval;
+
        retval = armv7m->examine_debug_reason(target);
        if (retval != ERROR_OK)
                return retval;
@@ -339,25 +413,23 @@ static int adapter_debug_entry(struct target *target)
        adapter_load_context(target);
 
        /* make sure we clear the vector catch bit */
-       adapter->layout->api->write_debug_reg(adapter->fd, DCB_DEMCR, 0);
+       adapter->layout->api->write_debug_reg(adapter->fd, DCB_DEMCR, TRCENA);
 
-       r = armv7m->core_cache->reg_list + ARMV7M_xPSR;
+       r = arm->cpsr;
        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
+               unsigned control = buf_get_u32(arm->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->core_mode = control & 1
                                ? ARM_MODE_USER_THREAD
                                : ARM_MODE_THREAD;
 
@@ -371,7 +443,7 @@ static int adapter_debug_entry(struct target *target)
        }
 
        LOG_DEBUG("entered debug state in core mode: %s at PC 0x%08" PRIx32 ", target->state: %s",
-               armv7m_mode_strings[armv7m->core_mode],
+               arm_mode_name(arm->core_mode),
                *(uint32_t *)(arm->pc->value),
                target_state_name(target));
 
@@ -383,6 +455,7 @@ static int adapter_poll(struct target *target)
        enum target_state state;
        struct hl_interface_s *adapter = target_to_adapter(target);
        struct armv7m_common *armv7m = target_to_armv7m(target);
+       enum target_state prev_target_state = target->state;
 
        state = adapter->layout->api->state(adapter->fd);
 
@@ -401,10 +474,15 @@ static int adapter_poll(struct target *target)
                if (retval != ERROR_OK)
                        return retval;
 
-               if (arm_semihosting(target, &retval) != 0)
-                       return retval;
+               if (prev_target_state == TARGET_DEBUG_RUNNING) {
+                       target_call_event_callbacks(target, TARGET_EVENT_DEBUG_HALTED);
+               } else {
+                       if (arm_semihosting(target, &retval) != 0)
+                               return retval;
+
+                       target_call_event_callbacks(target, TARGET_EVENT_HALTED);
+               }
 
-               target_call_event_callbacks(target, TARGET_EVENT_HALTED);
                LOG_DEBUG("halted: PC: 0x%08x", buf_get_u32(armv7m->arm.pc->value, 0, 32));
        }
 
@@ -424,7 +502,8 @@ static int adapter_assert_reset(struct target *target)
 
        bool srst_asserted = false;
 
-       if (jtag_reset_config & RESET_SRST_NO_GATING) {
+       if ((jtag_reset_config & RESET_HAS_SRST) &&
+           (jtag_reset_config & RESET_SRST_NO_GATING)) {
                jtag_add_reset(0, 1);
                res = adapter->layout->api->assert_srst(adapter->fd, 0);
                srst_asserted = true;
@@ -434,9 +513,9 @@ static int adapter_assert_reset(struct target *target)
 
        /* only set vector catch if halt is requested */
        if (target->reset_halt)
-               adapter->layout->api->write_debug_reg(adapter->fd, DCB_DEMCR, VC_CORERESET);
+               adapter->layout->api->write_debug_reg(adapter->fd, DCB_DEMCR, TRCENA|VC_CORERESET);
        else
-               adapter->layout->api->write_debug_reg(adapter->fd, DCB_DEMCR, 0);
+               adapter->layout->api->write_debug_reg(adapter->fd, DCB_DEMCR, TRCENA);
 
        if (jtag_reset_config & RESET_HAS_SRST) {
                if (!srst_asserted) {
@@ -462,7 +541,7 @@ static int adapter_assert_reset(struct target *target)
                return res;
 
        /* registers are now invalid */
-       register_cache_invalidate(armv7m->core_cache);
+       register_cache_invalidate(armv7m->arm.core_cache);
 
        if (target->reset_halt) {
                target->state = TARGET_RESET;
@@ -476,7 +555,6 @@ static int adapter_assert_reset(struct target *target)
 
 static int adapter_deassert_reset(struct target *target)
 {
-       int res;
        struct hl_interface_s *adapter = target_to_adapter(target);
 
        enum reset_types jtag_reset_config = jtag_get_reset_config();
@@ -491,20 +569,9 @@ static int adapter_deassert_reset(struct target *target)
         */
        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;
-}
+       target->savedDCRDR = 0;  /* clear both DCC busy bits on initial resume */
 
-static int adapter_soft_reset_halt(struct target *target)
-{
-       LOG_DEBUG("%s", __func__);
-       return ERROR_OK;
+       return target->reset_halt ? ERROR_OK : target_resume(target, 1, 0, 0, 0);
 }
 
 static int adapter_halt(struct target *target)
@@ -571,10 +638,20 @@ static int adapter_resume(struct target *target, int current,
 
        resume_pc = buf_get_u32(pc->value, 0, 32);
 
+       /* write any user vector flags */
+       res = target_write_u32(target, DCB_DEMCR, TRCENA | armv7m->demcr);
+       if (res != ERROR_OK)
+               return res;
+
        armv7m_restore_context(target);
 
+       /* restore savedDCRDR */
+       res = target_write_u32(target, DCB_DCRDR, target->savedDCRDR);
+       if (res != ERROR_OK)
+               return res;
+
        /* registers are now invalid */
-       register_cache_invalidate(armv7m->core_cache);
+       register_cache_invalidate(armv7m->arm.core_cache);
 
        /* the front-end may request us not to handle breakpoints */
        if (handle_breakpoints) {
@@ -600,10 +677,15 @@ static int adapter_resume(struct target *target, int current,
        if (res != ERROR_OK)
                return res;
 
-       target->state = TARGET_RUNNING;
        target->debug_reason = DBG_REASON_NOTHALTED;
 
-       target_call_event_callbacks(target, TARGET_EVENT_RESUMED);
+       if (!debug_execution) {
+               target->state = TARGET_RUNNING;
+               target_call_event_callbacks(target, TARGET_EVENT_RESUMED);
+       } else {
+               target->state = TARGET_DEBUG_RUNNING;
+               target_call_event_callbacks(target, TARGET_EVENT_DEBUG_RESUMED);
+       }
 
        return ERROR_OK;
 }
@@ -646,6 +728,11 @@ static int adapter_step(struct target *target, int current,
 
        armv7m_restore_context(target);
 
+       /* restore savedDCRDR */
+       res = target_write_u32(target, DCB_DCRDR, target->savedDCRDR);
+       if (res != ERROR_OK)
+               return res;
+
        target_call_event_callbacks(target, TARGET_EVENT_RESUMED);
 
        res = adapter->layout->api->step(adapter->fd);
@@ -654,7 +741,7 @@ static int adapter_step(struct target *target, int current,
                return res;
 
        /* registers are now invalid */
-       register_cache_invalidate(armv7m->core_cache);
+       register_cache_invalidate(armv7m->arm.core_cache);
 
        if (breakpoint)
                cortex_m3_set_breakpoint(target, breakpoint);
@@ -763,13 +850,6 @@ static int adapter_write_memory(struct target *target, uint32_t address,
        return ERROR_OK;
 }
 
-static int adapter_bulk_write_memory(struct target *target,
-               uint32_t address, uint32_t count,
-               const uint8_t *buffer)
-{
-       return adapter_write_memory(target, address, 4, count, buffer);
-}
-
 static const struct command_registration adapter_command_handlers[] = {
        {
                .chain = arm_command_handlers,
@@ -789,9 +869,9 @@ struct target_type hla_target = {
        .poll = adapter_poll,
        .arch_state = armv7m_arch_state,
 
+       .target_request_data = hl_target_request_data,
        .assert_reset = adapter_assert_reset,
        .deassert_reset = adapter_deassert_reset,
-       .soft_reset_halt = adapter_soft_reset_halt,
 
        .halt = adapter_halt,
        .resume = adapter_resume,
@@ -801,7 +881,6 @@ struct target_type hla_target = {
 
        .read_memory = adapter_read_memory,
        .write_memory = adapter_write_memory,
-       .bulk_write_memory = adapter_bulk_write_memory,
        .checksum_memory = armv7m_checksum_memory,
        .blank_check_memory = armv7m_blank_check_memory,
 

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)