ARM11: store a clean copy of DSCR
authorDavid Brownell <dbrownell@users.sourceforge.net>
Thu, 3 Dec 2009 06:57:08 +0000 (22:57 -0800)
committerDavid Brownell <dbrownell@users.sourceforge.net>
Thu, 3 Dec 2009 07:08:43 +0000 (23:08 -0800)
Just store a clean copy of DSCR in the per-CPU struct, so we
trivially pass a pointer to a recent copy.  This replaces the
previous "last_dscr" and cleans up most of the related calling
conventions ... but it doesn't remove the other DSCR copy.

src/target/arm11.c
src/target/arm11.h
src/target/arm11_dbgtap.c
src/target/arm11_dbgtap.h

index 608008620a1e29236d5cbd92693b8781250ba509..5bbf4652d5c6cb03fbe92066395378a9b802e041 100644 (file)
@@ -86,33 +86,24 @@ static int arm11_get_reg(struct reg *reg);
 /** Check and if necessary take control of the system
  *
  * \param arm11                Target state variable.
- * \param dscr         If the current DSCR content is
- *                                     available a pointer to a word holding the
- *                                     DSCR can be passed. Otherwise use NULL.
  */
-static int arm11_check_init(struct arm11_common *arm11, uint32_t *dscr)
+static int arm11_check_init(struct arm11_common *arm11)
 {
-       uint32_t                        dscr_local_tmp_copy;
+       CHECK_RETVAL(arm11_read_DSCR(arm11));
+       LOG_DEBUG("DSCR %08x", (unsigned) arm11->dscr);
 
-       if (!dscr)
-       {
-               dscr = &dscr_local_tmp_copy;
-
-               CHECK_RETVAL(arm11_read_DSCR(arm11, dscr));
-       }
-
-       if (!(*dscr & ARM11_DSCR_MODE_SELECT))
+       if (!(arm11->dscr & ARM11_DSCR_MODE_SELECT))
        {
                LOG_DEBUG("Bringing target into debug mode");
 
-               *dscr |= ARM11_DSCR_MODE_SELECT;                /* Halt debug-mode */
-               arm11_write_DSCR(arm11, *dscr);
+               arm11->dscr |= ARM11_DSCR_MODE_SELECT;          /* Halt debug-mode */
+               arm11_write_DSCR(arm11, arm11->dscr);
 
                /* add further reset initialization here */
 
                arm11->simulate_reset_on_next_halt = true;
 
-               if (*dscr & ARM11_DSCR_CORE_HALTED)
+               if (arm11->dscr & ARM11_DSCR_CORE_HALTED)
                {
                        /** \todo TODO: this needs further scrutiny because
                          * arm11_debug_entry() never gets called.  (WHY NOT?)
@@ -122,7 +113,7 @@ static int arm11_check_init(struct arm11_common *arm11, uint32_t *dscr)
 
                        arm11->arm.target->state = TARGET_HALTED;
                        arm11->arm.target->debug_reason =
-                                       arm11_get_DSCR_debug_reason(*dscr);
+                                       arm11_get_DSCR_debug_reason(arm11->dscr);
                }
                else
                {
@@ -144,14 +135,15 @@ static int arm11_check_init(struct arm11_common *arm11, uint32_t *dscr)
 /**
  * Save processor state.  This is called after a HALT instruction
  * succeeds, and on other occasions the processor enters debug mode
- * (breakpoint, watchpoint, etc).
+ * (breakpoint, watchpoint, etc).  Caller has updated arm11->dscr.
  */
-static int arm11_debug_entry(struct arm11_common *arm11, uint32_t dscr)
+static int arm11_debug_entry(struct arm11_common *arm11)
 {
        int retval;
 
        arm11->arm.target->state = TARGET_HALTED;
-       arm11->arm.target->debug_reason = arm11_get_DSCR_debug_reason(dscr);
+       arm11->arm.target->debug_reason =
+                       arm11_get_DSCR_debug_reason(arm11->dscr);
 
        /* REVISIT entire cache should already be invalid !!! */
        register_cache_invalidate(arm11->arm.core_cache);
@@ -165,10 +157,10 @@ static int arm11_debug_entry(struct arm11_common *arm11, uint32_t dscr)
        /* See e.g. ARM1136 TRM, "14.8.4 Entering Debug state" */
 
        /* Save DSCR */
-       R(DSCR) = dscr;
+       R(DSCR) = arm11->dscr;
 
-       /* Save wDTR */
-       arm11->is_wdtr_saved = !!(dscr & ARM11_DSCR_WDTR_FULL);
+       /* maybe save wDTR (pending DCC write to debug SW, e.g. libdcc) */
+       arm11->is_wdtr_saved = !!(arm11->dscr & ARM11_DSCR_WDTR_FULL);
        if (arm11->is_wdtr_saved)
        {
                arm11_add_debug_SCAN_N(arm11, 0x05, ARM11_TAP_DEFAULT);
@@ -183,6 +175,7 @@ static int arm11_debug_entry(struct arm11_common *arm11, uint32_t dscr)
                arm11_setup_field(arm11,  1, NULL, NULL,                chain5_fields + 2);
 
                arm11_add_dr_scan_vc(ARRAY_SIZE(chain5_fields), chain5_fields, TAP_DRPAUSE);
+
        }
 
        /* DSCR: set ARM11_DSCR_EXECUTE_ARM_INSTRUCTION_ENABLE
@@ -191,11 +184,9 @@ static int arm11_debug_entry(struct arm11_common *arm11, uint32_t dscr)
         * but not to issue ITRs. ARM1136 seems to require this to issue
         * ITR's as well...
         */
-       uint32_t new_dscr = dscr | ARM11_DSCR_EXECUTE_ARM_INSTRUCTION_ENABLE;
 
-       /* this executes JTAG queue: */
-
-       arm11_write_DSCR(arm11, new_dscr);
+       arm11_write_DSCR(arm11, ARM11_DSCR_EXECUTE_ARM_INSTRUCTION_ENABLE
+                               | arm11->dscr);
 
 
        /* From the spec:
@@ -243,8 +234,8 @@ static int arm11_debug_entry(struct arm11_common *arm11, uint32_t dscr)
        if (retval != ERROR_OK)
                return retval;
 
-       /* maybe save rDTR */
-       arm11->is_rdtr_saved = !!(dscr & ARM11_DSCR_RDTR_FULL);
+       /* maybe save rDTR (pending DCC read from debug SW, e.g. libdcc) */
+       arm11->is_rdtr_saved = !!(arm11->dscr & ARM11_DSCR_RDTR_FULL);
        if (arm11->is_rdtr_saved)
        {
                /* MRC p14,0,R0,c0,c5,0 (move rDTR -> r0 (-> wDTR -> local var)) */
@@ -302,11 +293,9 @@ static int arm11_leave_debug_state(struct arm11_common *arm11, bool bpwp)
        /* spec says clear wDTR and rDTR; we assume they are clear as
           otherwise our programming would be sloppy */
        {
-               uint32_t DSCR;
-
-               CHECK_RETVAL(arm11_read_DSCR(arm11, &DSCR));
+               CHECK_RETVAL(arm11_read_DSCR(arm11));
 
-               if (DSCR & (ARM11_DSCR_RDTR_FULL | ARM11_DSCR_WDTR_FULL))
+               if (arm11->dscr & (ARM11_DSCR_RDTR_FULL | ARM11_DSCR_WDTR_FULL))
                {
                        /*
                        The wDTR/rDTR two registers that are used to send/receive data to/from
@@ -315,7 +304,8 @@ static int arm11_leave_debug_state(struct arm11_common *arm11, bool bpwp)
                        registers hold data that was written by one side (CPU or JTAG) and not
                        read out by the other side.
                        */
-                       LOG_ERROR("wDTR/rDTR inconsistent (DSCR %08" PRIx32 ")", DSCR);
+                       LOG_ERROR("wDTR/rDTR inconsistent (DSCR %08x)",
+                                       (unsigned) arm11->dscr);
                        return ERROR_FAIL;
                }
        }
@@ -380,22 +370,17 @@ static int arm11_poll(struct target *target)
 {
        int retval;
        struct arm11_common *arm11 = target_to_arm11(target);
-       uint32_t        dscr;
-
-       CHECK_RETVAL(arm11_read_DSCR(arm11, &dscr));
 
-       LOG_DEBUG("DSCR %08" PRIx32 "", dscr);
+       CHECK_RETVAL(arm11_check_init(arm11));
 
-       CHECK_RETVAL(arm11_check_init(arm11, &dscr));
-
-       if (dscr & ARM11_DSCR_CORE_HALTED)
+       if (arm11->dscr & ARM11_DSCR_CORE_HALTED)
        {
                if (target->state != TARGET_HALTED)
                {
                        enum target_state old_state = target->state;
 
                        LOG_DEBUG("enter TARGET_HALTED");
-                       retval = arm11_debug_entry(arm11, dscr);
+                       retval = arm11_debug_entry(arm11);
                        if (retval != ERROR_OK)
                                return retval;
 
@@ -459,14 +444,13 @@ static int arm11_halt(struct target *target)
 
        CHECK_RETVAL(jtag_execute_queue());
 
-       uint32_t dscr;
        int i = 0;
 
        while (1)
        {
-               CHECK_RETVAL(arm11_read_DSCR(arm11, &dscr));
+               CHECK_RETVAL(arm11_read_DSCR(arm11));
 
-               if (dscr & ARM11_DSCR_CORE_HALTED)
+               if (arm11->dscr & ARM11_DSCR_CORE_HALTED)
                        break;
 
 
@@ -488,7 +472,7 @@ static int arm11_halt(struct target *target)
 
        enum target_state old_state     = target->state;
 
-       arm11_debug_entry(arm11, dscr);
+       arm11_debug_entry(arm11);
 
        CHECK_RETVAL(
                target_call_event_callbacks(target,
@@ -590,13 +574,11 @@ static int arm11_resume(struct target *target, int current,
        int i = 0;
        while (1)
        {
-               uint32_t dscr;
-
-               CHECK_RETVAL(arm11_read_DSCR(arm11, &dscr));
+               CHECK_RETVAL(arm11_read_DSCR(arm11));
 
-               LOG_DEBUG("DSCR %08" PRIx32 "", dscr);
+               LOG_DEBUG("DSCR %08x", (unsigned) arm11->dscr);
 
-               if (dscr & ARM11_DSCR_CORE_RESTARTED)
+               if (arm11->dscr & ARM11_DSCR_CORE_RESTARTED)
                        break;
 
 
@@ -753,16 +735,16 @@ static int arm11_step(struct target *target, int current,
 
                /* wait for halt */
                int i = 0;
-               uint32_t dscr;
 
                while (1)
                {
-                       CHECK_RETVAL(arm11_read_DSCR(arm11, &dscr));
+                       const uint32_t mask = ARM11_DSCR_CORE_RESTARTED
+                                       | ARM11_DSCR_CORE_HALTED;
 
-                       LOG_DEBUG("DSCR %08" PRIx32 "e", dscr);
+                       CHECK_RETVAL(arm11_read_DSCR(arm11));
+                       LOG_DEBUG("DSCR %08x e", (unsigned) arm11->dscr);
 
-                       if ((dscr & (ARM11_DSCR_CORE_RESTARTED | ARM11_DSCR_CORE_HALTED)) ==
-                               (ARM11_DSCR_CORE_RESTARTED | ARM11_DSCR_CORE_HALTED))
+                       if ((arm11->dscr & mask) == mask)
                                break;
 
                        long long then = 0;
@@ -785,7 +767,7 @@ static int arm11_step(struct target *target, int current,
                arm11_sc7_clear_vbw(arm11);
 
                /* save state */
-               CHECK_RETVAL(arm11_debug_entry(arm11, dscr));
+               CHECK_RETVAL(arm11_debug_entry(arm11));
 
            /* restore default state */
                R(DSCR) &= ~ARM11_DSCR_INTERRUPTS_DISABLE;
@@ -804,7 +786,7 @@ static int arm11_assert_reset(struct target *target)
        int retval;
        struct arm11_common *arm11 = target_to_arm11(target);
 
-       retval = arm11_check_init(arm11, NULL);
+       retval = arm11_check_init(arm11);
        if (retval != ERROR_OK)
                return retval;
 
@@ -1303,7 +1285,7 @@ static int arm11_examine(struct target *target)
         * as suggested by the spec.
         */
 
-       retval = arm11_check_init(arm11, NULL);
+       retval = arm11_check_init(arm11);
        if (retval != ERROR_OK)
                return retval;
 
index 56feb2ea54a0b0239a50b9f10f1b454013e4c638..1cc09e1450cfe53c6d48a6248c72831944c08029 100644 (file)
@@ -59,8 +59,7 @@ struct arm11_common
        size_t  wrp;                    /**< Number of Watchpoint Register Pairs from DIDR      */
        size_t  free_brps;              /**< Number of breakpoints allocated */
 
-       uint32_t                last_dscr;              /**< Last retrieved DSCR value;
-                                                            Use only for debug message generation              */
+       uint32_t dscr;                  /**< Last retrieved DSCR value. */
 
        uint32_t saved_rdtr;
        uint32_t saved_wdtr;
index 7fd5e3a1e008cb25bc2e60ba32aac7ca033fccba..7e1e9cba7493055852d19e1fd7189027e6758e6a 100644 (file)
@@ -214,19 +214,20 @@ static void arm11_add_debug_INST(struct arm11_common * arm11,
        arm11_add_dr_scan_vc(ARRAY_SIZE(itr), itr, state == ARM11_TAP_DEFAULT ? TAP_IDLE : state);
 }
 
-/** Read the Debug Status and Control Register (DSCR)
- *
- * same as CP14 c1
+/**
+ * Read and save the Debug Status and Control Register (DSCR).
  *
  * \param arm11                Target state variable.
- * \param value                DSCR content
- * \return                     Error status
+ * \return Error status; arm11->dscr is updated on success.
  *
- * \remarks                    This is a stand-alone function that executes the JTAG command queue.
+ * \remarks This is a stand-alone function that executes the JTAG
+ * command queue.  It does not require the ARM11 debug TAP to be
+ * in any particular state.
  */
-int arm11_read_DSCR(struct arm11_common * arm11, uint32_t *value)
+int arm11_read_DSCR(struct arm11_common *arm11)
 {
        int retval;
+
        retval = arm11_add_debug_SCAN_N(arm11, 0x01, ARM11_TAP_DEFAULT);
        if (retval != ERROR_OK)
                return retval;
@@ -242,14 +243,12 @@ int arm11_read_DSCR(struct arm11_common * arm11, uint32_t *value)
 
        CHECK_RETVAL(jtag_execute_queue());
 
-       if (arm11->last_dscr != dscr)
+       if (arm11->dscr != dscr)
                JTAG_DEBUG("DSCR  = %08x (OLD %08x)",
                                (unsigned) dscr,
-                               (unsigned) arm11->last_dscr);
-
-       arm11->last_dscr = dscr;
+                               (unsigned) arm11->dscr);
 
-       *value = dscr;
+       arm11->dscr = dscr;
 
        return ERROR_OK;
 }
@@ -282,9 +281,9 @@ int arm11_write_DSCR(struct arm11_common * arm11, uint32_t dscr)
 
        JTAG_DEBUG("DSCR <= %08x (OLD %08x)",
                        (unsigned) dscr,
-                       (unsigned) arm11->last_dscr);
+                       (unsigned) arm11->dscr);
 
-       arm11->last_dscr = dscr;
+       arm11->dscr = dscr;
 
        return ERROR_OK;
 }
index 2203361d632f91103ac74d23ce77dd0720072482..fa197447e1577390f118d8db0d3f4e2e07734c81 100644 (file)
@@ -11,7 +11,7 @@ void arm11_add_IR(struct arm11_common *arm11,
                uint8_t instr, tap_state_t state);
 int arm11_add_debug_SCAN_N(struct arm11_common *arm11,
                uint8_t chain, tap_state_t state);
-int arm11_read_DSCR(struct arm11_common *arm11, uint32_t *dscr);
+int arm11_read_DSCR(struct arm11_common *arm11);
 int arm11_write_DSCR(struct arm11_common *arm11, uint32_t dscr);
 
 enum target_debug_reason arm11_get_DSCR_debug_reason(uint32_t dscr);