From a03e73eeb01cdba232f98bf63fdd18e2feddb3a9 Mon Sep 17 00:00:00 2001 From: makestuff Date: Sun, 17 Mar 2013 18:37:45 +0000 Subject: [PATCH] Moved useful JTAG stuff from nero.c into jtag.c --- jtag.c | 198 ++++++++++++++++++++++++++++++++++++++++- nero.c | 275 --------------------------------------------------------- 2 files changed, 196 insertions(+), 277 deletions(-) diff --git a/jtag.c b/jtag.c index c678aa2..d554881 100644 --- a/jtag.c +++ b/jtag.c @@ -23,14 +23,208 @@ #include "libfpgalink.h" #include "private.h" #include "csvfplay.h" +#include "vendorCommands.h" #include "prog.h" -NeroStatus beginShift( +static NeroStatus beginShift( struct FLContext *handle, uint32 numBits, ProgOp progOp, uint8 mode, const char **error); -NeroStatus doSend( +static NeroStatus doSend( struct FLContext *handle, const uint8 *sendPtr, uint16 chunkSize, const char **error); +static NeroStatus doReceive( + struct FLContext *handle, uint8 *receivePtr, uint16 chunkSize, const char **error); + + + + +// Shift data into and out of JTAG chain. +// In pointer may be ZEROS (shift in zeros) or ONES (shift in ones). +// Out pointer may be NULL (not interested in data shifted out of the chain). +// +NeroStatus neroShift( + struct FLContext *handle, uint32 numBits, const uint8 *inData, uint8 *outData, bool isLast, + const char **error) +{ + NeroStatus returnCode, nStatus; + uint32 numBytes = bitsToBytes(numBits); + uint16 chunkSize; + uint8 mode = 0x00; + bool isSending = false; + + if ( inData == ONES ) { + mode |= bmSENDONES; + } else if ( inData != ZEROS ) { + isSending = true; + } + if ( isLast ) { + mode |= bmISLAST; + } + if ( isSending ) { + if ( outData ) { + nStatus = beginShift(handle, numBits, PROG_JTAG_ISSENDING_ISRECEIVING, mode, error); + CHECK_STATUS(nStatus, "neroShift()", NERO_BEGIN_SHIFT); + while ( numBytes ) { + chunkSize = (numBytes >= 64) ? 64 : (uint16)numBytes; + nStatus = doSend(handle, inData, chunkSize, error); + CHECK_STATUS(nStatus, "neroShift()", NERO_SEND); + inData += chunkSize; + nStatus = doReceive(handle, outData, chunkSize, error); + CHECK_STATUS(nStatus, "neroShift()", NERO_RECEIVE); + outData += chunkSize; + numBytes -= chunkSize; + } + } else { + nStatus = beginShift(handle, numBits, PROG_JTAG_ISSENDING_NOTRECEIVING, mode, error); + CHECK_STATUS(nStatus, "neroShift()", NERO_BEGIN_SHIFT); + while ( numBytes ) { + chunkSize = (numBytes >= 64) ? 64 : (uint16)numBytes; + nStatus = doSend(handle, inData, chunkSize, error); + CHECK_STATUS(nStatus, "neroShift()", NERO_SEND); + inData += chunkSize; + numBytes -= chunkSize; + } + } + } else { + if ( outData ) { + nStatus = beginShift(handle, numBits, PROG_JTAG_NOTSENDING_ISRECEIVING, mode, error); + CHECK_STATUS(nStatus, "neroShift()", NERO_BEGIN_SHIFT); + while ( numBytes ) { + chunkSize = (numBytes >= 64) ? 64 : (uint16)numBytes; + nStatus = doReceive(handle, outData, chunkSize, error); + CHECK_STATUS(nStatus, "neroShift()", NERO_RECEIVE); + outData += chunkSize; + numBytes -= chunkSize; + } + } else { + nStatus = beginShift(handle, numBits, PROG_JTAG_NOTSENDING_NOTRECEIVING, mode, error); + CHECK_STATUS(nStatus, "neroShift()", NERO_BEGIN_SHIFT); + } + } + return NERO_SUCCESS; +cleanup: + return returnCode; +} + +// Apply the supplied bit pattern to TMS, to move the TAP to a specific state. +// +NeroStatus neroClockFSM( + struct FLContext *handle, uint32 bitPattern, uint8 transitionCount, const char **error) +{ + NeroStatus returnCode = NERO_SUCCESS; + int uStatus; + union { + uint32 u32; + uint8 bytes[4]; + } lePattern; + lePattern.u32 = littleEndian32(bitPattern); + uStatus = usbControlWrite( + handle->device, + CMD_JTAG_CLOCK_FSM, // bRequest + (uint16)transitionCount, // wValue + 0x0000, // wIndex + lePattern.bytes, // bit pattern + 4, // wLength + 5000, // timeout (ms) + error + ); + CHECK_STATUS(uStatus, "neroClockFSM()", NERO_CLOCKFSM); +cleanup: + return returnCode; +} + +// Cycle the TCK line for the given number of times. +// +NeroStatus neroClocks(struct FLContext *handle, uint32 numClocks, const char **error) { + NeroStatus returnCode = NERO_SUCCESS; + int uStatus = usbControlWrite( + handle->device, + CMD_JTAG_CLOCK, // bRequest + numClocks&0xFFFF, // wValue + numClocks>>16, // wIndex + NULL, // no data + 0, // wLength + 5000, // timeout (ms) + error + ); + CHECK_STATUS(uStatus, "neroClocks()", NERO_CLOCKS); +cleanup: + return returnCode; +} + +// ------------------------------------------------------------------------------------------------- +// Implementation of private functions +// ------------------------------------------------------------------------------------------------- + +// Kick off a shift operation on the micro. This will be followed by a bunch of sends and receives. +// +static NeroStatus beginShift( + struct FLContext *handle, uint32 numBits, ProgOp progOp, uint8 mode, const char **error) +{ + NeroStatus returnCode = NERO_SUCCESS; + int uStatus; + union { + uint32 u32; + uint8 bytes[4]; + } leNumBits; + leNumBits.u32 = littleEndian32(numBits); + uStatus = usbControlWrite( + handle->device, + CMD_JTAG_CLOCK_DATA, // bRequest + (uint8)mode, // wValue + (uint8)progOp, // wIndex + leNumBits.bytes, // send bit count + 4, // wLength + 5000, // timeout (ms) + error + ); + CHECK_STATUS(uStatus, "beginShift()", NERO_BEGIN_SHIFT); +cleanup: + return returnCode; +} + +// Send a chunk of data to the micro. +// +static NeroStatus doSend( + struct FLContext *handle, const uint8 *sendPtr, uint16 chunkSize, const char **error) +{ + NeroStatus returnCode = NERO_SUCCESS; + int uStatus = usbBulkWrite( + handle->device, + handle->jtagOutEP, // write to out endpoint + sendPtr, // write from send buffer + chunkSize, // write this many bytes + 5000, // timeout in milliseconds + error + ); + CHECK_STATUS(uStatus, "doSend()", NERO_SEND); +cleanup: + return returnCode; +} + +// Receive a chunk of data from the micro. +// +static NeroStatus doReceive( + struct FLContext *handle, uint8 *receivePtr, uint16 chunkSize, const char **error) +{ + NeroStatus returnCode = NERO_SUCCESS; + int uStatus = usbBulkRead( + handle->device, + handle->jtagInEP, // read from in endpoint + receivePtr, // read into the receive buffer + chunkSize, // read this many bytes + 5000, // timeout in milliseconds + error + ); + CHECK_STATUS(uStatus, "doReceive()", NERO_RECEIVE); +cleanup: + return returnCode; +} + + + + + #define GET_CHAR(func) \ ch = *ptr; \ if ( ch == '\0' ) { \ diff --git a/nero.c b/nero.c index 7730647..9437460 100644 --- a/nero.c +++ b/nero.c @@ -27,22 +27,6 @@ // Declaration of private types & functions // ------------------------------------------------------------------------------------------------- -NeroStatus beginShift( - struct FLContext *handle, uint32 numBits, ProgOp progOp, uint8 mode, const char **error -) WARN_UNUSED_RESULT; - -NeroStatus doSend( - struct FLContext *handle, const uint8 *sendPtr, uint16 chunkSize, const char **error -) WARN_UNUSED_RESULT; - -static NeroStatus doReceive( - struct FLContext *handle, uint8 *receivePtr, uint16 chunkSize, const char **error -) WARN_UNUSED_RESULT; - -//static NeroStatus setEndpointSize( -// struct NeroContext *handle, const char **error -//) WARN_UNUSED_RESULT; - static NeroStatus setJtagMode( struct FLContext *handle, bool enable, const char **error ) WARN_UNUSED_RESULT; @@ -192,265 +176,6 @@ NeroStatus neroClose(struct FLContext *handle, const char **error) { return returnCode; } -// Shift data into and out of JTAG chain. -// In pointer may be ZEROS (shift in zeros) or ONES (shift in ones). -// Out pointer may be NULL (not interested in data shifted out of the chain). -// -NeroStatus neroShift( - struct FLContext *handle, uint32 numBits, const uint8 *inData, uint8 *outData, bool isLast, - const char **error) -{ - NeroStatus returnCode, nStatus; - uint32 numBytes = bitsToBytes(numBits); - uint16 chunkSize; - uint8 mode = 0x00; - bool isSending = false; - - if ( inData == ONES ) { - mode |= bmSENDONES; - } else if ( inData != ZEROS ) { - isSending = true; - } - if ( isLast ) { - mode |= bmISLAST; - } - if ( isSending ) { - if ( outData ) { - nStatus = beginShift(handle, numBits, PROG_JTAG_ISSENDING_ISRECEIVING, mode, error); - CHECK_STATUS(nStatus, "neroShift()", NERO_BEGIN_SHIFT); - while ( numBytes ) { - chunkSize = (numBytes >= 64) ? 64 : (uint16)numBytes; - nStatus = doSend(handle, inData, chunkSize, error); - CHECK_STATUS(nStatus, "neroShift()", NERO_SEND); - inData += chunkSize; - nStatus = doReceive(handle, outData, chunkSize, error); - CHECK_STATUS(nStatus, "neroShift()", NERO_RECEIVE); - outData += chunkSize; - numBytes -= chunkSize; - } - } else { - nStatus = beginShift(handle, numBits, PROG_JTAG_ISSENDING_NOTRECEIVING, mode, error); - CHECK_STATUS(nStatus, "neroShift()", NERO_BEGIN_SHIFT); - while ( numBytes ) { - chunkSize = (numBytes >= 64) ? 64 : (uint16)numBytes; - nStatus = doSend(handle, inData, chunkSize, error); - CHECK_STATUS(nStatus, "neroShift()", NERO_SEND); - inData += chunkSize; - numBytes -= chunkSize; - } - } - } else { - if ( outData ) { - nStatus = beginShift(handle, numBits, PROG_JTAG_NOTSENDING_ISRECEIVING, mode, error); - CHECK_STATUS(nStatus, "neroShift()", NERO_BEGIN_SHIFT); - while ( numBytes ) { - chunkSize = (numBytes >= 64) ? 64 : (uint16)numBytes; - nStatus = doReceive(handle, outData, chunkSize, error); - CHECK_STATUS(nStatus, "neroShift()", NERO_RECEIVE); - outData += chunkSize; - numBytes -= chunkSize; - } - } else { - nStatus = beginShift(handle, numBits, PROG_JTAG_NOTSENDING_NOTRECEIVING, mode, error); - CHECK_STATUS(nStatus, "neroShift()", NERO_BEGIN_SHIFT); - } - } - return NERO_SUCCESS; -cleanup: - return returnCode; -} - -// Apply the supplied bit pattern to TMS, to move the TAP to a specific state. -// -NeroStatus neroClockFSM( - struct FLContext *handle, uint32 bitPattern, uint8 transitionCount, const char **error) -{ - NeroStatus returnCode = NERO_SUCCESS; - int uStatus; - union { - uint32 u32; - uint8 bytes[4]; - } lePattern; - lePattern.u32 = littleEndian32(bitPattern); - uStatus = usbControlWrite( - handle->device, - CMD_JTAG_CLOCK_FSM, // bRequest - (uint16)transitionCount, // wValue - 0x0000, // wIndex - lePattern.bytes, // bit pattern - 4, // wLength - 5000, // timeout (ms) - error - ); - CHECK_STATUS(uStatus, "neroClockFSM()", NERO_CLOCKFSM); -cleanup: - return returnCode; -} - -// Cycle the TCK line for the given number of times. -// -NeroStatus neroClocks(struct FLContext *handle, uint32 numClocks, const char **error) { - NeroStatus returnCode = NERO_SUCCESS; - int uStatus = usbControlWrite( - handle->device, - CMD_JTAG_CLOCK, // bRequest - numClocks&0xFFFF, // wValue - numClocks>>16, // wIndex - NULL, // no data - 0, // wLength - 5000, // timeout (ms) - error - ); - CHECK_STATUS(uStatus, "neroClocks()", NERO_CLOCKS); -cleanup: - return returnCode; -} - -// ------------------------------------------------------------------------------------------------- -// Implementation of private functions -// ------------------------------------------------------------------------------------------------- - -// Kick off a shift operation on the micro. This will be followed by a bunch of sends and receives. -// -NeroStatus beginShift( - struct FLContext *handle, uint32 numBits, ProgOp progOp, uint8 mode, const char **error) -{ - NeroStatus returnCode = NERO_SUCCESS; - int uStatus; - union { - uint32 u32; - uint8 bytes[4]; - } leNumBits; - leNumBits.u32 = littleEndian32(numBits); - uStatus = usbControlWrite( - handle->device, - CMD_JTAG_CLOCK_DATA, // bRequest - (uint8)mode, // wValue - (uint8)progOp, // wIndex - leNumBits.bytes, // send bit count - 4, // wLength - 5000, // timeout (ms) - error - ); - CHECK_STATUS(uStatus, "beginShift()", NERO_BEGIN_SHIFT); -cleanup: - return returnCode; -} - -// Send a chunk of data to the micro. -// -NeroStatus doSend( - struct FLContext *handle, const uint8 *sendPtr, uint16 chunkSize, const char **error) -{ - NeroStatus returnCode = NERO_SUCCESS; - int uStatus = usbBulkWrite( - handle->device, - handle->jtagOutEP, // write to out endpoint - sendPtr, // write from send buffer - chunkSize, // write this many bytes - 5000, // timeout in milliseconds - error - ); - CHECK_STATUS(uStatus, "doSend()", NERO_SEND); -cleanup: - return returnCode; -} - -// Receive a chunk of data from the micro. -// -static NeroStatus doReceive( - struct FLContext *handle, uint8 *receivePtr, uint16 chunkSize, const char **error) -{ - NeroStatus returnCode = NERO_SUCCESS; - int uStatus = usbBulkRead( - handle->device, - handle->jtagInEP, // read from in endpoint - receivePtr, // read into the receive buffer - chunkSize, // read this many bytes - 5000, // timeout in milliseconds - error - ); - CHECK_STATUS(uStatus, "doReceive()", NERO_RECEIVE); -cleanup: - return returnCode; -} - -/* -// Find the size of the out & in bulk endpoints (they must be the same) -// -static NeroStatus setEndpointSize(struct NeroContext *handle, const char **error) { - NeroStatus returnCode; - int uStatus; - char descriptorBuffer[1024]; // TODO: Fix by doing two queries - char *ptr = descriptorBuffer; - uint8 endpointNum; - uint16 outEndpointSize = 0; - uint16 inEndpointSize = 0; - struct usb_config_descriptor *configDesc; - struct usb_interface_descriptor *interfaceDesc; - struct usb_endpoint_descriptor *endpointDesc; - handle->endpointSize = 0; - uStatus = usb_control_msg( - handle->device, - USB_ENDPOINT_IN | USB_TYPE_STANDARD | USB_RECIP_DEVICE, - USB_REQ_GET_DESCRIPTOR, // bRequest - 0x0200, // wValue - 0x0000, // wIndex - descriptorBuffer, - 1024, // wLength - 5000 // timeout (ms) - ); - if ( uStatus < 0 ) { - errRender( - error, "setEndpointSize(): Failed to get config descriptor: %s (%d)", usb_strerror(), uStatus); - FAIL(NERO_ENDPOINTS); - } - if ( uStatus > 0 ) { - configDesc = (struct usb_config_descriptor *)ptr; - ptr += configDesc->bLength; - interfaceDesc = (struct usb_interface_descriptor *)ptr; - ptr += interfaceDesc->bLength; - endpointNum = interfaceDesc->bNumEndpoints; - while ( endpointNum-- ) { - endpointDesc = (struct usb_endpoint_descriptor *)ptr; - if ( endpointDesc-> bmAttributes == 0x02 ) { - if ( endpointDesc->bEndpointAddress == handle->outEndpoint ) { - outEndpointSize = littleEndian16(endpointDesc->wMaxPacketSize); - } else if ( endpointDesc->bEndpointAddress == (handle->inEndpoint | 0x80) ) { - inEndpointSize = littleEndian16(endpointDesc->wMaxPacketSize); - } - } - ptr += endpointDesc->bLength; - } - } - if ( !outEndpointSize ) { - errRender( - error, "setEndpointSize(): EP%dOUT not found or not configured as a bulk endpoint!", - handle->outEndpoint - ); - FAIL(NERO_ENDPOINTS); - } - if ( !inEndpointSize ) { - errRender( - error, "setEndpointSize(): EP%dIN not found or not configured as a bulk endpoint!", - handle->inEndpoint - ); - FAIL(NERO_ENDPOINTS); - } - if ( outEndpointSize != inEndpointSize ) { - errRender( - error, "setEndpointSize(): EP%dOUT's wMaxPacketSize differs from that of EP%dIN", - handle->outEndpoint, handle->inEndpoint - ); - FAIL(NERO_ENDPOINTS); - } - handle->endpointSize = outEndpointSize; - return NERO_SUCCESS; -cleanup: - return returnCode; -} -*/ - // Put the device in jtag mode (i.e drive or tristate the JTAG lines) // static NeroStatus setJtagMode(struct FLContext *handle, bool enable, const char **error) {