formatting

This commit is contained in:
Jaime van Kessel 2015-03-31 10:40:21 +02:00
parent 9d889cf2db
commit 3fa02d3710
6 changed files with 289 additions and 286 deletions

View file

@ -29,7 +29,8 @@ class PrinterConnection():
def _connect(self): def _connect(self):
self._is_connecting = True self._is_connecting = True
programmer.connect(serial_port) #Connect with the serial, if this succeeds, it's an arduino based usb device. programmer = stk500v2.Stk500v2()
programmer.connect(self._serial_port) #Connect with the serial, if this succeeds, it's an arduino based usb device.
try: try:
self._serial = programmer.leaveISP() self._serial = programmer.leaveISP()
# Create new printer connection # Create new printer connection

View file

@ -17,7 +17,7 @@ class USBPrinterManager(SignalEmitter,PluginObject):
self._check_ports_thread = threading.Thread(target=self._updateConnectionList) self._check_ports_thread = threading.Thread(target=self._updateConnectionList)
self._check_ports_thread.daemon = True self._check_ports_thread.daemon = True
self._check_ports_thread.start() self._check_ports_thread.start()
time.sleep(6) time.sleep(2)
self.connectAllConnections() self.connectAllConnections()
## Check all serial ports and create a PrinterConnection object for them. ## Check all serial ports and create a PrinterConnection object for them.

View file

@ -1,25 +1,25 @@
""" """
Database of AVR chips for avr_isp programming. Contains signatures and flash sizes from the AVR datasheets. Database of AVR chips for avr_isp programming. Contains signatures and flash sizes from the AVR datasheets.
To support more chips add the relevant data to the avrChipDB list. To support more chips add the relevant data to the avrChipDB list.
This is a python 3 conversion of the code created by David Braam for the Cura project.
""" """
__copyright__ = "Copyright (C) 2013 David Braam - Released under terms of the AGPLv3 License"
avrChipDB = { avrChipDB = {
'ATMega1280': { 'ATMega1280': {
'signature': [0x1E, 0x97, 0x03], 'signature': [0x1E, 0x97, 0x03],
'pageSize': 128, 'pageSize': 128,
'pageCount': 512, 'pageCount': 512,
}, },
'ATMega2560': { 'ATMega2560': {
'signature': [0x1E, 0x98, 0x01], 'signature': [0x1E, 0x98, 0x01],
'pageSize': 128, 'pageSize': 128,
'pageCount': 1024, 'pageCount': 1024,
}, },
} }
def getChipFromDB(sig): def getChipFromDB(sig):
for chip in avrChipDB.values(): for chip in avrChipDB.values():
if chip['signature'] == sig: if chip['signature'] == sig:
return chip return chip
return False return False

View file

