EETool/Code/EECommander

284 lines
6.0 KiB
Python
Executable File

#!/usr/bin/python
import sys, getopt, serial, binascii, struct, time
class Mode:
NONE = 0
READ = 1
DUMP = 2
BURN = 3
CHECK = 4
class Command:
PREFIX = 0x42
NONE = 0
PING = 1
STARTRW = 2
READBLOCK = 3
READBLOCK_MASK = 4
WRITEBLOCK = 5
PONG = 'PONG'
BLOCKSIZE = 512
CRCSIZE = 4
romfile = ''
serialport = ''
def main(argv):
global romfile
global serialport
global mode
mode = Mode.NONE
if len(argv)==0:
usage()
try:
opts, args = getopt.getopt(argv,'dRbcs:r:',['dump','burn','check','serial=','rom='])
except getopt.GetoptError:
usage()
for opt, arg in opts:
if opt == '-c':
mode = Mode.CHECK
elif opt == '-d':
mode = Mode.DUMP
elif opt == '-R':
mode = Mode.READ
elif opt == '-b':
mode = Mode.BURN
elif opt == '-s':
serialport = arg
elif opt == '-r':
romfile = arg
else:
mode = Mode.NONE
commands = {
Mode.NONE: usage,
Mode.BURN: burnROM,
Mode.DUMP: dumpROM,
Mode.READ: dumpROM,
Mode.CHECK: checkConnection
}
commands[mode]()
def checkConnection():
if serialport=='':
usage()
print 'Checking connection to ' + serialport + '...'
try:
# Create the serial connection
connection = serial.Serial(serialport,19200,timeout=1)
print 'Found ' + serialport + '. Pinging EETool...'
except (OSError,serial.SerialException):
print 'Unable to find that serial port.'
sys.exit(2)
try:
# Try sending a ping
wrote = connection.write(bytearray([Command.PREFIX,Command.PING]))
if wrote != 2:
raise ValueError()
print 'Sent', wrote, 'byte ping. Waiting for response...'
# Did we get a pong back?
while 1:
numBytes = connection.inWaiting()
if numBytes>0:
break
print 'Received', numBytes, 'byte pong'
if numBytes != len(PONG):
raise serial.SerialException
response = connection.read(numBytes)
if (response != PONG):
raise serial.SerialException
except (ValueError,OSError,serial.SerialException):
print 'EETool is not responding. Check connections and try again.'
connection.close()
sys.exit(2)
print 'EETool is online and ready for use.'
connection.close()
sys.exit(0)
def burnROM():
if romfile=='' or serialport=='':
usage()
print 'Connecting to ' + serialport + '...'
try:
# Create the serial connection
connection = serial.Serial(serialport,19200,timeout=1)
except (OSError,serial.SerialException):
print 'Unable to find that serial port.'
sys.exit(2)
try:
destFile = open (romfile, "r")
except OSError:
print 'Unable to read from ROM file',romfile
sys.exit(2)
try:
# Prepare to write
wrote = connection.write(bytearray([Command.PREFIX,Command.STARTRW]))
if wrote != 2:
raise ValueError()
print 'Sending data to EETool...'
totalSize = 0
# Transmit all the blocks
for blockNum in range(0,64):
wrote = connection.write(bytearray([Command.PREFIX,Command.WRITEBLOCK]))
if wrote != 2:
raise ValueError()
# Read block from ROM file
block = destFile.read(BLOCKSIZE)
# Send block to EETool
numBytes = connection.write(block)
if numBytes != BLOCKSIZE:
raise ValueError()
# Wait for confirmation
while 1:
wrote = connection.inWaiting()
if wrote>=1:
break
confirmation = connection.read(numBytes)
chk = bytearray([confirmation]);
if not ((wrote==1) and (chk[0]==Command.PREFIX)):
print 'ERROR: Confirmation failed while uploading block',blockNum,' Aborting.'
sys.exit(2)
sys.stdout.write('#')
sys.stdout.flush()
totalSize += numBytes
time.sleep(0.1)
destFile.close()
print '\nDone! Wrote',totalSize,'bytes to EEPROM.'
sys.exit(0)
except (ValueError,OSError,serial.SerialException):
print 'UNKNOWN ERROR'
connection.close()
sys.exit(0)
def dumpROM():
if romfile=='' or serialport=='':
usage()
print 'Connecting to ' + serialport + '...'
try:
# Create the serial connection
connection = serial.Serial(serialport,19200,timeout=1)
except (OSError,serial.SerialException):
print 'Unable to find that serial port.'
sys.exit(2)
try:
destFile = open (romfile, "wb")
except OSError:
print 'Unable to write to ROM file',romfile
sys.exit(2)
try:
# Prepare to read
wrote = connection.write(bytearray([Command.PREFIX,Command.STARTRW]))
if wrote != 2:
raise ValueError()
print 'Requesting data from EETool...'
totalSize = 0
cmd = Command.READBLOCK_MASK if mode==Mode.DUMP else Command.READBLOCK
# Request all the blocks
for blockNum in range(0,64):
wrote = connection.write(bytearray([Command.PREFIX,cmd]))
if wrote != 2:
raise ValueError()
while 1:
numBytes = connection.inWaiting()
if numBytes>=BLOCKSIZE + CRCSIZE:
break
if (numBytes!=BLOCKSIZE + CRCSIZE):
print 'ERROR: Block',blockNum,'failed to download. Aborting.'
sys.exit(2)
response = connection.read(numBytes)
crc = struct.unpack('<I',response[BLOCKSIZE:BLOCKSIZE+CRCSIZE])[0]
block = response[0:BLOCKSIZE]
calcCRC = binascii.crc32(block) & 0xFFFFFFFF
if crc != calcCRC:
print numBytes,'CRC failed on block',blockNum,'Read CRC =',hexU32(crc),' Calcuated CRC =',hexU32(calcCRC)
print 'Aborting.'
sys.exit(2)
# Write the block to our file
destFile.write(bytes(block))
sys.stdout.write('#')
sys.stdout.flush()
totalSize += numBytes - CRCSIZE
destFile.close()
print '\nDone! ROM is',totalSize,'bytes.'
sys.exit(0)
except (ValueError,OSError,serial.SerialException):
print 'UNKNOWN ERROR'
connection.close()
sys.exit(0)
def hexU32(n):
return "0x%x"%(n&0xffffffff)
def usage():
print '''
Usage: EECommander -[d|b|c] -s <serial port> -r <rom file>
-d: Dump the contents of the attached MASK ROM to a file
-R: Read the contents of the attached EEPROM to a file
-b: Burn the rom file to the attached EEPROM
-c: Check your connection to EETool (no other action taken)
To find your serial port, connect EETool and try "ls /dev/tty.usbmodem*" on Mac or Linux.
On Windows, use a COM port name, such as "COM1". You can use the -c option to find out which one.
'''
sys.exit(2)
if __name__ == "__main__":
main(sys.argv[1:])