You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 04:25:55