]> git.sur5r.net Git - openocd/blobdiff - src/target/arm11_dbgtap.c
Reset wip. Just adding hooks. This is just to reduce the size of the actual change...
[openocd] / src / target / arm11_dbgtap.c
index d77c9535115ea2a0fae65c736b484d4f0f079c91..3513e5997ece7720e8d5e9b93cba05f00b292432 100644 (file)
 #include <string.h>
 
 #if 0
-#define JTAG_DEBUG(expr ...) \
-       do { \
-           log_printf (LOG_DEBUG, __FILE__, __LINE__, __FUNCTION__, expr); \
-       } while(0)
+#define JTAG_DEBUG(expr ...)   DEBUG(expr)
 #else
-#define JTAG_DEBUG(expr ...) \
-       do {} while(0)
+#define JTAG_DEBUG(expr ...)   do {} while(0)
 #endif
 
+enum tap_state arm11_move_pi_to_si_via_ci[] =
+{
+    TAP_E2I, TAP_UI, TAP_SDS, TAP_SIS, TAP_CI, TAP_SI
+};
+
+
+int arm11_add_ir_scan_vc(int num_fields, scan_field_t *fields, enum tap_state state)
+{
+    if (cmd_queue_cur_state == TAP_PI)
+       jtag_add_pathmove(asizeof(arm11_move_pi_to_si_via_ci), arm11_move_pi_to_si_via_ci);
+
+    jtag_add_ir_scan(num_fields, fields, state);
+    return ERROR_OK;
+}
+
+enum tap_state arm11_move_pd_to_sd_via_cd[] =
+{
+    TAP_E2D, TAP_UD, TAP_SDS, TAP_CD, TAP_SD
+};
+
+int arm11_add_dr_scan_vc(int num_fields, scan_field_t *fields, enum tap_state state)
+{
+    if (cmd_queue_cur_state == TAP_PD)
+       jtag_add_pathmove(asizeof(arm11_move_pd_to_sd_via_cd), arm11_move_pd_to_sd_via_cd);
+
+    jtag_add_dr_scan(num_fields, fields, state);
+    return ERROR_OK;
+}
+
+
 /** Code de-clutter: Construct scan_field_t to write out a value
  *
  * \param arm11                Target state variable.
@@ -87,7 +113,7 @@ void arm11_add_IR(arm11_common_t * arm11, u8 instr, enum tap_state state)
 
     arm11_setup_field(arm11, 5, &instr, NULL, &field);
 
-    jtag_add_ir_scan_vc(1, &field, state == -1 ? TAP_PI : state);
+    arm11_add_ir_scan_vc(1, &field, state == -1 ? TAP_PI : state);
 }
 
 /** Verify shifted out data from Scan Chain Register (SCREG)
@@ -102,7 +128,7 @@ static int arm11_in_handler_SCAN_N(u8 *in_value, void *priv, struct scan_field_s
 
     if (v != 0x10)
     {
-        ERROR("'arm11 target' JTAG communication error SCREG SCAN OUT 0x%02x (expected 0x10)", v);
+        LOG_ERROR("'arm11 target' JTAG communication error SCREG SCAN OUT 0x%02x (expected 0x10)", v);
         exit(-1);
     }
 
@@ -146,7 +172,7 @@ void arm11_add_debug_SCAN_N(arm11_common_t * arm11, u8 chain, enum tap_state sta
 
     field.in_handler = arm11_in_handler_SCAN_N;
 
-    jtag_add_dr_scan_vc(1, &field, state == -1 ? TAP_PD : state);
+    arm11_add_dr_scan_vc(1, &field, state == -1 ? TAP_PD : state);
 }
 
 /** Write an instruction into the ITR register
@@ -175,7 +201,7 @@ void arm11_add_debug_INST(arm11_common_t * arm11, u32 inst, u8 * flag, enum tap_
     arm11_setup_field(arm11, 32,    &inst,     NULL, itr + 0);
     arm11_setup_field(arm11, 1,            NULL,       flag, itr + 1);
 
-    jtag_add_dr_scan_vc(asizeof(itr), itr, state == -1 ? TAP_RTI : state);
+    arm11_add_dr_scan_vc(asizeof(itr), itr, state == -1 ? TAP_RTI : state);
 }
 
 /** Read the Debug Status and Control Register (DSCR)
@@ -198,7 +224,7 @@ u32 arm11_read_DSCR(arm11_common_t * arm11)
 
     arm11_setup_field(arm11, 32, NULL, &dscr, &chain1_field);
 
-    jtag_add_dr_scan_vc(1, &chain1_field, TAP_PD);
+    arm11_add_dr_scan_vc(1, &chain1_field, TAP_PD);
 
     jtag_execute_queue();
 
@@ -229,7 +255,7 @@ void arm11_write_DSCR(arm11_common_t * arm11, u32 dscr)
 
     arm11_setup_field(arm11, 32, &dscr, NULL, &chain1_field);
 
-    jtag_add_dr_scan_vc(1, &chain1_field, TAP_PD);
+    arm11_add_dr_scan_vc(1, &chain1_field, TAP_PD);
 
     jtag_execute_queue();
 
@@ -250,14 +276,32 @@ enum target_debug_reason arm11_get_DSCR_debug_reason(u32 dscr)
 {
     switch (dscr & ARM11_DSCR_METHOD_OF_DEBUG_ENTRY_MASK)
     {
-    case ARM11_DSCR_METHOD_OF_DEBUG_ENTRY_HALT:                        return DBG_REASON_DBGRQ;
-    case ARM11_DSCR_METHOD_OF_DEBUG_ENTRY_BREAKPOINT:          return DBG_REASON_BREAKPOINT;
-    case ARM11_DSCR_METHOD_OF_DEBUG_ENTRY_WATCHPOINT:          return DBG_REASON_WATCHPOINT;
-    case ARM11_DSCR_METHOD_OF_DEBUG_ENTRY_BKPT_INSTRUCTION:    return DBG_REASON_BREAKPOINT;
-    case ARM11_DSCR_METHOD_OF_DEBUG_ENTRY_EDBGRQ:              return DBG_REASON_DBGRQ;
-    case ARM11_DSCR_METHOD_OF_DEBUG_ENTRY_VECTOR_CATCH:                return DBG_REASON_BREAKPOINT;
+    case ARM11_DSCR_METHOD_OF_DEBUG_ENTRY_HALT:
+       LOG_INFO("Debug entry: JTAG HALT");
+       return DBG_REASON_DBGRQ;
+
+    case ARM11_DSCR_METHOD_OF_DEBUG_ENTRY_BREAKPOINT:
+       LOG_INFO("Debug entry: breakpoint");
+       return DBG_REASON_BREAKPOINT;
+
+    case ARM11_DSCR_METHOD_OF_DEBUG_ENTRY_WATCHPOINT:
+       LOG_INFO("Debug entry: watchpoint");
+       return DBG_REASON_WATCHPOINT;
+
+    case ARM11_DSCR_METHOD_OF_DEBUG_ENTRY_BKPT_INSTRUCTION:
+       LOG_INFO("Debug entry: BKPT instruction");
+       return DBG_REASON_BREAKPOINT;
+
+    case ARM11_DSCR_METHOD_OF_DEBUG_ENTRY_EDBGRQ:
+       LOG_INFO("Debug entry: EDBGRQ signal");
+       return DBG_REASON_DBGRQ;
+
+    case ARM11_DSCR_METHOD_OF_DEBUG_ENTRY_VECTOR_CATCH:
+       LOG_INFO("Debug entry: VCR vector catch");
+       return DBG_REASON_BREAKPOINT;
 
     default:
+       LOG_INFO("Debug entry: unknown");
        return DBG_REASON_DBGRQ;
     }
 };
@@ -385,7 +429,7 @@ void arm11_run_instr_data_to_core(arm11_common_t * arm11, u32 opcode, u32 * data
        {
            Data            = *data;
 
-           jtag_add_dr_scan_vc(asizeof(chain5_fields), chain5_fields, TAP_RTI);
+           arm11_add_dr_scan_vc(asizeof(chain5_fields), chain5_fields, TAP_RTI);
            jtag_execute_queue();
 
            JTAG_DEBUG("DTR  Ready %d  nRetry %d", Ready, nRetry);
@@ -401,16 +445,106 @@ void arm11_run_instr_data_to_core(arm11_common_t * arm11, u32 opcode, u32 * data
     {
        Data        = 0;
 
-       jtag_add_dr_scan_vc(asizeof(chain5_fields), chain5_fields, TAP_PD);
+       arm11_add_dr_scan_vc(asizeof(chain5_fields), chain5_fields, TAP_PD);
        jtag_execute_queue();
 
        JTAG_DEBUG("DTR  Data %08x  Ready %d  nRetry %d", Data, Ready, nRetry);
     }
     while (!Ready);
+}
+
+/** JTAG path for arm11_run_instr_data_to_core_noack
+ *
+ *  The repeated TAP_RTI's do not cause a repeated execution
+ *  if passed without leaving the state.
+ *
+ *  Since this is more than 7 bits (adjustable via adding more
+ *  TAP_RTI's) it produces an artificial delay in the lower
+ *  layer (FT2232) that is long enough to finish execution on
+ *  the core but still shorter than any manually inducible delays.
+ *
+ */
+enum tap_state arm11_MOVE_PD_RTI_PD_with_delay[] =
+{
+    TAP_E2D, TAP_UD, TAP_RTI, TAP_RTI, TAP_RTI, TAP_SDS, TAP_CD, TAP_SD
+};
+
+
 
