Files
STM32F4-Base/docs/测试说明/serial-mcp-server_串口调试.md
T
2026-09-02 14:22:33 +08:00

5.6 KiB
Raw Blame History

serial-mcp-server 串口调试指南

通过 Adancurusul/serial-mcp-server(Rust,MIT)自主读取/控制 USART1 串口(PA9 TX / PA10 RX,115200bps)的打印流(MCU printf)。

项目与安装

  • 仓库:https://github.com/Adancurusul/serial-mcp-server
  • 本机安装:%LOCALAPPDATA%\serial-mcp-server\serial-mcp-server.exe(自源码 cargo build --release 编译,v0.3.0)
  • 两种形态:
    • MCP stdio server(serve 子命令)—— opencode.json 中 mcp.serial,工具带 serial_ 前缀
    • CLI(list-ports / open / read / write / close 等)—— 适合脚本化/一次性抓取
  • 串口端口单一配置源:.opencode/serial_config.json(当前本机 COM6 / 115200)。端口变化只改这个文件

核心能力边界(重要)

⚠️ 该项目没有"读取历史消息/历史缓冲"功能(对比 qarnet/serial-mcp 有常驻环形缓冲):

  • MCP read 只能读到调用之后到达的字节,之前的数据直接丢弃
  • 连接打开期间没有后台 ring buffer(源码 src/serial/connection.rs 只持有流,无历史)
  • 抓开机日志必须用 采集窗口模式(duration_ms + start_trigger=first-byte):先启动采集等第一字节,再触发设备输出,否则错过

采集窗口模式(capture)

这是该项目抓完整连续输出的唯一方式,等价于"有边界的持续读"。

CLI 参数

serial-mcp-server read --port COM6 --baud 115200 \
  --duration-ms 30000 \              # 采集窗口时长(从触发点起算)
  --start-trigger first-byte \       # 触发方式:first-byte(默认)/ immediate
  --initial-timeout-ms 90000 \       # first-byte 模式最多等多久来第一字节(超时空返回)
  --idle-timeout-ms 8000 \           # 采集开始后连续静默多久提前结束
  --max-bytes 65536 \                # 累计字节硬上限
  --json

结束原因(completion_reason)

值 含义
initial_timeout 等 first-byte 超时,返回空(不算错误)
duration_elapsed 从触发点采满 duration-ms
idle_timeout 采集中途静默超过 idle-timeout-ms 提前收工
max_bytes 累计达 max-bytes

返回结构

read 对象含:data(合并完整字节)、bytes_read、status(ok/timeout)、completion_reason、waited_ms(等到首字节耗时)、elapsed_ms(采集时长)、chunks[](每块 offset/bytes_read/waited_ms/elapsed_ms)。

抓取 MCU 开机日志(@test 核心场景)

顺序必须:先启动采集(打开 COM 等 first-byte)→ 再烧录触发复位 → 采集自动抓取。

# 一键:采集(含 EOF 重试)→ 烧录 → 提取日志 → verify 校验(在仓库根目录执行,路径用仓库相对路径)
powershell -ExecutionPolicy Bypass -File "test\run_boot_test.ps1" `
  -Port COM6 -BaudRate 115200 -DurationMs 30000 -InitialTimeoutMs 90000 `
  -IdleTimeoutMs 8000 -MaxBytes 65536 `
  -FlashCmd "MDK-ARM\download.bat" `
  -Required "App init OK;Network Init;net init: OK;PHY: 100M FULL" `
  -Forbidden "FAIL;ERROR;HardFault"

退出码:0=PASS / 1=FAIL / 2=采集或烧录错误。

底层脚本(test/serial_capture.ps1)

  • -FlashCmd 分支:一个调用内完成 稳定启动采集 → 烧录 → 等采集结束,避免工具调用间隔导致采集超时
  • EOF 自动重试:COM 被上一个进程释放后立即重开会报 UnexpectedEof: serial stream returned zero bytes during capture(tokio-serial 读 0 字节,第三方项目 capture.rs 视为致命错误)。脚本检测到后退避 1.5s 重开,最多 3 次
  • 采集稳定启动判据:进程存活超过 -StabilityCheckMs(默认 1.5s)

参数经验值(本机固件)

参数 值 理由
idle-timeout-ms 8000 boot 阶段有自然静默间隙(defaultTask 与 netTask 之间约 3~4s),太小会在网络初始化前提前结束
initial-timeout-ms 90000 容错:烧录编译+下载耗时可能 40s+,采集必须等得住
duration-ms 30000 覆盖完整开机流程(boot ~5s + net init ~3s + FTP 延迟 7s)

交互式调试(MCP)

用于主动下发命令、读取响应(非开机日志抓取):

  1. serial_list_ports → 找 COM6(读 .opencode/serial_config.json 确认)
  2. serial_open(port=COM6, baud_rate=115200)→ 返回 connection_id(UUID)
  3. serial_write(connection_id, data, encoding=utf8/hex/base64)
  4. serial_read(connection_id, timeout_ms=1000)→ 单次读,只能读到调用后的字节
  5. serial_close

MCP read 也支持采集窗口字段:duration_ms、start_trigger、initial_timeout_ms、idle_timeout_ms(传 duration_ms 即进入 capture 模式)。

常见陷阱

现象 原因/处理
UnexpectedEof: serial stream returned zero bytes COM 刚被释放立即重开(tokio-serial 读 0 字节)。用 serial_capture.ps1(含重试)或间隔几秒再开
抓到日志缺少 Network Init idle-timeout-ms 太小,在网络初始化前的静默间隙提前结束;调到 8000ms
烧录后无数据 采集必须在烧录前启动;initial-timeout-ms 太短导致采集先超时
Error: Connection ID ... not found connection_id 是每次 open 生成的 UUID,读/写/关都要用它
端口被占用 先 serial_close 释放;Keil ST-Link 下载不占 COM,可并存

工具历史

本项目是 Serial Studio MCP 的替代方案(更轻量、无 GUI 依赖、无导出文件定位问题)。Serial Studio 相关配置、bridge 与文档已全部清理。