@@ -114,9 +114,20 @@ def __str__(self):
114
114
return self .port_name
115
115
116
116
def __enter__ (self ):
117
+ # Timeouts:
118
+ # - Read: 2.0 seconds (timeout)
119
+ # - Write: 5.0 seconds (writeTimeout)
120
+ #
121
+ # Rationale: hitting the writeTimeout is fatal, so it pays to be
122
+ # patient in case there is a brief delay; readTimeout is less
123
+ # fatal, but can result in short reads if it is hit, so we want
124
+ # a timeout high enough that is never hit normally. In practice
125
+ # 1.0 seconds is *usually* enough, so the chosen values are double
126
+ # and five times the "usually enough" values.
127
+ #
117
128
try :
118
129
self .ser = serial .Serial (
119
- self .port_name , timeout = 1 .0 , writeTimeout = 1 .0 ).__enter__ ()
130
+ self .port_name , timeout = 2 .0 , writeTimeout = 5 .0 ).__enter__ ()
120
131
except serial .SerialException as e :
121
132
raise PortError ("Failed to open serial port:\n %s" % str (e ))
122
133
@@ -514,17 +525,36 @@ def program_sectors(self, addr, data):
514
525
minor_write_data = current_write_data [
515
526
minor_offset :minor_offset + minor_sector_size ]
516
527
528
+ # The TinyFPGA firmware and/or flash chip does not handle
529
+ # partial minor sector writes properly, so pad out a final
530
+ # write of a partial to a whole minor sector, if we are
531
+ # writing aligned to the SPI flash internal minor sectors.
532
+ #
533
+ # Due to the way SPI flash works, writing 0xff *without
534
+ # erasing* should be a no-opt, because 0xff is what you
535
+ # get after erasing, and you can only write 0 bits.
536
+ current_minor_addr = current_addr + minor_offset
537
+
538
+ if (((current_minor_addr % minor_sector_size ) == 0 ) and
539
+ (len (minor_write_data ) < minor_sector_size )):
540
+ assert ((current_minor_addr % minor_sector_size ) == 0 )
541
+
542
+ pad_len = minor_sector_size - len (minor_write_data )
543
+ padding = b'\xff ' * pad_len
544
+
545
+ minor_write_data = bytearray (minor_write_data )
546
+ minor_write_data .extend (padding )
547
+ assert (len (minor_write_data ) == minor_sector_size )
548
+
517
549
# if the minor data is all 0xFF then it will match
518
550
# the erased bits and doesn't need to be re-sent
519
- if minor_write_data == chr (0xFF ) * len (minor_write_data ):
520
- pbar .update (len (minor_write_data ))
521
- continue ;
551
+ if minor_write_data != chr (0xFF ) * len (minor_write_data ):
552
+ self .write (
553
+ current_addr + minor_offset ,
554
+ minor_write_data ,
555
+ disable_progress = True ,
556
+ max_length = 256 )
522
557
523
- self .write (
524
- current_addr + minor_offset ,
525
- minor_write_data ,
526
- disable_progress = True ,
527
- max_length = 256 )
528
558
minor_read_data = self .read (
529
559
current_addr + minor_offset ,
530
560
len (minor_write_data ),
0 commit comments