📄 ezusb_loader.cpp
字号:
/* * Copyright (C) 1999 Dirk-Willem van Gulik, dirkx@webweaving.org * WebWeaving Consultancy, All rights reserved. * * Original version for FreeBSD; Changes for Linux by Brad Hards, * brad.hards@dao.defence.gov.au. See '#ifdef BSD'. * * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY WEBWEAVING AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL WEBWEAVING OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ * * This downloader should work with all with all USB-EZ Anchorchips which * have on board ram; i.e. the AN21y1, AN21y5 and AN21y6QC series. Where y * is the log2 of the internal memory size (i.e. aAN2146QC has 2^64=16kByte * of ram.) * * It has however only been tested; and written specifically for the * ActiveWire Inc. USB board. See * http://www.activewireinc.com * * Anchorchips has excelent documentation on line at * http://www.anchorchips.com *//* This file is part of PXA250 USB JTAG controller. It has been heavily modified by Jean-Marc Koller and then by Julien Pilet <julien.pilet@epfl.ch> and Stephane Magnenat <stephane.magnenat@epfl.ch>*//*! This is the implementation of the EzUSB loader * * \author Dirk-Willem van Gulik <dirkx@webweaving.org> (FreeBSD original version) * \author Brad Hards <brad.hards@dao.defence.gov.au> (Linux version) * \author Jean-Marc Koller <jean-marc.koller@csem.ch> (fix and enhancement) * \author Julien Pilet <julien.pilet@epfl.ch> (C++ version) * \author Stephane Magnenat <stephane.magnenat@epfl.ch> (C++ version) */#include <string.h>#include <stdlib.h>#include <stdio.h>#include <unistd.h>#include <errno.h>#ifdef HAVE_GETOPT_LONG#include <getopt.h>#endif#include "ezusb_loader.h"#include "jtag_order.h"#include "jtag.h"#include "filemanager.h"EzUSB::EzUSB(const char *filename){ idVendor=0x547; idProduct=0x2131; if (filename) { strncpy(this->filename, filename, 1024); this->filename[sizeof(this->filename)-1]=0; } else this->filename[0]=0; devHandle=NULL;};EzUSB::~EzUSB(void){ forceClose();}void EzUSB::forceClose(void){ if (devHandle) { //usb_release_interface(devHandle, 0); //usb_close(devHandle); //printf("Closing device\n"); printf("USB : Reseting device\n"); usb_reset(devHandle); }}void EzUSB::parseCmdLine(int argc, char *argv[]){#ifdef HAVE_GETOPT_LONG int ch; struct option longOptions[] = { {"idvendor", 1, 0, 'v'}, {"idproduct", 1, 0, 'p'}, {"filaname", 1, 0, 'f'}, {0, 0, 0, 0} }; // handle the arguments while((ch = getopt_long(argc, argv, "vpf", longOptions, NULL)) != -1) { switch (ch) { case 'v': idVendor=atoi(optarg); break; case 'p': idProduct=atoi(optarg); break; case 'f': if (optarg) { strncpy(filename, optarg, 1024); filename[sizeof(filename)-1]=0; } break; default: break; }; }#else if (argc>1) fprintf(stderr, "WARNING ignoring arguments for EzUSB" " initialisation: getopt_long is not available !\n");#endif}bool EzUSB::findDevice(void){ struct usb_bus* bus; struct usb_device* device; if (devHandle) { // TODO : libusb doesn't seems to work here, check on other plateform /*printf("USB : Device already exists, reloading...\n"); usb_resetep(devHandle, 2); usb_release_interface( devHandle, 0); //return true;*/ //usb_reset(devHandle); } usb_init(); usb_find_busses(); usb_find_devices(); printf("USB : Enumerating USB\n"); for( bus=usb_busses; bus; bus=bus->next ) { for( device=bus->devices; device; device=device->next ) { printf(" Device found : Vendor=0x%x Product=0x%x\n", device->descriptor.idVendor, device->descriptor.idProduct ); if (device->descriptor.idVendor==idVendor && device->descriptor.idProduct==idProduct) { printf(" Correct device found :-)\n"); devHandle = usb_open( device ); if (devHandle) { printf(" Device has been opened\n"); return true; } else { fprintf(stderr, " Can't open device handle : %s\n", usb_strerror()); return false; } } } } fprintf(stderr, "USB : Device %x, %x can't be found\n", idVendor, idProduct); return false;}bool EzUSB::downloadFirmware(const char *fn){ /* See http://www.anchorchips.com for the * EZ-USB Technical Reference Manual (EZUSB_TRM.pdf). */ #define CPUCS 0x7f92 #define USBSC 0x7fd6 FILE *f=NULL; struct intels *hx, *d; char b[2]; int count; if (!devHandle) return false;// usb_set_configuration(devHandle, 1); // Claim the interface if (usb_claim_interface(devHandle, 0)<0) { fprintf(stderr, "USB : Can't claim interface : %s\n", usb_strerror()); return false; } // Set alternate interface if (usb_set_altinterface(devHandle,0) < 0 ) { fprintf(stderr, "USB : Can't set alternate interface : %s\n", usb_strerror()); return false; } // Open hex file const char *firmware = fn; if (filename && filename[0] != 0) // if the option -f <file> was provided firmware = filename; // use it. if (!(f=fileManagerPtr->openFP(firmware, "r"))) { fprintf(stderr, "USB : Can't open HEX file '%s' : %s\n", firmware, strerror(errno)); return false; } // Read hex file hx = NULL; if (!read_head(f, &hx)) { fprintf(stderr, "USB : Can't read HEX file\n"); fclose(f); return false; } fclose(f); // Sent reset b[0] = 1; if (shunt(devHandle, CPUCS, (void *) b, 1)<0) { fprintf(stderr, "USB : Could not send command to bring device in reset: %s\n", usb_strerror()); return false; } else { printf("USB : Command to bring 8051 to reset sent.\n"); } // Send data usleep(250000); printf("USB : Downloading "); count=0; for( d = hx; d; d = d->nxt) {#if 0 if ((d->len == 1) && (plen == 64) && (d->nxt == NULL)) fprintf(stderr,"Warning - Some chips cannot cope with 64*n+1 downloads\n" "See the erratum on the anchorchip.com site\n");#endif if (shunt(devHandle, d->addr, (void *) (d->data), d->len)<0) { fprintf(stderr, "USB : Download failed : %s\n", usb_strerror()); return false; } printf("."); fflush(stdout); count++; } printf("\nUSB : All %d packets downloaded.\n", count); usleep(250000); b[0] = 0; if (shunt(devHandle, CPUCS, (void *) b, 1)<0) { fprintf(stderr, "USB : Warning: Could not send command to get the device out of reset: %s\n", usb_strerror()); return false; } else printf("USB : Command to bring 8051 out of reset sent.\n"); usleep(100000); //usb_reset(devHandle); //findDevice(); return true;}/* This whole reading routine sucks. you could do it in * about 12 lines with scanf(). But this is the result * from testing it on too many hex files which went through * mac/pc/unic/mail conversion loops. * * Conceptually the format is simple, just a hex * string prefixed by a colon and terminated by your * local flavour of a line break. * * ':' <len> <addr> <type> <len-data> <crc> '\r' * Where len, type and crc are two char hex, addr * is a 4 char hex value and len data is 2*len * hex chars. */int EzUSB::read_head(FILE * fh, struct intels * * doutp ){ unsigned char crc; unsigned char buff[256*2 + 9 + 2 + 1]; /* read buffer */ unsigned char tmp[5]; /* temp buf for conversions */ unsigned char data[256]; char *last; /* last character processed */ int len, type, c, i; int line = 1; /* current line number */ int comment = 0; /* are we in a comment? */ int addr; // quat_t :-)#define WHITESPACE " \t_-\a"#define LFCR "\r\n"#define COMMENT "#;/*" /* macro for error printing */#define BAIL(x) \ do { \ fprintf(stderr, "USB : %s at line %d\n", x, line); \ return 0; \ } while(0) /* XXX silly way of doing it. Should add a cyclic * buffer of course. And you could use fscanf if * you are not worried about broken lines. But * unfortunately we are. */ while(!feof(fh)) { /* * read in the first 9 bytes: * : <len> <addr> <type> -> 1+2+4+2 = 9 */ for(i = 0; i < 9 && (c = fgetc(fh)) != EOF; /* noop */) { if (index(LFCR, c)) { line++; comment = 0; continue; } else if (index(WHITESPACE, c)) { continue; } else if (index(COMMENT, c)) { comment = 1; } if (comment) continue; buff[i] = c; i++; } if (ferror(fh)) { BAIL(strerror(errno)); } else if (feof(fh)) { if (i) BAIL("HDR Truncated"); else BAIL("EOF before a type 1 line"); } /* the colon at the begginning of the line */ if (buff[0] != ':') BAIL("Colon expected"); /* the len field */ if (!isxdigit(buff[1]) || !isxdigit(buff[2])) BAIL("Len malformed"); memcpy(tmp, buff+1, 2); tmp[2]='\0'; len = strtol((const char *)tmp, &last, 16); if (last[0] != '\0') /* up to end of string? */ BAIL("Could not convert len"); if (len < 0 || len > 255) BAIL("Bad len (>255)"); /* the addr field */ if (!isxdigit(buff[3]) || !isxdigit(buff[4]) || !isxdigit(buff[5]) || !isxdigit(buff[6]) ) BAIL("Addr malformed"); memcpy(tmp, buff+3, 4); tmp[4]='\0'; addr = strtol((const char *)tmp, &last, 16); if (last[0]) /* up to end of string? */ BAIL("Could not convert addr"); /* the type field */ if (!isxdigit(buff[7]) || !isxdigit(buff[8])) BAIL("Type malformed"); memcpy(tmp, buff+7, 2); tmp[2]='\0'; type = strtol((const char *)tmp, &last, 16); if (last[0] != '\0') /* up to end of string? */ BAIL("Could not convert type"); if (type < 0 || type > 1) BAIL("Unkown type (not one of 00, 01)"); /* read 2 * len pairs and a CRC.. */ for(i = 0; i < 2*(len)+2 && (c = fgetc(fh)) != EOF;) { if (index(LFCR, c)) { line++; continue; } else if (index(WHITESPACE, c)) { continue; } if (!isxdigit(c)) BAIL("Malformed hex data"); buff[9+i] = c; i++; } if (ferror(fh)) { BAIL(strerror(errno)); } else if (i != 2*(len)+2) { BAIL("data or CRC block Truncated"); } for(i = 0; i < len+1+4; i++) { memcpy(tmp, buff+1+i*2, 2); tmp[2]='\0'; data[i] = strtol((const char *)tmp, &last, 16); if (last[0] != '\0') /* up to end of string? */ BAIL("Could not convert data or crc pair"); } for(crc = 0, i = 0; i < 4+len;i++) crc += data[i]; crc = ~crc + 1; if (crc != data[len+4]) BAIL("Checksum mismatch"); if (len && type == 0) { *doutp = (struct intels *)malloc(sizeof(intels)); (*doutp)->addr = addr; (*doutp)->len = len; (*doutp)->data = (unsigned char *)malloc(len); memcpy((*doutp)->data, data+4, len); doutp = &( (*doutp)->nxt ); } else if (type == 1) { break; } else { BAIL("Unkown intel type"); } } return 1;}int EzUSB::shunt(usb_dev_handle *pdev, int at, void *d, int len){ int err; err = usb_control_msg( pdev, 0x40,0xA0, at, 0, (char*)d, len, 1000 ); return err;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -