This is an automated email from the ASF dual-hosted git repository. jiuzhudong pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx-apps.git
commit 2908f101549565c881b5ae422d66de7f1da3bbce Author: wangxingxing <[email protected]> AuthorDate: Mon Apr 14 17:42:59 2025 +0800 apps/system/ymodem: Optimized ymodem for burn during bootloader If device automatically enters the ymodem rb mode when it starts up, the PC tool does not need to send rb command anymore. Here, when a specified number of consecutive 'C' are received, the subsequent ymodem protocol content will continue. Signed-off-by: wangxingxing <[email protected]> --- system/ymodem/sbrb.py | 104 +++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 82 insertions(+), 22 deletions(-) diff --git a/system/ymodem/sbrb.py b/system/ymodem/sbrb.py index a5c90930f..8d93f1901 100755 --- a/system/ymodem/sbrb.py +++ b/system/ymodem/sbrb.py @@ -25,6 +25,7 @@ import io import os import sys import termios +import time import serial @@ -92,25 +93,31 @@ def ymodem_stdprogress(data): def ymodem_ser_read(size): - global fd_serial - data = fd_serial.read(size) return data def ymodem_ser_write(data): - global fd_serial fd_serial.write(data) fd_serial.flush() def ymodem_ser_clear(): - global fd_serial - fd_serial.reset_input_buffer() fd_serial.reset_output_buffer() +def ymodem_ser_recv_repeat_c(num, timeout): + except_data = b"C" * num + start_time = time.time() + + while time.time() - start_time < timeout: + read_data = ymodem_ser_read(num) + if read_data == except_data: + return 0 + return -1 + + def calc_crc16(data, crc=0): crctable = [ 0x0000, @@ -385,7 +392,7 @@ class ymodem: write=ymodem_stdwrite, progress=ymodem_stdprogress, clear=ymodem_stdclear, - timeout=100, + timeout=10, maxretry=RETRIESMAX, debug="", customsize=0, @@ -452,15 +459,30 @@ class ymodem: return PACKET_SIZE def recv_cmd(self, cmd): - chunk = self.read(1) - if chunk == NAK: - return -EAGAIN - if chunk != cmd: - self.debug("should be " + binascii.hexlify(cmd).decode("utf-8")) - self.debug("but receive " + binascii.hexlify(chunk).decode("utf-8") + "\n") - return -EINVAL - - return 0 + start_time = time.time() + unexpected_buffer = b"" + while time.time() - start_time < self.timeout: + chunk = self.read(1) + if chunk == cmd: + if unexpected_buffer: + # try to decode to UTF-8 + decoded = unexpected_buffer.decode("utf-8", errors="replace") + self.progress(f"Ignored unexpected text: {decoded}\n") + return 0 + elif chunk == NAK: + if unexpected_buffer: + decoded = unexpected_buffer.decode("utf-8", errors="replace") + self.progress(f"Ignored unexpected text: {decoded}\n") + print("EAGAIN!!!") + return -EAGAIN + elif chunk == b"": + continue + else: + unexpected_buffer += chunk + if unexpected_buffer: + decoded = unexpected_buffer.decode("utf-8", errors="replace") + self.progress(f"Ignored unexpected text: {decoded}\n") + return -EINVAL def send_handshake(self): self.write(CRC) @@ -686,7 +708,7 @@ class ymodem: return -1 self.progress("recv ret %d\n" % ret) - self.debug("recv frist packet\n") + self.debug("recv first packet\n") self.retries += 1 continue @@ -807,6 +829,29 @@ if __name__ == "__main__": help="This opthin set max retry for transmission", ) + parser.add_argument( + "-c", + "--countofc", + type=int, + default=0, + help=""" + When this value is greater than 0, it means that the rb command is not sent to + device, but to receive a specified number of consecutive 'C'. + If do not receive continuous 'C', time out and exit. + """, + ) + + parser.add_argument( + "-w", + "--waitctimeout", + type=int, + default=30, + help=""" + When the -c parameter is valid, this arg will determine whether it has timed out + while waiting for consecutive Cs. The unit is second. + """, + ) + parser.add_argument( "--debug", help="This opthin is save debug log on host", default="" ) @@ -821,19 +866,34 @@ if __name__ == "__main__": for i in args.recvfrom: recvfile += i + " " + if args.kblocksize: + recvfile += "-k %d " % (args.kblocksize) + fd_serial.write(("sb %s\r\n" % (recvfile)).encode()) fd_serial.flush() tmp = fd_serial.read(len(("sb %s\r\n" % (recvfile)).encode()) - 1) fd_serial.reset_input_buffer() else: - if args.sendto: - cmd = ("rb -f %s\r\n" % (args.sendto[0])).encode() + if args.countofc: + ret = ymodem_ser_recv_repeat_c(args.countofc, args.waitctimeout) + if ret < 0: + print("read C timeout") + fd_serial.close() + sys.exit(1) else: - cmd = ("rb\r\n").encode() + if args.sendto: + cmd = ("rb -f %s" % args.sendto[0]).encode() + else: + cmd = "rb".encode() - fd_serial.write(cmd) - fd_serial.flush() - fd_serial.read(len(cmd)) + if args.kblocksize: + cmd += (" -k %d" % args.kblocksize).encode() + + cmd += b"\r\n" + + fd_serial.write(cmd) + fd_serial.flush() + fd_serial.read(len(cmd)) fd_serial.reset_input_buffer() sbrb = ymodem(
