From b74b7f7390690f631274b46ef2bbe7984d825eec Mon Sep 17 00:00:00 2001 From: Federico Manzan Date: Sun, 10 Mar 2013 21:00:00 +0000 Subject: Samples: Add FX3 firmware upload support for fxload --- examples/ezusb.c | 101 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ examples/ezusb.h | 12 ++++--- examples/fxload.c | 6 ++-- 3 files changed, 113 insertions(+), 6 deletions(-) (limited to 'examples') diff --git a/examples/ezusb.c b/examples/ezusb.c index 13404ee..2ab7188 100644 --- a/examples/ezusb.c +++ b/examples/ezusb.c @@ -3,6 +3,7 @@ * Copyright © 2001-2002 David Brownell (dbrownell@users.sourceforge.net) * Copyright © 2008 Roger Williams (rawqux@users.sourceforge.net) * Copyright © 2012 Pete Batard (pete@akeo.ie) + * Copyright © 2013 Federico Manzan (f.manzan@gmail.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -141,6 +142,29 @@ static int ezusb_write(libusb_device_handle *device, const char *label, return (status < 0) ? -EIO : 0; } +/* + * Issues the specified vendor-specific read request. + */ +static int ezusb_read(libusb_device_handle *device, const char *label, + uint8_t opcode, uint32_t addr, const unsigned char *data, size_t len) +{ + int status; + + if (verbose) + logerror("%s, addr 0x%08x len %4u (0x%04x)\n", label, addr, (unsigned)len, (unsigned)len); + status = libusb_control_transfer(device, + LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE, + opcode, addr & 0xFFFF, addr >> 16, + (unsigned char*)data, (uint16_t)len, 1000); + if (status != len) { + if (status < 0) + logerror("%s: %s\n", label, libusb_error_name(status)); + else + logerror("%s ==> %d\n", label, status); + } + return (status < 0) ? -EIO : 0; +} + /* * Modifies the CPUCS register to stop or reset the CPU. * Returns false on error. @@ -502,6 +526,80 @@ static int ram_poke(void *context, uint32_t addr, bool external, return rc; } +/* + * Load an Cypress Image file into target RAM. + * The file is assumed to be in Cypress IMG format. + */ +int fx3_load_ram(libusb_device_handle *device, const char *path) +{ + unsigned int dCheckSum, dExpectedCheckSum, dAddress, i, dLen, dLength; + unsigned short wSignature; + unsigned int dImageBuf[512 * 1024]; + unsigned char *bBuf, rBuf[4096]; + FILE *image; + + image = fopen(path, "rb"); + if (image == NULL) { + logerror("%s: unable to open for input.\n", path); + return -2; + } else if (verbose) + logerror("open firmware image %s for RAM upload\n", path); + + fread(&wSignature, 1, 2, image); // read signature bytes + if (wSignature != 0x5943) { // check CY signature byte + logerror("Invalid image"); + return -3; + } + fread(&i, 2, 1, image); // skip 2 dummy bytes + + dCheckSum = 0; + while (1) { + fread(&dLength, 4, 1, image); // read dLength + fread(&dAddress, 4, 1, image); // read dAddress + if (dLength == 0) + break; // done + + // read sections + fread(dImageBuf, 4, dLength, image); + for (i = 0; i < dLength; i++) + dCheckSum += dImageBuf[i]; + dLength <<= 2; // convert to Byte length + bBuf = (unsigned char*) dImageBuf; + + while (dLength > 0) { + dLen = 4096; // 4K max + if (dLen > dLength) + dLen = dLength; + ezusb_write(device, "Write firmware", RW_INTERNAL, dAddress, bBuf, dLen); + ezusb_read(device, "Read firmware", RW_INTERNAL, dAddress, rBuf, dLen); + // Verify data: rBuf with bBuf + for (i = 0; i < dLen; i++) { + if (rBuf[i] != bBuf[i]) { + logerror("Fail to verify image"); + return -3; + } + } + + dLength -= dLen; + bBuf += dLen; + dAddress += dLen; + } + } + + // read pre-computed checksum data + fread(&dExpectedCheckSum, 4, 1, image); + if (dCheckSum != dExpectedCheckSum) { + logerror("Fail to boot due to checksum error\n"); + return -4; + } + + // transfer execution to Program Entry + ezusb_write(device, "Jump command", RW_INTERNAL, dAddress, NULL, 0); + + logerror("Done!\n"); + return 0; +} + /* * Load a firmware file into target RAM. device is the open libusbx * device, and the path is the name of the source file. Open the file, @@ -525,6 +623,9 @@ int ezusb_load_ram(libusb_device_handle *device, const char *path, int fx_type, int status; uint8_t iic_header[8] = { 0 }; + if (fx_type == FX_TYPE_FX3) + return fx3_load_ram(device, path); + image = fopen(path, "rb"); if (image == NULL) { logerror("%s: unable to open for input.\n", path); diff --git a/examples/ezusb.h b/examples/ezusb.h index 5ea4237..2bbe979 100644 --- a/examples/ezusb.h +++ b/examples/ezusb.h @@ -3,6 +3,7 @@ /* * Copyright © 2001 Stephen Williams (steve@icarus.com) * Copyright © 2002 David Brownell (dbrownell@users.sourceforge.net) + * Copyright © 2013 Federico Manzan (f.manzan@gmail.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -42,15 +43,17 @@ #define FX_TYPE_FX1 1 /* Updated Cypress versions */ #define FX_TYPE_FX2 2 /* USB 2.0 versions */ #define FX_TYPE_FX2LP 3 /* Updated FX2 */ -#define FX_TYPE_MAX 4 -#define FX_TYPE_NAMES { "an21", "fx", "fx2", "fx2lp" } +#define FX_TYPE_FX3 4 /* USB 3.0 versions */ +#define FX_TYPE_MAX 5 +#define FX_TYPE_NAMES { "an21", "fx", "fx2", "fx2lp", "fx3" } #define IMG_TYPE_UNDEFINED -1 #define IMG_TYPE_HEX 0 /* Intel HEX */ #define IMG_TYPE_IIC 1 /* Cypress 8051 IIC */ #define IMG_TYPE_BIX 2 /* Cypress 8051 BIX */ -#define IMG_TYPE_MAX 3 -#define IMG_TYPE_NAMES { "Intel HEX", "Cypress 8051 IIC", "Cypress 8051 BIX" } +#define IMG_TYPE_IMG 3 /* Cypress IMG format */ +#define IMG_TYPE_MAX 4 +#define IMG_TYPE_NAMES { "Intel HEX", "Cypress 8051 IIC", "Cypress 8051 BIX", "Cypress IMG format" } /* * Automatically identified devices (VID, PID, type, designation). @@ -75,6 +78,7 @@ typedef struct { { 0x0547, 0x2236, FX_TYPE_AN21, "Cypress EZ-USB (2236)" },\ { 0x04b4, 0x6473, FX_TYPE_FX1, "Cypress EZ-USB FX1" },\ { 0x04b4, 0x8613, FX_TYPE_FX2LP, "Cypress EZ-USB FX2LP (68013A/68014A/68015A/68016A)" }, \ + { 0x04b4, 0x00f3, FX_TYPE_FX3, "Cypress FX3" },\ } /* diff --git a/examples/fxload.c b/examples/fxload.c index 42e0ca4..7086fe7 100644 --- a/examples/fxload.c +++ b/examples/fxload.c @@ -24,7 +24,7 @@ * This program supports uploading firmware into a target USB device. * * -I -- Upload this firmware - * -t -- uController type: an21, fx, fx2, fx2lp + * -t -- uController type: an21, fx, fx2, fx2lp, fx3 * * -D -- Use this device, instead of $DEVICE * @@ -123,7 +123,7 @@ int main(int argc, char*argv[]) logerror("no firmware specified!\n"); usage: fprintf(stderr, "\nusage: %s [-vV] [-t type] [-D vid:pid] -I firmware\n", argv[0]); - fprintf(stderr, " type: one of an21, fx, fx2, fx2lp\n"); + fprintf(stderr, " type: one of an21, fx, fx2, fx2lp, fx3\n"); return -1; } @@ -237,6 +237,8 @@ usage: img_type[i] = IMG_TYPE_IIC; else if (_stricmp(ext, ".bix") == 0) img_type[i] = IMG_TYPE_BIX; + else if (_stricmp(ext, ".img") == 0) + img_type[i] = IMG_TYPE_IMG; else { logerror("%s is not a recognized image type\n", path[i]); goto err; -- cgit v1.2.3