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