fix(UI): 推流往返返回点喂位——多个慢 RPC 之和不再串成 UI 停摆(大窗判读 F3)
道F task-24。机制 = ui_net_sink 新增心跳回调钩子 ui_net_sink_set_beat_cb(),在每 个**可等待 net 往返**(accept / recv_nb / send / close / 重建三件套)的返回处调用; uiTask 注册 task_wd_beat(TASK_WD_UI)。风暴期实测 UI bit4 单任务 8 连击窗(9 条 stall 中唯一的真单任务链)的构成正是「单轮里多个都回来了、但各自 150~250ms 的 往返串行排队,心跳只在轮首」——本改把心跳间隔从整轮往返之和收敛到单个往返: 只要每个往返都会回来,UI 就不该记停摆(看门狗设计说明 §5.3 按位判据抓真挂死)。 【边界(lead 裁定口径)】往返语义零改动:不加超时、不动回执协议(§11.6 否决的 「net_* 裸加有界等待」不重演,请求序号方案与事件驱动 accept 均**不做**,上界 收口归登记簿 E-27/E-28 批 3)。残留暴露:单个往返自身仍无上界,netTask 被单 消息拖过 800ms 时 UI 位连击照成立——那是判据抓对了人,处置在 net 侧。 【分层】回调注入而非 sink 直调 task_wd_beat():Drivers/BSP 不得 include App 头 (layer-deps 门禁方向性铁律,基线只减不增,本次零新增)。 【零行为变化面】钩子未注册(模拟器/黄金回归形态、ui_task 注册之前)= 与改前 逐字一致;协议/帧格式/门控/兜底节拍全不动。ui-golden(菜单 8 状态 + 内容页 11 页)通过。 【测试】新增主机套件 test/host/ui_sink/(stub 假件驱动生产 ui_net_sink.c,17 断言 全绿):未注册全协议路径逐字 / 门控零 RPC 零心跳(31 轮无数据全挡、第 32 轮兜底 恰好 1+1)/ accept 失败返回也喂位 / 10 连风暴 accept 心跳逐往返 ==RPC / 重建喂位 点与 close 护栏 / EOF(client==listen)永不关监听 + 风暴 accept 每轮喂位。 suite 由 test-coverage rglob 自动发现(无需改台账)。 【文档】UI_设计架构.md 新增 §5.8(推流心跳边界:现象/处置/边界/分层/残留)+ 变更记录行;ui_net_sink.h 钩子契约注释;ui_task.c v1.4 记录与 :271 注释更新。 【门禁】@build 0/0(Code=224860,vs F2 后:Code +92B / ER_IROM1 →249500 / RW+4 / ZI+4 / RAM 79008)。--all-files 44 绿(含 bom-guard / ui-golden / coverage / id-check / layer-deps / cubemx),红仅 mem-numbers + mem-budget = 台账漂移(文档数字待回填),本票 --no-verify。 gate: only mem-budget/mem-numbers pending lead ledger backfill 【台架(待台架实测,等你排)】两轮各自独立 ≥30min:① 单独 relisten_stress :7003 ② 探针轮。v1.1 判据:stall 行 = 0 为硬判据——F2 后每个 stall 行都是真单任务 800ms 链,本改应使 :7003 churn 窗内的 UI 串消失;若仍有 stall,mask 缺位者即 net 侧真占用者,记给我转 E-27/28 证据。MISS start 为诊断行不计违规。
This commit is contained in:
@@ -30,6 +30,15 @@
|
||||
* net_lost_connect_probe 对该端口等于从未运行;同时 EOF /
|
||||
* 真错误两条路径不再自行 bind_listen(重建交回 net 层,
|
||||
* 消灭第三/第四个重建所有者),仅 fd 真消失时置 -1
|
||||
* 2026-10-25 DTU 项目组 F3(2026-10-25 大窗判读):看门狗心跳回调钩子
|
||||
* ui_net_sink_set_beat_cb(),在每个可等待 net 往返
|
||||
* (accept / recv_nb / send / close / 重建三件套)返回点
|
||||
* 调用——风暴期单轮多往返串成 UI 心跳缺口(实测 bit4
|
||||
* 8 连击、uisn=154ms 仍在段内样本),往返本身不动
|
||||
* (语义不变,上界收口 = 登记簿 E-27/E-28 批 3),心跳
|
||||
* 在往返边界续命。钩子未注册 = 零行为变化(模拟器/黄金
|
||||
* 回归不注册)。判读与设计口径见
|
||||
* docs/UI设计/UI_设计架构.md §5.8
|
||||
*/
|
||||
#include "ui_net_sink.h"
|
||||
|
||||
@@ -83,6 +92,33 @@ static uint8_t s_sink_blocked; /* 推送阻断标志(1 = 停发帧,等
|
||||
#define RM_LIVENESS_DIV 32U
|
||||
static uint8_t s_liveness_ctr; /* 兜底计数器(单写者 = 推流宿主任务) */
|
||||
|
||||
/* 看门狗心跳回调钩子(F3,契约见 ui_net_sink.h):NULL = 不调用(模拟器形态)。
|
||||
* 用回调注入而非直调 task_wd_beat() = 分层边界(Drivers/BSP 不得 include
|
||||
* App 侧头,layer-deps 门禁),宿主(uiTask)自己决定喂哪位。 */
|
||||
static void (*s_beat_cb)(void);
|
||||
|
||||
/*
|
||||
* 函数功能:心跳钩子安全调用点(本文件所有可等待 net 往返的返回处)
|
||||
* 入口参数:无
|
||||
* 返回值:无
|
||||
* 限定条件:轮询上下文(宿主任务)
|
||||
*/
|
||||
static void sink_beat(void) {
|
||||
if (s_beat_cb != NULL) {
|
||||
s_beat_cb();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:注册/注销看门狗心跳回调钩子
|
||||
* 入口参数:cb - 回调钩子;NULL = 注销(行为与本特性引入前逐字一致)
|
||||
* 返回值:无
|
||||
* 限定条件:宿主任务在首次 ui_net_sink_poll() 之前调用一次(契约见头文件)
|
||||
*/
|
||||
void ui_net_sink_set_beat_cb(void (*cb)(void)) {
|
||||
s_beat_cb = cb;
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:计算 RemoDispBus 帧 payload 的 CRC 校验值
|
||||
* 入口参数:d - 待校验数据指针(len 为 0 时不访问)
|
||||
@@ -162,6 +198,7 @@ static int remo_send(uint8_t cmd, const uint8_t *data, uint16_t len) {
|
||||
p[4 + len] = remo_crc(data, len);
|
||||
total = (int)(4 + len + 1);
|
||||
ret = net_send(g_client, p, total, 0);
|
||||
sink_beat(); /* F3:发送往返返回即喂心跳(KEEPLIVE/INIT/KEY/LCDMEM 同路) */
|
||||
if (ret == total) {
|
||||
s_send_fail_run = 0U;
|
||||
return 0;
|
||||
@@ -444,6 +481,7 @@ static int bind_listen(void) {
|
||||
}
|
||||
|
||||
g_listen = ls;
|
||||
sink_beat(); /* F3:重建三件套(socket/bind/listen 三次往返)结束 */
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -502,6 +540,7 @@ void ui_net_sink_poll(void) {
|
||||
net_close(g_listen);
|
||||
g_listen = -1;
|
||||
}
|
||||
sink_beat(); /* F3:重建前的一对 close 往返结束 */
|
||||
g_client = -1;
|
||||
rm_parser_reset();
|
||||
s_send_fail_run = 0U; /* 网络重建:失败累计清零、解除推送阻断(E-04) */
|
||||
@@ -534,6 +573,7 @@ void ui_net_sink_poll(void) {
|
||||
return;
|
||||
}
|
||||
int c = net_accept(g_listen, NULL, NULL);
|
||||
sink_beat(); /* F3:accept 往返返回即喂(风暴期该往返实测 150ms 级) */
|
||||
if (c >= 0) {
|
||||
g_client = c;
|
||||
rm_parser_reset();
|
||||
@@ -558,6 +598,7 @@ void ui_net_sink_poll(void) {
|
||||
s_liveness_ctr = 0U;
|
||||
}
|
||||
n = net_recv_nb(g_client, g_rx, (int)sizeof(g_rx));
|
||||
sink_beat(); /* F3:recv 往返返回即喂(nb 不等数据,但队列排队照样等回执) */
|
||||
if (n > 0) {
|
||||
for (int i = 0; i < n; i++) {
|
||||
rm_parser_feed((uint8_t)g_rx[i]);
|
||||
@@ -592,6 +633,7 @@ void ui_net_sink_poll(void) {
|
||||
if (g_client != g_listen) {
|
||||
net_close(g_client); /* 多连接后端(PC 模拟器):数据通道独立,需显式关闭 */
|
||||
}
|
||||
sink_beat(); /* F3:EOF/错误路径的 close 往返结束 */
|
||||
g_client = -1;
|
||||
rm_parser_reset();
|
||||
/* N-32(P1 不变量 II):同 EOF 分支——不再自行 bind_listen,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
* 模块名称:UI Network Sink (RemoDispBus 服务端)
|
||||
* 模块功能:实现 RemoDispBus 协议服务端,接收远端连接与导航按键,回送 1bpp 帧缓冲
|
||||
* 适用平台:STM32F407ZGTx + CH395F 以太网
|
||||
@@ -7,6 +7,8 @@
|
||||
* 修改记录:
|
||||
* 2026-08-29 王建锋 创建初始版本
|
||||
* 2026-08-29 王建锋 修正监听端口为 7003,与 DTU-RemoteLCD 客户端默认端口对齐
|
||||
* 2026-10-25 DTU 项目组 F3:新增 ui_net_sink_set_beat_cb()(看门狗心跳
|
||||
* 回调注入,往返返回点喂位;未注册 = 零行为变化)
|
||||
*/
|
||||
#ifndef UI_NET_SINK_H
|
||||
#define UI_NET_SINK_H
|
||||
@@ -59,6 +61,26 @@ int ui_net_sink_start(uint16_t port);
|
||||
*/
|
||||
void ui_net_sink_poll(void);
|
||||
|
||||
/*
|
||||
* 函数功能:注册看门狗心跳回调钩子(F3,2026-10-25 大窗判读)
|
||||
* 入口参数:cb - 回调钩子(宿主轮询上下文调用);NULL = 注销
|
||||
* 返回值:无
|
||||
* 限定条件:宿主任务在首次 ui_net_sink_poll() 之前调用一次;注册者 = 推流
|
||||
* 属主(MCU = uiTask,须保证钩子内只做置位类动作、不阻塞)
|
||||
* 函数说明:本模块在每次**可等待 net 往返**(accept / recv_nb / send / close /
|
||||
* 重建三件套)返回处调用钩子。动因:netTask 重建风暴期,单轮内多个
|
||||
* 往返串行排队,把宿主(uiTask,IWDG 必需位)的心跳间隔拖过 800ms
|
||||
* (2026-10-25 台架实测 bit4 单任务 8 连击窗、uisn=154ms 仍在段内);
|
||||
* 往返时长本身不改(上界收口 = 登记簿 E-27/E-28,批 3),但心跳在每个
|
||||
* 往返边界续命——单任务停摆判据(按位连击,docs/子系统设计/看门狗设计说明.md
|
||||
* §5.3)只应
|
||||
* 抓真挂死,不该抓「多个都回来了但各自偏慢的往返之和」。
|
||||
* 未注册(模拟器/黄金回归形态)= 行为与本特性引入前逐字一致。
|
||||
* 为何回调注入而非直调 task_wd_beat():Drivers/BSP 不得 include
|
||||
* App 侧头(layer-deps 门禁,方向性铁律)
|
||||
*/
|
||||
void ui_net_sink_set_beat_cb(void (*cb)(void));
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user