CH585 BLE连接移植踩坑实录——GATT注册、连接参数与CCCD配置
·
一、GATT服务注册模型不匹配
现象
iot_connect_sdk 调用 BleGattsStartServiceEx 传入属性列表动态注册GATT服务(OHOS标准流程),但CH585的WCH协议栈使用 GATTServApp_RegisterService 注册静态属性表。直接调用动态注册API会导致服务注册失败或属性表损坏。
根因
两种GATT注册模型的差异:
| 维度 | IOTC SDK (OHOS标准) | WCH协议栈 |
|---|---|---|
| 注册方式 | 运行时动态传入属性列表 | 编译时静态定义属性表 |
| UUID类型 | 运行时指定 | 编译时固定 |
| 回调绑定 | 属性列表中携带函数指针 | 通过handle匹配统一回调 |
| 注册API | BleGattsStartServiceEx |
GATTServApp_RegisterService |
解决方案:预注册固定服务,仅提取write回调
在 Peripheral_Init 中预注册固定的 ble_hw_service(128-bit UUID),BleGattsStartServiceEx 不实际注册服务,仅从IOTC传入的属性列表中提取write回调函数指针:
/* ohos_bt_gatt_server.c — BleGattsStartServiceEx */
BleGattServiceWrite gwriteFunc = NULL; /* 全局变量: IOTC注册的write回调 */
int BleGattsStartServiceEx(int *srvcHandle, BleGattService *srvcInfo)
{
/* 从属性列表索引[1]提取IOTC注册的write回调 */
gwriteFunc = srvcInfo->attrList[1].func.write;
if (gwriteFunc == NULL) {
PRINT("ERR gwriteFunc\n");
}
/* 不实际注册GATT服务 — 已由ble_hw_service预注册 */
return OHOS_BT_STATUS_SUCCESS;
}
ble_hw_service 的静态属性表在 ble_hw_service.c 中定义,包含6项属性(Primary Service、TX Characteristic Declaration、TX Value、CCCD、RX Characteristic Declaration、RX Value),使用固定的128-bit UUID:
Service: 15f1e600-a277-43fc-a484-dd39ef8a9100
├── TX (15f1e601): INDICATE | READ, CCCD支持
└── RX (15f1e602): WRITE | WRITE_NO_RSP
二、连接参数未优化导致吞吐低下
现象
BLE连接建立后使用默认连接参数(interval可能高达数秒),SPEKE协商报文传输延迟严重,协商超时。
解决方案:连接后主动发起参数更新
/* peripheral.c — 连接参数更新定时器 */
/* 在 Peripheral_LinkEstablished 中启动 */
tmos_start_task(Peripheral_TaskID, SBP_PARAM_UPDATE_EVT, SBP_PARAM_UPDATE_DELAY);
/* SBP_PARAM_UPDATE_DELAY = 6.25ms, 延迟后发起更新避免连接建立阶段不稳定 */
/* peripheral.c — SBP_PARAM_UPDATE_EVT 处理 */
if (events & SBP_PARAM_UPDATE_EVT) {
GAPRole_PeripheralConnParamUpdateReq(peripheralConnList.connHandle,
DEFAULT_DESIRED_MIN_CONN_INTERVAL, /* 6 = 7.5ms */
DEFAULT_DESIRED_MAX_CONN_INTERVAL, /* 100 = 125ms */
DEFAULT_DESIRED_SLAVE_LATENCY, /* 0 */
DEFAULT_DESIRED_CONN_TIMEOUT, /* 3200 = 32s */
Peripheral_TaskID);
return (events ^ SBP_PARAM_UPDATE_EVT);
}
/* 同时切换到2M PHY提升吞吐 */
if (events & SBP_PHY_UPDATE_EVT) {
GAPRole_UpdatePHY(peripheralConnList.connHandle, 0,
GAP_PHY_BIT_LE_2M, GAP_PHY_BIT_LE_2M, 0);
return (events ^ SBP_PHY_UPDATE_EVT);
}
三、CCCD未配置时Indication发送失败
现象
IOTC SDK在App端尚未使能CCCD时发送Indication,GATT_Indication 返回错误,且分配的缓冲区泄漏。
根因
BLE Indication要求对端先通过CCCD(Client Characteristic Configuration Descriptor)使能Indication后才能发送。若CCCD未配置,GATT_Indication 会返回错误,但调用方可能未释放已分配的缓冲区。
解决方案:发送前检查CCCD状态,失败时释放缓冲区
/* ble_hw_service.c — ble_hw_indicate */
bStatus_t ble_hw_indicate(uint16_t connHandle, attHandleValueInd_t *pIndicate, uint8_t taskId)
{
uint16_t value = GATTServApp_ReadCharCfg(connHandle, ble_hw_tx_cccd);
/* 检查CCCD是否开启INDICATE */
if (value & GATT_CLIENT_CFG_INDICATE) {
pIndicate->handle = ble_hw_profile_table[2].handle;
return GATT_Indication(connHandle, pIndicate, FALSE, taskId);
}
return bleIncorrectMode; /* CCCD未配置 */
}
/* ble_safe_api.c — Exec_SendIndication, 失败时释放缓冲区 */
static int32_t Exec_SendIndication(void *arg)
{
ParamSendIndication *p = (ParamSendIndication *)arg;
attHandleValueInd_t indi;
indi.len = p->len;
indi.pValue = GATT_bm_alloc(peripheralConnList.connHandle,
ATT_HANDLE_VALUE_IND, indi.len, NULL, 0);
if (indi.pValue) {
tmos_memcpy(indi.pValue, p->data, indi.len);
ret = ble_hw_indicate(peripheralConnList.connHandle, &indi, Peripheral_TaskID);
if (ret) {
GATT_bm_free((gattMsg_t *)&indi, ATT_HANDLE_VALUE_IND); /* 失败立即释放 */
}
}
return ret;
}
更多推荐
所有评论(0)