diff --git a/src/examples/i2ceeprom.py b/src/examples/i2ceeprom.py index 2de2acf..e7e84f3 100644 --- a/src/examples/i2ceeprom.py +++ b/src/examples/i2ceeprom.py @@ -1,40 +1,219 @@ #!/usr/bin/env python +import argparse, os, struct, sys, time + +# Check if were running on Python2.7 +if (sys.version[0:3] != "2.7"): + print("This script is meant to be run on python2.7.x ! Exiting") + exit(1) + +found=False +# Check if MPSSE lib can be found in pythons path first +for path in range(len(sys.path)): + if sys.path[path] != '' and os.path.exists(sys.path[path]) and os.path.isdir(sys.path[path]): + mpssename = "%s/mpsse.pyc" % sys.path[path] + if os.path.exists(mpssename) and os.path.isfile(mpssename): + found = True +# Try to locate mpsse in typical default dirs, if not found. +if found != True : + custom_paths = ['/usr/lib/python2.7/site-packages', '/usr/local/lib/python2.7/site-packages', '/usr/lib64/python2.7/site-packages', '/usr/local/lib64/python2.7/site-packages'] + for path in range(len(custom_paths)): + if custom_path[path] != '' and os.path.exists(custom_path[path]) and os.path.isdir(custom_path[path]): + mpssename = "%s/mpsse.pyc" % custom_path[path] + if os.path.exists(mpssename) and os.path.isfile(mpssename): + sys.path.append(custom_path[path]) + found = True +if found != True: + print("MPSSE Library could not be found. Exiting") + exit(1) + +from fish import ProgressFish from mpsse import * -SIZE = 0x8000 # Size of EEPROM chip (32 KB) -WCMD = "\xA0\x00\x00" # Write start address command -RCMD = "\xA1" # Read command -FOUT = "eeprom.bin" # Output file +parser = argparse.ArgumentParser(prog="i2c-eeprom", description="i2c-eeprom utility based on python-mpsse") +parser.add_argument("-a", "--addressbits", help="addresstype (8 / 16), default to 8bits for <=16kbit size, 16bits for eeprom > 16kbit", type=int, required=0, metavar="<8 / 16>", action="store", dest="addressbits") +parser.add_argument("-s", "--size", help="eeprom size in bytes", type=int, metavar="", action="store", dest="eeprom_size", required=1) +parser.add_argument("-p", "--pagesize", help="count of bytes per page", type=int, metavar="", action="store", dest="page_size", required=1) +parser.add_argument("-e", "--erase", help="erase eeprom (to FFh Values)", action="store_true", dest="mode_erase") +parser.add_argument("-r", "--read", help="read eeprom to ", type=str, metavar="", action="store", dest="readfilename") +parser.add_argument("-w", "--write", help="write to eeprom", type=str, metavar="", action="store", dest="writefilename") +parser.add_argument("-d", "--eeprom-id", help="3bit device-address of eeprom, hardwired, default = 0", metavar="<0-7>", type=int, default=0, action="store", dest="devaddress") +parser.add_argument("-c", "--count", help="number of bytes to read in read-mode. default = full eeprom-size", metavar="<0-524288>", type=long, action="store", dest="bytecount") +parser.add_argument("-o", "--offset", help="bytenumber to start reading at. default = 0", metavar="<0-524287>", type=long, default=0, action="store", dest="offset") +parser.add_argument("-S", "--speed", help="I2C bus frequency. default = 100000KHz", metavar="", type=str, action="store", dest="speed") +parser.add_argument("-i", "--devicecode", help="Vendor_ID:Product_ID default = 0403:6010", metavar="", type=str, default="0403:6010", action="store", dest="devid") +parser.add_argument("-I", "--interface", help="Interface to use (if FTDI-device has multiple UART-interfaces). default = A", metavar="", type=str, default="A", action="store", dest="iface") +parser.add_argument("-v", "--verbose", help="increase output verbosity", action="store_true") -try: - eeprom = MPSSE(I2C, FOUR_HUNDRED_KHZ) +args = parser.parse_args() + +if (args.devid != "0403:6010"): + vendor_id = int(args.devid.split(':')[0], 16) + product_id = int(args.devid.split(':')[1], 16) +else: + vendor_id = int("0403", 16) + product_id = int("6010", 16) + +if (args.iface == "A"): + IFACE=IFACE_A +elif (args.iface == "B"): + IFACE=IFACE_B +elif (args.iface == "C"): + IFACE=IFACE_C +elif (args.iface == "D"): + IFACE=IFACE_D +else: + parser.print_help() + print("This script supports interfaces A to D only !") + sys.exit(1) + +if ((args.mode_erase == False) and (args.readfilename == None) and (args.writefilename == None)): + parser.print_help() + print("\nYou need to specify either erase or read/write - mode!") + sys.exit(1) + +if (((args.mode_erase == True) and (args.readfilename != None)) or ((args.mode_erase == True) and (args.writefilename != None)) or ((args.writefilename != None) and (args.readfilename != None))): + parser.print_help() + print ("\nYou can only read OR write OR erase at a time ;) !") + sys.exit(1) + +if (args.addressbits != None): + addressbits = args.addressbits +elif ((args.addressbits == None) and (args.eeprom_size <= 2048)): + addressbits = 8 +else: + addressbits = 16 - print "%s initialized at %dHz (I2C)" % (eeprom.GetDescription(), eeprom.GetClock()) +FLASHSIZE = args.eeprom_size +PAGESIZE = args.page_size +PAGECOUNT = FLASHSIZE / PAGESIZE +MODE = None +DATA = '' - eeprom.Start() - eeprom.Write(WCMD) +if (args.speed != None): + if (args.speed == "ONE_HUNDRED_KHZ"): + SPEED = ONE_HUNDRED_KHZ + elif (args.speed == "FOUR_HUNDRED_KHZ"): + SPEED = FOUR_HUNDRED_KHZ + elif (args.speed == "ONE_MHZ"): + SPEED = ONE_MHZ + else: + parser.print_help() + print('Speed must be set to "ONE_HUNDRED_KHZ" or "FOUR_HUNDRED_KHZ" or "ONE_MHZ" (Default : ONE_HUNDRED_KHZ)!') + sys.exit(1) +else: + SPEED=ONE_HUNDRED_KHZ + +if (args.devaddress <= 7): + DEVADDR = args.devaddress +else: + parser.print_help() + print("\nOnly 8 chained i2c-eeprom-devices on one i2c-bus possible !") + +if (args.mode_erase == True): + HEXDATA = chr(255)*PAGESIZE + MODE = "erase" + +if (args.writefilename != None): + HEXDATA = open(args.writefilename, 'rb').read() + PAGECOUNT = len(HEXDATA) / PAGESIZE + MODE = "write" + +if (args.readfilename != None): + readfilename = args.readfilename + MODE = "read" - if eeprom.GetAck() == ACK: +if (args.bytecount != None): + bytecount = args.bytecount +else: + bytecount = FLASHSIZE +fish= ProgressFish(total=PAGECOUNT) + +try: + if (MODE == "read"): + eeprom = MPSSE(None) + eeprom.Open(vendor_id, product_id, I2C, SPEED, MSB, IFACE) + print "FTDI I2C initialized at %dHz" % (eeprom.GetClock()) + addressbyte = args.offset + addressbyte = 0 + if (addressbits == 8): + addr = divmod(addressbyte, 256) + byteaddress = struct.pack('BB', (160 + ((addr[0] + DEVADDR) * 2)), addr[1]) + else: + addr = divmod(addressbyte, 65536) + byteaddress = struct.pack('B', (160 + ((addr[0] + DEVADDR) * 2))) + struct.pack('>H', addr[1]) eeprom.Start() - eeprom.Write(RCMD) - - if eeprom.GetAck() == ACK: - data = eeprom.Read(SIZE) - eeprom.SendNacks() - eeprom.Read(1) + if (args.verbose == True): + print("Writing byteaddress %s" % byteaddress.encode('hex')) + eeprom.Write(byteaddress) + if eeprom.GetAck() != ACK: + print "Error writing byteaddress !" else: - raise Exception("Received read command NACK!") + if (args.verbose == True): + print("Eeprom acknowledged byteaddress.") + eeprom.Start() + eeprom.Write(struct.pack('B', (161 + (DEVADDR * 2)))) + if eeprom.GetAck() != ACK: + print "Error writing readcommand!" + else: + if (args.verbose == True): + print("Eeprom acknowledged readcommand, start reading %d bytes from eeprom." % bytecount) + DATA = eeprom.Read(bytecount) + eeprom.SendNacks() + eeprom.Stop() + eeprom.Close() + open(readfilename, "wb").write(DATA) + print "Dumped %d bytes to %s" % (len(DATA), readfilename) else: - raise Exception("Received write command NACK!") - - eeprom.Stop() - - open(FOUT, "wb").write(data) - print "Dumped %d bytes to %s" % (len(data), FOUT) - - eeprom.Close() + eeprom = MPSSE(None) + eeprom.Open(vendor_id, product_id, I2C, SPEED, MSB, IFACE) + print "FTDI I2C initialized at %dHz" % (eeprom.GetClock()) + for PAGENUM in range(PAGECOUNT): + BYTENUM = PAGENUM * PAGESIZE + if (addressbits == 8): + address = divmod(BYTENUM, 256) + pageaddress = struct.pack('BB', (160 + ((DEVADDR + address[0]) * 2)), address[1]) + else: + address = divmod(BYTENUM, 65536) + pageaddress = struct.pack('B', (160 + ((DEVADDR + address[0]) * 2))) + struct.pack('>H', address[1]) + eeprom.Start() + eeprom.Write(pageaddress) + if eeprom.GetAck() != ACK: + print "Error writing pageaddress for page %d" % PAGENUM + break + else: + if (MODE == "write"): + data = HEXDATA[BYTENUM:(BYTENUM+PAGESIZE)] + if (args.verbose == True): + print("Eeprom acknowledged pageaddress %s, start writing data to eeprom.\nData = \n%s" % ('\\x' + '\\x'.join(x.encode('HEX') for x in pageaddress), data.encode('hex'))) + eeprom.Write(data) + if eeprom.GetAck() != ACK: + print "Error writing page %d" % PAGENUM + break + else: + if (args.verbose == True): + print("Eeprom acknowledged pagewrite for page %d" % PAGENUM) + elif (MODE == "erase"): + if (args.verbose == True): + print("Eeprom acknowledged pageaddress %s, start erasing page %d with \\xFF * %d" % ('\\x' + '\\x'.join(x.encode('HEX') for x in pageaddress), PAGENUM, PAGESIZE)) + eeprom.Write(HEXDATA) + if eeprom.GetAck() != ACK: + print "Error erasing page %d" % PAGENUM + break + else: + if (args.verbose == True): + print("Eeprom acknowledged erase of page %d" % PAGENUM) + eeprom.Stop() + time.sleep(1/1000.0 * 5) + if (args.verbose == False): + fish.animate(amount=(PAGENUM + 1)) + if (MODE == "write"): + print("Finished writing %s to eeprom !" % args.writefilename) + elif (MODE == "erase"): + print("Erase of flash finished !") + eeprom.Close() + except Exception, e: print "MPSSE failure:", e - +sys.exit(0) diff --git a/src/examples/spiflash.py b/src/examples/spiflash.py index 5429d48..e7ce1a0 100644 --- a/src/examples/spiflash.py +++ b/src/examples/spiflash.py @@ -11,17 +11,15 @@ class SPIFlash(object): CECMD = "\xc7" # Standard SPI flash chip erase command (0xC7) IDCMD = "\x9f" # Standard SPI flash chip ID command (0x9F) - ID_LENGTH = 3 # Normal SPI chip ID length, in bytes ADDRESS_LENGTH = 3 # Normal SPI flash address length (24 bits, aka, 3 bytes) - BLOCK_SIZE = 256 # SPI block size, writes must be done in multiples of this size PP_PERIOD = .025 # Page program time, in seconds - + def __init__(self, speed=FIFTEEN_MHZ): # Sanity check on the specified clock speed if not speed: speed = FIFTEEN_MHZ - + self.flash = MPSSE(SPI0, speed, MSB) self.chip = self.flash.GetDescription() self.speed = self.flash.GetClock() @@ -50,7 +48,7 @@ def Read(self, count, address=0): return data - def Write(self, data, address=0): + def Write(self, data, address=0, blocksize=256): count = 0 while count < len(data): @@ -60,12 +58,12 @@ def Write(self, data, address=0): self.flash.Stop() self.flash.Start() - self.flash.Write(self.WCMD + self._addr2str(address) + data[address:address+self.BLOCK_SIZE]) + self.flash.Write(self.WCMD + self._addr2str(address) + data[address:address+blocksize]) self.flash.Stop() sleep(self.PP_PERIOD) - address += self.BLOCK_SIZE - count += self.BLOCK_SIZE + address += blocksize + count += blocksize def Erase(self): self.flash.Start() @@ -76,10 +74,10 @@ def Erase(self): self.flash.Write(self.CECMD) self.flash.Stop() - def ChipID(self): + def ChipID(self, idlen): self.flash.Start() self.flash.Write(self.IDCMD) - chipid = self.flash.Read(self.IDLEN) + chipid = self.flash.Read(idlen) self.flash.Stop() return chipid @@ -117,9 +115,11 @@ def usage(): print "\t-r, --read= Read data from the chip to file" print "\t-w, --write= Write data from file to the chip" print "\t-s, --size= Set the size of data to read/write" + print "\t-b, --blocksize= Set the block/page - size of data to read/write [256]" print "\t-a, --address= Set the starting address for the read/write operation [0]" print "\t-f, --frequency= Set the SPI clock frequency, in hertz [15,000,000]" print "\t-i, --id Read the chip ID" + print "\t-l, --id_len= Length of chip ID in bytes [3]" print "\t-v, --verify Verify data that has been read/written" print "\t-e, --erase Erase the entire chip" print "\t-p, --pin-mappings Display a table of SPI flash to FTDI pin mappings" @@ -134,11 +134,13 @@ def main(): action = None verify = False address = 0 + blocksize = 256 + id_len = 3 size = 0 data = "" try: - opts, args = GetOpt(sys.argv[1:], "f:s:a:r:w:eipvh", ["frequency=", "size=", "address=", "read=", "write=", "id", "erase", "verify", "pin-mappings", "help"]) + opts, args = GetOpt(sys.argv[1:], "f:s:b:l:a:r:w:eipvh", ["frequency=", "size=", "blocksize=", "id_len=","address=", "read=", "write=", "erase", "id", "verify", "pin-mappings", "help"]) except GetoptError, e: print e usage() @@ -148,6 +150,8 @@ def main(): freq = int(arg) elif opt in ('-s', '--size'): size = int(arg) + elif opt in ('-b', '--blocksize'): + blocksize = int(arg) elif opt in ('-a', '--address'): address = int(arg) elif opt in ('-r', '--read'): @@ -158,6 +162,8 @@ def main(): fname = arg elif opt in ('-i', '--id'): action = "id" + elif opt in ('-l', '--id_length'): + id_len = int(arg) elif opt in ('-e', '--erase'): action = "erase" elif opt in ('-v', '--verify'): @@ -193,15 +199,15 @@ def main(): data = open(fname, 'rb').read() if not size: size = len(data) - - sys.stdout.write("Writing %d bytes from %s to the chip starting at address 0x%X..." % (size, fname, address)) + sys.stdout.write("Writing %d bytes from %s to the chip starting at address 0x%X using a blocksize of %d ..." % (size, fname, address, blocksize)) sys.stdout.flush() spi.Write(data[0:size], address) print "done." elif action == "id": - - for byte in spi.ChipID(): + if not id_len: + id_len = 3 + for byte in spi.ChipID(id_len): print ("%.2X" % ord(byte)), print "" @@ -231,4 +237,3 @@ def main(): spi.Close() main() - diff --git a/src/mpsse.c b/src/mpsse.c index b929b81..8fb75c1 100644 --- a/src/mpsse.c +++ b/src/mpsse.c @@ -31,7 +31,8 @@ struct vid_pid supported_devices[] = { { 0x0403, 0x8879, "Bus Blaster v2 (channel B)" }, { 0x0403, 0xBDC8, "Turtelizer JTAG/RS232 Adapter A" }, { 0x0403, 0xCFF8, "Amontec JTAGkey" }, - { 0x0403, 0x8A98, "TIAO Multi Protocol Adapter"}, + { 0x0403, 0x8A98, "TIAO Multi Protocol Adapter"}, + { 0x0403, 0x8A99, "TIAO Multi Protocol Adapter Lite"}, { 0x15BA, 0x0003, "Olimex Ltd. OpenOCD JTAG" }, { 0x15BA, 0x0004, "Olimex Ltd. OpenOCD JTAG TINY" },