#!/usr/bin/env python """ # TOP2049 Open Source programming suite # # Commandline utility # # Copyright (c) 2009-2010 Michael Buesch # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. """ from toprammer_main import * import getopt def usage(): print "TOP2049 Open Source programming suite v%s" % VERSION print "" print "Usage: %s [OPTIONS]" % sys.argv[0] print "" print " -b|--bitfile The *.bit file (mandatory)" print " A full path to the bitfile is not required. Specifying the" print " chip-ID (see --list) usually is sufficient. The .bit file will" print " be searched for in the standard paths then." print "" print "Actions:" print " -s|--read-sig FILE Read the signature bytes" print " -x|--erase Erase the chip" print "" print " -p|--read-prog FILE Read the program memory" print " -P|--write-prog FILE Write the program memory" print "" print " -e|--read-eeprom FILE Read the EEPROM" print " -E|--write-eeprom FILE Write the EEPROM" print "" print " -f|--read-fuse FILE Read the fuse bits" print " -F|--write-fuse FILE Write the fuse bits" print "" print " -l|--read-lock FILE Read the lock bits" print " -L|--write-lock FILE Write the lock bits" print "" print "Optional:" print " -t|--list Print a list of supported chips and exit" print " -d|--device BUS.DEV Use the programmer at BUS.DEV" print " First found programmer is used, if not given." print " -V|--verbose LEVEL Set the verbosity level. Default = 1" print " -o|--force LEVEL Set the force level. Default = 0" print " Note that any value greater than 0 may brick devices" print " -Q|--noqueue Disable command queuing. Really slow!" print " -B|--broken Also use broken algorithms" print " -I|--in-format FMT Input file format. Default = autodetect" print " -O|--out-format FMT Output file format. Default = bin" print "" print "File formats (FMT):" print " auto Autodetect. (input only)" print " bin Raw binary data" print " ihex Intel hex" print " hex Human readable hex" class IO_ihex: TYPE_DATA = 0 TYPE_EOF = 1 TYPE_ESAR = 2 TYPE_SSAR = 3 TYPE_ELAR = 4 TYPE_SLAR = 5 def autodetect(self, data): try: self.toBinary(data) except (TOPException), e: return False return True def toBinary(self, ihexData): bin = [] try: lines = ihexData.splitlines() hiAddr = 0 for line in lines: line = line.strip() if len(line) == 0: continue if len(line) < 11 or (len(line) - 1) % 2 != 0: raise TOPException("Invalid IHEX format (length error)") if line[0] != ':': raise TOPException("Invalid IHEX format (magic error)") count = int(line[1:3], 16) if len(line) != count * 2 + 11: raise TOPException("Invalid IHEX format (count error)") addr = (int(line[3:5], 16) << 8) | int(line[5:7], 16) addr |= hiAddr << 16 type = int(line[7:9], 16) checksum = 0 for i in range(1, len(line), 2): byte = int(line[i:i+2], 16) checksum = (checksum + byte) & 0xFF checksum = checksum & 0xFF if checksum != 0: raise TOPException("Invalid IHEX format (checksum error)") if type == self.TYPE_EOF: break if type == self.TYPE_ELAR: if count != 2: raise TOPException("Invalid IHEX format (inval ELAR)") hiAddr = (int(line[9:11], 16) << 8) | int(line[11:13], 16) continue if type == self.TYPE_DATA: if len(bin) < addr + count: # Reallocate bin += ['\0'] * (addr + count - len(bin)) for i in range(9, 9 + count * 2, 2): byte = chr(int(line[i:i+2], 16)) if bin[(i - 9) / 2 + addr] != '\0': raise TOPException("Invalid IHEX format (corruption)") bin[(i - 9) / 2 + addr] = byte continue raise TOPException("Invalid IHEX format (unsup type %d)" % type) except ValueError: raise TOPException("Invalid IHEX format (digit format)") return "".join(bin) def fromBinary(self, binData): ihex = [] addr = 0 for i in range(0, len(binData), 16): if addr > 0xFFFF: checksum = 0 ihex.append(":%02X%04X%02X" % (2, 0, self.TYPE_ELAR)) checksum += 2 + 0 + 0 + self.TYPE_ELAR a = (addr >> 16) & 0xFFFF ihex.append("%04X" % a) checksum += ((a >> 8) & 0xFF) + (a & 0xFF) checksum = ((checksum ^ 0xFF) + 1) & 0xFF ihex.append("%02X\n" % checksum) addr -= 0xFFFF checksum = 0 size = min(len(binData) - i, 16) ihex.append(":%02X%04X%02X" % (size, addr, self.TYPE_DATA)) checksum += size + ((addr >> 8) & 0xFF) + (addr & 0xFF) + self.TYPE_DATA for j in range(0, size): data = ord(binData[i + j]) checksum = (checksum + data) & 0xFF ihex.append("%02X" % data) checksum = ((checksum ^ 0xFF) + 1) & 0xFF ihex.append("%02X\n" % checksum) addr += size ihex.append(":00000001FF\n") return "".join(ihex) class IO_hex: def autodetect(self, data): try: self.toBinary(data) except (TOPException), e: return False return True def toBinary(self, data): return parseHexdump(data) def fromBinary(self, data): return generateHexdump(data) class IO_binary: def autodetect(self, data): return True def toBinary(self, data): return data def fromBinary(self, data): return data IO_handlers = { "bin" : IO_binary, "ihex" : IO_ihex, "hex" : IO_hex, } def fileOut(filename, format, data): handler = IO_handlers[format]() data = handler.fromBinary(data) if filename == "-": sys.stdout.write(data) else: file(filename, "w+b").write(data) def fileIn(filename, format): if filename == "-": data = sys.stdin.read() else: data = file(filename, "rb").read() if format == "auto": if IO_ihex().autodetect(data): format = "ihex" elif IO_hex().autodetect(data): format = "hex" elif IO_binary().autodetect(data): format = "bin" else: assert(0) handler = IO_handlers[format]() data = handler.toBinary(data) return data def main(argv): opt_verbose = 1 opt_forceLevel = 0 opt_bitfile = None opt_device = None opt_action = None opt_file = None opt_noqueue = False opt_usebroken = False opt_informat = "auto" opt_outformat = "bin" try: (opts, args) = getopt.getopt(sys.argv[1:], "hb:d:V:Qs:xp:P:e:E:f:F:o:l:L:BtI:O:", [ "help", "bitfile=", "device=", "verbose=", "noqueue", "read-sig=", "erase", "read-prog=", "write-prog=", "read-eeprom=", "write-eeprom=", "read-fuse=", "write-fuse=", "read-lock=", "write-lock=", "force=", "broken", "list", "in-format=", "out-format=", ]) for (o, v) in opts: if o in ("-h", "--help"): usage() return 0 if o in ("-b", "--bitfile"): opt_bitfile = v if o in ("-t", "--list"): print "Supported chips:" dumpSupportedChips(sys.stdout) return 0 if o in ("-d", "--device"): try: v = v.split(".") opt_device = (int(v[0]), int(v[1])) except (IndexError, ValueError), e: print "-d|--device invalid BUS.DEV id." return 1 if o in ("-V", "--verbose"): opt_verbose = int(v) if o in ("-o", "--force"): opt_forceLevel = int(v) if o in ("-Q", "--noqueue"): opt_noqueue = True if o in ("-B", "--broken"): opt_usebroken = True if o in ("-I", "--in-format"): opt_informat = v.lower() if o in ("-O", "--out-format"): opt_outformat = v.lower() if o in ("-s", "--read-sig"): opt_action = "read-sig" opt_file = v if o in ("-x", "--erase"): opt_action = "erase" if o in ("-P", "--write-prog"): opt_action = "write-prog" opt_file = v if o in ("-p", "--read-prog"): opt_action = "read-prog" opt_file = v if o in ("-E", "--write-eeprom"): opt_action = "write-eeprom" opt_file = v if o in ("-e", "--read-eeprom"): opt_action = "read-eeprom" opt_file = v if o in ("-F", "--write-fuse"): opt_action = "write-fuse" opt_file = v if o in ("-f", "--read-fuse"): opt_action = "read-fuse" opt_file = v if o in ("-l", "--read-lock"): opt_action = "read-lock" opt_file = v if o in ("-L", "--write-lock"): opt_action = "write-lock" opt_file = v except (getopt.GetoptError, ValueError), e: usage() return 1 if not opt_bitfile: print "-b|--bitfile is mandatory!" return 1 if not opt_action: print "An action is mandatory!" return 1 if not opt_informat in ("auto", "bin", "ihex", "hex"): print "Invalid -I|--in-format" return 1 if not opt_outformat in ("bin", "ihex", "hex"): print "Invalid -O|--out-format" return 1 try: bitfile = bitfileFind(opt_bitfile) if not bitfile: print "Bitfile " + opt_bitfile + " not found" print "See --list for a list of supported devices" return 1 top = TOP(bitfileName = bitfile, busDev = opt_device, verbose = opt_verbose, forceLevel = opt_forceLevel, noqueue = opt_noqueue, usebroken = opt_usebroken) if opt_action == "read-sig": fileOut(opt_file, opt_outformat, top.readSignature()) elif opt_action == "erase": top.eraseChip() elif opt_action == "read-prog": fileOut(opt_file, opt_outformat, top.readProgmem()) elif opt_action == "write-prog": top.writeProgmem(fileIn(opt_file, opt_informat)) elif opt_action == "read-eeprom": fileOut(opt_file, opt_outformat, top.readEEPROM()) elif opt_action == "write-eeprom": top.writeEEPROM(fileIn(opt_file, opt_informat)) elif opt_action == "read-fuse": fileOut(opt_file, opt_outformat, top.readFuse()) elif opt_action == "write-fuse": top.writeFuse(fileIn(opt_file, opt_informat)) elif opt_action == "read-lock": fileOut(opt_file, opt_outformat, top.readLockbits()) elif opt_action == "write-lock": top.writeLockbits(fileIn(opt_file, opt_informat)) else: assert(0) top.shutdown() except (TOPException, BitfileException, IOError), e: print e return 1 return 0 if __name__ == "__main__": sys.exit(main(sys.argv))