You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by ji...@apache.org on 2026/02/02 03:00:27 UTC
(nuttx-apps) 02/02: apps/system/ymodem: Optimized ymodem for burn during bootloader
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 <wa...@xiaomi.com>
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 <wa...@xiaomi.com>
---
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(