hla: Add Simulated DCC register for target communicaton
authorBrent Roman <brent@mbari.org>
Fri, 26 Apr 2013 00:51:51 +0000 (17:51 -0700)
committerSpencer Oliver <spen@spen-soft.co.uk>
Fri, 14 Jun 2013 11:18:57 +0000 (11:18 +0000)
Change-Id: I193be169059caba661e46de8081d7e92f92cafee
Signed-off-by: Brent Roman <brent@mbari.org>
Reviewed-on: http://openocd.zylin.com/1364
Tested-by: jenkins
Reviewed-by: Spencer Oliver <spen@spen-soft.co.uk>
src/target/hla_target.c

index 070256fc9902686fef8012dc303eb1b5423d5265..5d31c7a2d299a72f599a072257b2b8473847f89c 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     *
 #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)
 {
@@ -263,6 +268,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)
@@ -280,6 +359,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;
 }
 
@@ -332,6 +413,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;
@@ -481,7 +567,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();
@@ -496,14 +581,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;
-       }
+       target->savedDCRDR = 0;  /* clear both DCC busy bits on initial resume */
 
-       return ERROR_OK;
+       return target->reset_halt ? ERROR_OK : target_resume(target, 1, 0, 0, 0);
 }
 
 static int adapter_soft_reset_halt(struct target *target)
@@ -583,6 +663,11 @@ static int adapter_resume(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;
+
        /* registers are now invalid */
        register_cache_invalidate(armv7m->arm.core_cache);
 
@@ -661,6 +746,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);
@@ -797,6 +887,7 @@ 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,