|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+import serial
|
|
|
2
|
+import sys
|
|
|
3
|
+import time
|
|
|
4
|
+import binascii
|
|
|
5
|
+import random
|
|
|
6
|
+
|
|
|
7
|
+class Error(Exception):
|
|
|
8
|
+ pass
|
|
|
9
|
+
|
|
|
10
|
+RETURN_CODE = {
|
|
|
11
|
+ 0: 'CMD_SUCCESS',
|
|
|
12
|
+ 1: 'INVALID_COMMAND',
|
|
|
13
|
+ 2: 'SRC_ADDR_ERROR',
|
|
|
14
|
+ 3: 'DST_ADDR_ERROR',
|
|
|
15
|
+ 4: 'SRC_ADDR_NOT_MAPPED',
|
|
|
16
|
+ 5: 'DST_ADDR_NOT_MAPPED',
|
|
|
17
|
+ 6: 'COUNT_ERROR',
|
|
|
18
|
+ 7: 'INVALID_SECTOR',
|
|
|
19
|
+ 8: 'SECTOR_NOT_BLANK',
|
|
|
20
|
+ 9: 'SECTOR_NOT_PREPARED_FOR_WRITE_OPERATION',
|
|
|
21
|
+ 10: 'COMPARE_ERROR',
|
|
|
22
|
+ 11: 'BUSY',
|
|
|
23
|
+ 12: 'PARAM_ERROR',
|
|
|
24
|
+ 13: 'ADDR_ERROR',
|
|
|
25
|
+ 14: 'ADDR_NOT_MAPPED',
|
|
|
26
|
+ 15: 'CMD_LOCKED',
|
|
|
27
|
+ 16: 'INVALID_CODE',
|
|
|
28
|
+ 17: 'INVALID_BAUD_RATE',
|
|
|
29
|
+ 18: 'INVALID_STOP_BIT',
|
|
|
30
|
+ 19: 'CODE_READ_PROTECTION_ENABLED ',
|
|
|
31
|
+}
|
|
|
32
|
+
|
|
|
33
|
+class LPC:
|
|
|
34
|
+ SYNCHRONIZED = 'Synchronized\r\n'
|
|
|
35
|
+ OK = 'OK\r\n'
|
|
|
36
|
+
|
|
|
37
|
+ def __init__(self):
|
|
|
38
|
+ self.port = serial.Serial('/dev/ttyUSB0', 115200, timeout=0.5)
|
|
|
39
|
+
|
|
|
40
|
+ def log(self, msg, eol=True):
|
|
|
41
|
+ if eol:
|
|
|
42
|
+ print msg
|
|
|
43
|
+ else:
|
|
|
44
|
+ print msg,
|
|
|
45
|
+
|
|
|
46
|
+ def set_reset(self, level):
|
|
|
47
|
+ self.port.setDTR(level == 0)
|
|
|
48
|
+
|
|
|
49
|
+ def set_bsl(self, level):
|
|
|
50
|
+ self.port.setRTS(level == 0)
|
|
|
51
|
+
|
|
|
52
|
+ def sync(self):
|
|
|
53
|
+ for tries in range(3):
|
|
|
54
|
+ self.set_bsl(0)
|
|
|
55
|
+ self.set_reset(1)
|
|
|
56
|
+ self.set_reset(0)
|
|
|
57
|
+ self.set_reset(1)
|
|
|
58
|
+
|
|
|
59
|
+ self.read(100)
|
|
|
60
|
+
|
|
|
61
|
+ self.write('?')
|
|
|
62
|
+
|
|
|
63
|
+ got = self.read(len(self.SYNCHRONIZED))
|
|
|
64
|
+
|
|
|
65
|
+ if got == self.SYNCHRONIZED:
|
|
|
66
|
+ self.send('Synchronized')
|
|
|
67
|
+ got = self.read(len(self.OK))
|
|
|
68
|
+
|
|
|
69
|
+ if got == self.OK:
|
|
|
70
|
+ self.send('12000')
|
|
|
71
|
+
|
|
|
72
|
+ got = self.read(len(self.OK))
|
|
|
73
|
+ if got == self.OK:
|
|
|
74
|
+ self.log(self.execute('N', (int, int, int, int)))
|
|
|
75
|
+ return
|
|
|
76
|
+
|
|
|
77
|
+ def load(self, address, data):
|
|
|
78
|
+ chunk = 512
|
|
|
79
|
+ per_line = 45
|
|
|
80
|
+
|
|
|
81
|
+ for offset in range(0, len(data), 512):
|
|
|
82
|
+ part = data[offset:offset+512]
|
|
|
83
|
+
|
|
|
84
|
+ self.send('W %d %d' % (address + offset, len(part)))
|
|
|
85
|
+ self.check_ok()
|
|
|
86
|
+
|
|
|
87
|
+ for micro in range(0, len(part), per_line):
|
|
|
88
|
+ encoded = binascii.b2a_uu(part[micro:micro+per_line])
|
|
|
89
|
+ assert encoded.endswith('\n')
|
|
|
90
|
+ encoded = encoded[:-1]
|
|
|
91
|
+
|
|
|
92
|
+ self.send(encoded)
|
|
|
93
|
+
|
|
|
94
|
+ check = sum(ord(x) for x in part)
|
|
|
95
|
+ self.send('%d' % check)
|
|
|
96
|
+
|
|
|
97
|
+ got = self.readline()
|
|
|
98
|
+
|
|
|
99
|
+ if got == 'OK':
|
|
|
100
|
+ pass
|
|
|
101
|
+ elif got == 'RESEND':
|
|
|
102
|
+ raise Error('Checksum error on write')
|
|
|
103
|
+ else:
|
|
|
104
|
+ raise Error('Protocol error')
|
|
|
105
|
+
|
|
|
106
|
+ def go(self, address):
|
|
|
107
|
+ self.execute('G', (), address, 'T')
|
|
|
108
|
+
|
|
|
109
|
+ while True:
|
|
|
110
|
+ try:
|
|
|
111
|
+ self.execute('J', (int, ))
|
|
|
112
|
+ break
|
|
|
113
|
+ except Error:
|
|
|
114
|
+ self.read(100)
|
|
|
115
|
+ time.sleep(0.1)
|
|
|
116
|
+
|
|
|
117
|
+ def unlock(self):
|
|
|
118
|
+ self.execute('U', (), 23130)
|
|
|
119
|
+
|
|
|
120
|
+ def check_ok(self):
|
|
|
121
|
+ assert self.readline() == '0'
|
|
|
122
|
+
|
|
|
123
|
+ def execute(self, command, result, *kargs):
|
|
|
124
|
+ send = command
|
|
|
125
|
+
|
|
|
126
|
+ for arg in kargs:
|
|
|
127
|
+ send += ' %s' % arg
|
|
|
128
|
+
|
|
|
129
|
+ self.send(send)
|
|
|
130
|
+
|
|
|
131
|
+ code = int(self.readline())
|
|
|
132
|
+
|
|
|
133
|
+ if code != 0:
|
|
|
134
|
+ raise Error(RETURN_CODE[code])
|
|
|
135
|
+
|
|
|
136
|
+ values = []
|
|
|
137
|
+
|
|
|
138
|
+ for t in result:
|
|
|
139
|
+ values.append(t(self.readline()))
|
|
|
140
|
+
|
|
|
141
|
+ return values
|
|
|
142
|
+
|
|
|
143
|
+ def readline(self):
|
|
|
144
|
+ v = ''
|
|
|
145
|
+
|
|
|
146
|
+ self.log('<', eol=False)
|
|
|
147
|
+
|
|
|
148
|
+ try:
|
|
|
149
|
+ while True:
|
|
|
150
|
+ got = self.read(1, True)
|
|
|
151
|
+
|
|
|
152
|
+ if got == '':
|
|
|
153
|
+ raise Error('No response')
|
|
|
154
|
+
|
|
|
155
|
+ if got == '\r':
|
|
|
156
|
+ got = self.read(1, True)
|
|
|
157
|
+
|
|
|
158
|
+ if got == '\n':
|
|
|
159
|
+ return v
|
|
|
160
|
+ else:
|
|
|
161
|
+ v += got
|
|
|
162
|
+ finally:
|
|
|
163
|
+ self.log('')
|
|
|
164
|
+
|
|
|
165
|
+ def write(self, v):
|
|
|
166
|
+ self.log('> %r' % v)
|
|
|
167
|
+ self.port.write(v)
|
|
|
168
|
+
|
|
|
169
|
+ def send(self, v):
|
|
|
170
|
+ v += '\r\n'
|
|
|
171
|
+
|
|
|
172
|
+ self.write(v)
|
|
|
173
|
+ got = self.read(len(v))
|
|
|
174
|
+
|
|
|
175
|
+ if got != v:
|
|
|
176
|
+ raise Error('Echo error. Sent %r, got %r' % (v, got))
|
|
|
177
|
+
|
|
|
178
|
+ def read(self, limit, partial=False):
|
|
|
179
|
+ got = self.port.read(limit)
|
|
|
180
|
+
|
|
|
181
|
+ if partial:
|
|
|
182
|
+ self.log('%r' % got, eol=False)
|
|
|
183
|
+ else:
|
|
|
184
|
+ self.log('< %r' % got)
|
|
|
185
|
+
|
|
|
186
|
+ return got
|
|
|
187
|
+
|
|
|
188
|
+l = LPC()
|
|
|
189
|
+l.sync()
|
|
|
190
|
+
|
|
|
191
|
+bin = open('first.bin', 'rb').read()
|
|
|
192
|
+l.unlock()
|
|
|
193
|
+l.load(0x10000400, bin)
|
|
|
194
|
+l.go(0x10000400)
|