zy1000: dev tool
authorØyvind Harboe <oyvind.harboe@zylin.com>
Thu, 4 Mar 2010 18:58:42 +0000 (19:58 +0100)
committerØyvind Harboe <oyvind.harboe@zylin.com>
Thu, 25 Mar 2010 19:46:34 +0000 (20:46 +0100)
first cut peek/poke over tcp/ip, used for debug/research
purposes only. Long term JTAG over TCP/IP might be an
offshoot. The performance is usable for development/testing
purposes.

Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
src/jtag/zy1000/jtag_minidriver.h
src/jtag/zy1000/zy1000.c

index 43d0c9755f32ec27316abbcef16a61906055cabb..d556699ab09d754826ee38bbf0ac81eb7f3664ac 100644 (file)
@@ -38,8 +38,11 @@ int  diag_printf(const char *fmt, ...);
 #else
 
 /* redirect this to TCP/IP */
-#define ZY1000_PEEK(a, b) b = 1;
-#define ZY1000_POKE(a, b)
+#define ZY1000_JTAG_BASE 0
+extern void zy1000_tcpout(uint32_t address, uint32_t data);
+extern uint32_t zy1000_tcpin(uint32_t address);
+#define ZY1000_PEEK(a, b) b=zy1000_tcpin(a)
+#define ZY1000_POKE(a, b) zy1000_tcpout(a, b)
 
 #endif
 
index 907b96578616885f560acb9f2e510f62c798040e..80731aabe207c2b80f111927e016d1da2a69e6e3 100644 (file)
@@ -50,6 +50,7 @@
 #include <jtag/interface.h>
 #include <time.h>
 
+#include <netinet/tcp.h>
 
 #if BUILD_ECOSBOARD
 #include "zy1000_version.h"
@@ -262,6 +263,18 @@ COMMAND_HANDLER(handle_power_command)
        return ERROR_OK;
 }
 
+#if !BUILD_ECOSBOARD
+static char *tcp_server = "notspecified";
+static int jim_zy1000_server(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+       if (argc != 2)
+               return JIM_ERR;
+
+       tcp_server = strdup(Jim_GetString(argv[1], NULL));
+
+       return JIM_OK;
+}
+#endif
 
 #if BUILD_ECOSBOARD
 /* Give TELNET a way to find out what version this is */
