drivers: xds110: Add support of alternate XDS110 configurations

The XDS110 supports alternate configurations, each of which has
a unique vid/pid:

0451/bef3 -- Standard (legacy) configuration
0451/bef4 -- Drag-n-Drop configuration
1cbe/02a5 -- CMSIS-DAP 2.0 on BULK interface configuration

It's not important to OpenOCD what the differences are except
that OpenOCD needs to know how to connect using the different
vid/pids and, in the case of the last one, use a different
interface for the debug connection.

Updated the XDS110 source to search for all possible
configurations, and updated the udev rules file to enable
user access to the alternate configuraitons.

For the curious, you can download the latest XDS emupack from
software-dl.ti.com/ccs/esd/documents/xdsdebugprobes/emu_xds_software_package_download.html
Install to an empty directory, and documentation for the
XDS110 is located in the .../ccs_base/common/uscif/xds110
of the installation.

Updated for comments in code review. Changed const variable
names to lower case. Reworked interface/endpoint setting
to use arrays suggestion.

Change-Id: Icc9d11c6618f43d87ae8171c78ebf238800d3ac2
Signed-off-by: Edward Fewell <efewell@ti.com>
Reviewed-on: http://openocd.zylin.com/5494
Tested-by: jenkins
Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
This commit is contained in:
Edward Fewell 2020-03-04 15:14:48 -06:00 committed by Antonio Borneo
parent 87a4158acf
commit d35c44c743
2 changed files with 54 additions and 23 deletions

View File

@ -139,6 +139,8 @@ ATTRS{idVendor}=="1cbe", ATTRS{idProduct}=="00fd", MODE="660", GROUP="plugdev",
# TI XDS110 Debug Probe (Launchpads and Standalone)
ATTRS{idVendor}=="0451", ATTRS{idProduct}=="bef3", MODE="660", GROUP="plugdev", TAG+="uaccess"
ATTRS{idVendor}=="0451", ATTRS{idProduct}=="bef4", MODE="660", GROUP="plugdev", TAG+="uaccess"
ATTRS{idVendor}=="1cbe", ATTRS{idProduct}=="02a5", MODE="660", GROUP="plugdev", TAG+="uaccess"
# TI Tiva-based ICDI and XDS110 probes in DFU mode
ATTRS{idVendor}=="1cbe", ATTRS{idProduct}=="00ff", MODE="660", GROUP="plugdev", TAG+="uaccess"

View File