+/** Execute one instruction via ITR repeatedly while
+ *  passing data to the core via DTR on each execution.
+ *
+ *  No Ready check during transmission.
+ *
+ *  The executed instruction \em must read data from DTR.
+ *
+ * \pre arm11_run_instr_data_prepare() /  arm11_run_instr_data_finish() block
+ *
+ * \param arm11                Target state variable.
+ * \param opcode       ARM opcode
+ * \param data         Pointer to the data words to be passed to the core
+ * \param count                Number of data words and instruction repetitions
+ *
+ */
+void arm11_run_instr_data_to_core_noack(arm11_common_t * arm11, u32 opcode, u32 * data, size_t count)
+{
+    arm11_add_IR(arm11, ARM11_ITRSEL, -1);
+
+    arm11_add_debug_INST(arm11, opcode, NULL, TAP_PD);
+
+    arm11_add_IR(arm11, ARM11_EXTEST, -1);
+
+    scan_field_t       chain5_fields[3];
+
+    arm11_setup_field(arm11, 32,    NULL/*&Data*/,  NULL,      chain5_fields + 0);
+    arm11_setup_field(arm11,  1,    NULL,   NULL /*&Ready*/,   chain5_fields + 1);
+    arm11_setup_field(arm11,  1,    NULL,   NULL,      chain5_fields + 2);
+
+    u8                 Readies[count + 1];
+    u8 *               ReadyPos            = Readies;
+
+    while (count--)
+    {
+       chain5_fields[0].out_value      = (void *)(data++);
+       chain5_fields[1].in_value       = ReadyPos++;
 
+       if (count)
+       {
+           jtag_add_dr_scan(asizeof(chain5_fields), chain5_fields, TAP_PD);
+           jtag_add_pathmove(asizeof(arm11_MOVE_PD_RTI_PD_with_delay),
+               arm11_MOVE_PD_RTI_PD_with_delay); 
+       }
+       else
+       {
+           jtag_add_dr_scan(asizeof(chain5_fields), chain5_fields, TAP_RTI);
+       }
+    }
+
+    arm11_add_IR(arm11, ARM11_INTEST, -1);
+
+    chain5_fields[0].out_value = 0;
+    chain5_fields[1].in_value   = ReadyPos++;
+
+    arm11_add_dr_scan_vc(asizeof(chain5_fields), chain5_fields, TAP_PD);
+
+    jtag_execute_queue();
+
+    size_t error_count = 0;
+
+    {size_t i;
+    for (i = 0; i < asizeof(Readies); i++)
+    {
+       if (Readies[i] != 1)
+       {
+           error_count++;
+       }
+    }}
+
+    if (error_count)
+       LOG_ERROR("Transfer errors " ZU, error_count);
 }
 
+
 /** Execute an instruction via ITR while handing data into the core via DTR.
  *
  *  The executed instruction \em must read data from DTR.
@@ -463,7 +597,7 @@ void arm11_run_instr_data_from_core(arm11_common_t * arm11, u32 opcode, u32 * da
     {
        do
        {
-           jtag_add_dr_scan_vc(asizeof(chain5_fields), chain5_fields, count ? TAP_RTI : TAP_PD);
+           arm11_add_dr_scan_vc(asizeof(chain5_fields), chain5_fields, count ? TAP_RTI : TAP_PD);
            jtag_execute_queue();
 
            JTAG_DEBUG("DTR  Data %08x  Ready %d  nRetry %d", Data, Ready, nRetry);
@@ -514,7 +648,15 @@ void arm11_run_instr_data_to_core_via_r0(arm11_common_t * arm11, u32 opcode, u32
     arm11_run_instr_no_data1(arm11, opcode);
 }
 
-
+/** Apply reads and writes to scan chain 7
+ *
+ * \see arm11_sc7_action_t
+ *
+ * \param arm11                Target state variable.
+ * \param actions      A list of read and/or write instructions
+ * \param count                Number of instructions in the list.
+ *
+ */
 void arm11_sc7_run(arm11_common_t * arm11, arm11_sc7_action_t * actions, size_t count)
 {
     arm11_add_debug_SCAN_N(arm11, 0x07, -1);
@@ -554,7 +696,7 @@ void arm11_sc7_run(arm11_common_t * arm11, arm11_sc7_action_t * actions, size_t
        {
            JTAG_DEBUG("SC7 <= Address %02x  Data %08x    nRW %d", AddressOut, DataOut, nRW);
 
-           jtag_add_dr_scan_vc(asizeof(chain7_fields), chain7_fields, TAP_PD);
+           arm11_add_dr_scan_vc(asizeof(chain7_fields), chain7_fields, TAP_PD);
            jtag_execute_queue();
 
            JTAG_DEBUG("SC7 => Address %02x  Data %08x  Ready %d", AddressIn, DataIn, Ready);
@@ -565,7 +707,7 @@ void arm11_sc7_run(arm11_common_t * arm11, arm11_sc7_action_t * actions, size_t
        {
            if (actions[i - 1].address != AddressIn)
            {
-               WARNING("Scan chain 7 shifted out unexpected address");
+               LOG_WARNING("Scan chain 7 shifted out unexpected address");
            }
 
            if (!actions[i - 1].write)
@@ -576,7 +718,7 @@ void arm11_sc7_run(arm11_common_t * arm11, arm11_sc7_action_t * actions, size_t
            {
                if (actions[i - 1].value != DataIn)
                {
-                   WARNING("Scan chain 7 shifted out unexpected data");
+                   LOG_WARNING("Scan chain 7 shifted out unexpected data");
                }
            }
        }
@@ -589,23 +731,75 @@ void arm11_sc7_run(arm11_common_t * arm11, arm11_sc7_action_t * actions, size_t
     }}
 }
 
-void arm11_sc7_clear_bw(arm11_common_t * arm11)
+/** Clear VCR and all breakpoints and watchpoints via scan chain 7
+ *
+ * \param arm11                Target state variable.
+ *
+ */
+void arm11_sc7_clear_vbw(arm11_common_t * arm11)
 {
-    size_t actions = arm11->brp + arm11->wrp;
-
-    arm11_sc7_action_t         clear_bw[actions];
+    arm11_sc7_action_t         clear_bw[arm11->brp + arm11->wrp + 1];
+    arm11_sc7_action_t *       pos = clear_bw;
 
     {size_t i;
-    for (i = 0; i < actions; i++)
+    for (i = 0; i < asizeof(clear_bw); i++)
     {
        clear_bw[i].write       = true;
        clear_bw[i].value       = 0;
-       clear_bw[i].address     =
-           i < arm11->brp ?
-               ARM11_SC7_BCR0 + i :
-               ARM11_SC7_WCR0 + i - arm11->brp;
     }}
 
-    arm11_sc7_run(arm11, clear_bw, actions);
+    {size_t i;
+    for (i = 0; i < arm11->brp; i++)
+       (pos++)->address = ARM11_SC7_BCR0 + i;
+    }
+
+    {size_t i;
+    for (i = 0; i < arm11->wrp; i++)
+       (pos++)->address = ARM11_SC7_WCR0 + i;
+    }
+
+    (pos++)->address = ARM11_SC7_VCR;
+
+    arm11_sc7_run(arm11, clear_bw, asizeof(clear_bw));
+}
+
+/** Write VCR register
+ *
+ * \param arm11                Target state variable.
+ * \param value                Value to be written
+ */
+void arm11_sc7_set_vcr(arm11_common_t * arm11, u32 value)
+{
+    arm11_sc7_action_t         set_vcr;
+
+    set_vcr.write              = true;
+    set_vcr.address            = ARM11_SC7_VCR;
+    set_vcr.value              = value;
+
+
+    arm11_sc7_run(arm11, &set_vcr, 1);
 }
 
+
+
+/** Read word from address
+ *
+ * \param arm11                Target state variable.
+ * \param address      Memory address to be read
+ * \param result       Pointer where to store result
+ *
+ */
+void arm11_read_memory_word(arm11_common_t * arm11, u32 address, u32 * result)
+{
+    arm11_run_instr_data_prepare(arm11);
+
+    /* MRC p14,0,r0,c0,c5,0 (r0 = address) */
+    arm11_run_instr_data_to_core1(arm11, 0xee100e15, address);
+
+    /* LDC p14,c5,[R0],#4 (DTR = [r0]) */
+    arm11_run_instr_data_from_core(arm11, 0xecb05e01, result, 1);
+
+    arm11_run_instr_data_finish(arm11);
+}
+
+