Support for new DirtyJtag2 protocol. Merged with head
This commit is contained in:
parent
43caa612ca
commit
9ee8e84fba
|
|
@ -23,17 +23,33 @@
|
|||
#include <map>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <cassert>
|
||||
|
||||
#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,32 +237,52 @@ 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;
|
||||
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;
|
||||
memset(tx_buf + 2, 0, 30);
|
||||
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;
|
||||
|
||||
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, 32, &actual_length, 1000);
|
||||
rx_buf, transfer_length, &actual_length, 1000);
|
||||
if (ret < 0) {
|
||||
cerr << "writeTDI: read: usb bulk write failed " << ret << endl;
|
||||
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) {
|
||||
for (int i = 0; i < bit_to_send; i++)
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
do {
|
||||
if (libusb_bulk_transfer(dev_handle, DIRTYJTAG_READ_EP,
|
||||
read, 1, &actual_length, 1000) < 0) {
|
||||
cerr << "sendBitBang: usb bulk write failed 4" << endl;
|
||||
cerr << "sendBitBang: usb bulk read failed 4" << endl;
|
||||
return -EXIT_FAILURE;
|
||||
}
|
||||
} while (actual_length == 0);
|
||||
}
|
||||
|
||||
if (last) {
|
||||
|
|
|
|||
|
|
@ -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_
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue