debug feature: jtagtcpip, improve performance
[fw/openocd] / src / jtag / zy1000 / zy1000.c
index b50e96a8a00c2e9178be5111a77ff14f54a6baec..97c94f7c2a2a2d32e0a275683a0157f9b8820a15 100644 (file)
 
 #endif
 
+
+/* The software needs to check if it's in RCLK mode or not */
+static bool zy1000_rclk = false;
+
 static int zy1000_khz(int khz, int *jtag_speed)
 {
        if (khz == 0)
@@ -222,11 +226,13 @@ int zy1000_speed(int speed)
        /* flush JTAG master FIFO before setting speed */
        waitIdle();
 
+       zy1000_rclk = false;
+
        if (speed == 0)
        {
                /*0 means RCLK*/
-               speed = 0;
                ZY1000_POKE(ZY1000_JTAG_BASE + 0x10, 0x100);
+               zy1000_rclk = true;
                LOG_DEBUG("jtag_speed using RCLK");
        }
        else
@@ -456,17 +462,24 @@ int interface_jtag_execute_queue(void)
        uint32_t empty;
 
        waitIdle();
-       ZY1000_PEEK(ZY1000_JTAG_BASE + 0x10, empty);
-       /* clear JTAG error register */
-       ZY1000_POKE(ZY1000_JTAG_BASE + 0x14, 0x400);
 
-       if ((empty&0x400) != 0)
+       if (zy1000_rclk)
        {
-               LOG_WARNING("RCLK timeout");
-               /* the error is informative only as we don't want to break the firmware if there
-                * is a false positive.
+               /* Only check for errors when using RCLK to speed up
+                * jtag over TCP/IP
                 */
-//             return ERROR_FAIL;
+               ZY1000_PEEK(ZY1000_JTAG_BASE + 0x10, empty);
+               /* clear JTAG error register */
+               ZY1000_POKE(ZY1000_JTAG_BASE + 0x14, 0x400);
+
+               if ((empty&0x400) != 0)
+               {
+                       LOG_WARNING("RCLK timeout");
+                       /* the error is informative only as we don't want to break the firmware if there
+                        * is a false positive.
+                        */
+       //              return ERROR_FAIL;
+               }
        }
        return ERROR_OK;
 }
