使用pySerial无法中断U-Boot的"Hit any key to stop autoboot:"提示
问题
我有一个用于iMX6设备执行Linux更新的Python脚本,可通过串口连接重启Linux,且能正常接收设备重启的控制台输出。但当串口输出中出现U-Boot的Hit any key to stop autoboot:提示时,脚本发送的写入命令似乎被忽略。
脚本代码
import time import serial def reboot_and_update(port, baudrate=115200): # Open the serial connection ser = serial.Serial(port, baudrate, timeout=1, bytesize=serial.EIGHTBITS, xonxoff=True, parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_ONE) print(f"Connected to {port} at {baudrate} baud. Output:") ser.write(b"reboot\r") # Send the command try: while True: # Read a line from the serial port line = ser.readline().decode('utf-8').strip() if line: # Print the received line to the console print(f"{line}") # Check for the specific line to trigger actions if "Hit any key to stop autoboot:" in line: print("Interrupt autoboot...") time.sleep(0.1) ser.write(b"345ju\r") time.sleep(1) ser.write(b"run install_linux_fw_sd\r") # Send the command # Check for the login prompt and wait 3 seconds elif "ccimx6ulsbc login:" in line: print("Login prompt detected. Waiting for 3 seconds.") time.sleep(3) # If nothing else happens, close the connection additional_line = ser.readline().decode('utf-8').strip() if not additional_line: break else: # Print any additional lines received during the wait period print(f"Received after login prompt: {additional_line}") else: time.sleep(0.1) # Small delay to prevent busy waiting finally: ser.close() print("Finished")
脚本运行输出
(py312) C:\...>python serialconn.py Connected to COM5 at 115200 baud. Output: reboot Broadcast message from root@ccimx6ulsbc (ttymxc4) (Fri Mar 9 14:41:36 2018): The system is going down for reboot NOW! INIT: Switching to runlevel: 6 INIT: Sending processes configured via /etc/inittab the TERM signal root@ccimx6ulsbc:~# Stopping syslogd/klogd: stopped syslogd (pid 639) stopped klogd (pid 642) done Stopping Dropbear SSH server: stopped /usr/sbin/dropbear (pid 661) dropbear. Stopping bluetooth: bluetoothd. Stopping Busybox ACPI daemon: done stopping Busybox HTTP Daemon: httpd... no httpd found; none killed Stopping Busybox NTP client/server: done Stopping system message bus: dbus. ModemManager[739]: <warn> could not acquire the 'org.freedesktop.ModemManager1' service name ModemManager[739]: <info> ModemManager is shut down Stopping HOSTAP Daemon: hostapd. Stopping tcf-agent: OK ALSA: Storing mixer settings... Unmounting remote filesystems... Deconfiguring network interfaces... done. Stopping NetworkManager: done Stopping vsftpd server: done Sending all processes the TERM signal... Sending all processes the KILL signal... Deactivating swap... Unmounting local filesystems... Rebooting... U-Boot dub-2020.04-r7.1+gaf77921f51 (Jan 30 2024 - 12:53:20 +0000) CPU: i.MX6UL rev1.2 528 MHz (running at 396 MHz) CPU: Industrial temperature grade (-40C to 105C) at 68C Reset cause: POR DRAM: 1 GiB MCA: HW_VER=1 FW_VER=1.14 PMIC: PFUZE3000 DEV_ID=0x30 REV_ID=0x11 NAND: 1024 MiB MMC: FSL_SDHC: 0 In: serial Out: serial Err: serial Model: Digi International ConnectCore 6UL SBC. ConnectCore 6UL SOM variant 0x04: Industrial Ultralite 528MHz, 1GB NAND, 1GB DDR3, -40/+85C, Wireless, Bluetooth Board version undefined, ID undefined Boot device: NAND Net: FEC0 [PRIME] Fastboot: Normal Normal Boot Hit any key to stop autoboot: 0 Interrupt autoboot... ubi0: attaching mtd4 ubi0: scanning is finished ubi0: attached mtd4 (name "linux", size 24 MiB) ubi0: PEB size: 131072 bytes (128 KiB), LEB size: 126976 bytes ubi0: min./max. I/O unit sizes: 2048/2048, sub-page size 2048 ubi0: VID header offset: 2048 (aligned 2048), data offset: 4096 ubi0: good PEBs: 192, bad PEBs: 0, corrupted PEBs: 0 ubi0: user volume: 1, internal volumes: 1, max. volumes count: 128 ubi0: max/mean erase counter: 15/11, WL threshold: 4096, image sequence number: 0 ubi0: available PEBs: 0, total reserved PEBs: 192, PEBs reserved for bad PEB handling: 8 Loading file 'boot.scr' to addr 0x80800000... Done ## Executing script at 80800000 ## Loading kernel: zImage-ccimx6ulsbc.bin
可见启动过程中的任何输入都被忽略。已尝试用PuTTY执行相同操作,可正常中断U-Boot自动启动,且已将PuTTY的连接设置复制到脚本中(即使关闭xonxoff也无效)。
解决思路与方案
1. 修正串口参数,禁用流控
U-Boot默认不支持软件流控(xonxoff),且多数串口设备在U-Boot阶段也不会启用硬件流控,需明确禁用这两项:
ser = serial.Serial(port, baudrate, timeout=0.5, bytesize=serial.EIGHTBITS, xonxoff=False, rtscts=False, parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_ONE)
2. 优化中断时机与输入内容
- 脚本检测到
Hit any key to stop autoboot:时,倒计时可能已接近结束,需立即发送中断字符,无需等待0.1秒 - U-Boot只需要任意一个字符即可中断自动启动,无需发送长字符串,用单个空格或回车更可靠
- 发送前清空接收缓冲区,避免残留数据干扰检测
3. 等待U-Boot提示符后再发送更新命令
不要用固定sleep,而是等待U-Boot的命令提示符(通常是=>),确认进入U-Boot命令行后再发送run命令,避免发送时机过早。
修改后的完整脚本
import time import serial def reboot_and_update(port, baudrate=115200): # Open serial connection with correct flow control settings ser = serial.Serial(port, baudrate, timeout=0.5, bytesize=serial.EIGHTBITS, xonxoff=False, rtscts=False, parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_ONE) print(f"Connected to {port} at {baudrate} baud. Output:") # Send reboot command ser.write(b"reboot\r") time.sleep(0.2) ser.flushInput() # Clear initial buffer try: uboot_prompt_detected = False while True: # Read available data instead of line-by-line to avoid missing partial output data = ser.read(1024) if data: line = data.decode('utf-8', errors='ignore').strip() if line: print(line) # Detect autoboot prompt and send interrupt immediately if "Hit any key to stop autoboot:" in line: print("Interrupt autoboot...") ser.flushInput() # Clear buffer before sending ser.write(b"\r") # Send single carriage return to interrupt ser.flush() # Ensure data is sent immediately # Detect U-Boot command prompt if "=>" in line: uboot_prompt_detected = True print("Entered U-Boot command line, sending update command...") ser.write(b"run install_linux_fw_sd\r") ser.flush() # Exit on login prompt if "ccimx6ulsbc login:" in line: print("Login prompt detected, exiting...") break else: time.sleep(0.05) # Shorter delay for faster response # Exit if we've sent the update command and waited enough if uboot_prompt_detected: time.sleep(5) # Wait for update to start break finally: ser.close() print("Finished")
额外调试建议
- 用
ser.write_timeout = 1设置写入超时,确保发送操作不会挂起 - 尝试发送不同的中断字符,比如
b' '(空格),部分U-Boot版本对特定字符响应更稳定 - 开启串口调试日志(部分serial库版本支持
ser.debug = True),查看实际发送的字节
内容的提问来源于stack exchange,提问作者Markus Klingsiek
相关产品推荐
相关产品推荐

