zy1000: add code to check that SRST asserts
[openocd.git] / src / jtag / zy1000 / zy1000.c
index 28c65b6e56658e9312e1ca3ca642b71a0dcdbc05..f2db47b3ad683bde43322d2570810bfc598163a2 100644 (file)
@@ -45,6 +45,8 @@
 #include "config.h"
 #endif
 
+#include <pthread.h>
+
 #include <target/embeddedice.h>
 #include <jtag/minidriver.h>
 #include <jtag/interface.h>
@@ -62,6 +64,9 @@
 #ifdef CYGPKG_HAL_NIOS2
 #include <cyg/hal/io.h>
 #include <cyg/firmwareutil/firmwareutil.h>
+#define ZYLIN_KHZ 60000
+#else
+#define ZYLIN_KHZ 64000
 #endif
 
 #define ZYLIN_VERSION GIT_ZY1000_VERSION
@@ -70,6 +75,9 @@
 #define ZYLIN_OPENOCD GIT_OPENOCD_VERSION
 #define ZYLIN_OPENOCD_VERSION "ZY1000 " ZYLIN_VERSION " " ZYLIN_DATE
 
+#else
+/* Assume we're connecting to a revc w/60MHz clock. */
+#define ZYLIN_KHZ 60000
 #endif
 
 
@@ -84,7 +92,33 @@ static int zy1000_khz(int khz, int *jtag_speed)
        }
        else
        {
-               *jtag_speed = 64000/khz;
+               int speed;
+               /* Round speed up to nearest divisor.
+                *
+                * E.g. 16000kHz
+                * (64000 + 15999) / 16000 = 4
+                * (4 + 1) / 2 = 2
+                * 2 * 2 = 4
+                *
+                * 64000 / 4 = 16000
+                *
+                * E.g. 15999
+                * (64000 + 15998) / 15999 = 5
+                * (5 + 1) / 2 = 3
+                * 3 * 2 = 6
+                *
+                * 64000 / 6 = 10666
+                *
+                */
+               speed = (ZYLIN_KHZ + (khz -1)) / khz;
+               speed = (speed + 1 ) / 2;
+               speed *= 2;
+               if (speed > 8190)
+               {
+                       /* maximum dividend */
+                       speed = 8190;
+               }
+               *jtag_speed = speed;
        }
        return ERROR_OK;
 }
@@ -97,7 +131,7 @@ static int zy1000_speed_div(int speed, int *khz)
        }
        else
        {
-               *khz = 64000/speed;
+               *khz = ZYLIN_KHZ / speed;
        }
 
        return ERROR_OK;
@@ -138,6 +172,45 @@ static int zy1000_power_dropout(int *dropout)
        return ERROR_OK;
 }
 
+/* Wait for SRST to assert or deassert */
+static void waitSRST(bool asserted)
+{
+       bool first = true;
+       long long start = 0;
+       long total = 0;
+       const char *mode = asserted ? "assert" : "deassert";
+
+       for (;;)
+       {
+               bool srstAsserted = readSRST();
+               if ( (asserted && srstAsserted) || (!asserted && !srstAsserted) )
+               {
+                       if (total > 1)
+                       {
+                               LOG_USER("SRST took %dms to %s", (int)total, mode);
+                       }
+                       break;
+               }
+
+               if (first)
+               {
+                       first = false;
+                       start = timeval_ms();
+               }
+
+               total = timeval_ms() - start;
+
+               keep_alive();
+
+               if (total > 5000)
+               {
+                       LOG_ERROR("SRST took too long to %s: %dms", mode, (int)total);
+                       break;
+               }
+       }
+}
+
+
 void zy1000_reset(int trst, int srst)
 {
        LOG_DEBUG("zy1000 trst=%d, srst=%d", trst, srst);
@@ -158,6 +231,8 @@ void zy1000_reset(int trst, int srst)
                 * idle in TAP_IDLE, reset halt on str912 will fail.
                 */
                ZY1000_POKE(ZY1000_JTAG_BASE + 0x10, 0x00000001);
+
+               waitSRST(true);
        }
 
        if (!trst)
