diff options
author | Antonio Borneo <borneo.antonio@gmail.com> | 2020-11-01 12:30:27 +0100 |
---|---|---|
committer | Antonio Borneo <borneo.antonio@gmail.com> | 2021-03-19 21:55:50 +0000 |
commit | b0fe92dba7c01adc25e5fe3552253a4a8c69ae1a (patch) | |
tree | 713df4f13e91a8c1517d5510c39176eb15cf5dbc | |
parent | 58b95eac48cf0ad3316a911ddc79ce8973b88fd1 (diff) | |
download | riscv-openocd-b0fe92dba7c01adc25e5fe3552253a4a8c69ae1a.zip riscv-openocd-b0fe92dba7c01adc25e5fe3552253a4a8c69ae1a.tar.gz riscv-openocd-b0fe92dba7c01adc25e5fe3552253a4a8c69ae1a.tar.bz2 |
zy1000: drop the code, deprecated in v0.10.0
The code for zy1000 has been marked as deprecated in release
v0.10.0, 4 years ago.
Time to drop it!
Change-Id: I08fca2a2bf8f616f031e15fd37dac3197a40ba50
Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
Reviewed-on: http://openocd.zylin.com/6090
Tested-by: jenkins
-rw-r--r-- | configure.ac | 43 | ||||
-rw-r--r-- | doc/manual/jtag.txt | 1 | ||||
-rw-r--r-- | doc/openocd.texi | 42 | ||||
-rw-r--r-- | src/jtag/Makefile.am | 4 | ||||
-rw-r--r-- | src/jtag/interfaces.c | 8 | ||||
-rw-r--r-- | src/jtag/jtag.h | 11 | ||||
-rw-r--r-- | src/jtag/startup.tcl | 4 | ||||
-rw-r--r-- | src/jtag/zy1000/jtag_minidriver.h | 182 | ||||
-rw-r--r-- | src/jtag/zy1000/zy1000.c | 1259 | ||||
-rw-r--r-- | tcl/board/zy1000.cfg | 117 |
10 files changed, 5 insertions, 1666 deletions
diff --git a/configure.ac b/configure.ac index 215d7a7..71cfe21 100644 --- a/configure.ac +++ b/configure.ac @@ -283,14 +283,6 @@ AC_ARG_ENABLE([amtjtagaccel], AS_HELP_STRING([--enable-amtjtagaccel], [Enable building the Amontec JTAG-Accelerator driver]), [build_amtjtagaccel=$enableval], [build_amtjtagaccel=no]) -AC_ARG_ENABLE([zy1000_master], - AS_HELP_STRING([--enable-zy1000-master], [Use ZY1000 JTAG master registers]), - [build_zy1000_master=$enableval], [build_zy1000_master=no]) - -AC_ARG_ENABLE([zy1000], - AS_HELP_STRING([--enable-zy1000], [Enable ZY1000 interface]), - [build_zy1000=$enableval], [build_zy1000=no]) - AS_CASE(["${host_cpu}"], [arm*|aarch64], [ AC_ARG_ENABLE([bcm2835gpio], @@ -373,16 +365,6 @@ AC_ARG_ENABLE([internal-libjaylink], [use_internal_libjaylink=$enableval], [use_internal_libjaylink=yes]) build_minidriver=no -AC_MSG_CHECKING([whether to enable ZY1000 minidriver]) -AS_IF([test "x$build_zy1000" = "xyes"], [ - AS_IF([test "x$build_minidriver" = "xyes"], [ - AC_MSG_ERROR([Multiple minidriver options have been enabled.]) - ]) - AC_DEFINE([HAVE_JTAG_MINIDRIVER_H], [1], - [Define to 1 if you have the <jtag_minidriver.h> header file.]) - build_minidriver=yes -]) -AC_MSG_RESULT([$build_zy1000]) AC_ARG_ENABLE([remote-bitbang], AS_HELP_STRING([--enable-remote-bitbang], [Enable building support for the Remote Bitbang jtag driver]), @@ -521,18 +503,6 @@ AS_IF([test "x$build_ep93xx" = "xyes"], [ AC_DEFINE([BUILD_EP93XX], [0], [0 if you don't want ep93xx.]) ]) -AS_IF([test "x$build_zy1000" = "xyes"], [ - AC_DEFINE([BUILD_ZY1000], [1], [1 if you want ZY1000.]) -], [ - AC_DEFINE([BUILD_ZY1000], [0], [0 if you don't want ZY1000.]) -]) - -AS_IF([test "x$build_zy1000_master" = "xyes"], [ - AC_DEFINE([BUILD_ZY1000_MASTER], [1], [1 if you want ZY1000 JTAG master registers.]) -], [ - AC_DEFINE([BUILD_ZY1000_MASTER], [0], [0 if you don't want ZY1000 JTAG master registers.]) -]) - AS_IF([test "x$build_at91rm9200" = "xyes"], [ build_bitbang=yes AC_DEFINE([BUILD_AT91RM9200], [1], [1 if you want at91rm9200.]) @@ -687,9 +657,6 @@ PKG_CHECK_MODULES([LIBJAYLINK], [libjaylink >= 0.2], m4_define([PROCESS_ADAPTERS], [ m4_foreach([adapter], [$1], [ - AS_IF([test "x$build_zy1000" = "xyes"], [ - ADAPTER_VAR([adapter])=no - ]) AS_IF([test $2], [ AS_IF([test "x$ADAPTER_VAR([adapter])" != "xno"], [ AC_DEFINE([BUILD_]ADAPTER_SYM([adapter]), [1], [1 if you want the ]ADAPTER_DESC([adapter]).) @@ -751,8 +718,6 @@ AM_CONDITIONAL([PARPORT], [test "x$build_parport" = "xyes"]) AM_CONDITIONAL([DUMMY], [test "x$build_dummy" = "xyes"]) AM_CONDITIONAL([GIVEIO], [test "x$parport_use_giveio" = "xyes"]) AM_CONDITIONAL([EP93XX], [test "x$build_ep93xx" = "xyes"]) -AM_CONDITIONAL([ZY1000], [test "x$build_zy1000" = "xyes"]) -AM_CONDITIONAL([ZY1000_MASTER], [test "x$build_zy1000_master" = "xyes"]) AM_CONDITIONAL([AT91RM9200], [test "x$build_at91rm9200" = "xyes"]) AM_CONDITIONAL([BCM2835GPIO], [test "x$build_bcm2835gpio" = "xyes"]) AM_CONDITIONAL([IMX_GPIO], [test "x$build_imx_gpio" = "xyes"]) @@ -867,11 +832,3 @@ m4_foreach([adapter], [USB1_ADAPTERS, USB0_ADAPTERS, ]) ]) echo - -AS_IF([test "x$build_zy1000" = "xyes" -o "x$build_zy1000_master" = "xyes"], [ - echo 'WARNING! Deprecated configure option (--enable-zy1000, --enable-zy1000-master)' - echo 'Support for the ZY1000 platform is deprecated and will be removed in the next' - echo 'release. If you regularly use this platform, please report to the OpenOCD' - echo 'Mailing List.' - echo -]) diff --git a/doc/manual/jtag.txt b/doc/manual/jtag.txt index 8f0804c..2653fc7 100644 --- a/doc/manual/jtag.txt +++ b/doc/manual/jtag.txt @@ -36,7 +36,6 @@ asynchronous transactions. - declared in @c src/jtag/minidriver.h - used @a only by the core and minidriver implementations: - @c jtag_driver.c (in-tree OpenOCD drivers) - - @c zy1000/build/include/jtag_minidriver.h (ZY1000 minidriver) - future implementations (on other embedded hosts) - interface device drivers do @b not need this API. diff --git a/doc/openocd.texi b/doc/openocd.texi index f52cfa7..b3fe854 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -298,7 +298,6 @@ The OpenOCD Bug Tracker is hosted on SourceForge: @cindex dongles @cindex FTDI @cindex wiggler -@cindex zy1000 @cindex printer port @cindex USB Adapter @cindex RTCK @@ -307,12 +306,7 @@ Defined: @b{dongle}: A small device that plugs into a computer and serves as an adapter .... [snip] In the OpenOCD case, this generally refers to @b{a small adapter} that -attaches to your computer via USB or the parallel port. One -exception is the Ultimate Solutions ZY1000, packaged as a small box you -attach via an ethernet cable. The ZY1000 has the advantage that it does not -require any drivers to be installed on the developer PC. It also has -a built in web interface. It supports RTCK/RCLK or adaptive clocking -and has a built-in relay to power cycle targets remotely. +attaches to your computer via USB or the parallel port. @section Choosing a Dongle @@ -334,26 +328,6 @@ Ethernet port needed? RTCK support (also known as ``adaptive clocking'')? @end enumerate -@section Stand-alone JTAG Probe - -The ZY1000 from Ultimate Solutions is technically not a dongle but a -stand-alone JTAG probe that, unlike most dongles, doesn't require any drivers -running on the developer's host computer. -Once installed on a network using DHCP or a static IP assignment, users can -access the ZY1000 probe locally or remotely from any host with access to the -IP address assigned to the probe. -The ZY1000 provides an intuitive web interface with direct access to the -OpenOCD debugger. -Users may also run a GDBSERVER directly on the ZY1000 to take full advantage -of GCC & GDB to debug any distribution of embedded Linux or NetBSD running on -the target. -The ZY1000 supports RTCK & RCLK or adaptive clocking and has a built-in relay -to power cycle the target remotely. - -For more information, visit: - -@b{ZY1000} See: @url{http://www.ultsol.com/index.php/component/content/article/8/210-zylin-zy1000-main} - @section USB FT2232 Based There are many USB JTAG dongles on the market, many of them based @@ -3222,20 +3196,6 @@ The string will be of the format "DDDD:BB:SS.F" such as "0000:65:00.1". @end deffn @end deffn -@deffn {Interface Driver} {ZY1000} -This is the Zylin ZY1000 JTAG debugger. -@end deffn - -@quotation Note -This defines some driver-specific commands, -which are not currently documented here. -@end quotation - -@deffn Command power [@option{on}|@option{off}] -Turn power switch to target on/off. -No arguments: print status. -@end deffn - @deffn {Interface Driver} {bcm2835gpio} This SoC is present in Raspberry Pi which is a cheap single-board computer exposing some GPIOs on its expansion header. diff --git a/src/jtag/Makefile.am b/src/jtag/Makefile.am index b82914b..8bc87a4 100644 --- a/src/jtag/Makefile.am +++ b/src/jtag/Makefile.am @@ -8,10 +8,6 @@ CLEANFILES += %D%/minidriver_imp.h if MINIDRIVER -if ZY1000 -JTAG_SRCS += %D%/zy1000/zy1000.c -JTAG_MINIDRIVER_DIR = %D%/zy1000 -endif if MINIDRIVER_DUMMY JTAG_SRCS += %D%/minidummy/minidummy.c JTAG_MINIDRIVER_DIR = %D%/minidummy diff --git a/src/jtag/interfaces.c b/src/jtag/interfaces.c index 061a78f..d229d8c 100644 --- a/src/jtag/interfaces.c +++ b/src/jtag/interfaces.c @@ -42,9 +42,7 @@ * that contain an adapter_driver structure that can added to this list. */ -#if BUILD_ZY1000 == 1 -extern struct adapter_driver zy1000_adapter_driver; -#elif defined(BUILD_MINIDRIVER_DUMMY) +#if defined(BUILD_MINIDRIVER_DUMMY) extern struct adapter_driver minidummy_adapter_driver; #else /* standard drivers */ #if BUILD_PARPORT == 1 @@ -162,9 +160,7 @@ extern struct adapter_driver rshim_dap_adapter_driver; * or some number of standard driver interfaces, never both. */ struct adapter_driver *adapter_drivers[] = { -#if BUILD_ZY1000 == 1 - &zy1000_adapter_driver, -#elif defined(BUILD_MINIDRIVER_DUMMY) +#if defined(BUILD_MINIDRIVER_DUMMY) &minidummy_adapter_driver, #else /* standard drivers */ #if BUILD_PARPORT == 1 diff --git a/src/jtag/jtag.h b/src/jtag/jtag.h index 2fa5802..044d7c0 100644 --- a/src/jtag/jtag.h +++ b/src/jtag/jtag.h @@ -46,15 +46,6 @@ typedef enum tap_state { TAP_INVALID = -1, -#if BUILD_ZY1000 - /* These are the old numbers. Leave as-is for now... */ - TAP_RESET = 0, TAP_IDLE = 8, - TAP_DRSELECT = 1, TAP_DRCAPTURE = 2, TAP_DRSHIFT = 3, TAP_DREXIT1 = 4, - TAP_DRPAUSE = 5, TAP_DREXIT2 = 6, TAP_DRUPDATE = 7, - TAP_IRSELECT = 9, TAP_IRCAPTURE = 10, TAP_IRSHIFT = 11, TAP_IREXIT1 = 12, - TAP_IRPAUSE = 13, TAP_IREXIT2 = 14, TAP_IRUPDATE = 15, - -#else /* Proper ARM recommended numbers */ TAP_DREXIT2 = 0x0, TAP_DREXIT1 = 0x1, @@ -72,8 +63,6 @@ typedef enum tap_state { TAP_IRUPDATE = 0xd, TAP_IRCAPTURE = 0xe, TAP_RESET = 0x0f, - -#endif } tap_state_t; /** diff --git a/src/jtag/startup.tcl b/src/jtag/startup.tcl index e5c3b0f..f1e69e5 100644 --- a/src/jtag/startup.tcl +++ b/src/jtag/startup.tcl @@ -29,7 +29,7 @@ proc init_reset { mode } { ######### # TODO: power_restore and power_dropout are currently neither -# documented nor supported except on ZY1000. +# documented nor supported. proc power_restore {} { echo "Sensed power restore, running reset init and halting GDB." @@ -55,7 +55,7 @@ proc power_dropout {} { ######### # TODO: srst_deasserted and srst_asserted are currently neither -# documented nor supported except on ZY1000. +# documented nor supported. proc srst_deasserted {} { echo "Sensed nSRST deasserted, running reset init and halting GDB." diff --git a/src/jtag/zy1000/jtag_minidriver.h b/src/jtag/zy1000/jtag_minidriver.h deleted file mode 100644 index 7d1ede5..0000000 --- a/src/jtag/zy1000/jtag_minidriver.h +++ /dev/null @@ -1,182 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007-2010 by Øyvind Harboe * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program. If not, see <http://www.gnu.org/licenses/>. * - ***************************************************************************/ - -/* used to test manual mode */ -#define TEST_MANUAL() 0 -#define VERBOSE(a) - -#if BUILD_ZY1000_MASTER - -#define ZY1000_PEEK(a, b) do {b = *((volatile uint32_t *)(a)); } while (0) -#define ZY1000_POKE(a, b) do {*((volatile uint32_t *)(a)) = b; } while (0) -extern volatile void *zy1000_jtag_master; -#define ZY1000_JTAG_BASE ((unsigned long)zy1000_jtag_master) - -#else - -/* redirect this to TCP/IP */ -#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 - -#if BUILD_ZY1000_MASTER -/* FIFO empty? */ -static inline void waitIdle(void) -{ - uint32_t empty; - do { - ZY1000_PEEK(ZY1000_JTAG_BASE + 0x10, empty); - } while ((empty & 0x100) == 0); -} - -static inline void zy1000_flush_readqueue(void) -{ - /* Not used w/hardware fifo */ -} -static inline void zy1000_flush_callbackqueue(void) -{ - /* Not used w/hardware fifo */ -} -#else -extern void waitIdle(void); -void zy1000_flush_readqueue(void); -void zy1000_flush_callbackqueue(void); -void zy1000_jtag_add_callback4(jtag_callback_t callback, - jtag_callback_data_t data0, - jtag_callback_data_t data1, - jtag_callback_data_t data2, - jtag_callback_data_t data3); -void zy1000_jtag_add_callback(jtag_callback1_t callback, jtag_callback_data_t data0); -#endif - -static inline void waitQueue(void) -{ -/* waitIdle(); */ -} - -static inline void sampleShiftRegister(void) -{ -#if 0 - uint32_t dummy; - waitIdle(); - ZY1000_PEEK(ZY1000_JTAG_BASE + 0xc, dummy); -#endif -} - -static inline void setCurrentState(enum tap_state state) -{ - uint32_t a; - a = state; - int repeat = 0; - if (state == TAP_RESET) { - /* The FPGA nor we know the current state of the CPU TAP */ - /* controller. This will move it to TAP for sure. */ - /* */ - /* 5 should be enough here, 7 is what OpenOCD uses */ - repeat = 7; - } - waitQueue(); - sampleShiftRegister(); - ZY1000_POKE(ZY1000_JTAG_BASE + 0x8, (repeat << 8) | (a << 4) | a); - -} - -/* - * Enter state and cause repeat transitions *out* of that state. So if the endState != state, then - * the transition from state to endState counts as a transition out of state. - */ -static inline void shiftValueInner(const enum tap_state state, - const enum tap_state endState, - int repeat, - uint32_t value) -{ - uint32_t a, b; - a = state; - b = endState; - waitQueue(); - sampleShiftRegister(); - ZY1000_POKE(ZY1000_JTAG_BASE + 0xc, value); -#if 1 -#if TEST_MANUAL() - if ((state == TAP_DRSHIFT) && (endState != TAP_DRSHIFT)) { - int i; - setCurrentState(state); - for (i = 0; i < repeat; i++) { - int tms; - tms = 0; - if ((i == repeat-1) && (state != endState)) - tms = 1; - /* shift out value */ - waitIdle(); - ZY1000_POKE(ZY1000_JTAG_BASE + 0x28, (((value >> i)&1) << 1) | tms); - } - waitIdle(); - ZY1000_POKE(ZY1000_JTAG_BASE + 0x28, 0); - waitIdle(); - /* ZY1000_POKE(ZY1000_JTAG_BASE + 0x20, TAP_DRSHIFT); // set this state and things - * break => expected */ - ZY1000_POKE(ZY1000_JTAG_BASE + 0x20, TAP_DRPAUSE); /* set this and things will - * work => expected. Not - * setting this is not - * sufficient to make things - * break. */ - setCurrentState(endState); - } else - ZY1000_POKE(ZY1000_JTAG_BASE + 0x8, (repeat << 8) | (a << 4) | b); - -#else - /* fast version */ - ZY1000_POKE(ZY1000_JTAG_BASE + 0x8, (repeat << 8) | (a << 4) | b); -#endif -#else - /* maximum debug version */ - if ((repeat > 0) && ((state == TAP_DRSHIFT) || (state == TAP_SI))) { - int i; - /* sample shift register for every bit. */ - for (i = 0; i < repeat-1; i++) { - sampleShiftRegister(); - ZY1000_POKE(ZY1000_JTAG_BASE + 0xc, value >> i); - ZY1000_POKE(ZY1000_JTAG_BASE + 0x8, (1 << 8) | (a << 4) | a); - } - sampleShiftRegister(); - ZY1000_POKE(ZY1000_JTAG_BASE + 0xc, value >> (repeat-1)); - ZY1000_POKE(ZY1000_JTAG_BASE + 0x8, (1 << 8) | (a << 4) | b); - } else { - sampleShiftRegister(); - ZY1000_POKE(ZY1000_JTAG_BASE + 0x8, (repeat << 8) | (a << 4) | b); - } - sampleShiftRegister(); -#endif -} - -#if BUILD_ZY1000_MASTER -#define interface_jtag_add_callback(callback, in) callback(in) -#define interface_jtag_add_callback4(callback, in, data1, data2, \ - data3) jtag_set_error(callback(in, data1, data2, data3)) -#else -#define interface_jtag_add_callback(callback, in) zy1000_jtag_add_callback(callback, in) -#define interface_jtag_add_callback4(callback, in, data1, data2, data3) zy1000_jtag_add_callback4( \ - callback, \ - in, \ - data1, \ - data2, \ - data3) -#endif diff --git a/src/jtag/zy1000/zy1000.c b/src/jtag/zy1000/zy1000.c deleted file mode 100644 index 669e6f4..0000000 --- a/src/jtag/zy1000/zy1000.c +++ /dev/null @@ -1,1259 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007-2010 by Øyvind Harboe * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program. If not, see <http://www.gnu.org/licenses/>. * - ***************************************************************************/ - -/* This file supports the zy1000 debugger: - * - * http://www.ultsol.com/index.php/component/content/article/8/33-zylin-zy1000-jtag-probe - * - * The zy1000 is a standalone debugger that has a web interface and - * requires no drivers on the developer host as all communication - * is via TCP/IP. The zy1000 gets it performance(~400-700kBytes/s - * DCC downloads @ 16MHz target) as it has an FPGA to hardware - * accelerate the JTAG commands, while offering *very* low latency - * between OpenOCD and the FPGA registers. - * - * The disadvantage of the zy1000 is that it has a feeble CPU compared to - * a PC(ca. 50-500 DMIPS depending on how one counts it), whereas a PC - * is on the order of 10000 DMIPS(i.e. at a factor of 20-200). - * - * The zy1000 revc hardware is using an Altera Nios CPU, whereas the - * revb is using ARM7 + Xilinx. - * - * See Zylin web pages or contact Zylin for more information. - * - * The reason this code is in OpenOCD rather than OpenOCD linked with the - * ZY1000 code is that OpenOCD is the long road towards getting - * libopenocd into place. libopenocd will support both low performance, - * low latency systems(embedded) and high performance high latency - * systems(PCs). - */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <pthread.h> - -#include <target/embeddedice.h> -#include <jtag/minidriver.h> -#include <jtag/interface.h> -#include <time.h> -#include <helper/time_support.h> - -#include <netinet/tcp.h> - -/* Assume we're connecting to a revc w/60MHz clock. */ -#define ZYLIN_KHZ 60000 - -/* The software needs to check if it's in RCLK mode or not */ -static bool zy1000_rclk; - -static int zy1000_khz(int khz, int *jtag_speed) -{ - if (khz == 0) - *jtag_speed = 0; - else { - 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; -} - -static int zy1000_speed_div(int speed, int *khz) -{ - if (speed == 0) - *khz = 0; - else - *khz = ZYLIN_KHZ / speed; - - return ERROR_OK; -} - -static bool readPowerDropout(void) -{ - uint32_t state; - /* sample and clear power dropout */ - ZY1000_POKE(ZY1000_JTAG_BASE + 0x10, 0x80); - ZY1000_PEEK(ZY1000_JTAG_BASE + 0x10, state); - bool powerDropout; - powerDropout = (state & 0x80) != 0; - return powerDropout; -} - - -static bool readSRST(void) -{ - uint32_t state; - /* sample and clear SRST sensing */ - ZY1000_POKE(ZY1000_JTAG_BASE + 0x10, 0x00000040); - ZY1000_PEEK(ZY1000_JTAG_BASE + 0x10, state); - bool srstAsserted; - srstAsserted = (state & 0x40) != 0; - return srstAsserted; -} - -static int zy1000_srst_asserted(int *srst_asserted) -{ - *srst_asserted = readSRST(); - return ERROR_OK; -} - -static int zy1000_power_dropout(int *dropout) -{ - *dropout = readPowerDropout(); - return ERROR_OK; -} - -/* Wait for SRST to assert or deassert */ -static void waitSRST(bool asserted) -{ - bool first = true; - int64_t start = 0; - int64_t 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: %" PRId64 "ms", mode, total); - break; - } - } -} - -void zy1000_reset(int trst, int srst) -{ - LOG_DEBUG("zy1000 trst=%d, srst=%d", trst, srst); - - /* flush the JTAG FIFO. Not flushing the queue before messing with - * reset has such interesting bugs as causing hard to reproduce - * RCLK bugs as RCLK will stop responding when TRST is asserted - */ - waitIdle(); - - if (!srst) - ZY1000_POKE(ZY1000_JTAG_BASE + 0x14, 0x00000001); - else { - /* Danger!!! if clk != 0 when in - * idle in TAP_IDLE, reset halt on str912 will fail. - */ - ZY1000_POKE(ZY1000_JTAG_BASE + 0x10, 0x00000001); - - waitSRST(true); - } - - if (!trst) - ZY1000_POKE(ZY1000_JTAG_BASE + 0x14, 0x00000002); - else { - /* assert reset */ - ZY1000_POKE(ZY1000_JTAG_BASE + 0x10, 0x00000002); - } - - if (trst || (srst && (jtag_get_reset_config() & RESET_SRST_PULLS_TRST))) { - /* we're now in the RESET state until trst is deasserted */ - ZY1000_POKE(ZY1000_JTAG_BASE + 0x20, TAP_RESET); - } else { - /* We'll get RCLK failure when we assert TRST, so clear any false positives here */ - ZY1000_POKE(ZY1000_JTAG_BASE + 0x14, 0x400); - } - - /* wait for srst to float back up */ - if ((!srst && ((jtag_get_reset_config() & RESET_TRST_PULLS_SRST) == 0)) || - (!srst && !trst && (jtag_get_reset_config() & RESET_TRST_PULLS_SRST))) - waitSRST(false); -} - -int zy1000_speed(int speed) -{ - /* flush JTAG master FIFO before setting speed */ - waitIdle(); - - zy1000_rclk = false; - - if (speed == 0) { - /*0 means RCLK*/ - ZY1000_POKE(ZY1000_JTAG_BASE + 0x10, 0x100); - zy1000_rclk = true; - LOG_DEBUG("jtag_speed using RCLK"); - } else { - if (speed > 8190 || speed < 2) { - 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_COMMAND_SYNTAX_ERROR; - } - - 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); - } - return ERROR_OK; -} - -static bool savePower; - -static void setPower(bool power) -{ - savePower = power; - if (power) - ZY1000_POKE(ZY1000_JTAG_BASE + 0x14, 0x8); - else - ZY1000_POKE(ZY1000_JTAG_BASE + 0x10, 0x8); -} - -COMMAND_HANDLER(handle_power_command) -{ - switch (CMD_ARGC) { - case 1: { - bool enable; - COMMAND_PARSE_ON_OFF(CMD_ARGV[0], enable); - setPower(enable); - } - /* fall through */ - case 0: - LOG_INFO("Target power %s", savePower ? "on" : "off"); - break; - default: - return ERROR_COMMAND_SYNTAX_ERROR; - } - - return ERROR_OK; -} - -#if !BUILD_ZY1000_MASTER -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 - -static int zylinjtag_Jim_Command_powerstatus(Jim_Interp *interp, - int argc, - Jim_Obj * const *argv) -{ - if (argc != 1) { - Jim_WrongNumArgs(interp, 1, argv, "powerstatus"); - return JIM_ERR; - } - - bool dropout = readPowerDropout(); - - Jim_SetResult(interp, Jim_NewIntObj(interp, dropout)); - - return JIM_OK; -} - -int zy1000_quit(void) -{ - - return ERROR_OK; -} - -int interface_jtag_execute_queue(void) -{ - uint32_t empty; - - waitIdle(); - - /* We must make sure to write data read back to memory location before we return - * from this fn - */ - zy1000_flush_readqueue(); - - /* and handle any callbacks... */ - zy1000_flush_callbackqueue(); - - if (zy1000_rclk) { - /* Only check for errors when using RCLK to speed up - * jtag over TCP/IP - */ - 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; -} - -static void writeShiftValue(uint8_t *data, int bits); - -/* here we shuffle N bits out/in */ -static inline void scanBits(const uint8_t *out_value, - uint8_t *in_value, - int num_bits, - bool pause_now, - tap_state_t shiftState, - tap_state_t end_state) -{ - tap_state_t pause_state = shiftState; - for (int j = 0; j < num_bits; j += 32) { - int k = num_bits - j; - if (k > 32) { - k = 32; - /* we have more to shift out */ - } else if (pause_now) { - /* this was the last to shift out this time */ - pause_state = end_state; - } - - /* we have (num_bits + 7)/8 bytes of bits to toggle out. */ - /* bits are pushed out LSB to MSB */ - uint32_t value; - value = 0; - if (out_value != NULL) { - for (int l = 0; l < k; l += 8) - value |= out_value[(j + l)/8]<<l; - } - /* mask away unused bits for easier debugging */ - if (k < 32) - value &= ~(((uint32_t)0xffffffff) << k); - else { - /* Shifting by >= 32 is not defined by the C standard - * and will in fact shift by &0x1f bits on nios */ - } - - shiftValueInner(shiftState, pause_state, k, value); - - if (in_value != NULL) - writeShiftValue(in_value + (j/8), k); - } -} - -static inline void scanFields(int num_fields, - const struct scan_field *fields, - tap_state_t shiftState, - tap_state_t end_state) -{ - for (int i = 0; i < num_fields; i++) { - scanBits(fields[i].out_value, - fields[i].in_value, - fields[i].num_bits, - (i == num_fields-1), - shiftState, - end_state); - } -} - -int interface_jtag_add_ir_scan(struct jtag_tap *active, - const struct scan_field *fields, - tap_state_t state) -{ - int scan_size = 0; - struct jtag_tap *tap, *nextTap; - tap_state_t pause_state = TAP_IRSHIFT; - - for (tap = jtag_tap_next_enabled(NULL); tap != NULL; tap = nextTap) { - nextTap = jtag_tap_next_enabled(tap); - if (nextTap == NULL) - pause_state = state; - scan_size = tap->ir_length; - - /* search the list */ - if (tap == active) { - scanFields(1, fields, TAP_IRSHIFT, pause_state); - /* update device information */ - buf_cpy(fields[0].out_value, tap->cur_instr, scan_size); - - tap->bypass = 0; - } else { - /* if a device isn't listed, set it to BYPASS */ - assert(scan_size <= 32); - shiftValueInner(TAP_IRSHIFT, pause_state, scan_size, 0xffffffff); - - /* Optimization code will check what the cur_instr is set to, so - * we must set it to bypass value. - */ - buf_set_ones(tap->cur_instr, tap->ir_length); - - tap->bypass = 1; - } - } - - return ERROR_OK; -} - -int interface_jtag_add_plain_ir_scan(int num_bits, - const uint8_t *out_bits, - uint8_t *in_bits, - tap_state_t state) -{ - scanBits(out_bits, in_bits, num_bits, true, TAP_IRSHIFT, state); - return ERROR_OK; -} - -int interface_jtag_add_dr_scan(struct jtag_tap *active, - int num_fields, - const struct scan_field *fields, - tap_state_t state) -{ - struct jtag_tap *tap, *nextTap; - tap_state_t pause_state = TAP_DRSHIFT; - for (tap = jtag_tap_next_enabled(NULL); tap != NULL; tap = nextTap) { - nextTap = jtag_tap_next_enabled(tap); - if (nextTap == NULL) - pause_state = state; - - /* Find a range of fields to write to this tap */ - if (tap == active) { - assert(!tap->bypass); - - scanFields(num_fields, fields, TAP_DRSHIFT, pause_state); - } else { - /* Shift out a 0 for disabled tap's */ - assert(tap->bypass); - shiftValueInner(TAP_DRSHIFT, pause_state, 1, 0); - } - } - return ERROR_OK; -} - -int interface_jtag_add_plain_dr_scan(int num_bits, - const uint8_t *out_bits, - uint8_t *in_bits, - tap_state_t state) -{ - scanBits(out_bits, in_bits, num_bits, true, TAP_DRSHIFT, state); - return ERROR_OK; -} - -int interface_jtag_add_tlr(void) -{ - setCurrentState(TAP_RESET); - return ERROR_OK; -} - -int interface_jtag_add_reset(int req_trst, int req_srst) -{ - zy1000_reset(req_trst, req_srst); - return ERROR_OK; -} - -static int zy1000_jtag_add_clocks(int num_cycles, tap_state_t state, tap_state_t clockstate) -{ - /* num_cycles can be 0 */ - setCurrentState(clockstate); - - /* execute num_cycles, 32 at the time. */ - int i; - for (i = 0; i < num_cycles; i += 32) { - int num; - num = 32; - if (num_cycles-i < num) - num = num_cycles-i; - shiftValueInner(clockstate, clockstate, num, 0); - } - -#if !TEST_MANUAL() - /* finish in end_state */ - setCurrentState(state); -#else - tap_state_t t = TAP_IDLE; - /* test manual drive code on any target */ - int tms; - uint8_t tms_scan = tap_get_tms_path(t, state); - int tms_count = tap_get_tms_path_len(tap_get_state(), tap_get_end_state()); - - for (i = 0; i < tms_count; i++) { - tms = (tms_scan >> i) & 1; - waitIdle(); - ZY1000_POKE(ZY1000_JTAG_BASE + 0x28, tms); - } - waitIdle(); - ZY1000_POKE(ZY1000_JTAG_BASE + 0x20, state); -#endif - - return ERROR_OK; -} - -int interface_jtag_add_runtest(int num_cycles, tap_state_t state) -{ - return zy1000_jtag_add_clocks(num_cycles, state, TAP_IDLE); -} - -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_add_tms_seq(unsigned num_bits, const uint8_t *seq, enum tap_state state) -{ - /*wait for the fifo to be empty*/ - waitIdle(); - - for (unsigned i = 0; i < num_bits; i++) { - int tms; - - if (((seq[i/8] >> (i % 8)) & 1) == 0) - tms = 0; - else - tms = 1; - - waitIdle(); - ZY1000_POKE(ZY1000_JTAG_BASE + 0x28, tms); - } - - waitIdle(); - if (state != TAP_INVALID) - ZY1000_POKE(ZY1000_JTAG_BASE + 0x20, state); - else { - /* this would be normal if - * we are switching to SWD mode */ - } - return ERROR_OK; -} - -int interface_jtag_add_pathmove(int num_states, const tap_state_t *path) -{ - int state_count; - int tms = 0; - - state_count = 0; - - tap_state_t cur_state = cmd_queue_cur_state; - - uint8_t seq[16]; - memset(seq, 0, sizeof(seq)); - assert(num_states < (int)((sizeof(seq) * 8))); - - while (num_states) { - if (tap_state_transition(cur_state, false) == path[state_count]) - tms = 0; - else if (tap_state_transition(cur_state, true) == path[state_count]) - tms = 1; - else { - LOG_ERROR("BUG: %s -> %s isn't a valid TAP transition", - tap_state_name(cur_state), tap_state_name(path[state_count])); - exit(-1); - } - - seq[state_count/8] = seq[state_count/8] | (tms << (state_count % 8)); - - cur_state = path[state_count]; - state_count++; - num_states--; - } - - return interface_add_tms_seq(state_count, seq, cur_state); -} - -static void jtag_pre_post_bits(struct jtag_tap *tap, int *pre, int *post) -{ - /* bypass bits before and after */ - int pre_bits = 0; - int post_bits = 0; - - 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++; - } - } - *pre = pre_bits; - *post = post_bits; -} - -void embeddedice_write_dcc(struct jtag_tap *tap, - int reg_addr, - const uint8_t *buffer, - int little, - int count) -{ -#if 0 - int i; - for (i = 0; i < count; i++) { - embeddedice_write_reg_inner(tap, reg_addr, fast_target_buffer_get_u32(buffer, - little)); - buffer += 4; - } -#else - int pre_bits; - int post_bits; - jtag_pre_post_bits(tap, &pre_bits, &post_bits); - - if ((pre_bits > 32) || (post_bits + 6 > 32)) { - int i; - for (i = 0; i < count; i++) { - embeddedice_write_reg_inner(tap, reg_addr, - fast_target_buffer_get_u32(buffer, little)); - buffer += 4; - } - } else { - int i; - for (i = 0; i < count; i++) { - /* Fewer pokes means we get to use the FIFO more efficiently */ - shiftValueInner(TAP_DRSHIFT, TAP_DRSHIFT, pre_bits, 0); - shiftValueInner(TAP_DRSHIFT, TAP_DRSHIFT, 32, - fast_target_buffer_get_u32(buffer, little)); - /* Danger! here we need to exit into the TAP_IDLE state to make - * DCC pick up this value. - */ - shiftValueInner(TAP_DRSHIFT, TAP_IDLE, 6 + post_bits, - (reg_addr | (1 << 5))); - buffer += 4; - } - } -#endif -} - -int arm11_run_instr_data_to_core_noack_inner(struct jtag_tap *tap, - uint32_t opcode, - uint32_t *data, - size_t count) -{ - /* bypass bits before and after */ - int pre_bits; - int post_bits; - jtag_pre_post_bits(tap, &pre_bits, &post_bits); - post_bits += 2; - - if ((pre_bits > 32) || (post_bits > 32)) { - 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 uint8_t zero; - - /* 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 - /* Danger! This code doesn't update cmd_queue_cur_state, so - * invoking jtag_add_pathmove() before jtag_add_dr_scan() after - * this loop would fail! - */ - shiftValueInner(TAP_DRSHIFT, TAP_DRSHIFT, pre_bits, 0); - - 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 - }; - - struct scan_field fields[2] = { - { .num_bits = 32, .out_value = t }, - { .num_bits = 2, .out_value = &zero }, - }; - t += 4; - - jtag_add_dr_scan(tap, - 2, - fields, - TAP_IDLE); - - jtag_add_pathmove(ARRAY_SIZE(arm11_MOVE_DRPAUSE_IDLE_DRPAUSE_with_delay), - arm11_MOVE_DRPAUSE_IDLE_DRPAUSE_with_delay); -#endif - } - - struct scan_field fields[2] = { - { .num_bits = 32, .out_value = t }, - { .num_bits = 2, .out_value = &zero }, - }; - - /* 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_scan(tap, - 2, - fields, - TAP_IDLE); - - return jtag_execute_queue(); - } -} - -static const struct command_registration zy1000_commands[] = { - { - .name = "power", - .handler = handle_power_command, - .mode = COMMAND_ANY, - .help = "Turn power switch to target on/off. " - "With no arguments, prints status.", - .usage = "('on'|'off)", - }, -#if !BUILD_ZY1000_MASTER - { - .name = "zy1000_server", - .mode = COMMAND_ANY, - .jim_handler = jim_zy1000_server, - .help = "Tcpip address for ZY1000 server.", - .usage = "address", - }, -#endif - { - .name = "powerstatus", - .mode = COMMAND_ANY, - .jim_handler = zylinjtag_Jim_Command_powerstatus, - .help = "Returns power status of target", - }, - COMMAND_REGISTRATION_DONE -}; - -#if !BUILD_ZY1000_MASTER - -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) -{ - uint32_t data = 0; - int i; - for (i = 0; i < 4; i++) { - 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)); - 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, - ZY1000_CMD_WAITIDLE = 2 -}; - -#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 */ - tcp_ip = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); - if (tcp_ip < 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); - } -} - -/* 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(); - - zy1000_flush_readqueue(); - - 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; -} - -/* queue a readback */ -#define readqueue_size 16384 -static struct { - uint8_t *dest; - int bits; -} readqueue[readqueue_size]; - -static int readqueue_pos; - -/* flush the readqueue, this means reading any data that - * we're expecting and store them into the final position - */ -void zy1000_flush_readqueue(void) -{ - if (readqueue_pos == 0) { - /* simply debugging by allowing easy breakpoints when there - * is something to do. */ - return; - } - int i; - tcpip_open(); - for (i = 0; i < readqueue_pos; i++) { - uint32_t value; - if (!readLong(&value)) { - fprintf(stderr, "Could not read from zy1000 server\n"); - exit(-1); - } - - uint8_t *in_value = readqueue[i].dest; - int k = readqueue[i].bits; - - /* we're shifting in data to MSB, shift data to be aligned for returning the value */ - value >>= 32-k; - - for (int l = 0; l < k; l += 8) - in_value[l/8] = (value >> l)&0xff; - } - readqueue_pos = 0; -} - -/* By queuing the callback's we avoid flushing the - * read queue until jtag_execute_queue(). This can - * reduce latency dramatically for cases where - * callbacks are used extensively. -*/ -#define callbackqueue_size 128 -static struct callbackentry { - jtag_callback_t callback; - jtag_callback_data_t data0; - jtag_callback_data_t data1; - jtag_callback_data_t data2; - jtag_callback_data_t data3; -} callbackqueue[callbackqueue_size]; - -static int callbackqueue_pos; - -void zy1000_jtag_add_callback4(jtag_callback_t callback, - jtag_callback_data_t data0, - jtag_callback_data_t data1, - jtag_callback_data_t data2, - jtag_callback_data_t data3) -{ - if (callbackqueue_pos >= callbackqueue_size) - zy1000_flush_callbackqueue(); - - callbackqueue[callbackqueue_pos].callback = callback; - callbackqueue[callbackqueue_pos].data0 = data0; - callbackqueue[callbackqueue_pos].data1 = data1; - callbackqueue[callbackqueue_pos].data2 = data2; - callbackqueue[callbackqueue_pos].data3 = data3; - callbackqueue_pos++; - - /* KLUDGE! - * make callbacks synchronous for now as minidriver requires callback - * to be synchronous. - * - * We can get away with making read and writes asynchronous so we - * don't completely kill performance. - */ - zy1000_flush_callbackqueue(); -} - -static int zy1000_jtag_convert_to_callback4(jtag_callback_data_t data0, - jtag_callback_data_t data1, - jtag_callback_data_t data2, - jtag_callback_data_t data3) -{ - ((jtag_callback1_t)data1)(data0); - return ERROR_OK; -} - -void zy1000_jtag_add_callback(jtag_callback1_t callback, jtag_callback_data_t data0) -{ - zy1000_jtag_add_callback4(zy1000_jtag_convert_to_callback4, - data0, - (jtag_callback_data_t)callback, - 0, - 0); -} - -void zy1000_flush_callbackqueue(void) -{ - /* we have to flush the read queue so we have access to - the data the callbacks will use - */ - zy1000_flush_readqueue(); - int i; - for (i = 0; i < callbackqueue_pos; i++) { - struct callbackentry *entry = &callbackqueue[i]; - jtag_set_error(entry->callback(entry->data0, entry->data1, entry->data2, - entry->data3)); - } - callbackqueue_pos = 0; -} - -static void writeShiftValue(uint8_t *data, int bits) -{ - waitIdle(); - - if (!writeLong((ZY1000_CMD_PEEK << 24) | (ZY1000_JTAG_BASE + 0xc))) { - fprintf(stderr, "Could not read from zy1000 server\n"); - exit(-1); - } - - if (readqueue_pos >= readqueue_size) - zy1000_flush_readqueue(); - - readqueue[readqueue_pos].dest = data; - readqueue[readqueue_pos].bits = bits; - readqueue_pos++; - - /* KLUDGE!!! minidriver requires readqueue to be synchronous */ - zy1000_flush_readqueue(); -} - -#else - -static void writeShiftValue(uint8_t *data, int bits) -{ - uint32_t value; - waitIdle(); - ZY1000_PEEK(ZY1000_JTAG_BASE + 0xc, value); - VERBOSE(LOG_INFO("getShiftValue %08x", value)); - - /* data in, LSB to MSB */ - /* we're shifting in data to MSB, shift data to be aligned for returning the value */ - value >>= 32 - bits; - - for (int l = 0; l < bits; l += 8) - data[l/8] = (value >> l)&0xff; -} - -#endif - -#if BUILD_ZY1000_MASTER - -#ifdef WATCHDOG_BASE -/* If we connect to port 8888 we must send a char every 10s or the board resets itself */ -static void watchdog_server(cyg_addrword_t data) -{ - int so_reuseaddr_option = 1; - - int fd = socket(AF_INET, SOCK_STREAM, 0); - if (fd == -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(8888); - - 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 (;; ) { - int watchdog_ip = accept(fd, (struct sockaddr *) &sin, &address_size); - - /* Start watchdog, must be reset every 10 seconds. */ - HAL_WRITE_UINT32(WATCHDOG_BASE + 4, 4); - - if (watchdog_ip < 0) { - LOG_ERROR("couldn't open watchdog socket: %s", strerror(errno)); - exit(-1); - } - - int flag = 1; - setsockopt(watchdog_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 */ - - - char buf; - for (;; ) { - if (read(watchdog_ip, &buf, 1) == 1) { - /* Reset timer */ - HAL_WRITE_UINT32(WATCHDOG_BASE + 8, 0x1234); - /* Echo so we can telnet in and see that resetting works */ - write(watchdog_ip, &buf, 1); - } else { - /* Stop tickling the watchdog, the CPU will reset in < 10 seconds - * now. - */ - return; - } - - } - - /* Never reached */ - } -} -#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 -volatile void *zy1000_jtag_master; -#include <sys/mman.h> -#endif - -int zy1000_init(void) -{ -#if BUILD_ZY1000_MASTER - int fd = open("/dev/mem", O_RDWR | O_SYNC); - if (fd == -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 */ - - setPower(true); /* on by default */ - - /* deassert resets. Important to avoid infinite loop waiting for SRST to deassert */ - zy1000_reset(0, 0); - - return ERROR_OK; -} - -static struct jtag_interface zy1000_interface = { - .supported = DEBUG_CAP_TMS_SEQ, - .execute_queue = NULL, -}; - -struct adapter_driver zy1000_adapter_driver = { - .name = "ZY1000", - .transports = jtag_only, - .commands = zy1000_commands, - - .init = zy1000_init, - .quit = zy1000_quit, - .speed = zy1000_speed, - .khz = zy1000_khz, - .speed_div = zy1000_speed_div, - .power_dropout = zy1000_power_dropout, - .srst_asserted = zy1000_srst_asserted, - - .jtag_ops = &zy1000_interface, -}; diff --git a/tcl/board/zy1000.cfg b/tcl/board/zy1000.cfg deleted file mode 100644 index e0d1ccf..0000000 --- a/tcl/board/zy1000.cfg +++ /dev/null @@ -1,117 +0,0 @@ -#Script for ZY1000 - -#Atmel ties SRST & TRST together, at which point it makes -#no sense to use TRST, but use TMS instead. -# -#The annoying thing with tying SRST & TRST together is that -#there is no way to halt the CPU *before and during* the -#SRST reset, which means that the CPU will run a number -#of cycles before it can be halted(as much as milliseconds). -reset_config srst_only srst_pulls_trst - - -if { [info exists CHIPNAME] } { - set _CHIPNAME $CHIPNAME -} else { - set _CHIPNAME zy1000 -} - -if { [info exists ENDIAN] } { - set _ENDIAN $ENDIAN -} else { - set _ENDIAN little -} - - -#jtag scan chain -if { [info exists CPUTAPID] } { - set _CPUTAPID $CPUTAPID -} else { - set _CPUTAPID 0x1f0f0f0f -} -jtag newtap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID - -set _TARGETNAME $_CHIPNAME.cpu -target create $_TARGETNAME arm7tdmi -endian $_ENDIAN -chain-position $_TARGETNAME - -# at CPU CLK <32kHz this must be disabled -arm7_9 fast_memory_access enable -arm7_9 dcc_downloads enable - -set _FLASHNAME $_CHIPNAME.flash -flash bank $_FLASHNAME cfi 0x01000000 0x200000 2 2 $_TARGETNAME - -$_TARGETNAME configure -event reset-init { - # Set up chip selects & timings - mww 0xFFE00000 0x0100273D - mww 0xFFE00004 0x08002125 - mww 0xFFEe0008 0x02002125 - mww 0xFFE0000c 0x03002125 - mww 0xFFE00010 0x40000000 - mww 0xFFE00014 0x50000000 - mww 0xFFE00018 0x60000000 - mww 0xFFE0001c 0x70000000 - mww 0xFFE00020 0x00000001 - mww 0xFFE00024 0x00000000 - - # remap - mww 0xFFFFF124 0xFFFFFFFF - mww 0xffff0010 0x100 - mww 0xffff0034 0x100 - - #disable 16x5x UART interrupts - mww 0x08020004 0 -} - -$_TARGETNAME configure -event gdb-attach { - # Without this gdb-attach will first time as probe will fail - reset init -} - -# required for usable performance. Used for lots of -# other things than flash programming. -$_TARGETNAME configure -work-area-phys 0x00020000 -work-area-size 0x20000 -work-area-backup 0 - -adapter speed 16000 - - -proc production_info {} { - return "Serial number is official MAC number. Format XXXXXXXXXXXX" -} - -# There is no return value from this procedure. If it is -# successful it does not throw an exception -# -# Progress messages are output via puts -proc production {firmwarefile serialnumber} { - if {[string length $serialnumber]!=12} { - echo "Invalid serial number" - return - } - - echo "Power cycling target" - power off - sleep 3000 - power on - sleep 1000 - reset init - flash write_image erase $firmwarefile 0x1000000 bin - verify_image $firmwarefile 0x1000000 bin - - # Big endian... weee!!!! - echo "Setting MAC number to $serialnumber" - flash fillw [expr 0x1030000-0x8] "0x[string range $serialnumber 2 3][string range $serialnumber 0 1]0000" 1 - flash fillw [expr 0x1030000-0x4] "0x[string range $serialnumber 10 11][string range $serialnumber 8 9][string range $serialnumber 6 7][string range $serialnumber 4 5]" 1 - echo "Production successful" -} - - -proc production_test {} { - power on - sleep 1000 - target_request debugmsgs enable - reset run - sleep 25000 - target_request debugmsgs disable - return "See IP address above..." -} |