@ -2,45 +2,45 @@
Module to read intel hex files into binary data blobs. Module to read intel hex files into binary data blobs.
IntelHex files are commonly used to distribute firmware IntelHex files are commonly used to distribute firmware
See: http://en.wikipedia.org/wiki/Intel_HEX See: http://en.wikipedia.org/wiki/Intel_HEX
This is a python 3 conversion of the code created by David Braam for the Cura project.
""" """
__copyright__ = "Copyright (C) 2013 David Braam - Released under terms of the AGPLv3 License"
import io import io
def readHex(filename): def readHex(filename):
""" """
Read an verify an intel hex file. Return the data as an list of bytes. Read an verify an intel hex file. Return the data as an list of bytes.
""" """
data = [] data = []
extraAddr = 0 extraAddr = 0
f = io.open(filename, "r") f = io.open(filename, "r")
for line in f: for line in f:
line = line.strip() line = line.strip()
if len(line) < 1: if len(line) < 1:
continue continue
if line[0] != ':': if line[0] != ':':
raise Exception("Hex file has a line not starting with ':'") raise Exception("Hex file has a line not starting with ':'")
recLen = int(line[1:3], 16) recLen = int(line[1:3], 16)
addr = int(line[3:7], 16) + extraAddr addr = int(line[3:7], 16) + extraAddr
recType = int(line[7:9], 16) recType = int(line[7:9], 16)
if len(line) != recLen * 2 + 11: if len(line) != recLen * 2 + 11:
raise Exception("Error in hex file: " + line) raise Exception("Error in hex file: " + line)
checkSum = 0 checkSum = 0
for i in xrange(0, recLen + 5): for i in range(0, recLen + 5):
checkSum += int(line[i*2+1:i*2+3], 16) checkSum += int(line[i*2+1:i*2+3], 16)
checkSum &= 0xFF checkSum &= 0xFF
if checkSum != 0: if checkSum != 0:
raise Exception("Checksum error in hex file: " + line) raise Exception("Checksum error in hex file: " + line)
if recType == 0:#Data record if recType == 0:#Data record
while len(data) < addr + recLen: while len(data) < addr + recLen:
data.append(0) data.append(0)
for i in xrange(0, recLen): for i in xrange(0, recLen):
data[addr + i] = int(line[i*2+9:i*2+11], 16) data[addr + i] = int(line[i*2+9:i*2+11], 16)
elif recType == 1: #End Of File record elif recType == 1: #End Of File record
pass pass
elif recType == 2: #Extended Segment Address Record elif recType == 2: #Extended Segment Address Record
extraAddr = int(line[9:13], 16) * 16 extraAddr = int(line[9:13], 16) * 16
else: else:
print(recType, recLen, addr, checkSum, line) print(recType, recLen, addr, checkSum, line)
f.close() f.close()
return data return data

View file

@ -4,60 +4,60 @@ The ISP AVR programmer can load firmware into AVR chips. Which are commonly used
Needs to be subclassed to support different programmers. Needs to be subclassed to support different programmers.
Currently only the stk500v2 subclass exists. Currently only the stk500v2 subclass exists.
This is a python 3 conversion of the code created by David Braam for the Cura project.
""" """
__copyright__ = "Copyright (C) 2013 David Braam - Released under terms of the AGPLv3 License"
from . import chipDB from . import chipDB
class IspBase(): class IspBase():
""" """
Base class for ISP based AVR programmers. Base class for ISP based AVR programmers.
Functions in this class raise an IspError when something goes wrong. Functions in this class raise an IspError when something goes wrong.
""" """
def programChip(self, flashData): def programChip(self, flashData):
""" Program a chip with the given flash data. """ """ Program a chip with the given flash data. """
self.curExtAddr = -1 self.curExtAddr = -1
self.chip = chipDB.getChipFromDB(self.getSignature()) self.chip = chipDB.getChipFromDB(self.getSignature())
if not self.chip: if not self.chip:
raise IspError("Chip with signature: " + str(self.getSignature()) + "not found") raise IspError("Chip with signature: " + str(self.getSignature()) + "not found")
self.chipErase() self.chipErase()
print("Flashing %i bytes" % len(flashData)) print("Flashing %i bytes" % len(flashData))
self.writeFlash(flashData) self.writeFlash(flashData)
print("Verifying %i bytes" % len(flashData)) print("Verifying %i bytes" % len(flashData))
self.verifyFlash(flashData) self.verifyFlash(flashData)
def getSignature(self): def getSignature(self):
""" """
Get the AVR signature from the chip. This is a 3 byte array which describes which chip we are connected to. Get the AVR signature from the chip. This is a 3 byte array which describes which chip we are connected to.
This is important to verify that we are programming the correct type of chip and that we use proper flash block sizes. This is important to verify that we are programming the correct type of chip and that we use proper flash block sizes.
""" """
sig = [] sig = []
sig.append(self.sendISP([0x30, 0x00, 0x00, 0x00])[3]) sig.append(self.sendISP([0x30, 0x00, 0x00, 0x00])[3])
sig.append(self.sendISP([0x30, 0x00, 0x01, 0x00])[3]) sig.append(self.sendISP([0x30, 0x00, 0x01, 0x00])[3])
sig.append(self.sendISP([0x30, 0x00, 0x02, 0x00])[3]) sig.append(self.sendISP([0x30, 0x00, 0x02, 0x00])[3])
return sig return sig
def chipErase(self):
"""
Do a full chip erase, clears all data, and lockbits.
"""
self.sendISP([0xAC, 0x80, 0x00, 0x00])
def writeFlash(self, flashData): def chipErase(self):
""" """
Write the flash data, needs to be implemented in a subclass. Do a full chip erase, clears all data, and lockbits.
""" """
raise IspError("Called undefined writeFlash") self.sendISP([0xAC, 0x80, 0x00, 0x00])
def verifyFlash(self, flashData): def writeFlash(self, flashData):
""" """
Verify the flash data, needs to be implemented in a subclass. Write the flash data, needs to be implemented in a subclass.
""" """
raise IspError("Called undefined verifyFlash") raise IspError("Called undefined writeFlash")
def verifyFlash(self, flashData):
"""
Verify the flash data, needs to be implemented in a subclass.
"""
raise IspError("Called undefined verifyFlash")
class IspError(): class IspError():
def __init__(self, value): def __init__(self, value):
self.value = value self.value = value
def __str__(self): def __str__(self):
return repr(self.value) return repr(self.value)