@@ -184,40 +259,7 @@ void zy1000_reset(int trst, int srst)
        if ((!srst && ((jtag_get_reset_config() & RESET_TRST_PULLS_SRST) == 0))||
                (!srst && !trst && (jtag_get_reset_config() & RESET_TRST_PULLS_SRST)))
        {
-               bool first = true;
-               long long start = 0;
-               long total = 0;
-               for (;;)
-               {       
-                       // We don't want to sense our own reset, so we clear here.
-                       // There is of course a timing hole where we could loose
-                       // a "real" reset.
-                       if (!readSRST())
-                       {
-                               if (total > 1)
-                               {
-                                 LOG_USER("SRST took %dms to deassert", (int)total);
-                               }
-                               break;
-                       }
-
-                       if (first)
-                       {
-                           first = false;
-                           start = timeval_ms();
-                       }
-
-                       total = timeval_ms() - start;
-
-                       keep_alive();
-
-                       if (total > 5000)
-                       {
-                               LOG_ERROR("SRST took too long to deassert: %dms", (int)total);
-                           break;
-                       }
-               }
-
+               waitSRST(false);
        }
 }
 
@@ -239,13 +281,17 @@ int zy1000_speed(int speed)
        {
                if (speed > 8190 || speed < 2)
                {
-                       LOG_USER("valid ZY1000 jtag_speed=[8190,2]. Divisor is 64MHz / even values between 8190-2, i.e. min 7814Hz, max 32MHz");
+                       LOG_USER("valid ZY1000 jtag_speed=[8190,2]. With divisor is %dkHz / even values between 8190-2, i.e. min %dHz, max %dMHz",
+                                       ZYLIN_KHZ, (ZYLIN_KHZ * 1000) / 8190, ZYLIN_KHZ / (2 * 1000));
                        return ERROR_INVALID_ARGUMENTS;
                }
 
-               LOG_USER("jtag_speed %d => JTAG clk=%f", speed, 64.0/(float)speed);
+               int khz;
+               speed &= ~1;
+               zy1000_speed_div(speed, &khz);
+               LOG_USER("jtag_speed %d => JTAG clk=%d kHz", speed, khz);
                ZY1000_POKE(ZY1000_JTAG_BASE + 0x14, 0x100);
-               ZY1000_POKE(ZY1000_JTAG_BASE + 0x1c, speed&~1);
+               ZY1000_POKE(ZY1000_JTAG_BASE + 0x1c, speed);
        }
        return ERROR_OK;
 }
@@ -285,7 +331,7 @@ COMMAND_HANDLER(handle_power_command)
        return ERROR_OK;
 }
 
-#if !BUILD_ECOSBOARD
+#if !BUILD_ZY1000_MASTER
 static char *tcp_server = "notspecified";
 static int jim_zy1000_server(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
 {
@@ -402,24 +448,10 @@ struct cyg_upgrade_info firmware_info =
                report_info,
 };
 
+// File written to /ram/firmware.phi before arriving at this fn
 static int jim_zy1000_writefirmware(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
 {
-       if (argc != 2)
-               return JIM_ERR;
-
-       int length;
-       const char *str = Jim_GetString(argv[1], &length);
-
-       /* */
-       int tmpFile;
-       if ((tmpFile = open(firmware_info.file, O_RDWR | O_CREAT | O_TRUNC)) <= 0)
-       {
-               return JIM_ERR;
-       }
-       bool success;
-       success = write(tmpFile, str, length) == length;
-       close(tmpFile);
-       if (!success)
+       if (argc != 1)
                return JIM_ERR;
 
        if (!cyg_firmware_upgrade(NULL, firmware_info))
@@ -966,6 +998,7 @@ static const struct command_registration zy1000_commands[] = {
                        "With no arguments, prints status.",
                .usage = "('on'|'off)",
        },
+#if BUILD_ZY1000_MASTER
 #if BUILD_ECOSBOARD
        {
                .name = "zy1000_version",
@@ -974,6 +1007,7 @@ static const struct command_registration zy1000_commands[] = {
                .help = "Print version info for zy1000.",
                .usage = "['openocd'|'zy1000'|'date'|'time'|'pcb'|'fpga']",
        },
+#endif
 #else
        {
                .name = "zy1000_server",
@@ -1038,14 +1072,6 @@ static bool writeLong(uint32_t l)
 
 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++)
@@ -1053,6 +1079,17 @@ static bool readLong(uint32_t *out_data)
                uint8_t c;
                if (in_pos == in_write)
                {
+                       /* If we have some data that we can send, send them before
+                        * we wait for more data
+                        */
+                       if (out_pos > 0)
+                       {
+                               if (!flush_writes())
+                               {
+                                       return false;
+                               }
+                       }
+
                        /* read more */
                        int t;
                        t = read(tcp_ip, in_buffer, sizeof(in_buffer));
@@ -1080,7 +1117,7 @@ enum ZY1000_CMD
 };
 
 
-#if !BUILD_ECOSBOARD
+#if !BUILD_ZY1000_MASTER
 
 #include <sys/socket.h> /* for socket(), connect(), send(), and recv() */
 #include <arpa/inet.h>  /* for sockaddr_in and inet_addr() */
@@ -1324,14 +1361,15 @@ static void writeShiftValue(uint8_t *data, int bits)
 
 #endif
 
-#if BUILD_ECOSBOARD
-static char tcpip_stack[2048];
-static cyg_thread tcpip_thread_object;
-static cyg_handle_t tcpip_thread_handle;
+#if BUILD_ZY1000_MASTER
+
+pthread_t thread;
 
+#if BUILD_ECOSBOARD
 static char watchdog_stack[2048];
 static cyg_thread watchdog_thread_object;
 static cyg_handle_t watchdog_thread_handle;
+#endif
 
 /* Infinite loop peeking & poking */
 static void tcpipserver(void)
@@ -1367,7 +1405,8 @@ static void tcpipserver(void)
                                uint32_t data;
                                if (!readLong(&data))
                                        return;
-                               jtag_sleep(data);
+                               /* Wait for some us */
+                               usleep(data);
                                break;
                        }
                        case ZY1000_CMD_WAITIDLE:
@@ -1382,7 +1421,7 @@ static void tcpipserver(void)
 }
 
 
-static void tcpip_server(cyg_addrword_t data)
+static void *tcpip_server(void *data)
 {
        int so_reuseaddr_option = 1;
 
@@ -1444,8 +1483,10 @@ static void tcpip_server(cyg_addrword_t data)
                close(tcp_ip);
 
        }
+       /* Never reached actually */
        close(fd);
 
+       return NULL;
 }
 
 #ifdef WATCHDOG_BASE
@@ -1530,20 +1571,48 @@ static void watchdog_server(cyg_addrword_t data)
 }
 #endif
 
