fix(tcp): MUX模式网口失联 — 对端关闭时用tcp_abort替代tcp_close避免TIME_WAIT耗尽pcb池

根因: tcp_close()将对端关闭的pcb推入TIME_WAIT(120s), 占用MEMP_TCP_PCB池(仅4个),
多连接同时断开后pcb池耗尽, tcp_new()返回NULL, 新连接无法建立直到120s超时释放。

核心修复:
- tcp_server/client: 对端关闭(p=NULL)时tcp_abort替代tcp_close, pcb立即释放
- ch390_runtime: PKT_ERR恢复强制OR上RCR_RXEN(与WCH官方一致)
- ch390_runtime: TX连续超时3次自动emergency reset
- ch390_runtime: 每5秒health_check读VID验证芯片存活
- main: App_StartLinksIfNeeded失败时不标记g_links_started, 允许重试
- main: MUX逐帧RTT printf改为#if DEBUG门控, 减少主循环延迟
- uart_trans: MUX帧解析改为先搜0x7E再消费header, 非法帧只丢1字节
This commit is contained in:
2026-04-14 03:44:26 +08:00
parent efb88ea367
commit 31a3da48fa
7 changed files with 151 additions and 19 deletions
+28 -2
View File
@@ -39,6 +39,7 @@
#define LED_PORT GPIOC
#define APP_ROUTE_BUFFER_SIZE 256u
#define STACK_GUARD_WORD 0xA5A5A5A5u
#define APP_HEALTH_CHECK_INTERVAL_MS 5000u
/* USER CODE END PD */
/* Private variables ---------------------------------------------------------*/
@@ -175,15 +176,27 @@ static void App_ConfigureLinks(const device_config_t *cfg)
static void App_StartLinksIfNeeded(void)
{
int any_failed;
if ((g_links_started != 0u) || !netif_is_link_up(&ch390_netif)) {
return;
}
any_failed = 0;
for (uint8_t i = 0; i < TCP_SERVER_INSTANCE_COUNT; ++i) {
(void)tcp_server_start(i);
if (tcp_server_start(i) != 0) {
any_failed = 1;
}
}
for (uint8_t i = 0; i < TCP_CLIENT_INSTANCE_COUNT; ++i) {
(void)tcp_client_connect(i);
if (tcp_client_connect(i) != 0) {
any_failed = 1;
}
}
if (any_failed) {
SEGGER_RTT_WriteString(0, "NET links start partially failed, will retry\r\n");
return;
}
g_links_started = 1u;
@@ -343,7 +356,9 @@ static void App_RouteMuxUartTraffic(void)
const device_config_t *cfg = config_get();
while (uart_mux_try_extract_frame(UART_CHANNEL_U0, &frame)) {
#if defined(DEBUG) && (DEBUG != 0)
SEGGER_RTT_printf(0, "Mux frame from UART0: src_id=%u dst_mask=0x%02X len=%u\r\n", frame.src_id, frame.dst_mask, frame.payload_len);
#endif
if (frame.dst_mask == 0u) {
at_result_t result;
char *response_text = (char *)&g_mux_response_frame[5];
@@ -382,7 +397,9 @@ static void App_RouteMuxUartTraffic(void)
}
while (uart_mux_try_extract_frame(UART_CHANNEL_U1, &frame)) {
#if defined(DEBUG) && (DEBUG != 0)
SEGGER_RTT_printf(0, "Mux frame from UART1: src_id=%u dst_mask=0x%02X len=%u\r\n", frame.src_id, frame.dst_mask, frame.payload_len);
#endif
if (frame.dst_mask == 0u) {
at_result_t result;
char *response_text = (char *)&g_mux_response_frame[5];
@@ -423,6 +440,9 @@ static void App_RouteMuxUartTraffic(void)
static void App_Poll(void)
{
static uint32_t s_health_check_tick;
uint32_t now;
ethernetif_poll();
ethernetif_check_link();
sys_check_timeouts();
@@ -440,6 +460,12 @@ static void App_Poll(void)
App_RouteRawUartTraffic();
}
now = HAL_GetTick();
if ((now - s_health_check_tick) >= APP_HEALTH_CHECK_INTERVAL_MS) {
s_health_check_tick = now;
ch390_runtime_health_check(&ch390_netif);
}
if (config_is_reset_requested()) {
config_clear_reset_requested();
NVIC_SystemReset();