深入解析 Sensor Hub Transport Protocol (SHTP) 协议
文章目录
- [深入解析 Sensor Hub Transport Protocol (SHTP) 协议](#深入解析 Sensor Hub Transport Protocol (SHTP) 协议)
-
- [1. SHTP 概述](#1. SHTP 概述)
- [2. 工作原理与核心概念](#2. 工作原理与核心概念)
-
- [2.1 通道(Channels)](#2.1 通道(Channels))
- [2.2 SHTP 报文头格式](#2.2 SHTP 报文头格式)
- [2.3 核心传输规则](#2.3 核心传输规则)
- [2.4 主机中断 (HINT) 与时间戳](#2.4 主机中断 (HINT) 与时间戳)
- [3. 同步物理层协议 (SPI / I2C)](#3. 同步物理层协议 (SPI / I2C))
-
- [3.1 握手机制(Host-Hub Handshaking)](#3.1 握手机制(Host-Hub Handshaking))
- [3.2 I2C 传输规范](#3.2 I2C 传输规范)
- [3.3 SPI 全双工传输](#3.3 SPI 全双工传输)
- [3.4 读状态机](#3.4 读状态机)
- [4. 异步物理层协议 (SHTP over UART)](#4. 异步物理层协议 (SHTP over UART))
-
- [4.1 帧定界与字符转义](#4.1 帧定界与字符转义)
- [4.2 UART 消息结构](#4.2 UART 消息结构)
- [4.3 串口控制消息(Protocol ID = 0)](#4.3 串口控制消息(Protocol ID = 0))
- [4.4 流控与 WAKE 模式](#4.4 流控与 WAKE 模式)
- [5. 命令通道 (Channel 0) 与广播机制](#5. 命令通道 (Channel 0) 与广播机制)
-
- [5.1 命令与响应格式](#5.1 命令与响应格式)
- [5.2 广播格式(TLV 结构)](#5.2 广播格式(TLV 结构))
-
- [全局广播标签 (Global Advertisement Tags):](#全局广播标签 (Global Advertisement Tags):)
- [SHTP 专用标签 (SHTP Advertisement Tags):](#SHTP 专用标签 (SHTP Advertisement Tags):)
- [6. 总结](#6. 总结)
1. SHTP 概述
Sensor Hub Transport Protocol (SHTP) 是由 Hillcrest Labs 开发的一种低开销、结构简单的传输层协议。它主要用于管理主机(Host)与传感器枢纽(Sensor Hub)之间在物理层(如 SPI、I2C 或 UART)之上的数据通信。
SHTP 的核心定位是"传输机制":它不关心"货物"(Cargo,即具体的数据负载)的具体内容,只负责在主机与 Hub 之间安全、有序地传递数据。数据的解析工作由接收端的具体应用来完成。
- 写入操作(Write): 数据从 Host 传输到 Hub。
- 读取操作(Read): 数据从 Hub 传输到 Host。

2. 工作原理与核心概念

2.1 通道(Channels)
SHTP 引入了"通道"的概念,用于在 Host 和 Hub 之间隔离不同的通信路径。
- 通道是独占分配给特定用户或应用的。
- 通道是双向的,即某一通道的发送和接收均归属于同一个用户。
- 通道 0(Channel 0) 被保留为 命令通道(Command Channel),专门用于 SHTP 协议自身的控制与配置。
2.2 SHTP 报文头格式
所有的 SHTP 读写操作,其数据负载(Cargo)前都必须附加一个 4 字节的报文头(Header)。其具体结构如下:
| 字节 (Byte) | 字段名称 (Field) | 说明 |
|---|---|---|
| 0 | Length LSB | 长度字段低字节 |
| 1 | Length MSB | 长度字段高字节(含控制位) |
| 2 | Channel | 通道号(0 为命令通道) |
| 3 | SeqNum | 序列号 |
- Length (长度字段,16位):
- 第 15 位 (MSB): 用于指示当前传输是否为前一次传输的延续(Continuation)。若该位为 1,代表分片延续。
- 第 14:0 位: 指示该数据包的总字节数(包含 4 字节的 Header 长度)。
- 限制: 长度值
0xFFFF(65535) 被保留作为错误指示(防止因外设损坏持续输出高电平而产生误判)。因此,单次传输的最大 Cargo 长度为32766字节(减去 Header 字节)。
- SeqNum (序列号):
- 每个通道拥有独立的、单调递增的序列号。
- 用于检测重复报文、漏发报文以及重建分包传输的完整数据。
2.3 核心传输规则
- 分片读取(Segmented Reads): 如果主机读取的字节数少于报文头指示的长度,主机会在后续发起额外的读取操作。Hub 会设置长度字段的 MSB(表示延续),并递增序列号,直到整包 Cargo 传输完毕。
- 填充规则: 在全双工物理层(如 SPI)中,如果读取的数据长度超出了实际 Cargo 长度,超出部分必须填充 0。
- 空报文头(Null Header): 长度为 0 的报文头代表无数据(空 Cargo),通常用于 SPI 物理层或主机在无可用数据时发起的空读。
- 系统启动: 系统复位启动时,Hub 必须先向主机发送完整的 应用广播消息(Advertisement Message),在此之前不得发送任何其他数据。
2.4 主机中断 (HINT) 与时间戳
- HINT(Host Interrupt) 是一个边沿触发的中断信号。当 Hub 有数据等待读取时,会拉低/断言 HINT。主机开始读取后,HINT 被去断言(恢复高电平)。
- 时间戳重建: 为了精确记录传感器事件,主机应当在 HINT 发生边沿跳变的时刻记录系统时间戳。Hub 发送的传感器数据中会包含相对于该 HINT 触发时刻的相对时间,主机通过"HINT时间戳 + 相对时间"即可还原出高精度的事件时间。
3. 同步物理层协议 (SPI / I2C)
在 SPI 和 I2C 等同步 serial 接口上,SHTP 定义了专门的握手和传输状态机。
3.1 握手机制(Host-Hub Handshaking)
为防止竞争关系(Race Conditions),推荐采用以下三步握手流程:
- 主机断言 WAKE 信号,请求 Hub 准备传输。
- Hub 断言 HINT 信号,表示其已就绪。
- 主机发起传输,Hub 在传输开始时去断言 HINT。
3.2 I2C 传输规范
- 不支持 I2C 的重复起始条件(Repeated Start)。
- 每次 SHTP 传输必须以 STOP 信号 结束。
3.3 SPI 全双工传输
SPI 支持同时读写。如果读写双方的长度限制不同,超出较小限制的部分将被截断。例如,写限制 64 字节,读限制 128 字节,那么在 128 字节的双工传输中,写 Cargo 的 65~128 字节将被 Hub 忽略。
3.4 读状态机
为了管理读取流程,主机与 Hub 分别运行读状态机:
- 主机侧(Host-Side):
- 检测到 HINT -> 触发 READ。
- 解析 Header 中的 Length:
- 若读取完成(字节数 ≥ \ge ≥ Length 且 Length ≠ \ne = 0)-> 处理 Cargo,回到 IDLE。
- 若读取未完成 -> 继续发起读取,组装分片。
- Hub侧(Hub-Side):
- 数据就绪 -> 断言 HINT 进入 READY。
- 主机开始读取 -> 传输数据,去断言 HINT 进入 READ。
- 根据主机读取的实际字节数,决定进入 IDLE(传输完毕)或 CONTINUE(继续等待读取剩余分片)。
4. 异步物理层协议 (SHTP over UART)
UART 是异步两线协议。由于缺乏同步时钟,且为了支持低功耗和时间戳,SHTP over UART 引入了帧定界符以及专门的流控机制。
4.1 帧定界与字符转义
为了标示一帧数据的开始和结束,协议引入了类似 RFC-1662 标准的控制字符:
- Flag Byte(帧标志):
0x7E - Control Escape(转义字符):
0x7D
转义规则: 当 Payload 数据中出现 0x7E 或 0x7D 时,需先发送 0x7D,随后发送该字节与 0x20 进行异或(XOR)运算后的结果。例如:
- 数据
0x7E→ \rightarrow → 发送0x7D 0x5E
4.2 UART 消息结构
UART 帧的基本结构如下:
text
+-------------+-------------+-----------------------+-------------+
| Flag (0x7E) | Protocol ID | Payload | Flag (0x7E) |
+-------------+-------------+-----------------------+-------------+
- Protocol ID (协议ID):
0x00:SHTP over UART 控制消息0x01:标准 SHTP 数据消息
4.3 串口控制消息(Protocol ID = 0)
控制消息主要用于协调主机写入的缓冲区安全性,防止 Hub 接收溢出:
- Buffer Status Query (BSQ,缓冲状态查询): 主机发送给 Hub,查询其剩余接收空间。
- 格式:
0x7E 0x00 0x7E
- 格式:
- Buffer Status Notification (BSN,缓冲状态通知): Hub 回复给主机,告知可用缓冲区大小。
- 格式:
0x7E 0x00 [Bytes available LSB] [Bytes available MSB] 0x7E
- 格式:
4.4 流控与 WAKE 模式
为了适配不同的功耗需求,UART 写入支持三种 WAKE 硬件管理模式:
- WAKE 信号由主机控制(最省电): 主机拉高 WAKE → \rightarrow → 等待 Hub 回复 BSN → \rightarrow → 发送数据 → \rightarrow → 释放 WAKE。
- WAKE 始终断言: 适用于无 WAKE 信号线,但 Hub 需要 GPIO 维持工作模式的系统。主机必须在每次发送写操作前,通过发送 BSQ 获得 BSN,确认空间充足后才可发送数据。
- WAKE 始终去断言: 适用于仅依靠串口 RX 唤醒的系统。首个 BSQ 可能会因为 Hub 唤醒延迟而丢失,主机会自动进行重试。
注意: 在 UART 模式下写入时,主机在字节之间必须延迟至少 100 微秒。
5. 命令通道 (Channel 0) 与广播机制
SHTP 将通道 0 定义为控制与配置通道。
5.1 命令与响应格式
命令通道上的数据采用"命令/响应"结构:
- Command / Response (1 字节): 表示具体的控制命令或对应的应答。
- P0 ... Pn-1 (参数): 可变长度的参数列表。
常用命令/响应:
- Command 0 (Get Advertisement): 主机向 Hub 请求广播数据。参数 0 用于指定范围(
0代表仅请求 SHTP 广播;1代表请求整个 Hub 广播)。 - Response 0 (Advertisement): 广播响应。系统启动时,Hub 也会主动(unsolicited)向主机发送。
- Command 1 (Send Error List): 请求 SHTP 协议错误列表。
- Response 1 (Error List): 返回未处理的错误码列表(错误码参考 Figure 18,如:代码
1超出最大读限制、代码3写报文超长等)。
5.2 广播格式(TLV 结构)
广播消息采用 TLV (Tag-Length-Value) 格式编码,用于告知主机 Hub 上的通道分配、缓冲区能力限制以及应用 GUID。
其中,长度和 Tag 均为 1 字节。多字节数值字段采用 小端字节序(LSB to MSB)。
全局广播标签 (Global Advertisement Tags):
- Tag 1 (GUID): 全球唯一标识符。GUID 0 被分配给 SHTP 本身。
- Tag 2 (MaxCargoPlusHeaderWrite): 最大写入 Cargo+Header 长度。
- Tag 3 (MaxCargoPlusHeaderRead): 最大读取 Cargo+Header 长度。
- Tag 4 (MaxTransferWrite): 单次写操作的最大传输限制。
- Tag 5 (MaxTransferRead): 单次读操作的最大传输限制。
- Tag 6 (NormalChannel): 常规数据通道(不会唤醒主机)。
- Tag 7 (WakeChannel): 唤醒通道(会唤醒主机)。
- Tag 8 (AppName): Null 结尾的应用名称字符串。
- Tag 9 (ChannelName): Null 结尾的通道名称字符串。
SHTP 专用标签 (SHTP Advertisement Tags):
- Tag 0x80 (SHTP Version): SHTP 协议的版本号。格式为
Null结尾的<major>.<minor>.<patch>字符串(如 "1.0.0")。 - Tag 0x81 (SHTP over UART Timeout): 32 位无符号整数,表示 Hub 发送 BSN 后保持活跃状态的超时时间(单位:毫秒)。
6. 总结
SHTP 协议通过在底层总线(SPI/I2C/UART)之上构建轻量级的通道分用、长度指示和流控机制,成功解决了多应用数据复用同一物理接口的难题。其严谨的状态机设计与 BSN 流控机制,能够避免慢速主机或受限 Hub 在高速通信中发生丢包,是嵌入式传感器系统设计中非常经典且实用的传输层协议。