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

107 lines
5.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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)→ 再烧录触发复位 → 采集自动抓取。**
```powershell
# 一键:采集(含 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 与文档已全部清理。