Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Draft FX3 firmware interface #43

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ AM_LDFLAGS += $(libusb_LIBS)
endif

if BACKEND_CYPRESSFX3
libglip_la_SOURCES += backend_cypressfx3/sw/backend_cypressfx3.c
libglip_la_SOURCES += backend_cypressfx3/sw/backend_cypressfx3.c \
backend_cypressfx3/sw/interface.c
AM_CFLAGS += $(libusb_CFLAGS)
AM_LDFLAGS += $(libusb_LIBS)
endif
Expand Down
76 changes: 29 additions & 47 deletions src/backend_cypressfx3/sw/backend_cypressfx3.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
* Stefan Wallentowitz <[email protected]>
*/

#include "interface.h"
#include "backend_cypressfx3.h"
#include "glip-protected.h"
#include "cbuf.h"
Expand All @@ -50,26 +51,26 @@ struct usb_dev_entry {
uint16_t vid;
/** product id (idProduct) */
uint16_t pid;
const char *firmware_interface;
};

/** A list of well-known supported devices with Cypress FX3 chip */
static const struct usb_dev_entry usb_devs[] = {
/* FX3 superspeed explorer boards */
{
.vid = 0x04b4,
.pid = 0x00f1
.pid = 0x00f1,
.firmware_interface = "OpTiMSoC"
},
/* ZTEX boards */
{
.vid = 0x221a,
.pid = 0x0100,
.firmware_interface = "ZTEX"
},
{} /* leave this as last element! */
};



/* USB device constants */
/** USB write endpoint */
static const int USB_WR_EP = 0x01 | LIBUSB_ENDPOINT_OUT; /* EP1 OUT */
/** USB read endpoint */
static const int USB_RD_EP = 0x01 | LIBUSB_ENDPOINT_IN; /* EP1 IN */

/**
* USB read timeout [ms]
*
Expand Down Expand Up @@ -141,6 +142,8 @@ struct glip_backend_ctx {
/** libusb-1.0 device handle */
struct libusb_device_handle *usb_dev_handle;

struct firmware_interface *firmware_interface;

/** USB sending thread */
pthread_t usb_write_thread;
/** USB sending thread attributes */
Expand Down Expand Up @@ -328,8 +331,15 @@ int gb_cypressfx3_open(struct glip_ctx *ctx, unsigned int num_channels)
found_cnt++;
found_dev_idx = dev_idx;

const char *fwifname;
fwifname = dev_searchlist[dev_searchlist_idx].firmware_interface;
struct firmware_interface *fwif;
fwif = get_firmware_interface(fwifname);
assert(fwif != 0);
ctx->backend_ctx->firmware_interface = fwif;

/* Serial number is used to determine the FIFO width. */
ctx->backend_ctx->fifo_width = desc.iSerialNumber;
ctx->backend_ctx->fifo_width = fwif->get_fifo_width(&desc);
assert(ctx->backend_ctx->fifo_width != 0);
info(ctx, "Detected FX3 firmware with %u bit FIFO width.\n",
ctx->backend_ctx->fifo_width * 8);
Expand Down Expand Up @@ -376,19 +386,9 @@ int gb_cypressfx3_open(struct glip_ctx *ctx, unsigned int num_channels)
}

/* reset communication */
rv = libusb_control_transfer(ctx->backend_ctx->usb_dev_handle, 0x40, 0x60,
(1 << 0), 0, 0, 0, USB_TX_TIMEOUT_MS);
if (rv < 0) {
err(ctx, "Unable to send USB control message to reset system "
"(r=1). Error %d: %s\n", rv, libusb_error_name(rv));
return -1;
}

rv = libusb_control_transfer(ctx->backend_ctx->usb_dev_handle, 0x40, 0x60,
(0 << 0), 0, 0, 0, USB_TX_TIMEOUT_MS);
rv = ctx->backend_ctx->firmware_interface->reset_communication(ctx, ctx->backend_ctx->usb_dev_handle);
if (rv < 0) {
err(ctx, "Unable to send USB control message to reset system (r=0). "
"Error %d: %s\n", rv, libusb_error_name(rv));
err(ctx, "Unable to reset communication\n");
return -1;
}

Expand Down Expand Up @@ -493,33 +493,15 @@ int gb_cypressfx3_close(struct glip_ctx *ctx)
*/
int gb_cypressfx3_logic_reset(struct glip_ctx *ctx)
{
struct firmware_interface *fwif;

if (ctx->backend_ctx->usb_dev_handle == NULL) {
err(ctx, "Not connected!\n");
return -1;
}

int rv;

/* set reset signal */
rv = libusb_control_transfer(ctx->backend_ctx->usb_dev_handle, 0x40, 0x60,
(1 << 1), 0, 0, 0, USB_TX_TIMEOUT_MS);
if (rv < 0) {
err(ctx, "Unable to send USB control message to reset system "
"(r=1). Error %d: %s\n", rv, libusb_error_name(rv));
return -1;
}

/* unset reset signal */
rv = libusb_control_transfer(ctx->backend_ctx->usb_dev_handle, 0x40, 0x60,
(0 << 1), 0, 0, 0, USB_TX_TIMEOUT_MS);

if (rv < 0) {
err(ctx, "Unable to send USB control message to reset system (r=0). "
"Error %d: %s\n", rv, libusb_error_name(rv));
return -1;
}

return 0;
fwif = ctx->backend_ctx->firmware_interface;
return fwif->reset_logic(ctx, ctx->backend_ctx->usb_dev_handle);
}