+#endif
+
+#if BUILD_ZY1000_MASTER
 int interface_jtag_add_sleep(uint32_t us)
 {
        jtag_sleep(us);
        return ERROR_OK;
 }
-
 #endif
 
+#if BUILD_ZY1000_MASTER && !BUILD_ECOSBOARD
+volatile void *zy1000_jtag_master;
+#include <sys/mman.h>
+#endif
 
 int zy1000_init(void)
 {
 #if BUILD_ECOSBOARD
        LOG_USER("%s", ZYLIN_OPENOCD_VERSION);
+#elif BUILD_ZY1000_MASTER
+       int fd;
+       if((fd = open("/dev/mem", O_RDWR | O_SYNC)) == -1)
+       {
+               LOG_ERROR("No access to /dev/mem");
+               return ERROR_FAIL;
+       }
+#ifndef REGISTERS_BASE
+#define REGISTERS_BASE 0x9002000
+#define REGISTERS_SPAN 128
 #endif
+    
+    zy1000_jtag_master = mmap(0, REGISTERS_SPAN, PROT_READ | PROT_WRITE, MAP_SHARED, fd, REGISTERS_BASE);
+    
+    if(zy1000_jtag_master == (void *) -1) 
+    {
+           close(fd);
+               LOG_ERROR("No access to /dev/mem");
+               return ERROR_FAIL;
+    } 
+#endif
+
+
 
        ZY1000_POKE(ZY1000_JTAG_BASE + 0x10, 0x30); // Turn on LED1 & LED2
 
@@ -1552,20 +1621,23 @@ int zy1000_init(void)
 
         /* deassert resets. Important to avoid infinite loop waiting for SRST to deassert */
        zy1000_reset(0, 0);
-       zy1000_speed(jtag_get_speed());
+       int jtag_speed_var;
+       int retval = jtag_get_speed(&jtag_speed_var);
+       if (retval != ERROR_OK)
+               return retval;
+       zy1000_speed(jtag_speed_var);
 
+#if BUILD_ZY1000_MASTER
+       pthread_create(&thread, NULL, tcpip_server, NULL);
 
 #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);
 #ifdef WATCHDOG_BASE
        cyg_thread_create(1, watchdog_server, (cyg_addrword_t) 0, "watchdog tcip/ip server",
                        (void *) watchdog_stack, sizeof(watchdog_stack),
                        &watchdog_thread_handle, &watchdog_thread_object);
        cyg_thread_resume(watchdog_thread_handle);
 #endif
+#endif
 #endif
 
        return ERROR_OK;

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)