修复 P0-a 重传周期 200ms 与 P0-b per-recv 日志,台架重锁 M2/M3 基线并复验
This commit is contained in:
@@ -121,6 +121,10 @@ int net_stack_bring_up(void) {
|
|||||||
(phy == CH395F_PHY_10M_HALF) ? "10M HALF" :
|
(phy == CH395F_PHY_10M_HALF) ? "10M HALF" :
|
||||||
(phy == CH395F_PHY_DISCONN) ? "DISCONNECT" : "UNKNOWN");
|
(phy == CH395F_PHY_DISCONN) ? "DISCONNECT" : "UNKNOWN");
|
||||||
|
|
||||||
|
/* P0-a 证据行:重传周期芯片验收状态(net_init 静默采集,此处延迟打印——
|
||||||
|
* 本位置与 testTask 启动日志无并发窗口,不会触发 UART 丢行) */
|
||||||
|
net_retrans_status_log();
|
||||||
|
|
||||||
/* 自检埋点:链路超时未建立 → 记入自检记录(仅故障才写) */
|
/* 自检埋点:链路超时未建立 → 记入自检记录(仅故障才写) */
|
||||||
if (phy == CH395F_PHY_DISCONN) {
|
if (phy == CH395F_PHY_DISCONN) {
|
||||||
syslog_post(SYSLOG_SELFTEST, "comms fault");
|
syslog_post(SYSLOG_SELFTEST, "comms fault");
|
||||||
|
|||||||
@@ -9,6 +9,8 @@
|
|||||||
* 2026-09-10 王建锋 清理未引用宏(TCP Server 监听 Socket 索引、收发缓冲、
|
* 2026-09-10 王建锋 清理未引用宏(TCP Server 监听 Socket 索引、收发缓冲、
|
||||||
* 连接/接受超时、select/队列/轮询);KeepAlive 三宏改为
|
* 连接/接受超时、select/队列/轮询);KeepAlive 三宏改为
|
||||||
* 实际生效值 60s/5s/3 并在 net_socket.c 引用(原宏为无效遗留值)
|
* 实际生效值 60s/5s/3 并在 net_socket.c 引用(原宏为无效遗留值)
|
||||||
|
* 2026-09-22 新增 NET_RETRANS_COUNT/NET_RETRANS_PERIOD_MS(P0-a:重传周期
|
||||||
|
* 500→200ms 治 D1 症状),net_socket.c 的字面量 8/500 移入本文件
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef NET_CONFIG_H
|
#ifndef NET_CONFIG_H
|
||||||
@@ -37,6 +39,21 @@ extern "C" {
|
|||||||
#define NET_RECV_TIMEOUT_MS 30000 /* 接收超时(30秒,0=无限等待) */
|
#define NET_RECV_TIMEOUT_MS 30000 /* 接收超时(30秒,0=无限等待) */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TCP 重传配置(由 net_socket.c 的 net_init() 在 ch395f_init() 之前下发)
|
||||||
|
* P0-a(2026-09-22):周期 500→200ms——单次丢包代价 500→200ms(治 D1 症状),
|
||||||
|
* 总窗口 8×200=1.6s,链路真断时判失败更快(对远端显示重连有利)。
|
||||||
|
* 手册 §5.18 仅标注上限(≤1000ms)未标注下限;200ms 已经台架验证芯片接受
|
||||||
|
*(GET_CMD_STATUS=0x00 + 全套件无回归,见《链路延迟测试说明.md》§10.2 记录)。
|
||||||
|
*/
|
||||||
|
#ifndef NET_RETRANS_COUNT
|
||||||
|
#define NET_RETRANS_COUNT 8 /* 重传次数(手册:最大 20,默认 12) */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef NET_RETRANS_PERIOD_MS
|
||||||
|
#define NET_RETRANS_PERIOD_MS 200 /* 重传周期 ms(手册:最大 1000,默认 500) */
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* TCP KeepAlive 配置(单位 ms;须为 500 的倍数且 IDLE > INTVL)
|
* TCP KeepAlive 配置(单位 ms;须为 500 的倍数且 IDLE > INTVL)
|
||||||
* 由 net_socket.c 的 net_init() 在 ch395f_init() 之前下发
|
* 由 net_socket.c 的 net_init() 在 ch395f_init() 之前下发
|
||||||
|
|||||||
@@ -40,6 +40,7 @@
|
|||||||
static net_sock_t s_net_socks[NET_MAX_SOCKETS]; /* Socket 控制块数组 */
|
static net_sock_t s_net_socks[NET_MAX_SOCKETS]; /* Socket 控制块数组 */
|
||||||
static int s_net_errno = 0; /* 最后错误码 */
|
static int s_net_errno = 0; /* 最后错误码 */
|
||||||
static uint8_t s_net_initialized = 0; /* 初始化标志 */
|
static uint8_t s_net_initialized = 0; /* 初始化标志 */
|
||||||
|
static uint8_t s_retrans_cmd_status = 0xFFU; /* P0-a:重传周期 GET_CMD_STATUS 验收结果(0xFF=未采集) */
|
||||||
static uint8_t s_local_ip[4]; /* 本机 IP 缓存(网络序,net_getsockname 用) */
|
static uint8_t s_local_ip[4]; /* 本机 IP 缓存(网络序,net_getsockname 用) */
|
||||||
static uint16_t s_dynamic_port = 49152; /* 动态端口分配起始值 */
|
static uint16_t s_dynamic_port = 49152; /* 动态端口分配起始值 */
|
||||||
static volatile uint32_t s_net_generation = 0; /* 网络代次号:网络重建完成时递增(服务据此重建监听) */
|
static volatile uint32_t s_net_generation = 0; /* 网络代次号:网络重建完成时递增(服务据此重建监听) */
|
||||||
@@ -147,8 +148,30 @@ static bool s_mac_is_zero(const uint8_t *p_mac) {
|
|||||||
ch395f_set_tcp_mss(CH395F_TCP_MSS);
|
ch395f_set_tcp_mss(CH395F_TCP_MSS);
|
||||||
|
|
||||||
/* 设置 TCP 重传参数(必须在 INIT_CH395 之前调用*/
|
/* 设置 TCP 重传参数(必须在 INIT_CH395 之前调用*/
|
||||||
ch395f_set_retrans_count(8); /* 重传 8 次*/
|
ch395f_set_retrans_count(NET_RETRANS_COUNT);
|
||||||
ch395f_set_retrans_period(500); /* 每次间隔 500ms,总计 4s 重传窗口 */
|
ch395f_set_retrans_period(NET_RETRANS_PERIOD_MS);
|
||||||
|
/* P0-a 一次性验收(手册无重传参数回读命令):设置命令之后查 GET_CMD_STATUS。
|
||||||
|
* 实测(2026-09-22 台架,500ms 合法值与 2000ms 超限值行为完全一致):
|
||||||
|
* SET 类命令不更新状态寄存器——读到的是 RESET_ALL 的 0x10(BUSY) 陈旧残留
|
||||||
|
* (ch395f_reset 只延时 20ms、不轮询状态);INIT 类长命令才重写寄存器。
|
||||||
|
* 故 3 次 × 20ms 轮询即可捕获真正的值/参数错误码(0x19/0x1A 等),
|
||||||
|
* 0x10 只证明"寄存器未更新",不构成值判据——值的接受性以
|
||||||
|
* 手册范围(≤1000ms)+ 全套件无回归 + 与 500ms 行为一致为准。
|
||||||
|
* 注意:此处只静默捕获状态,不打日志——本窗口与 testTask 启动日志并发,
|
||||||
|
* 并发 printf 会因非重入 UART 发送丢整行(2026-09-22 台架实测);
|
||||||
|
* 打印延迟到 net_stack_bring_up 的 PHY 行之后(net_retrans_status_log)。 */
|
||||||
|
{
|
||||||
|
uint8_t rto_st = CH395F_ERR_BUSY;
|
||||||
|
|
||||||
|
for (uint32_t i = 0U; i < 3U; i++) {
|
||||||
|
osDelay(20U);
|
||||||
|
rto_st = ch395f_get_cmd_status();
|
||||||
|
if (rto_st != CH395F_ERR_BUSY) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s_retrans_cmd_status = rto_st;
|
||||||
|
}
|
||||||
|
|
||||||
/* 设置 TCP KeepAlive 参数(必须在 INIT_CH395 之前,单位 ms,必须为 500 的倍数,且 IDLE > INTVL)
|
/* 设置 TCP KeepAlive 参数(必须在 INIT_CH395 之前,单位 ms,必须为 500 的倍数,且 IDLE > INTVL)
|
||||||
* 值来自 net_config.h 的 NET_KEEPALIVE_*(60s/5s/3)*/
|
* 值来自 net_config.h 的 NET_KEEPALIVE_*(60s/5s/3)*/
|
||||||
@@ -216,6 +239,34 @@ static bool s_mac_is_zero(const uint8_t *p_mac) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 函数功能:打印 P0-a 重传周期芯片验收证据行(一次性)
|
||||||
|
* 入口参数:无
|
||||||
|
* 返 回 值:无
|
||||||
|
* 限定条件:net_init 之后调用;建议放在 net_stack_bring_up 的 PHY 行之后
|
||||||
|
* (启动日志低并发窗口)——net_init 尾部与其它任务启动日志并发时,
|
||||||
|
* 非重入 UART 发送会丢整行(2026-09-22 台架实测)
|
||||||
|
* 函数说明:三分支判读(实测 2026-09-22:SET 类命令不更新状态寄存器):
|
||||||
|
* 0x00 = 芯片明确报告接受;0x10 = 陈旧 BUSY 残留(无判别力,INFO 级,
|
||||||
|
* 避免健康启动误触 [ERR] 标记);其它状态码 = 真值/参数错误(ERROR 级)
|
||||||
|
*/
|
||||||
|
void net_retrans_status_log(void) {
|
||||||
|
if (s_retrans_cmd_status == 0xFFU) {
|
||||||
|
return; /* 本次启动未走 NET 层 bring_up(如硬件层测试模式) */
|
||||||
|
}
|
||||||
|
if (s_retrans_cmd_status == CH395F_ERR_SUCCESS) {
|
||||||
|
DBG_INFO("net_init: retrans %u x %u ms accepted by chip (status=0x00)",
|
||||||
|
(unsigned)NET_RETRANS_COUNT, (unsigned)NET_RETRANS_PERIOD_MS);
|
||||||
|
} else if (s_retrans_cmd_status == CH395F_ERR_BUSY) {
|
||||||
|
DBG_INFO("net_init: retrans %u x %u ms set (status 0x10 = stale residue, inconclusive)",
|
||||||
|
(unsigned)NET_RETRANS_COUNT, (unsigned)NET_RETRANS_PERIOD_MS);
|
||||||
|
} else {
|
||||||
|
DBG_ERROR("net_init: retrans period %u ms REJECTED by chip (cmd status=0x%02X)",
|
||||||
|
(unsigned)NET_RETRANS_PERIOD_MS, (unsigned)s_retrans_cmd_status);
|
||||||
|
}
|
||||||
|
s_retrans_cmd_status = 0xFFU; /* 只打印一次 */
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 函数功能:取网络代次号
|
* 函数功能:取网络代次号
|
||||||
* 入口参数:无
|
* 入口参数:无
|
||||||
@@ -1112,7 +1163,6 @@ static int net_recv_locked(net_sock_t *p_sock, void *buf, int len, int flags,
|
|||||||
int recv_len = ch395f_get_recv_len(sockfd);
|
int recv_len = ch395f_get_recv_len(sockfd);
|
||||||
if (recv_len > 0) {
|
if (recv_len > 0) {
|
||||||
int read_len = (recv_len > len) ? len : recv_len;
|
int read_len = (recv_len > len) ? len : recv_len;
|
||||||
DBG_INFO("recv sock%d len=%d", sockfd, recv_len);
|
|
||||||
ch395f_read_recv_buf(sockfd, (uint8_t *)buf, (uint16_t)read_len);
|
ch395f_read_recv_buf(sockfd, (uint8_t *)buf, (uint16_t)read_len);
|
||||||
p_sock->recv_bytes += (uint32_t)read_len;
|
p_sock->recv_bytes += (uint32_t)read_len;
|
||||||
p_sock->readable = 0; /* 已消费数据(注:部分读受 Trap 13 限制,下一次 RECV_OK 会重新置位) */
|
p_sock->readable = 0; /* 已消费数据(注:部分读受 Trap 13 限制,下一次 RECV_OK 会重新置位) */
|
||||||
|
|||||||
@@ -74,6 +74,17 @@ typedef struct {
|
|||||||
*/
|
*/
|
||||||
int net_init(const char *ip, const char *mask, const char *gateway, const uint8_t *mac);
|
int net_init(const char *ip, const char *mask, const char *gateway, const uint8_t *mac);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 函数功能:打印 P0-a 重传周期芯片验收证据行(一次性)
|
||||||
|
* 入口参数:无
|
||||||
|
* 返回值:无
|
||||||
|
* 限定条件:net_init() 之后;建议放在 net_stack_bring_up() 的 PHY 行之后
|
||||||
|
* 函数说明:net_init 在设置重传参数后立即静默查询 GET_CMD_STATUS(手册无回读
|
||||||
|
* 命令,此状态是"芯片是否接受该周期"的唯一证据);打印延迟到 PHY 行
|
||||||
|
* 之后,避开启动期多任务并发 printf 丢行
|
||||||
|
*/
|
||||||
|
void net_retrans_status_log(void);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 函数功能:取网络代次号
|
* 函数功能:取网络代次号
|
||||||
* 入口参数:无
|
* 入口参数:无
|
||||||
|
|||||||
@@ -0,0 +1,277 @@
|
|||||||
|
{
|
||||||
|
"mode": "net",
|
||||||
|
"host": "192.168.1.100",
|
||||||
|
"port": 8080,
|
||||||
|
"ts_start": "2026-09-22 11:10:26",
|
||||||
|
"ts_end": "2026-09-22 11:10:29",
|
||||||
|
"duration_s": 2.44,
|
||||||
|
"ops_seen": 24,
|
||||||
|
"ftp_stress": false,
|
||||||
|
"seg_l6": {
|
||||||
|
"n": 10,
|
||||||
|
"min_ms": 1.67,
|
||||||
|
"med_ms": 3.917,
|
||||||
|
"p95_ms": 11.951,
|
||||||
|
"max_ms": 11.951,
|
||||||
|
"spikes500": 0,
|
||||||
|
"echo_ok": 10,
|
||||||
|
"echo_fail": 0
|
||||||
|
},
|
||||||
|
"seg_l7_first_byte": {
|
||||||
|
"n": 10,
|
||||||
|
"min_ms": 4.022,
|
||||||
|
"med_ms": 10.01,
|
||||||
|
"p95_ms": 13.815,
|
||||||
|
"max_ms": 13.815,
|
||||||
|
"spikes500": 0
|
||||||
|
},
|
||||||
|
"seg_l7_total": {
|
||||||
|
"n": 10,
|
||||||
|
"min_ms": 53.606,
|
||||||
|
"med_ms": 57.877,
|
||||||
|
"p95_ms": 69.879,
|
||||||
|
"max_ms": 69.879,
|
||||||
|
"spikes500": 0
|
||||||
|
},
|
||||||
|
"l7_crc": {
|
||||||
|
"ok": 10,
|
||||||
|
"fail": 0,
|
||||||
|
"batches_per_frame": [
|
||||||
|
4
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"l5_recv": {
|
||||||
|
"bytes": 2000,
|
||||||
|
"window_ms": 1008.6737
|
||||||
|
},
|
||||||
|
"l5_send": {
|
||||||
|
"bytes": 2000,
|
||||||
|
"window_ms": 47.5123
|
||||||
|
},
|
||||||
|
"l3_drain": {
|
||||||
|
"bytes": 65536,
|
||||||
|
"window_ms": 125.4687
|
||||||
|
},
|
||||||
|
"frames_l7": [
|
||||||
|
{
|
||||||
|
"first_ms": 8.255,
|
||||||
|
"total_ms": 56.233,
|
||||||
|
"batches": [
|
||||||
|
[
|
||||||
|
8.261,
|
||||||
|
1024
|
||||||
|
],
|
||||||
|
[
|
||||||
|
10.034,
|
||||||
|
1024
|
||||||
|
],
|
||||||
|
[
|
||||||
|
11.848,
|
||||||
|
1024
|
||||||
|
],
|
||||||
|
[
|
||||||
|
56.217,
|
||||||
|
137
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"first_ms": 13.815,
|
||||||
|
"total_ms": 60.593,
|
||||||
|
"batches": [
|
||||||
|
[
|
||||||
|
13.82,
|
||||||
|
1024
|
||||||
|
],
|
||||||
|
[
|
||||||
|
15.597,
|
||||||
|
1024
|
||||||
|
],
|
||||||
|
[
|
||||||
|
17.411,
|
||||||
|
1024
|
||||||
|
],
|
||||||
|
[
|
||||||
|
60.577,
|
||||||
|
137
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"first_ms": 4.022,
|
||||||
|
"total_ms": 55.84,
|
||||||
|
"batches": [
|
||||||
|
[
|
||||||
|
4.026,
|
||||||
|
1024
|
||||||
|
],
|
||||||
|
[
|
||||||
|
5.803,
|
||||||
|
1024
|
||||||
|
],
|
||||||
|
[
|
||||||
|
7.671,
|
||||||
|
1024
|
||||||
|
],
|
||||||
|
[
|
||||||
|
55.825,
|
||||||
|
137
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"first_ms": 10.01,
|
||||||
|
"total_ms": 55.081,
|
||||||
|
"batches": [
|
||||||
|
[
|
||||||
|
10.017,
|
||||||
|
1024
|
||||||
|
],
|
||||||
|
[
|
||||||
|
11.805,
|
||||||
|
1024
|
||||||
|
],
|
||||||
|
[
|
||||||
|
13.598,
|
||||||
|
1024
|
||||||
|
],
|
||||||
|
[
|
||||||
|
55.065,
|
||||||
|
137
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"first_ms": 5.731,
|
||||||
|
"total_ms": 64.762,
|
||||||
|
"batches": [
|
||||||
|
[
|
||||||
|
5.738,
|
||||||
|
1024
|
||||||
|
],
|
||||||
|
[
|
||||||
|
7.497,
|
||||||
|
1024
|
||||||
|
],
|
||||||
|
[
|
||||||
|
9.345,
|
||||||
|
1024
|
||||||
|
],
|
||||||
|
[
|
||||||
|
64.748,
|
||||||
|
137
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"first_ms": 13.778,
|
||||||
|
"total_ms": 57.877,
|
||||||
|
"batches": [
|
||||||
|
[
|
||||||
|
13.784,
|
||||||
|
1024
|
||||||
|
],
|
||||||
|
[
|
||||||
|
15.562,
|
||||||
|
1024
|
||||||
|
],
|
||||||
|
[
|
||||||
|
17.362,
|
||||||
|
1024
|
||||||
|
],
|
||||||
|
[
|
||||||
|
57.864,
|
||||||
|
137
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"first_ms": 6.701,
|
||||||
|
"total_ms": 55.287,
|
||||||
|
"batches": [
|
||||||
|
[
|
||||||
|
6.706,
|
||||||
|
1024
|
||||||
|
],
|
||||||
|
[
|
||||||
|
8.51,
|
||||||
|
1024
|
||||||
|
],
|
||||||
|
[
|
||||||
|
10.302,
|
||||||
|
1024
|
||||||
|
],
|
||||||
|
[
|
||||||
|
55.272,
|
||||||
|
137
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"first_ms": 13.296,
|
||||||
|
"total_ms": 69.879,
|
||||||
|
"batches": [
|
||||||
|
[
|
||||||
|
13.303,
|
||||||
|
1024
|
||||||
|
],
|
||||||
|
[
|
||||||
|
15.055,
|
||||||
|
1024
|
||||||
|
],
|
||||||
|
[
|
||||||
|
16.877,
|
||||||
|
1024
|
||||||
|
],
|
||||||
|
[
|
||||||
|
69.864,
|
||||||
|
137
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"first_ms": 5.153,
|
||||||
|
"total_ms": 53.606,
|
||||||
|
"batches": [
|
||||||
|
[
|
||||||
|
5.157,
|
||||||
|
1024
|
||||||
|
],
|
||||||
|
[
|
||||||
|
6.952,
|
||||||
|
1024
|
||||||
|
],
|
||||||
|
[
|
||||||
|
8.765,
|
||||||
|
1024
|
||||||
|
],
|
||||||
|
[
|
||||||
|
53.592,
|
||||||
|
137
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"first_ms": 13.369,
|
||||||
|
"total_ms": 61.291,
|
||||||
|
"batches": [
|
||||||
|
[
|
||||||
|
13.374,
|
||||||
|
1024
|
||||||
|
],
|
||||||
|
[
|
||||||
|
15.179,
|
||||||
|
1024
|
||||||
|
],
|
||||||
|
[
|
||||||
|
17.008,
|
||||||
|
1024
|
||||||
|
],
|
||||||
|
[
|
||||||
|
61.279,
|
||||||
|
137
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,277 @@
|
|||||||
|
{
|
||||||
|
"mode": "net",
|
||||||
|
"host": "192.168.1.100",
|
||||||
|
"port": 8080,
|
||||||
|
"ts_start": "2026-09-22 11:08:59",
|
||||||
|
"ts_end": "2026-09-22 11:09:02",
|
||||||
|
"duration_s": 2.59,
|
||||||
|
"ops_seen": 24,
|
||||||
|
"ftp_stress": false,
|
||||||
|
"seg_l6": {
|
||||||
|
"n": 10,
|
||||||
|
"min_ms": 9.348,
|
||||||
|
"med_ms": 12.065,
|
||||||
|
"p95_ms": 16.051,
|
||||||
|
"max_ms": 16.051,
|
||||||
|
"spikes500": 0,
|
||||||
|
"echo_ok": 10,
|
||||||
|
"echo_fail": 0
|
||||||
|
},
|
||||||
|
"seg_l7_first_byte": {
|
||||||
|
"n": 10,
|
||||||
|
"min_ms": 7.619,
|
||||||
|
"med_ms": 13.088,
|
||||||
|
"p95_ms": 53.221,
|
||||||
|
"max_ms": 53.221,
|
||||||
|
"spikes500": 0
|
||||||
|
},
|
||||||
|
"seg_l7_total": {
|
||||||
|
"n": 10,
|
||||||
|
"min_ms": 57.397,
|
||||||
|
"med_ms": 62.679,
|
||||||
|
"p95_ms": 106.185,
|
||||||
|
"max_ms": 106.185,
|
||||||
|
"spikes500": 0
|
||||||
|
},
|
||||||
|
"l7_crc": {
|
||||||
|
"ok": 10,
|
||||||
|
"fail": 0,
|
||||||
|
"batches_per_frame": [
|
||||||
|
4
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"l5_recv": {
|
||||||
|
"bytes": 2000,
|
||||||
|
"window_ms": 1008.8286
|
||||||
|
},
|
||||||
|
"l5_send": {
|
||||||
|
"bytes": 2000,
|
||||||
|
"window_ms": 45.519
|
||||||
|
},
|
||||||
|
"l3_drain": {
|
||||||
|
"bytes": 65536,
|
||||||
|
"window_ms": 125.3308
|
||||||
|
},
|
||||||
|
"frames_l7": [
|
||||||
|
{
|
||||||
|
"first_ms": 12.655,
|
||||||
|
"total_ms": 70.865,
|
||||||
|
"batches": [
|
||||||
|
[
|
||||||
|
12.662,
|
||||||
|
1024
|
||||||
|
],
|
||||||
|
[
|
||||||
|
14.453,
|
||||||
|
1024
|
||||||
|
],
|
||||||
|
[
|
||||||
|
16.304,
|
||||||
|
1024
|
||||||
|
],
|
||||||
|
[
|
||||||
|
70.85,
|
||||||
|
137
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"first_ms": 7.619,
|
||||||
|
"total_ms": 58.158,
|
||||||
|
"batches": [
|
||||||
|
[
|
||||||
|
7.627,
|
||||||
|
1024
|
||||||
|
],
|
||||||
|
[
|
||||||
|
9.427,
|
||||||
|
1024
|
||||||
|
],
|
||||||
|
[
|
||||||
|
11.18,
|
||||||
|
1024
|
||||||
|
],
|
||||||
|
[
|
||||||
|
58.143,
|
||||||
|
137
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"first_ms": 15.244,
|
||||||
|
"total_ms": 68.911,
|
||||||
|
"batches": [
|
||||||
|
[
|
||||||
|
15.249,
|
||||||
|
1024
|
||||||
|
],
|
||||||
|
[
|
||||||
|
17.025,
|
||||||
|
1024
|
||||||
|
],
|
||||||
|
[
|
||||||
|
18.875,
|
||||||
|
1024
|
||||||
|
],
|
||||||
|
[
|
||||||
|
68.889,
|
||||||
|
137
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"first_ms": 13.088,
|
||||||
|
"total_ms": 62.212,
|
||||||
|
"batches": [
|
||||||
|
[
|
||||||
|
13.092,
|
||||||
|
1024
|
||||||
|
],
|
||||||
|
[
|
||||||
|
14.853,
|
||||||
|
1024
|
||||||
|
],
|
||||||
|
[
|
||||||
|
16.691,
|
||||||
|
1024
|
||||||
|
],
|
||||||
|
[
|
||||||
|
62.196,
|
||||||
|
137
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"first_ms": 16.735,
|
||||||
|
"total_ms": 60.274,
|
||||||
|
"batches": [
|
||||||
|
[
|
||||||
|
16.741,
|
||||||
|
1024
|
||||||
|
],
|
||||||
|
[
|
||||||
|
18.501,
|
||||||
|
1024
|
||||||
|
],
|
||||||
|
[
|
||||||
|
20.294,
|
||||||
|
1024
|
||||||
|
],
|
||||||
|
[
|
||||||
|
60.262,
|
||||||
|
137
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"first_ms": 53.221,
|
||||||
|
"total_ms": 106.185,
|
||||||
|
"batches": [
|
||||||
|
[
|
||||||
|
53.226,
|
||||||
|
1024
|
||||||
|
],
|
||||||
|
[
|
||||||
|
55.039,
|
||||||
|
1024
|
||||||
|
],
|
||||||
|
[
|
||||||
|
56.83,
|
||||||
|
1024
|
||||||
|
],
|
||||||
|
[
|
||||||
|
106.171,
|
||||||
|
137
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"first_ms": 12.842,
|
||||||
|
"total_ms": 69.886,
|
||||||
|
"batches": [
|
||||||
|
[
|
||||||
|
12.846,
|
||||||
|
1024
|
||||||
|
],
|
||||||
|
[
|
||||||
|
14.662,
|
||||||
|
1024
|
||||||
|
],
|
||||||
|
[
|
||||||
|
16.428,
|
||||||
|
1024
|
||||||
|
],
|
||||||
|
[
|
||||||
|
69.865,
|
||||||
|
137
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"first_ms": 8.738,
|
||||||
|
"total_ms": 61.345,
|
||||||
|
"batches": [
|
||||||
|
[
|
||||||
|
8.742,
|
||||||
|
1024
|
||||||
|
],
|
||||||
|
[
|
||||||
|
10.551,
|
||||||
|
1024
|
||||||
|
],
|
||||||
|
[
|
||||||
|
12.391,
|
||||||
|
1024
|
||||||
|
],
|
||||||
|
[
|
||||||
|
61.323,
|
||||||
|
137
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"first_ms": 13.19,
|
||||||
|
"total_ms": 57.397,
|
||||||
|
"batches": [
|
||||||
|
[
|
||||||
|
13.195,
|
||||||
|
1024
|
||||||
|
],
|
||||||
|
[
|
||||||
|
14.977,
|
||||||
|
1024
|
||||||
|
],
|
||||||
|
[
|
||||||
|
16.845,
|
||||||
|
1024
|
||||||
|
],
|
||||||
|
[
|
||||||
|
57.382,
|
||||||
|
137
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"first_ms": 10.595,
|
||||||
|
"total_ms": 62.679,
|
||||||
|
"batches": [
|
||||||
|
[
|
||||||
|
10.608,
|
||||||
|
1024
|
||||||
|
],
|
||||||
|
[
|
||||||
|
12.441,
|
||||||
|
1024
|
||||||
|
],
|
||||||
|
[
|
||||||
|
14.225,
|
||||||
|
1024
|
||||||
|
],
|
||||||
|
[
|
||||||
|
62.668,
|
||||||
|
137
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
+106
-78
@@ -6,6 +6,7 @@
|
|||||||
> **数据日期**:2026-09-22 台架(COM6 @115200;STM32F407ZGTx @168MHz + CH395F,SPI2 分频 8)
|
> **数据日期**:2026-09-22 台架(COM6 @115200;STM32F407ZGTx @168MHz + CH395F,SPI2 分频 8)
|
||||||
> **数据文件**:`m2_data/`、`m3_data/`(JSON + 串口证据片段);本文所有数字均可回溯到这些文件
|
> **数据文件**:`m2_data/`、`m3_data/`(JSON + 串口证据片段);本文所有数字均可回溯到这些文件
|
||||||
> **代码状态**:D10 / E-02 / D17 / D12 / D14 / D15 / D16 已修复并台架复验(§8);
|
> **代码状态**:D10 / E-02 / D17 / D12 / D14 / D15 / D16 已修复并台架复验(§8);
|
||||||
|
> D1(重传周期 200ms)/ D6(per-recv 日志)2026-09-22 已实施并台架复验(P0-a/P0-b,§10.1);
|
||||||
> D20(开机首个 FTP 会话第 2 个数据连接 425)已定位未修(§8.2)
|
> D20(开机首个 FTP 会话第 2 个数据连接 425)已定位未修(§8.2)
|
||||||
> **合并说明**:本文统一原《链路延迟测试说明》《链路时延实测数据分析》《远程显示延迟分析》
|
> **合并说明**:本文统一原《链路延迟测试说明》《链路时延实测数据分析》《远程显示延迟分析》
|
||||||
> (2026-09-22);过程性历史记录(逐日变更、调试过程)不再保留,现状以本文与 git 历史为准。
|
> (2026-09-22);过程性历史记录(逐日变更、调试过程)不再保留,现状以本文与 git 历史为准。
|
||||||
@@ -14,9 +15,10 @@
|
|||||||
|
|
||||||
## 1. 一句话结论(当前状态)
|
## 1. 一句话结论(当前状态)
|
||||||
|
|
||||||
**远端显示一帧(3209B 全帧)端到端实测中位 66.0ms,其中约 52.6ms(79%)是帧尾那 137B 小段的等待**;
|
**远端显示一帧(3209B 全帧)端到端实测中位 61.6ms,其中约 52.6ms(85%)是帧尾那 137B 小段的等待**;
|
||||||
MCU 侧真实处理只占 7.1ms,任务拾取/调度约 6.8ms。同一客户端、同一台 PC 打 PC 模拟器只要 6.8ms
|
MCU 侧真实处理只占 6.7ms,任务拾取/调度约 2.3ms(2026-09-22 重锁:P0-b 删 per-recv 日志后
|
||||||
(Δ = 59.2ms 为 CH395F 链路净贡献,且模拟器完全没有尾批延迟)。
|
帧周期 66.0→61.6ms,拾取/调度 6.8→2.3ms,差的 ~4.4ms 即原 per-recv 日志税)。同一客户端、同一台 PC 打 PC 模拟器只要 6.8ms
|
||||||
|
(Δ = 54.8ms 为 CH395F 链路净贡献,且模拟器完全没有尾批延迟)。
|
||||||
|
|
||||||
- **尾批根因(已确证,无需抓包)**:芯片按 Nagle 扣住帧尾的次 MSS 段(MSS=1024,3209 = 3×1024 + 137)
|
- **尾批根因(已确证,无需抓包)**:芯片按 Nagle 扣住帧尾的次 MSS 段(MSS=1024,3209 = 3×1024 + 137)
|
||||||
等对端 ACK,Windows 延迟 ACK 把这一等推迟 ~50ms(§7.3 五组带内实验)。
|
等对端 ACK,Windows 延迟 ACK 把这一等推迟 ~50ms(§7.3 五组带内实验)。
|
||||||
@@ -24,7 +26,8 @@ MCU 侧真实处理只占 7.1ms,任务拾取/调度约 6.8ms。同一客户端
|
|||||||
非 Windows 用"入站轻推"兜底(**29.4ms**,2.3×);协议与固件都不需要改(§7.4)。
|
非 Windows 用"入站轻推"兜底(**29.4ms**,2.3×);协议与固件都不需要改(§7.4)。
|
||||||
- **设备侧无可行解**(帧长 3209 为质数、TX FIFO = MSS、CH395F 无 Nagle 开关)→ 不必再投入。
|
- **设备侧无可行解**(帧长 3209 为质数、TX FIFO = MSS、CH395F 无 Nagle 开关)→ 不必再投入。
|
||||||
- **缺陷**:D10(断线重监听 588ms 冻结 netTask)、E-02(一条空闲 FTP 控制连接冻结全网 17.7s)、
|
- **缺陷**:D10(断线重监听 588ms 冻结 netTask)、E-02(一条空闲 FTP 控制连接冻结全网 17.7s)、
|
||||||
D17(INIT 应答帧字节数字段恒 0)等已量化并**修复 + 台架复验**(§8.1);D20 已定位未修(§8.2)。
|
D17(INIT 应答帧字节数字段恒 0)等已量化并**修复 + 台架复验**(§8.1);
|
||||||
|
D1(重传周期 500→200ms)/ D6(per-recv 日志)2026-09-22 已实施(§10.1);D20 已定位未修(§8.2)。
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -68,7 +71,7 @@ sequenceDiagram
|
|||||||
N->>C: WRITE_SEND_BUF ≤1KB(SPI DMA ≈1.6ms/KB)
|
N->>C: WRITE_SEND_BUF ≤1KB(SPI DMA ≈1.6ms/KB)
|
||||||
C-->>N: SENBUF_FREE 中断
|
C-->>N: SENBUF_FREE 中断
|
||||||
end
|
end
|
||||||
Note over C: D1 丢一段 → 重传 +500ms(现 8×500ms;D7 供包)
|
Note over C: D1 丢一段 → 重传 +200ms(现 8×200ms,P0-a 已实装;D7 供包)
|
||||||
C-->>F: 3×1024B 满段 + 137B 尾段
|
C-->>F: 3×1024B 满段 + 137B 尾段
|
||||||
Note over F: D4 Windows 延迟确认 40~200ms(生产客户端已关)→ 尾段扣住 ~50ms
|
Note over F: D4 Windows 延迟确认 40~200ms(生产客户端已关)→ 尾段扣住 ~50ms
|
||||||
F->>B: PNG → base64 → socketio → canvas
|
F->>B: PNG → base64 → socketio → canvas
|
||||||
@@ -85,7 +88,7 @@ sequenceDiagram
|
|||||||
| `NET_SEND_CHUNK_MAX` | **1KB**(受发送缓冲与 DMA 载荷 2048 双重钳制) | `net_socket.c` |
|
| `NET_SEND_CHUNK_MAX` | **1KB**(受发送缓冲与 DMA 载荷 2048 双重钳制) | `net_socket.c` |
|
||||||
| LCDMEM 一帧分块数 / 分段数 | **4**(1024×3 + 137) | 3209 ÷ 1024 |
|
| LCDMEM 一帧分块数 / 分段数 | **4**(1024×3 + 137) | 3209 ÷ 1024 |
|
||||||
| CH395F 内部 RAM | 48 块 × 512B = 24KB,`net_init` 按 8 socket 均分 6 块 | `net_init` |
|
| CH395F 内部 RAM | 48 块 × 512B = 24KB,`net_init` 按 8 socket 均分 6 块 | `net_init` |
|
||||||
| TCP 重传 | **8 次 × 500ms = 4s 窗口**(固定周期,非 RTT 自适应) | `ch395f_set_retrans_count/period` |
|
| TCP 重传 | **8 次 × 200ms = 1.6s 窗口**(固定周期,非 RTT 自适应;P0-a 2026-09-22 实装,原 8×500ms=4s) | `NET_RETRANS_COUNT/PERIOD_MS`(`net_config.h`) |
|
||||||
| SPI2 速率 | APB1 42MHz ÷ 8 ≈ **5.25 Mbit/s** → 1KB ≈ **1.6ms**(分频 8 为 PCB 约束,勿"优化") | `Src/spi.c` |
|
| SPI2 速率 | APB1 42MHz ÷ 8 ≈ **5.25 Mbit/s** → 1KB ≈ **1.6ms**(分频 8 为 PCB 约束,勿"优化") | `Src/spi.c` |
|
||||||
| 发送等待超时 | 1s(`NET_SEND_TIMEOUT_MS`) | `net_config.h` |
|
| 发送等待超时 | 1s(`NET_SEND_TIMEOUT_MS`) | `net_config.h` |
|
||||||
| 接收超时 | 30s(`NET_RECV_TIMEOUT_MS`) | `net_config.h` |
|
| 接收超时 | 30s(`NET_RECV_TIMEOUT_MS`) | `net_config.h` |
|
||||||
@@ -110,15 +113,15 @@ sequenceDiagram
|
|||||||
| **L1** | SPI 字节命令 | 一条小 SPI 事务(GET_IC_VER / CHECK_EXIST / GLOB_INT,4~7B)端到端 | MCU,DWT µs,Phase 12,N=100/命令 | 10 / 15 / 15µs | SPI 走线/PCB/分频/DMA 配置 |
|
| **L1** | SPI 字节命令 | 一条小 SPI 事务(GET_IC_VER / CHECK_EXIST / GLOB_INT,4~7B)端到端 | MCU,DWT µs,Phase 12,N=100/命令 | 10 / 15 / 15µs | SPI 走线/PCB/分频/DMA 配置 |
|
||||||
| **L2** | SPI DMA | `ch395f_read_recv_buf(N)` 完整 DMA 事务(含 CS 切换),N ∈ {4, 64, 1024, 2048} | MCU,DWT µs,Phase 12,N=100/档 | 20 / 114 / **1611** / 3208µs(斜率 1.56µs/B + 固定 14µs) | SPI2/DMA/总线异常 |
|
| **L2** | SPI DMA | `ch395f_read_recv_buf(N)` 完整 DMA 事务(含 CS 切换),N ∈ {4, 64, 1024, 2048} | MCU,DWT µs,Phase 12,N=100/档 | 20 / 114 / **1611** / 3208µs(斜率 1.56µs/B + 固定 14µs) | SPI2/DMA/总线异常 |
|
||||||
| **L3** | 发送分块握手 | `write_send_buf(1KB)` → `SENBUF_FREE` 的等待时长(= `net_send_locked` 每 chunk 的真实等待) | MCU(netTask 上下文),Phase 13 | **219µs**/chunk | 芯片发送路径 / 重传(D1) / 链路(D7) |
|
| **L3** | 发送分块握手 | `write_send_buf(1KB)` → `SENBUF_FREE` 的等待时长(= `net_send_locked` 每 chunk 的真实等待) | MCU(netTask 上下文),Phase 13 | **219µs**/chunk | 芯片发送路径 / 重传(D1) / 链路(D7) |
|
||||||
| **L4** | 芯片→线上+PC | 数据交入芯片协议栈 → PC 首见字节 / 收齐全帧(peer 逐 `recv()` 批次打时间戳) | PC(peer),Phase 13/14 | 首批 8.6ms;**段间间隙 ≥500ms = 重传** | D1/D4/D7("网络延迟"直接证据) |
|
| **L4** | 芯片→线上+PC | 数据交入芯片协议栈 → PC 首见字节 / 收齐全帧(peer 逐 `recv()` 批次打时间戳) | PC(peer),Phase 13/14 | 首批 8.6ms;**段间间隙 ≥200ms = 重传**(P0-a 后粒度;旧固件 500ms) | D1/D4/D7("网络延迟"直接证据) |
|
||||||
| **L5** | 队列往返 | 调用方视角 `net_recv(DONTWAIT)` / `net_send` 全程 = 入队 + netTask 调度 + 处理 + 通知 | MCU(调用方计时),Phase 13,**两档**:静默基线 + 压力档(并发 FTP 流量) | 静默:收 5997µs / 发 987µs | D3(E-02 头阻塞,已修) / D5 调度 |
|
| **L5** | 队列往返 | 调用方视角 `net_recv(DONTWAIT)` / `net_send` 全程 = 入队 + netTask 调度 + 处理 + 通知 | MCU(调用方计时),Phase 13,**两档**:静默基线 + 压力档(并发 FTP 流量) | 静默:收 1223µs / 发 988µs(2026-09-22 重锁,P0-b 后) | D3(E-02 头阻塞,已修) / D5 调度 |
|
||||||
| **L6** | 请求→首字节 | peer 发 10B 请求 → MCU 收齐并回显(服务端视角);与 PC 侧对照,差值 = 线路 + PC 栈 | MCU + PC 双侧,Phase 13 | MCU 319µs / PC 1.4ms | MCU 收路径/调度 |
|
| **L6** | 请求→首字节 | peer 发 10B 请求 → MCU 收齐并回显(服务端视角);与 PC 侧对照,差值 = 线路 + PC 栈 | MCU + PC 双侧,Phase 13 | MCU 986µs / PC 3.9ms | MCU 收路径/调度 |
|
||||||
| **L7** | 整帧 3209B 往返 | LCDMEM 全帧:PC 发 → 收齐(含 L3+L4) | PC 为主,Phase 13 | 61.0ms(M2);**spike(≥500ms)=0** | D1+D2+D4 综合 |
|
| **L7** | 整帧 3209B 往返 | LCDMEM 全帧:PC 发 → 收齐(含 L3+L4) | PC 为主,Phase 13 | 61.0ms(M2);**spike(≥500ms)=0** | D1+D2+D4 综合 |
|
||||||
| **L8** | 生产路径帧周期 | **真实 uiTask + 真实 `ui_net_sink`**(:7003)完整帧周期:请求拾取(10ms 拍)+ 队列 + 发送 + L4 + peer 侧编码 | MCU 探针 + PC,Phase 14 | 真机 66.0ms / 模拟器 6.8ms(含 peer 100ms 节拍) | 全段(用户真实体感) |
|
| **L8** | 生产路径帧周期 | **真实 uiTask + 真实 `ui_net_sink`**(:7003)完整帧周期:请求拾取(10ms 拍)+ 队列 + 发送 + L4 + peer 侧编码 | MCU 探针 + PC,Phase 14 | 真机 61.6ms / 模拟器 6.8ms(含 peer 100ms 节拍) | 全段(用户真实体感) |
|
||||||
| **L9** | 连接/重监听 | connect→ESTABLISHED;close→relisten 成功 | MCU(net_poll 观测点),Phase 14 | relisten **89ms**(D10 修复后) | 握手/队列;**≥500ms = D10 回归** |
|
| **L9** | 连接/重监听 | connect→ESTABLISHED;close→relisten 成功 | MCU(net_poll 观测点),Phase 14 | relisten **89ms**(D10 修复后) | 握手/队列;**≥500ms = D10 回归** |
|
||||||
| **L10** | 日志税 | 一行 60 字符 `printf`(现 fputc 逐字节 @115200)耗时 | MCU,Phase 13 附带 | **4396µs/行** | D6(待办 P0-b/S8) |
|
| **L10** | 日志税 | 一行 60 字符 `printf`(现 fputc 逐字节 @115200)耗时 | MCU,Phase 13 附带 | **4402µs/行** | D6(per-recv 日志已删 2026-09-22;S8 非阻塞日志仍待办) |
|
||||||
| **L11** | uiTask 节拍 | 生产循环实测周期(`osDelay(10)` 之外多花多少 = LVGL 渲染 + 渲染中排空) | MCU 探针,Phase 14 | **10986µs**(渲染仅 ~1ms/帧) | D5/D9(实测均非瓶颈) |
|
| **L11** | uiTask 节拍 | 生产循环实测周期(`osDelay(10)` 之外多花多少 = LVGL 渲染 + 渲染中排空) | MCU 探针,Phase 14 | **10986µs**(渲染仅 ~1ms/帧) | D5/D9(实测均非瓶颈) |
|
||||||
| **Δ** | CH395F 净贡献 | `L8(真机) − L8(模拟器)`,同一 peer 交替跑 | PC,Phase 14 | **59.2ms**(阈值 ≤80ms) | 直接回答"网络延迟"占多少 |
|
| **Δ** | CH395F 净贡献 | `L8(真机) − L8(模拟器)`,同一 peer 交替跑 | PC,Phase 14 | **54.8ms**(阈值 ≤80ms) | 直接回答"网络延迟"占多少 |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -333,70 +336,83 @@ DMA 斜率实测 1.56µs/B(≈5.25 Mbit/s,与 SPI2 分频 8 @42MHz APB1 设
|
|||||||
|
|
||||||
### 6.2 M2 段(Phase 13,芯片 + 队列)
|
### 6.2 M2 段(Phase 13,芯片 + 队列)
|
||||||
|
|
||||||
run12/run13/run15 三次独立完整 PASS(6 段全 OK、零尖峰、`1/1 PASSED`、peer exit 0);
|
2026-09-22 重锁(P0-a/P0-b):同日 A/B 两档对照——**B1**(周期 500ms + per-recv 日志,= run15 条件,
|
||||||
下表 = run15(最终代码)基线。
|
复跑数值与 run15 基线重合 ±0.2%)→ **B2**(周期 200ms + per-recv 日志已删,= 当前代码)。
|
||||||
|
两档全部 `1/1 PASSED`、零尖峰、peer exit 0;下表 = **B2 基线**(A/B 差值即 P0-b 效果,P0-a 在干净链路上惰性)。
|
||||||
|
|
||||||
**MCU 侧(`[LAT]` 报告,安静档 `ftp_stress=0`)**
|
**MCU 侧(`[LAT]` 报告,安静档 `ftp_stress=0`)**
|
||||||
|
|
||||||
| 段(seg) | 测量含义 | med(min/max, n) | warn(med >) | crit(med >) |
|
| 段(seg) | 测量含义 | med(min/max, n) | warn(med >) | crit(med >) |
|
||||||
|---|---|---|---|---|
|
|---|---|---|---|---|
|
||||||
| `queue_rt_recv` | L5 对端灌 100B×20@50ms,MCU 非阻塞收的队列往返 | **5997µs**(5513/6033, 20) | 10ms | 100ms |
|
| `queue_rt_recv` | L5 对端灌 100B×20@50ms,MCU 非阻塞收的队列往返 | **1223µs**(1194/1223, 20) | 10ms | 100ms |
|
||||||
| `queue_rt_send` | L5 MCU 阻塞发 100B×20 | **987µs**(838/1209, 20) | 10ms | 100ms |
|
| `queue_rt_send` | L5 MCU 阻塞发 100B×20 | **988µs**(840/1216, 20) | 10ms | 100ms |
|
||||||
| `chunk_wait` | L3 16×4KB,芯片 chunk 内 SENBUF 等待(探针) | **219µs**(214/381, 64) | 10ms | 500ms(spike) |
|
| `chunk_wait` | L3 16×4KB,芯片 chunk 内 SENBUF 等待(探针) | **219µs**(213/378, 64) | 10ms | 500ms(spike) |
|
||||||
| `logtax_line` | 60 字符 printf @115200(本地) | **4396µs**(4394/4422, 10) | 10ms | 25ms |
|
| `logtax_line` | 60 字符 printf @115200(本地) | **4402µs**(4396/8779, 10) | 10ms | 25ms |
|
||||||
| `req2first_mcu` | L6 10B 请求到齐 → 回显发出 | **319µs**(308/338, 10) | 20ms | 200ms |
|
| `req2first_mcu` | L6 10B 请求到齐 → 回显发出 | **986µs**(979/1015, 10) | 20ms | 200ms |
|
||||||
| `fullframe_mcu` | L7 9B 请求 → 3209B 全帧发给芯片(netTask 内 4 分块) | **6028µs**(5991/6066, 10) | 50ms | 500ms |
|
| `fullframe_mcu` | L7 9B 请求 → 3209B 全帧发给芯片(netTask 内 4 分块) | **6614µs**(6546/6649, 10) | 50ms | 500ms |
|
||||||
|
|
||||||
|
(旧 run15 值对照:`queue_rt_recv` 5997 / `req2first_mcu` 319 / `fullframe_mcu` 6028µs——前两项差异均为
|
||||||
|
per-recv 日志移除的调度效应,非芯片行为变化:`queue_rt_recv` 差值 4.8ms ≈ 一行日志税;`req2first_mcu`
|
||||||
|
旧值 319µs 是日志阻塞期 netTask 恰在循环内(同轮命中)的幸运快值,新值 ≈ 1 个 netTask 循环周期(~1ms),
|
||||||
|
是隔离小帧发送的真实成本。`queue_rt_send`/`chunk_wait` 两档同值 = 与日志无关的段。)
|
||||||
|
|
||||||
**PC 侧端到端(peer JSON,含线路 + Windows 栈)**
|
**PC 侧端到端(peer JSON,含线路 + Windows 栈)**
|
||||||
|
|
||||||
| 段 | med(min/max) | 说明 |
|
| 段 | med(min/max) | 说明 |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| L6 端到端(op→收到回显) | 8.9ms(6.3/16.0) | 比 MCU 侧 `req2first_mcu` 多 ~7ms → PC/线路段 |
|
| L6 端到端(op→收到回显) | 3.9ms(1.7/12.0) | 比 MCU 侧 `req2first_mcu` 多 ~2.9ms → PC/线路段 |
|
||||||
| L7 首字节 | 11.3ms(7.8/16.5) | 同上量级 |
|
| L7 首字节 | 10.0ms(4.0/13.8) | 同上量级 |
|
||||||
| L7 全帧 3209B | 57.9ms(52.6/72.3) | 每帧固定 4 个 recv 批次;**尾批 137B 稳定迟到 ~50ms**(§7.3) |
|
| L7 全帧 3209B | 57.9ms(53.6/69.9) | 每帧固定 4 个 recv 批次;**尾批 137B 稳定迟到 ~50ms**(§7.3) |
|
||||||
| L7 CRC 校验 | 10/0 fail | 帧格式/CRC 正确(生产格式对齐后) |
|
| L7 CRC 校验 | 10/0 fail | 帧格式/CRC 正确(生产格式对齐后) |
|
||||||
| L3 flood 64KB(16×4KB) | 7.5~8.7ms/次 | ≈2ms/KB,满块无尾批惩罚 |
|
| L3 flood 64KB(16×4KB) | 7.5~8.7ms/次 | ≈2ms/KB,满块无尾批惩罚(MCU 发送路径,与 per-recv 日志无关) |
|
||||||
|
|
||||||
**M2 三个结论**:
|
**M2 三个结论**:
|
||||||
1. **安静档不存在 500ms 台阶**——六段全部 `verdict=OK`、零尖峰、p95≈med;会话级路径的 MCU 净成本
|
1. **安静档不存在重传台阶**——六段全部 `verdict=OK`、零尖峰、p95≈med;会话级路径的 MCU 净成本
|
||||||
量级 ~6ms(`queue_rt_recv`),与 netTask 轮询节拍同量级;
|
~1.2ms(`queue_rt_recv`,P0-b 删日志后;旧值 5.997ms 含 per-recv 日志税 4.4ms/行);
|
||||||
2. **芯片 chunk 级不是瓶颈**——`chunk_wait` ≈219µs ≈ 每 chunk SPI 成本(1.61ms)的 1/7,
|
2. **芯片 chunk 级不是瓶颈**——`chunk_wait` ≈219µs ≈ 每 chunk SPI 成本(1.61ms)的 1/7,
|
||||||
`SENBUF_FREE` 等待远小于 SPI 搬运本身;
|
`SENBUF_FREE` 等待远小于 SPI 搬运本身;
|
||||||
3. **L7 全帧的最后 137B 尾巴稳定迟到 ~50ms**(10/10 帧)——尾批主导整帧时长,MCU 侧发完 3209B 仅 6.0ms
|
3. **L7 全帧的最后 137B 尾巴稳定迟到 ~50ms**(10/10 帧)——尾批主导整帧时长,MCU 侧发完 3209B 仅 6.6ms
|
||||||
→ 延迟不在 MCU 发送路径,在芯片 TCP 尾段发送/对端 ACK 交互(M3 定性见 §7.3)。
|
→ 延迟不在 MCU 发送路径,在芯片 TCP 尾段发送/对端 ACK 交互(M3 定性见 §7.3)。
|
||||||
|
|
||||||
### 6.3 M3 段(Phase 14,生产路径 + 模拟器 Δ)
|
### 6.3 M3 段(Phase 14,生产路径 + 模拟器 Δ)
|
||||||
|
|
||||||
**MCU 侧(`[LAT]` 报告,真实 uiTask + `ui_net_sink` :7003;修复后代码)**
|
**MCU 侧(`[LAT]` 报告,真实 uiTask + `ui_net_sink` :7003;P0-a/P0-b 代码,2026-09-22 重锁)**
|
||||||
|
|
||||||
| 段(seg) | 测量含义 | 实测 med(min/max, n) | warn(med >) | crit(med >) |
|
| 段(seg) | 测量含义 | 实测 med(min/max, n) | warn(med >) | crit(med >) |
|
||||||
|---|---|---|---|---|
|
|---|---|---|---|---|
|
||||||
| `ui_loop`(L11) | uiTask 生产循环实测周期(渲染+轮询+osDelay(10)) | **10986µs**(10970/21000, 120) | 25ms | 50ms |
|
| `ui_loop`(L11) | uiTask 生产循环实测周期(渲染+轮询+osDelay(10)) | **10986µs**(10951/11022, 120) | 25ms | 50ms |
|
||||||
| `prod_cycle_mcu`(L8) | LCDMEM 取 1bpp + 组帧 + net_send 4 分块(不含 10ms 拾取拍) | **7142µs**(7111/7179, 50) | 20ms | 200ms |
|
| `prod_cycle_mcu`(L8) | LCDMEM 取 1bpp + 组帧 + net_send 4 分块(不含 10ms 拾取拍) | **6707µs**(6701/6757, 50) | 20ms | 200ms |
|
||||||
| `relisten`(L9) | 断线后 auto-relisten 全程(**修复后**:单次尝试 + netTask 延迟重试) | **89000µs ×3**(三次同值) | 100ms | 500ms |
|
| `relisten`(L9) | 断线后 auto-relisten 全程(**修复后**:单次尝试 + netTask 延迟重试) | **89000µs ×3**(三次同值) | 100ms | 500ms |
|
||||||
|
|
||||||
|
(旧值对照:`prod_cycle_mcu` 7142µs → 6707µs = P0-b 移除请求路径 per-recv 日志的 ~435µs;
|
||||||
|
`ui_loop`/`relisten` 两档同值 = 与日志无关的段。)
|
||||||
|
|
||||||
`relisten` 阈值说明:修复前 588000µs(Trap 09 `osDelay(500)` 忙等)→ crit 500ms 即 D10 指纹;
|
`relisten` 阈值说明:修复前 588000µs(Trap 09 `osDelay(500)` 忙等)→ crit 500ms 即 D10 指纹;
|
||||||
D10 修复后实测 89ms(= 30ms 重试间隔 + 约 60ms 芯片沉降),故 warn 放宽到 **100ms**、crit 保持 500ms
|
D10 修复后实测 89ms(= 30ms 重试间隔 + 约 60ms 芯片沉降),故 warn 放宽到 **100ms**、crit 保持 500ms
|
||||||
(仍能捕获"退回阻塞重试"的回归)。
|
(仍能捕获"退回阻塞重试"的回归)。
|
||||||
|
|
||||||
**PC 侧端到端(peer `--mode remo`,与模拟器 A/B)**
|
**PC 侧端到端(peer `--mode remo`,与模拟器 A/B)**
|
||||||
|
|
||||||
| 指标 | 真机(65 帧) | 模拟器(50 帧) | Δ(真机−模拟器) | 阈值 |
|
| 指标 | 真机(50 帧静默档) | 模拟器(50 帧) | Δ(真机−模拟器) | 阈值 |
|
||||||
|---|---|---|---|---|
|
|---|---|---|---|---|
|
||||||
| 帧周期 total | **66.0ms**(53.3/75.3) | **6.8ms**(0.6/13.1) | **+59.2ms** | ≤80ms |
|
| 帧周期 total | **61.6ms**(50.4/69.8) | **6.8ms**(0.6/13.1) | **+54.8ms** | ≤80ms |
|
||||||
| 首字节 | 13.9ms(8.5/19.1) | 6.7ms(0.5/13.0) | +7.2ms | — |
|
| 首字节 | 9.6ms(3.2/14.2) | 6.7ms(0.5/13.0) | +2.9ms | — |
|
||||||
| **尾批延迟 tail lag** | **52.6ms**(43.3/61.5) | **0.0ms**(0/0.1) | **+52.6ms** | — |
|
| **尾批延迟 tail lag** | **52.6ms**(44.1/59.1) | **0.0ms**(0/0.1) | **+52.6ms** | — |
|
||||||
| 帧 CRC / 位图非平凡 | 65/0、65/65 | 50/0、50/50 | — | 全通过 |
|
| 帧 CRC / 位图非平凡 | 50/0、50/50 | 50/0、50/50 | — | 全通过 |
|
||||||
| 连接 / 断开重连(+INIT) | 2.6ms / 23.5~34.7ms | 10.5ms / 32.0ms | — | ≤150ms |
|
| 连接 / 断开重连(+INIT) | 17.1ms / 22.4ms | 10.5ms / 32.0ms | — | ≤150ms |
|
||||||
|
|
||||||
|
(模拟器列为 2026-09-21 基线,模拟器工程本日未改动;真机列 = 2026-09-22 P0-a/P0-b 代码重测。
|
||||||
|
旧真机值:帧周期 66.0ms / 首字节 13.9ms / 重连 23.5~34.7ms。)
|
||||||
|
|
||||||
**压力档(`--ftp-stress`,E-02 复现;第 15 帧起 FTP 停留半登录态)**
|
**压力档(`--ftp-stress`,E-02 复现;第 15 帧起 FTP 停留半登录态)**
|
||||||
|
|
||||||
| 分桶 | n | med | p95 | max | 尖峰(≥500ms) |
|
| 分桶 | n | med | p95 | max | 尖峰(≥500ms) |
|
||||||
|---|---|---|---|---|---|
|
|---|---|---|---|---|---|
|
||||||
| quiet(0~14 帧) | 15 | 65.9ms | 75.8ms | 75.8ms | 0 |
|
| quiet(0~14 帧) | 15 | 59.9ms | 65.3ms | 65.3ms | 0 |
|
||||||
| stress(15~44 帧,**E-02 修复后**) | 30 | **74.7ms** | 90.8ms | **106.8ms** | **0** |
|
| stress(15~44 帧,**E-02 修复后 + P0-a/P0-b**) | 30 | **65.0ms** | 73.9ms | **133.5ms** | **0** |
|
||||||
|
|
||||||
(E-02 修复前 stress 档 med 17718ms、尖峰 1 次 = 17.7s 全网冻结;修复后零尖峰,见 §8.1。)
|
(E-02 修复前 stress 档 med 17718ms、尖峰 1 次 = 17.7s 全网冻结;修复后零尖峰,见 §8.1。
|
||||||
|
133.5ms 为压力启动瞬态单帧(FTP 连接建立与帧周期交叠),远低于 500ms 尖峰阈值。)
|
||||||
|
|
||||||
### 6.4 全段基线总表
|
### 6.4 全段基线总表
|
||||||
|
|
||||||
@@ -404,27 +420,29 @@ D10 修复后实测 89ms(= 30ms 重试间隔 + 约 60ms 芯片沉降),故
|
|||||||
|---|---|---|---|---|---|---|
|
|---|---|---|---|---|---|---|
|
||||||
| **L1** `spi_cmd_*` | SPI 字节命令(3 条) | 10 / 15 / 15µs | 10~16µs | 100 | 40/100µs | OK |
|
| **L1** `spi_cmd_*` | SPI 字节命令(3 条) | 10 / 15 / 15µs | 10~16µs | 100 | 40/100µs | OK |
|
||||||
| **L2** `spi_dma_*` | SPI DMA 读(4/64/1024/2048B) | 20 / 114 / **1611** / 3208µs | ±2µs | 100 | 见 §6.1 | OK |
|
| **L2** `spi_dma_*` | SPI DMA 读(4/64/1024/2048B) | 20 / 114 / **1611** / 3208µs | ±2µs | 100 | 见 §6.1 | OK |
|
||||||
| **L3** `chunk_wait` | 写发送缓冲 → `SENBUF_FREE`(每 chunk) | **219µs** | 213/381µs | 64 | 10ms/500ms | OK |
|
| **L3** `chunk_wait` | 写发送缓冲 → `SENBUF_FREE`(每 chunk) | **219µs** | 213/378µs | 64 | 10ms/500ms | OK |
|
||||||
| **L5** `queue_rt_recv` | 调用方 `net_recv(DONTWAIT)` 队列全程 | **5997µs** | 5513/6033µs | 20 | 10ms/100ms | OK |
|
| **L5** `queue_rt_recv` | 调用方 `net_recv(DONTWAIT)` 队列全程 | **1223µs** | 1194/1223µs | 20 | 10ms/100ms | OK |
|
||||||
| **L5** `queue_rt_send` | 调用方 `net_send` 队列全程 | **987µs** | 838/1209µs | 20 | 10ms/100ms | OK |
|
| **L5** `queue_rt_send` | 调用方 `net_send` 队列全程 | **988µs** | 840/1216µs | 20 | 10ms/100ms | OK |
|
||||||
| **L6** `req2first_mcu` | 10B 请求到齐 → 回显发出(MCU 侧) | **319µs** | 308/338µs | 10 | 20ms/200ms | OK |
|
| **L6** `req2first_mcu` | 10B 请求到齐 → 回显发出(MCU 侧) | **986µs** | 979/1015µs | 10 | 20ms/200ms | OK |
|
||||||
| **L7** `fullframe_mcu` | 9B 请求 → 3209B 全帧交给芯片 | **6028µs** | 5991/6066µs | 10 | 50ms/500ms | OK |
|
| **L7** `fullframe_mcu` | 9B 请求 → 3209B 全帧交给芯片 | **6614µs** | 6546/6649µs | 10 | 50ms/500ms | OK |
|
||||||
| **L8** `prod_cycle_mcu` | **生产路径**:LCDMEM 取帧+组帧+net_send(MCU 净成本) | **7142µs** | 7111/7179µs | 50 | 20ms/200ms | OK |
|
| **L8** `prod_cycle_mcu` | **生产路径**:LCDMEM 取帧+组帧+net_send(MCU 净成本) | **6707µs** | 6701/6757µs | 50 | 20ms/200ms | OK |
|
||||||
| **L10** `logtax_line` | 一行 60 字符 `printf` @115200 | **4396µs** | 4394/4422µs | 10 | 10ms/25ms | OK(D6 量化) |
|
| **L10** `logtax_line` | 一行 60 字符 `printf` @115200 | **4402µs** | 4396/8779µs | 10 | 10ms/25ms | OK(D6 量化) |
|
||||||
| **L11** `ui_loop` | uiTask 生产循环实测周期 | **10986µs** | 10970/21000µs | 120 | 25ms/50ms | OK |
|
| **L11** `ui_loop` | uiTask 生产循环实测周期 | **10986µs** | 10951/11022µs | 120 | 25ms/50ms | OK |
|
||||||
| **L9** `relisten` | 断线后自动重监听耗时(MCU 侧,修复后) | **89000µs** | 89000µs ×3 | 3 | 100ms/500ms | OK |
|
| **L9** `relisten` | 断线后自动重监听耗时(MCU 侧,修复后) | **89000µs** | 89000µs ×3 | 3 | 100ms/500ms | OK |
|
||||||
| **L4/L8** peer cycle | 生产客户端完整帧周期(发→收齐 3209B) | **66.0ms** | 53.3/77.4ms | 65 | — | 见 §7 |
|
| **L4/L8** peer cycle | 生产客户端完整帧周期(发→收齐 3209B) | **61.6ms** | 50.4/69.8ms | 50 | — | 见 §7 |
|
||||||
| **Δ** | `peer cycle(设备) − peer cycle(模拟器)` | **59.2ms** | — | 65/50 | ≤80ms | 见 §7.1 |
|
| **Δ** | `peer cycle(设备) − peer cycle(模拟器)` | **54.8ms** | — | 50/50 | ≤80ms | 见 §7.1 |
|
||||||
|
|
||||||
数据来源:L1/L2 = §6.1;其余 MCU 侧 = M2 run15 / M3 串口 `[LAT]` 行
|
数据来源:L1/L2 = §6.1;其余 MCU 侧 = M2 B2 档(200ms、per-recv 日志已删)/ M3 静默档的串口 `[LAT]` 行
|
||||||
(`m2_data/m2_serial_excerpt_run15.txt`、`m3_data/` 各 JSON);peer 侧 = `m3_data/*.json`。
|
(`m2_data/m2_quiet_r200.json`、`m3_data/m3_dev_quiet_r200.json`);A/B 对照档 = `m2_quiet_r500.json`(旧条件);
|
||||||
|
peer 侧 = `m3_data/m3_dev_*_r200.json`。旧 run15 摘录(`m2_serial_excerpt_run15.txt`)保留作 A/B 历史对照。
|
||||||
|
|
||||||
### 6.5 重锁规则
|
### 6.5 重锁规则
|
||||||
|
|
||||||
- warn ≈ 2×med,crit ≈ 2×warn(兼顾板间/温度漂移与回归灵敏度:SPI 时钟减半 → 超 warn;
|
- warn ≈ 2×med,crit ≈ 2×warn(兼顾板间/温度漂移与回归灵敏度:SPI 时钟减半 → 超 warn;
|
||||||
再减半 → 超 crit;DMA 超时 1s → 必超 crit);
|
再减半 → 超 crit;DMA 超时 1s → 必超 crit);
|
||||||
- M2 各段 warn ≈ 现状 ×1.7~10(保留回归灵敏度),crit 取"明显故障"档;
|
- M2 各段 warn ≈ 现状 ×1.7~10(保留回归灵敏度),crit 取"明显故障"档;
|
||||||
`chunk_wait` 以 500ms spike 为 crit(D1 重传指纹);
|
`chunk_wait` 以 500ms spike 为 crit(旧 500ms 周期的重传指纹;P0-a 后单次重传台阶 = 200ms,
|
||||||
|
低于 crit,弱网需看**连续台阶**而非单点);
|
||||||
- 换板/换固件重跑后,任何段超 warn → 重测确认后按实测重锁本表。
|
- 换板/换固件重跑后,任何段超 warn → 重测确认后按实测重锁本表。
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -435,25 +453,26 @@ D10 修复后实测 89ms(= 30ms 重试间隔 + 约 60ms 芯片沉降),故
|
|||||||
|
|
||||||
同一客户端(`latency_peer.py --mode remo`,100ms 节拍)对**真机 :7003** 与**PC 模拟器 :7003** 各跑一轮:
|
同一客户端(`latency_peer.py --mode remo`,100ms 节拍)对**真机 :7003** 与**PC 模拟器 :7003** 各跑一轮:
|
||||||
|
|
||||||
| 指标 | 真机(65 帧) | 模拟器(50 帧) | 差值 |
|
| 指标 | 真机(50 帧静默档) | 模拟器(50 帧) | 差值 |
|
||||||
|---|---|---|---|
|
|---|---|---|---|
|
||||||
| 帧周期 total(发请求 → 收齐 3209B) | **66.0ms**(53.3/75.3,max 77.4) | **6.8ms**(0.6/13.1,max 15.7) | **+59.2ms** |
|
| 帧周期 total(发请求 → 收齐 3209B) | **61.6ms**(50.4/69.8,max 69.8) | **6.8ms**(0.6/13.1,max 15.7) | **+54.8ms** |
|
||||||
| 首字节 first byte | 13.9ms(8.5/19.1) | 6.7ms(0.5/13.0) | +7.2ms |
|
| 首字节 first byte | 9.6ms(3.2/14.2) | 6.7ms(0.5/13.0) | +2.9ms |
|
||||||
| **尾批延迟 tail lag**(末批 → 首批) | **52.6ms**(43.3/61.5) | **0.0ms**(0/0.1) | **+52.6ms** |
|
| **尾批延迟 tail lag**(末批 → 首批) | **52.6ms**(44.1/59.1) | **0.0ms**(0/0.1) | **+52.6ms** |
|
||||||
| recv 批次数/帧 | 5(8B 头 + 1016 + 1024 + 1024 + **137**) | 2 | — |
|
| recv 批次数/帧 | 5(8B 头 + 1016 + 1024 + 1024 + **137**) | 2 | — |
|
||||||
|
|
||||||
**真机 66.0ms 的构成**(三段相加 ≈ 66.5,闭合):
|
**真机 61.6ms 的构成**(三段相加 ≈ 61.6,闭合):
|
||||||
|
|
||||||
```
|
```
|
||||||
[T+0] 客户端发 9B LCDMEM 请求
|
[T+0] 客户端发 9B LCDMEM 请求
|
||||||
[T+6.8ms] 实测推算:uiTask 10ms 轮询拾取 + netTask 调度(≈ L11 的一半)
|
[T+2.3ms] 实测推算:uiTask 10ms 轮询拾取 + netTask 调度(P0-b 删日志后 6.8→2.3ms)
|
||||||
[T+13.9ms] 首字节到达 = 6.8 + MCU 净处理 7.1ms(prod_cycle_mcu:取 1bpp + 组帧 + net_send 4 分块)
|
[T+9.6ms] 首字节到达 = 2.3 + MCU 净处理 6.7ms + 首批线路段
|
||||||
[T+66.0ms] 全帧收齐 —— 最后的 137B 尾巴比前三批(1024B×3,前 4ms 内到齐)晚 52.6ms
|
(prod_cycle_mcu:取 1bpp + 组帧 + net_send 4 分块)
|
||||||
|
[T+61.6ms] 全帧收齐 —— 最后的 137B 尾巴比前三批(1024B×3,前 4ms 内到齐)晚 52.6ms
|
||||||
```
|
```
|
||||||
|
|
||||||
- 前三批 1024B 在**首字节后约 4ms 内**全部到齐;
|
- 前三批 1024B 在**首字节后约 4ms 内**全部到齐;
|
||||||
- 第 4 批只有 **137B = 3209 − 3×1024**,比前三批晚 **52.6ms**(与负载无关:压力档 tail 中位 52.2ms);
|
- 第 4 批只有 **137B = 3209 − 3×1024**,比前三批晚 **52.6ms**(与负载无关:压力档 tail 中位 50.2ms);
|
||||||
- **MCU 侧把 3209B 全部交给芯片只要 7.1ms** → 慢的不在 MCU,在芯片协议栈的尾段发送/ACK 交互。
|
- **MCU 侧把 3209B 全部交给芯片只要 6.7ms** → 慢的不在 MCU,在芯片协议栈的尾段发送/ACK 交互。
|
||||||
|
|
||||||
### 7.2 交叉对照(三条独立证据 → 归因)
|
### 7.2 交叉对照(三条独立证据 → 归因)
|
||||||
|
|
||||||
@@ -513,8 +532,9 @@ D10 修复后实测 89ms(= 30ms 重试间隔 + 约 60ms 芯片沉降),故
|
|||||||
|
|
||||||
### 7.5 队列与调度:静默档不存在台阶
|
### 7.5 队列与调度:静默档不存在台阶
|
||||||
|
|
||||||
- **L5 队列往返**:收 5997µs / 发 987µs —— 与 netTask 10ms 轮询节拍同量级,属**调度周期**而非排队拥塞;
|
- **L5 队列往返**:收 1223µs / 发 988µs(P0-b 后;旧值 5997/987µs)——收段 ≈ 1 个 netTask 循环周期量级,
|
||||||
`queue_rt_send` 987µs ≈ 1 个 chunk(1611µs)量级,发送路径没有额外排队;
|
属**调度周期**而非排队拥塞(旧收值 5997µs 含 per-recv 日志税 4.4ms/行,已移除);
|
||||||
|
`queue_rt_send` 988µs ≈ 1 个循环周期,发送路径没有额外排队;
|
||||||
- **L3 chunk 级**:219µs ≈ 每 chunk SPI 成本的 1/7 → **芯片 TX 缓冲不是瓶颈**,SPI 搬运才是;
|
- **L3 chunk 级**:219µs ≈ 每 chunk SPI 成本的 1/7 → **芯片 TX 缓冲不是瓶颈**,SPI 搬运才是;
|
||||||
- **L11 uiTask 周期**:10986µs(= osDelay(10) + 渲染开销 ≈ 1ms)→ **LVGL 渲染只占约 1ms/帧**,
|
- **L11 uiTask 周期**:10986µs(= osDelay(10) + 渲染开销 ≈ 1ms)→ **LVGL 渲染只占约 1ms/帧**,
|
||||||
uiTask 不是延迟来源;
|
uiTask 不是延迟来源;
|
||||||
@@ -541,7 +561,7 @@ D10 修复后实测 89ms(= 30ms 重试间隔 + 约 60ms 芯片沉降),故
|
|||||||
| **D18** | 多打点站点共用全局探针窗口 → 跨段污染(测试工装) | **已修复** | 探针窗口串行全局,prod/relisten 段读出 ui_loop 的 ~11ms 值 | `lat_probe_add_seg()` 按段名过滤 | run17 对照 |
|
| **D18** | 多打点站点共用全局探针窗口 → 跨段污染(测试工装) | **已修复** | 探针窗口串行全局,prod/relisten 段读出 ui_loop 的 ~11ms 值 | `lat_probe_add_seg()` 按段名过滤 | run17 对照 |
|
||||||
| **D19** | Phase 14 漏调 `lat_time_init()` → DWT 恒 0 假绿(测试工装) | **已修复** | 时基未使能 → 三段全 0 却 `verdict=OK` | 补初始化 + `med==0` 判无效 | run16 对照 |
|
| **D19** | Phase 14 漏调 `lat_time_init()` → DWT 恒 0 假绿(测试工装) | **已修复** | 时基未使能 → 三段全 0 却 `verdict=OK` | 补初始化 + `med==0` 判无效 | run16 对照 |
|
||||||
| **D20** | FTP 开机首个会话的第 2 个数据连接失败(425) | **已定位未修**(暂缓) | 延迟 DISCONNECT 事件与首次 `net_accept` 的先后竞态(详见 §8.2) | 未实施;保留安全硬化(陈旧 DISCONNECT 甄别 + 2 字节状态缓冲越界修复);两次不稳定修法已回退 | 复现脚本 `test/ftp_regression.py` |
|
| **D20** | FTP 开机首个会话的第 2 个数据连接失败(425) | **已定位未修**(暂缓) | 延迟 DISCONNECT 事件与首次 `net_accept` 的先后竞态(详见 §8.2) | 未实施;保留安全硬化(陈旧 DISCONNECT 甄别 + 2 字节状态缓冲越界修复);两次不稳定修法已回退 | 复现脚本 `test/ftp_regression.py` |
|
||||||
| **E-02** | 空闲 FTP 控制连接头阻塞冻结 netTask(= §10.1 的 D3) | **已修复** | `lftpd` 控制行 `read_line` 走阻塞 `net_recv(0)`,netTask 是全部 socket 操作的唯一执行者 → 单会话可冻结全网最长 30s+ | 控制行/数据读改**分片有界读**(`net_recv_to` 5ms 片 + 每片 `vTaskDelay(1)` 让出,总预算仍 30s) | 受压帧 **17.7s → med 74.7ms / max 106.8ms,零尖峰** |
|
| **E-02** | 空闲 FTP 控制连接头阻塞冻结 netTask(= §10.1 的 D3) | **已修复** | `lftpd` 控制行 `read_line` 走阻塞 `net_recv(0)`,netTask 是全部 socket 操作的唯一执行者 → 单会话可冻结全网最长 30s+ | 控制行/数据读改**分片有界读**(`net_recv_to` 5ms 片 + 每片 `vTaskDelay(1)` 让出,总预算仍 30s) | 受压帧 **17.7s → med 65.0ms / max 133.5ms,零尖峰**(2026-09-22 P0-a/P0-b 代码下复验) |
|
||||||
|
|
||||||
### 8.2 D20 详情(已定位,未修复)
|
### 8.2 D20 详情(已定位,未修复)
|
||||||
|
|
||||||
@@ -612,7 +632,7 @@ sock4 auto-relisten ok / relisten retry ok ← 监听器随后自行恢复
|
|||||||
| 观测现象 | 首要指向 | 动作 |
|
| 观测现象 | 首要指向 | 动作 |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| 每帧都**稳定**慢 ≈150~300ms | 结构性基线(§10.1 的 D2/D5/D6/D8) | 跑 §5 的 Phase 13/14 对照基线 |
|
| 每帧都**稳定**慢 ≈150~300ms | 结构性基线(§10.1 的 D2/D5/D6/D8) | 跑 §5 的 Phase 13/14 对照基线 |
|
||||||
| **间歇**卡,且 ≈500ms 的整数倍 | **D1** 丢包重传 | Wireshark `tcp.analysis.retransmission`;查 PHY/网线/Wi-Fi |
|
| **间歇**卡,且 ≈200ms 的整数倍(旧固件 500ms) | **D1** 丢包重传 | Wireshark `tcp.analysis.retransmission`;查 PHY/网线/Wi-Fi |
|
||||||
| **间歇**整屏冻结数秒~数十秒 | **E-02** 头阻塞(已修)/ D10 重连(已修)/ 回归 | 查 FTP/对时会话是否挂着;核对 §8.1 修复在位 |
|
| **间歇**整屏冻结数秒~数十秒 | **E-02** 头阻塞(已修)/ D10 重连(已修)/ 回归 | 查 FTP/对时会话是否挂着;核对 §8.1 修复在位 |
|
||||||
| 只在开 FTP / 对时后卡 | E-02 + 单连接 socket 争用 | 临时停 ftpTask/timeSyncTask 对照 |
|
| 只在开 FTP / 对时后卡 | E-02 + 单连接 socket 争用 | 临时停 ftpTask/timeSyncTask 对照 |
|
||||||
| 换网口/换线/换 PC 就好 | D7 物理链路 | §10.2-S3 拓扑纪律 |
|
| 换网口/换线/换 PC 就好 | D7 物理链路 | §10.2-S3 拓扑纪律 |
|
||||||
@@ -622,8 +642,8 @@ sock4 auto-relisten ok / relisten retry ok ← 监听器随后自行恢复
|
|||||||
| 现象(段超标) | 首要怀疑 | 动作 |
|
| 现象(段超标) | 首要怀疑 | 动作 |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| L1/L2 超 crit | SPI 走线/PCB/SPI2 分频或 DMA 配置 | 对照 `docs/问题记录/CH395F_Trap_Records.md`;逻辑分析仪抓 SCK/CS |
|
| L1/L2 超 crit | SPI 走线/PCB/SPI2 分频或 DMA 配置 | 对照 `docs/问题记录/CH395F_Trap_Records.md`;逻辑分析仪抓 SCK/CS |
|
||||||
| L3 spike ≥500ms | **D1 重传 / D7 链路** | Wireshark `tcp.analysis.retransmission`;查 PHY 协商/网线/Wi-Fi |
|
| L3 spike ≥200ms(连续台阶;旧固件 500ms) | **D1 重传 / D7 链路** | Wireshark `tcp.analysis.retransmission`;查 PHY 协商/网线/Wi-Fi |
|
||||||
| L3 基线(非 spike)抬高 | 芯片发送路径 / 中断响应 | 对照 CH395F 手册 §5.17/5.18;`GET_CMD_STATUS` 逐段核对 |
|
| L3 基线(非 spike)抬高 | 芯片发送路径 / 中断响应 | 对照 CH395F 手册 §5.17/5.18(注意:状态寄存器**不被 SET 类命令更新**,`GET_CMD_STATUS` 恒读到 RESET 的 0x10 陈旧残留,2026-09-22 台架实证——不可用作 SET 值验收) |
|
||||||
| L5 压力档爆表 | **E-02 头阻塞(已修)** → 回归 | 定位触发源(阻塞 recv 的 FTP/对时);核对 `net_recv_to` 分片在位 |
|
| L5 压力档爆表 | **E-02 头阻塞(已修)** → 回归 | 定位触发源(阻塞 recv 的 FTP/对时);核对 `net_recv_to` 分片在位 |
|
||||||
| L5/L6 静默档抬高 | D5 调度(任务抢占/节拍) | 查任务优先级与 osDelay;`stack_report.py` 核对栈水位 |
|
| L5/L6 静默档抬高 | D5 调度(任务抢占/节拍) | 查任务优先级与 osDelay;`stack_report.py` 核对栈水位 |
|
||||||
| L6/L7 整体抬高且 L1~L5 正常 | 线路+PC 段(L4) | Wireshark 段间间隙;`Δ` 对照定位 MCU 侧净贡献 |
|
| L6/L7 整体抬高且 L1~L5 正常 | 线路+PC 段(L4) | Wireshark 段间间隙;`Δ` 对照定位 MCU 侧净贡献 |
|
||||||
@@ -633,6 +653,7 @@ sock4 auto-relisten ok / relisten retry ok ← 监听器随后自行恢复
|
|||||||
| **L7 一直超时 / peer 报 `l7_crc.fail`** | **D15**:帧格式不一致 / peer 超读 | 对照 `ui_net_sink.c` 的 `remo_send`/`remo_handle`(§8.1 D15) |
|
| **L7 一直超时 / peer 报 `l7_crc.fail`** | **D15**:帧格式不一致 / peer 超读 | 对照 `ui_net_sink.c` 的 `remo_send`/`remo_handle`(§8.1 D15) |
|
||||||
| **会话跑完一段后无限循环、peer 空等 300s** | **D16**:Phase 13 状态机迁移目标错 | 核对顺序 L5→L3→L10→L6→L7→DONE(§8.1 D16) |
|
| **会话跑完一段后无限循环、peer 空等 300s** | **D16**:Phase 13 状态机迁移目标错 | 核对顺序 L5→L3→L10→L6→L7→DONE(§8.1 D16) |
|
||||||
| **`[LAT]` 段行缺失/截断、wait-idle 判不出空闲** | **D12-b**:热路径日志洪水 | 删除 net 热路径逐调用日志(§8.1 D12-b) |
|
| **`[LAT]` 段行缺失/截断、wait-idle 判不出空闲** | **D12-b**:热路径日志洪水 | 删除 net 热路径逐调用日志(§8.1 D12-b) |
|
||||||
|
| **开机日志连续丢行**(含必检标记 `net init: OK` 等)但系统健康 | **日志并发竞态**:多任务并发 `printf` → 非重入 `fputc`/`HAL_UART_Transmit` 丢整行、UART 状态短暂卡住(2026-09-22 台架实证:boot 时 testTask 启动行与 netTask 日志并发 → 连续 4 行丢失、~2s 后自恢复) | 必现证据行采用"静默采集 + 延迟到安静窗口打印"模式(范例:`net_retrans_status_log` 在 PHY 行之后打印);根治 = S8 日志非阻塞/串行化(§10.2) |
|
||||||
| **`relisten` 段 FAIL、断线固定 ~588ms** | **D10** 回归(退回 `osDelay(500)`) | 核对 `net_relisten_try`/`net_relisten_retry_tick` 非阻塞重试在位(§8.1 D10) |
|
| **`relisten` 段 FAIL、断线固定 ~588ms** | **D10** 回归(退回 `osDelay(500)`) | 核对 `net_relisten_try`/`net_relisten_retry_tick` 非阻塞重试在位(§8.1 D10) |
|
||||||
| **远端显示整帧卡住十几秒后自恢复** | **E-02** 回归 | 核对 `net_recv_to` 5ms 分片 + 让出在位(§8.1 E-02) |
|
| **远端显示整帧卡住十几秒后自恢复** | **E-02** 回归 | 核对 `net_recv_to` 5ms 分片 + 让出在位(§8.1 E-02) |
|
||||||
| **INIT 应答帧字节数字段恒为 0** | **D17** 回归 | 核对 `remo_send_init` 发满 8B(§8.1 D17) |
|
| **INIT 应答帧字节数字段恒为 0** | **D17** 回归 | 核对 `remo_send_init` 发满 8B(§8.1 D17) |
|
||||||
@@ -640,7 +661,7 @@ sock4 auto-relisten ok / relisten retry ok ← 监听器随后自行恢复
|
|||||||
| **`[LAT]` 多段数值雷同 / 全 0 却 verdict=OK** | **D18/D19**(测试工装) | 核对 `lat_probe_add_seg` 段名过滤 + `lat_time_init` 调用 + `med==0` 判无效 |
|
| **`[LAT]` 多段数值雷同 / 全 0 却 verdict=OK** | **D18/D19**(测试工装) | 核对 `lat_probe_add_seg` 段名过滤 + `lat_time_init` 调用 + `med==0` 判无效 |
|
||||||
| **连接建立后 15~30s 无流量即被 RST** | **D13**:芯片空闲超时(芯片行为) | 客户端须容忍并重连(peer `--wait` 重试是正常路径) |
|
| **连接建立后 15~30s 无流量即被 RST** | **D13**:芯片空闲超时(芯片行为) | 客户端须容忍并重连(peer `--wait` 重试是正常路径) |
|
||||||
| **peer 重连后 MCU 状态滞留、新连接字节被吞** | **D14**:芯片静默回收 Socket | `net_resync_listen`/`net_relisten` 自愈路径核对 |
|
| **peer 重连后 MCU 状态滞留、新连接字节被吞** | **D14**:芯片静默回收 Socket | `net_resync_listen`/`net_relisten` 自愈路径核对 |
|
||||||
| L8 超而 L7 正常 | 生产路径附加成本(uiTask 节拍/LVGL/日志) | 对照 L10/L11 与 §10.1(渲染已排除;日志税待办 P0-b/S8) |
|
| L8 超而 L7 正常 | 生产路径附加成本(uiTask 节拍/LVGL/日志) | 对照 L10/L11 与 §10.1(渲染已排除;per-recv 日志已删,S8 非阻塞日志仍待办) |
|
||||||
| Δ 显著 >80ms | CH395F 栈净开销异常 | 回到 L1~L9 逐段排查 |
|
| Δ 显著 >80ms | CH395F 栈净开销异常 | 回到 L1~L9 逐段排查 |
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -651,23 +672,22 @@ sock4 auto-relisten ok / relisten retry ok ← 监听器随后自行恢复
|
|||||||
|
|
||||||
| # | 原因 | 实测验证(2026-09-22 台架) | 当前状态 |
|
| # | 原因 | 实测验证(2026-09-22 台架) | 当前状态 |
|
||||||
|---|---|---|---|
|
|---|---|---|---|
|
||||||
| D1 | CH395F TCP 重传固定 500ms 周期(8 次 = 4s 窗口;非 RTT 自适应) | 台架链路(有线 100M 全双工)三轮零重传尖峰 → 台架无丢包;**弱网(Wi-Fi/双工不匹配)仍是秒级卡顿首要嫌疑**,0.5/1.0/1.5s 台阶 = 500ms 粒度指纹 | **未修**(仍 `ch395f_set_retrans_count(8)` + `period(500)`);待办 P0-a(周期 200ms,需台架验证) |
|
| D1 | CH395F TCP 重传固定周期(非 RTT 自适应) | 台架链路(有线 100M 全双工)多轮零重传尖峰 → 台架无丢包;**弱网(Wi-Fi/双工不匹配)仍是秒级卡顿首要嫌疑**,200ms 粒度台阶 = 重传指纹(旧固件 500ms) | **已修(P0-a,2026-09-22)**:`NET_RETRANS_PERIOD_MS` 500→**200**(窗口 8×200=1.6s,原 4s)。台架验收说明:`GET_CMD_STATUS` 对 SET 类命令无判别力(500/2000ms 超限对照均读 0x10 陈旧残留,§9.2)→ 接受性以手册范围(≤1000ms)+ 全套件零回归(§6.2/§6.3)+ 与 500ms 行为同构为准 |
|
||||||
| D2 | 3209B × 1KB 发送 FIFO 停止等待(4 次串行分块握手,期间 netTask 全程占用) | `chunk_wait` 219µs/块 ≈ SPI 搬运成本的 1/7 → 握手本身**不是瓶颈**;每帧固定成本小(MCU 净 7.1ms) | 基线成本,可接受;根治 = 差量/RLE + 帧版本号(待办 S2) |
|
| D2 | 3209B × 1KB 发送 FIFO 停止等待(4 次串行分块握手,期间 netTask 全程占用) | `chunk_wait` 219µs/块 ≈ SPI 搬运成本的 1/7 → 握手本身**不是瓶颈**;每帧固定成本小(MCU 净 7.1ms) | 基线成本,可接受;根治 = 差量/RLE + 帧版本号(待办 S2) |
|
||||||
| D3 | netMsgQueue 头阻塞(= §8.1 E-02) | 已量化:一条空闲 FTP 控制连接冻结全网 17.7s | **已修复**(5ms 分片有界读 + 让出,§8.1) |
|
| D3 | netMsgQueue 头阻塞(= §8.1 E-02) | 已量化:一条空闲 FTP 控制连接冻结全网 17.7s | **已修复**(5ms 分片有界读 + 让出,§8.1) |
|
||||||
| D4 | PC 端延迟 ACK 与"每段等 ACK"停止等待交互 | `--ack-fast` 带内实验证实:关掉延迟 ACK 尾批自行消失(52→3.9ms) | **已客户端侧解决**(生产客户端关延迟 ACK/轻推兜底,§7.4) |
|
| D4 | PC 端延迟 ACK 与"每段等 ACK"停止等待交互 | `--ack-fast` 带内实验证实:关掉延迟 ACK 尾批自行消失(52→3.9ms) | **已客户端侧解决**(生产客户端关延迟 ACK/轻推兜底,§7.4) |
|
||||||
| D5 | uiTask 节拍:10ms 循环 + 每拍一次 64B recv + step 在 poll 前 | `ui_loop` 10986µs ≈ 设计值(渲染 ~1ms);拾取调度 ~6.8ms | 基线行为;可选优化 S7(poll 前置 + while 排空),低优先 |
|
| D5 | uiTask 节拍:10ms 循环 + 每拍一次 64B recv + step 在 poll 前 | `ui_loop` 10986µs ≈ 设计值(渲染 ~1ms);拾取调度 ~2.3ms(P0-b 删 per-recv 日志后,原 ~6.8ms) | 基线行为;可选优化 S7(poll 前置 + while 排空),低优先 |
|
||||||
| D6 | 阻塞式日志在关键路径(fputc 逐字节 @115200) | `logtax_line` 4396µs/行;`net_recv_locked` 的 per-recv 日志仍在 | **部分待办**(P0-b:删/降级 per-recv 日志;S8:日志改非阻塞) |
|
| D6 | 阻塞式日志在关键路径(fputc 逐字节 @115200) | `logtax_line` 4402µs/行;per-recv 日志已删(2026-09-22):`queue_rt_recv` 5997→1223µs、帧周期 66.0→61.6ms、首字节 13.9→9.6ms | **部分已修(P0-b,2026-09-22)**;S8 非阻塞日志仍待办(同时是开机日志并发丢行 §9.2 的根治项) |
|
||||||
| D7 | 物理链路:强制 100M 全双工 vs 交换机自协商 → 双工不匹配静默丢包 | 台架 `PHY: 100M FULL` 成立、零尖峰 → 台架干净 | 现场排查项(S3):核对开机日志 PHY 行 + 交换机端口强制全双工 + 验证 PC 有线直连 |
|
| D7 | 物理链路:强制 100M 全双工 vs 交换机自协商 → 双工不匹配静默丢包 | 台架 `PHY: 100M FULL` 成立、零尖峰 → 台架干净 | 现场排查项(S3):核对开机日志 PHY 行 + 交换机端口强制全双工 + 验证 PC 有线直连 |
|
||||||
| D8 | 客户端固定成本:100ms 拉取节拍、按键后不立即取帧、1bpp→PNG→base64→WS 编码链 | 生产客户端优化后:帧耗时 20.7ms、显示帧率 ~9fps | 部分已优化(延迟确认抑制已上线);其余待办 S9(按键后立即取帧/不传 PNG/自适应节拍)——客户端仓库 |
|
| D8 | 客户端固定成本:100ms 拉取节拍、按键后不立即取帧、1bpp→PNG→base64→WS 编码链 | 生产客户端优化后:帧耗时 20.7ms、显示帧率 ~9fps | 部分已优化(延迟确认抑制已上线);其余待办 S9(按键后立即取帧/不传 PNG/自适应节拍)——客户端仓库 |
|
||||||
| D9 | LVGL 全量渲染(RENDER_MODE_FULL)+ uiTask BelowNormal 易被抢占 | `ui_loop` 显示渲染仅 ~1ms/帧 | **已排除**(非瓶颈;调优先级/栈无收益,§7.5) |
|
|
||||||
| D10 | 断线重连路径 `osDelay(500)`(netTask 忙等) | 已量化:relisten 588ms×3 且冻结 netTask | **已修复**(非阻塞延迟重试 → 89ms,§8.1) |
|
|
||||||
|
|
||||||
### 10.2 待办优化项(按性价比排序,均未实施)
|
### 10.2 待办优化项(按性价比排序,均未实施)
|
||||||
|
|
||||||
1. **D20 数据 Socket 轮换**(§8.2)——唯一未修的功能性缺陷;现场可用客户端重试 425 规避;
|
1. **D20 数据 Socket 轮换**(§8.2)——唯一未修的功能性缺陷;现场可用客户端重试 425 规避;
|
||||||
2. **P0-a** `ch395f_set_retrans_period(500) → 200`(一行级;治 D1 症状:单次丢包代价 500→200ms;
|
2. **~~P0-a~~ 已实施(2026-09-22)**:`NET_RETRANS_PERIOD_MS` 500→200 + `GET_CMD_STATUS` 一次性验收检查
|
||||||
总窗口 8×200=1.6s,链路真断时判失败更快;手册 §5.18 允许 ≤1000ms,最小值未标注 → **需台架验证 200 被接受**);
|
(实测该状态对 SET 类命令无判别力,见 §10.1 D1);全套件复验零回归(§6.2/§6.3);
|
||||||
3. **P0-b** 删除/降级 `net_socket.c` 的 per-recv `DBG_INFO`(每帧省 ~4.4ms netTask 阻塞,顺带减 syslog 噪声);
|
3. **~~P0-b~~ 已实施(2026-09-22)**:删除 `net_socket.c` per-recv `DBG_INFO`;实测 `queue_rt_recv` −80%
|
||||||
|
(5997→1223µs)、生产帧周期 −4.4ms(66.0→61.6ms)、首字节 −4.3ms(13.9→9.6ms);
|
||||||
4. **S1** 超时参数分档:`NET_SEND/RECV_TIMEOUT_MS` 全局一刀切 → 按服务分离(远显短超时+非阻塞,FTP 保留长超时);
|
4. **S1** 超时参数分档:`NET_SEND/RECV_TIMEOUT_MS` 全局一刀切 → 按服务分离(远显短超时+非阻塞,FTP 保留长超时);
|
||||||
5. **S2** 差量/RLE + 帧版本号 + 由拉改推(**根治,收益最大**:典型变化 <100B → 单段一帧,延迟 ≈ 一个 RTT;
|
5. **S2** 差量/RLE + 帧版本号 + 由拉改推(**根治,收益最大**:典型变化 <100B → 单段一帧,延迟 ≈ 一个 RTT;
|
||||||
稳态带宽 32KB/s → ≈0;D1 影响面 4 段 → 1 段;新命令走同一帧格式与 CRC,旧客户端兼容);
|
稳态带宽 32KB/s → ≈0;D1 影响面 4 段 → 1 段;新命令走同一帧格式与 CRC,旧客户端兼容);
|
||||||
@@ -682,6 +702,10 @@ sock4 auto-relisten ok / relisten retry ok ← 监听器随后自行恢复
|
|||||||
11. **M4**(可选)`test/run_latency_test.py` 一键编排(open/clear/flash/wait-idle/peer/collect/merge/verdict)——待排期;
|
11. **M4**(可选)`test/run_latency_test.py` 一键编排(open/clear/flash/wait-idle/peer/collect/merge/verdict)——待排期;
|
||||||
12. **M5**(可选,在役设备)非独占采样器:事件触发、10s 旁路打点入 syslog——设计预留;
|
12. **M5**(可选,在役设备)非独占采样器:事件触发、10s 旁路打点入 syslog——设计预留;
|
||||||
13. 协议补位(尾批退路,仅当客户端无法改动时;见 §7.4)。
|
13. 协议补位(尾批退路,仅当客户端无法改动时;见 §7.4)。
|
||||||
|
14. **日志并发保护(2026-09-22 新增,与 S8 同源、优先级上调)**:开机多任务并发 `printf` 丢整行
|
||||||
|
(实测 §9.2:必检标记 `net init: OK` 曾被竞态吞掉 → 影响开机验收可靠性)。过渡:必现证据行按
|
||||||
|
"静默采集 + 延迟到安静窗口打印"模式(范例 `net_retrans_status_log`);根治 = S8(串口 TX 环形缓冲
|
||||||
|
+ 中断/DMA,溢出丢弃策略需定义)。
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -708,12 +732,16 @@ sock4 auto-relisten ok / relisten retry ok ← 监听器随后自行恢复
|
|||||||
| `m2_data/m2_quiet.json` | M2 安静档 peer 侧(run15 最终代码):L3~L7 端到端 + 逐帧尾批明细 |
|
| `m2_data/m2_quiet.json` | M2 安静档 peer 侧(run15 最终代码):L3~L7 端到端 + 逐帧尾批明细 |
|
||||||
| `m2_data/m2_quiet_run13.json` | M2 run13(独立 PASS 对照) |
|
| `m2_data/m2_quiet_run13.json` | M2 run13(独立 PASS 对照) |
|
||||||
| `m2_data/m2_quiet_run14.json` | M2 run14(仅 peer 侧有效;MCU 侧因热路径日志洪水不作基线,D12-b) |
|
| `m2_data/m2_quiet_run14.json` | M2 run14(仅 peer 侧有效;MCU 侧因热路径日志洪水不作基线,D12-b) |
|
||||||
| `m2_data/m2_serial_excerpt_run13/15.txt` | M2 串口 `[LAT]`/`[NET]` 证据片段 |
|
| `m2_data/m2_serial_excerpt_run13/15.txt` | M2 串口 `[LAT]`/`[NET]` 证据片段(旧基线,A/B 历史对照) |
|
||||||
|
| `m2_data/m2_quiet_r500.json` | 2026-09-22 A/B 对照档 B1(500ms + per-recv 日志 = 旧基线条件;复跑与 run15 重合 ±0.2%) |
|
||||||
|
| `m2_data/m2_quiet_r200.json` | **2026-09-22 M2 重锁基线** B2(200ms、per-recv 日志已删 = 当前代码) |
|
||||||
| `m2_data/README.md` | M2 数据说明(逐帧尾批明细、方法学约束) |
|
| `m2_data/README.md` | M2 数据说明(逐帧尾批明细、方法学约束) |
|
||||||
| `m3_data/m3_dev_quiet.json` | 真机 65 帧生产周期(D10/E-02/D17 修复前基线) |
|
| `m3_data/m3_dev_quiet.json` | 真机 65 帧生产周期(D10/E-02/D17 修复前基线) |
|
||||||
| `m3_data/m3_dev_quiet_fixed.json` | 真机 65 帧(修复后:帧周期 65.7ms、relisten OK、INIT framebytes=3200) |
|
| `m3_data/m3_dev_quiet_fixed.json` | 真机 65 帧(修复后:帧周期 65.7ms、relisten OK、INIT framebytes=3200) |
|
||||||
| `m3_data/m3_dev_stress.json` | E-02 压力档(修复前:17.7s 尖峰) |
|
| `m3_data/m3_dev_stress.json` | E-02 压力档(修复前:17.7s 尖峰) |
|
||||||
| `m3_data/m3_dev_stress_fixed.json` | E-02 压力档(修复后:med 74.7ms / max 106.8ms,零尖峰) |
|
| `m3_data/m3_dev_stress_fixed.json` | E-02 压力档(修复后:med 74.7ms / max 106.8ms,零尖峰) |
|
||||||
|
| `m3_data/m3_dev_quiet_r200.json` | **2026-09-22 M3 静默档重锁基线**(50 帧,P0-a/P0-b 代码:帧周期 61.6ms) |
|
||||||
|
| `m3_data/m3_dev_stress_r200.json` | **2026-09-22 M3 压力档重锁基线**(45 帧,第 15 帧起 FTP stress:med 65.0ms / max 133.5ms,零尖峰) |
|
||||||
| `m3_data/m3_sim_quiet.json` | 模拟器基线 50 帧(Δ 对照,tail=0) |
|
| `m3_data/m3_sim_quiet.json` | 模拟器基线 50 帧(Δ 对照,tail=0) |
|
||||||
| `m3_data/m3_tail_ackprobe.json` | 尾批实验 ①:帧未收齐即回 1 字节(捎带 ACK)→ tail 3.9ms |
|
| `m3_data/m3_tail_ackprobe.json` | 尾批实验 ①:帧未收齐即回 1 字节(捎带 ACK)→ tail 3.9ms |
|
||||||
| `m3_data/m3_tail_ackfast.json` | 尾批实验 ②:Windows 立即 ACK(不发探测字节)→ tail 3.9ms |
|
| `m3_data/m3_tail_ackfast.json` | 尾批实验 ②:Windows 立即 ACK(不发探测字节)→ tail 3.9ms |
|
||||||
|
|||||||
+2
-2
@@ -63,9 +63,9 @@ extern "C" {
|
|||||||
//#define ENABLE_PHASE10_TESTS /* [网] 边界条件测试 */
|
//#define ENABLE_PHASE10_TESTS /* [网] 边界条件测试 */
|
||||||
//#define ENABLE_PHASE11_TESTS /* [网] KeepAlive 超时断开测试 */
|
//#define ENABLE_PHASE11_TESTS /* [网] KeepAlive 超时断开测试 */
|
||||||
/* ---- 链路时延基线(M1;分段/阈值见 docs/测试说明/链路延迟测试说明.md)---- */
|
/* ---- 链路时延基线(M1;分段/阈值见 docs/测试说明/链路延迟测试说明.md)---- */
|
||||||
//#define ENABLE_PHASE12_TESTS /* [硬] SPI 字节命令 / DMA 时延基线(L1/L2,无需 PC)—— M1 已完成,基线见说明文档 §4.1 */
|
//#define ENABLE_PHASE12_TESTS /* [硬] SPI 字节命令 / DMA 时延基线(L1/L2,无需 PC)—— M1 已完成,基线见说明文档 §6.1 */
|
||||||
/* ---- 链路时延(M2/M3;分段/阈值见 docs/测试说明/链路延迟测试说明.md)---- */
|
/* ---- 链路时延(M2/M3;分段/阈值见 docs/测试说明/链路延迟测试说明.md)---- */
|
||||||
//#define ENABLE_PHASE13_TESTS /* [网] 芯片 + 队列时延(L3~L7/L10,需 PC peer)—— M2 已完成,基线见说明文档 §4.2 */
|
//#define ENABLE_PHASE13_TESTS /* [网] 芯片 + 队列时延(L3~L7/L10,需 PC peer)—— M2 已完成,基线见说明文档 §6.2 */
|
||||||
#define ENABLE_PHASE14_TESTS /* [网] 生产路径时延(L8~L11 + 模拟器 Δ)—— M3,需 peer --mode remo(:7003) */
|
#define ENABLE_PHASE14_TESTS /* [网] 生产路径时延(L8~L11 + 模拟器 Δ)—— M3,需 peer --mode remo(:7003) */
|
||||||
|
|
||||||
#if defined(ENABLE_PHASE1_TESTS) || defined(ENABLE_PHASE2_TESTS) || \
|
#if defined(ENABLE_PHASE1_TESTS) || defined(ENABLE_PHASE2_TESTS) || \
|
||||||
|
|||||||
+4
-5
@@ -23,11 +23,10 @@ extern "C" {
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
/* === 选择当前构建的测试套件(三选一,或都注释 = 正常产品构建)===
|
/* === 选择当前构建的测试套件(三选一,或都注释 = 正常产品构建)===
|
||||||
* 2026-09-22:M2(链路时延 Phase 13,NET 层,需 PC peer)交付 ——
|
* 2026-09-22:M1~M3(链路时延 Phase 12/13/14,阶段表见说明文档 §4.2)交付 ——
|
||||||
* 当前启用 CH395F 套件 + Phase 13(独立运行,勿与其他 Phase 混选)。
|
* 当前启用 CH395F 套件 + Phase 14(生产路径时延,M3 基线已锁定,2026-09-22 重锁)。
|
||||||
* 执行:先起 test/latency_peer.py --mode net --port 8080,再 @test 烧录。
|
* 恢复产品构建 = 注释掉下方 TEST_SUITE_CH395F 一行(ch395f_test.h 的阶段宏
|
||||||
* 恢复产品构建 = 注释掉下面两行(TEST_SUITE_CH395F 与 ch395f_test.h 的
|
* 仅在套件启用时生效,无需另改)。详见 docs/测试说明/链路延迟测试说明.md §4.2/§5。 */
|
||||||
* ENABLE_PHASE13_TESTS)。详见 docs/测试说明/链路延迟测试说明.md §5.2。 */
|
|
||||||
#define TEST_SUITE_CH395F
|
#define TEST_SUITE_CH395F
|
||||||
//#define TEST_SUITE_STORAGE
|
//#define TEST_SUITE_STORAGE
|
||||||
//#define TEST_SUITE_GD5F
|
//#define TEST_SUITE_GD5F
|
||||||
|
|||||||
Reference in New Issue
Block a user