/**
Expand Down Expand Up @@ -814,7 +796,7 @@ static void* usb_write_thread(void* ctx_void)
assert(rv == 0);

pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
rv = libusb_bulk_transfer(bctx->usb_dev_handle, USB_WR_EP,
rv = libusb_bulk_transfer(bctx->usb_dev_handle, bctx->firmware_interface->wr_ep,
transfer_data, transfer_len,
(int*)&transfer_len_sent, USB_TX_TIMEOUT_MS);
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
Expand Down Expand Up @@ -859,7 +841,7 @@ static void* usb_write_thread(void* ctx_void)
dbg(ctx, "Sending a zero-length packet to signal the end of the "
"transfer.\n");

rv = libusb_bulk_transfer(bctx->usb_dev_handle, USB_WR_EP,
rv = libusb_bulk_transfer(bctx->usb_dev_handle, bctx->firmware_interface->wr_ep,
transfer_data, 0,
(int*)&transfer_len_sent,
USB_TX_TIMEOUT_MS);
Expand Down Expand Up @@ -926,7 +908,7 @@ static void* usb_read_thread(void* ctx_void)
* is available is returned.
*/
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
rv = libusb_bulk_transfer(bctx->usb_dev_handle, USB_RD_EP,
rv = libusb_bulk_transfer(bctx->usb_dev_handle, bctx->firmware_interface->rd_ep,
(unsigned char*)buf,
buf_size,
&received,
Expand Down
104 changes: 104 additions & 0 deletions src/backend_cypressfx3/sw/interface.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
#include "interface.h"

#include <string.h>

static const int USB_TX_TIMEOUT_MS = 1000; /* 1 second */

static uint8_t optimsoc_get_fifo_width(struct libusb_device_descriptor * desc ) {
return desc->iSerialNumber;
}

static int optimsoc_reset_communication(struct glip_ctx * ctx,
struct libusb_device_handle * dev) {
int rv;
rv = libusb_control_transfer(dev, 0x40, 0x60,
(1 << 0), 0, 0, 0, USB_TX_TIMEOUT_MS);
if (rv < 0) {
err(ctx, "Unable to send USB control message to reset system "
"(r=1). Error %d: %s\n", rv, libusb_error_name(rv));
return -1;
}

rv = libusb_control_transfer(dev, 0x40, 0x60,
(0 << 0), 0, 0, 0, USB_TX_TIMEOUT_MS);
if (rv < 0) {
err(ctx, "Unable to send USB control message to reset system (r=0). "
"Error %d: %s\n", rv, libusb_error_name(rv));
return -1;
}

return 0;
}


static int optimsoc_reset_logic(struct glip_ctx * ctx,
struct libusb_device_handle * dev) {
int rv;

/* set reset signal */
rv = libusb_control_transfer(dev, 0x40, 0x60,
(1 << 1), 0, 0, 0, USB_TX_TIMEOUT_MS);
if (rv < 0) {
err(ctx, "Unable to send USB control message to reset system "
"(r=1). Error %d: %s\n", rv, libusb_error_name(rv));
return -1;
}

/* unset reset signal */
rv = libusb_control_transfer(dev, 0x40, 0x60,
(0 << 1), 0, 0, 0, USB_TX_TIMEOUT_MS);

if (rv < 0) {
err(ctx, "Unable to send USB control message to reset system (r=0). "
"Error %d: %s\n", rv, libusb_error_name(rv));
return -1;
}

return 0;
}

static uint8_t ztex_get_fifo_width(struct libusb_device_descriptor * desc) {
(void) desc;
return 2;
}

static int ztex_reset_communication(struct glip_ctx * ctx,
struct libusb_device_handle * dev) {
return 0;
}

static int ztex_reset_logic(struct glip_ctx * ctx,
struct libusb_device_handle * dev) {
return 0;
}

static struct firmware_interface interfaces[] = {
{
.name = "OpTiMSoC",
.get_fifo_width = optimsoc_get_fifo_width,
.reset_communication = optimsoc_reset_communication,
.reset_logic = optimsoc_reset_logic,
.wr_ep = 0x01 | LIBUSB_ENDPOINT_OUT,
.rd_ep = 0x01 | LIBUSB_ENDPOINT_IN
},
{
.name = "ZTEX",
.get_fifo_width = ztex_get_fifo_width,
.reset_communication = ztex_reset_communication,
.reset_logic = ztex_reset_logic,
.wr_ep = 0x02 | LIBUSB_ENDPOINT_OUT,
.rd_ep = 0x04 | LIBUSB_ENDPOINT_IN
},
{}
};

struct firmware_interface *get_firmware_interface(const char* name) {
for (int idx = 0; interfaces[idx].name != 0; idx++) {
struct firmware_interface *fwif = &interfaces[idx];
if (strncmp(name, fwif->name, strlen(fwif->name)) == 0) {
return fwif;
}
}

return 0;
}
19 changes: 19 additions & 0 deletions src/backend_cypressfx3/sw/interface.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#pragma once

#include "glip-protected.h"

#include <stdint.h>
#include <libusb.h>

struct firmware_interface {
const char *name;
uint8_t (*get_fifo_width)(struct libusb_device_descriptor * /* desc */);
int (*reset_communication)(struct glip_ctx * /* ctx */,
struct libusb_device_handle * /* dev */);
int (*reset_logic)(struct glip_ctx * /* ctx */,
struct libusb_device_handle * /* dev */);
int wr_ep;
int rd_ep;
};

struct firmware_interface *get_firmware_interface(const char* name);