Merge pull request #329 from chenzhuoyu/feat/status_led

FTDI: Adds an option to use an extra GPIO pin as the status indicator
This commit is contained in:
Gwenhael Goavec-Merou 2023-04-11 20:49:17 +02:00 committed by GitHub
commit 3ca60dd14d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 44 additions and 4 deletions

View File

@ -38,6 +38,7 @@ typedef struct {
int bit_high_val; /*! xCBUS 0-7 default value */ int bit_high_val; /*! xCBUS 0-7 default value */
int bit_high_dir; /*! xCBUS 0-7 default direction (0: in, 1: out) */ int bit_high_dir; /*! xCBUS 0-7 default direction (0: in, 1: out) */
int index; int index;
int status_pin;
} mpsse_bit_config; } mpsse_bit_config;
/*! /*!
@ -64,10 +65,10 @@ struct cable_t {
/* FTDI serial (MPSSE) configuration */ /* FTDI serial (MPSSE) configuration */
#define FTDI_SER(_vid, _pid, _intf, _blv, _bld, _bhv, _bhd) \ #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 */ /* FTDI bitbang configuration */
#define FTDI_BB(_vid, _pid, _intf, _blv, _bld, _bhv, _bhd) \ #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 */ /* CMSIS DAP configuration */
#define CMSIS_CL(_vid, _pid) \ #define CMSIS_CL(_vid, _pid) \
{MODE_CMSISDAP, _vid, _pid, 0, 0, {}} {MODE_CMSISDAP, _vid, _pid, 0, 0, {}}

View File

@ -31,6 +31,7 @@ FTDIpp_MPSSE::FTDIpp_MPSSE(const cable_t &cable, const string &dev,
_verbose(verbose > 2), _cable(cable.config), _vid(0), _verbose(verbose > 2), _cable(cable.config), _vid(0),
_pid(0), _index(0), _pid(0), _index(0),
_bus(cable.bus_addr), _addr(cable.device_addr), _bus(cable.bus_addr), _addr(cable.device_addr),
_bitmode(BITMODE_RESET),
_interface(cable.config.interface), _interface(cable.config.interface),
_clkHZ(clkHZ), _buffer_size(2*32768), _num(0) _clkHZ(clkHZ), _buffer_size(2*32768), _num(0)
{ {
@ -96,6 +97,13 @@ FTDIpp_MPSSE::~FTDIpp_MPSSE()
{ {
char err[256]; char err[256];
int ret; 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) { if ((ret = ftdi_set_bitmode(_ftdi, 0, BITMODE_RESET)) < 0) {
snprintf(err, sizeof(err), "unable to config pins : %d %s", snprintf(err, sizeof(err), "unable to config pins : %d %s",
ret, ftdi_get_error_string(_ftdi)); 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) if (setClkFreq(_clkHZ) < 0)
return -1; 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; int to_wr = 3;
buf_cmd[1] = _cable.bit_low_val; // 0xe8; 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; return -1;
} }
_bitmode = mode;
return 0; return 0;
} }

View File

@ -69,6 +69,7 @@ class FTDIpp_MPSSE {
private: private:
uint8_t _bus; uint8_t _bus;
uint8_t _addr; uint8_t _addr;
uint8_t _bitmode;
char _product[64]; char _product[64];
unsigned char _interface; unsigned char _interface;
/* gpio */ /* gpio */

View File

@ -52,6 +52,7 @@ struct arguments {
string cable; string cable;
string ftdi_serial; string ftdi_serial;
int ftdi_channel; int ftdi_channel;
int status_pin;
uint32_t freq; uint32_t freq;
bool invert_read_edge; bool invert_read_edge;
string board; string board;
@ -108,7 +109,7 @@ int main(int argc, char **argv)
/* command line args. */ /* command line args. */
struct arguments args = {0, false, false, false, false, 0, "", "", "", "-", "", -1, 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 */ /* spi dfu file_type fpga_part bridge_path probe_firmware */
false, false, "", "", "", "", false, false, "", "", "", "",
/* index_chain file_size target_flash external_flash altsetting */ /* 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) { if (args.vid != 0) {
printInfo("Cable VID overridden"); printInfo("Cable VID overridden");
cable.vid = args.vid; cable.vid = args.vid;
@ -232,8 +240,9 @@ int main(int argc, char **argv)
cable.bus_addr = args.bus_addr; cable.bus_addr = args.bus_addr;
cable.device_addr = args.device_addr; cable.device_addr = args.device_addr;
// always set this // always set these
cable.config.index = args.cable_index; cable.config.index = args.cable_index;
cable.config.status_pin = args.status_pin;
/* FLASH direct access */ /* FLASH direct access */
if (args.spi || (board && board->mode == COMM_SPI)) { 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)", "bitstream(intel/xilinx)",
cxxopts::value<string>(args->bridge_path)) cxxopts::value<string>(args->bridge_path))
("c,cable", "jtag interface", cxxopts::value<string>(args->cable)) ("c,cable", "jtag interface", cxxopts::value<string>(args->cable))
("status-pin",
"JTAG mode / FTDI: GPIO pin number to use as a status indicator (active low)",
cxxopts::value<int>(args->status_pin))
("invert-read-edge", ("invert-read-edge",
"JTAG mode / FTDI: read on negative edge instead of positive", "JTAG mode / FTDI: read on negative edge instead of positive",
cxxopts::value<bool>(args->invert_read_edge)) cxxopts::value<bool>(args->invert_read_edge))
@ -857,6 +869,13 @@ int parse_opt(int argc, char **argv, struct arguments *args,
args->freq = static_cast<uint32_t>(freq); args->freq = static_cast<uint32_t>(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 (result.count("ftdi-channel")) {
if (args->ftdi_channel < 0 || args->ftdi_channel > 3) { if (args->ftdi_channel < 0 || args->ftdi_channel > 3) {
printError("Error: valid FTDI channels are 0-3."); printError("Error: valid FTDI channels are 0-3.");