diff --git a/src/cable.hpp b/src/cable.hpp index f2cf2df..ee346cf 100644 --- a/src/cable.hpp +++ b/src/cable.hpp @@ -38,6 +38,7 @@ typedef struct { int bit_high_val; /*! xCBUS 0-7 default value */ int bit_high_dir; /*! xCBUS 0-7 default direction (0: in, 1: out) */ int index; + int status_pin; } mpsse_bit_config; /*! @@ -64,10 +65,10 @@ struct cable_t { /* FTDI serial (MPSSE) configuration */ #define FTDI_SER(_vid, _pid, _intf, _blv, _bld, _bhv, _bhd) \ - {MODE_FTDI_SERIAL, _vid, _pid, 0, 0, {_intf, _blv, _bld, _bhv, _bhd, 0}} + {MODE_FTDI_SERIAL, _vid, _pid, 0, 0, {_intf, _blv, _bld, _bhv, _bhd, 0, -1}} /* FTDI bitbang configuration */ #define FTDI_BB(_vid, _pid, _intf, _blv, _bld, _bhv, _bhd) \ - {MODE_FTDI_BITBANG, _vid, _pid, 0, 0, {_intf, _blv, _bld, _bhv, _bhd, 0}} + {MODE_FTDI_BITBANG, _vid, _pid, 0, 0, {_intf, _blv, _bld, _bhv, _bhd, 0, -1}} /* CMSIS DAP configuration */ #define CMSIS_CL(_vid, _pid) \ {MODE_CMSISDAP, _vid, _pid, 0, 0, {}} diff --git a/src/ftdipp_mpsse.cpp b/src/ftdipp_mpsse.cpp index cef14c7..646bc37 100644 --- a/src/ftdipp_mpsse.cpp +++ b/src/ftdipp_mpsse.cpp @@ -31,6 +31,7 @@ FTDIpp_MPSSE::FTDIpp_MPSSE(const cable_t &cable, const string &dev, _verbose(verbose > 2), _cable(cable.config), _vid(0), _pid(0), _index(0), _bus(cable.bus_addr), _addr(cable.device_addr), + _bitmode(BITMODE_RESET), _interface(cable.config.interface), _clkHZ(clkHZ), _buffer_size(2*32768), _num(0) { @@ -96,6 +97,13 @@ FTDIpp_MPSSE::~FTDIpp_MPSSE() { char err[256]; int ret; + + if (_bitmode == BITMODE_MPSSE) { + if (_cable.status_pin != -1) { + gpio_set(1 << _cable.status_pin); + } + } + if ((ret = ftdi_set_bitmode(_ftdi, 0, BITMODE_RESET)) < 0) { snprintf(err, sizeof(err), "unable to config pins : %d %s", ret, ftdi_get_error_string(_ftdi)); @@ -278,6 +286,16 @@ int FTDIpp_MPSSE::init(unsigned char latency, unsigned char bitmask_mode, if (setClkFreq(_clkHZ) < 0) return -1; + if (_cable.status_pin != -1) { + if (_cable.status_pin <= 7) { + _cable.bit_low_dir |= 1 << _cable.status_pin; + _cable.bit_low_val &= ~(1 << _cable.status_pin); + } else { + _cable.bit_high_dir |= 1 << (_cable.status_pin - 8); + _cable.bit_high_val &= ~(1 << (_cable.status_pin - 8)); + } + } + int to_wr = 3; buf_cmd[1] = _cable.bit_low_val; // 0xe8; @@ -311,6 +329,7 @@ int FTDIpp_MPSSE::init(unsigned char latency, unsigned char bitmask_mode, return -1; } + _bitmode = mode; return 0; } diff --git a/src/ftdipp_mpsse.hpp b/src/ftdipp_mpsse.hpp index 97709c1..4f47c9f 100644 --- a/src/ftdipp_mpsse.hpp +++ b/src/ftdipp_mpsse.hpp @@ -69,6 +69,7 @@ class FTDIpp_MPSSE { private: uint8_t _bus; uint8_t _addr; + uint8_t _bitmode; char _product[64]; unsigned char _interface; /* gpio */ diff --git a/src/main.cpp b/src/main.cpp index 2667bd5..e1ad65d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -52,6 +52,7 @@ struct arguments { string cable; string ftdi_serial; int ftdi_channel; + int status_pin; uint32_t freq; bool invert_read_edge; string board; @@ -108,7 +109,7 @@ int main(int argc, char **argv) /* command line args. */ struct arguments args = {0, false, false, false, false, 0, "", "", "", "-", "", -1, - 0, false, "-", false, false, false, false, Device::PRG_NONE, false, + -1, 0, false, "-", false, false, false, false, Device::PRG_NONE, false, /* spi dfu file_type fpga_part bridge_path probe_firmware */ false, false, "", "", "", "", /* index_chain file_size target_flash external_flash altsetting */ @@ -220,6 +221,13 @@ int main(int argc, char **argv) } } + if (args.status_pin != -1) { + if (cable.type != MODE_FTDI_SERIAL){ + printError("Error: FTDI status pin is for FTDI MPSSE cables."); + return EXIT_FAILURE; + } + } + if (args.vid != 0) { printInfo("Cable VID overridden"); cable.vid = args.vid; @@ -232,8 +240,9 @@ int main(int argc, char **argv) cable.bus_addr = args.bus_addr; cable.device_addr = args.device_addr; - // always set this + // always set these cable.config.index = args.cable_index; + cable.config.status_pin = args.status_pin; /* FLASH direct access */ if (args.spi || (board && board->mode == COMM_SPI)) { @@ -701,6 +710,9 @@ int parse_opt(int argc, char **argv, struct arguments *args, "bitstream(intel/xilinx)", cxxopts::value(args->bridge_path)) ("c,cable", "jtag interface", cxxopts::value(args->cable)) + ("status-pin", + "JTAG mode / FTDI: GPIO pin number to use as a status indicator (active low)", + cxxopts::value(args->status_pin)) ("invert-read-edge", "JTAG mode / FTDI: read on negative edge instead of positive", cxxopts::value(args->invert_read_edge)) @@ -857,6 +869,13 @@ int parse_opt(int argc, char **argv, struct arguments *args, args->freq = static_cast(freq); } + if (result.count("status-pin")) { + if (args->status_pin < 4 || args->status_pin > 15) { + printError("Error: valid status pin numbers are 4-15."); + throw std::exception(); + } + } + if (result.count("ftdi-channel")) { if (args->ftdi_channel < 0 || args->ftdi_channel > 3) { printError("Error: valid FTDI channels are 0-3.");