turn ftdi driver into echo server
[goodfet] / client / goodfet.bslold
1 #!/usr/bin/env python
2 # Serial Bootstrap Loader software for the MSP430 embedded proccessor.
3 #
4 # (C) 2001-2003 Chris Liechti <cliechti@gmx.net>
5 # this is distributed under a free software license, see license-bsl.txt
6 #
7 # fixes from Colin Domoney
8 #
9 # based on the application note slas96b.pdf from Texas Instruments, Inc.,
10 # Volker Rzehak
11 # additional infos from slaa089a.pdf
12
13 # Forked by Travis Goodspeed <travis at tnbelt.com> for use with the GoodFET
14 # JTAG programmer.
15
16 # This WIP is intended to save the info flash when using --fromweb.
17 # DONE:
18 #  - Save info flash before actionMassErase
19 #  - Make actionFromweb use board name to get the right firmware image
20 #  - Program saved info after other programming is complete
21 #  - Make saveinfo detect missing info (all 0xFF)
22 # TODO:
23 #  - Trim unnecessary BSL unlocks
24 #  - Download image from web before erasing
25 #  - Add param to override saveinfo with a provided info.txt
26 #  - Figure out better way to saveinfo when -P is required
27 #  - Maybe use the best guess from contrib/infos/ when nothing better is provided?
28 #  - If saveinfo gets something interesting, request a copy
29 #  - Use FTDI Serial Number to archive info text and/or password (dragorn's idea)
30 #      /sys/bus/usb-serial/devices/ttyUSB0/../../serial
31
32 import sys, time, string, cStringIO, struct
33 #sys.path.append("/usr/lib/tinyos")  #We no longer require TinyOS.
34 import serial, os, glob
35
36 #forked from TinyOS Telos version.
37 VERSION = string.split("Revision: 1.39-goodfet-8 ")[1] 
38
39 DEBUG = 0                                       #disable debug messages by default
40
41 #copy of the patch file provided by TI
42 #this part is (C) by Texas Instruments
43 PATCH = """@0220
44 31 40 1A 02 09 43 B0 12 2A 0E B0 12 BA 0D 55 42
45 0B 02 75 90 12 00 1F 24 B0 12 BA 02 55 42 0B 02
46 75 90 16 00 16 24 75 90 14 00 11 24 B0 12 84 0E
47 06 3C B0 12 94 0E 03 3C 21 53 B0 12 8C 0E B2 40
48 10 A5 2C 01 B2 40 00 A5 28 01 30 40 42 0C 30 40
49 76 0D 30 40 AC 0C 16 42 0E 02 17 42 10 02 E2 B2
50 08 02 14 24 B0 12 10 0F 36 90 00 10 06 28 B2 40
51 00 A5 2C 01 B2 40 40 A5 28 01 D6 42 06 02 00 00
52 16 53 17 83 EF 23 B0 12 BA 02 D3 3F B0 12 10 0F
53 17 83 FC 23 B0 12 BA 02 D0 3F 18 42 12 02 B0 12
54 10 0F D2 42 06 02 12 02 B0 12 10 0F D2 42 06 02
55 13 02 38 E3 18 92 12 02 BF 23 E2 B3 08 02 BC 23
56 30 41
57 q
58 """
59
60 #These BSL's are (C) by TI. They come with the application note slaa089a
61 F1X_BSL = """@0220
62 24 02 2E 02 31 40 20 02 2B D2 C0 43 EA FF 32 C2
63 F2 C0 32 00 00 00 B2 40 80 5A 20 01 F2 40 85 00
64 57 00 F2 40 80 00 56 00 E2 D3 21 00 E2 D3 22 00
65 E2 C3 26 00 E2 C2 2A 00 E2 C2 2E 00 B2 40 10 A5
66 2C 01 B2 40 00 A5 28 01 3B C0 3A 00 B0 12 D6 04
67 82 43 12 02 09 43 36 40 0A 02 37 42 B0 12 AC 05
68 C6 4C 00 00 16 53 17 83 F9 23 D2 92 0C 02 0D 02
69 28 20 55 42 0B 02 75 90 12 00 80 24 75 90 10 00
70 6D 24 B0 12 9C 04 55 42 0B 02 75 90 18 00 31 24
71 75 90 1E 00 B8 24 75 90 20 00 17 24 2B B2 11 24
72 75 90 16 00 22 24 75 90 14 00 B3 24 75 90 1A 00
73 18 24 75 90 1C 00 45 24 04 3C B0 12 36 05 BE 3F
74 21 53 B0 12 3C 05 BA 3F 03 43 B0 12 36 05 D2 42
75 0E 02 56 00 D2 42 0F 02 57 00 D2 42 10 02 16 02
76 AD 3F B0 12 36 05 10 42 0E 02 16 42 0E 02 15 43
77 07 3C 36 40 FE FF B2 40 06 A5 10 02 35 40 0C 00
78 B2 40 00 A5 2C 01 92 42 10 02 28 01 B6 43 00 00
79 92 B3 2C 01 FD 23 15 83 F3 23 36 90 FE FF CD 27
80 37 40 80 00 36 F0 80 FF 36 90 00 11 0E 28 07 57
81 36 F0 00 FF 36 90 00 12 08 28 07 57 36 F0 00 FE
82 04 3C 16 42 0E 02 17 42 10 02 35 43 75 96 03 20
83 17 83 FC 23 B2 3F 82 46 00 02 B3 3F 36 40 E0 FF
84 37 40 20 00 B0 12 AC 05 7C 96 01 24 2B D3 17 83
85 F9 23 2B C2 B0 12 9C 04 2B D2 9F 3F 16 42 0E 02
86 17 42 10 02 2B B2 38 24 3B D0 10 00 B0 12 AC 05
87 36 90 00 10 06 2C 36 90 00 01 09 2C C6 4C 00 00
88 25 3C B2 40 00 A5 2C 01 B2 40 40 A5 28 01 16 B3
89 03 20 C2 4C 14 02 1A 3C C2 4C 15 02 86 9A FD FF
90 08 24 2B D3 3B B0 20 00 04 20 3B D0 20 00 82 46
91 00 02 36 90 01 02 04 28 3B D2 3B B0 10 00 02 24
92 3B C0 32 00 1A 42 14 02 86 4A FF FF 16 53 17 83
93 CD 23 B0 12 9C 04 61 3F B0 12 AC 05 17 83 FC 23
94 B0 12 9C 04 5E 3F B2 40 F0 0F 0E 02 B2 40 10 00
95 10 02 B2 40 80 00 0A 02 D2 42 10 02 0C 02 D2 42
96 10 02 0D 02 82 43 12 02 09 43 36 40 0A 02 27 42
97 7C 46 B0 12 40 05 17 83 FB 23 16 42 0E 02 17 42
98 10 02 36 90 00 01 0A 28 B2 46 14 02 5C 42 14 02
99 B0 12 40 05 17 83 5C 42 15 02 01 3C 7C 46 B0 12
100 40 05 17 83 EE 23 B2 E3 12 02 5C 42 12 02 B0 12
101 40 05 5C 42 13 02 B0 12 40 05 E0 3E 18 42 12 02
102 B0 12 AC 05 C2 4C 12 02 B0 12 AC 05 C2 4C 13 02
103 38 E3 3B B2 0A 24 86 9A FE FF 07 24 3B B0 20 00
104 04 20 16 53 82 46 00 02 2B D3 18 92 12 02 08 23
105 2B B3 06 23 30 41 E2 B2 28 00 FD 27 E2 B2 28 00
106 FD 23 B2 40 24 02 60 01 E2 B2 28 00 FD 27 15 42
107 70 01 05 11 05 11 05 11 82 45 02 02 05 11 82 45
108 04 02 B2 80 1E 00 04 02 57 42 16 02 37 80 03 00
109 05 11 05 11 17 53 FD 23 35 50 40 A5 82 45 2A 01
110 35 42 B2 40 24 02 60 01 92 92 70 01 02 02 FC 2F
111 15 83 F7 23 09 43 7C 40 90 00 02 3C 7C 40 A0 00
112 C2 43 07 02 C9 EC 12 02 19 E3 1B C3 55 42 07 02
113 55 45 56 05 00 55 0C 2E 2E 2E 2E 2E 2E 2E 2E 1A
114 34 34 92 42 70 01 72 01 B2 50 0C 00 72 01 07 3C
115 1B B3 0B 20 82 43 62 01 92 B3 62 01 FD 27 E2 C3
116 21 00 0A 3C 4C 11 F6 2B 1B E3 82 43 62 01 92 B3
117 62 01 FD 27 E2 D3 21 00 92 52 02 02 72 01 D2 53
118 07 02 F0 90 0C 00 61 FC D1 23 30 41 C2 43 09 02
119 1B C3 55 42 09 02 55 45 BC 05 00 55 0C 56 56 56
120 56 56 56 56 56 36 76 00 E2 B2 28 00 FD 23 92 42
121 70 01 72 01 92 52 04 02 72 01 82 43 62 01 92 B3
122 62 01 FD 27 E2 B2 28 00 1E 28 2B D3 1C 3C 4C 10
123 1A 3C 82 43 62 01 92 B3 62 01 FD 27 E2 B2 28 00
124 01 28 1B E3 1B B3 01 24 2B D3 C9 EC 12 02 19 E3
125 0A 3C 82 43 62 01 92 B3 62 01 FD 27 E2 B2 28 00
126 E6 2B 4C 10 1B E3 92 52 02 02 72 01 D2 53 09 02
127 C0 3F 82 43 62 01 92 B3 62 01 FD 27 E2 B2 28 00
128 01 2C 2B D3 30 41
129 q
130 """
131
132 F4X_BSL = """@0220
133 24 02 2E 02 31 40 20 02 2B D2 C0 43 EA FF 32 C2
134 F2 C0 32 00 00 00 B2 40 80 5A 20 01 32 D0 40 00
135 C2 43 50 00 F2 40 98 00 51 00 F2 C0 80 00 52 00
136 D2 D3 21 00 D2 D3 22 00 D2 C3 26 00 E2 C3 22 00
137 E2 C3 26 00 B2 40 10 A5 2C 01 B2 40 00 A5 28 01
138 3B C0 3A 00 B0 12 DE 04 82 43 12 02 09 43 36 40
139 0A 02 37 42 B0 12 B4 05 C6 4C 00 00 16 53 17 83
140 F9 23 D2 92 0C 02 0D 02 28 20 55 42 0B 02 75 90
141 12 00 80 24 75 90 10 00 6D 24 B0 12 A4 04 55 42
142 0B 02 75 90 18 00 31 24 75 90 1E 00 B8 24 75 90
143 20 00 17 24 2B B2 11 24 75 90 16 00 22 24 75 90
144 14 00 B3 24 75 90 1A 00 18 24 75 90 1C 00 45 24
145 04 3C B0 12 3E 05 BE 3F 21 53 B0 12 44 05 BA 3F
146 03 43 B0 12 3E 05 D2 42 0E 02 50 00 D2 42 0F 02
147 51 00 D2 42 10 02 16 02 AD 3F B0 12 3E 05 10 42
148 0E 02 16 42 0E 02 15 43 07 3C 36 40 FE FF B2 40
149 06 A5 10 02 35 40 0C 00 B2 40 00 A5 2C 01 92 42
150 10 02 28 01 B6 43 00 00 92 B3 2C 01 FD 23 15 83
151 F3 23 36 90 FE FF CD 27 37 40 80 00 36 F0 80 FF
152 36 90 00 11 0E 28 07 57 36 F0 00 FF 36 90 00 12
153 08 28 07 57 36 F0 00 FE 04 3C 16 42 0E 02 17 42
154 10 02 35 43 75 96 03 20 17 83 FC 23 B2 3F 82 46
155 00 02 B3 3F 36 40 E0 FF 37 40 20 00 B0 12 B4 05
156 7C 96 01 24 2B D3 17 83 F9 23 2B C2 B0 12 A4 04
157 2B D2 9F 3F 16 42 0E 02 17 42 10 02 2B B2 38 24
158 3B D0 10 00 B0 12 B4 05 36 90 00 10 06 2C 36 90
159 00 01 09 2C C6 4C 00 00 25 3C B2 40 00 A5 2C 01
160 B2 40 40 A5 28 01 16 B3 03 20 C2 4C 14 02 1A 3C
161 C2 4C 15 02 86 9A FD FF 08 24 2B D3 3B B0 20 00
162 04 20 3B D0 20 00 82 46 00 02 36 90 01 02 04 28
163 3B D2 3B B0 10 00 02 24 3B C0 32 00 1A 42 14 02
164 86 4A FF FF 16 53 17 83 CD 23 B0 12 A4 04 61 3F
165 B0 12 B4 05 17 83 FC 23 B0 12 A4 04 5E 3F B2 40
166 F0 0F 0E 02 B2 40 10 00 10 02 B2 40 80 00 0A 02
167 D2 42 10 02 0C 02 D2 42 10 02 0D 02 82 43 12 02
168 09 43 36 40 0A 02 27 42 7C 46 B0 12 48 05 17 83
169 FB 23 16 42 0E 02 17 42 10 02 36 90 00 01 0A 28
170 B2 46 14 02 5C 42 14 02 B0 12 48 05 17 83 5C 42
171 15 02 01 3C 7C 46 B0 12 48 05 17 83 EE 23 B2 E3
172 12 02 5C 42 12 02 B0 12 48 05 5C 42 13 02 B0 12
173 48 05 E0 3E 18 42 12 02 B0 12 B4 05 C2 4C 12 02
174 B0 12 B4 05 C2 4C 13 02 38 E3 3B B2 0A 24 86 9A
175 FE FF 07 24 3B B0 20 00 04 20 16 53 82 46 00 02
176 2B D3 18 92 12 02 08 23 2B B3 06 23 30 41 E2 B3
177 20 00 FD 27 E2 B3 20 00 FD 23 B2 40 24 02 60 01
178 E2 B3 20 00 FD 27 15 42 70 01 05 11 05 11 05 11
179 82 45 02 02 05 11 82 45 04 02 B2 80 1E 00 04 02
180 57 42 16 02 37 80 03 00 05 11 05 11 17 53 FD 23
181 35 50 40 A5 82 45 2A 01 35 42 B2 40 24 02 60 01
182 92 92 70 01 02 02 FC 2F 15 83 F7 23 09 43 7C 40
183 90 00 02 3C 7C 40 A0 00 C2 43 07 02 C9 EC 12 02
184 19 E3 1B C3 55 42 07 02 55 45 5E 05 00 55 0C 2E
185 2E 2E 2E 2E 2E 2E 2E 1A 34 34 92 42 70 01 72 01
186 B2 50 0C 00 72 01 07 3C 1B B3 0B 20 82 43 62 01
187 92 B3 62 01 FD 27 D2 C3 21 00 0A 3C 4C 11 F6 2B
188 1B E3 82 43 62 01 92 B3 62 01 FD 27 D2 D3 21 00
189 92 52 02 02 72 01 D2 53 07 02 F0 90 0C 00 59 FC
190 D1 23 30 41 C2 43 09 02 1B C3 55 42 09 02 55 45
191 C4 05 00 55 0C 56 56 56 56 56 56 56 56 36 76 00
192 E2 B3 20 00 FD 23 92 42 70 01 72 01 92 52 04 02
193 72 01 82 43 62 01 92 B3 62 01 FD 27 E2 B3 20 00
194 1E 28 2B D3 1C 3C 4C 10 1A 3C 82 43 62 01 92 B3
195 62 01 FD 27 E2 B3 20 00 01 28 1B E3 1B B3 01 24
196 2B D3 C9 EC 12 02 19 E3 0A 3C 82 43 62 01 92 B3
197 62 01 FD 27 E2 B3 20 00 E6 2B 4C 10 1B E3 92 52
198 02 02 72 01 D2 53 09 02 C0 3F 82 43 62 01 92 B3
199 62 01 FD 27 E2 B3 20 00 01 2C 2B D3 30 41
200 q
201 """
202
203 #cpu types for "change baudrate"
204 #use strings as ID so that they can be used in outputs too
205 F1x                     = "F1x family"
206 F2x                     = "F2x family"
207 F4x                     = "F4x family"
208
209 #known device list
210 deviceids = {
211     0xf149: F1x,
212     0xf16c: F1x, #for GoodFET10 to '20
213     0xf112: F1x,
214     0xf413: F4x,
215     0xf123: F1x,
216     0xf449: F4x,
217     0x1232: F1x,
218     0xf26f: F2x, #for GoodFET20
219     0xf227: F2x, #for GoodFET30
220 }
221
222 #GoodFET firmware
223 FIRMWARE_BASEURL = "http://goodfet.sourceforge.net/dist/";
224
225 board = None
226 BOARDS = {
227     #'apimote': "apimote1",     # .hex not uploaded yet
228     #'apimote1': "apimote1",
229     'facedancer10': "facedancer10",
230     'facedancer11': "facedancer11",
231     'goodfet11': "goodfet11",
232     'goodfet31': "goodfet31",
233     'goodfet41': "goodfet41",
234     'goodthopter10': "goodthopter10",
235     'goodthopter11': "goodthopter11",
236     'telosb': "telosb",
237     'telosbbt': "telosb",
238     'z1': "z1",
239     'zolertiaz1': "z1",
240 }
241
242 class BSLException(Exception):
243     pass
244
245 class LowLevel:
246     "lowlevel communication"
247     #Constants
248     MODE_SSP                = 0
249     MODE_BSL                = 1
250
251     BSL_SYNC                = 0x80
252     BSL_TXPWORD             = 0x10
253     BSL_TXBLK               = 0x12 #Transmit block to boot loader
254     BSL_RXBLK               = 0x14 #Receive  block from boot loader
255     BSL_ERASE               = 0x16 #Erase one segment
256     BSL_MERAS               = 0x18 #Erase complete FLASH memory
257     BSL_CHANGEBAUD          = 0x20 #Change baudrate
258     BSL_LOADPC              = 0x1A #Load PC and start execution
259     BSL_TXVERSION           = 0x1E #Get BSL version
260
261     #Upper limit of address range that might be modified by
262     #"BSL checksum bug".
263     BSL_CRITICAL_ADDR       = 0x0A00
264
265     #Header Definitions
266     CMD_FAILED              = 0x70
267     DATA_FRAME              = 0x80
268     DATA_ACK                = 0x90
269     DATA_NAK                = 0xA0
270
271     QUERY_POLL              = 0xB0
272     QUERY_RESPONSE          = 0x50
273
274     OPEN_CONNECTION         = 0xC0
275     ACK_CONNECTION          = 0x40
276
277     DEFAULT_TIMEOUT         =   1
278     DEFAULT_PROLONG         =  10
279     MAX_FRAME_SIZE          = 256
280     MAX_DATA_BYTES          = 250
281     MAX_DATA_WORDS          = 125
282
283     MAX_FRAME_COUNT         = 16
284
285     #Error messages
286     ERR_COM                 = "Unspecific error"
287     ERR_RX_NAK              = "NAK received (wrong password?)"
288     #ERR_CMD_NOT_COMPLETED   = "Command did not send ACK: indicates that it didn't complete correctly"
289     ERR_CMD_FAILED          = "Command failed, is not defined or is not allowed"
290     ERR_BSL_SYNC            = "Bootstrap loader synchronization error (maybe you need -P)"
291     ERR_FRAME_NUMBER        = "Frame sequence number error."
292     
293     z1 = 0;
294     
295     def calcChecksum(self, data, length):
296         """Calculates a checksum of "data"."""
297         checksum = 0
298
299         for i in range(length/2):
300             checksum = checksum ^ (ord(data[i*2]) | (ord(data[i*2+1]) << 8))    #xor-ing
301         return 0xffff & (checksum ^ 0xffff)         #inverting
302
303     def __init__(self, aTimeout = None, aProlongFactor = None):
304         """init bsl object, don't connect yet"""
305         if aTimeout is None:
306             self.timeout = self.DEFAULT_TIMEOUT
307         else:
308             self.timeout = aTimeout
309         if aProlongFactor is None:
310             self.prolongFactor = self.DEFAULT_PROLONG
311         else:
312             self.prolongFactor = aProlongFactor
313
314         #flags for inverted use of control pins
315         #used for some hardware
316         self.invertRST = 0
317         self.invertTEST = 0
318         self.swapRSTTEST = 0
319         self.telosLatch = 0
320         self.telosI2C = 0
321         
322         self.protocolMode = self.MODE_BSL
323         self.BSLMemAccessWarning = 0                #Default: no warning.
324         self.slowmode = 0
325
326     def comInit(self, port):
327         """Tries to open the serial port given and
328         initialises the port and variables.
329         The timeout and the number of allowed errors is multiplied by
330         'aProlongFactor' after transmission of a command to give
331         plenty of time to the micro controller to finish the command.
332         Returns zero if the function is successful."""
333         if DEBUG > 1: sys.stderr.write("* comInit()\n")
334         self.seqNo = 0
335         self.reqNo = 0
336         self.rxPtr = 0
337         self.txPtr = 0
338         # Startup-Baudrate: 9600,8,E,1, 1s timeout
339         self.serialport = serial.Serial(
340             port,
341             9600,
342             parity = serial.PARITY_EVEN,
343             timeout = self.timeout
344         )
345         if DEBUG: sys.stderr.write("using serial port %r\n" % self.serialport.portstr)
346         
347         if not self.z1:
348             self.SetRSTpin()                        #enable power
349             self.SetTESTpin()                       #enable power
350         self.serialport.flushInput()
351         self.serialport.flushOutput()
352
353     def comDone(self):
354         """Closes the used serial port.
355         This function must be called at the end of a program,
356         otherwise the serial port might not be released and can not be
357         used in other programs.
358         Returns zero if the function is successful."""
359         if DEBUG > 1: sys.stderr.write("* comDone()")
360         self.SetRSTpin(1)                       #disable power
361         self.SetTESTpin(0)                      #disable power
362         self.serialport.close()
363
364     def comRxHeader(self):
365         """receive header and split data"""
366         if DEBUG > 1: sys.stderr.write("* comRxHeader()\n")
367
368         hdr = self.serialport.read(1)
369         if not hdr: raise BSLException("Timeout")
370         rxHeader = ord(hdr) & 0xf0;
371         rxNum    = ord(hdr) & 0x0f;
372
373         if self.protocolMode == self.MODE_BSL:
374             self.reqNo = 0
375             self.seqNo = 0
376             rxNum = 0
377         if DEBUG > 1: sys.stderr.write("* comRxHeader() OK\n")
378         return rxHeader, rxNum
379
380     def comRxFrame(self, rxNum):
381         if DEBUG > 1: sys.stderr.write("* comRxFrame()\n")
382         rxFrame = chr(self.DATA_FRAME | rxNum)
383
384         if DEBUG > 2: sys.stderr.write("  comRxFrame() header...\n")
385         rxFramedata = self.serialport.read(3)
386         if len(rxFramedata) != 3: raise BSLException("Timeout")
387         rxFrame = rxFrame + rxFramedata
388
389         if DEBUG > 3: sys.stderr.write("  comRxFrame() check header...\n")
390         if rxFrame[1] == chr(0) and rxFrame[2] == rxFrame[3]:   #Add. header info. correct?
391             rxLengthCRC = ord(rxFrame[2]) + 2       #Add CRC-Bytes to length
392             if DEBUG > 2: sys.stderr.write("  comRxFrame() receiving data, size: %s\n" % rxLengthCRC)
393
394             rxFramedata = self.serialport.read(rxLengthCRC)
395             if len(rxFramedata) != rxLengthCRC: raise BSLException("Timeout")
396             rxFrame = rxFrame + rxFramedata
397             #Check received frame:
398             if DEBUG > 3: sys.stderr.write("  comRxFrame() crc check\n")
399             #rxLength+4: Length with header but w/o CRC:
400             checksum = self.calcChecksum(rxFrame, ord(rxFrame[2]) + 4)
401             if rxFrame[ord(rxFrame[2])+4] == chr(0xff & checksum) and \
402                rxFrame[ord(rxFrame[2])+5] == chr(0xff & (checksum >> 8)): #Checksum correct?
403                 #Frame received correctly (=> send next frame)
404                 if DEBUG > 2: sys.stderr.write("* comRxFrame() OK\n")
405                 return rxFrame
406             else:
407                 if DEBUG: sys.stderr.write("  comRxFrame() Checksum wrong\n")
408         else:
409             if DEBUG: sys.stderr.write("  comRxFrame() Header corrupt %r" % rxFrame)
410         raise BSLException(self.ERR_COM)            #Frame has errors!
411
412     def comTxHeader(self, txHeader):
413         """send header"""
414         if DEBUG > 1: sys.stderr.write("* txHeader()\n")
415         self.serialport.write(txHeader)
416
417     def comTxRx(self, cmd, dataOut, length):
418         """Sends the command cmd with the data given in dataOut to the
419         microcontroller and expects either an acknowledge or a frame
420         with result from the microcontroller.  The results are stored
421         in dataIn (if not a NULL pointer is passed).
422         In this routine all the necessary protocol stuff is handled.
423         Returns zero if the function was successful."""
424         if DEBUG > 1: sys.stderr.write("* comTxRx()\n")
425         txFrame     = []
426         rxHeader    = 0
427         rxNum       = 0
428
429         dataOut = list(dataOut)     #convert to a list for simpler data fill in
430         #Transmitting part ----------------------------------------
431         #Prepare data for transmit
432         if (length % 2) != 0:
433             #/* Fill with one byte to have even number of bytes to send */
434             if self.protocolMode == self.MODE_BSL:
435                 dataOut.append(0xFF)  #fill with 0xFF
436             else:
437                 dataOut.append(0)     #fill with zero
438
439         txFrame = "%c%c%c%c" % (self.DATA_FRAME | self.seqNo, cmd, len(dataOut), len(dataOut))
440
441         self.reqNo = (self.seqNo + 1) % self.MAX_FRAME_COUNT
442
443         txFrame = txFrame + string.join(dataOut,'')
444         checksum = self.calcChecksum(txFrame, length + 4)
445         txFrame = txFrame + chr(checksum & 0xff)
446         txFrame = txFrame + chr((checksum >> 8) & 0xff)
447
448         accessAddr = (0x0212 + (checksum^0xffff)) & 0xfffe  #0x0212: Address of wCHKSUM
449         if self.BSLMemAccessWarning and accessAddr < self.BSL_CRITICAL_ADDR:
450             sys.stderr.write("WARNING: This command might change data at address %04x or %04x!\n" % (accessAddr, accessAddr + 1))
451
452         self.serialport.flushInput()                #clear receiving queue
453         #TODO: Check after each transmitted character,
454         #TODO: if microcontroller did send a character (probably a NAK!).
455         for c in txFrame:
456             self.serialport.write(c)
457             if DEBUG > 3: sys.stderr.write("\ttx %02x" % ord(c))
458             #if self.serialport.inWaiting(): break  #abort when BSL replies, probably NAK
459         else:
460             if DEBUG > 1: sys.stderr.write( "  comTxRx() transmit OK\n")
461
462         #Receiving part -------------------------------------------
463         rxHeader, rxNum = self.comRxHeader()        #receive header
464         if DEBUG > 1: sys.stderr.write("  comTxRx() rxHeader=0x%02x, rxNum=%d, seqNo=%d, reqNo=%s\n" % (rxHeader, rxNum, self.seqNo, self.reqNo))
465         if rxHeader == self.DATA_ACK:               #acknowledge/OK
466             if DEBUG > 2: sys.stderr.write("  comTxRx() DATA_ACK\n")
467             if rxNum == self.reqNo:
468                 self.seqNo = self.reqNo
469                 if DEBUG > 2: sys.stderr.write("* comTxRx() DATA_ACK OK\n")
470                 return          #Acknowledge received correctly => next frame
471             raise BSLException(self.ERR_FRAME_NUMBER)
472         elif rxHeader == self.DATA_NAK:             #not acknowledge/error
473             if DEBUG > 2: sys.stderr.write("* comTxRx() DATA_NAK\n")
474             raise BSLException(self.ERR_RX_NAK)
475         elif rxHeader == self.DATA_FRAME:           #receive data
476             if DEBUG > 2: sys.stderr.write("* comTxRx() DATA_FRAME\n")
477             if rxNum == self.reqNo:
478                 rxFrame = self.comRxFrame(rxNum)
479                 return rxFrame
480             raise BSLException(self.ERR_FRAME_NUMBER)
481         elif rxHeader == self.CMD_FAILED:           #Frame ok, but command failed.
482             if DEBUG > 2: sys.stderr.write("*  comTxRx() CMD_FAILED\n")
483             raise BSLException(self.ERR_CMD_FAILED)
484
485         raise BSLException("Unknown header 0x%02x\nAre you downloading to RAM into an old device that requires the patch? Try option -U" % rxHeader)
486
487     def SetDTR(self, level, invert):
488         """Controls DTR pin (0: GND; 1: VCC; unless inverted flag is set)"""
489         if invert:
490             self.serialport.setDTR(not level)
491         else:
492             self.serialport.setDTR(level)
493         if self.slowmode:
494             time.sleep(0.040)
495
496     def SetRTS(self, level, invert):
497         """Controls RTS pin (0: GND; 1: VCC; unless inverted flag is set)"""
498         if invert:
499             self.serialport.setRTS(not level)
500         else:
501             self.serialport.setRTS(level)
502         if self.slowmode:
503             time.sleep(0.040)
504
505     def SetRSTpin(self, level=1):
506         """Controls RST/NMI pin (0: GND; 1: VCC; unless inverted flag is set)"""
507         if self.swapRSTTEST:
508             self.SetRTS(level, self.invertRST)
509         else:
510             self.SetDTR(level, self.invertRST)
511
512     def SetTESTpin(self, level=1):
513         """Controls TEST pin (inverted on board: 0: VCC; 1: GND; unless inverted flag is set)"""
514         if self.swapRSTTEST:
515             self.SetDTR(level, self.invertTEST)
516         else:
517             self.SetRTS(level, self.invertTEST)
518
519     def telosSetSCL(self, level):
520         self.serialport.setRTS(not level)
521
522     def telosSetSDA(self, level):
523         self.serialport.setDTR(not level)
524
525     def telosI2CStart(self):
526         self.telosSetSDA(1)
527         self.telosSetSCL(1)
528         self.telosSetSDA(0)
529
530     def telosI2CStop(self):
531         self.telosSetSDA(0)
532         self.telosSetSCL(1)
533         self.telosSetSDA(1)
534
535     def telosI2CWriteBit(self, bit):
536         self.telosSetSCL(0)
537         self.telosSetSDA(bit)
538         time.sleep(2e-6)
539         self.telosSetSCL(1)
540         time.sleep(1e-6)
541         self.telosSetSCL(0)
542
543     def telosI2CWriteByte(self, byte):
544         self.telosI2CWriteBit( byte & 0x80 );
545         self.telosI2CWriteBit( byte & 0x40 );
546         self.telosI2CWriteBit( byte & 0x20 );
547         self.telosI2CWriteBit( byte & 0x10 );
548         self.telosI2CWriteBit( byte & 0x08 );
549         self.telosI2CWriteBit( byte & 0x04 );
550         self.telosI2CWriteBit( byte & 0x02 );
551         self.telosI2CWriteBit( byte & 0x01 );
552         self.telosI2CWriteBit( 0 );  # "acknowledge"
553
554     def telosI2CWriteCmd(self, addr, cmdbyte):
555         self.telosI2CStart()
556         self.telosI2CWriteByte( 0x90 | (addr << 1) )
557         self.telosI2CWriteByte( cmdbyte )
558         self.telosI2CStop()
559     def writepicROM(self, address, data):
560         ''' Writes data to @address'''
561         for i in range(7,-1,-1):
562             self.picROMclock((address >> i) & 0x01)
563         self.picROMclock(0)
564         recbuf = 0
565         for i in range(7,-1,-1):
566             s = ((data >> i) & 0x01)
567             #print s
568             if i < 1:
569                 r = not self.picROMclock(s, True)
570             else:
571                 r = not self.picROMclock(s)
572             recbuf = (recbuf << 1) + r
573
574         self.picROMclock(0, True)
575         #k = 1
576         #while not self.serial.getCTS():
577         #    pass 
578         #time.sleep(0.1)
579         return recbuf
580
581     def readpicROM(self, address):
582         ''' reads a byte from @address'''
583         for i in range(7,-1,-1):
584             self.picROMclock((address >> i) & 0x01)
585         self.picROMclock(1)
586         recbuf = 0
587         r = 0
588         for i in range(7,-1,-1):
589             r = self.picROMclock(0)
590             recbuf = (recbuf << 1) + r
591         self.picROMclock(r)
592         #time.sleep(0.1)
593         return recbuf
594         
595     def picROMclock(self, masterout, slow = False):
596         #print "setting masterout to "+str(masterout)
597         self.serialport.setRTS(masterout)
598         self.serialport.setDTR(1)
599         #time.sleep(0.02)
600         self.serialport.setDTR(0)
601         if slow:
602             time.sleep(0.02)
603         return self.serialport.getCTS()
604
605     def picROMfastclock(self, masterout):
606         #print "setting masterout to "+str(masterout)
607         self.serialport.setRTS(masterout)
608         self.serialport.setDTR(1)
609         self.serialport.setDTR(0)
610         time.sleep(0.02)
611         return self.serialport.getCTS()
612
613     def bslResetZ1(self, invokeBSL=0):
614         '''
615         Applies BSL entry sequence on RST/NMI and TEST/VPP pins
616         Parameters:
617             invokeBSL = 1: complete sequence
618             invokeBSL = 0: only RST/NMI pin accessed
619             
620         By now only BSL mode is accessed
621         '''
622         
623         if DEBUG > 1: sys.stderr.write("* bslReset(invokeBSL=%s)\n" % invokeBSL)
624         if invokeBSL:
625             #sys.stderr.write("in Z1 bsl reset...\n")
626             time.sleep(0.1)
627             self.writepicROM(0xFF, 0xFF)
628             time.sleep(0.1)
629             #sys.stderr.write("z1 bsl reset done...\n")
630         else:
631             #sys.stderr.write("in Z1 reset...\n")
632             time.sleep(0.1)
633             self.writepicROM(0xFF, 0xFE)
634             time.sleep(0.1)
635             #sys.stderr.write("z1 reset done...\n")
636
637     def telosBReset(self,invokeBSL=0):
638         # "BSL entry sequence at dedicated JTAG pins"
639         # rst !s0: 0 0 0 0 1 1
640         # tck !s1: 1 0 1 0 0 1
641         #   s0|s1: 1 3 1 3 2 0
642
643         # "BSL entry sequence at shared JTAG pins"
644         # rst !s0: 0 0 0 0 1 1
645         # tck !s1: 0 1 0 1 1 0
646         #   s0|s1: 3 1 3 1 0 2
647
648         if invokeBSL:
649             self.telosI2CWriteCmd(0,1)
650             self.telosI2CWriteCmd(0,3)
651             self.telosI2CWriteCmd(0,1)
652             self.telosI2CWriteCmd(0,3)
653             self.telosI2CWriteCmd(0,2)
654             self.telosI2CWriteCmd(0,0)
655         else:
656             self.telosI2CWriteCmd(0,3)
657             self.telosI2CWriteCmd(0,2)
658
659         # This line was not defined inside the else: block, not sure where it
660         # should be however
661         self.telosI2CWriteCmd(0,0)
662         time.sleep(0.250)       #give MSP430's oscillator time to stabilize
663         self.serialport.flushInput()  #clear buffers
664
665     def bslReset(self, invokeBSL=0):
666         """Applies BSL entry sequence on RST/NMI and TEST/VPP pins
667         Parameters:
668             invokeBSL = 1: complete sequence
669             invokeBSL = 0: only RST/NMI pin accessed
670
671         RST is inverted twice on boot loader hardware
672         TEST is inverted (only once)
673         Need positive voltage on DTR, RTS for power-supply of hardware"""
674         if self.telosI2C:
675             self.telosBReset(invokeBSL)
676             return
677         
678         if self.z1:
679             if DEBUG > 1: sys.stderr.write("* entering bsl with z1\n")
680             self.bslResetZ1(invokeBSL)
681             return
682     
683
684         if DEBUG > 1: sys.stderr.write("* bslReset(invokeBSL=%s)\n" % invokeBSL)
685         self.SetRSTpin(1)       #power suply
686         self.SetTESTpin(1)      #power suply
687         time.sleep(0.250)       #charge capacitor on boot loader hardware
688
689         if self.telosLatch:
690             self.SetTESTpin(0)
691             self.SetRSTpin(0)
692             self.SetTESTpin(1)
693         self.SetRSTpin(0)       #RST  pin: GND
694
695         if invokeBSL:
696             self.SetTESTpin(1)  #TEST pin: GND
697             self.SetTESTpin(0)  #TEST pin: Vcc
698             self.SetTESTpin(1)  #TEST pin: GND
699             self.SetTESTpin(0)  #TEST pin: Vcc
700             self.SetRSTpin (1)  #RST  pin: Vcc
701             self.SetTESTpin(1)  #TEST pin: GND
702         else:
703             self.SetRSTpin(1)   #RST  pin: Vcc
704         time.sleep(0.250)       #give MSP430's oscillator time to stabilize
705
706         self.serialport.flushInput()    #clear buffers
707
708     def bslSync(self,wait=0):
709         """Transmits Synchronization character and expects to receive Acknowledge character
710         if wait is 0 it must work the first time. otherwise if wait is 1
711         it is retried (forever).
712         """
713         loopcnt = 5                                 #Max. tries to get synchronization
714
715         if DEBUG > 1: sys.stderr.write("* bslSync(wait=%d)\n" % wait)
716         while wait or loopcnt:
717             loopcnt = loopcnt - 1                   #count down tries
718             self.serialport.flushInput()            #clear input, in case a prog is running
719
720             self.serialport.write(chr(self.BSL_SYNC))   #Send synchronization byte
721             c = self.serialport.read(1)             #read answer
722             if c == chr(self.DATA_ACK):             #ACk
723                 if DEBUG > 1: sys.stderr.write("  bslSync() OK\n")
724                 return                              #Sync. successful
725             elif not c:                             #timeout
726                     if loopcnt > 4:
727                         if DEBUG > 1:
728                             sys.stderr.write("  bslSync() timeout, retry ...\n")
729                     elif loopcnt == 4:
730                         #nmi may have caused the first reset to be ignored, try again
731                         self.bslReset(0) 
732                         self.bslReset(1)
733                     elif loopcnt > 0:
734                         if DEBUG > 1:
735                             sys.stderr.write("  bslSync() timeout, retry ...\n")
736                     else :
737                         if DEBUG > 1:
738                             sys.stderr.write("  bslSync() timeout\n")
739             else:                                   #garbage
740                 if DEBUG > 1: sys.stderr.write("  bslSync() failed (0x%02x), retry ...\n" % ord(c))
741                 
742                 raise BSLException(self.ERR_BSL_SYNC)       #Sync. failed
743
744     def bslTxRx(self, cmd, addr, length = 0, blkout = None, wait=0):
745         """Transmits a command (cmd) with its parameters:
746         start-address (addr), length (len) and additional
747         data (blkout) to boot loader.
748         wait specified if the bsl sync should be tried once or
749         repeated, forever
750         Parameters return by boot loader are passed via blkin.
751         """
752         if DEBUG > 1: sys.stderr.write("* bslTxRx()\n")
753
754         if cmd == self.BSL_TXBLK:
755             #Align to even start address
756             if (addr % 2) != 0:
757                 addr = addr - 1                     #Decrement address and
758                 blkout = chr(0xFF) + blkOut         #fill first byte of blkout with 0xFF
759                 length = length + 1
760             #Make sure that len is even
761             if (length % 2) != 0:
762                 blkout = blkout + chr(0xFF)         #Inc. len and fill last byte of blkout with 0xFF
763                 length = length + 1
764
765         elif cmd == self.BSL_RXBLK:
766             #Align to even start address
767             if (addr % 2) != 0:
768                 addr = addr - 1                     #Decrement address but
769                 length = length + 1                 #request an additional byte
770             #Make sure that len is even
771             if (length % 2) != 0:
772                 length = length + 1
773
774         #if cmd == self.BSL_TXBLK or cmd == self.BSL_TXPWORD:
775         #    length = len + 4
776
777         #Add necessary information data to frame
778         dataOut =  struct.pack("<HH", addr, length)
779
780         if blkout: #Copy data out of blkout into frame
781             dataOut = dataOut + blkout
782
783         self.bslSync(wait)                          #synchronize BSL
784         rxFrame = self.comTxRx(cmd, dataOut, len(dataOut))  #Send frame
785         if rxFrame:                                 #test answer
786             return rxFrame[4:] #return only data w/o [hdr,null,len,len]
787         else:
788             return rxFrame
789
790
791 class Segment:
792     """store a string with memory contents along with its startaddress"""
793     def __init__(self, startaddress = 0, data=None):
794         if data is None:
795             self.data = ''
796         else:
797             self.data = data
798         self.startaddress = startaddress
799
800     def __getitem__(self, index):
801         return self.data[index]
802
803     def __len__(self):
804         return len(self.data)
805
806     def __repr__(self):
807         return "Segment(startaddress = 0x%04x, data=%r)" % (self.startaddress, self.data)
808
809 class Memory:
810     """represent memory contents. with functions to load files"""
811     def __init__(self, filename=None):
812         self.segments = []
813         if filename:
814             self.filename = filename
815             self.loadFile(filename)
816
817     def append(self, seg):
818         self.segments.append(seg)
819
820     def __getitem__(self, index):
821         return self.segments[index]
822
823     def __len__(self):
824         return len(self.segments)
825
826     def loadIHex(self, file):
827         """load data from a (opened) file in Intel-HEX format"""
828         segmentdata = []
829         currentAddr = 0
830         startAddr   = 0
831         lines = file.readlines()
832         for l in lines:
833             if l[0] != ':': raise BSLException("File Format Error\n")
834             l = l.strip()       #fix CR-LF issues...
835             length  = int(l[1:3],16)
836             address = int(l[3:7],16)
837             type    = int(l[7:9],16)
838             check   = int(l[-2:],16)
839             if type == 0x00:
840                 if currentAddr != address:
841                     if segmentdata:
842                         self.segments.append( Segment(startAddr, string.join(segmentdata,'')) )
843                     startAddr = currentAddr = address
844                     segmentdata = []
845                 for i in range(length):
846                     segmentdata.append( chr(int(l[9+2*i:11+2*i],16)) )
847                 currentAddr = length + currentAddr
848             elif type in (0x01, 0x02, 0x03, 0x04, 0x05):
849                 pass
850             else:
851                 sys.stderr.write("Ignored unknown field (type 0x%02x) in ihex file.\n" % type)
852         if segmentdata:
853             self.segments.append( Segment(startAddr, string.join(segmentdata,'')) )
854
855     def loadTIText(self, file):
856         """load data from a (opened) file in TI-Text format"""
857         next        = 1
858         startAddr   = 0
859         segmentdata = []
860         #Convert data for MSP430, TXT-File is parsed line by line
861         while next >= 1:
862             #Read one line
863             l = file.readline()
864             if not l: break #EOF
865             l = l.strip()
866             if l[0] == 'q': break
867             elif l[0] == '@':        #if @ => new address => send frame and set new addr.
868                 #create a new segment
869                 if segmentdata:
870                     self.segments.append( Segment(startAddr, string.join(segmentdata,'')) )
871                 startAddr = int(l[1:],16)
872                 segmentdata = []
873             else:
874                 for i in string.split(l):
875                     segmentdata.append(chr(int(i,16)))
876         if segmentdata:
877             self.segments.append( Segment(startAddr, string.join(segmentdata,'')) )
878
879     def loadELF(self, file):
880         """load data from a (opened) file in ELF object format.
881         File must be seekable"""
882         import elf
883         obj = elf.ELFObject()
884         obj.fromFile(file)
885         if obj.e_type != elf.ELFObject.ET_EXEC:
886             raise Exception("No executable")
887         for section in obj.getSections():
888             if DEBUG:
889                 sys.stderr.write("ELF section %s at 0x%04x %d bytes\n" % (section.name, section.lma, len(section.data)))
890             if len(section.data):
891                 self.segments.append( Segment(section.lma, section.data) )
892
893     def loadString(self, startAddr=0, string=None):
894         """fill memory with the contents of a binary chunk of data."""
895         self.segments.append(Segment(startAddr, string));
896         
897     def loadFile(self, filename):
898         """fill memory with the contents of a file. file type is determined from extension"""
899         #TODO: do a contents based detection
900         if filename[-4:].lower() == '.txt':
901             self.loadTIText(open(filename, "rb"))
902         elif filename[-4:].lower() in ('.a43', '.hex'):
903             self.loadIHex(open(filename, "rb"))
904         else:
905             self.loadELF(open(filename, "rb"))
906
907     def getMemrange(self, fromadr, toadr):
908         """get a range of bytes from the memory. unavailable values are filled with 0xff."""
909         res = ''
910         toadr = toadr + 1   #python indxes are excluding end, so include it
911         while fromadr < toadr:
912             #print "fromto: %04x %04x" % (fromadr, toadr)
913             for seg in self.segments:
914                 #print seg
915                 segend = seg.startaddress + len(seg.data)
916                 if seg.startaddress <= fromadr and fromadr < segend:
917                     #print "startok 0x%04x %d" % (seg.startaddress, len(seg.data))
918                     #print ("0x%04x "*3) % (segend, fromadr, toadr)
919                     if toadr > segend:   #not all data in segment
920                         #print "out of segment"
921                         catchlength = segend-fromadr
922                     else:
923                         catchlength = toadr-fromadr
924                     #print toadr-fromadr
925                     #print catchlength
926                     res = res + seg.data[fromadr-seg.startaddress : fromadr-seg.startaddress+catchlength]
927                     fromadr = fromadr + catchlength    #adjust start
928                     if len(res) >= toadr-fromadr:
929                         break#return res
930             else:
931                     res = res + chr(255)
932                     fromadr = fromadr + 1 #adjust start
933                     #print "fill FF"
934         #print "res: %r" % res
935         return res
936
937
938 class BootStrapLoader(LowLevel):
939     """higher level Bootstrap Loader functions."""
940
941     ERR_VERIFY_FAILED       = "Error: verification failed"
942     ERR_ERASE_CHECK_FAILED  = "Error: erase check failed"
943
944     ACTION_PROGRAM          = 0x01 #Mask: program data
945     ACTION_VERIFY           = 0x02 #Mask: verify data
946     ACTION_ERASE_CHECK      = 0x04 #Mask: erase check
947
948     #Max. bytes sent within one frame if parsing a TI TXT file.
949     #( >= 16 and == n*16 and <= MAX_DATA_BYTES!)
950     MAXDATA                 = 240-16
951
952
953     def __init__(self, *args, **kargs):
954         LowLevel.__init__(self, *args, **kargs)
955         self.byteCtr        = 0
956         self.meraseCycles   = 1
957         self.patchRequired  = 0
958         self.patchLoaded    = 0
959         self.bslVer         = 0
960         self.passwd         = None
961         self.data           = None
962         self.maxData        = self.MAXDATA
963         self.cpu            = None
964         self.info           = None
965
966     def fetchinfo(self):
967         data=self.uploadData(0x1000,256);
968         return data;
969
970     def dumpinfo(self):
971         data = self.fetchinfo();
972         hex="@1000\n";
973         for c in data:
974             hex+=("%02x "%ord(c));
975         hex+="\nq\n";
976         print hex;
977         return data;
978
979     def saveinfo(self):
980         sys.stderr.write('Checking for info flash...')
981         sys.stderr.flush()
982         data = self.fetchinfo();
983         good_data = False;
984         for c in data:
985             if ord(c) is not 255:
986                 good_data=True;
987                 break;
988         if good_data:
989             sys.stderr.write('  Saved!\n')
990             sys.stderr.flush()
991             self.info = Memory();
992             self.info.loadString(0x1000,data);
993         else:
994             sys.stderr.write('  None.\n')
995             sys.stderr.write('Look at contrib/infos/README.txt for better performance.\n')
996             sys.stderr.flush()
997
998     def preparePatch(self):
999         """prepare to download patch"""
1000         if DEBUG > 1: sys.stderr.write("* preparePatch()\n")
1001
1002         if self.patchLoaded:
1003             #Load PC with 0x0220.
1004             #This will invoke the patched bootstrap loader subroutines.
1005             self.bslTxRx(self.BSL_LOADPC,           #Command: Load PC
1006                            0x0220)                  #Address to load into PC
1007             self.BSLMemAccessWarning = 0 #Error is removed within workaround code
1008         return
1009
1010     def postPatch(self):
1011         """setup after the patch is loaded"""
1012         if DEBUG > 1: sys.stderr.write("* postPatch()\n")
1013         if self.patchLoaded:
1014             self.BSLMemAccessWarning = 1                #Turn warning back on.
1015
1016     
1017     def verifyBlk(self, addr, blkout, action):
1018         """verify memory against data or 0xff"""
1019         if DEBUG > 1: sys.stderr.write("* verifyBlk()\n")
1020
1021         if action & self.ACTION_VERIFY or action & self.ACTION_ERASE_CHECK:
1022             if DEBUG: sys.stderr.write("  Check starting at 0x%04x, %d bytes ... \n" % (addr, len(blkout)))
1023
1024             self.preparePatch()
1025             blkin = self.bslTxRx(self.BSL_RXBLK, addr, len(blkout))
1026             self.postPatch()
1027
1028             for i in range(len(blkout)):
1029                 if action & self.ACTION_VERIFY:
1030                     #Compare data in blkout and blkin
1031                     if blkin[i] != blkout[i]:
1032                         sys.stderr.write("Verification failed at 0x%04x (0x%02x, 0x%02x)\n" % (addr+i, ord(blkin[i]), ord(blkout[i])))
1033                         sys.stderr.flush()
1034                         raise BSLException(self.ERR_VERIFY_FAILED)      #Verify failed!
1035                     continue
1036                 elif action & self.ACTION_ERASE_CHECK:
1037                     #Compare data in blkin with erase pattern
1038                     if blkin[i] != chr(0xff):
1039                         sys.stderr.write("Erase Check failed at 0x%04x (0x%02x)\n" % (addr+i, ord(blkin[i])))
1040                         sys.stderr.flush()
1041                         raise BSLException(self.ERR_ERASE_CHECK_FAILED) #Erase Check failed!
1042                     continue
1043     def readBlk(self,adr,len):
1044         """Read a block of memory."""
1045         blkin = self.bslTxRx(self.BSL_RXBLK, addr, len(blkout))
1046         
1047     def programBlk(self, addr, blkout, action):
1048         """program a memory block"""
1049         if DEBUG > 1: sys.stderr.write("* programBlk()\n")
1050
1051         #Check, if specified range is erased
1052         self.verifyBlk(addr, blkout, action & self.ACTION_ERASE_CHECK)
1053
1054         if action & self.ACTION_PROGRAM:
1055             if DEBUG: sys.stderr.write("  Program starting at 0x%04x, %i bytes ...\n" % (addr, len(blkout)))
1056             self.preparePatch()
1057             #Program block
1058             self.bslTxRx(self.BSL_TXBLK, addr, len(blkout), blkout)
1059             self.postPatch()
1060
1061         #Verify block
1062         self.verifyBlk(addr, blkout, action & self.ACTION_VERIFY)
1063
1064     #segments:
1065     #list of tuples or lists:
1066     #segements = [ (addr1, [d0,d1,d2,...]), (addr2, [e0,e1,e2,...])]
1067     def programData(self, segments, action):
1068         """programm or verify data"""
1069         if DEBUG > 1: sys.stderr.write("* programData()\n")
1070         for seg in segments:
1071             currentAddr = seg.startaddress
1072             pstart = 0
1073             while pstart<len(seg.data):
1074                 length = self.MAXDATA
1075                 if pstart+length > len(seg.data):
1076                     length = len(seg.data) - pstart
1077                 self.programBlk(currentAddr, seg.data[pstart:pstart+length], action)
1078                 pstart = pstart + length
1079                 currentAddr = currentAddr + length
1080                 self.byteCtr = self.byteCtr + length #total sum
1081     
1082     def uploadData(self, startaddress, size, wait=0):
1083         """upload a datablock"""
1084         if DEBUG > 1: sys.stderr.write("* uploadData()\n")
1085         data = ''
1086         pstart = 0
1087         while pstart<size:
1088             length = self.maxData
1089             if pstart+length > size:
1090                 length = size - pstart
1091             data = data + self.bslTxRx(self.BSL_RXBLK,
1092                                        pstart+startaddress,
1093                                        length,
1094                                        wait=wait)[:-2] #cut away checksum
1095             pstart = pstart + length
1096         return data
1097
1098     def txPasswd(self, passwd=None, wait=0):
1099         """transmit password, default if None is given."""
1100         if DEBUG > 1: sys.stderr.write("* txPassword(%r)\n" % passwd)
1101         if passwd is None:
1102             #Send "standard" password to get access to protected functions.
1103             sys.stderr.write("Transmit default password ...\n")
1104             sys.stderr.flush()
1105             #Flash is completely erased, the contents of all Flash cells is 0xff
1106             passwd = chr(0xff)*32
1107         else:
1108             #sanity check of password
1109             if len(passwd) != 32:
1110                 raise ValueError, "password has wrong length (%d)\n" % len(passwd)
1111             sys.stderr.write('Transmit password ...\n')
1112             sys.stderr.flush()
1113         #send the password
1114         self.bslTxRx(self.BSL_TXPWORD,      #Command: Transmit Password
1115                        0xffe0,              #Address of interupt vectors
1116                        0x0020,              #Number of bytes
1117                        passwd,              #password
1118                        wait=wait)           #if wait is 1, try to sync forever
1119
1120
1121     #-----------------------------------------------------------------
1122
1123     def actionMassErase(self):
1124         """Erase the flash memory completely (with mass erase command)"""
1125         sys.stderr.write("Mass Erase...\n")
1126         sys.stderr.flush()
1127         self.bslReset(1)                            #Invoke the boot loader.
1128         for i in range(self.meraseCycles):
1129             if i == 1: sys.stderr.write("Additional Mass Erase Cycles...\n")
1130             self.bslTxRx(self.BSL_MERAS,            #Command: Mass Erase
1131                                 0xff00,             #Any address within flash memory.
1132                                 0xa506)             #Required setting for mass erase!
1133         self.passwd = None                          #No password file required!
1134         #print "Mass Erase complete"
1135         #Transmit password to get access to protected BSL functions.
1136         self.txPasswd()
1137
1138     def actionStartBSL(self, usepatch=1, adjsp=1, replacementBSL=None, forceBSL=0, mayuseBSL=0, speed=None, bslreset=1):
1139         """start BSL, download patch if desired and needed, adjust SP if desired"""
1140         sys.stderr.write("Invoking BSL...\n")
1141         sys.stderr.flush()
1142         
1143         #for '30, invertTEST=0, else =1
1144         if bslreset:
1145             self.bslReset(1)                        #Invoke the boot loader.
1146         
1147         
1148         self.txPasswd(self.passwd)                  #transmit password
1149
1150         #Read actual bootstrap loader version.
1151         #sys.stderr.write("Reading BSL version ...\n")
1152         blkin = self.bslTxRx(self.BSL_RXBLK,        #Command: Read/Receive Block
1153                           0x0ff0,                   #Start address
1154                           16)                       #No. of bytes to read
1155         dev_id, bslVerHi, bslVerLo = struct.unpack(">H8xBB4x", blkin[:-2]) #cut away checksum and extract data
1156         self.dev_id=dev_id;
1157         
1158         
1159         if self.cpu is None:                        #cpy type forced?
1160             if deviceids.has_key(dev_id):
1161                 self.cpu = deviceids[dev_id]        #try to autodectect CPU type
1162                 
1163                 if DEBUG:
1164                     sys.stderr.write("Autodetect successful: %04x -> %s\n" % (dev_id, self.cpu))
1165             else:
1166                 sys.stderr.write("Autodetect failed! Unkown ID: %04x. Trying to continue anyway.\n" % dev_id)
1167                 self.cpu = F1x                      #assume something and try anyway..
1168
1169         sys.stderr.write("Current bootstrap loader version: %x.%x (Device ID: %04x)\n" % (bslVerHi, bslVerLo, dev_id))
1170         sys.stderr.flush()
1171         self.bslVer = (bslVerHi << 8) | bslVerLo
1172
1173         if self.bslVer <= 0x0110:                   #check if patch is needed
1174             self.BSLMemAccessWarning = 1
1175         else:
1176             self.BSLMemAccessWarning = 0 #Fixed in newer versions of BSL.
1177
1178         if self.bslVer <= 0x0130 and adjsp:
1179             #only do this on BSL where it's needed to prevent
1180             #malfunction with F4xx devices/ newer ROM-BSLs
1181             
1182             #Execute function within bootstrap loader
1183             #to prepare stack pointer for the following patch.
1184             #This function will lock the protected functions again.
1185             sys.stderr.write("Adjust SP. Load PC with 0x0C22 ...\n")
1186             self.bslTxRx(self.BSL_LOADPC,           #Command: Load PC
1187                                 0x0C22)             #Address to load into PC
1188             #Re-send password to re-gain access to protected functions.
1189             self.txPasswd(self.passwd)
1190
1191         #get internal BSL replacement if needed or forced by the user
1192         #required if speed is set but an old BSL is in the device
1193         #if a BSL is given by the user, that one is used and not the internal one
1194         if ((mayuseBSL and speed and self.bslVer < 0x0150) or forceBSL) and replacementBSL is None:
1195             replacementBSL = Memory() #File to program
1196             if self.cpu == F4x:
1197                 if DEBUG:
1198                     sys.stderr.write("Using built in BSL replacement for F4x devices\n")
1199                     sys.stderr.flush()
1200                 replacementBSL.loadTIText(cStringIO.StringIO(F4X_BSL))  #parse embedded BSL
1201             else:
1202                 if DEBUG:
1203                     sys.stderr.write("Using built in BSL replacement for F1x devices\n")
1204                     sys.stderr.flush()
1205                 replacementBSL.loadTIText(cStringIO.StringIO(F1X_BSL))  #parse embedded BSL
1206     
1207         #now download the new BSL, if allowed and needed (version lower than the
1208         #the replacement) or forced
1209         if replacementBSL is not None:
1210             self.actionDownloadBSL(replacementBSL)
1211
1212         #debug message with the real BSL version in use (may have changed after replacement BSL)
1213         if DEBUG:
1214             sys.stderr.write("Current bootstrap loader version: 0x%04x\n" % (self.bslVer,))
1215             sys.stderr.flush()
1216
1217         #now apply workarounds or patches if BSL in use requires that
1218         if self.bslVer <= 0x0110:                   #check if patch is needed
1219             if usepatch:                            #test if patch is desired
1220                 sys.stderr.write("Patch for flash programming required!\n")
1221                 self.patchRequired = 1
1222
1223                 sys.stderr.write("Load and verify patch ...\n")
1224                 sys.stderr.flush()
1225                 #Programming and verification is done in one pass.
1226                 #The patch file is only read and parsed once.
1227                 segments = Memory()                     #data to program
1228                 segments.loadTIText(cStringIO.StringIO(PATCH))  #parse embedded patch
1229                 #program patch
1230                 self.programData(segments, self.ACTION_PROGRAM | self.ACTION_VERIFY)
1231                 self.patchLoaded = 1
1232             else:
1233                 if DEBUG:
1234                     sys.stderr.write("Device needs patch, but not applied (usepatch is false).\n")    #message if not patched
1235
1236         #should the baudrate be changed?
1237         if speed is not None:
1238             self.actionChangeBaudrate(speed)            #change baudrate
1239
1240     def actionDownloadBSL(self, bslsegments):
1241         sys.stderr.write("Load new BSL into RAM...\n")
1242         sys.stderr.flush()
1243         self.programData(bslsegments, self.ACTION_PROGRAM)
1244         sys.stderr.write("Verify new BSL...\n")
1245         sys.stderr.flush()
1246         self.programData(bslsegments, self.ACTION_VERIFY) #File to verify
1247
1248         #Read startvector of bootstrap loader
1249         #blkin = self.bslTxRx(self.BSL_RXBLK, 0x0300, 2)
1250         #blkin = self.bslTxRx(self.BSL_RXBLK, 0x0220, 2)
1251         blkin = self.bslTxRx(self.BSL_RXBLK, bslsegments[0].startaddress, 2)
1252         startaddr = struct.unpack("<H", blkin[:2])[0]
1253
1254         sys.stderr.write("Starting new BSL at 0x%04x...\n" % startaddr)
1255         sys.stderr.flush()
1256         self.bslTxRx(self.BSL_LOADPC,  #Command: Load PC
1257                      startaddr)        #Address to load into PC
1258
1259         #BSL-Bugs should be fixed within "new" BSL
1260         self.BSLMemAccessWarning = 0
1261         self.patchRequired = 0
1262         self.patchLoaded   = 0
1263
1264         #Re-send password to re-gain access to protected functions.
1265         self.txPasswd(self.passwd)
1266
1267         #update version info
1268         #verison only valid for the internal ones, but it also makes sure 
1269         #that the patches are not applied if the user d/ls one
1270         self.bslVer = 0x0150
1271
1272     def actionEraseCheck(self):
1273         """check the erasure of required flash cells."""
1274         sys.stderr.write("Erase Check by file ...\n")
1275         sys.stderr.flush()
1276         if self.data is not None:
1277             self.programData(self.data, self.ACTION_ERASE_CHECK)
1278         else:
1279             raise BSLException, "cannot do erase check against data with not knowing the actual data"
1280
1281     def actionProgram(self):
1282         """program data into flash memory."""
1283         if self.data is not None:
1284             sys.stderr.write("Program ...\n")
1285             sys.stderr.flush()
1286             self.programData(self.data, self.ACTION_PROGRAM)
1287             sys.stderr.write("%i bytes programmed.\n" % self.byteCtr)
1288             sys.stderr.flush()
1289         else:
1290             raise BSLException, "programming without data not possible"
1291
1292     def actionFromweb(self):
1293         """Grab GoodFET firmware from the web, then flash it."""
1294         url="%s%s.hex" % (FIRMWARE_BASEURL, self.board);
1295         print "Grabbing %s firmware from %s" % (self.board, url);
1296         fn="/tmp/.%s.hex" % self.board
1297         os.system("curl %s >%s" % (url,fn))
1298         
1299         fw=Memory(fn);
1300         
1301         sys.stderr.write("Program ...\n")
1302         sys.stderr.flush()
1303         self.programData(fw, self.ACTION_PROGRAM | self.ACTION_VERIFY)
1304         sys.stderr.write("%i bytes programmed.\n" % self.byteCtr)
1305         sys.stderr.flush()
1306
1307     def actionVerify(self):
1308         """Verify programmed data"""
1309         if self.data is not None:
1310             sys.stderr.write("Verify ...\n")
1311             sys.stderr.flush()
1312             self.programData(self.data, self.ACTION_VERIFY)
1313         else:
1314             raise BSLException, "verify without data not possible"
1315
1316     def actionReset(self):
1317         """perform a reset, start user programm"""
1318         sys.stderr.write("Reset device ...\n")
1319         sys.stderr.flush()
1320         self.bslReset(0) #only reset
1321
1322     def actionRun(self, address=0x220):
1323         """start program at specified address"""
1324         sys.stderr.write("Load PC with 0x%04x ...\n" % address)
1325         sys.stderr.flush()
1326         self.bslTxRx(self.BSL_LOADPC, #Command: Load PC
1327                             address)  #Address to load into PC
1328
1329     #table with values from slaa089a.pdf
1330     bauratetable = {
1331         F1x: {
1332              9600:[0x8580, 0x0000],
1333             19200:[0x86e0, 0x0001],
1334             38400:[0x87e0, 0x0002],
1335         },
1336         F2x: {
1337              9600:[0x8580, 0x0000],
1338             19200:[0x8B00, 0x0001],
1339             38400:[0x8C80, 0x0002],
1340         },
1341         F4x: {
1342              9600:[0x9800, 0x0000],
1343             19200:[0xb000, 0x0001],
1344             38400:[0xc800, 0x0002],
1345         },
1346     }
1347     def actionChangeBaudrate(self, baudrate=9600):
1348         """change baudrate. first the command is sent, then the comm
1349         port is reprogrammed. only possible with newer MSP430-BSL versions.
1350         (ROM >=1.6, downloadable >=1.5)"""
1351         try:
1352             baudconfigs = self.bauratetable[self.cpu]
1353         except KeyError:
1354             raise ValueError, "unknown CPU type %s, can't switch baudrate" % self.cpu
1355         try:
1356             a,l = baudconfigs[baudrate]
1357         except KeyError:
1358             raise ValueError, "baudrate not valid. valid values are %r" % baudconfigs.keys()
1359         
1360         sys.stderr.write("Changing baudrate to %d ...\n" % baudrate)
1361         sys.stderr.flush()
1362         self.bslTxRx(self.BSL_CHANGEBAUD,   #Command: change baudrate
1363                     a, l)                   #args are coded in adr and len
1364         time.sleep(0.010)                   #recomended delay
1365         self.serialport.setBaudrate(baudrate)
1366
1367     def actionReadBSLVersion(self):
1368         """informational output of BSL version number.
1369         (newer MSP430-BSLs only)"""
1370         ans = self.bslTxRx(self.BSL_TXVERSION, 0) #Command: receive version info
1371         #the following values are in big endian style!!!
1372         family_type, bsl_version = struct.unpack(">H8xH4x", ans[:-2]) #cut away checksum and extract data
1373         print "Device Type: 0x%04x\nBSL version: 0x%04x\n" % (family_type, bsl_version)
1374
1375
1376 def usage():
1377     """print some help message"""
1378     sys.stderr.write("""
1379 USAGE: %s [options] [file]
1380 Version: %s
1381
1382 If "-" is specified as file the data is read from the stdinput.
1383 A file ending with ".txt" is considered to be in TIText format,
1384 '.a43' and '.hex' as IntelHex and all other filenames are
1385 considered as ELF files.
1386
1387 General options:
1388   -h, --help            Show this help screen.
1389   -c, --comport=port    Specify the communication port to be used.
1390                         (Default is 0)
1391                                 0->COM1 / ttyS0
1392                                 1->COM2 / ttyS1
1393                                 etc.
1394   -P, --password=file   Specify a file with the interrupt vectors that
1395                         are used as password. This can be any file that
1396                         has previously been used to program the device.
1397                         (e.g. -P INT_VECT.TXT or -P goodfet.hex).
1398   -f, --framesize=num   Max. number of data bytes within one transmitted
1399                         frame (16 to 240 in steps of 16) (e.g. -f 240).
1400   -m, --erasecycles=num Number of mass erase cycles (default is 1). Some
1401                         old F149 devices need additional erase cycles.
1402                         On newer devices it is no longer needed. (e.g. for
1403                         an old F149: -m20)
1404   -U, --unpatched       Do not download the BSL patch, even when it is
1405                         needed. This is used when a program is downloaded
1406                         into RAM and executed from there (and where flash
1407                         programming is not needed.)
1408   -D, --debug           Increase level of debug messages. This won't be
1409                         very useful for the average user...
1410   -I, --intelhex        Force fileformat to IntelHex
1411   -T, --titext          Force fileformat to be TIText
1412   -N, --notimeout       Don't use timeout on serial port (use with care)
1413   -B, --bsl=bsl.txt     Load and use new BSL from the TI Text file
1414   -S, --speed=baud      Reconfigure speed, only possible with newer
1415                         MSP403-BSL versions (>1.5, read slaa089a.pdf for
1416                         details). If the --bsl option is not used, an
1417                         internal BSL replacement will be loaded.
1418                         Needs a target with at least 2kB RAM!
1419                         Possible values are 9600, 19200, 38400
1420                         (default 9600)
1421   -1, --f1x             Specify CPU family, in case autodetect fails
1422   -2, --f2x             Specify CPU family, in case autodetect fails
1423   -4, --f4x             Specify CPU family, in case autodetect fails
1424                         --F1x and --f2x are only needed when the "change
1425                         baudrate" feature is used and the autodetect feature
1426                         fails. If the device ID that is uploaded is known, it
1427                         has precedence to the command line option.
1428   --invert-reset        Invert signal on RST pin (used for some BSL hardware)
1429   --invert-test         Invert signal on TEST/TCK pin (used for some BSL
1430                         hardware)
1431   --swap-reset-test     Swap the RST and TEST pins (used for some BSL hardware)
1432   --telos-latch         Special twiddle in BSL reset for Telos hardware
1433   --telos-i2c           DTR/RTS map via an I2C switch to TCK/RST in Telos Rev.B
1434   --telos               Implies options --invert-reset, --invert-test, 
1435                         --swap-reset-test, and --telos-latch
1436   --telosb              Implies options --swap-reset-test, --telos-i2c,
1437                         --no-BSL-download, and --speed=38400
1438   --apimote             Implies --swap-reset-test
1439   --goodfet10
1440   --goodfet20
1441   --goodfet30
1442   --goodthopter         Same as GF30.
1443   --tmote               Identical operation to --telosb
1444   --z1                  Bootstrap a Z1
1445   --no-BSL-download     Do not download replacement BSL (disable automatic)
1446   --force-BSL-download  Download replacement BSL even if not needed (the one
1447                         in the device would have the required features)
1448   --slow                Add delays when operating the conrol pins. Useful if
1449                         the pins/circuit has high capacitance.
1450   --dumpinfo            Print the info flash timing data so you can save a copy
1451                         for later.  You must provide -P if flash is not empty.
1452
1453 Program Flow Specifiers:
1454   -e, --masserase       Mass Erase (clear all flash memory)
1455   -E, --erasecheck      Erase Check by file
1456   -p, --program         Program file
1457   -v, --verify          Verify by file
1458
1459 The order of the above options matters! The table is ordered by normal
1460 execution order. For the options "Epv" a file must be specified.
1461 Program flow specifiers default to "pvr" if a file is given.
1462 Don't forget to specify "e" or "eE" when programming flash!
1463
1464 Data retreiving:
1465   -u, --upload=addr     Upload a datablock (see also: -s).
1466   -s, --size=num        Size of the data block do upload. (Default is 2)
1467   -x, --hex             Show a hexadecimal display of the uploaded data.
1468                         (Default)
1469   -b, --bin             Get binary uploaded data. This can be used
1470                         to redirect the output into a file.
1471
1472 Do before exit:
1473   -g, --go=address      Start programm execution at specified address.
1474                         This implies option --wait.
1475   -r, --reset           Reset connected MSP430. Starts application.
1476                         This is a normal device reset and will start
1477                         the programm that is specified in the reset
1478                         vector. (see also -g)
1479   -w, --wait            Wait for <ENTER> before closing serial port.
1480
1481 If it says "NAK received" it's probably because you specified no or a
1482 wrong password.
1483 """ % (sys.argv[0], VERSION))
1484
1485 #add some arguments to a function, but don't call it yet, instead return
1486 #a wrapper object for later invocation
1487 class curry:
1488     """create a callable with some arguments specified in advance"""
1489     def __init__(self, fun, *args, **kwargs):
1490         self.fun = fun
1491         self.pending = args[:]
1492         self.kwargs = kwargs.copy()
1493
1494     def __call__(self, *args, **kwargs):
1495         if kwargs and self.kwargs:
1496             kw = self.kwargs.copy()
1497             kw.update(kwargs)
1498         else:
1499             kw = kwargs or self.kwargs
1500         return apply(self.fun, self.pending + args, kw)
1501
1502     def __repr__(self):
1503         #first try if it a function
1504         try:
1505             return "curry(%s, %r, %r)" % (self.fun.func_name, self.pending, self.kwargs)
1506         except AttributeError:
1507             #fallback for callable classes
1508             return "curry(%s, %r, %r)" % (self.fun, self.pending, self.kwargs)
1509
1510 def hexify(line, bytes, width=16):
1511     return  '%04x  %s%s %s' % (
1512         line,
1513         ('%02x '*len(bytes)) % tuple(bytes),
1514         '   '* (width-len(bytes)),
1515         ('%c'*len(bytes)) % tuple(map(lambda x: (x>=32 and x<127) and x or ord('.'), bytes))
1516         )
1517
1518 #Main:
1519 def main(itest=1):
1520     global DEBUG
1521     global board
1522     import getopt
1523     filetype    = None
1524     filename    = None
1525     comPort     = None     #Default setting.
1526     speed       = None
1527     unpatched   = 0
1528     reset       = 0
1529     wait        = 0     #wait at the end
1530     goaddr      = None
1531     bsl         = BootStrapLoader()
1532     deviceinit  = []
1533     todo        = []
1534     startaddr   = None
1535     size        = 2
1536     hexoutput   = 1
1537     notimeout   = 0
1538     bslrepl     = None
1539     mayuseBSL   = 1
1540     forceBSL    = 0
1541     dumpivt     = 0
1542     dumpinfo    = 0
1543     
1544     bsl.invertRST = 1
1545     bsl.invertTEST = itest
1546     
1547     if os.environ.get("board")==None:
1548       if board==None:
1549         print "Board not specified.  Defaulting to goodfet41.";
1550         raw_input("Press Ctrl+C to cancel, or Enter to continue.");
1551         board='goodfet41';
1552       bsl.board=board;
1553     else:
1554       bsl.board=None;
1555       try:
1556         bsl.board=BOARDS[os.environ.get("board").lower()];
1557       except:
1558         pass;
1559     if bsl.board==None:
1560       print "Unknown board specified.  Try goodfet41, facedancer11, or similar.";
1561       sys.exit(2);
1562       
1563     if bsl.board=='telosb':
1564         bsl.swapRSTTEST = 1
1565         bsl.telosI2C = 1
1566         mayuseBSL = 0
1567     if bsl.board=='z1':
1568         bsl.z1 = 1
1569     if bsl.board=='apimote':
1570         bsl.swapRSTTEST = 1;
1571     
1572     
1573     if comPort is None and os.environ.get("GOODFET")!=None:
1574         glob_list = glob.glob(os.environ.get("GOODFET"));
1575         if len(glob_list) > 0:
1576             comPort = glob_list[0];
1577     if comPort is None:
1578         glob_list = glob.glob("/dev/tty.usbserial*");
1579         if len(glob_list) > 0:
1580             comPort = glob_list[0];
1581     if comPort is None:
1582         glob_list = glob.glob("/dev/ttyUSB*");
1583         if len(glob_list) > 0:
1584             comPort = glob_list[0];
1585     if os.name=='nt':
1586             from scanwin32 import winScan;
1587             scan=winScan();
1588             for order,comport,desc,hwid in sorted(scan.comports()):
1589                 try:
1590                     if hwid.index('FTDI')==0:
1591                         comPort=comport;
1592                         #print "Using FTDI port %s" % port
1593                 except:
1594                     #Do nothing.
1595                     a=1;
1596     sys.stderr.write("MSP430 Bootstrap Loader Version: %s\n" % VERSION)
1597
1598     try:
1599         opts, args = getopt.getopt(sys.argv[1:],
1600             "hc:P:wf:m:eEpvrg:UDudsxbITNB:S:V14",
1601             ["help", "comport=", "password=", "wait", "framesize=",
1602              "erasecycles=", "masserase", "erasecheck", "program",
1603              "verify", "reset", "go=", "unpatched", "debug",
1604              "upload=", "download=", "size=", "hex", "bin",
1605              "intelhex", "titext", "notimeout", "bsl=", "speed=",
1606              "bslversion", "f1x", "f2x", "f4x", "invert-reset", "invert-test",
1607              "swap-reset-test", "telos-latch", "telos-i2c", "telos", "telosb",
1608              "tmote","no-BSL-download", "force-BSL-download", "slow",
1609              "dumpivt", "dumpinfo", "fromweb",
1610              "goodfet40", "goodfet30",  "goodthopter", "goodfet20", "goodfet10",
1611              "z1",
1612              "nhbadge", "nhbadgeb", "goodfet"
1613             ]
1614         )
1615     except getopt.GetoptError:
1616         # print help information and exit:
1617         usage()
1618         sys.exit(2)
1619
1620     for o, a in opts:
1621         if o in ("-h", "--help"):
1622             usage()
1623             sys.exit()
1624         elif o in ("-c", "--comport"):
1625             try:
1626                 comPort = int(a)                    #try to convert decimal
1627             except ValueError:
1628                 comPort = a                         #take the string and let serial driver decide
1629         elif o in ("-P", "--password"):
1630             #extract password from file
1631             bsl.passwd = Memory(a).getMemrange(0xffe0, 0xffff)
1632         elif o in ("-w", "--wait"):
1633             wait = 1
1634         elif o in ("--dumpivt"):
1635             dumpivt=1;
1636         elif o in ("--dumpinfo"):
1637             dumpinfo=1;
1638         elif o in ("-f", "--framesize"):
1639             try:
1640                 maxData = int(a)                    #try to convert decimal
1641             except ValueError:
1642                 sys.stderr.write("framesize must be a valid number\n")
1643                 sys.exit(2)
1644             #Make sure that conditions for maxData are met:
1645             #( >= 16 and == n*16 and <= MAX_DATA_BYTES!)
1646             if maxData > BootStrapLoader.MAX_DATA_BYTES:
1647                 maxData = BootStrapLoader.MAX_DATA_BYTES
1648             elif maxData < 16:
1649                 maxData = 16
1650             bsl.maxData = maxData - (maxData % 16)
1651             sys.stderr.write( "Max. number of data bytes within one frame set to %i.\n" % maxData)
1652         elif o in ("-m", "--erasecycles"):
1653             try:
1654                 meraseCycles = int(a)               #try to convert decimal
1655             except ValueError:
1656                 sys.stderr.write("erasecycles must be a valid number\n")
1657                 sys.exit(2)
1658             #sanity check of value
1659             if meraseCycles < 1:
1660                 sys.stderr.write("erasecycles must be a positive number\n")
1661                 sys.exit(2)
1662             if meraseCycles > 20:
1663                 sys.stderr.write("warning: erasecycles set to a large number (>20): %d\n" % meraseCycles)
1664             sys.stderr.write( "Number of mass erase cycles set to %i.\n" % meraseCycles)
1665             bsl.meraseCycles = meraseCycles
1666         elif o in ("-e", "--masserase"):
1667             deviceinit.append(bsl.actionMassErase)        #Erase Flash
1668         elif o in ("-E", "--erasecheck"):
1669             deviceinit.append(bsl.actionEraseCheck)       #Erase Check (by file)
1670         elif o in ("-p", "--program"):
1671             todo.append(bsl.actionProgram)          #Program file
1672         elif o in ("--fromweb"):
1673             deviceinit.append(bsl.actionMassErase)        #Erase Flash
1674             todo.append(bsl.actionFromweb)          #Program GoodFET code
1675         elif o in ("-v", "--verify"):
1676             todo.append(bsl.actionVerify)           #Verify file
1677         elif o in ("-r", "--reset"):
1678             reset = 1
1679         elif o in ("-g", "--go"):
1680             try:
1681                 goaddr = int(a)                    #try to convert decimal
1682             except ValueError:
1683                 try:
1684                     goaddr = int(a[2:],16)         #try to convert hex
1685                 except ValueError:
1686                     sys.stderr.write("go address must be a valid number\n")
1687                     sys.exit(2)
1688             wait = 1
1689         elif o in ("-U", "--unpatched"):
1690             unpatched = 1
1691         elif o in ("-D", "--debug"):
1692             DEBUG = DEBUG + 1
1693         elif o in ("-u", "--upload"):
1694             try:
1695                 startaddr = int(a)                  #try to convert decimal
1696             except ValueError:
1697                 try:
1698                     startaddr = int(a,16)           #try to convert hex
1699                 except ValueError:
1700                     sys.stderr.write("upload address must be a valid number\n")
1701                     sys.exit(2)
1702         elif o in ("-s", "--size"):
1703             try:
1704                 size = int(a)
1705             except ValueError:
1706                 try:
1707                     size = int(a,16)
1708                 except ValueError:
1709                     sys.stderr.write("size must be a valid number\n")
1710                     sys.exit(2)
1711         elif o in ("-x", "--hex"):
1712             hexoutput = 1
1713         elif o in ("-b", "--bin"):
1714             hexoutput = 0
1715         elif o in ("-I", "--intelhex"):
1716             filetype = 0
1717         elif o in ("-T", "--titext"):
1718             filetype = 1
1719         elif o in ("-N", "--notimeout"):
1720             notimeout = 1
1721         elif o in ("-B", "--bsl"):
1722             bslrepl = Memory() #File to program
1723             bslrepl.loadFile(a)
1724         elif o in ("-V", "--bslversion"):
1725             todo.append(bsl.actionReadBSLVersion) #load replacement BSL as first item
1726         elif o in ("-S", "--speed"):
1727             try:
1728                 speed = int(a)                    #try to convert decimal
1729             except ValueError:
1730                 sys.stderr.write("speed must be decimal number\n")
1731                 sys.exit(2)
1732         elif o in ("-1", "--f1x"):
1733             bsl.cpu = F1x
1734         elif o in ("-2", "--f2x"):
1735             bsl.cpu = F2x
1736         elif o in ("-4", "--f4x"):
1737             bsl.cpu = F4x
1738         elif o in ("--invert-reset", ):
1739             bsl.invertRST = 1
1740         elif o in ("--invert-test", ):
1741             bsl.invertTEST = 1
1742         elif o in ("--swap-reset-test", ):
1743             bsl.swapRSTTEST = 1
1744         elif o in ("--telos-latch", ):
1745             bsl.telosLatch = 1
1746         elif o in ("--telos-i2c", ):
1747             bsl.telosI2C = 1
1748         elif o in ("--telos", ):
1749             bsl.invertRST = 1
1750             bsl.invertTEST = 1
1751             bsl.swapRSTTEST = 1
1752             bsl.telosLatch = 1
1753         elif o in ("--goodfet10", ):
1754             bsl.invertRST = 1
1755             bsl.invertTEST = 1
1756         elif o in ("--goodfet20", ):
1757             bsl.invertRST = 1
1758             bsl.invertTEST = 1
1759         elif o in ("--goodfet30", "--goodfet31", "--goodthopter" ):
1760             bsl.invertRST = 1
1761             bsl.invertTEST = 0
1762         elif o in ("--goodfet40", ):
1763             bsl.invertRST = 1
1764             bsl.invertTEST = 1
1765         elif o in ("--goodfet", ):
1766             bsl.invertRST = 1
1767             bsl.invertTEST = 1
1768         elif o in ("--apimote",):
1769             bsl.swapRSTTEST = 1;
1770         elif o in ("--nhbadge", "--nhbadgeb" ):
1771             bsl.invertRST = 1
1772             bsl.invertTEST = 1
1773         elif o in ("--telosb", ):
1774             bsl.swapRSTTEST = 1
1775             bsl.telosI2C = 1
1776             mayuseBSL = 0
1777             speed = 38400
1778         elif o in ("--tmote", ):
1779             bsl.swapRSTTEST = 1
1780             bsl.telosI2C = 1
1781             mayuseBSL = 0
1782             speed = 38400
1783         elif o in ("--z1", ):
1784             bsl.z1 = 1
1785             speed = 38400
1786         elif o in ("--no-BSL-download", ):
1787             mayuseBSL = 0
1788         elif o in ("--force-BSL-download", ):
1789             forceBSL = 1
1790         elif o in ("--slow", ):
1791             bsl.slowmode = 1
1792
1793     if len(args) == 0:
1794         sys.stderr.write("Use -h for help\n");
1795         sys.stderr.write("Use --fromweb to upgrade a GoodFET.\n")
1796     elif len(args) == 1:                            #a filename is given
1797         if not todo:                                #if there are no actions yet
1798             todo.extend([                           #add some useful actions...
1799                 bsl.actionProgram,
1800                 bsl.actionVerify,
1801             ])
1802         filename = args[0]
1803     else:                                           #number of args is wrong
1804         usage()
1805         sys.exit(2)
1806
1807     if DEBUG:   #debug infos
1808         sys.stderr.write("Debug level set to %d\n" % DEBUG)
1809         sys.stderr.write("Python version: %s\n" % sys.version)
1810
1811     #sanity check of options
1812     if notimeout and goaddr is not None and startaddr is not None:
1813         sys.stderr.write("Option --notimeout can not be used together with both --upload and --go\n")
1814         sys.exit(1)
1815
1816     if notimeout:
1817         sys.stderr.write("Warning: option --notimeout can cause improper function in some cases!\n")
1818         bsl.timeout = 0
1819
1820     if goaddr and reset:
1821         sys.stderr.write("Warning: option --reset ignored as --go is specified!\n")
1822         reset = 0
1823
1824     if startaddr and reset:
1825         sys.stderr.write("Warning: option --reset ignored as --upload is specified!\n")
1826         reset = 0
1827
1828     sys.stderr.flush()
1829     
1830     #prepare data to download
1831     bsl.data = Memory()                             #prepare downloaded data
1832     if filetype is not None:                        #if the filetype is given...
1833         if filename is None:
1834             raise ValueError("no filename but filetype specified")
1835         if filename == '-':                         #get data from stdin
1836             file = sys.stdin
1837         else:
1838             file = open(filename, "rb")             #or from a file
1839         if filetype == 0:                           #select load function
1840             bsl.data.loadIHex(file)                 #intel hex
1841         elif filetype == 1:
1842             bsl.data.loadTIText(file)               #TI's format
1843         else:
1844             raise ValueError("illegal filetype specified")
1845     else:                                           #no filetype given...
1846         if filename == '-':                         #for stdin:
1847             bsl.data.loadIHex(sys.stdin)            #assume intel hex
1848         elif filename:
1849             bsl.data.loadFile(filename)             #autodetect otherwise
1850
1851     if DEBUG > 3: sys.stderr.write("File: %r" % filename)
1852
1853     bsl.comInit(comPort)                            #init port
1854
1855     if bsl.actionMassErase in deviceinit:
1856         bsl.actionStartBSL()
1857         bsl.saveinfo()
1858
1859     #initialization list
1860     if deviceinit:  #erase and erase check
1861         if DEBUG: sys.stderr.write("Preparing device ...\n")
1862         #bsl.actionStartBSL(usepatch=0, adjsp=0)     #no workarounds needed
1863         #if speed: bsl.actionChangeBaudrate(speed)   #change baud rate as fast as possible
1864         for f in deviceinit: f()
1865
1866     if todo or goaddr or startaddr:
1867         if DEBUG: sys.stderr.write("Actions ...\n")
1868         #connect to the BSL
1869         bsl.actionStartBSL(
1870             usepatch=not unpatched,
1871             replacementBSL=bslrepl,
1872             forceBSL=forceBSL,
1873             mayuseBSL=mayuseBSL,
1874             speed=speed,
1875         )
1876
1877     #work list
1878     if todo:
1879         if DEBUG > 0:       #debug
1880             #show a nice list of sheduled actions
1881             sys.stderr.write("TODO list:\n")
1882             for f in todo:
1883                 try:
1884                     sys.stderr.write("   %s\n" % f.func_name)
1885                 except AttributeError:
1886                     sys.stderr.write("   %r\n" % f)
1887         for f in todo: f()                          #work through todo list
1888
1889     if bsl.info is not None:
1890         sys.stderr.write('Programming info flash...\n')
1891         sys.stderr.flush()
1892         bsl.programData(bsl.info, bsl.ACTION_PROGRAM)
1893
1894     if reset:                                       #reset device first if desired
1895         bsl.actionReset()
1896     if dumpivt:
1897         bsl.txPasswd(); #default pass
1898         data=bsl.uploadData(0xc00,1024);
1899         hex="";
1900         for c in data:
1901             hex+=("%02x "%ord(c));
1902         print hex;
1903     if dumpinfo:
1904         # I don't know what bslreset is all about, but if it is enabled and
1905         # the wrong password is provided, the chip gets erased.
1906         reset = True
1907         if not bsl.passwd:
1908             reset = False
1909         bsl.actionStartBSL(bslreset=reset)
1910         bsl.dumpinfo()
1911     
1912     if goaddr is not None:                          #start user programm at specified address
1913         bsl.actionRun(goaddr)                       #load PC and execute
1914
1915     #upload datablock and output
1916     if startaddr is not None:
1917         if goaddr:                                  #if a program was started...
1918             #don't restart BSL but wait for the device to enter it itself
1919             sys.stderr.write("Waiting for device to reconnect for upload: ")
1920             sys.stderr.flush()
1921             bsl.txPasswd(bsl.passwd, wait=1)        #synchronize, try forever...
1922             data = bsl.uploadData(startaddr, size)  #upload data
1923         else:
1924             data = bsl.uploadData(startaddr, size)  #upload data
1925         if hexoutput:                               #depending on output format
1926             m = 0
1927             while m < len(data):                    #print a hex display
1928                 print hexify(startaddr+m, map(ord,data[m:m+16]))
1929                 m = m + 16
1930         else:
1931             sys.stdout.write(data)                  #binary output w/o newline!
1932         wait = 0    #wait makes no sense as after the upload the device is still in BSL
1933
1934     if wait:                                        #wait at the end if desired
1935         sys.stderr.write("Press <ENTER> ...\n")     #display a prompt
1936         sys.stderr.flush()
1937         raw_input()                                 #wait for newline
1938
1939     bsl.comDone()           #Release serial communication port
1940
1941 if __name__ == '__main__':
1942     try:
1943         main(1)
1944     except SystemExit:
1945         raise               #let pass exit() calls
1946     except KeyboardInterrupt:
1947         if DEBUG: raise     #show full trace in debug mode
1948         sys.stderr.write("user abort.\n")   #short messy in user mode
1949         sys.exit(1)         #set errorlevel for script usage
1950     except Exception, msg:  #every Exception is caught and displayed
1951         if DEBUG: raise     #show full trace in debug mode
1952         #sys.stderr.write("\nAn error occoured:\n%s\n" % msg) #short messy in user mode
1953         #sys.exit(1)         #set errorlevel for script usage
1954         main(0);