Merge pull request #665 from r4d10n/esp_usb_jtag
esp_usb_jtag: support multiple boards (--busdev-num, --usb-serial-num)
This commit is contained in:
commit
79aa75dd8e
|
|
@ -70,7 +70,9 @@ openFPGALoader -- a program to flash FPGA
|
||||||
--cable-index arg probe index (FTDI and cmsisDAP)
|
--cable-index arg probe index (FTDI and cmsisDAP)
|
||||||
--busdev-num arg select a probe by it bus and device number
|
--busdev-num arg select a probe by it bus and device number
|
||||||
(bus_num:device_addr)
|
(bus_num:device_addr)
|
||||||
--ftdi-serial arg FTDI chip serial number
|
--usb-serial-num arg USB iSerial (FTDI chip serial number or ESP32
|
||||||
|
iSerialNumber substring)
|
||||||
|
--ftdi-serial arg FTDI chip serial number (Deprecated)
|
||||||
--ftdi-channel arg FTDI chip channel number (channels 0-3 map to
|
--ftdi-channel arg FTDI chip channel number (channels 0-3 map to
|
||||||
A-D)
|
A-D)
|
||||||
-d, --device arg device to use (/dev/ttyUSBx)
|
-d, --device arg device to use (/dev/ttyUSBx)
|
||||||
|
|
|
||||||
|
|
@ -245,13 +245,17 @@ static uint16_t esp_usb_target_chip_id = 0; /* not applicable for FPGA, they hav
|
||||||
|
|
||||||
/* end copy from openocd */
|
/* end copy from openocd */
|
||||||
|
|
||||||
esp_usb_jtag::esp_usb_jtag(uint32_t clkHZ, int8_t verbose, int vid = ESPUSBJTAG_VID, int pid = ESPUSBJTAG_PID):
|
esp_usb_jtag::esp_usb_jtag(uint32_t clkHZ, int8_t verbose,
|
||||||
|
int vid = ESPUSBJTAG_VID, int pid = ESPUSBJTAG_PID,
|
||||||
|
uint8_t bus_addr = 0, uint8_t dev_addr = 0,
|
||||||
|
const std::string &serial = ""):
|
||||||
_verbose(verbose > 1),
|
_verbose(verbose > 1),
|
||||||
dev_handle(NULL), usb_ctx(NULL), _tdi(0), _tms(0),
|
dev_handle(NULL), usb_ctx(NULL), _tdi(0), _tms(0),
|
||||||
/* Default for emard firmware. */
|
/* Default for emard firmware. */
|
||||||
_esp_usb_jtag_caps(0x2000), _write_ep(0x02),
|
_esp_usb_jtag_caps(0x2000), _write_ep(0x02),
|
||||||
_vid(ESPUSBJTAG_VID), _pid(ESPUSBJTAG_PID)
|
_vid(ESPUSBJTAG_VID), _pid(ESPUSBJTAG_PID)
|
||||||
{
|
{
|
||||||
|
libusb_device **devs = NULL;
|
||||||
int ret;
|
int ret;
|
||||||
char mess[256];
|
char mess[256];
|
||||||
|
|
||||||
|
|
@ -260,18 +264,61 @@ esp_usb_jtag::esp_usb_jtag(uint32_t clkHZ, int8_t verbose, int vid = ESPUSBJTAG_
|
||||||
throw std::exception();
|
throw std::exception();
|
||||||
}
|
}
|
||||||
|
|
||||||
dev_handle = libusb_open_device_with_vid_pid(usb_ctx,
|
ssize_t cnt = libusb_get_device_list(usb_ctx, &devs);
|
||||||
_vid, _pid);
|
if (cnt < 0) {
|
||||||
if (!dev_handle) {
|
std::cerr << "esp_usb_jtag: libusb_get_device_list failed: "
|
||||||
_esp_usb_jtag_caps = 0x030A;
|
<< libusb_error_name(static_cast<int>(cnt)) << std::endl;
|
||||||
_write_ep = 0x03;
|
libusb_exit(usb_ctx);
|
||||||
_pid = 0x1002;
|
throw std::exception();
|
||||||
dev_handle = libusb_open_device_with_vid_pid(usb_ctx,
|
|
||||||
_vid, _pid);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (ssize_t i = 0; i < cnt; i++) {
|
||||||
|
libusb_device *dev = devs[i];
|
||||||
|
struct libusb_device_descriptor desc;
|
||||||
|
if (libusb_get_device_descriptor(dev, &desc) < 0)
|
||||||
|
continue;
|
||||||
|
if (desc.idVendor != vid || desc.idProduct != pid)
|
||||||
|
continue;
|
||||||
|
/* bus/device filter (only when both are user-supplied) */
|
||||||
|
if (bus_addr != 0 && dev_addr != 0 &&
|
||||||
|
(libusb_get_bus_number(dev) != bus_addr ||
|
||||||
|
libusb_get_device_address(dev) != dev_addr))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* serial filter */
|
||||||
|
if (!serial.empty()) {
|
||||||
|
libusb_device_handle *probe = NULL;
|
||||||
|
if (libusb_open(dev, &probe) < 0)
|
||||||
|
continue;
|
||||||
|
unsigned char raw[256] = {0};
|
||||||
|
int n = 0;
|
||||||
|
if (desc.iSerialNumber)
|
||||||
|
n = libusb_get_string_descriptor_ascii(probe,
|
||||||
|
desc.iSerialNumber, raw, sizeof(raw));
|
||||||
|
libusb_close(probe);
|
||||||
|
if (n <= 0)
|
||||||
|
continue;
|
||||||
|
const std::string found(reinterpret_cast<char *>(raw), n);
|
||||||
|
|
||||||
|
if (found.find(serial) == std::string::npos)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (libusb_open(dev, &dev_handle) == 0)
|
||||||
|
break;
|
||||||
|
dev_handle = NULL;
|
||||||
|
}
|
||||||
|
libusb_free_device_list(devs, 1);
|
||||||
|
|
||||||
if (!dev_handle) {
|
if (!dev_handle) {
|
||||||
snprintf(mess, 256, "fails to open esp_usb_jtag device");
|
std::cerr << "fails to open esp_usb_jtag device vid:pid 0x"
|
||||||
printError(mess);
|
<< std::hex << vid << ":0x" << pid;
|
||||||
|
if (bus_addr || dev_addr)
|
||||||
|
std::cerr << " bus:dev " << std::dec << static_cast<int>(bus_addr)
|
||||||
|
<< ":" << static_cast<int>(dev_addr);
|
||||||
|
if (!serial.empty())
|
||||||
|
std::cerr << " serial '" << serial << "'";
|
||||||
|
std::cerr << std::endl;
|
||||||
libusb_exit(usb_ctx);
|
libusb_exit(usb_ctx);
|
||||||
throw std::exception();
|
throw std::exception();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,8 @@
|
||||||
|
|
||||||
#include <libusb.h>
|
#include <libusb.h>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
#include "jtagInterface.hpp"
|
#include "jtagInterface.hpp"
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
|
@ -23,7 +25,9 @@
|
||||||
|
|
||||||
class esp_usb_jtag : public JtagInterface {
|
class esp_usb_jtag : public JtagInterface {
|
||||||
public:
|
public:
|
||||||
esp_usb_jtag(uint32_t clkHZ, int8_t verbose, int vid, int pid);
|
esp_usb_jtag(uint32_t clkHZ, int8_t verbose, int vid, int pid,
|
||||||
|
uint8_t bus_addr, uint8_t dev_addr,
|
||||||
|
const std::string &serial);
|
||||||
virtual ~esp_usb_jtag();
|
virtual ~esp_usb_jtag();
|
||||||
|
|
||||||
int setClkFreq(uint32_t clkHZ) override;
|
int setClkFreq(uint32_t clkHZ) override;
|
||||||
|
|
|
||||||
|
|
@ -165,7 +165,8 @@ Jtag::Jtag(const cable_t &cable, const jtag_pins_conf_t *pin_conf,
|
||||||
break;
|
break;
|
||||||
case MODE_ESP:
|
case MODE_ESP:
|
||||||
#ifdef ENABLE_ESP_USB
|
#ifdef ENABLE_ESP_USB
|
||||||
_jtag = new esp_usb_jtag(clkHZ, verbose, 0x303a, 0x1001);
|
_jtag = new esp_usb_jtag(clkHZ, verbose, 0x303a, 0x1001,
|
||||||
|
cable.bus_addr, cable.device_addr, serial);
|
||||||
#else
|
#else
|
||||||
std::cerr << "Jtag: support for esp32s3 cable was not enabled at compile time" << std::endl;
|
std::cerr << "Jtag: support for esp32s3 cable was not enabled at compile time" << std::endl;
|
||||||
throw std::exception();
|
throw std::exception();
|
||||||
|
|
|
||||||
36
src/main.cpp
36
src/main.cpp
|
|
@ -79,7 +79,7 @@ struct arguments {
|
||||||
std::string secondary_bit_file;
|
std::string secondary_bit_file;
|
||||||
std::string device;
|
std::string device;
|
||||||
std::string cable;
|
std::string cable;
|
||||||
std::string ftdi_serial;
|
std::string usb_serial_num;
|
||||||
int ftdi_channel;
|
int ftdi_channel;
|
||||||
int status_pin;
|
int status_pin;
|
||||||
uint32_t freq;
|
uint32_t freq;
|
||||||
|
|
@ -264,13 +264,6 @@ int main(int argc, char **argv)
|
||||||
cable.config.interface = mapping[args.ftdi_channel];
|
cable.config.interface = mapping[args.ftdi_channel];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!args.ftdi_serial.empty()) {
|
|
||||||
if (cable.type != MODE_FTDI_SERIAL && cable.type != MODE_FTDI_BITBANG){
|
|
||||||
printError("Error: FTDI serial param is for FTDI cables.");
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (args.status_pin != -1) {
|
if (args.status_pin != -1) {
|
||||||
if (cable.type != MODE_FTDI_SERIAL){
|
if (cable.type != MODE_FTDI_SERIAL){
|
||||||
printError("Error: FTDI status pin is for FTDI MPSSE cables.");
|
printError("Error: FTDI status pin is for FTDI MPSSE cables.");
|
||||||
|
|
@ -279,6 +272,14 @@ int main(int argc, char **argv)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (!args.usb_serial_num.empty()) {
|
||||||
|
if (cable.type != MODE_FTDI_SERIAL && cable.type != MODE_FTDI_BITBANG &&
|
||||||
|
cable.type != MODE_ESP){
|
||||||
|
printError("Error: usb-serial-num param is for FTDI and esp32s3 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;
|
||||||
|
|
@ -389,7 +390,7 @@ int main(int argc, char **argv)
|
||||||
|
|
||||||
Jtag *jtag;
|
Jtag *jtag;
|
||||||
try {
|
try {
|
||||||
jtag = new Jtag(cable, &pins_config, args.device, args.ftdi_serial,
|
jtag = new Jtag(cable, &pins_config, args.device, args.usb_serial_num,
|
||||||
args.freq, args.verbose, args.ip_adr, args.port,
|
args.freq, args.verbose, args.ip_adr, args.port,
|
||||||
args.invert_read_edge, args.probe_firmware,
|
args.invert_read_edge, args.probe_firmware,
|
||||||
args.user_misc_devs);
|
args.user_misc_devs);
|
||||||
|
|
@ -667,7 +668,7 @@ int run_xvc_server(const struct arguments &args, const cable_t &cable,
|
||||||
try {
|
try {
|
||||||
XVC_server *xvc = NULL;
|
XVC_server *xvc = NULL;
|
||||||
xvc = new XVC_server(args.port, cable, pins_config, args.device,
|
xvc = new XVC_server(args.port, cable, pins_config, args.device,
|
||||||
args.ftdi_serial, args.freq, args.verbose, args.ip_adr,
|
args.usb_serial_num, args.freq, args.verbose, args.ip_adr,
|
||||||
args.invert_read_edge, args.probe_firmware);
|
args.invert_read_edge, args.probe_firmware);
|
||||||
/* create connection */
|
/* create connection */
|
||||||
xvc->open_connection();
|
xvc->open_connection();
|
||||||
|
|
@ -889,6 +890,7 @@ int parse_opt(int argc, char **argv, struct arguments *args,
|
||||||
jtag_pins_conf_t *pins_config)
|
jtag_pins_conf_t *pins_config)
|
||||||
{
|
{
|
||||||
std::string freqo;
|
std::string freqo;
|
||||||
|
std::string ftdi_serial;
|
||||||
std::vector<std::string> pins, bus_dev_num;
|
std::vector<std::string> pins, bus_dev_num;
|
||||||
bool verbose = false, quiet = false;
|
bool verbose = false, quiet = false;
|
||||||
int8_t verbose_level = -2;
|
int8_t verbose_level = -2;
|
||||||
|
|
@ -927,8 +929,10 @@ int parse_opt(int argc, char **argv, struct arguments *args,
|
||||||
("busdev-num",
|
("busdev-num",
|
||||||
"select a probe by it bus and device number (bus_num:device_addr)",
|
"select a probe by it bus and device number (bus_num:device_addr)",
|
||||||
cxxopts::value<std::vector<std::string>>(bus_dev_num))
|
cxxopts::value<std::vector<std::string>>(bus_dev_num))
|
||||||
("ftdi-serial", "FTDI chip serial number",
|
("usb-serial-num", "USB iSerial (FTDI chip serial number or ESP32 iSerialNumber substring)",
|
||||||
cxxopts::value<std::string>(args->ftdi_serial))
|
cxxopts::value<std::string>(args->usb_serial_num))
|
||||||
|
("ftdi-serial", "FTDI chip serial number (Deprecated)",
|
||||||
|
cxxopts::value<std::string>(ftdi_serial))
|
||||||
("ftdi-channel",
|
("ftdi-channel",
|
||||||
"FTDI chip channel number (channels 0-3 map to A-D)",
|
"FTDI chip channel number (channels 0-3 map to A-D)",
|
||||||
cxxopts::value<int>(args->ftdi_channel))
|
cxxopts::value<int>(args->ftdi_channel))
|
||||||
|
|
@ -1134,6 +1138,14 @@ int parse_opt(int argc, char **argv, struct arguments *args,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (result.count("ftdi-serial")) {
|
||||||
|
if (result.count("usb-serial-num")) {
|
||||||
|
printError("Error: ftdi-serial and usb-serial-num can't be used at the same time.");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
args->usb_serial_num = ftdi_serial;
|
||||||
|
}
|
||||||
|
|
||||||
if (result.count("busdev-num")) {
|
if (result.count("busdev-num")) {
|
||||||
if (bus_dev_num.size() != 2) {
|
if (bus_dev_num.size() != 2) {
|
||||||
printError("Error: busdev-num must be xx:yy");
|
printError("Error: busdev-num must be xx:yy");
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue