diff options
-rw-r--r-- | fpga/xilinx/programmer/svfplayer/beaglebone_black/Makefile | 47 | ||||
-rw-r--r-- | fpga/xilinx/programmer/svfplayer/beaglebone_black/xsvf-bbb.c | 546 | ||||
-rw-r--r-- | fpga/xilinx/programmer/svfplayer/raspberry_pi/Makefile (renamed from fpga/xilinx/programmer/svfplayer/Makefile) | 0 | ||||
-rw-r--r-- | fpga/xilinx/programmer/svfplayer/raspberry_pi/xsvf-rpi.c (renamed from fpga/xilinx/programmer/svfplayer/xsvf-rpi.c) | 0 |
4 files changed, 593 insertions, 0 deletions
diff --git a/fpga/xilinx/programmer/svfplayer/beaglebone_black/Makefile b/fpga/xilinx/programmer/svfplayer/beaglebone_black/Makefile new file mode 100644 index 0000000..5a5701e --- /dev/null +++ b/fpga/xilinx/programmer/svfplayer/beaglebone_black/Makefile @@ -0,0 +1,47 @@ +# Copyright (C) 2013 Timothy Pearson +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +AR = ar +RANLIB = ranlib +CC = gcc + +CFLAGS += -Wall -Os -ggdb -MD +#CFLAGS += -Wextra -Wno-unused-parameter -Werror + +help: + @echo "" + @echo "Usage:" + @echo "" + @echo " $(MAKE) xsvf-bbb" + @echo " .... build xsvf-bbb" + @echo "" + @echo " $(MAKE) all" + @echo " .... build everything" + @echo "" + @echo " $(MAKE) install" + @echo " .... install everything in /usr/" + @echo "" + +all: xsvf-bbb + +install: all + install -Dt /usr/bin/ xsvf-bbb + +xsvf-bbb: /usr/lib/libxsvf.a xsvf-bbb.o + +clean: + rm -f xsvf-bbb.o + +-include *.d + diff --git a/fpga/xilinx/programmer/svfplayer/beaglebone_black/xsvf-bbb.c b/fpga/xilinx/programmer/svfplayer/beaglebone_black/xsvf-bbb.c new file mode 100644 index 0000000..3b314af --- /dev/null +++ b/fpga/xilinx/programmer/svfplayer/beaglebone_black/xsvf-bbb.c @@ -0,0 +1,546 @@ +/* + * Lib(X)SVF - A library for implementing SVF and XSVF JTAG players + * + * Copyright (C) 2013 Timothy Pearson <kb9vqf@pearsoncomputing.net> (Beaglebone Black) + * Copyright (C) 2009 RIEGL Research ForschungsGmbH + * Copyright (C) 2009 Clifford Wolf <clifford@clifford.at> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#include "libxsvf.h" + +#include <sys/time.h> +#include <unistd.h> +#include <string.h> +#include <stdlib.h> +#include <stdio.h> +#include <errno.h> + + +/** BEGIN: Low-Level I/O Implementation **/ + +// Beaglebone Black GPIO driver +// TMS: P9 11 (GPIO 30) +// TDI: P9 13 (GPIO 31) +// TDO: P9 21 (GPIO 3) +// TCK: P9 22 (GPIO 2) + +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/mman.h> +#include <fcntl.h> + +#define GPIO0_BASE 0x44E07000 +#define GPIO1_BASE 0x4804C000 +#define GPIO2_BASE 0x481AC000 +#define GPIO3_BASE 0x481AE000 + +#define GPIO_SIZE 0x00000FFF + +// OE: 0 is output, 1 is input +#define GPIO_OE 0x14d +#define GPIO_IN 0x14e +#define GPIO_OUT 0x14f + +#define TMS_PIN (1<<30) +#define TDI_PIN (1<<31) +#define TDO_PIN (1<<3) +#define TCK_PIN (1<<2) + +int mem_fd; +char *gpio_mem, *gpio_map; + +// I/O access +volatile unsigned *gpio; + +static void io_setup(void) +{ + // Enable all GPIO banks + // Without this, access to deactivated banks (i.e. those with no clock source setup) will (logically) fail with SIGBUS + // Idea taken from https://groups.google.com/forum/#!msg/beagleboard/OYFp4EXawiI/Mq6s3sg14HoJ + system("echo 5 > /sys/class/gpio/export"); + system("echo 65 > /sys/class/gpio/export"); + system("echo 105 > /sys/class/gpio/export"); + + /* open /dev/mem */ + if ((mem_fd = open("/dev/mem", O_RDWR|O_SYNC) ) < 0) { + printf("can't open /dev/mem \n"); + exit (-1); + } + + /* mmap GPIO */ + gpio_map = (char *)mmap( + 0, + GPIO_SIZE, + PROT_READ|PROT_WRITE, + MAP_SHARED, + mem_fd, + GPIO0_BASE + ); + + if (gpio_map == MAP_FAILED) { + printf("mmap error %d\n", (int)gpio_map); + exit (-1); + } + + // Always use volatile pointer! + gpio = (volatile unsigned *)gpio_map; + +#if 0 + // DEBUG ONLY + // Prints the contents of the memory mapped control register space + // Originally used to reverse engineer the register offsets #defined at the top of this file + int k; + for (k=0;k<GPIO_SIZE; k++) { + printf("0x%08x\t%08x\n", k, *(gpio + k)); + } + fflush(stdout); +#endif + + // Get direction control register contents + unsigned int creg = *(gpio + GPIO_OE); + + // Set outputs + creg = creg & (~TMS_PIN); + creg = creg & (~TDI_PIN); + creg = creg & (~TCK_PIN); + + // Set inputs + creg = creg | TDO_PIN; + + // Set new direction control register contents + *(gpio + GPIO_OE) = creg; +} + +static void io_shutdown(void) +{ + // Get direction control register contents + unsigned int creg = *(gpio + GPIO_OE); + + // Set inputs + creg = creg | TMS_PIN; + creg = creg | TDI_PIN; + creg = creg | TDO_PIN; + creg = creg | TCK_PIN; + + // Set new direction control register contents + *(gpio + GPIO_OE) = creg; +} + +static void io_tms(int val) +{ + if (val) { + *(gpio + GPIO_OUT) = *(gpio + GPIO_OUT) | TMS_PIN; + } + else { + *(gpio + GPIO_OUT) = *(gpio + GPIO_OUT) & (~TMS_PIN); + } +} + +static void io_tdi(int val) +{ + if (val) { + *(gpio + GPIO_OUT) = *(gpio + GPIO_OUT) | TDI_PIN; + } + else { + *(gpio + GPIO_OUT) = *(gpio + GPIO_OUT) & (~TDI_PIN); + } +} + +static void io_tck(int val) +{ + if (val) { + *(gpio + GPIO_OUT) = *(gpio + GPIO_OUT) | TCK_PIN; + } + else { + *(gpio + GPIO_OUT) = *(gpio + GPIO_OUT) & (~TCK_PIN); + } + + // usleep(1); +} + +static void io_sck(int val) +{ + /* not available */ +} + +static void io_trst(int val) +{ + /* not available */ +} + +static int io_tdo() +{ + return ((*(gpio + GPIO_IN)) & TDO_PIN) ? 1 : 0; +} + +/** END: Low-Level I/O Implementation **/ + + +struct udata_s { + FILE *f; + int verbose; + int clockcount; + int bitcount_tdi; + int bitcount_tdo; + int retval_i; + int retval[256]; +}; + +static int h_setup(struct libxsvf_host *h) +{ + struct udata_s *u = h->user_data; + if (u->verbose >= 2) { + fprintf(stderr, "[SETUP]\n"); + fflush(stderr); + } + io_setup(); + return 0; +} + +static int h_shutdown(struct libxsvf_host *h) +{ + struct udata_s *u = h->user_data; + if (u->verbose >= 2) { + fprintf(stderr, "[SHUTDOWN]\n"); + fflush(stderr); + } + io_shutdown(); + return 0; +} + +static void h_udelay(struct libxsvf_host *h, long usecs, int tms, long num_tck) +{ + struct udata_s *u = h->user_data; + if (u->verbose >= 3) { + fprintf(stderr, "[DELAY:%ld, TMS:%d, NUM_TCK:%ld]\n", usecs, tms, num_tck); + fflush(stderr); + } + if (num_tck > 0) { + struct timeval tv1, tv2; + gettimeofday(&tv1, NULL); + io_tms(tms); + while (num_tck > 0) { + io_tck(0); + io_tck(1); + num_tck--; + } + gettimeofday(&tv2, NULL); + if (tv2.tv_sec > tv1.tv_sec) { + usecs -= (1000000 - tv1.tv_usec) + (tv2.tv_sec - tv1.tv_sec - 1) * 1000000; + tv1.tv_usec = 0; + } + usecs -= tv2.tv_usec - tv1.tv_usec; + if (u->verbose >= 3) { + fprintf(stderr, "[DELAY_AFTER_TCK:%ld]\n", usecs > 0 ? usecs : 0); + fflush(stderr); + } + } + if (usecs > 0) { + usleep(usecs); + } +} + +static int h_getbyte(struct libxsvf_host *h) +{ + struct udata_s *u = h->user_data; + return fgetc(u->f); +} + +static int h_pulse_tck(struct libxsvf_host *h, int tms, int tdi, int tdo, int rmask, int sync) +{ + struct udata_s *u = h->user_data; + + io_tms(tms); + + if (tdi >= 0) { + u->bitcount_tdi++; + io_tdi(tdi); + } + + io_tck(0); + io_tck(1); + + int line_tdo = io_tdo(); + int rc = line_tdo >= 0 ? line_tdo : 0; + + if (rmask == 1 && u->retval_i < 256) + u->retval[u->retval_i++] = line_tdo; + + if (tdo >= 0 && line_tdo >= 0) { + u->bitcount_tdo++; + if (tdo != line_tdo) + rc = -1; + } + + if (u->verbose >= 4) { + fprintf(stderr, "[TMS:%d, TDI:%d, TDO_ARG:%d, TDO_LINE:%d, RMASK:%d, RC:%d]\n", tms, tdi, tdo, line_tdo, rmask, rc); + } + + u->clockcount++; + return rc; +} + +static void h_pulse_sck(struct libxsvf_host *h) +{ + struct udata_s *u = h->user_data; + if (u->verbose >= 4) { + fprintf(stderr, "[SCK]\n"); + } + io_sck(0); + io_sck(1); +} + +static void h_set_trst(struct libxsvf_host *h, int v) +{ + struct udata_s *u = h->user_data; + if (u->verbose >= 4) { + fprintf(stderr, "[TRST:%d]\n", v); + } + io_trst(v); +} + +static int h_set_frequency(struct libxsvf_host *h, int v) +{ + fprintf(stderr, "WARNING: Setting JTAG clock frequency to %d ignored!\n", v); + return 0; +} + +static void h_report_tapstate(struct libxsvf_host *h) +{ + struct udata_s *u = h->user_data; + if (u->verbose >= 3) { + fprintf(stderr, "[%s]\n", libxsvf_state2str(h->tap_state)); + } +} + +static void h_report_device(struct libxsvf_host *h, unsigned long idcode) +{ + // struct udata_s *u = h->user_data; + printf("idcode=0x%08lx, revision=0x%01lx, part=0x%04lx, manufactor=0x%03lx\n", idcode, + (idcode >> 28) & 0xf, (idcode >> 12) & 0xffff, (idcode >> 1) & 0x7ff); +} + +static void h_report_status(struct libxsvf_host *h, const char *message) +{ + struct udata_s *u = h->user_data; + if (u->verbose >= 2) { + fprintf(stderr, "[STATUS] %s\n", message); + } +} + +static void h_report_error(struct libxsvf_host *h, const char *file, int line, const char *message) +{ + fprintf(stderr, "[%s:%d] %s\n", file, line, message); +} + +static int realloc_maxsize[LIBXSVF_MEM_NUM]; + +static void *h_realloc(struct libxsvf_host *h, void *ptr, int size, enum libxsvf_mem which) +{ + struct udata_s *u = h->user_data; + if (size > realloc_maxsize[which]) + realloc_maxsize[which] = size; + if (u->verbose >= 3) { + fprintf(stderr, "[REALLOC:%s:%d]\n", libxsvf_mem2str(which), size); + } + return realloc(ptr, size); +} + +static struct udata_s u; + +static struct libxsvf_host h = { + .udelay = h_udelay, + .setup = h_setup, + .shutdown = h_shutdown, + .getbyte = h_getbyte, + .pulse_tck = h_pulse_tck, + .pulse_sck = h_pulse_sck, + .set_trst = h_set_trst, + .set_frequency = h_set_frequency, + .report_tapstate = h_report_tapstate, + .report_device = h_report_device, + .report_status = h_report_status, + .report_error = h_report_error, + .realloc = h_realloc, + .user_data = &u +}; + +const char *progname; + +static void copyleft() +{ + static int already_printed = 0; + if (already_printed) + return; + fprintf(stderr, "xsvftool-gpio, part of Lib(X)SVF (http://www.clifford.at/libxsvf/).\n"); + fprintf(stderr, "Copyright (C) 2009 RIEGL Research ForschungsGmbH\n"); + fprintf(stderr, "Copyright (C) 2009 Clifford Wolf <clifford@clifford.at>\n"); + fprintf(stderr, "Copyright (C) 2013 Timothy Pearson <kb9vqf@pearsoncomputing.net> (Beaglebone Black)\n"); + fprintf(stderr, "Lib(X)SVF is free software licensed under the ISC license.\n"); + already_printed = 1; +} + +static void help() +{ + copyleft(); + fprintf(stderr, "\n"); + fprintf(stderr, "Usage: %s [ -r funcname ] [ -v ... ] [ -L | -B ] { -s svf-file | -x xsvf-file | -c } ...\n", progname); + fprintf(stderr, "\n"); + fprintf(stderr, " -r funcname\n"); + fprintf(stderr, " Dump C-code for pseudo-allocator based on example files\n"); + fprintf(stderr, "\n"); + fprintf(stderr, " -v, -vv, -vvv, -vvvv\n"); + fprintf(stderr, " Verbose, more verbose and even more verbose\n"); + fprintf(stderr, "\n"); + fprintf(stderr, " -L, -B\n"); + fprintf(stderr, " Print RMASK bits as hex value (little or big endian)\n"); + fprintf(stderr, "\n"); + fprintf(stderr, " -s svf-file\n"); + fprintf(stderr, " Play the specified SVF file\n"); + fprintf(stderr, "\n"); + fprintf(stderr, " -x xsvf-file\n"); + fprintf(stderr, " Play the specified XSVF file\n"); + fprintf(stderr, "\n"); + fprintf(stderr, " -c\n"); + fprintf(stderr, " List devices in JTAG chain\n"); + fprintf(stderr, "\n"); + exit(1); +} + +int main(int argc, char **argv) +{ + int rc = 0; + int gotaction = 0; + int hex_mode = 0; + const char *realloc_name = NULL; + int opt, i, j; + + progname = argc >= 1 ? argv[0] : "xvsftool"; + while ((opt = getopt(argc, argv, "r:vLBx:s:c")) != -1) + { + switch (opt) + { + case 'r': + realloc_name = optarg; + break; + case 'v': + copyleft(); + u.verbose++; + break; + case 'x': + case 's': + gotaction = 1; + if (u.verbose) + fprintf(stderr, "Playing %s file `%s'.\n", opt == 's' ? "SVF" : "XSVF", optarg); + if (!strcmp(optarg, "-")) + u.f = stdin; + else + u.f = fopen(optarg, "rb"); + if (u.f == NULL) { + fprintf(stderr, "Can't open %s file `%s': %s\n", opt == 's' ? "SVF" : "XSVF", optarg, strerror(errno)); + rc = 1; + break; + } + if (libxsvf_play(&h, opt == 's' ? LIBXSVF_MODE_SVF : LIBXSVF_MODE_XSVF) < 0) { + fprintf(stderr, "Error while playing %s file `%s'.\n", opt == 's' ? "SVF" : "XSVF", optarg); + rc = 1; + } + if (strcmp(optarg, "-")) + fclose(u.f); + break; + case 'c': + gotaction = 1; + if (libxsvf_play(&h, LIBXSVF_MODE_SCAN) < 0) { + fprintf(stderr, "Error while scanning JTAG chain.\n"); + rc = 1; + } + break; + case 'L': + hex_mode = 1; + break; + case 'B': + hex_mode = 2; + break; + default: + help(); + break; + } + } + + if (!gotaction) + help(); + + if (u.verbose) { + fprintf(stderr, "Total number of clock cycles: %d\n", u.clockcount); + fprintf(stderr, "Number of significant TDI bits: %d\n", u.bitcount_tdi); + fprintf(stderr, "Number of significant TDO bits: %d\n", u.bitcount_tdo); + if (rc == 0) { + fprintf(stderr, "Finished without errors.\n"); + } else { + fprintf(stderr, "Finished with errors!\n"); + } + } + + if (u.retval_i) { + if (hex_mode) { + printf("0x"); + for (i=0; i < u.retval_i; i+=4) { + int val = 0; + for (j=i; j<i+4; j++) + val = val << 1 | u.retval[hex_mode > 1 ? j : u.retval_i - j - 1]; + printf("%x", val); + } + } else { + printf("%d rmask bits:", u.retval_i); + for (i=0; i < u.retval_i; i++) + printf(" %d", u.retval[i]); + } + printf("\n"); + } + + if (realloc_name) { + int num = 0; + for (i = 0; i < LIBXSVF_MEM_NUM; i++) { + if (realloc_maxsize[i] > 0) + num = i+1; + } + printf("void *%s(void *h, void *ptr, int size, int which) {\n", realloc_name); + for (i = 0; i < num; i++) { + if (realloc_maxsize[i] > 0) + printf("\tstatic unsigned char buf_%s[%d];\n", libxsvf_mem2str(i), realloc_maxsize[i]); + } + printf("\tstatic unsigned char *buflist[%d] = {", num); + for (i = 0; i < num; i++) { + if (realloc_maxsize[i] > 0) + printf("%sbuf_%s", i ? ", " : " ", libxsvf_mem2str(i)); + else + printf("%s(void*)0", i ? ", " : " "); + } + printf(" };\n\tstatic int sizelist[%d] = {", num); + for (i = 0; i < num; i++) { + if (realloc_maxsize[i] > 0) + printf("%ssizeof(buf_%s)", i ? ", " : " ", libxsvf_mem2str(i)); + else + printf("%s0", i ? ", " : " "); + } + printf(" };\n"); + printf("\treturn which < %d && size <= sizelist[which] ? buflist[which] : (void*)0;\n", num); + printf("};\n"); + } + + return rc; +} + diff --git a/fpga/xilinx/programmer/svfplayer/Makefile b/fpga/xilinx/programmer/svfplayer/raspberry_pi/Makefile index 176b0a3..176b0a3 100644 --- a/fpga/xilinx/programmer/svfplayer/Makefile +++ b/fpga/xilinx/programmer/svfplayer/raspberry_pi/Makefile diff --git a/fpga/xilinx/programmer/svfplayer/xsvf-rpi.c b/fpga/xilinx/programmer/svfplayer/raspberry_pi/xsvf-rpi.c index 034abbc..034abbc 100644 --- a/fpga/xilinx/programmer/svfplayer/xsvf-rpi.c +++ b/fpga/xilinx/programmer/svfplayer/raspberry_pi/xsvf-rpi.c |