From 68d19f7b88784e901af2efb434e5eca9325de58f Mon Sep 17 00:00:00 2001 From: Grigori Goronzy Date: Tue, 10 Oct 2017 22:11:07 +0200 Subject: [PATCH 1/2] Use calculated delays Some serial drivers don't handle draining the transmit buffer correctly. This has been handled with a long delay so far, which might be problematic. There's a race condition with some protocol versions. Until STC15, the baud rate switch is initiated with a command sent by stcgal, which is replied to by the MCU with the new baud rate. So the switch of the baud rate has to be done after the command has finished transmission, but before the MCU has started to transmit the response. This change calculates the minimum delay needed (with some tolerance added) so that it's unlikely that the baud rate switch will happen too late. --- stcgal/protocols.py | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/stcgal/protocols.py b/stcgal/protocols.py index 31b88f9..07eebad 100644 --- a/stcgal/protocols.py +++ b/stcgal/protocols.py @@ -238,6 +238,20 @@ class StcBaseProtocol: return iap_wait + def delay_safely_written(self, length): + """ + Delay until data has been safely written and sent to device. + Some buggy serial drivers don't implement tcdrain/flush correctly. + That is, they wait until all data has been written to USB, but they + do not wait until the data has actually finished transmission. + Add additional delay to work around. + """ + + bit_time = 1.0 / self.ser.baudrate + byte_time = bit_time * 11.0 # start, 8 data bits, stop, parity + clock_safety_factor = 1.05 # additional delay in case clock is slow + time.sleep(byte_time * length * clock_safety_factor) + def set_option(self, name, value): self.options.set_option(name, value) @@ -448,7 +462,7 @@ class Stc89Protocol(StcBaseProtocol): packet += struct.pack(">H", brt) packet += bytes([0xff - (brt >> 8), brt_csum, delay, iap]) self.write_packet(packet) - time.sleep(0.2) + self.delay_safely_written(len(packet)) self.ser.baudrate = self.baud_transfer response = self.read_packet() self.ser.baudrate = self.baud_handshake @@ -462,7 +476,7 @@ class Stc89Protocol(StcBaseProtocol): packet += struct.pack(">H", brt) packet += bytes([0xff - (brt >> 8), brt_csum, delay]) self.write_packet(packet) - time.sleep(0.2) + self.delay_safely_written(len(packet)) self.ser.baudrate = self.baud_transfer response = self.read_packet() if response[0] != 0x8e: @@ -638,7 +652,7 @@ class Stc12AProtocol(Stc12AOptionsMixIn, Stc89Protocol): sys.stdout.flush() packet = bytes([0x8f, 0xc0, brt, 0x3f, brt_csum, delay, iap]) self.write_packet(packet) - time.sleep(0.2) + self.delay_safely_written(len(packet)) self.ser.baudrate = self.baud_transfer response = self.read_packet() self.ser.baudrate = self.baud_handshake @@ -650,7 +664,7 @@ class Stc12AProtocol(Stc12AOptionsMixIn, Stc89Protocol): sys.stdout.flush() packet = bytes([0x8e, 0xc0, brt, 0x3f, brt_csum, delay]) self.write_packet(packet) - time.sleep(0.2) + self.delay_safely_written(len(packet)) self.ser.baudrate = self.baud_transfer response = self.read_packet() if response[0] != 0x8e: @@ -835,7 +849,7 @@ class Stc12BaseProtocol(StcBaseProtocol): sys.stdout.flush() packet = bytes([0x8f, 0xc0, brt, 0x3f, brt_csum, delay, iap]) self.write_packet(packet) - time.sleep(0.2) + self.delay_safely_written(len(packet)) self.ser.baudrate = self.baud_transfer response = self.read_packet() self.ser.baudrate = self.baud_handshake @@ -847,7 +861,7 @@ class Stc12BaseProtocol(StcBaseProtocol): sys.stdout.flush() packet = bytes([0x8e, 0xc0, brt, 0x3f, brt_csum, delay]) self.write_packet(packet) - time.sleep(0.2) + self.delay_safely_written(len(packet)) self.ser.baudrate = self.baud_transfer response = self.read_packet() if response[0] != 0x84: @@ -1121,7 +1135,7 @@ class Stc15AProtocol(Stc12Protocol): packet += struct.pack(">B", 230400 // self.baud_transfer) packet += bytes([0xa1, 0x64, 0xb8, 0x00, iap_wait, 0x20, 0xff, 0x00]) self.write_packet(packet) - time.sleep(0.2) + self.delay_safely_written(len(packet)) self.ser.baudrate = self.baud_transfer response = self.read_packet() if response[0] != 0x84: @@ -1307,7 +1321,6 @@ class Stc15Protocol(Stc15AProtocol): response = self.read_packet() if response[0] != 0x01: raise StcProtocolException("incorrect magic in handshake packet") - time.sleep(0.2) self.ser.baudrate = self.baud_transfer def switch_baud_ext(self): @@ -1324,7 +1337,6 @@ class Stc15Protocol(Stc15AProtocol): response = self.read_packet() if response[0] != 0x01: raise StcProtocolException("incorrect magic in handshake packet") - time.sleep(0.2) self.ser.baudrate = self.baud_transfer # for switching back to RC, program factory values From a414bfb864b0a97fe3bdb3ab243358fc289509f9 Mon Sep 17 00:00:00 2001 From: Andrew 'ncrmnt' Andrianov Date: Sat, 14 Oct 2017 21:08:26 +0300 Subject: [PATCH 2/2] protocols.py: Increase clock_safety_factor to 2.5 This fixes cp2102 and ch341a baudswitch on mac sierra Signed-off-by: Andrew 'ncrmnt' Andrianov --- stcgal/protocols.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stcgal/protocols.py b/stcgal/protocols.py index 07eebad..f22c660 100644 --- a/stcgal/protocols.py +++ b/stcgal/protocols.py @@ -249,7 +249,7 @@ class StcBaseProtocol: bit_time = 1.0 / self.ser.baudrate byte_time = bit_time * 11.0 # start, 8 data bits, stop, parity - clock_safety_factor = 1.05 # additional delay in case clock is slow + clock_safety_factor = 2.5 # additional delay in case clock is slow time.sleep(byte_time * length * clock_safety_factor) def set_option(self, name, value):