Line 24... |
Line 24... |
#include <string.h> // for memcpy()
|
#include <string.h> // for memcpy()
|
|
|
#include "usb.h" // libusb header
|
#include "usb.h" // libusb header
|
|
|
#include "cable_usbblaster.h"
|
#include "cable_usbblaster.h"
|
|
#include "utilities.h"
|
#include "errcodes.h"
|
#include "errcodes.h"
|
|
|
#define debug(...) //fprintf(stderr, __VA_ARGS__ )
|
#define debug(...) //fprintf(stderr, __VA_ARGS__ )
|
|
|
jtag_cable_t usbblaster_cable_driver = {
|
jtag_cable_t usbblaster_cable_driver = {
|
Line 78... |
Line 79... |
#define USBBLASTER_MAX_WRITE 63
|
#define USBBLASTER_MAX_WRITE 63
|
static char data_out_scratchpad[USBBLASTER_MAX_WRITE+1];
|
static char data_out_scratchpad[USBBLASTER_MAX_WRITE+1];
|
#define USBBLASTER_MAX_READ 62
|
#define USBBLASTER_MAX_READ 62
|
static char data_in_scratchpad[USBBLASTER_MAX_READ+2];
|
static char data_in_scratchpad[USBBLASTER_MAX_READ+2];
|
|
|
|
// Flag used to avoid unnecessary transfers
|
|
// Since clock is lowered if high (and never the other way around),
|
|
// 1 is a safe default value.
|
|
static unsigned char clock_is_high = 1;
|
|
|
int cable_usbblaster_open_cable(void);
|
int cable_usbblaster_open_cable(void);
|
void cable_usbblaster_close_cable(void);
|
void cable_usbblaster_close_cable(void);
|
//int cable_usbblaster_reopen_cable(void);
|
//int cable_usbblaster_reopen_cable(void);
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
Line 246... |
Line 252... |
if (rv != 1){
|
if (rv != 1){
|
fprintf(stderr, "\nFailed to write to the FIFO (rv = %d):\n%s", rv, usb_strerror());
|
fprintf(stderr, "\nFailed to write to the FIFO (rv = %d):\n%s", rv, usb_strerror());
|
err |= APP_ERR_USB;
|
err |= APP_ERR_USB;
|
}
|
}
|
|
|
|
if(value & TCLK_BIT)
|
|
{
|
|
clock_is_high = 1;
|
|
}
|
|
else
|
|
{
|
|
clock_is_high = 0;
|
|
}
|
|
|
return err;
|
return err;
|
}
|
}
|
|
|
|
|
int cable_usbblaster_inout(uint8_t value, uint8_t *in_bit)
|
int cable_usbblaster_inout(uint8_t value, uint8_t *in_bit)
|
Line 282... |
Line 297... |
fprintf(stderr, "\nFailed to write a read request to the EP2 FIFO:\n%s", usb_strerror());
|
fprintf(stderr, "\nFailed to write a read request to the EP2 FIFO:\n%s", usb_strerror());
|
cable_usbblaster_close_cable();
|
cable_usbblaster_close_cable();
|
return APP_ERR_USB;
|
return APP_ERR_USB;
|
}
|
}
|
|
|
|
if(value & TCLK_BIT)
|
|
{
|
|
clock_is_high = 1;
|
|
}
|
|
else
|
|
{
|
|
clock_is_high = 0;
|
|
}
|
|
|
// receive the response
|
// receive the response
|
// Sometimes, we do a read but just get the useless 0x31,0x60 chars...
|
// Sometimes, we do a read but just get the useless 0x31,0x60 chars...
|
// retry until we get a 3rd byte (with real data), for a reasonable number of retries.
|
// retry until we get a 3rd byte (with real data), for a reasonable number of retries.
|
int retries = 0;
|
int retries = 0;
|
Line 337... |
Line 360... |
if(bytes_to_transfer == 0) {
|
if(bytes_to_transfer == 0) {
|
return cable_common_write_stream(stream, len_bits, set_last_bit);
|
return cable_common_write_stream(stream, len_bits, set_last_bit);
|
}
|
}
|
|
|
// Bitbang functions leave clock high. USBBlaster assumes clock low at the start of a burst.
|
// Bitbang functions leave clock high. USBBlaster assumes clock low at the start of a burst.
|
|
if(clock_is_high)
|
|
{
|
err |= cable_usbblaster_out(0); // Lower the clock.
|
err |= cable_usbblaster_out(0); // Lower the clock.
|
|
}
|
|
|
// Set leftover bits
|
// Set leftover bits
|
leftover_bits = (stream[bytes_to_transfer>>2] >> ((bytes_to_transfer & 0x3) * 8)) & 0xFF;
|
leftover_bits = (stream[bytes_to_transfer>>2] >> ((bytes_to_transfer & 0x3) * 8)) & 0xFF;
|
|
|
debug("leftover_bits: 0x%X, LSB_first_xfer = %d\n", leftover_bits, LSB_first_xfer);
|
debug("leftover_bits: 0x%X, LSB_first_xfer = %d\n", leftover_bits, LSB_first_xfer);
|
Line 375... |
Line 401... |
|
|
bytes_remaining -= bytes_this_xfer;
|
bytes_remaining -= bytes_this_xfer;
|
xfer_ptr += bytes_this_xfer;
|
xfer_ptr += bytes_this_xfer;
|
}
|
}
|
|
|
|
clock_is_high = 0;
|
|
|
// if we have a number of bits not divisible by 8, or we need to set TMS...
|
// if we have a number of bits not divisible by 8, or we need to set TMS...
|
if(leftover_bit_length != 0) {
|
if(leftover_bit_length != 0) {
|
//printf("Doing leftovers: (0x%X, %d, %d)\n", leftover_bits, leftover_bit_length, set_last_bit);
|
//printf("Doing leftovers: (0x%X, %d, %d)\n", leftover_bits, leftover_bit_length, set_last_bit);
|
return cable_common_write_stream(&leftover_bits, leftover_bit_length, set_last_bit);
|
return cable_common_write_stream(&leftover_bits, leftover_bit_length, set_last_bit);
|
}
|
}
|
Line 416... |
Line 444... |
if(bytes_to_transfer == 0) {
|
if(bytes_to_transfer == 0) {
|
return cable_common_read_stream(outstream, instream, len_bits, set_last_bit);
|
return cable_common_read_stream(outstream, instream, len_bits, set_last_bit);
|
}
|
}
|
|
|
// Bitbang functions leave clock high. USBBlaster assumes clock low at the start of a burst.
|
// Bitbang functions leave clock high. USBBlaster assumes clock low at the start of a burst.
|
|
if(clock_is_high)
|
|
{
|
// Lower the clock.
|
// Lower the clock.
|
retval |= cable_usbblaster_out(0);
|
retval |= cable_usbblaster_out(0);
|
|
}
|
|
|
// Zero the input, since we add new data by logical-OR
|
// Zero the input, since we add new data by logical-OR
|
for(i = 0; i < (len_bits/32); i++) instream[i] = 0;
|
for(i = 0; i < (len_bits/32); i++) instream[i] = 0;
|
if(len_bits % 32) instream[i] = 0;
|
if(len_bits % 32) instream[i] = 0;
|
|
|
Line 493... |
Line 524... |
|
|
bytes_remaining -= bytes_this_xfer;
|
bytes_remaining -= bytes_this_xfer;
|
xfer_ptr += bytes_this_xfer;
|
xfer_ptr += bytes_this_xfer;
|
}
|
}
|
|
|
|
clock_is_high = 0;
|
|
|
// if we have a number of bits not divisible by 8
|
// if we have a number of bits not divisible by 8
|
if(leftover_bit_length != 0) {
|
if(leftover_bit_length != 0) {
|
debug("Doing leftovers: (0x%X, %d, %d)\n", leftover_bits, leftover_bit_length, set_last_bit);
|
debug("Doing leftovers: (0x%X, %d, %d)\n", leftover_bits, leftover_bit_length, set_last_bit);
|
retval |= cable_common_read_stream(&leftover_bits, &leftovers_received, leftover_bit_length, set_last_bit);
|
retval |= cable_common_read_stream(&leftover_bits, &leftovers_received, leftover_bit_length, set_last_bit);
|
instream[bytes_to_transfer>>2] |= (leftovers_received & 0xFF) << (8*(bytes_to_transfer & 0x3));
|
instream[bytes_to_transfer>>2] |= (leftovers_received & 0xFF) << (8*(bytes_to_transfer & 0x3));
|
Line 544... |
Line 577... |
}
|
}
|
|
|
|
|
int cable_usbblaster_open_cable(void)
|
int cable_usbblaster_open_cable(void)
|
{
|
{
|
|
int if_not_claimed = 1;
|
|
timeout_timer timer;
|
|
|
// open the device
|
// open the device
|
h_device = usb_open(usbblaster_device);
|
h_device = usb_open(usbblaster_device);
|
if (h_device == NULL){
|
if (h_device == NULL){
|
fprintf(stderr, "USBBlaster driver failed to open device\n");
|
fprintf(stderr, "USBBlaster driver failed to open device\n");
|
return APP_ERR_USB;
|
return APP_ERR_USB;
|
Line 561... |
Line 597... |
fprintf(stderr, "USBBlaster driver failed to set configuration\n");
|
fprintf(stderr, "USBBlaster driver failed to set configuration\n");
|
return APP_ERR_USB;
|
return APP_ERR_USB;
|
}
|
}
|
|
|
// wait until device is ready
|
// wait until device is ready
|
// *** TODO: add timeout
|
if ( create_timer(&timer) )
|
|
{
|
|
fprintf(stderr, "Failed to create timer\n");
|
|
// fall back to infinite wait
|
while (usb_claim_interface(h_device, usbblaster_device->config->interface->altsetting->bInterfaceNumber));
|
while (usb_claim_interface(h_device, usbblaster_device->config->interface->altsetting->bInterfaceNumber));
|
|
}
|
|
else
|
|
{
|
|
while (if_not_claimed && !timedout(&timer) )
|
|
if_not_claimed = usb_claim_interface(h_device, usbblaster_device->config->interface->altsetting->bInterfaceNumber);
|
|
|
|
if ( timedout(&timer) )
|
|
{
|
|
fprintf(stderr, "Claiming interface timed out...\n");
|
|
return APP_ERR_USB;
|
|
}
|
|
}
|
|
|
return APP_ERR_NONE;
|
return APP_ERR_NONE;
|
}
|
}
|
|
|
|
|