From 513a799a394176ecb9aebb546c8a6baa6009f946 Mon Sep 17 00:00:00 2001 From: David Lattimore Date: Thu, 3 Dec 2020 13:28:49 +1100 Subject: [PATCH 1/3] lxterm: Don't attempt to recover from CRC errors during upload. This allows transfers to proceed at the full speed of the serial link. We still check all responses, but will now fail outright if a CRC error occurs. --- litex/tools/litex_term.py | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/litex/tools/litex_term.py b/litex/tools/litex_term.py index 4999cdd55..25e28b6a8 100755 --- a/litex/tools/litex_term.py +++ b/litex/tools/litex_term.py @@ -203,6 +203,19 @@ class LiteXTerm: retry = 0 return 1 + def receive_upload_response(self): + # If we're not doing CRC checking, then there's no response to read. + if self.no_crc: + return + reply = self.port.read() + if reply == sfl_ack_success: + return + elif reply == sfl_ack_crcerror: + print("[LXTERM] Upload to device failed due to data corruption (CRC error)") + else: + print(f"[LXTERM] Got unexpected response from device '{reply}'") + sys.exit(1) + def upload(self, filename, address): f = open(filename, "rb") f.seek(0, 2) @@ -214,6 +227,7 @@ class LiteXTerm: position = 0 start = time.time() remaining = length + outstanding = 0 while remaining: sys.stdout.write("|{}>{}| {}%\r".format('=' * (20*position//length), ' ' * (20-20*position//length), @@ -227,12 +241,17 @@ class LiteXTerm: frame.cmd = sfl_cmd_load if not self.no_crc else sfl_cmd_load_no_crc frame.payload = current_address.to_bytes(4, "big") frame.payload += frame_data - if self.send_frame(frame) == 0: - return + self.port.write(frame.encode()) + outstanding += 1 + if self.port.in_waiting: + self.receive_upload_response() + outstanding -= 1 current_address += len(frame_data) position += len(frame_data) remaining -= len(frame_data) time.sleep(1e-5) # Inter-frame delay for fast UARTs (ex: FT245). + for _ in range(outstanding): + self.receive_upload_response() end = time.time() elapsed = end - start f.close() From 03c2257baf3cbc21734e3439607e6c58776e925e Mon Sep 17 00:00:00 2001 From: David Lattimore Date: Thu, 3 Dec 2020 13:35:14 +1100 Subject: [PATCH 2/3] lxterm: Deprecate --no-crc flag The flag is left, in case people are using it from scripts, but now does nothing besides printing a warning. --- litex/tools/litex_term.py | 32 +++++++++++++------------------- 1 file changed, 13 insertions(+), 19 deletions(-) diff --git a/litex/tools/litex_term.py b/litex/tools/litex_term.py index 25e28b6a8..2d025c7bc 100755 --- a/litex/tools/litex_term.py +++ b/litex/tools/litex_term.py @@ -63,7 +63,6 @@ sfl_payload_length = 64 # General commands sfl_cmd_abort = b"\x00" sfl_cmd_load = b"\x01" -sfl_cmd_load_no_crc = b"\x03" sfl_cmd_jump = b"\x02" sfl_cmd_flash = b"\x04" sfl_cmd_reboot = b"\x05" @@ -137,7 +136,7 @@ def crc16(l): # LiteXTerm ---------------------------------------------------------------------------------------- class LiteXTerm: - def __init__(self, serial_boot, kernel_image, kernel_address, json_images, no_crc, flash): + def __init__(self, serial_boot, kernel_image, kernel_address, json_images, flash): self.serial_boot = serial_boot assert not (kernel_image is not None and json_images is not None) self.mem_regions = {} @@ -149,7 +148,6 @@ class LiteXTerm: self.mem_regions.update(json.load(f)) self.boot_address = self.mem_regions[list(self.mem_regions.keys())[-1]] f.close() - self.no_crc = no_crc self.flash = flash self.reader_alive = False @@ -189,24 +187,18 @@ class LiteXTerm: retry = 1 while retry: self.port.write(frame.encode()) - if not self.no_crc: - # Get the reply from the device - reply = self.port.read() - if reply == sfl_ack_success: - retry = 0 - elif reply == sfl_ack_crcerror: - retry = 1 - else: - print("[LXTERM] Got unknown reply '{}' from the device, aborting.".format(reply)) - return 0 - else: + # Get the reply from the device + reply = self.port.read() + if reply == sfl_ack_success: retry = 0 + elif reply == sfl_ack_crcerror: + retry = 1 + else: + print("[LXTERM] Got unknown reply '{}' from the device, aborting.".format(reply)) + return 0 return 1 def receive_upload_response(self): - # If we're not doing CRC checking, then there's no response to read. - if self.no_crc: - return reply = self.port.read() if reply == sfl_ack_success: return @@ -238,7 +230,7 @@ class LiteXTerm: if self.flash: frame.cmd = sfl_cmd_flash else: - frame.cmd = sfl_cmd_load if not self.no_crc else sfl_cmd_load_no_crc + frame.cmd = sfl_cmd_load frame.payload = current_address.to_bytes(4, "big") frame.payload += frame_data self.port.write(frame.encode()) @@ -384,7 +376,9 @@ def _get_args(): def main(): args = _get_args() - term = LiteXTerm(args.serial_boot, args.kernel, args.kernel_adr, args.images, args.no_crc, args.flash) + if args.no_crc: + print("[LXTERM] --no-crc is deprecated and now does nothing (CRC checking is now fast)") + term = LiteXTerm(args.serial_boot, args.kernel, args.kernel_adr, args.images, args.flash) term.open(args.port, int(float(args.speed))) term.console.configure() term.start() From b421d50b4054fcd677c6bc82616d68d1127cb9dc Mon Sep 17 00:00:00 2001 From: David Lattimore Date: Thu, 3 Dec 2020 13:38:05 +1100 Subject: [PATCH 3/3] lxterm: Increase maximum payload size to match BIOS sfl_frame (in sfl.h) already had a payload size of 255. This should give about a 10% speed gain due to reduced overhead. 8 bytes of header per 251 bytes sent, as opposed to 8 bytes of header per 60 bytes sent --- litex/tools/litex_term.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/litex/tools/litex_term.py b/litex/tools/litex_term.py index 2d025c7bc..c521c0f4e 100755 --- a/litex/tools/litex_term.py +++ b/litex/tools/litex_term.py @@ -58,7 +58,7 @@ sfl_prompt_ack = b"\x06" sfl_magic_req = b"sL5DdSMmkekro\n" sfl_magic_ack = b"z6IHG7cYDID6o\n" -sfl_payload_length = 64 +sfl_payload_length = 255 # General commands sfl_cmd_abort = b"\x00"