diff --git a/vd960DBN/BLE/OnlyUpdateApp_Peripheral/APP/peripheral.c b/vd960DBN/BLE/OnlyUpdateApp_Peripheral/APP/peripheral.c index e3e8c9f..1d1a540 100644 --- a/vd960DBN/BLE/OnlyUpdateApp_Peripheral/APP/peripheral.c +++ b/vd960DBN/BLE/OnlyUpdateApp_Peripheral/APP/peripheral.c @@ -684,13 +684,18 @@ static void peripheralStateNotificationCB(gapRole_States_t newState, gapRoleEven */ static void performPeriodicTask(void) { - // uint8_t notiData[SIMPLEPROFILE_CHAR4_LEN] = {0x88}; - // peripheralChar4Notify(notiData, SIMPLEPROFILE_CHAR4_LEN); if(g_flag_notify_temp){ g_flag_notify_temp = 0; peripheralChar4Notify(g_notify_buftemp.buf, g_notify_buftemp.len); clear_ble_notify_buf(&g_notify_buftemp); } + /* chunk continuation: when notify buf idle and response queue still + has more fragments, actively pull next packet here (50ms period), + do NOT rely on poll_dbn_ble rx events */ + if(g_notify_buftemp.flag == 0) + { + g_flag_notify_temp = set_response_to_notify(&g_buf_ble_response, &g_notify_buftemp); + } } /********************************************************************* @@ -718,8 +723,13 @@ static void peripheralChar4Notify(uint8_t *pValue, uint16_t len) tmos_memcpy(noti.pValue, pValue, noti.len); if(simpleProfile_Notify(peripheralConnList.connHandle, ¬i) != SUCCESS) { + PRINT("BLE notify FAIL, len:%d, MTU:%d\n", len, peripheralMTU); GATT_bm_free((gattMsg_t *)¬i, ATT_HANDLE_VALUE_NOTI); } + else + { + PRINT("BLE notify OK, len:%d, MTU:%d\n", len, peripheralMTU); + } } } diff --git a/vd960DBN/docs/devlog.md b/vd960DBN/docs/devlog.md index 11a8054..5450d80 100644 --- a/vd960DBN/docs/devlog.md +++ b/vd960DBN/docs/devlog.md @@ -68,6 +68,50 @@ static uint16_t ble_notify_chunk_max(void) --- +## 2026-08-12 — 续:第二分包丢失 — performPeriodicTask 主动拉包 + +### 现场复测 + +小程序发 QUERY 后,第一包 93B 正常收到(`value: ArrayBuffer(93)`,header `0x21` = amount=2/seq=1,含 2 条完整记录 + 第 3 条 21B 残片),**第二包 49B 永远收不到**。设备侧无 `Too large noti`(MTU 检查已过),两包间隔 50ms。 + +### 根因:分包续传依赖"下一次收包事件" + +`poll_dbn_ble` 尾部 `set_response_to_notify` 虽在主循环每轮执行,但分包第二包的填充/发送链路脆弱: + +1. 第一包由 `performPeriodicTask`(50ms TMOS)发出并 `clear_ble_notify_buf` +2. 第二包的填充依赖主循环下一轮 `poll_dbn_ble` 执行 `set_response_to_notify` —— 与 TMOS 周期事件交错,任何主循环阻塞(WCHNET/uart/网络轮询)都会让时序错位 +3. `peripheralChar4Notify` 发送失败(`simpleProfile_Notify != SUCCESS`)时**静默丢弃**,无任何日志 + +### 修复 + +```c +static void performPeriodicTask(void) +{ + if(g_flag_notify_temp){ + g_flag_notify_temp = 0; + peripheralChar4Notify(g_notify_buftemp.buf, g_notify_buftemp.len); + clear_ble_notify_buf(&g_notify_buftemp); + } + /* 分包续传: notify 空闲且响应队列还有分片时, 50ms 周期主动拉下一包, + 不依赖 poll_dbn_ble 收包事件 */ + if(g_notify_buftemp.flag == 0) + { + g_flag_notify_temp = set_response_to_notify(&g_buf_ble_response, &g_notify_buftemp); + } +} +``` + +- `peripheral.c`:`performPeriodicTask` 发完当前包后主动 `set_response_to_notify` 拉下一分片;`peripheralChar4Notify` 增加发送结果打印(`BLE notify OK/FAIL, len, MTU`),定位发送失败不再静默 +- 时序:cycle1 填充 pkt1 → cycle2 发 pkt1 + 填充 pkt2 → cycle3 发 pkt2,**两包间隔 50ms,与收包事件解耦** + +### 验证 + +- 隔离 C 测试:无任何收包事件、仅靠 `performPeriodicTask` 驱动,MTU=96 → 3 周期发出 93B+49B 两包,重组 130B 逐字节一致;MTU=185 → 100B+42B,全 PASS +- 板上烧录后设备日志应出现:`BLE notify OK, len:93` → `BLE notify OK, len:49`;若出现 `FAIL` 则问题在 GATT 层(连接/通知使能) +- 待真机确认:若固件打印两包都 OK 但小程序仍只收 1 包 → 检查小程序 `onBLECharacteristicValueChange` 订阅连续性/连接参数(连接间隔大 + 从机延迟会拉长第二包到达时间) + +--- + ## 2026-08-10 — BLE 读取脱机日志接口 (OFFLOG_STAT/QUERY/CLEAR) ### 背景