@ -66,15 +66,6 @@
#endif
#define MAX_RESULT_QUEUE (MAX_DATA_BLOCK / 4)
/***************************************************************************
* USB Connection Endpoints *
***************************************************************************/
/* Bulk endpoints used by the XDS110 debug interface */
#define INTERFACE_DEBUG (2)
#define ENDPOINT_DEBUG_IN (3 | LIBUSB_ENDPOINT_IN)
#define ENDPOINT_DEBUG_OUT (2 | LIBUSB_ENDPOINT_OUT)
/***************************************************************************
* XDS110 Firmware API Definitions *
***************************************************************************/
@ -227,6 +218,13 @@ struct xds110_info {
unsigned char read_payload[USB_PAYLOAD_SIZE];
unsigned char write_packet[3];
unsigned char write_payload[USB_PAYLOAD_SIZE];
/* Device vid/pid */
uint16_t vid;
uint16_t pid;
/* Debug interface */
uint8_t interface;
uint8_t endpoint_in;
uint8_t endpoint_out;
/* Status flags */
bool is_connected;
bool is_cmapi_connected;
@ -259,6 +257,11 @@ struct xds110_info {
static struct xds110_info xds110 = {
.ctx = NULL,
.dev = NULL,
.vid = 0,
.pid = 0,
.interface = 0,
.endpoint_in = 0,
.endpoint_out = 0,
.is_connected = false,
.is_cmapi_connected = false,
.is_cmapi_acquired = false,
@ -320,12 +323,20 @@ static bool usb_connect(void)
struct libusb_device_descriptor desc;
uint16_t vid = 0x0451;
uint16_t pid = 0xbef3;
/* The vid/pids of possible XDS110 configurations */
uint16_t vids[] = { 0x0451, 0x0451, 0x1cbe };
uint16_t pids[] = { 0xbef3, 0xbef4, 0x02a5 };
/* Corresponding interface and endpoint numbers for configurations */
uint8_t interfaces[] = { 2, 2, 0 };
uint8_t endpoints_in[] = { 3, 3, 1 };
uint8_t endpoints_out[] = { 2, 2, 1 };
ssize_t count = 0;
ssize_t i = 0;
int result = 0;
bool found = false;
uint32_t device = 0;
bool match = false;
/* Initialize libusb context */
result = libusb_init(&ctx);
@ -342,13 +353,21 @@ static bool usb_connect(void)
if (0 == result) {
/* Scan through list of devices for any XDS110s */
for (i = 0; i < count; i++) {
/* Check for device VID/PID match */
/* Check for device vid/pid match */
libusb_get_device_descriptor(list[i], &desc);
if (desc.idVendor == vid && desc.idProduct == pid) {
match = false;
for (device = 0; device < sizeof(vids)/sizeof(vids[0]); device++) {
if (desc.idVendor == vids[device] &&
desc.idProduct == pids[device]) {
match = true;
break;
}
}
if (match) {
result = libusb_open(list[i], &dev);
if (0 == result) {
const int MAX_DATA = 256;
unsigned char data[MAX_DATA + 1];
const int max_data = 256;
unsigned char data[max_data + 1];
*data = '\0';
/* May be the requested device if serial number matches */
@ -359,7 +378,7 @@ static bool usb_connect(void)
} else {
/* Get the device's serial number string */
result = libusb_get_string_descriptor_ascii(dev,
desc.iSerialNumber, data, MAX_DATA);
desc.iSerialNumber, data, max_data);
if (0 < result &&
0 == strcmp((char *)data, (char *)xds110.serial)) {
found = true;
@ -387,6 +406,15 @@ static bool usb_connect(void)
}
if (found) {
/* Save the vid/pid of the device we're using */
xds110.vid = vids[device];
xds110.pid = pids[device];
/* Save the debug interface and endpoints for the device */
xds110.interface = interfaces[device];
xds110.endpoint_in = endpoints_in[device] | LIBUSB_ENDPOINT_IN;
xds110.endpoint_out = endpoints_out[device] | LIBUSB_ENDPOINT_OUT;
/* Save the context and device handles */
xds110.ctx = ctx;
xds110.dev = dev;
@ -395,7 +423,7 @@ static bool usb_connect(void)
(void)libusb_set_auto_detach_kernel_driver(dev, 1);
/* Claim the debug interface on the XDS110 */
result = libusb_claim_interface(dev, INTERFACE_DEBUG);
result = libusb_claim_interface(dev, xds110.interface);
} else {
/* Couldn't find an XDS110, flag the error */
result = -1;
@ -405,7 +433,7 @@ static bool usb_connect(void)
if (0 != result) {
if (NULL != dev) {
/* Release the debug and data interface on the XDS110 */
(void)libusb_release_interface(dev, INTERFACE_DEBUG);
(void)libusb_release_interface(dev, xds110.interface);
libusb_close(dev);
}
if (NULL != ctx)
@ -427,7 +455,7 @@ static void usb_disconnect(void)
{
if (NULL != xds110.dev) {
/* Release the debug and data interface on the XDS110 */
(void)libusb_release_interface(xds110.dev, INTERFACE_DEBUG);
(void)libusb_release_interface(xds110.dev, xds110.interface);
libusb_close(xds110.dev);
xds110.dev = NULL;
}
@ -451,7 +479,7 @@ static bool usb_read(unsigned char *buffer, int size, int *bytes_read,
if (0 == timeout)
timeout = DEFAULT_TIMEOUT;
result = libusb_bulk_transfer(xds110.dev, ENDPOINT_DEBUG_IN, buffer, size,
result = libusb_bulk_transfer(xds110.dev, xds110.endpoint_in, buffer, size,
bytes_read, timeout);
return (0 == result) ? true : false;
@ -466,13 +494,13 @@ static bool usb_write(unsigned char *buffer, int size, int *written)
if (NULL == xds110.dev || NULL == buffer)
return false;
result = libusb_bulk_transfer(xds110.dev, ENDPOINT_DEBUG_OUT, buffer,
result = libusb_bulk_transfer(xds110.dev, xds110.endpoint_out, buffer,
size, &bytes_written, 0);
while (LIBUSB_ERROR_PIPE == result && retries < 3) {
/* Try clearing the pipe stall and retry transfer */
libusb_clear_halt(xds110.dev, ENDPOINT_DEBUG_OUT);
result = libusb_bulk_transfer(xds110.dev, ENDPOINT_DEBUG_OUT, buffer,
libusb_clear_halt(xds110.dev, xds110.endpoint_out);
result = libusb_bulk_transfer(xds110.dev, xds110.endpoint_out, buffer,
size, &bytes_written, 0);
retries++;
}
@ -1360,6 +1388,7 @@ static void xds110_show_info(void)
{
uint32_t firmware = xds110.firmware;
LOG_INFO("XDS110: vid/pid = %04x/%04x", xds110.vid, xds110.pid);
LOG_INFO("XDS110: firmware version = %d.%d.%d.%d",
(((firmware >> 28) & 0xf) * 10) + ((firmware >> 24) & 0xf),
(((firmware >> 20) & 0xf) * 10) + ((firmware >> 16) & 0xf),