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 =
 {

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)