diff --git a/src/dirtyJtag.cpp b/src/dirtyJtag.cpp index d7512f4..5e280a2 100644 --- a/src/dirtyJtag.cpp +++ b/src/dirtyJtag.cpp @@ -23,17 +23,33 @@ #include #include #include +#include #include "dirtyJtag.hpp" #include "display.hpp" using namespace std; +//#define DIRTY_JTAG_TEENSY_4 + +#ifdef DIRTY_JTAG_TEENSY_4 + +#define DIRTYJTAG_VID 0x16C0 +#define DIRTYJTAG_PID 0x1485 + +#define DIRTYJTAG_INTF 0 +#define DIRTYJTAG_WRITE_EP 0x2 +#define DIRTYJTAG_READ_EP 0x82 + +#else #define DIRTYJTAG_VID 0x1209 #define DIRTYJTAG_PID 0xC0CA +#define DIRTYJTAG_INTF 0 #define DIRTYJTAG_WRITE_EP 0x01 #define DIRTYJTAG_READ_EP 0x82 +#endif + enum dirtyJtagCmd { CMD_STOP = 0x00, @@ -45,6 +61,11 @@ enum dirtyJtagCmd { CMD_CLK = 0x06 }; +enum CommandModifier { + EXTEND_LENGTH = 0x40, + NO_READ = 0x80 +}; + enum dirtyJtagSig { SIG_TCK = (1 << 1), SIG_TDI = (1 << 2), @@ -71,14 +92,17 @@ DirtyJtag::DirtyJtag(uint32_t clkHZ, bool verbose): throw std::exception(); } - ret = libusb_claim_interface(dev_handle, 0); + ret = libusb_claim_interface(dev_handle, DIRTYJTAG_INTF); if (ret) { - cerr << "libusb error while claiming DirtyJTAG interface #0" << endl; + cerr << "libusb error while claiming DirtyJTAG interface" << endl; libusb_close(dev_handle); libusb_exit(usb_ctx); throw std::exception(); } + _version = 0; + getVersion(); + if (setClkFreq(clkHZ) < 0) { cerr << "Fail to set frequency" << endl; throw std::exception(); @@ -93,14 +117,50 @@ DirtyJtag::~DirtyJtag() libusb_exit(usb_ctx); } +void DirtyJtag::getVersion() +{ + int actual_length; + int ret; + uint8_t buf[] = {CMD_INFO, + CMD_STOP}; + uint8_t rx_buf[64]; + ret = libusb_bulk_transfer(dev_handle, DIRTYJTAG_WRITE_EP, + buf, 2, &actual_length, 1000); + if (ret < 0) { + cerr << "getVersion: usb bulk write failed " << ret << endl; + return; + } + do { + ret = libusb_bulk_transfer(dev_handle, DIRTYJTAG_READ_EP, + rx_buf, 64, &actual_length, 1000); + if (ret < 0) { + cerr << "getVersion: read: usb bulk read failed " << ret << endl; + return; + } + } while (actual_length == 0); + if (!strncmp("DJTAG1\n", (char*)rx_buf, 7)) { + _version = 1; + } else if (!strncmp("DJTAG2\n", (char*)rx_buf, 7)) { + _version = 2; + } else if (!strncmp("DJTAG3\n", (char*)rx_buf, 7)) { + _version = 3; + } else { + cerr << "dirtyJtag version unknown" << endl; + _version = 0; + } + +} + + + int DirtyJtag::setClkFreq(uint32_t clkHZ) { int actual_length; int ret, req_freq = clkHZ; - if (clkHZ > 600000) { - printWarn("DirtyJTAG probe limited to 600kHz"); - clkHZ = 600000; + if (clkHZ > 16000000) { + printWarn("DirtyJTAG probe limited to 16000kHz"); + clkHZ = 16000000; } printInfo("Jtag frequency : requested " + std::to_string(req_freq) + @@ -142,7 +202,7 @@ int DirtyJtag::toggleClk(uint8_t tms, uint8_t tdi, uint32_t clk_len) 0, CMD_STOP}; while (clk_len > 0) { - buf[2] = (clk_len > 100) ? 100 : (uint8_t)clk_len; + buf[2] = (clk_len > 64) ? 64 : (uint8_t)clk_len; int ret = libusb_bulk_transfer(dev_handle, DIRTYJTAG_WRITE_EP, buf, 4, &actual_length, 1000); @@ -168,7 +228,7 @@ int DirtyJtag::writeTDI(uint8_t *tx, uint8_t *rx, uint32_t len, bool end) uint32_t real_byte_len = (len + 7) / 8; uint8_t tx_cpy[real_byte_len]; - uint8_t tx_buf[33], rx_buf[32]; + uint8_t tx_buf[512], rx_buf[512]; uint8_t *tx_ptr = tx, *rx_ptr = rx; if (tx) @@ -177,31 +237,51 @@ int DirtyJtag::writeTDI(uint8_t *tx, uint8_t *rx, uint32_t len, bool end) memset(tx_cpy, 0, real_byte_len); tx_ptr = tx_cpy; - /* first send 30 x 8 bits */ - tx_buf[0] = CMD_XFER; + tx_buf[0] = CMD_XFER | ((rx || (_version <= 1)) ? 0 : NO_READ); + uint16_t max_bit_transfer_length = (uint16_t[]){240, 496, 4000}[_version -1]; + assert(max_bit_transfer_length %8 == 0);//need to cut the bits on byte size. while (real_bit_len != 0) { - uint8_t bit_to_send = (real_bit_len > 240) ? 240 : real_bit_len; - uint8_t byte_to_send = (bit_to_send + 7) / 8; - tx_buf[1] = bit_to_send; - memset(tx_buf + 2, 0, 30); + uint16_t bit_to_send = (real_bit_len > max_bit_transfer_length) ? max_bit_transfer_length : real_bit_len; + size_t byte_to_send = (bit_to_send + 7) / 8; + size_t header_offset = 0; + if (_version == 3) { + tx_buf[1] = (bit_to_send >> 8) & 0xFF; + tx_buf[2] = bit_to_send & 0xFF; + header_offset = 3; + } else if (bit_to_send > 255) { + tx_buf[0] |= EXTEND_LENGTH; + tx_buf[1] = bit_to_send - 256; + header_offset = 2; + }else { + tx_buf[0] &= ~EXTEND_LENGTH; + tx_buf[1] = bit_to_send; + header_offset = 2; + } + memset(tx_buf + header_offset, 0, byte_to_send); for (int i = 0; i < bit_to_send; i++) if (tx_ptr[i >> 3] & (1 << (i & 0x07))) - tx_buf[2 + (i >> 3)] |= (0x80 >> (i & 0x07)); - - tx_buf[2 + byte_to_send] = CMD_STOP; - + tx_buf[header_offset + (i >> 3)] |= (0x80 >> (i & 0x07)); + + actual_length = 0; int ret = libusb_bulk_transfer(dev_handle, DIRTYJTAG_WRITE_EP, - (unsigned char *)tx_buf, 33, &actual_length, 1000); - if (ret < 0) { - cerr << "writeTDI: fill: usb bulk write failed " << ret << endl; + (unsigned char *)tx_buf, (byte_to_send + header_offset), &actual_length, 1000); + if ((ret < 0) || (actual_length != (int)(byte_to_send + header_offset))) { + cerr << "writeTDI: fill: usb bulk write failed " << actual_length << endl; return EXIT_FAILURE; } + //cerr << actual_length << ", " << bit_to_send << endl; - ret = libusb_bulk_transfer(dev_handle, DIRTYJTAG_READ_EP, - rx_buf, 32, &actual_length, 1000); - if (ret < 0) { - cerr << "writeTDI: read: usb bulk write failed " << ret << endl; - return EXIT_FAILURE; + if (rx || (_version <= 1)) { + int transfer_length = (bit_to_send > 255) ? byte_to_send :32; + do { + ret = libusb_bulk_transfer(dev_handle, DIRTYJTAG_READ_EP, + rx_buf, transfer_length, &actual_length, 1000); + if (ret < 0) { + cerr << "writeTDI: read: usb bulk read failed " << ret << endl; + return EXIT_FAILURE; + } + } while (actual_length == 0); + assert((size_t)actual_length >= byte_to_send); } if (rx) { @@ -223,7 +303,7 @@ int DirtyJtag::writeTDI(uint8_t *tx, uint8_t *rx, uint32_t len, bool end) (tx_cpy[pos >> 3] & (1 << (pos & 0x07))) ? SIG_TDI: 0; if (sendBitBang(SIG_TMS | SIG_TDI, - SIG_TMS | (last_bit), &sig, true) != 0) { + SIG_TMS | (last_bit), (rx ? &sig : 0), true) != 0) { cerr << "writeTDI: last bit error" << endl; return -EXIT_FAILURE; } @@ -235,6 +315,7 @@ int DirtyJtag::writeTDI(uint8_t *tx, uint8_t *rx, uint32_t len, bool end) } } } + return EXIT_SUCCESS; } @@ -264,11 +345,13 @@ int DirtyJtag::sendBitBang(uint8_t mask, uint8_t val, uint8_t *read, bool last) return -EXIT_FAILURE; } - if (libusb_bulk_transfer(dev_handle, DIRTYJTAG_READ_EP, - read, 1, &actual_length, 1000) < 0) { - cerr << "sendBitBang: usb bulk write failed 4" << endl; - return -EXIT_FAILURE; - } + do { + if (libusb_bulk_transfer(dev_handle, DIRTYJTAG_READ_EP, + read, 1, &actual_length, 1000) < 0) { + cerr << "sendBitBang: usb bulk read failed 4" << endl; + return -EXIT_FAILURE; + } + } while (actual_length == 0); } if (last) { diff --git a/src/dirtyJtag.hpp b/src/dirtyJtag.hpp index 515958f..249d822 100644 --- a/src/dirtyJtag.hpp +++ b/src/dirtyJtag.hpp @@ -58,10 +58,13 @@ class DirtyJtag : public JtagInterface { bool _verbose; int sendBitBang(uint8_t mask, uint8_t val, uint8_t *read, bool last); + void getVersion(); libusb_device_handle *dev_handle; libusb_context *usb_ctx; uint8_t _tdi; uint8_t _tms; + uint8_t _version; + }; #endif // SRC_DIRTYJTAG_HPP_ diff --git a/src/ftdiJtagBitbang.cpp b/src/ftdiJtagBitbang.cpp index ee33c56..d4cd946 100644 --- a/src/ftdiJtagBitbang.cpp +++ b/src/ftdiJtagBitbang.cpp @@ -107,8 +107,7 @@ int FtdiJtagBitBang::setBitmode(uint8_t mode) _bitmode = mode; int ret = ftdi_set_bitmode(_ftdi, _tck_pin | _tms_pin | _tdi_pin, _bitmode); - ftdi_usb_purge_rx_buffer(_ftdi); - ftdi_usb_purge_tx_buffer(_ftdi); + ftdi_tcioflush(_ftdi); return ret; }