MSP v1、v2与DisplayPort¶
多旋翼飞行器串行协议(MSP,MultiWii Serial Protocol)常用于飞控配置、状态查询、命令、外设桥接和屏幕叠加显示。MSP历史长、实现多,兼容性必须绑定具体固件和应用程序编程接口(API,Application Programming Interface)版本。

MSP不是单一功能¶
同一MSP传输可以包含:
- 固件和API身份;
- 状态与传感器数据;
- 配置读取与写入;
- 重启或进入引导加载器;
- OSD配置;
- DisplayPort字符和绘制命令;
- 厂商或项目扩展。
能够解析只读状态,不代表可以安全发送写配置或重启命令。工具必须先识别API、飞控类型和能力,再开放对应功能。
MSP v1¶
请求帧概念结构:
响应方向通常使用>,错误响应可使用!。其中:
size8是载荷字节数;command8是8位命令;- 校验是
size8、command8和全部载荷字节的逐字节异或; - 三字节前导符不进入异或;
- 载荷最大长度受8位长度及实现缓冲区共同限制。
异或校验只能发现部分错误,不能提供密码学完整性。
原生MSP v2¶
原生v2请求概念结构:
关键点:
- 命令和长度扩展为16位;
- 多字节字段低字节先传;
- CRC采用CRC-8/DVB-S2;
- CRC覆盖
flags、命令、长度和载荷; $X<前导符不进入CRC;- 接收端仍必须把协议长度与本地缓冲上限比较。
响应方向和错误方向与v1采用相同概念,但第二个标识字节为X。
v2-over-v1¶
为了穿过只识别MSP v1外框的传输路径,MSP v2还可以封装在v1帧中:
这类帧同时存在:
- v1外层长度和异或校验;
- v1外层命令固定为
255; - v2内层字段和CRC-8/DVB-S2。
外层异或覆盖v1长度、命令255、全部封装内容和内层CRC。新实现和网关应验证两层长度与两层校验,不能因外层通过就跳过内层。
Betaflight 2026.6.2接收状态机会验证外层异或和内层CRC,但不会额外强制外层长度等于5 + 内层载荷长度 + 1。这是一项固定实现边界,不是推荐的新解析器行为。差分测试必须覆盖“外层可容纳、内外声明不一致”的帧,防止桥接器和飞控对同一输入得出不同结论。
长度与缓冲区¶
安全解析顺序:
- 识别
$M或$X; - 验证方向字符;
- 收集固定头;
- 解码声明长度;
- 比较协议上限和本地缓冲上限;
- 等待完整载荷;
- 校验;
- 若为v2-over-v1,再验证内层;
- 分派已知命令。
协议字段上限不等于固定固件实例的输入能力。Betaflight 2026.6.2串口MSP输入缓冲为192字节,接收状态机不解析Jumbo输入。发送边界要按线格式分开:
| 发送格式 | 进入Jumbo的条件 | 固定源码的线上位置 |
|---|---|---|
| MSP v1 | 应用数据载荷长度>=255 |
size=255、8位命令之后紧跟16位小端应用数据长度 |
| v2-over-v1 | 外层封装载荷5 + dataLen + 1 >= 255,即应用数据dataLen >= 249 |
size=255、命令255、5字节v2头之后,紧跟16位小端外层封装载荷长度 |
| Native MSP v2 | 不使用v1 Jumbo | 原生16位小端size直接表示应用数据长度 |
Jumbo额外长度字节进入v1外层异或校验;v2-over-v1的内层v2 CRC仍只覆盖v2头和应用数据,不覆盖位于v2头后的Jumbo长度,外层异或则覆盖全部头、应用数据和v2 CRC。Jumbo在该固定实现中是发送侧特殊路径,不存在通用的线上容量协商。客户端必须按命令和固定接收上限选择请求,不能只根据v1长度字段推导“双方都能收255字节”,也不能假定可以自动分块。
必须测试:
- v1长度255附近;
- v2长度大于本地缓冲;
- 内外层长度矛盾;
- 截断帧;
- 载荷包含
$M<或$X<; - 连续无间隔帧;
- 错误帧后的重同步。
API版本和飞控身份¶
Betaflight的MSP API约定要求客户端先读取API版本和飞控标识。工具至少记录:
- MSP协议版本;
- API主、次版本;
- 飞控标识;
- 固件版本;
- 板卡或目标标识;
- 能力和可用命令。
MSP线格式版本与MSP API版本不是同一概念。Betaflight 2026.6.2可以使用MSP_V1、MSP_V2_OVER_V1或MSP_V2_NATIVE线格式,而MSP_API_VERSION返回协议版本字节、API主版本1和次版本48。使用v2帧不等于“API v2”。
API主版本不兼容时,客户端不应继续通信和写配置。对更高次版本,应在已知命令范围内尝试兼容,并对未知或失败命令优雅降级,只关闭依赖该命令的功能。派生固件若API不完全一致,应使用不同飞控标识,不能伪装成相同标识和API。
未知命令应返回协议定义的错误或被安全拒绝,不能造成解析器失步、重启或部分写入。
读、写和执行命令¶
建议按风险分级:
| 级别 | 示例 | 最低门禁 |
|---|---|---|
| 只读 | 身份、状态、传感器、配置读取 | 版本和长度验证 |
| 配置写入 | 端口、接收机、OSD、模式 | API兼容、范围、状态和回读 |
| 持久化 | 保存非易失配置 | 事务、结果和重启恢复 |
| 执行动作 | 重启、引导加载器、电机测试 | 物理安全、权限和当前状态 |
收到合法帧不能绕过飞控内部解锁和安全状态机。客户端也不能在不知道命令结果时自动重复高风险操作。
请求和响应匹配¶
MSP通常在串行会话中按请求和响应工作,但实现仍需处理:
- 超时;
- 上一次迟到响应;
- 异步状态数据;
- 错误方向;
- 重连;
- 多客户端共享同一桥接链路;
- 请求并发。
串行链路没有天然事务ID时,最保守的方法是限制同一会话只有一个未完成请求,并按命令、长度和当前状态匹配响应。
DisplayPort¶
MSP DisplayPort让飞控向显示设备发送屏幕叠加显示(OSD,On-Screen Display)的字符网格和绘制控制。常见操作包括:
- 心跳;
- 释放或停止会话;
- 清屏;
- 写入字符串或字符属性;
- 提交绘制;
- 设置显示选项或画布信息。
具体子命令和字段必须以固定版本API文档与源码为准。
它传输什么¶
DisplayPort传输的是OSD绘制语义,例如在某行某列写字符,再提交一帧显示。它不是:
- 模拟视频波形;
- 压缩数字视频码流;
- 摄像头图像;
- 射频图传本身。
典型路径是:
DisplayPort正常而视频黑屏,问题可能在摄像头、编码、射频或显示端;视频正常而OSD不更新,问题可能在MSP路径、画布能力或字体映射。
画布与字符¶
双方需要协商或约定:
- 行列数;
- 字符集和字体页;
- 坐标原点;
- 字符属性;
- 扩展字符;
- 清屏和提交时序;
- 心跳和超时;
- 设备重连后的重绘。
发送端不能根据一个固定分辨率假定所有设备具有同一画布。文本越界应裁剪或拒绝,不能写出缓冲区。
帧更新¶
OSD刷新可能产生突发数据。实现应:
- 合并同一显示周期的更新;
- 避免每个字符单独产生不必要请求;
- 保留关键告警优先级;
- 监测队列和丢弃;
- 在链路恢复后执行明确清屏或全量重绘;
- 避免旧字符长期残留。
显示一帧成功不代表长期带宽足够。
安全边界¶
MSP传统链路通常不提供认证或加密。风险控制依赖:
- 限制物理和网络可达范围;
- 区分只读与写入入口;
- 禁止从不受信网络直接桥接;
- 飞控状态门禁;
- 工具侧确认和审计;
- 固件更新与协议解析器安全。
USB不是天然可信边界;连接到被攻陷的计算机仍可能收到恶意命令。
固定版本核验¶
Betaflight 2026.6.2至少核对:
src/main/msp/msp_serial.c中的v1、v2和封装解析;src/main/msp/msp_protocol.h中的API与命令;- DisplayPort实现和当前文档;
- 端口共享、最大载荷和命令状态门禁。
INAV与Betaflight有共同历史,但命令、字段和API版本不能直接互换。其他平台或设备实现MSP子集时,应建立独立能力表。
测试矩阵¶
执行写参数、重启、引导加载器或DisplayPort主动输出前,必须先完成协议审查与测试卡第0节,并按抓包、解码、一致性与版本迁移保存请求、响应和最终状态。
| 类别 | 用例 | 通过标准 |
|---|---|---|
| 身份 | v1/v2读取API与飞控身份 | 版本与固定固件一致 |
| 帧 | 正常、截断、超长、错误校验 | 安全拒绝并能重新同步 |
| 兼容 | 未知命令、旧工具、新工具 | 明确错误,不执行错误写入 |
| 写入 | 合法值、越界值、错误状态 | 仅合法写入,回读一致 |
| 重启 | 应用前断线、应用后断线 | 最终状态可判定 |
| DisplayPort | 不同画布、越界、突发更新 | 无越界、无长期残留 |
| 资源 | 最大持续流量 | 队列和任务时延不越门限 |
异常帧和写入测试仅在SITL、HITL或拆桨且动力级断开的隔离台架执行。
常见误判¶
- 把MSP API版本等同于飞控产品版本;
- 只按命令ID解析,不先读取飞控身份;
- 把v1异或校验称为CRC;
- 忘记v2多字节字段是小端;
- 对v2-over-v1只验证一层校验;
- 把未知命令当作成功空响应;
- 把DisplayPort当作视频传输协议;
- 用一次OSD显示成功证明持续链路容量;
- 允许网络桥接客户端无门禁地发送写入或电机命令。
检查理解¶
- MSP v1和原生v2的前导符有什么不同?
- v2-over-v1为什么需要两层校验?
- 工具为什么要先读取API版本和飞控身份?
- DisplayPort和视频码流分别承载什么?
- MSP帧校验正确为什么仍不能直接执行高风险命令?