SMP 传输规范

本文档说明了实现服务器端和客户端 SMP 传输所需的信息。

Bluetooth Low Energy (LE)

MCUmgr 客户端在实现 SMP 客户端时需要使用以下 Bluetooth 特征:

  • 服务 UUID:8D53DC1D-1DB7-4CD3-868B-8A527460AA84

  • 特征 UUID:DA2E7828-FBCE-4E01-AE9E-261174997C48

所有 SMP 通信都使用单个 GATT 特征。SMP 请求通过 GATT Write Without Response 命令发送。SMP 响应以 GATT Notification 的形式发送

如果 SMP 请求或响应太大,无法放入单个 GATT 命令,发送方会将其分片到多个数据包中。对请求或响应进行分片时不会引入额外的帧格式;有效载荷只是被拆分到多个数据包中。由于 GATT 保证数据包按序交付,第一个分片中的 SMP 头包含重组所需的足够信息。

UART/串行和控制台

Zephyr 的 MCUmgr 子系统中的 SMP 协议规范使用基本的数据帧格式,以支持 UART 通道的多路复用。多路复用要求为每个帧添加两个字节的标记作为前缀,并以换行符终止。目前 MCUmgr 对帧大小施加 127 字节的限制,尽管并没有实际的协议约束要求这一限制。该限制包括前缀和换行符,因此允许的有效载荷大小实际上是 124 字节。

尽管 Zephyr 中不存在这样的传输方式,但可以实现不使用任何帧格式、使用硬件串口控制或使用其他帧界定方式的 UART 传输上的 MCUmgr 客户端/服务器。

帧分片

串行链路上的 SMP 协议被分片为 MTU 大小的帧;每个帧由两个字节的起始标记、正文和终止换行符组成。

帧有四种类型:初始帧、部分帧、部分-最终帧和初始-最终帧;每种帧类型通过起始标记和/或正文内容来区分。

帧格式

初始帧后面必须跟随可选的部分帧序列,最后是部分-最终帧。正文始终采用 Base64 编码,因此正文大小(此处描述为 MTU - 3)实际上能够承载 N = (MTU - 3) / 4 * 3 字节的原始数据。

初始帧的正文前面有两个字节的总数据包长度,采用大端序编码,其值等于原始正文大小加上 CRC16 的两个字节;这意味着初始帧中允许的实际正文大小为 N - 2。

如果正文大小小于 N - 4,则可以在单个帧中承载整个正文及其前面的长度和后面的 CRC,此帧称为初始-最终帧;有关初始-最终帧的说明,请参见下文。

初始帧格式:

内容

大小

描述

0x06 0x09

2 字节

帧起始标记

<base64-i>

不超过 MTU - 3 字节

Base64 编码的正文

0x0a

1 字节

帧终止

<base64-i> 是格式如下的 Base64 编码正文:

内容

大小

描述

总长度

2 字节

大端序 16 位值,表示正文总长度加上 CRC16 的 2 字节;请注意,总长度字段本身的大小不会加到总长度值中。

正文

不超过 MTU - 5

原始正文数据片段

初始-最终帧格式与初始帧格式类似,但 <base64-i> 的定义不同。

初始-最终帧的 <base64-i> 是格式如下的 Base64 编码数据:

内容

大小

描述

总长度

2 字节

大端序 16 位值,表示正文总长度加上 CRC16 的 2 字节;请注意,总长度字段本身的大小不会加到总长度值中。

正文

不超过 MTU - 7

原始正文数据片段

crc16

2 字节

整个数据包正文的 CRC16,不包括前面的长度字段。

部分帧是前一个初始帧或其他部分帧的延续。部分帧的形式如下:

内容

大小

描述

0x04 0x14

2 字节

帧起始标记

<base64-i>

不超过 MTU - 3 字节

Base64 编码的正文

0x0a

1 字节

帧终止

部分帧的 <base64-i> 是数据的 Base64 编码,形式如下:

内容

大小

描述

正文

不超过 MTU - 3

原始正文数据片段

部分-最终帧的 <base64-i> 是数据的 Base64 编码,形式如下:

内容

大小

描述

正文

不超过 MTU - 5

原始正文数据片段

crc16

2 字节

整个数据包正文的 CRC16,不包括前面的长度字段。

CRC 详细信息

最终类型帧中包含的 CRC16 仅对原始数据计算,不包括数据包长度。CRC16 多项式为 0x1021,初始值为 0。

原始 UART/串行(无控制台)

在 Zephyr 中,UART 还有一种替代传输方式,它不像基于控制台的 SMP 传输那样使用 Base64;这可以实现更小的代码体积和更快的传输,但不能用于在同一 UART 上具有 shell 或日志输出的设备,也不能用于连接到显示 ASCII 数据的终端,因为所有通信都使用原始二进制 SMP 协议。

要使用此协议,请使用 CONFIG_MCUMGR_TRANSPORT_RAW_UART,它要求以原始模式启用 MCUmgr UART 控制台驱动。

超时

由于使用此传输方式时没有帧界定,UART 上可能会收到无效数据,导致系统等待例如一个永远也不会到达的超长数据包。为防止这种情况,系统提供了超时机制:如果在特定时间范围内未收到完整数据包,则会清空整个接收缓冲区。建议在 UART 端口上启用此选项;对于 USB CDC 等传输方式,如果它是“虚拟”UART,并且数据在传递前可以被验证,则不需要此选项。可以使用 CONFIG_MCUMGR_TRANSPORT_RAW_UART_INPUT_TIMEOUT 启用该选项,其超时时间可以使用 CONFIG_MCUMGR_TRANSPORT_RAW_UART_INPUT_TIMEOUT_TIME_MS 设置。

API 参考

SMP transport