@@ -415,25 +428,6 @@ zylinjtag_Jim_Command_powerstatus(Jim_Interp *interp,
 
 
 
-
-int zy1000_init(void)
-{
-#if BUILD_ECOSBOARD
-       LOG_USER("%s", ZYLIN_OPENOCD_VERSION);
-#endif
-
-       ZY1000_POKE(ZY1000_JTAG_BASE + 0x10, 0x30); // Turn on LED1 & LED2
-
-       setPower(true); // on by default
-
-
-        /* deassert resets. Important to avoid infinite loop waiting for SRST to deassert */
-       zy1000_reset(0, 0);
-       zy1000_speed(jtag_get_speed());
-
-       return ERROR_OK;
-}
-
 int zy1000_quit(void)
 {
 
@@ -710,12 +704,6 @@ int interface_jtag_add_clocks(int num_cycles)
        return zy1000_jtag_add_clocks(num_cycles, cmd_queue_cur_state, cmd_queue_cur_state);
 }
 
-int interface_jtag_add_sleep(uint32_t us)
-{
-       jtag_sleep(us);
-       return ERROR_OK;
-}
-
 int interface_add_tms_seq(unsigned num_bits, const uint8_t *seq, enum tap_state state)
 {
        /*wait for the fifo to be empty*/
@@ -967,6 +955,14 @@ static const struct command_registration zy1000_commands[] = {
                .help = "Print version info for zy1000.",
                .usage = "['openocd'|'zy1000'|'date'|'time'|'pcb'|'fpga']",
        },
+#else
+       {
+               .name = "zy1000_server",
+               .mode = COMMAND_ANY,
+               .jim_handler = jim_zy1000_server,
+               .help = "Tcpip address for ZY1000 server.",
+               .usage = "address",
+       },
 #endif
        {
                .name = "powerstatus",
@@ -987,6 +983,320 @@ static const struct command_registration zy1000_commands[] = {
 };
 
 
+static int tcp_ip = -1;
+
+/* Write large packets if we can */
+static size_t out_pos;
+static uint8_t out_buffer[16384];
+static size_t in_pos;
+static size_t in_write;
+static uint8_t in_buffer[16384];
+
+static bool flush_writes(void)
+{
+       bool ok = (write(tcp_ip, out_buffer, out_pos) == (int)out_pos);
+       out_pos = 0;
+       return ok;
+}
+
+static bool writeLong(uint32_t l)
+{
+       int i;
+       for (i = 0; i < 4; i++)
+       {
+               uint8_t c = (l >> (i*8))&0xff;
+               out_buffer[out_pos++] = c;
+               if (out_pos >= sizeof(out_buffer))
+               {
+                       if (!flush_writes())
+                       {
+                               return false;
+                       }
+               }
+       }
+       return true;
+}
+
+static bool readLong(uint32_t *out_data)
+{
+       if (out_pos > 0)
+       {
+               if (!flush_writes())
+               {
+                       return false;
+               }
+       }
+
+       uint32_t data = 0;
+       int i;
+       for (i = 0; i < 4; i++)
+       {
+               uint8_t c;
+               if (in_pos == in_write)
+               {
+                       /* read more */
+                       int t;
+                       t = read(tcp_ip, in_buffer, sizeof(in_buffer));
+                       if (t < 1)
+                       {
+                               return false;
+                       }
+                       in_write = (size_t) t;
+                       in_pos = 0;
+               }
+               c = in_buffer[in_pos++];
+
+               data |= (c << (i*8));
+       }
+       *out_data = data;
+       return true;
+}
+
+enum ZY1000_CMD
+{
+       ZY1000_CMD_POKE = 0x0,
+       ZY1000_CMD_PEEK = 0x8,
+       ZY1000_CMD_SLEEP = 0x1,
+};
+
+
+#if !BUILD_ECOSBOARD
+
+#include <sys/socket.h> /* for socket(), connect(), send(), and recv() */
+#include <arpa/inet.h>  /* for sockaddr_in and inet_addr() */
+
+/* We initialize this late since we need to know the server address
+ * first.
+ */
+static void tcpip_open(void)
+{
+       if (tcp_ip >= 0)
+               return;
+
+       struct sockaddr_in echoServAddr; /* Echo server address */
+
+       /* Create a reliable, stream socket using TCP */
+       if ((tcp_ip = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
+       {
+               fprintf(stderr, "Failed to connect to zy1000 server\n");
+               exit(-1);
+       }
+
+       /* Construct the server address structure */
+       memset(&echoServAddr, 0, sizeof(echoServAddr)); /* Zero out structure */
+       echoServAddr.sin_family = AF_INET; /* Internet address family */
+       echoServAddr.sin_addr.s_addr = inet_addr(tcp_server); /* Server IP address */
+       echoServAddr.sin_port = htons(7777); /* Server port */
+
+       /* Establish the connection to the echo server */
+       if (connect(tcp_ip, (struct sockaddr *) &echoServAddr, sizeof(echoServAddr)) < 0)
+       {
+               fprintf(stderr, "Failed to connect to zy1000 server\n");
+               exit(-1);
+       }
+
+       int flag = 1;
+       setsockopt(tcp_ip,      /* socket affected */
+                       IPPROTO_TCP,            /* set option at TCP level */
+                       TCP_NODELAY,            /* name of option */
+                       (char *)&flag,          /* the cast is historical cruft */
+                       sizeof(int));           /* length of option value */
+
+}
+
+
+/* send a poke */
+void zy1000_tcpout(uint32_t address, uint32_t data)
+{
+       tcpip_open();
+       if (!writeLong((ZY1000_CMD_POKE << 24) | address)||
+                       !writeLong(data))
+       {
+               fprintf(stderr, "Could not write to zy1000 server\n");
+               exit(-1);
+       }
+}
+
+uint32_t zy1000_tcpin(uint32_t address)
+{
+       tcpip_open();
+       uint32_t data;
+       if (!writeLong((ZY1000_CMD_PEEK << 24) | address)||
+                       !readLong(&data))
+       {
+               fprintf(stderr, "Could not read from zy1000 server\n");
+               exit(-1);
+       }
+       return data;
+}
+
+int interface_jtag_add_sleep(uint32_t us)
+{
+       tcpip_open();
+       if (!writeLong((ZY1000_CMD_SLEEP << 24))||
+                       !writeLong(us))
+       {
+               fprintf(stderr, "Could not read from zy1000 server\n");
+               exit(-1);
+       }
+       return ERROR_OK;
+}
+
+
+#endif
+
+#if BUILD_ECOSBOARD
+static char tcpip_stack[2048];
+
+static cyg_thread tcpip_thread_object;
+static cyg_handle_t tcpip_thread_handle;
+
+/* Infinite loop peeking & poking */
+static void tcpipserver(void)
+{
+       for (;;)
+       {
+               uint32_t address;
+               if (!readLong(&address))
+                       return;
+               enum ZY1000_CMD c = (address >> 24) & 0xff;
+               address &= 0xffffff;
+               switch (c)
+               {
+                       case ZY1000_CMD_POKE:
+                       {
+                               uint32_t data;
+                               if (!readLong(&data))
+                                       return;
+                               address &= ~0x80000000;
+                               ZY1000_POKE(address + ZY1000_JTAG_BASE, data);
+                               break;
+                       }
+                       case ZY1000_CMD_PEEK:
+                       {
+                               uint32_t data;
+                               ZY1000_PEEK(address + ZY1000_JTAG_BASE, data);
+                               if (!writeLong(data))
+                                       return;
+                               break;
+                       }
+                       case ZY1000_CMD_SLEEP:
+                       {
+                               uint32_t data;
+                               if (!readLong(&data))
+                                       return;
+                               jtag_sleep(data);
+                               break;
+                       }
+                       default:
+                               return;
+               }
+       }
+}
+
+
+static void tcpip_server(cyg_addrword_t data)
+{
+       int so_reuseaddr_option = 1;
+
+       int fd;
+       if ((fd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
+       {
+               LOG_ERROR("error creating socket: %s", strerror(errno));
+               exit(-1);
+       }
+
+       setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void*) &so_reuseaddr_option,
+                       sizeof(int));
+
+       struct sockaddr_in sin;
+       unsigned int address_size;
+       address_size = sizeof(sin);
+       memset(&sin, 0, sizeof(sin));
+       sin.sin_family = AF_INET;
+       sin.sin_addr.s_addr = INADDR_ANY;
+       sin.sin_port = htons(7777);
+
+       if (bind(fd, (struct sockaddr *) &sin, sizeof(sin)) == -1)
+       {
+               LOG_ERROR("couldn't bind to socket: %s", strerror(errno));
+               exit(-1);
+       }
+
+       if (listen(fd, 1) == -1)
+       {
+               LOG_ERROR("couldn't listen on socket: %s", strerror(errno));
+               exit(-1);
+       }
+
+
+       for (;;)
+       {
+               tcp_ip = accept(fd, (struct sockaddr *) &sin, &address_size);
+               if (tcp_ip < 0)
+               {
+                       continue;
+               }
+
+               int flag = 1;
+               setsockopt(tcp_ip,      /* socket affected */
+                               IPPROTO_TCP,            /* set option at TCP level */
+                               TCP_NODELAY,            /* name of option */
+                               (char *)&flag,          /* the cast is historical cruft */
+                               sizeof(int));           /* length of option value */
+
+               bool save_poll = jtag_poll_get_enabled();
+
+               /* polling will screw up the "connection" */
+               jtag_poll_set_enabled(false);
+
+               tcpipserver();
+
+               jtag_poll_set_enabled(save_poll);
+
+               close(tcp_ip);
+
+       }
+       close(fd);
+
+}
+
+int interface_jtag_add_sleep(uint32_t us)
+{
+       jtag_sleep(us);
+       return ERROR_OK;
+}
+
+#endif
+
+
+int zy1000_init(void)
+{
+#if BUILD_ECOSBOARD
+       LOG_USER("%s", ZYLIN_OPENOCD_VERSION);
+#endif
+
+       ZY1000_POKE(ZY1000_JTAG_BASE + 0x10, 0x30); // Turn on LED1 & LED2
+
+       setPower(true); // on by default
+
+
+        /* deassert resets. Important to avoid infinite loop waiting for SRST to deassert */
+       zy1000_reset(0, 0);
+       zy1000_speed(jtag_get_speed());
+
+
+#if BUILD_ECOSBOARD
+       cyg_thread_create(1, tcpip_server, (cyg_addrword_t) 0, "tcip/ip server",
+                       (void *) tcpip_stack, sizeof(tcpip_stack),
+                       &tcpip_thread_handle, &tcpip_thread_object);
+       cyg_thread_resume(tcpip_thread_handle);
+#endif
+
+       return ERROR_OK;
+}
+
+
 
 struct jtag_interface zy1000_interface =
 {