Skip to content

Instantly share code, notes, and snippets.

@pbatard
Created Jul 5, 2012
Embed
What would you like to do?
FX3 firmware upload patch for xusb
--- D:/__PROJECTS/_INTERNAL/20120118_USB3.0/LibUSBx/libusbx-1.0.12-rc1/examples/xusb.c.orig Mon Jun 18 12:00:44 2012
+++ D:/__PROJECTS/_INTERNAL/20120118_USB3.0/LibUSBx/libusbx-1.0.12-rc1/examples/xusb.c Mon Jun 18 17:04:39 2012
@@ -47,14 +47,13 @@
#define false (!true)
#endif
-
// Future versions of libusbx will use usb_interface instead of interface
// in libusb_config_descriptor => catter for that
#define usb_interface interface
// Global variables
bool binary_dump = false;
-char binary_name[64] = "raw.bin";
+char binary_name[1024] = "raw.bin";
static int perr(char const *format, ...)
{
@@ -138,6 +137,7 @@
USE_XBOX,
USE_SCSI,
USE_HID,
+ USE_FX3,
} test_mode;
uint16_t VID, PID;
@@ -729,6 +729,111 @@
}
}
+// Download firmware to a Cypress FX3 device in bootloader mode
+static int download_fx3_firmware(libusb_device_handle *handle, char* path)
+{
+ unsigned char header[4];
+ unsigned char data[4096];
+ const int RETRY_LIMIT = 5;
+ FILE *fw;
+ int status = 0;
+
+ printf("\nDownloading firmware to FX3 DVK:\n");
+
+ fw = fopen(path, "rb");
+ if ( fw == NULL) {
+ perr(" Failed to open %s: %s\n", path, strerror(errno));
+ return;
+ }
+
+ // Validate the header
+ if (!fread(header, sizeof(char), sizeof(header), fw))
+ return;
+
+ if ((header[0] != 'C') || (header[1] != 'Y')) {
+ perr(" Invalid file: missing CYpress signature\n");
+ return;
+ }
+
+ if (header[3] != 0xB0) {
+ perr(" Invalid file: format 0x%02X, expected 0xB0\n", header[3]);
+ return;
+ }
+
+ // Now process the data segments
+ do {
+ uint32_t retry;
+ uint32_t segment_addr, cur_addr;
+ uint32_t segment_len, bytes_remaining, bytes_this_chunk;
+
+ if (!fread(&segment_len, sizeof(segment_len), 1, fw))
+ break;
+
+ if (!fread(&segment_addr, sizeof(segment_len), 1, fw))
+ break;
+
+ segment_len = segment_len << 2;
+ cur_addr = segment_addr;
+ bytes_remaining = segment_len;
+
+ // Make sure we run one time after segment_len == 0,
+ // as FX3 interprets this as a "run from address" command
+ if (segment_len == 0) {
+ printf("\nResetting device to load new firmware image:\n");
+ }
+
+ do {
+ bytes_this_chunk = bytes_remaining;
+
+ if (bytes_this_chunk > sizeof(data))
+ bytes_this_chunk = sizeof(data);
+
+ if (bytes_this_chunk && !fread(data, sizeof(char), bytes_this_chunk, fw))
+ break;
+
+ printf ("Writing %4d (0x%04x) bytes to address 0x%05x\n", bytes_this_chunk, bytes_this_chunk, cur_addr);
+
+ // Issue the control request. For more information, see also
+ // FX3 programmers manual, p. 131
+ // http://www.cypress.com/?app=forum&id=167&rID=54054
+ // http://www.cypress.com/?app=forum&id=167&rID=53996
+ retry = 0;
+ while ((status = libusb_control_transfer(
+ handle, // handle
+ 0x40, // bmRequestType: Host to Device, Vendor, Device
+ 0xA0, // bRequest: Vendor (Cypress)
+ cur_addr & 0xFFFF, // wValue (LSW)
+ cur_addr >> 16, // wIndex (MSW)
+ (unsigned char*)data,// data
+ bytes_this_chunk, // wLength
+ 1000 )) // timeout in ms
+ < 0 && retry < RETRY_LIMIT) {
+ retry += 1;
+ if (status != LIBUSB_ERROR_TIMEOUT)
+ break;
+ }
+
+ if (status != bytes_this_chunk) {
+ // libusbx will return an I/O error, as the device disappears instantly
+ if (status == LIBUSB_ERROR_IO && segment_len == 0)
+ perr(" Device reset successfully accomplished\n");
+ else if (status < 0)
+ perr(" Write error: %s\n", libusb_error_name(status));
+ else
+ perr(" Write error: Only %d of %d bytes transmitted\n", status, bytes_this_chunk);
+ }
+
+ cur_addr += bytes_this_chunk;
+ bytes_remaining -= bytes_this_chunk;
+
+ } while ((status >= 0) && (bytes_remaining > 0));
+
+ if (segment_len == 0)
+ break;
+
+ } while (status >= 0);
+}
+
static int test_device(uint16_t vid, uint16_t pid)
{
libusb_device_handle *handle;
@@ -878,6 +983,9 @@
case USE_HID:
test_hid(handle, endpoint_in);
break;
+ case USE_FX3:
+ CALL_CHECK(download_fx3_firmware(handle, binary_name));
+ break;
case USE_SCSI:
CALL_CHECK(test_mass_storage(handle, endpoint_in, endpoint_out));
case USE_GENERIC:
@@ -935,11 +1043,22 @@
break;
case 'b':
if (j+1 < argc) {
- strncpy(binary_name, argv[j+1], 64);
+ strncpy(binary_name, argv[j+1], 1024);
j++;
}
binary_dump = true;
break;
+ case 'f':
+ // Force Cypress FX3 DVK VID/PID
+ VID = 0x04B4;
+ PID = 0x0053;
+ binary_name[0] = '\0'; // Clear file name global
+ if (j+1 < argc) {
+ strncpy(binary_name, argv[j+1], 1024);
+ j++;
+ }
+ test_mode = USE_FX3;
+ break;
case 'g':
break;
case 'j':
@@ -999,10 +1118,11 @@
}
if ((show_help) || (argc == 1) || (argc > 7)) {
- printf("usage: %s [-d] [-b [file]] [-h] [-i] [-j] [-k] [-x] [vid:pid]\n", argv[0]);
+ printf("usage: %s [-d] [-b [file]] [-f file] [-h] [-i] [-j] [-k] [-x] [vid:pid]\n", argv[0]);
printf(" -h: display usage\n");
printf(" -d: enable debug output (if library was compiled with debug enabled)\n");
printf(" -b: dump Mass Storage first block to binary file\n");
+ printf(" -f: download firmware to Cypress FX3 device (using WinUSB)\n");
printf(" -g: short generic test (default)\n");
printf(" -k: test generic Mass Storage USB device (using WinUSB)\n");
printf(" -j: test FTDI based JTAG device (using WinUSB)\n");
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment