jtagonizer

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README

commit 486f882823b5c64053903d9834439ef40c0601b2
parent 940b6d1fa9e0f9483d2f05447a699e98d5903282
Author: Brian Swetland <swetland@frotz.net>
Date:   Sat,  4 Oct 2014 22:52:09 -0700

fpga: tool to download bitfile to xilinx 7-series fpga

- Currently only works if the FPGA is unprogrammed, out of reset.
- Does not have the entire 7-series idcodes in its table, so will
  not recognize all parts.
- Does not do any bitfile metadata vs device validation yet, so will
  happily send the wrong bitfile to a device (but that should always
  fail).

Diffstat:
MMakefile | 9+++++++--
Afpga.c | 80+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mjtag-core.c | 38+++++++++++++++++++++++++++++---------
Mjtag.h | 3+++
4 files changed, 119 insertions(+), 11 deletions(-)

diff --git a/Makefile b/Makefile @@ -4,7 +4,7 @@ CFLAGS := -Wall -O0 -g LIBS := -lusb-1.0 -lrt -all: jtag dap-test zynq +all: zynq fpga JTAG_OBJS := jtag-mpsse-driver.o jtag-core.o jtag.o $(JTAG_OBJS): jtag.h jtag-driver.h @@ -21,5 +21,10 @@ $(ZYNQ_OBJS): jtag.h jtag-driver.h dap.h dap-registers.h v7debug.h v7debug-regis zynq: $(ZYNQ_OBJS) $(CC) -o zynq $(ZYNQ_OBJS) $(LIBS) +FPGA_OBJS := fpga.o jtag-core.o jtag-mpsse-driver.o +$(FPGA_OBJS): jtag.h jtag-driver.h +fpga: $(FPGA_OBJS) + $(CC) -o fpga $(FPGA_OBJS) $(LIBS) + clean: - rm -f *.o jtag dap-test zynq + rm -f *.o jtag dap-test zynq fpga diff --git a/fpga.c b/fpga.c @@ -0,0 +1,80 @@ +// Copyright 2014 Brian Swetland <swetland@frotz.net> +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <unistd.h> +#include <fcntl.h> + +#include "jtag.h" + +static void *loadfile(const char *fn, u32 *sz) { + int fd; + off_t end; + void *data = NULL; + if ((fd = open(fn, O_RDONLY)) < 0) return NULL; + if ((end = lseek(fd, 0, SEEK_END)) < 0) goto oops; + if (lseek(fd, 0, SEEK_SET) < 0) goto oops; + if ((data = malloc(end + 4)) == NULL) goto oops; + if (read(fd, data, end) != end) goto oops; + close(fd); + *sz = end; + return data; + +oops: + free(data); + close(fd); + return NULL; +} + +static u8 bitrev(u8 x) { + x = (x << 4) | (x >> 4); + x = ((x << 2) & 0xcc) | ((x >> 2) & 0x33); + x = ((x << 1) & 0xaa) | ((x >> 1) & 0x55); + return x; +} + +int main(int argc, char **argv) { + JTAG *jtag; + u8 *data; + u32 sz, n; + + if (argc != 2) { + fprintf(stderr, "usage: fpga <bitfile>\n"); + return -1; + } + + if ((data = loadfile(argv[1], &sz)) == NULL) return -1; + + for (n = 0; n < sz; n++) { + data[n] = bitrev(data[n]); + } + + if (jtag_mpsse_open(&jtag)) return -1; + if (jtag_enumerate(jtag) < 0) return -1; + if (jtag_select_by_family(jtag, "Xilinx 7")) return -1; + + fprintf(stderr, "begin.\n"); + n = 5; + jtag_ir_wr(jtag, 6, &n); + jtag_dr_wr(jtag, sz * 8, data); + + if (jtag_commit(jtag)) return -1; + + fprintf(stderr, "done.\n"); + return 0; +} + diff --git a/jtag-core.c b/jtag-core.c @@ -23,13 +23,13 @@ #define ZYNQMASK 0x0FFFFFFF static JTAG_INFO LIBRARY[] = { - { 0x4ba00477, 0xFFFFFFFF, 4, "Cortex A9" }, - { ZYNQID(0x02), ZYNQMASK, 6, "xc7x010" }, - { ZYNQID(0x1b), ZYNQMASK, 6, "xc7x015" }, - { ZYNQID(0x07), ZYNQMASK, 6, "xc7x020" }, - { ZYNQID(0x0c), ZYNQMASK, 6, "xc7x030" }, - { ZYNQID(0x11), ZYNQMASK, 6, "xc7x045" }, - { 0x13631093, 0xFFFFFFFF, 6, "xc7a100t" }, + { 0x4ba00477, 0xFFFFFFFF, 4, "Cortex A9", "ARM A9" }, + { ZYNQID(0x02), ZYNQMASK, 6, "xc7x010", "Xilinx 7" }, + { ZYNQID(0x1b), ZYNQMASK, 6, "xc7x015", "Xilinx 7" }, + { ZYNQID(0x07), ZYNQMASK, 6, "xc7x020", "Xilinx 7" }, + { ZYNQID(0x0c), ZYNQMASK, 6, "xc7x030", "Xilinx 7" }, + { ZYNQID(0x11), ZYNQMASK, 6, "xc7x045", "Xilinx 7" }, + { 0x13631093, 0xFFFFFFFF, 6, "xc7a100t", "Xilinx 7" }, }; JTAG_INFO *jtag_lookup_device(unsigned idcode) { @@ -327,8 +327,8 @@ int jtag_enumerate(JTAG *jtag) { return -1; } memcpy(jtag->devinfo + n, info, sizeof(JTAG_INFO)); - fprintf(stderr, "device %02d idcode %08x '%s'\n", - n, info->idcode, info->name); + fprintf(stderr, "device %02d idcode: %08x name: %-16s family: %s\n", + n, info->idcode, info->name, info->family); } fprintf(stderr, "too many devices\n"); return -1; @@ -376,3 +376,23 @@ int jtag_select_device(JTAG *jtag, unsigned idcode) { return -1; } +int jtag_select_by_family(JTAG *jtag, const char *family) { + int i, n; + int count = 0; + for (i = 0; i < jtag->devcount; i++) { + if (!strcmp(jtag->devinfo[i].family, family)) { + count++; + n = i; + } + } + if (count == 0) { + fprintf(stderr, "jtag: no devices of family '%s' found.\n", family); + return -1; + } + if (count > 1) { + fprintf(stderr, "jtag: multiple devices of family '%s' found.\n", family); + return -1; + } + return jtag_select_device_nth(jtag, n); +} + diff --git a/jtag.h b/jtag.h @@ -83,6 +83,7 @@ typedef struct { unsigned idmask; unsigned irsize; const char *name; + const char *family; } JTAG_INFO; // reset the bus and probe it @@ -99,4 +100,6 @@ int jtag_select_device(JTAG *jtag, unsigned idcode); // select by position in scan chain int jtag_select_device_nth(JTAG *jtag, int n); +int jtag_select_by_family(JTAG *jtag, const char *family); + #endif