如何解决JLinkExe自动化中弹窗导致脚本阻塞的问题?
问题描述
我使用JLinkExe烧录STM32固件,Windows/Powershell下启动命令:
& "C:\Program Files\SEGGER\JLink\JLink.exe" -nogui 1
Linux/WSL下启动命令:
JLinkExe -nogui 1
启动后程序会进入J-Link>提示符,需执行以下命令完成烧录:
connect STM32F429ZI SWD 4000 erase loadbin program.elf , 0x0 q
但执行4000(设置JTAG/SWD速度为4000kHz)后,JLinkExe会弹出GUI窗口要求点击Accept,导致后续命令无法自动执行。我用Python+pytest编写的自动化脚本,在发送4000命令后会因JLink进程阻塞而停住,无法执行pyautogui的点击操作。
解决方案
方法1:用JLink参数直接跳过弹窗
JLinkExe支持-accept-license参数,可自动接受许可证弹窗,无需手动点击。
修改启动命令
- Windows/Powershell:
& "C:\Program Files\SEGGER\JLink\JLink.exe" -nogui 1 -accept-license
- Linux/WSL:
JLinkExe -nogui 1 -accept-license
对应Python脚本修改
更新subprocess启动部分,添加-accept-license参数:
# Windows平台 p = subprocess.Popen( [r"C:\Program Files\SEGGER\JLink\JLink.exe", "-nogui", "1", "-accept-license"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True, text=True, shell=True ) # Linux/WSL平台 p = subprocess.Popen( ["JLinkExe", "-nogui", "1", "-accept-license"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True, text=True )
修改后发送4000命令不会弹窗,脚本可继续执行后续烧录命令,无需pyautogui操作。
方法2:多线程分离进程通信与GUI操作
如果使用的JLink版本不支持-accept-license参数,可通过Python多线程,让一个线程负责监听并点击弹窗,主线程继续与JLink进程通信。
修改flash fixture代码
import threading import time @pytest.fixture def flash(canScriptRun) -> None: # 定义点击弹窗的线程函数 def click_accept_button(): time.sleep(2) # 等待弹窗加载,可根据实际情况调整时长 buttonCenterLocation = pyautogui.locateCenterOnScreen("accept.png") if buttonCenterLocation: pyautogui.moveTo(buttonCenterLocation, duration=1) pyautogui.click() # 启动点击线程 click_thread = threading.Thread(target=click_accept_button) click_thread.start() # 启动JLink进程 if (os.name == "nt"): p = subprocess.Popen( [r"C:\Program Files\SEGGER\JLink\JLink.exe", "-nogui", "1"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True, text=True, shell=True ) elif (os.name == "posix"): p = subprocess.Popen( ["JLinkExe", "-nogui", "1"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True, text=True ) # 发送完整烧录命令 full_commands = "connect\nSTM32F429ZI\nSWD\n4000\nerase\nloadbin program.elf , 0x0\nq\n" stdout, stderr = p.communicate(input=full_commands, timeout=None) print(stdout) print(stderr) # 等待点击线程执行完毕 click_thread.join()
方法3:使用JLink脚本文件
将所有烧录命令写入独立脚本文件(如flash_script.jlink):
connect STM32F429ZI SWD 4000 erase loadbin program.elf , 0x0 q
然后用JLinkExe的-scriptfile参数直接执行脚本,同时加上-accept-license跳过弹窗:
启动命令
- Windows/Powershell:
& "C:\Program Files\SEGGER\JLink\JLink.exe" -nogui 1 -accept-license -scriptfile flash_script.jlink
- Linux/WSL:
JLinkExe -nogui 1 -accept-license -scriptfile flash_script.jlink
对应Python脚本简化
@pytest.fixture def flash(canScriptRun) -> None: script_path = "flash_script.jlink" if (os.name == "nt"): p = subprocess.Popen( [r"C:\Program Files\SEGGER\JLink\JLink.exe", "-nogui", "1", "-accept-license", "-scriptfile", script_path], stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True, text=True, shell=True ) elif (os.name == "posix"): p = subprocess.Popen( ["JLinkExe", "-nogui", "1", "-accept-license", "-scriptfile", script_path], stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True, text=True ) stdout, stderr = p.communicate(timeout=None) print(stdout) print(stderr)
内容的提问来源于stack exchange,提问作者71GA
相关产品推荐
相关产品推荐

