Hi Markus,
Since I got my hands on an EZ-FX2 board (and I can only wish it won't be
long before basic FX3 boards come as cheap as the FX2 ones), I amended
your patch to add support for FX2 firmware upload as well.
I don't think the modifications I added will impact the FX3 upload, but
the changes were fairly intrusive, so I wouldn't mind get some
confirmation before I push the patch. If you have a chance to apply this
patch on top of latest libusbx and confirm that FX3 upload still works,
I would appreciate it.
Regards,
/Pete
PS: I am aware that Cypress use "download" where xusb uses "upload", but
since we are considering things from an xusb user's perspective, I think
upload makes more logical sense.
>From fafac9f91787004183504dfea272163885383793 Mon Sep 17 00:00:00 2001
From: Markus Schatzl <li...@neuronenwerk.de>
Date: Sat, 4 Aug 2012 17:12:26 +0100
Subject: [PATCH] Samples: Add FX2/FX3 firmware upload to RAM
---
examples/xusb.c | 186 ++++++++++++++++++++++++++++++++++++++++++++++----
1 files changed, 175 insertions(+), 13 deletions(-)
diff --git a/examples/xusb.c b/examples/xusb.c
index 3e8d262..fbae778 100644
--- a/examples/xusb.c
+++ b/examples/xusb.c
@@ -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[256] = "data.bin";
static int perr(char const *format, ...)
{
@@ -138,6 +137,8 @@ enum test_type {
USE_XBOX,
USE_SCSI,
USE_HID,
+ USE_FX2, // Cypress FX2/FX3 code upload
+ USE_FX3,
} test_mode;
uint16_t VID, PID;
@@ -729,6 +730,149 @@ static void
read_ms_winsub_feature_descriptors(libusb_device_handle *handle, uin
}
}
+// Set an FX2 device in or out of reset mode, for RAM upload.
+// See chapter 3.8 of the FX2 EZ-USB Technical Reference Manual
+static int fx2_reset(libusb_device_handle *handle, bool set)
+{
+ unsigned char cpucs_data = (set)?0x01:0x00;
+ int status = 0;
+
+ // Set the CPU in or out of reset mode to upload data to RAM
+ printf("Putting FX2 %s reset mode\n", (set)?"in":"out of");
+ status = libusb_control_transfer(handle,
+
LIBUSB_ENDPOINT_OUT|LIBUSB_REQUEST_TYPE_VENDOR|LIBUSB_RECIPIENT_DEVICE,
+ 0xA0, // bRequest: Vendor (Cypress)
+ 0xE600, // wValue (LSW)
+ 0x0000, // wIndex (MSW) => CPUCS register at 0xE600
+ &cpucs_data, // data
+ 1, // wLength
+ 1000); // timeout in ms
+ if (status < 0) {
+ perr(" Failed: %s\n", libusb_error_name(status));
+ return 1;
+ }
+ return 0;
+}
+
+// Upload 8051 (BIX format) or ARM (IMG format) code to the RAM of a Cypress
FX2/FX3 device in bootloader mode
+static int upload_to_fx_ram(libusb_device_handle *handle, char* path, bool
fx3_mode)
+{
+ unsigned char header[4];
+ unsigned char data[4096];
+ const uint32_t RETRY_LIMIT = 5;
+ FILE *fw;
+ int status = 0;
+ uint32_t retry;
+ uint32_t segment_addr = 0, cur_addr = 0;
+ uint32_t segment_len = sizeof(data), bytes_remaining, bytes_this_chunk;
+
+ printf("\nUploading firmware to FX2 device's RAM:\n");
+
+ fw = fopen(path, "rb");
+ if ( fw == NULL) {
+ perr(" Failed to open %s: %s\n", path, strerror(errno));
+ return -1;
+ }
+
+ if (fx3_mode) {
+ // Validate the header
+ if (!fread(header, sizeof(char), sizeof(header), fw))
+ return -1;
+
+ if ((header[0] != 'C') || (header[1] != 'Y')) {
+ perr(" Invalid file: missing CYpress signature\n");
+ return -1;
+ }
+
+ if (header[3] != 0xB0) {
+ perr(" Invalid file: format 0x%02X, expected 0xB0\n",
header[3]);
+ return -1;
+ }
+ } else {
+ // Set the CPU in reset mode to upload data to RAM
+ if (fx2_reset(handle, true))
+ return 1;
+ (void) header;
+ }
+
+ // Now process the data segments
+ do {
+ if (fx3_mode) {
+ 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
+ // Because segment_len is never zero, this does not apply for
FX2
+ if (segment_len == 0) {
+ printf("\nResetting device to load new firmware
image:\n");
+ }
+
+ do {
+ bytes_this_chunk = bytes_remaining;
+ memset(data, 0, sizeof(data));
+
+ 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%08x\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
+ status = LIBUSB_ERROR_TIMEOUT;
+ retry = 0;
+ do {
+ status = libusb_control_transfer(handle,
+
LIBUSB_ENDPOINT_OUT|LIBUSB_REQUEST_TYPE_VENDOR|LIBUSB_RECIPIENT_DEVICE,
+ 0xA0, //
bRequest: Vendor (Cypress)
+ cur_addr & 0xFFFF, // wValue
(address LSW)
+ cur_addr >> 16, // wIndex
(address MSW)
+ data, // data
+ (uint16_t)bytes_this_chunk, // wLength
+ 1000); // timeout
in ms
+ } while ((status == LIBUSB_ERROR_TIMEOUT) && (retry++
<= RETRY_LIMIT));
+
+ if (status != bytes_this_chunk) {
+ // For FX3, libusbx will return an I/O error
after upload, and 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) || (feof(fw)))
+ break;
+
+ } while (status >= 0);
+
+ if (!fx3_mode) {
+ // Bring the CPU out of reset (FX2)
+ if (fx2_reset(handle, false))
+ return 1;
+ }
+
+ return 0;
+}
+
static int test_device(uint16_t vid, uint16_t pid)
{
libusb_device_handle *handle;
@@ -878,6 +1022,10 @@ static int test_device(uint16_t vid, uint16_t pid)
case USE_HID:
test_hid(handle, endpoint_in);
break;
+ case USE_FX2:
+ case USE_FX3:
+ CALL_CHECK(upload_to_fx_ram(handle, binary_name, (test_mode ==
USE_FX3)));
+ break;
case USE_SCSI:
CALL_CHECK(test_mass_storage(handle, endpoint_in,
endpoint_out));
case USE_GENERIC:
@@ -933,7 +1081,20 @@ int main(int argc, char** argv)
case 'd':
debug_mode = true;
break;
+ case 'f':
+ test_mode = USE_FX2;
+ // Fall through
+ case 'g':
+ if (!VID && !PID) {
+ // Cypress FX2/FX3 DVK VID/PID
+ VID = 0x04B4;
+ PID = (test_mode ==
USE_FX2)?0x8613:0x0053;
+ }
+ if (test_mode != USE_FX2)
+ test_mode = USE_FX3;
+ // Fall through
case 'b':
+ binary_dump = true; // doesn't
matter for FX2/FX3
if (j+1 < argc) {
// WDK's OACR doesn't like
strncpy...
for (i=0;
(i<(sizeof(binary_name)-1)) && (argv[j+1][i] != 0); i++)
@@ -941,9 +1102,8 @@ int main(int argc, char** argv)
binary_name[i] = 0;
j++;
}
- binary_dump = true;
break;
- case 'g':
+ case 't':
break;
case 'j':
// OLIMEX ARM-USB-TINY JTAG, 2 channel
composite device - 2 interfaces
@@ -1002,16 +1162,18 @@ int main(int argc, char** argv)
}
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|g} [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(" -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");
- printf(" -p: test Sony PS3 SixAxis controller (using
WinUSB)\n");
- printf(" -s: test Microsoft Sidewinder Precision Pro (using
HID)\n");
- printf(" -x: test Microsoft XBox Controller Type S (using
WinUSB)\n");
+ printf(" -b: dump Mass Storage first block to binary file
(default='data.bin')\n");
+ printf(" -f: upload firmware to Cypress FX2 RAM
(default='data.bin')\n");
+ printf(" -g: upload firmware to Cypress FX3 RAM
(default='data.bin')\n");
+ printf(" -k: test generic Mass Storage USB device\n");
+ printf(" -j: test FTDI based JTAG device\n");
+ printf(" -p: test Sony PS3 SixAxis controller\n");
+ printf(" -s: test Microsoft Sidewinder Precision Pro\n");
+ printf(" -x: test Microsoft XBox Controller\n");
+ printf(" -t: short generic test (default)\n");
return 0;
}
--
1.7.11.msysgit.0
------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and
threat landscape has changed and how IT managers can respond. Discussions
will include endpoint security, mobile security and the latest in malware
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
_______________________________________________
libusbx-devel mailing list
libusbx-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/libusbx-devel