@@ -114,9 +114,20 @@ def __str__(self):
114114 return self .port_name
115115
116116 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+ #
117128 try :
118129 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__ ()
120131 except serial .SerialException as e :
121132 raise PortError ("Failed to open serial port:\n %s" % str (e ))
122133
@@ -514,17 +525,36 @@ def program_sectors(self, addr, data):
514525 minor_write_data = current_write_data [
515526 minor_offset :minor_offset + minor_sector_size ]
516527
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+
517549 # if the minor data is all 0xFF then it will match
518550 # 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 )
522557
523- self .write (
524- current_addr + minor_offset ,
525- minor_write_data ,
526- disable_progress = True ,
527- max_length = 256 )
528558 minor_read_data = self .read (
529559 current_addr + minor_offset ,
530560 len (minor_write_data ),
0 commit comments