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