jtag

commandline jtag stuff
git clone http://frotz.net/git/jtag.git
Log | Files | Refs | README

jtag.c (4975B)


      1 /* Copyright 2012 Brian Swetland <swetland@frotz.net>
      2  *
      3  * Licensed under the Apache License, Version 2.0 (the "License");
      4  * you may not use this file except in compliance with the License.
      5  * You may obtain a copy of the License at
      6  *
      7  *     http://www.apache.org/licenses/LICENSE-2.0
      8  *
      9  * Unless required by applicable law or agreed to in writing, software
     10  * distributed under the License is distributed on an "AS IS" BASIS,
     11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12  * See the License for the specific language governing permissions and
     13  * limitations under the License.
     14  */
     15 
     16 #include <stdio.h>
     17 #include <stdlib.h>
     18 #include <unistd.h>
     19 #include <string.h>
     20 #include <ctype.h>
     21 
     22 #include <libusb-1.0/libusb.h>
     23 
     24 #define TRACE_USB	0
     25 #define TRACE_JTAG	0
     26 
     27 static struct libusb_device_handle *udev;
     28 static int usb_open(unsigned vid, unsigned pid) {
     29 	if (libusb_init(NULL) < 0)
     30 		return -1;
     31 
     32 	if (!(udev = libusb_open_device_with_vid_pid(NULL, vid, pid))) {
     33 		fprintf(stderr,"cannot find device\n");
     34 		return -1;
     35 	}
     36 
     37 	if (libusb_claim_interface(udev, 0) < 0) {
     38 		fprintf(stderr,"cannot claim interface\n");
     39 		return -1;
     40 	}
     41 	return 0;
     42 }
     43 static void usb_close(void) {
     44 	libusb_exit(NULL);
     45 }
     46 #if TRACE_USB
     47 static void dump(char *prefix, void *data, int len) {
     48 	unsigned char *x = data;
     49 	fprintf(stderr,"%s: (%d)", prefix, len);
     50 	while (len > 0) {
     51 		fprintf(stderr," %02x", *x++);
     52 		len--;
     53 	}
     54 	fprintf(stderr,"\n");
     55 }
     56 #endif
     57 static int usb_bulk(unsigned char ep, void *data, int len, unsigned timeout) {
     58 	int r, xfer;
     59 #if TRACE_USB
     60 	if (!(ep & 0x80))
     61 		dump("xmit", data, len);
     62 #endif
     63 	r = libusb_bulk_transfer(udev, ep, data, len, &xfer, timeout);
     64 	if (r < 0) {
     65 		fprintf(stderr,"bulk: error: %d\n", r);
     66 		return r;
     67 	}
     68 #if TRACE_USB
     69 	if (ep & 0x80)
     70 		dump("recv", data, xfer);
     71 #endif
     72 	return xfer;
     73 }
     74 
     75 #define EP1_IN	0x81
     76 #define EP2_OUT	0x02
     77 
     78 #define UB_BYTEMODE	0x80
     79 #define UB_BITMODE	0x00
     80 #define UB_READBACK	0x40
     81 
     82 /* bits in bit mode */
     83 #define UB_OE		0x20
     84 #define UB_TDI		0x10
     85 #define UB_nCS		0x08
     86 #define UB_nCE		0x04
     87 #define UB_TMS		0x02
     88 #define UB_TCK		0x01
     89 
     90 /* bytecount for data bytes that follow in byte mode */
     91 #define UB_COUNT(n)	((n) & 0x3F)
     92 
     93 int jtag_move(int count, unsigned bits){
     94 	unsigned char buf[64];
     95 	int n = 0;
     96 #if TRACE_JTAG
     97 	fprintf(stderr,"move: %08x (%d)\n", bits, count);
     98 #endif
     99 	while (count-- > 0) {
    100 		if (bits & 1) {
    101 			buf[n++] = UB_TMS;
    102 			buf[n++] = UB_TMS | UB_TCK;
    103 		} else {
    104 			buf[n++] = 0;
    105 			buf[n++] = UB_TCK;
    106 		}
    107 		bits >>= 1;
    108 	}
    109 	return usb_bulk(EP2_OUT, buf, n, 1000);
    110 }
    111 
    112 int jtag_shift(int count, unsigned bits, unsigned *out) {
    113 	unsigned char buf[64];
    114 	unsigned RB = out ? UB_READBACK : 0;
    115 	int n = 0;
    116 	int readcount = count;
    117 	int r,bit;
    118 #if TRACE_JTAG
    119 	fprintf(stderr,"xfer: %08x (%d)\n", bits, count);
    120 #endif
    121 	while (count-- > 0) {
    122 		if (bits & 1) {
    123 			buf[n++] = UB_TDI;
    124 			buf[n++] = UB_TDI | UB_TCK | RB;
    125 		} else {
    126 			buf[n++] = 0;
    127 			buf[n++] = UB_TCK | RB;
    128 		}
    129 		bits >>= 1;
    130 	}
    131 	buf[n-1] |= UB_TMS;
    132 	buf[n-2] |= UB_TMS;
    133 	r = usb_bulk(EP2_OUT, buf, n, 1000);
    134 	if (r < 0)
    135 		return r;
    136 	if (!out)
    137 		return 0;
    138 	bits = 0;
    139 	bit = 1;
    140 	while (readcount > 0) {
    141 		r = usb_bulk(EP1_IN, buf, 64, 1000);
    142 		if (r < 0)
    143 			return r;
    144 		if (r < 3)
    145 			continue;
    146 		for (n = 2; n < r; n++) {
    147 			if (buf[n] & 1)
    148 				bits |= bit;
    149 			bit <<= 1;
    150 			readcount--;
    151 			if (readcount == 0) {
    152 #if TRACE_JTAG
    153 				fprintf(stderr,"    : %08x\n", bits);
    154 #endif
    155 				*out = bits;
    156 				return 0;
    157 			}
    158 		}
    159 	}
    160 	return -1;
    161 }
    162 
    163 /* JTAG notes
    164  *
    165  * TMS is sampled on +TCK
    166  * Capture-XR state loads shift register on +TCK as state is exited
    167  * Shift-XR state TDO goes active (containing shiftr[0]) on the first -TCK
    168  *          after entry, shifts occur on each +TCK, *including* the +TCK
    169  *          that will exist Shift-XR when TMS=1 again
    170  * Update-XR update occurs on the -TCK after entry to state
    171  * 
    172  * Any -> Reset: 11111
    173  * Any -> Reset -> RTI: 111110
    174  * RTI -> ShiftDR: 100
    175  * ShiftDR shifting: 0 x N
    176  * ShiftDR -> UpdateDR -> RTI: 110
    177  * ShiftDR -> UpdateDR -> ShiftDR: 11100
    178  * RTI -> ShiftIR: 1100
    179  * ShiftIR shifting: 0 x N
    180  * ShiftIR -> UpdateIR -> RTI: 110
    181  */
    182 
    183 #define RESET	8,0b01111111
    184 #define SHIFTDR	3,0b001
    185 #define SHIFTIR	4,0b0011
    186 #define DONE	2,0b01
    187 #define AGAIN	4,0b0011
    188 
    189 int jtag_ir(unsigned sz, unsigned bits) {
    190 	int r;
    191 	if ((r = jtag_move(SHIFTIR)) < 0) return r;
    192 	if ((r = jtag_shift(sz, bits, 0)) < 0) return r;
    193 	if ((r = jtag_move(DONE)) < 0) return r;
    194 	return 0;
    195 }
    196 
    197 int jtag_dr(unsigned sz, unsigned bits, unsigned *out) {
    198 	int r;
    199 	if ((r = jtag_move(SHIFTDR)) < 0) return r;
    200 	if ((r = jtag_shift(sz, bits, out)) < 0) return r;
    201 	if ((r = jtag_move(DONE)) < 0) return r;
    202 	return 0;
    203 }
    204 
    205 static int jtag_is_open = 0;
    206 
    207 int jtag_open(void) {
    208 	int r;
    209 	if (!jtag_is_open) {
    210 		r = usb_open(0x09fb, 0x6001);
    211 		if (r < 0)
    212 			return r;
    213 		jtag_is_open = 1;
    214 	}
    215 	return 0;
    216 }
    217 int jtag_close(void) {
    218 	if (jtag_is_open) {
    219 		usb_close();
    220 		jtag_is_open = 0;
    221 	}
    222 	return 0;
    223 }
    224 int jtag_reset(void) {
    225 	return jtag_move(RESET);
    226 }
    227