View file

@ -1,8 +1,8 @@
""" """
STK500v2 protocol implementation for programming AVR chips. STK500v2 protocol implementation for programming AVR chips.
The STK500v2 protocol is used by the ArduinoMega2560 and a few other Arduino platforms to load firmware. The STK500v2 protocol is used by the ArduinoMega2560 and a few other Arduino platforms to load firmware.
This is a python 3 conversion of the code created by David Braam for the Cura project.
""" """
__copyright__ = "Copyright (C) 2013 David Braam - Released under terms of the AGPLv3 License"
import os, struct, sys, time import os, struct, sys, time
from serial import Serial from serial import Serial
@ -12,205 +12,207 @@ from serial import SerialTimeoutException
from . import ispBase, intelHex from . import ispBase, intelHex
class Stk500v2(ispBase.IspBase): class Stk500v2(ispBase.IspBase):
def __init__(self): def __init__(self):
self.serial = None self.serial = None
self.seq = 1 self.seq = 1
self.lastAddr = -1 self.lastAddr = -1
self.progressCallback = None self.progressCallback = None
def connect(self, port = 'COM22', speed = 115200): def connect(self, port = 'COM22', speed = 115200):
if self.serial is not None: if self.serial is not None:
self.close() self.close()
try: try:
self.serial = Serial(str(port), speed, timeout=1, writeTimeout=10000) self.serial = Serial(str(port), speed, timeout=1, writeTimeout=10000)
except SerialException as e: except SerialException as e:
raise ispBase.IspError("Failed to open serial port") raise ispBase.IspError("Failed to open serial port")
except: except:
raise ispBase.IspError("Unexpected error while connecting to serial port:" + port + ":" + str(sys.exc_info()[0])) raise ispBase.IspError("Unexpected error while connecting to serial port:" + port + ":" + str(sys.exc_info()[0]))
self.seq = 1 self.seq = 1
#Reset the controller #Reset the controller
for n in xrange(0, 2): for n in range(0, 2):
self.serial.setDTR(True) self.serial.setDTR(True)
time.sleep(0.1) time.sleep(0.1)
self.serial.setDTR(False) self.serial.setDTR(False)
time.sleep(0.1) time.sleep(0.1)
time.sleep(0.2) time.sleep(0.2)
self.serial.flushInput() self.serial.flushInput()
self.serial.flushOutput() self.serial.flushOutput()
if self.sendMessage([0x10, 0xc8, 0x64, 0x19, 0x20, 0x00, 0x53, 0x03, 0xac, 0x53, 0x00, 0x00]) != [0x10, 0x00]: if self.sendMessage([0x10, 0xc8, 0x64, 0x19, 0x20, 0x00, 0x53, 0x03, 0xac, 0x53, 0x00, 0x00]) != [0x10, 0x00]:
self.close() self.close()
raise ispBase.IspError("Failed to enter programming mode") raise ispBase.IspError("Failed to enter programming mode")
self.sendMessage([0x06, 0x80, 0x00, 0x00, 0x00]) self.sendMessage([0x06, 0x80, 0x00, 0x00, 0x00])
if self.sendMessage([0xEE])[1] == 0x00: if self.sendMessage([0xEE])[1] == 0x00:
self._has_checksum = True self._has_checksum = True
else: else:
self._has_checksum = False self._has_checksum = False
self.serial.timeout = 5 self.serial.timeout = 5
def close(self): def close(self):
if self.serial is not None: if self.serial is not None:
self.serial.close() self.serial.close()
self.serial = None self.serial = None
#Leave ISP does not reset the serial port, only resets the device, and returns the serial port after disconnecting it from the programming interface. #Leave ISP does not reset the serial port, only resets the device, and returns the serial port after disconnecting it from the programming interface.
# This allows you to use the serial port without opening it again. # This allows you to use the serial port without opening it again.
def leaveISP(self): def leaveISP(self):
if self.serial is not None: if self.serial is not None:
if self.sendMessage([0x11]) != [0x11, 0x00]: if self.sendMessage([0x11]) != [0x11, 0x00]:
raise ispBase.IspError("Failed to leave programming mode") raise ispBase.IspError("Failed to leave programming mode")
ret = self.serial ret = self.serial
self.serial = None self.serial = None
return ret return ret
return None return None
def isConnected(self): def isConnected(self):
return self.serial is not None return self.serial is not None
def hasChecksumFunction(self): def hasChecksumFunction(self):
return self._has_checksum return self._has_checksum
def sendISP(self, data): def sendISP(self, data):
recv = self.sendMessage([0x1D, 4, 4, 0, data[0], data[1], data[2], data[3]]) recv = self.sendMessage([0x1D, 4, 4, 0, data[0], data[1], data[2], data[3]])
return recv[2:6] return recv[2:6]
def writeFlash(self, flashData): def writeFlash(self, flashData):
#Set load addr to 0, in case we have more then 64k flash we need to enable the address extension #Set load addr to 0, in case we have more then 64k flash we need to enable the address extension
pageSize = self.chip['pageSize'] * 2 pageSize = self.chip['pageSize'] * 2
flashSize = pageSize * self.chip['pageCount'] flashSize = pageSize * self.chip['pageCount']
if flashSize > 0xFFFF: if flashSize > 0xFFFF:
self.sendMessage([0x06, 0x80, 0x00, 0x00, 0x00]) self.sendMessage([0x06, 0x80, 0x00, 0x00, 0x00])
else: else:
self.sendMessage([0x06, 0x00, 0x00, 0x00, 0x00]) self.sendMessage([0x06, 0x00, 0x00, 0x00, 0x00])
loadCount = (len(flashData) + pageSize - 1) / pageSize loadCount = (len(flashData) + pageSize - 1) / pageSize
for i in xrange(0, loadCount): for i in xrange(0, loadCount):
recv = self.sendMessage([0x13, pageSize >> 8, pageSize & 0xFF, 0xc1, 0x0a, 0x40, 0x4c, 0x20, 0x00, 0x00] + flashData[(i * pageSize):(i * pageSize + pageSize)]) recv = self.sendMessage([0x13, pageSize >> 8, pageSize & 0xFF, 0xc1, 0x0a, 0x40, 0x4c, 0x20, 0x00, 0x00] + flashData[(i * pageSize):(i * pageSize + pageSize)])
if self.progressCallback is not None: if self.progressCallback is not None:
if self._has_checksum: if self._has_checksum:
self.progressCallback(i + 1, loadCount) self.progressCallback(i + 1, loadCount)
else: else:
self.progressCallback(i + 1, loadCount*2) self.progressCallback(i + 1, loadCount*2)
def verifyFlash(self, flashData): def verifyFlash(self, flashData):
if self._has_checksum: if self._has_checksum:
self.sendMessage([0x06, 0x00, (len(flashData) >> 17) & 0xFF, (len(flashData) >> 9) & 0xFF, (len(flashData) >> 1) & 0xFF]) self.sendMessage([0x06, 0x00, (len(flashData) >> 17) & 0xFF, (len(flashData) >> 9) & 0xFF, (len(flashData) >> 1) & 0xFF])
res = self.sendMessage([0xEE]) res = self.sendMessage([0xEE])
checksum_recv = res[2] | (res[3] << 8) checksum_recv = res[2] | (res[3] << 8)
checksum = 0 checksum = 0
for d in flashData: for d in flashData:
checksum += d checksum += d
checksum &= 0xFFFF checksum &= 0xFFFF
if hex(checksum) != hex(checksum_recv): if hex(checksum) != hex(checksum_recv):
raise ispBase.IspError('Verify checksum mismatch: 0x%x != 0x%x' % (checksum & 0xFFFF, checksum_recv)) raise ispBase.IspError('Verify checksum mismatch: 0x%x != 0x%x' % (checksum & 0xFFFF, checksum_recv))
else: else:
#Set load addr to 0, in case we have more then 64k flash we need to enable the address extension #Set load addr to 0, in case we have more then 64k flash we need to enable the address extension
flashSize = self.chip['pageSize'] * 2 * self.chip['pageCount'] flashSize = self.chip['pageSize'] * 2 * self.chip['pageCount']
if flashSize > 0xFFFF: if flashSize > 0xFFFF:
self.sendMessage([0x06, 0x80, 0x00, 0x00, 0x00]) self.sendMessage([0x06, 0x80, 0x00, 0x00, 0x00])
else: else:
self.sendMessage([0x06, 0x00, 0x00, 0x00, 0x00]) self.sendMessage([0x06, 0x00, 0x00, 0x00, 0x00])
loadCount = (len(flashData) + 0xFF) / 0x100 loadCount = (len(flashData) + 0xFF) / 0x100
for i in xrange(0, loadCount): for i in xrange(0, loadCount):
recv = self.sendMessage([0x14, 0x01, 0x00, 0x20])[2:0x102] recv = self.sendMessage([0x14, 0x01, 0x00, 0x20])[2:0x102]
if self.progressCallback is not None: if self.progressCallback is not None:
self.progressCallback(loadCount + i + 1, loadCount*2) self.progressCallback(loadCount + i + 1, loadCount*2)
for j in xrange(0, 0x100): for j in xrange(0, 0x100):
if i * 0x100 + j < len(flashData) and flashData[i * 0x100 + j] != recv[j]: if i * 0x100 + j < len(flashData) and flashData[i * 0x100 + j] != recv[j]:
raise ispBase.IspError('Verify error at: 0x%x' % (i * 0x100 + j)) raise ispBase.IspError('Verify error at: 0x%x' % (i * 0x100 + j))
def sendMessage(self, data): def sendMessage(self, data):
message = struct.pack(">BBHB", 0x1B, self.seq, len(data), 0x0E) message = struct.pack(">BBHB", 0x1B, self.seq, len(data), 0x0E)
for c in data: for c in data:
message += struct.pack(">B", c) message += struct.pack(">B", c)
checksum = 0 checksum = 0
for c in message: print("messsage " , message)
checksum ^= ord(c) for c in message:
message += struct.pack(">B", checksum) print(c)
try: checksum ^= ord(c)
self.serial.write(message) message += struct.pack(">B", checksum)
self.serial.flush() try:
except SerialTimeoutException: self.serial.write(message)
raise ispBase.IspError('Serial send timeout') self.serial.flush()
self.seq = (self.seq + 1) & 0xFF except SerialTimeoutException:
return self.recvMessage() raise ispBase.IspError('Serial send timeout')
self.seq = (self.seq + 1) & 0xFF
def recvMessage(self): return self.recvMessage()
state = 'Start'
checksum = 0 def recvMessage(self):
while True: state = 'Start'
s = self.serial.read() checksum = 0
if len(s) < 1: while True:
raise ispBase.IspError("Timeout") s = self.serial.read()
b = struct.unpack(">B", s)[0] if len(s) < 1:
checksum ^= b raise ispBase.IspError("Timeout")
#print(hex(b)) b = struct.unpack(">B", s)[0]
if state == 'Start': checksum ^= b
if b == 0x1B: #print(hex(b))
state = 'GetSeq' if state == 'Start':
checksum = 0x1B if b == 0x1B:
elif state == 'GetSeq': state = 'GetSeq'
state = 'MsgSize1' checksum = 0x1B
elif state == 'MsgSize1': elif state == 'GetSeq':
msgSize = b << 8 state = 'MsgSize1'
state = 'MsgSize2' elif state == 'MsgSize1':
elif state == 'MsgSize2': msgSize = b << 8
msgSize |= b state = 'MsgSize2'
state = 'Token' elif state == 'MsgSize2':
elif state == 'Token': msgSize |= b
if b != 0x0E: state = 'Token'
state = 'Start' elif state == 'Token':
else: if b != 0x0E:
state = 'Data' state = 'Start'
data = [] else:
elif state == 'Data': state = 'Data'
data.append(b) data = []
if len(data) == msgSize: elif state == 'Data':
state = 'Checksum' data.append(b)
elif state == 'Checksum': if len(data) == msgSize:
if checksum != 0: state = 'Checksum'
state = 'Start' elif state == 'Checksum':
else: if checksum != 0:
return data state = 'Start'
else:
return data
def portList(): def portList():
ret = [] ret = []
import _winreg import _winreg
key=_winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE,"HARDWARE\\DEVICEMAP\\SERIALCOMM") key=_winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE,"HARDWARE\\DEVICEMAP\\SERIALCOMM")
i=0 i=0
while True: while True:
try: try:
values = _winreg.EnumValue(key, i) values = _winreg.EnumValue(key, i)
except: except:
return ret return ret
if 'USBSER' in values[0]: if 'USBSER' in values[0]:
ret.append(values[1]) ret.append(values[1])
i+=1 i+=1
return ret return ret
def runProgrammer(port, filename): def runProgrammer(port, filename):
""" Run an STK500v2 program on serial port 'port' and write 'filename' into flash. """ """ Run an STK500v2 program on serial port 'port' and write 'filename' into flash. """
programmer = Stk500v2() programmer = Stk500v2()
programmer.connect(port = port) programmer.connect(port = port)
programmer.programChip(intelHex.readHex(filename)) programmer.programChip(intelHex.readHex(filename))
programmer.close() programmer.close()
def main(): def main():
""" Entry point to call the stk500v2 programmer from the commandline. """ """ Entry point to call the stk500v2 programmer from the commandline. """
import threading import threading
if sys.argv[1] == 'AUTO': if sys.argv[1] == 'AUTO':
print(portList()) print(portList())
for port in portList(): for port in portList():
threading.Thread(target=runProgrammer, args=(port,sys.argv[2])).start() threading.Thread(target=runProgrammer, args=(port,sys.argv[2])).start()
time.sleep(5) time.sleep(5)
else: else:
programmer = Stk500v2() programmer = Stk500v2()
programmer.connect(port = sys.argv[1]) programmer.connect(port = sys.argv[1])
programmer.programChip(intelHex.readHex(sys.argv[2])) programmer.programChip(intelHex.readHex(sys.argv[2]))
sys.exit(1) sys.exit(1)
if __name__ == '__main__': if __name__ == '__main__':
main() main()