1 #!/usr/bin/env python 2 3 """ 4 A ROM upload utility for the Arduino-Am29F010 interface. 5 6 Copyright (C) 2015 Paul Boddie <paul@boddie.org.uk> 7 8 This program is free software; you can redistribute it and/or modify it under 9 the terms of the GNU General Public License as published by the Free Software 10 Foundation; either version 3 of the License, or (at your option) any later 11 version. 12 13 This program is distributed in the hope that it will be useful, but WITHOUT ANY 14 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 15 PARTICULAR PURPOSE. See the GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License along 18 with this program. If not, see <http://www.gnu.org/licenses/>. 19 """ 20 21 from serial import Serial 22 from time import sleep 23 import sys 24 25 port = "/dev/ttyUSB0" 26 rate = 115200 27 28 def openPort(): 29 global s 30 s = Serial(port, rate) 31 s.setTimeout(5) 32 s.readline() 33 34 def closePort(): 35 global s 36 s.close() 37 s = None 38 39 def writeToPort(data): 40 s.write(data) 41 s.flush() 42 print >>sys.stderr, data.rstrip() 43 44 def readFromPort(): 45 resp = s.readline().rstrip("\r\n") 46 if resp == "?": 47 resp = s.readline().rstrip("\r\n") 48 return resp 49 50 def console(): 51 try: 52 while 1: 53 cmd = raw_input("> ") 54 if cmd: 55 s.write(cmd + "\n") 56 s.flush() 57 print s.readline().rstrip("\r\n") 58 except EOFError: 59 print "Session closed." 60 61 def upload(filename, sector, verify_only=False): 62 data = open(filename, "rb").read() 63 64 if len(data) != 0x4000: 65 print >>sys.stderr, "File", filename, "is not", 0x4000, "bytes long." 66 return False 67 68 if not verify_only: 69 print >>sys.stderr, "Erasing sector", sector, "..." 70 71 writeToPort("S%x\n" % sector) 72 resp = readFromPort() 73 if resp != "S": 74 print >>sys.stderr, "Sector %d erase failed: %s" % (sector, resp) 75 return False 76 77 print >>sys.stderr, "Uploading", filename, "to sector", sector, "..." 78 else: 79 print >>sys.stderr, "Verifying sector", sector, "..." 80 81 i = 0 82 while i < 0x4000: 83 value = ord(data[i]) 84 addr = (sector << 14) | i 85 86 if not verify_only: 87 writeToPort("P%05x%02x\n" % (addr, value)) 88 resp = readFromPort() 89 if resp == "P": 90 i += 1 91 continue 92 else: 93 closePort() 94 openPort() 95 96 for attempt in "first", "second": 97 writeToPort("R%05x\n" % addr) 98 resp = readFromPort() 99 if resp == "%02X" % value or resp == "%X" % value: 100 break 101 closePort() 102 openPort() 103 else: 104 print >>sys.stderr, "%s of location %05x failed: %s" % (verify_only and "Verify" or "Program", addr, resp) 105 return False 106 107 i += 1 108 109 return True 110 111 if __name__ == "__main__": 112 openPort() 113 114 try: 115 if "-i" in sys.argv: 116 console() 117 elif len(sys.argv) > 1: 118 if len(sys.argv) > 3 and sys.argv[1] == "-s": 119 base = int(sys.argv[2]) 120 i = 3 121 else: 122 base = 0 123 i = 1 124 if len(sys.argv) > i and sys.argv[i] == "-v": 125 verify_only = True 126 i += 1 127 else: 128 verify_only = False 129 130 for sector, filename in enumerate(sys.argv[i:]): 131 if not upload(filename, sector + base, verify_only): 132 break 133 sleep(5) # give the device a rest 134 else: 135 print >>sys.stderr, sys.argv[0], "-i | [ -s <sector> ] [ -v ] <filename>..." 136 sys.exit(1) 137 finally: 138 closePort() 139 140 # vim: tabstop=4 expandtab shiftwidth=4