chiark / gitweb /
Updated all lineends for py files to unix style.
[cura.git] / Cura / avr_isp / stk500v2.py
1 import os, struct, sys, time
2
3 from serial import Serial
4 from serial import SerialException
5
6 import ispBase, intelHex
7
8 class Stk500v2(ispBase.IspBase):
9         def __init__(self):
10                 self.serial = None
11                 self.seq = 1
12                 self.lastAddr = -1
13                 self.progressCallback = None
14         
15         def connect(self, port = 'COM22', speed = 115200):
16                 if self.serial != None:
17                         self.close()
18                 try:
19                         self.serial = Serial(port, speed, timeout=1, writeTimeout=10000)
20                 except SerialException as e:
21                         raise ispBase.IspError("Failed to open serial port")
22                 except:
23                         raise ispBase.IspError("Unexpected error while connecting to serial port:" + port + ":" + str(sys.exc_info()[0]))
24                 self.seq = 1
25                 
26                 #Reset the controller
27                 self.serial.setDTR(1)
28                 time.sleep(0.1)
29                 self.serial.setDTR(0)
30                 time.sleep(0.2)
31                 
32                 self.sendMessage([1])
33                 if self.sendMessage([0x10, 0xc8, 0x64, 0x19, 0x20, 0x00, 0x53, 0x03, 0xac, 0x53, 0x00, 0x00]) != [0x10, 0x00]:
34                         self.close()
35                         raise ispBase.IspError("Failed to enter programming mode")
36
37         def close(self):
38                 if self.serial != None:
39                         self.serial.close()
40                         self.serial = None
41
42         #Leave ISP does not reset the serial port, only resets the device, and returns the serial port after disconnecting it from the programming interface.
43         #       This allows you to use the serial port without opening it again.
44         def leaveISP(self):
45                 if self.serial != None:
46                         if self.sendMessage([0x11]) != [0x11, 0x00]:
47                                 raise ispBase.IspError("Failed to leave programming mode")
48                         ret = self.serial
49                         self.serial = None
50                         return ret
51                 return None
52         
53         def isConnected(self):
54                 return self.serial != None
55         
56         def sendISP(self, data):
57                 recv = self.sendMessage([0x1D, 4, 4, 0, data[0], data[1], data[2], data[3]])
58                 return recv[2:6]
59         
60         def writeFlash(self, flashData):
61                 #Set load addr to 0, in case we have more then 64k flash we need to enable the address extension
62                 pageSize = self.chip['pageSize'] * 2
63                 flashSize = pageSize * self.chip['pageCount']
64                 if flashSize > 0xFFFF:
65                         self.sendMessage([0x06, 0x80, 0x00, 0x00, 0x00])
66                 else:
67                         self.sendMessage([0x06, 0x00, 0x00, 0x00, 0x00])
68                 
69                 loadCount = (len(flashData) + pageSize - 1) / pageSize
70                 for i in xrange(0, loadCount):
71                         recv = self.sendMessage([0x13, pageSize >> 8, pageSize & 0xFF, 0xc1, 0x0a, 0x40, 0x4c, 0x20, 0x00, 0x00] + flashData[(i * pageSize):(i * pageSize + pageSize)])
72                         if self.progressCallback != None:
73                                 self.progressCallback(i + 1, loadCount*2)
74         
75         def verifyFlash(self, flashData):
76                 #Set load addr to 0, in case we have more then 64k flash we need to enable the address extension
77                 flashSize = self.chip['pageSize'] * 2 * self.chip['pageCount']
78                 if flashSize > 0xFFFF:
79                         self.sendMessage([0x06, 0x80, 0x00, 0x00, 0x00])
80                 else:
81                         self.sendMessage([0x06, 0x00, 0x00, 0x00, 0x00])
82                 
83                 loadCount = (len(flashData) + 0xFF) / 0x100
84                 for i in xrange(0, loadCount):
85                         recv = self.sendMessage([0x14, 0x01, 0x00, 0x20])[2:0x102]
86                         if self.progressCallback != None:
87                                 self.progressCallback(loadCount + i + 1, loadCount*2)
88                         for j in xrange(0, 0x100):
89                                 if i * 0x100 + j < len(flashData) and flashData[i * 0x100 + j] != recv[j]:
90                                         raise ispBase.IspError('Verify error at: 0x%x' % (i * 0x100 + j))
91
92         def sendMessage(self, data):
93                 message = struct.pack(">BBHB", 0x1B, self.seq, len(data), 0x0E)
94                 for c in data:
95                         message += struct.pack(">B", c)
96                 checksum = 0
97                 for c in message:
98                         checksum ^= ord(c)
99                 message += struct.pack(">B", checksum)
100                 try:
101                         self.serial.write(message)
102                         self.serial.flush()
103                 except SerialTimeoutException:
104                         raise ispBase.IspError('Serial send timeout')
105                 self.seq = (self.seq + 1) & 0xFF
106                 return self.recvMessage()
107         
108         def recvMessage(self):
109                 state = 'Start'
110                 checksum = 0
111                 while True:
112                         s = self.serial.read()
113                         if len(s) < 1:
114                                 raise ispBase.IspError("Timeout")
115                         b = struct.unpack(">B", s)[0]
116                         checksum ^= b
117                         #print(hex(b))
118                         if state == 'Start':
119                                 if b == 0x1B:
120                                         state = 'GetSeq'
121                                         checksum = 0x1B
122                         elif state == 'GetSeq':
123                                 state = 'MsgSize1'
124                         elif state == 'MsgSize1':
125                                 msgSize = b << 8
126                                 state = 'MsgSize2'
127                         elif state == 'MsgSize2':
128                                 msgSize |= b
129                                 state = 'Token'
130                         elif state == 'Token':
131                                 if b != 0x0E:
132                                         state = 'Start'
133                                 else:
134                                         state = 'Data'
135                                         data = []
136                         elif state == 'Data':
137                                 data.append(b)
138                                 if len(data) == msgSize:
139                                         state = 'Checksum'
140                         elif state == 'Checksum':
141                                 if checksum != 0:
142                                         state = 'Start'
143                                 else:
144                                         return data
145
146
147 def main():
148         programmer = Stk500v2()
149         programmer.connect(port = sys.argv[1])
150         programmer.programChip(intelHex.readHex(sys.argv[2]))
151         sys.exit(1)
152
153 if __name__ == '__main__':
154         main()