@@ -878,101 +891,100 @@ void embeddedice_write_dcc(struct jtag_tap *tap, int reg_addr, uint8_t *buffer,
 
 int arm11_run_instr_data_to_core_noack_inner(struct jtag_tap * tap, uint32_t opcode, uint32_t * data, size_t count)
 {
-#if 0
-       int arm11_run_instr_data_to_core_noack_inner_default(struct jtag_tap * tap, uint32_t opcode, uint32_t * data, size_t count);
-       return arm11_run_instr_data_to_core_noack_inner_default(tap, opcode, data, count);
-#else
-       static const int bits[] = {32, 2};
-       uint32_t values[] = {0, 0};
-
-       /* FIX!!!!!! the target_write_memory() API started this nasty problem
-        * with unaligned uint32_t * pointers... */
-       const uint8_t *t = (const uint8_t *)data;
-
-
        /* bypass bits before and after */
        int pre_bits;
        int post_bits;
        jtag_pre_post_bits(tap, &pre_bits, &post_bits);
-
-       bool found = false;
-       struct jtag_tap *cur_tap, *nextTap;
-       for (cur_tap = jtag_tap_next_enabled(NULL); cur_tap!= NULL; cur_tap = nextTap)
-       {
-               nextTap = jtag_tap_next_enabled(cur_tap);
-               if (cur_tap == tap)
-               {
-                       found = true;
-               } else
-               {
-                       if (found)
-                       {
-                               post_bits++;
-                       } else
-                       {
-                               pre_bits++;
-                       }
-               }
-       }
-
        post_bits+=2;
 
-
-       while (--count > 0)
+       if ((pre_bits > 32) || (post_bits > 32))
        {
-               shiftValueInner(TAP_DRSHIFT, TAP_DRSHIFT, pre_bits, 0);
-
-               uint32_t value;
-               value = *t++;
-               value |= (*t++<<8);
-               value |= (*t++<<16);
-               value |= (*t++<<24);
+               int arm11_run_instr_data_to_core_noack_inner_default(struct jtag_tap * tap, uint32_t opcode, uint32_t * data, size_t count);
+               return arm11_run_instr_data_to_core_noack_inner_default(tap, opcode, data, count);
+       } else
+       {
+               static const int bits[] = {32, 2};
+               uint32_t values[] = {0, 0};
 
-               shiftValueInner(TAP_DRSHIFT, TAP_DRSHIFT, 32, value);
-               /* minimum 2 bits */
-               shiftValueInner(TAP_DRSHIFT, TAP_DRPAUSE, post_bits, 0);
+               /* FIX!!!!!! the target_write_memory() API started this nasty problem
+                * with unaligned uint32_t * pointers... */
+               const uint8_t *t = (const uint8_t *)data;
 
+               while (--count > 0)
+               {
 #if 1
-               /* copy & paste from arm11_dbgtap.c */
-               //TAP_DREXIT2, TAP_DRUPDATE, TAP_IDLE, TAP_IDLE, TAP_IDLE, TAP_DRSELECT, TAP_DRCAPTURE, TAP_DRSHIFT
+                       /* Danger! This code doesn't update cmd_queue_cur_state, so
+                        * invoking jtag_add_pathmove() before jtag_add_dr_out() after
+                        * this loop would fail!
+                        */
+                       shiftValueInner(TAP_DRSHIFT, TAP_DRSHIFT, pre_bits, 0);
 
-               waitIdle();
-               ZY1000_POKE(ZY1000_JTAG_BASE + 0x28, 1);
-               ZY1000_POKE(ZY1000_JTAG_BASE + 0x28, 1);
-               ZY1000_POKE(ZY1000_JTAG_BASE + 0x28, 0);
-               ZY1000_POKE(ZY1000_JTAG_BASE + 0x28, 0);
-               ZY1000_POKE(ZY1000_JTAG_BASE + 0x28, 0);
-               ZY1000_POKE(ZY1000_JTAG_BASE + 0x28, 1);
-               ZY1000_POKE(ZY1000_JTAG_BASE + 0x28, 0);
-               ZY1000_POKE(ZY1000_JTAG_BASE + 0x28, 0);
-               /* we don't have to wait for the queue to empty here. waitIdle();        */
-               ZY1000_POKE(ZY1000_JTAG_BASE + 0x20, TAP_DRSHIFT);
+                       uint32_t value;
+                       value = *t++;
+                       value |= (*t++<<8);
+                       value |= (*t++<<16);
+                       value |= (*t++<<24);
+
+                       shiftValueInner(TAP_DRSHIFT, TAP_DRSHIFT, 32, value);
+                       /* minimum 2 bits */
+                       shiftValueInner(TAP_DRSHIFT, TAP_DRPAUSE, post_bits, 0);
+
+                       /* copy & paste from arm11_dbgtap.c */
+                       //TAP_DREXIT2, TAP_DRUPDATE, TAP_IDLE, TAP_IDLE, TAP_IDLE, TAP_DRSELECT, TAP_DRCAPTURE, TAP_DRSHIFT
+                       /* KLUDGE! we have to flush the fifo or the Nios CPU locks up.
+                        * This is probably a bug in the Avalon bus(cross clocking bridge?)
+                        * or in the jtag registers module.
+                        */
+                       waitIdle();
+                       ZY1000_POKE(ZY1000_JTAG_BASE + 0x28, 1);
+                       ZY1000_POKE(ZY1000_JTAG_BASE + 0x28, 1);
+                       ZY1000_POKE(ZY1000_JTAG_BASE + 0x28, 0);
+                       ZY1000_POKE(ZY1000_JTAG_BASE + 0x28, 0);
+                       ZY1000_POKE(ZY1000_JTAG_BASE + 0x28, 0);
+                       ZY1000_POKE(ZY1000_JTAG_BASE + 0x28, 1);
+                       ZY1000_POKE(ZY1000_JTAG_BASE + 0x28, 0);
+                       ZY1000_POKE(ZY1000_JTAG_BASE + 0x28, 0);
+                       /* we don't have to wait for the queue to empty here */
+                       ZY1000_POKE(ZY1000_JTAG_BASE + 0x20, TAP_DRSHIFT);
+                       waitIdle();
 #else
-               static const tap_state_t arm11_MOVE_DRPAUSE_IDLE_DRPAUSE_with_delay[] =
-               {
-                       TAP_DREXIT2, TAP_DRUPDATE, TAP_IDLE, TAP_IDLE, TAP_IDLE, TAP_DRSELECT, TAP_DRCAPTURE, TAP_DRSHIFT
-               };
-
-               jtag_add_pathmove(ARRAY_SIZE(arm11_MOVE_DRPAUSE_IDLE_DRPAUSE_with_delay),
-                       arm11_MOVE_DRPAUSE_IDLE_DRPAUSE_with_delay);
+                       static const tap_state_t arm11_MOVE_DRPAUSE_IDLE_DRPAUSE_with_delay[] =
+                       {
+                               TAP_DREXIT2, TAP_DRUPDATE, TAP_IDLE, TAP_IDLE, TAP_IDLE, TAP_DRSELECT, TAP_DRCAPTURE, TAP_DRSHIFT
+                       };
+
+                       values[0] = *t++;
+                       values[0] |= (*t++<<8);
+                       values[0] |= (*t++<<16);
+                       values[0] |= (*t++<<24);
+
+                       jtag_add_dr_out(tap,
+                               2,
+                               bits,
+                               values,
+                               TAP_IDLE);
+
+                       jtag_add_pathmove(ARRAY_SIZE(arm11_MOVE_DRPAUSE_IDLE_DRPAUSE_with_delay),
+                               arm11_MOVE_DRPAUSE_IDLE_DRPAUSE_with_delay);
 #endif
-       }
+               }
 
-       values[0] = *t++;
-       values[0] |= (*t++<<8);
-       values[0] |= (*t++<<16);
-       values[0] |= (*t++<<24);
+               values[0] = *t++;
+               values[0] |= (*t++<<8);
+               values[0] |= (*t++<<16);
+               values[0] |= (*t++<<24);
 
-       /* This will happen on the last iteration updating the current tap state
-        * so we don't have to track it during the common code path */
-       jtag_add_dr_out(tap,
-               2,
-               bits,
-               values,
-               TAP_IDLE);
+               /* This will happen on the last iteration updating cmd_queue_cur_state
+                * so we don't have to track it during the common code path
+                */
+               jtag_add_dr_out(tap,
+                       2,
+                       bits,
+                       values,
+                       TAP_IDLE);
 
-       return jtag_execute_queue();
-#endif
+               return jtag_execute_queue();
+       }
 }
 
 
@@ -1095,6 +1107,7 @@ enum ZY1000_CMD
        ZY1000_CMD_POKE = 0x0,
        ZY1000_CMD_PEEK = 0x8,
        ZY1000_CMD_SLEEP = 0x1,
+       ZY1000_CMD_WAITIDLE = 2
 };
 
 
@@ -1155,6 +1168,22 @@ void zy1000_tcpout(uint32_t address, uint32_t data)
        }
 }
 
+/* By sending the wait to the server, we avoid a readback
+ * of status. Radically improves performance for this operation
+ * with long ping times.
+ */
+void waitIdle(void)
+{
+       tcpip_open();
+       if (!writeLong((ZY1000_CMD_WAITIDLE << 24)))
+       {
+               fprintf(stderr, "Could not write to zy1000 server\n");
+               exit(-1);
+       }
+}
+
+
+
 uint32_t zy1000_tcpin(uint32_t address)
 {
        tcpip_open();
@@ -1229,6 +1258,11 @@ static void tcpipserver(void)
                                jtag_sleep(data);
                                break;
                        }
+                       case ZY1000_CMD_WAITIDLE:
+                       {
+                               waitIdle();
+                               break;
+                       }
                        default:
                                return;
                }