连接参数动态更新
使用技术:SLE 连接参数更新、连接间隔、从机延迟和监督超时
学习目标
- 理解连接间隔、从机延迟和监督超时的单位、范围及相互约束。
- 掌握
sle_update_connect_param()的在线更新流程。 - 观察参数更新请求回调和更新完成回调。
- 通过 Kconfig 在 Low Power、Balanced 和 Low Latency 三个编译期档位之间选择。
- 能在两块 WS53 开发板上验证双方最终生效的连接参数。
案例说明
本案例使用两块 WS53 开发板:
- Server 广播设备名
sle_param_server,连接建立后发起参数更新。 - Client 扫描并连接目标设备,输出收到的参数更新请求。
- 双方通过
connect_param_update_cb输出最终生效的参数。 - 断连后 Server 重新广播,Client 重新扫描。
源码目录为:
基本概念
三个核心参数
| 参数 | 含义 | 单位 | 当前 SDK 范围 |
|---|---|---|---|
interval_min / interval_max |
两个连接事件之间的调度间隔 | 0.25 ms | 0x001E~0x3E80,即 7.5 ms~4 s |
max_latency |
允许终端在无数据时跳过的最大连接事件数 | 次 | 0~499 |
supervision_timeout |
多久未收到对端数据后判定断连 | 10 ms | 10~3200,即 100 ms~32 s |
连接间隔越短,通常延迟越低、射频活动越频繁;连接间隔越长,通常更利于降低功耗,但响应延迟会上升。
max_latency 只允许设备在无数据时跳过连接事件。设备有数据要发送时,不需要等满整个休眠周期。
监督超时约束
监督超时必须严格大于最大休眠连接间隔的两倍:
换算成当前 SDK 的原始配置值:
以源码中的 Low Power profile 为例:
因此 12 秒超时满足严格大于约束。若使用 10 秒,左右两边相等,不满足要求。源码会在调用 sle_update_connect_param() 前执行这一校验。
参数档位
源码中的 interval 单位为 0.25 ms,supervision_timeout 单位为 10 ms。Server 的三种 profile 如下:
| 档位 | interval | 折算连接间隔 | max_latency | timeout | 折算监督超时 | 适用方向 |
|---|---|---|---|---|---|---|
| Low Power | 400 | 100 ms | 49 | 1200 | 12 s | 低频上报、低功耗 |
| Balanced(默认) | 50 | 12.5 ms | 0 | 500 | 5 s | 通用交互 |
| Low Latency | 30 | 7.5 ms | 0 | 200 | 2 s | 实时控制、HID |
表中的“折算”值由源码单位换算得到:interval × 0.25 ms、timeout × 10 ms。这些是请求参数的时间换算,不等同于整机功耗、吞吐量或端到端时延的实测结果;最终是否被控制器采用,应以双方 update complete 回调中的参数和 status 为准。
参数定义
WS53 源码使用静态 profile 保存档位名称、连接间隔、从机延迟和监督超时,并通过 Kconfig 在编译期选择:
typedef struct {
const char *name;
uint16_t interval;
uint16_t latency;
uint16_t timeout;
} sle_conn_param_profile_t;
#if defined(CONFIG_SLE_CONN_PARAM_PROFILE_LOW_POWER)
static const sle_conn_param_profile_t PROFILE = {"low-power", 400, 49, 1200};
#elif defined(CONFIG_SLE_CONN_PARAM_PROFILE_LOW_LATENCY)
static const sle_conn_param_profile_t PROFILE = {"low-latency", 30, 0, 200};
#else
static const sle_conn_param_profile_t PROFILE = {"balanced", 50, 0, 500};
#endif
参数合法性校验
Server 在调用协议栈前检查源码定义的范围:interval 为 0x001E~0x3E80,max_latency 不大于 0x01F3,supervision_timeout 为 0x000A~0x0C80,且最小间隔不大于最大间隔。
监督超时约束在源码中通过以下计算检查:
timeout_scaled = (uint32_t)param->supervision_timeout * 20U;
max_connection_gap = ((uint32_t)param->max_latency + 1U) * param->interval_max;
if (timeout_scaled <= max_connection_gap) {
return ERRCODE_INVALID_PARAM;
}
不满足时,Server 打印 invalid profile,不会发送更新请求。
发起参数更新
Server 在连接状态回调收到 SLE_ACB_STATE_CONNECTED 后构造参数,并将同一个 PROFILE.interval 写入最小和最大连接间隔:
sle_connection_param_update_t param = {
.conn_id = conn_id,
.interval_min = PROFILE.interval,
.interval_max = PROFILE.interval,
.max_latency = PROFILE.latency,
.supervision_timeout = PROFILE.timeout,
};
sle_update_connect_param(¶m);
连接回调运行于 SLE service 上下文,不能在其中执行长时间阻塞操作;本案例不会在回调中调用 sleep()。
工作流程
sequenceDiagram
participant S as Server
participant C as Client
S->>S: enable_sle,注册广播和连接回调
S->>C: 广播 sle_param_server
C->>C: 扫描并匹配名称
C->>S: sle_connect_remote_device()
Note over S,C: 连接建立
S->>S: 选择 profile 并校验参数
S->>C: sle_update_connect_param()
Note right of S: connect_param_update_req_cb
Note over S,C: 控制器协商并应用参数
Note right of S: connect_param_update_cb(status)
Note right of C: connect_param_update_cb(status)
当前 SDK 没有 sle_connect_param_update_rsp()。connect_param_update_req_cb 用于观察请求参数,最终结果由 connect_param_update_cb 报告,案例不演示应用层显式接受或拒绝。
代码结构
sle_conn_param_tuning/
├── CMakeLists.txt
├── Kconfig
├── README.md
├── sle_conn_param_tuning.c
├── sle_conn_param_tuning_server/src/
│ ├── sle_conn_param_tuning_server.c
│ ├── sle_conn_param_tuning_server.h
│ ├── sle_conn_param_tuning_server_adv.c
│ └── sle_conn_param_tuning_server_adv.h
└── sle_conn_param_tuning_client/src/
├── sle_conn_param_tuning_client.c
└── sle_conn_param_tuning_client.h
| 文件或函数 | 作用 |
|---|---|
sle_conn_param_tuning.c / sle_conn_param_tuning_entry() |
根据 Kconfig 创建 Server 或 Client 启动任务。 |
sle_conn_param_tuning_server.c |
定义 profile,校验参数并请求更新。 |
sle_conn_param_tuning_server_adv.c |
配置 sle_param_server 广播。 |
sle_conn_param_tuning_client.c |
扫描、连接并记录请求和最终更新结果。 |
sle_conn_param_validate() |
检查协议范围及监督超时约束。 |
sle_conn_param_request_update() |
建链回调中组装 sle_connection_param_update_t 并调用 sle_update_connect_param()。 |
相关 API
| API | 角色 | 用途 |
|---|---|---|
enable_sle() |
Server、Client | 启动 SLE 协议栈。 |
sle_announce_seek_register_callbacks() |
Server、Client | 注册广播或扫描回调。 |
sle_connection_register_callbacks() |
Server、Client | 注册连接状态、参数请求和更新完成回调。 |
sle_set_announce_param() / sle_start_announce() |
Server | 配置并启动广播。 |
sle_set_seek_param() / sle_start_seek() |
Client | 配置并启动扫描。 |
sle_connect_remote_device() |
Client | 发起连接。 |
sle_update_connect_param() |
Server | 请求更新连接参数。 |
Kconfig 配置
角色选项为:
CONFIG_SAMPLE_SUPPORT_SLE_CONN_PARAM_TUNING_SERVER_SAMPLE
CONFIG_SAMPLE_SUPPORT_SLE_CONN_PARAM_TUNING_CLIENT_SAMPLE
Server 的 profile 是一个 Kconfig choice,默认 CONFIG_SLE_CONN_PARAM_PROFILE_BALANCED=y:
CONFIG_SLE_CONN_PARAM_PROFILE_LOW_POWER
CONFIG_SLE_CONN_PARAM_PROFILE_BALANCED
CONFIG_SLE_CONN_PARAM_PROFILE_LOW_LATENCY
Server 和 Client 角色互斥构建;每次更换 profile 后,应重新构建 Server 固件。
编译、烧录和验证
在 SDK 根目录执行。<SERVER_COM> 和 <CLIENT_COM> 替换为实际串口;构建目标使用工程中的 ws53_liteos_app。
第一步:构建并烧录 Server
fbb config set CONFIG_SAMPLE_SUPPORT_SLE_CONN_PARAM_TUNING_SERVER_SAMPLE=y --target ws53_liteos_app
fbb config set CONFIG_SLE_CONN_PARAM_PROFILE_BALANCED=y --target ws53_liteos_app
fbb build ws53_liteos_app --clean
fbb flash ws53_liteos_app --port <SERVER_COM> --json-summary
第二步:构建并烧录 Client
fbb config set CONFIG_SAMPLE_SUPPORT_SLE_CONN_PARAM_TUNING_CLIENT_SAMPLE=y --target ws53_liteos_app
fbb build ws53_liteos_app --clean
fbb flash ws53_liteos_app --port <CLIENT_COM> --json-summary
第三步:验证 Client
fbb monitor --port COM_CLIENT --reset --until "\[sle conn param client\] update complete:.*status=0x0" --timeout 45 --json-summary
平衡模式的关键日志:
[sle conn param client] found sle_param_server, stop seek
[sle conn param client] connected, conn_id=0x00
[sle conn param client] update requested: conn_id=0x00, status=0x0, interval=50-50, latency=0, timeout=500
[sle conn param client] update complete: conn_id=0x00, status=0x0, interval=50, latency=0, timeout=500
第四步:验证 Server
fbb monitor --port COM_SERVER --reset --until "\[sle conn param server\] update complete:.*status=0x0" --timeout 45 --json-summary
平衡模式的关键日志:
[sle conn param server] selected profile=balanced
[sle conn param server] start announce, name=sle_param_server
[sle conn param server] connected, conn_id=0x00
[sle conn param server] update request: profile=balanced, interval=50 (0.25ms), latency=0, timeout=500 (10ms)
[sle conn param server] update request sent, status=0x0
[sle conn param server] update complete: conn_id=0x00, status=0x0, interval=50, latency=0, timeout=500
常见问题
Client 扫描不到 Server
- 确认先启动 Server,串口出现
start announce, name=sle_param_server。 - 确认两块板烧录的是不同角色,而不是同一固件。
- 确认 Client 日志中出现
start seek。
更新请求返回失败
- 检查连接间隔、Latency 和监管超时是否在 SDK 范围内。
- 检查监管超时是否严格满足约束,不能只取临界相等值。
- 使用
connect_param_update_cb的status判断最终结果。
只有系统心跳,没有案例日志
检查目标文件是否包含:
sle_conn_param_tuning.c.obj
sle_conn_param_tuning_server.c.obj
sle_conn_param_tuning_server_adv.c.obj
或 Client 对应的 sle_conn_param_tuning_client.c.obj。若对象文件缺失,重新执行 --clean 构建并检查 Kconfig choice。
限制
- profile 在编译期选择,运行时不能动态切换。
- 示例验证的是参数协商和回调结果,不是功耗、吞吐或端到端时延基准。
- 实际结果还受业务流量、PHY、射频环境和睡眠策略影响。