11
11
import serial
12
12
import array
13
13
import time
14
- from intelhex import IntelHex
14
+ # from intelhex import IntelHex
15
15
from Tkinter import *
16
16
from ttk import *
17
17
import tkFileDialog
28
28
## Programmer Hardware Adapters
29
29
########################################
30
30
class ProgrammerHardwareAdapter (object ):
31
- def __init__ (self ):
32
- pass
31
+ def __init__ (self , port ):
32
+ self .port = port
33
+ self .bus , self .portnum = [int (x ) for x in self .port [2 ].split ('=' )[- 1 ].split ('-' )]
33
34
34
35
@staticmethod
35
36
def canProgram (port ):
@@ -44,10 +45,18 @@ def checkPortStatus(self):
44
45
def exitBootloader (self ):
45
46
pass
46
47
48
+ def reset (self ):
49
+ try :
50
+ import usb
51
+ device = usb .core .find (custom_match = lambda d : d .bus == self .bus and d .port_number == self .portnum )
52
+ device .reset ()
53
+ except :
54
+ traceback .print_exc ()
55
+
47
56
48
57
class TinyFPGABSeries (ProgrammerHardwareAdapter ):
49
58
def __init__ (self , port ):
50
- self . port = port
59
+ super ( TinyFPGABSeries , self ). __init__ ( port )
51
60
52
61
@staticmethod
53
62
def canProgram (port ):
@@ -74,33 +83,34 @@ def program(self, filename, progress):
74
83
fpga .program_bitstream (addr , bitstream )
75
84
except :
76
85
program_failure = True
86
+ traceback .print_exc ()
87
+
77
88
78
89
79
90
def checkPortStatus (self , update_button_state ):
80
91
global serial_port_ready
81
- if not program_in_progress :
82
- try :
83
- with serial .Serial (self .port [0 ], 10000000 , timeout = 0.1 , writeTimeout = 0.1 ) as ser :
84
- fpga = TinyFPGAB (ser )
92
+ try :
93
+ with serial .Serial (self .port [0 ], 10000000 , timeout = 0.1 , writeTimeout = 0.1 ) as ser :
94
+ fpga = TinyFPGAB (ser )
85
95
86
- fpga .wake ()
87
- devid = fpga .read_id ()
96
+ fpga .wake ()
97
+ devid = fpga .read_id ()
88
98
89
- expected_devid = [0x1F , 0x84 , 0x01 ]
90
- if devid == expected_devid :
91
- com_port_status_sv .set ("Connected to TinyFPGA B2. Ready to program." )
92
- update_button_state (new_serial_port_ready = True , new_has_bootloader = True )
93
- else :
94
- com_port_status_sv .set ("Unable to communicate with TinyFPGA. Reconnect and reset TinyFPGA before programming." )
95
- update_button_state (new_serial_port_ready = False , new_has_bootloader = True )
99
+ expected_devid = [0x1F , 0x84 , 0x01 ]
100
+ if devid == expected_devid :
101
+ com_port_status_sv .set ("Connected to TinyFPGA B2. Ready to program." )
102
+ update_button_state (new_serial_port_ready = True , new_has_bootloader = True )
103
+ else :
104
+ com_port_status_sv .set ("Unable to communicate with TinyFPGA. Reconnect and reset TinyFPGA before programming." )
105
+ update_button_state (new_serial_port_ready = False , new_has_bootloader = True )
96
106
97
- except serial .SerialTimeoutException :
98
- com_port_status_sv .set ("Hmm...try pressing the reset button on TinyFPGA again." )
99
- update_button_state (new_serial_port_ready = False , new_has_bootloader = True )
107
+ except serial .SerialTimeoutException :
108
+ com_port_status_sv .set ("Hmm...try pressing the reset button on TinyFPGA again." )
109
+ update_button_state (new_serial_port_ready = False , new_has_bootloader = True )
100
110
101
- except :
102
- com_port_status_sv .set ("Bootloader not active. Press reset button on TinyFPGA before programming." )
103
- update_button_state (new_serial_port_ready = False , new_has_bootloader = True )
111
+ except :
112
+ com_port_status_sv .set ("Bootloader not active. Press reset button on TinyFPGA before programming." )
113
+ update_button_state (new_serial_port_ready = False , new_has_bootloader = True )
104
114
105
115
def exitBootloader (self ):
106
116
with serial .Serial (self .port [0 ], 10000000 , timeout = 0.1 , writeTimeout = 0.1 ) as ser :
@@ -114,7 +124,7 @@ def exitBootloader(self):
114
124
115
125
class TinyFPGAASeries (ProgrammerHardwareAdapter ):
116
126
def __init__ (self , port ):
117
- self . port = port
127
+ super ( TinyFPGAASeries , self ). __init__ ( port )
118
128
119
129
@staticmethod
120
130
def canProgram (port ):
@@ -126,8 +136,8 @@ def displayName(self):
126
136
def program (self , filename , progress ):
127
137
global max_progress
128
138
129
- with serial .Serial (self .port [0 ], 12000000 , timeout = 2.0 , writeTimeout = 20 ) as ser :
130
- async_serial = tinyfpgaa .AsyncSerial (ser )
139
+ with serial .Serial (self .port [0 ], 12000000 , timeout = 10 , writeTimeout = 5 ) as ser :
140
+ async_serial = tinyfpgaa .SyncSerial (ser )
131
141
pins = tinyfpgaa .JtagTinyFpgaProgrammer (async_serial )
132
142
jtag = tinyfpgaa .Jtag (pins )
133
143
programmer = tinyfpgaa .JtagCustomProgrammer (jtag )
@@ -137,17 +147,18 @@ def program(self, filename, progress):
137
147
138
148
max_progress = jedec_file .numRows () * 3
139
149
140
- programmer .program (jedec_file , progress )
141
-
142
-
143
150
try :
144
- fpga .program_bitstream (addr , bitstream )
151
+ programmer .program (jedec_file , progress )
152
+
145
153
except :
146
154
program_failure = True
155
+ self .reset ()
156
+ traceback .print_exc ()
157
+
147
158
148
159
def checkPortStatus (self , update_button_state ):
149
160
with serial .Serial (self .port [0 ], 12000000 , timeout = .5 , writeTimeout = 0.1 ) as ser :
150
- async_serial = tinyfpgaa .AsyncSerial (ser )
161
+ async_serial = tinyfpgaa .SyncSerial (ser )
151
162
pins = tinyfpgaa .JtagTinyFpgaProgrammer (async_serial )
152
163
jtag = tinyfpgaa .Jtag (pins )
153
164
programmer = tinyfpgaa .JtagCustomProgrammer (jtag )
@@ -186,6 +197,8 @@ def exitBootloader(self):
186
197
################################################################################
187
198
################################################################################
188
199
200
+ communication_lock = threading .Lock ()
201
+
189
202
r = Tk ()
190
203
r .title ("TinyFPGA Programmer" )
191
204
r .resizable (width = False , height = False )
@@ -199,8 +212,9 @@ def exitBootloader(self):
199
212
200
213
program_status_sv = StringVar (r )
201
214
202
- serial_port_ready = False ;
203
- bitstream_file_ready = False ;
215
+ serial_port_ready = False
216
+ bitstream_file_ready = False
217
+ has_bootloader = False
204
218
file_mtime = 0
205
219
206
220
def update_button_state (new_serial_port_ready = None , new_has_bootloader = None ):
@@ -260,8 +274,8 @@ def update_serial_port_list_task():
260
274
global tinyfpga_adapters
261
275
262
276
if not program_in_progress :
263
- tinyfpga_adapters = dict ((adapter .displayName (), adapter ) for adapter in [getProgrammerHardwareAdapter (port ) for port in comports ()] if adapter is not None )
264
- new_tinyfpga_ports = [key for key , value in tinyfpga_adapters .iteritems ()]
277
+ new_tinyfpga_adapters = dict ((adapter .displayName (), adapter ) for adapter in [getProgrammerHardwareAdapter (port ) for port in comports ()] if adapter is not None )
278
+ new_tinyfpga_ports = [key for key , value in new_tinyfpga_adapters .iteritems ()]
265
279
266
280
if new_tinyfpga_ports != tinyfpga_ports :
267
281
if com_port_sv .get () == "" and len (new_tinyfpga_ports ) > 0 :
@@ -273,25 +287,34 @@ def update_serial_port_list_task():
273
287
label = string ,
274
288
command = lambda value = string : com_port_sv .set (value ))
275
289
tinyfpga_ports = new_tinyfpga_ports
290
+ tinyfpga_adapters = new_tinyfpga_adapters
276
291
277
292
r .after (1000 , update_serial_port_list_task )
278
293
279
294
update_serial_port_list_task ()
280
295
281
296
def check_port_status_task ():
282
- if not program_in_progress :
297
+ global adapter
298
+ if communication_lock .acquire (False ):
283
299
try :
284
300
adapter = tinyfpga_adapters [com_port_sv .get ()]
285
301
adapter .checkPortStatus (update_button_state )
286
302
except :
287
303
com_port_status_sv .set ("Unable to communicate with TinyFPGA. Reset your TinyFPGA and check your connections." )
288
304
update_button_state (new_serial_port_ready = False )
305
+ traceback .print_exc ()
306
+ try :
307
+ adapter .reset ()
308
+ except :
309
+ pass
310
+ finally :
311
+ communication_lock .release ()
289
312
290
-
291
- r .after (500 , check_port_status_task )
313
+ r .after (100 , check_port_status_task )
292
314
293
315
294
316
check_port_status_task ()
317
+ #update_button_state(new_serial_port_ready = True)
295
318
296
319
297
320
########################################
@@ -365,37 +388,39 @@ def check_bitstream_file_status_cb(*args):
365
388
program_progress_pb .grid (column = 1 , row = 2 , sticky = W + E , padx = 10 , pady = 8 )
366
389
367
390
def program_fpga_thread ():
368
- global program_in_progress
369
- global program_failure
370
- program_failure = False
371
-
372
- try :
373
- global current_progress
374
- global max_progress
375
- global progress_lock
376
- with progress_lock :
377
- current_progress = 0
391
+ with communication_lock :
392
+ global program_failure
393
+ global program_in_progress
394
+ program_failure = False
378
395
379
- def progress (v ):
396
+ try :
397
+ global current_progress
398
+ global max_progress
380
399
global progress_lock
381
400
with progress_lock :
382
- if isinstance (v , int ) or isinstance (v , long ):
383
- global current_progress
384
- current_progress += v
385
- elif isinstance (v , str ):
386
- program_status_sv .set (v )
401
+ current_progress = 0
387
402
388
- adapter = tinyfpga_adapters [com_port_sv .get ()]
389
- adapter .program (filename_sv .get (), progress )
403
+ def progress (v ):
404
+ global progress_lock
405
+ with progress_lock :
406
+ if isinstance (v , int ) or isinstance (v , long ):
407
+ global current_progress
408
+ current_progress += v
409
+ elif isinstance (v , str ):
410
+ program_status_sv .set (v )
390
411
391
- program_in_progress = False
412
+ adapter = tinyfpga_adapters [com_port_sv .get ()]
413
+ adapter .program (filename_sv .get (), progress )
392
414
393
- except :
394
- program_failure = True
395
- traceback .print_exc ()
396
415
397
- finally :
398
- program_in_progress = False
416
+ except :
417
+ program_failure = True
418
+ traceback .print_exc ()
419
+
420
+ finally :
421
+ program_in_progress = False
422
+ pass
423
+
399
424
400
425
current_progress = 0
401
426
max_progress = 0
@@ -406,11 +431,17 @@ def update_progress_task():
406
431
global max_progress
407
432
global progress_lock
408
433
409
- with progress_lock :
410
- if isinstance (current_progress , (int , long )):
411
- program_progress_pb ["value" ] = current_progress
412
- program_progress_pb ["maximum" ] = max_progress
413
- r .after (10 , update_progress_task )
434
+ if progress_lock .acquire (False ):
435
+ try :
436
+ if isinstance (current_progress , (int , long )):
437
+ program_progress_pb ["value" ] = current_progress
438
+ program_progress_pb ["maximum" ] = max_progress
439
+ except :
440
+ traceback .print_exc ()
441
+ finally :
442
+ progress_lock .release ()
443
+
444
+ r .after (100 , update_progress_task )
414
445
415
446
update_progress_task ()
416
447
@@ -426,7 +457,9 @@ def program_fpga_cmd():
426
457
427
458
def program_failure_task ():
428
459
global program_failure
460
+ global adapter
429
461
if program_failure :
462
+ adapter .reset ()
430
463
program_status_sv .set ("Programming failed! Reset TinyFPGA and try again." )
431
464
program_failure = False
432
465
0 commit comments