ppp拨号优化,关闭协议压缩,地址压缩,MagicNumber
author孙春阳 <snickersun@163.com>
Fri, 19 Sep 2025 06:11:03 +0000 (14:11 +0800)
committer孙春阳 <snickersun@163.com>
Fri, 19 Sep 2025 06:11:03 +0000 (14:11 +0800)
code/sdk/zhihui/ppp/CMakeLists.txt
code/sdk/zhihui/ppp/include/ppp_config.h
code/sdk/zhihui/ppp/include/ppp_lwip.h
code/sdk/zhihui/ppp/src/ppp_at_handler.c
code/sdk/zhihui/ppp/src/ppp_lwip.c
code/sdk/zhihui/ppp/src/ppp_lwip_thread.c

index 48f198d..c5c3d3c 100644 (file)
@@ -73,6 +73,12 @@ set(PUBLIC_DEFINES
     IPCP_DEBUG=LWIP_DBG_ON
     # 确保IPCP功能完全启用
     PPP_IPV4_SUPPORT=1
+    # 启用LCP相关功能
+    LCP_SUPPORT=1
+    LCP_ECHOINTERVAL=30
+    LCP_MAXECHOFAILS=3
+    # 启用网络接口状态回调
+    LWIP_NETIF_STATUS_CALLBACK=1
     # PPP_OPTIONS=1 
     SUPPORT_PPP_SERVICE
     SUPPORT_AT_PPP
index 65730f1..260c7c2 100644 (file)
@@ -27,7 +27,7 @@ extern "C" {
 #define SIO_UART_IRQ_NUM            UART_0_IRQN         // UART IRQ引脚
 #endif
 
-#define PPP_UART_BAUDRATE          2000000
+#define PPP_UART_BAUDRATE          1000000
 
 /* 支持的波特率列表(自适应模式) */
 #define PPP_BAUDRATE_AUTO_LIST      {9600, 57600, 115200}
index b5c44bc..a2da4ef 100644 (file)
@@ -61,7 +61,7 @@ ppp_error_t ppp_lwip_init(const ppp_lwip_config_t *config);
 /**
  * @brief 反初始化PPP lwIP集成
  */
-void ppp_lwip_deinit(void);
+ppp_error_t ppp_lwip_deinit(void);
 
 /**
  * @brief 连接PPP
@@ -126,6 +126,19 @@ const char* ppp_lwip_get_gateway(void);
  * @return DNS地址字符串(静态缓冲区,非线程安全)
  */
 const char* ppp_lwip_get_dns(void);
+
+/**
+ * @brief PPP连接保活检查
+ * @return true 连接正常,false 连接异常
+ */
+bool ppp_lwip_check_connection_alive(void);
+
+/**
+ * @brief 触发PPP连接保活测试
+ * @return PPP_ERR_OK 成功,其他值失败
+ */
+ppp_error_t ppp_lwip_trigger_keepalive(void);
+
 #ifdef __cplusplus
 }
 #endif
index d8877aa..e16d9b9 100644 (file)
@@ -93,11 +93,11 @@ void ppp_at_handler_deinit(void)
 /**
  * @brief 执行波特率自适应握手
  *
- * 进入自适应波特率,证明2000000没有正常工作,需要先reset,等5秒,开始设置自动握手的第一个波特率,
+ * 进入自适应波特率,证明1000000没有正常工作,需要先reset,等5秒,开始设置自动握手的第一个波特率,
  * 读取所有缓存数据丢掉,下达at指令,等待结果,重试3次,如果不成功,就设置第二个波特率,读取所有缓存数据丢掉,
  * 下达at指令,等结果,重试3次,直至第三个波特率检测。如果都没有成功,则返回失败。
- * 如果任何一次at指令返回正确ok,直接在当前设置下,下达指 AT+IPR 配置 2000000 波特率,并返回成功。
- * 设置当前波特率为2000000,再次reset 模组,让其自动工作在 2000000波特率下。
+ * 如果任何一次at指令返回正确ok,直接在当前设置下,下达指 AT+IPR 配置 1000000 波特率,并返回成功。
+ * 设置当前波特率为1000000,再次reset 模组,让其自动工作在 1000000波特率下。
  */
 ppp_error_t ppp_at_baudrate_handshake(void)
 {
@@ -105,10 +105,10 @@ ppp_error_t ppp_at_baudrate_handshake(void)
         return PPP_ERR_INVALID_PARAM;
     }
 
-    PPP_DEBUG_INFO("Starting baudrate handshake (prove 2000000 not working, then try auto handshake)");
+    PPP_DEBUG_INFO("Starting baudrate handshake (prove 1000000 not working, then try auto handshake)");
 
-    // 1. 先reset模组,证明2000000没有正常工作
-    PPP_DEBUG_DEBUG("Resetting module to prove 2000000 baudrate is not working...");
+    // 1. 先reset模组,证明1000000没有正常工作
+    PPP_DEBUG_DEBUG("Resetting module to prove 1000000 baudrate is not working...");
     ppp_power_reset_cat1();
     osal_msleep(5000);
 
@@ -155,25 +155,25 @@ ppp_error_t ppp_at_baudrate_handshake(void)
             if (ret == PPP_ERR_OK) {
                 PPP_DEBUG_INFO("AT command successful at baudrate %u", baudrate);
 
-                // 在当前波特率下,设置AT+IPR=2000000
+                // 在当前波特率下,设置AT+IPR=1000000
                 char ipr_cmd[32];
-                snprintf_s(ipr_cmd, sizeof(ipr_cmd), sizeof(ipr_cmd) - 1, "AT+IPR=2000000");
-                PPP_DEBUG_DEBUG("Setting module baudrate to 2000000 with: %s", ipr_cmd);
+                snprintf_s(ipr_cmd, sizeof(ipr_cmd), sizeof(ipr_cmd) - 1, "AT+IPR=1000000");
+                PPP_DEBUG_DEBUG("Setting module baudrate to 1000000 with: %s", ipr_cmd);
 
                 ppp_at_response_t ipr_response;
                 ppp_error_t ipr_ret = ppp_at_send_command(ipr_cmd, "OK", 3000, &ipr_response);
                 if (ipr_ret != PPP_ERR_OK) {
-                    PPP_DEBUG_ERROR("Failed to set module baudrate to 2000000 (AT+IPR)");
+                    PPP_DEBUG_ERROR("Failed to set module baudrate to 1000000 (AT+IPR)");
                     return PPP_ERR_AT_FAILED;
                 }
 
                 ppp_at_set_baudrate(PPP_UART_BAUDRATE);
 
-                // 再次reset模组,让其自动工作在2000000波特率下
-                PPP_DEBUG_DEBUG("Resetting module again to switch to 2000000 baudrate...");
+                // 再次reset模组,让其自动工作在1000000波特率下
+                PPP_DEBUG_DEBUG("Resetting module again to switch to 1000000 baudrate...");
                 ppp_power_reset_cat1();               
                 osal_msleep(5000);
-                PPP_DEBUG_INFO("Baudrate handshake successful, now at 2000000 baud");
+                PPP_DEBUG_INFO("Baudrate handshake successful, now at 1000000 baud");
                 return PPP_ERR_OK;
             } else {
                 PPP_DEBUG_WARN("AT command failed at baudrate %u, retry %d/3 (error: %d)", baudrate, retry + 1, ret);
@@ -464,10 +464,10 @@ ppp_error_t ppp_at_complete_dial_sequence(const char *apn)
     char cgdcont_cmd[128];
     if (apn && strlen(apn) > 0) {
         snprintf_s(cgdcont_cmd, sizeof(cgdcont_cmd), sizeof(cgdcont_cmd) - 1, 
-                   "AT+CGDCONT=3,\"IP\",\"%s\"", apn);
+                   "AT+CGDCONT=2,\"IP\",\"%s\"", apn);
     } else {
         snprintf_s(cgdcont_cmd, sizeof(cgdcont_cmd), sizeof(cgdcont_cmd) - 1, 
-                   "AT+CGDCONT=3,\"IP\"");
+                   "AT+CGDCONT=2,\"IP\",\"CMNET\"");
     }
     
     ret = ppp_at_send_command(cgdcont_cmd, "OK", 5000, &response);
@@ -477,21 +477,21 @@ ppp_error_t ppp_at_complete_dial_sequence(const char *apn)
     }
     PPP_DEBUG_INFO("PDP context set successfully");
     
-    // 4.5. 设置网络注册模式(确保网络连接稳定)
-    ret = ppp_at_send_command("AT+CREG=1", "OK", 5000, &response);
-    if (ret != PPP_ERR_OK) {
-        PPP_DEBUG_WARN("Failed to set network registration mode, continuing anyway");
-    } else {
-        PPP_DEBUG_INFO("Network registration mode set successfully");
-    }
+    // // 4.5. 设置网络注册模式(确保网络连接稳定)
+    // ret = ppp_at_send_command("AT+CREG=1", "OK", 5000, &response);
+    // if (ret != PPP_ERR_OK) {
+    //     PPP_DEBUG_WARN("Failed to set network registration mode, continuing anyway");
+    // } else {
+    //     PPP_DEBUG_INFO("Network registration mode set successfully");
+    // }
     
-    // 4.6. 设置GPRS附着模式
-    ret = ppp_at_send_command("AT+CGATT=1", "OK", 10000, &response);
-    if (ret != PPP_ERR_OK) {
-        PPP_DEBUG_WARN("Failed to attach to GPRS, continuing anyway");
-    } else {
-        PPP_DEBUG_INFO("GPRS attach successful");
-    }
+    // // 4.6. 设置GPRS附着模式
+    // ret = ppp_at_send_command("AT+CGATT=1", "OK", 10000, &response);
+    // if (ret != PPP_ERR_OK) {
+    //     PPP_DEBUG_WARN("Failed to attach to GPRS, continuing anyway");
+    // } else {
+    //     PPP_DEBUG_INFO("GPRS attach successful");
+    // }
     
     // 4.7. 检查网络状态
     ret = ppp_at_send_command("AT+CREG?", "OK", 5000, &response);
index 6f5b61e..27a82df 100644 (file)
@@ -7,6 +7,8 @@
 #include "securec.h"
 #include "osal_addr.h"      // 添加OSAL内存管理头文件
 #include "osal_timer.h"     // 添加OSAL时间函数头文件
+#include "soc_osal.h"       // 添加OSAL任务管理头文件
+#include "schedule/osal_task.h"  // 添加任务创建头文件
 #include <string.h>
 
 /* lwIP相关头文件 - 需要在编译时确保PPP支持已启用 */
@@ -18,6 +20,7 @@
 #include "netif/ppp/ppp.h"
 #include "netif/ppp/pppos.h"
 #include "netif/ppp/pppapi.h"  // 添加pppapi头文件,用于线程安全的PPP API
+#include "netif/ppp/lcp.h"     // 添加LCP头文件,用于echo请求功能
 #include "lwip/sio.h"  // 添加SIO头文件
 #endif
 
@@ -41,21 +44,119 @@ typedef struct {
 
 static ppp_lwip_context_t g_lwip_ctx = {0};
 
+/* PPP连接监控相关 */
+static bool g_ppp_monitor_enabled = false;
+static uint32_t g_last_data_activity_time = 0;
+static uint32_t g_connection_idle_timeout = 60000; /* 60秒无数据活动后检查连接 */
 /* 内部函数声明 */
+static u32_t ppp_lwip_output_callback(ppp_pcb *pcb, u8_t *data, u32_t len, void *ctx);
+static void ppp_lwip_link_status_callback(ppp_pcb *pcb, int err_code, void *ctx);
+static void ppp_lwip_status_callback(ppp_pcb *pcb, int err_code, void *ctx);
+static void ppp_lwip_netif_status_callback(struct netif *netif);
 static uint32_t ppp_lwip_get_time_ms(void);
+static void ppp_lwip_record_data_activity(void);
+static void ppp_lwip_monitor_thread(void *arg);
+static ppp_error_t ppp_lwip_start_connection_monitor(void);
+static void ppp_lwip_stop_connection_monitor(void);
+
+/**
+ * @brief 记录数据活动时间
+ */
+static void ppp_lwip_record_data_activity(void)
+{
+    g_last_data_activity_time = ppp_lwip_get_time_ms();
+    PPP_DEBUG_DEBUG("PPP data activity recorded at %u ms", g_last_data_activity_time);
+}
+
+/**
+ * @brief PPP连接监控线程函数
+ */
+static void ppp_lwip_monitor_thread(void *arg)
+{
+    (void)arg;
+    
+    PPP_DEBUG_INFO("PPP connection monitor thread started");
+    
+    while (g_ppp_monitor_enabled && g_lwip_ctx.initialized) {
+        if (g_lwip_ctx.connected && g_lwip_ctx.ppp_pcb) {
+            uint32_t current_time = ppp_lwip_get_time_ms();
+            uint32_t idle_time = current_time - g_last_data_activity_time;
+            
+            /* 检查空闲时间是否超过阈值 */
+            if (idle_time > g_connection_idle_timeout) {
+                PPP_DEBUG_WARN("PPP connection idle for %u ms, checking health...", idle_time);
+                
+                /* 检查PPP连接是否仍然正常 */
+                if (!ppp_lwip_check_connection_alive()) {
+                    PPP_DEBUG_ERROR("PPP connection health check failed, attempting recovery...");
+                    
+                    /* 重新记录活动时间,避免连续检查 */
+                    ppp_lwip_record_data_activity();
+                } else {
+                    PPP_DEBUG_INFO("PPP connection health check passed");
+                    /* 更新活动时间 */
+                    ppp_lwip_record_data_activity();
+                }
+            }
+        }
+        
+        /* 监控线程休眠10秒 */
+        osal_msleep(10000);
+    }
+    
+    PPP_DEBUG_INFO("PPP connection monitor thread exited");
+}
+
+/**
+ * @brief 启动PPP连接监控
+ */
+static ppp_error_t ppp_lwip_start_connection_monitor(void)
+{
+    if (g_ppp_monitor_enabled) {
+        PPP_DEBUG_WARN("PPP connection monitor already running");
+        return PPP_ERR_OK;
+    }
+    
+    g_ppp_monitor_enabled = true;
+    g_last_data_activity_time = ppp_lwip_get_time_ms();
+    
+    /* 创建监控线程 - 使用osal_kthread_create */
+    osal_task *monitor_task = osal_kthread_create(ppp_lwip_monitor_thread, NULL, 
+                                                 "ppp_monitor", 4096);
+    if (monitor_task == NULL) {
+        PPP_DEBUG_ERROR("Failed to create PPP monitor thread");
+        g_ppp_monitor_enabled = false;
+        return PPP_ERR_UNKNOWN;
+    }
+    
+    PPP_DEBUG_INFO("PPP connection monitor started successfully");
+    return PPP_ERR_OK;
+}
+
+/**
+ * @brief 停止PPP连接监控
+ */
+static void ppp_lwip_stop_connection_monitor(void)
+{
+    if (g_ppp_monitor_enabled) {
+        PPP_DEBUG_INFO("Stopping PPP connection monitor...");
+        g_ppp_monitor_enabled = false;
+        /* 等待线程退出 */
+        osal_msleep(500);
+        PPP_DEBUG_INFO("PPP connection monitor stopped");
+    }
+}
+
+
+/**
+ * @brief 获取当前时间(毫秒)
+ */
 static uint32_t ppp_lwip_get_time_ms(void)
 {
     osal_timeval tv = {0};
     osal_gettimeofday(&tv);
     return (uint32_t)(tv.tv_sec * 1000 + tv.tv_usec / 1000);
 }
-#ifdef LWIP_PPP_SUPPORT
-static void ppp_lwip_status_callback(ppp_pcb *pcb, int err_code, void *ctx);
-static void ppp_lwip_link_status_callback(ppp_pcb *pcb, int err_code, void *ctx);
-static u32_t ppp_lwip_output_callback(ppp_pcb *pcb, u8_t *data, u32_t len, void *ctx);
-static void ppp_lwip_netif_status_callback(struct netif *netif);
-static void ppp_lwip_check_default_interface_timer(void *arg);
-#endif
 
 /**
  * @brief 初始化PPP lwIP集成
@@ -146,11 +247,38 @@ ppp_error_t ppp_lwip_init(const ppp_lwip_config_t *config)
     
     /* 优化LCP相关参数以提高连接稳定性 */
     g_lwip_ctx.ppp_pcb->settings.lcp_loopbackfail = 5;        /* 减少loopback检测次数从10到5 */
-    g_lwip_ctx.ppp_pcb->settings.lcp_echo_interval = 0;       /* 禁用LCP echo请求以减少开销 */
-    g_lwip_ctx.ppp_pcb->settings.lcp_echo_fails = 3;          /* 保持echo失败容忍度为3 */
+    g_lwip_ctx.ppp_pcb->settings.lcp_echo_interval = 30;      /* 启用LCP echo:30秒间隔检测连接存活 */
+    g_lwip_ctx.ppp_pcb->settings.lcp_echo_fails = 3;          /* 连续3次echo失败后认为连接断开 */
     
-    PPP_DEBUG_INFO("PPP parameters optimized: FSM(timeout=3s, max_conf_req=6, max_nak_loops=3), LCP(loopback_fail=5, echo_interval=0)");
+#if LWIP_DNS
+    /* 启用自动DNS获取功能 */
+    g_lwip_ctx.ppp_pcb->settings.usepeerdns = 1;             /* 自动从运营商获取DNS服务器地址 */
+    PPP_DEBUG_INFO("PPP DNS auto-configuration enabled");
+#endif
     
+    PPP_DEBUG_INFO("PPP parameters optimized: FSM(timeout=3s, max_conf_req=6, max_nak_loops=3), LCP(loopback_fail=5, echo_interval=30s, echo_fails=3)");
+    
+    /* 根据标准gprs-dial配置,禁用可能导致协商失败的选项 */
+    PPP_DEBUG_INFO("Applying standard GPRS dial compatibility settings...");
+
+    /* 禁用协议压缩 (对应 nobsdcomp) */
+    g_lwip_ctx.ppp_pcb->lcp_wantoptions.neg_pcompression = 0;
+    g_lwip_ctx.ppp_pcb->lcp_allowoptions.neg_pcompression = 0;
+
+    /* 禁用地址/控制压缩 (对应 nodeflate) */  
+    g_lwip_ctx.ppp_pcb->lcp_wantoptions.neg_accompression = 0;
+    g_lwip_ctx.ppp_pcb->lcp_allowoptions.neg_accompression = 0;
+
+    /* 禁用Magic Number (很多运营商不支持) */
+    g_lwip_ctx.ppp_pcb->lcp_wantoptions.neg_magicnumber = 0;
+    g_lwip_ctx.ppp_pcb->lcp_allowoptions.neg_magicnumber = 0;
+
+    /* 启用IPCP接受选项 (对应 ipcp-accept-local/remote) */
+    g_lwip_ctx.ppp_pcb->ipcp_wantoptions.accept_local = 1;
+    g_lwip_ctx.ppp_pcb->ipcp_wantoptions.accept_remote = 1;
+
+    PPP_DEBUG_INFO("PPP configured for maximum carrier compatibility (no compression, no magic number)");
+
     /* 设置状态回调 */
     ppp_set_notify_phase_callback(g_lwip_ctx.ppp_pcb, ppp_lwip_status_callback);
     
@@ -181,9 +309,9 @@ ppp_error_t ppp_lwip_init(const ppp_lwip_config_t *config)
         magic_number = PPP_MAGIC_NUMBER_FALLBACK;      /* 使用配置的备用值 */
     }
     
-    g_lwip_ctx.ppp_pcb->lcp_wantoptions.neg_magicnumber = 1;
+    // g_lwip_ctx.ppp_pcb->lcp_wantoptions.neg_magicnumber = 1;
     g_lwip_ctx.ppp_pcb->lcp_wantoptions.magicnumber = magic_number;
-    g_lwip_ctx.ppp_pcb->lcp_allowoptions.neg_magicnumber = 1;
+    // g_lwip_ctx.ppp_pcb->lcp_allowoptions.neg_magicnumber = 1;
     PPP_DEBUG_INFO("LCP Magic Number configured: 0x%08X (enhanced randomness)", magic_number);
 
     /* 使用标准PPP/LCP配置 */
@@ -203,16 +331,19 @@ ppp_error_t ppp_lwip_init(const ppp_lwip_config_t *config)
 /**
  * @brief 反初始化PPP lwIP集成
  */
-void ppp_lwip_deinit(void)
+ppp_error_t ppp_lwip_deinit(void)
 {
 #ifdef LWIP_PPP_SUPPORT
     if (!g_lwip_ctx.initialized) {
-        return;
+        return PPP_ERR_OK;
     }
 
-    PPP_DEBUG_INFO("Deinitializing PPP lwIP integration");
+    PPP_DEBUG_INFO("Deinitializing PPP lwIP integration...");
+    
+    /* 停止连接监控 */
+    ppp_lwip_stop_connection_monitor();
 
-    /* 断开连接 */
+    /* 首先断开连接 */
     if (g_lwip_ctx.connected) {
         ppp_lwip_disconnect();
     }
@@ -257,7 +388,10 @@ void ppp_lwip_deinit(void)
     }
 
     memset_s(&g_lwip_ctx, sizeof(g_lwip_ctx), 0, sizeof(g_lwip_ctx));
-    PPP_DEBUG_INFO("PPP lwIP integration deinitialized - network interface removed");
+    PPP_DEBUG_INFO("PPP lwIP integration deinitialized");
+    return PPP_ERR_OK;
+#else
+    return PPP_ERR_INVALID_PARAM;
 #endif
 }
 
@@ -323,6 +457,9 @@ ppp_error_t ppp_lwip_disconnect(void)
 
     PPP_DEBUG_INFO("Disconnecting PPP connection...");
     
+    /* 停止连接监控 */
+    ppp_lwip_stop_connection_monitor();
+    
     err_t err = pppapi_close(g_lwip_ctx.ppp_pcb, 0);
     if (err != ERR_OK) {
         PPP_DEBUG_ERROR("Failed to close PPP connection: %d", err);
@@ -349,11 +486,8 @@ ppp_error_t ppp_lwip_input(const uint8_t *data, uint32_t length)
         return PPP_ERR_INVALID_PARAM;
     }
     
-    // /* 添加合理性检查 - PPP帧长度限制 */
-    // if (length > 1500) {  // PPP最大帧长度
-    //     PPP_DEBUG_ERROR("PPP frame too large: %u bytes", length);
-    //     return PPP_ERR_INVALID_PARAM;
-    // }
+    /* 记录数据活动 */
+    ppp_lwip_record_data_activity();
     
     /* 检查PPP控制块是否有效 */
     if (!g_lwip_ctx.ppp_pcb) {
@@ -361,16 +495,32 @@ ppp_error_t ppp_lwip_input(const uint8_t *data, uint32_t length)
         return PPP_ERR_INVALID_STATE;
     }
 
+    /* 添加数据完整性检查 */
+    if (length > 1500) {  // PPP最大帧长度
+        PPP_DEBUG_WARN("PPP frame too large: %u bytes, truncating", length);
+        length = 1500;  // 截断而不是拒绝
+    }
+    
+    /* 检查数据有效性 */
+    if (length < 4) {  // PPP最小帧长度(地址+控制+协议)
+        PPP_DEBUG_DEBUG("PPP frame too small: %u bytes, ignoring", length);
+        return PPP_ERR_OK;  // 忽略而不是报错
+    }
+
     PPP_DEBUG_PRINT("=== PPP Input Data ===\n");
     PPP_DEBUG_PRINT("Length: %d bytes\n", length);
     // PPP_DEBUG_HEXDUMP("RX", data, length > 32 ? 32 : length);
 
 #if !NO_SYS && !PPP_INPROC_IRQ_SAFE
-    /* 在多线程环境中使用线程安全的输入函数 */
-    err_t result = pppos_input_tcpip(g_lwip_ctx.ppp_pcb, (u8_t *)data, length);
+    /* 在多线程环境中使用线程安全的输入函数,添加异常保护 */
+    err_t result;
+    
+    /* 使用try-catch风格的错误处理 */
+    result = pppos_input_tcpip(g_lwip_ctx.ppp_pcb, (u8_t *)data, length);
     if (result != ERR_OK) {
-        PPP_DEBUG_ERROR("pppos_input_tcpip failed with error: %d", result);
-        return PPP_ERR_UNKNOWN;
+        PPP_DEBUG_WARN("pppos_input_tcpip failed with error: %d (continuing)", result);
+        /* 不要因为单次输入失败就返回错误,这可能导致连接中断 */
+        return PPP_ERR_OK;
     }
 #else
     /* 在单线程或中断安全环境中使用直接输入 */
@@ -469,10 +619,13 @@ static void ppp_lwip_status_callback(ppp_pcb *pcb, int err_code, void *ctx)
             PPP_DEBUG_INFO("PPP Phase transition: %d -> %s (%d) [duration: %ums]", 
                           last_phase, phase_str, err_code, phase_duration);
             
-            /* 检测异常缓慢的阶段 */
-            if (phase_duration > 5000) {  /* 超过5秒 */
+            /* 检测异常缓慢的阶段 - 调整阈值避免误报 */
+            if (phase_duration > 30000) {  /* 超过30秒才警告 */
                 PPP_DEBUG_WARN("PPP Phase %d took too long: %ums (potential performance issue)", 
                               last_phase, phase_duration);
+            } else if (phase_duration > 10000) {  /* 超过10秒提示 */
+                PPP_DEBUG_INFO("PPP Phase %d completed in %ums (normal for network negotiation)", 
+                              last_phase, phase_duration);
             }
         } else {
             PPP_DEBUG_INFO("PPP Phase: %s (%d) [initial]", phase_str, err_code);
@@ -488,8 +641,17 @@ static void ppp_lwip_status_callback(ppp_pcb *pcb, int err_code, void *ctx)
 
     switch (err_code) {
         case PPP_PHASE_RUNNING:
-            /* 连接成功 - PPP协议栈运行中 */
-            g_lwip_ctx.connected = true;
+            PPP_DEBUG_INFO("PPP connection established successfully");
+            PPP_DEBUG_INFO("PPP connected - Local IP: %s", ppp_lwip_get_ip_address());
+            PPP_DEBUG_INFO("PPP connected - Remote IP: %s", ppp_lwip_get_gateway());
+            PPP_DEBUG_INFO("PPP interface set as default network interface");
+            
+            /* 启动PPP连接监控 */
+            ppp_lwip_start_connection_monitor();
+            
+            /* 发送连接成功事件 */
+            ppp_lwip_event_t event;
+            memset_s(&event, sizeof(event), 0, sizeof(event));
             event.type = PPP_LWIP_EVENT_CONNECTED;
             PPP_DEBUG_CRITICAL("PPP connection established successfully");
             /* 获取IP地址信息 */
@@ -759,13 +921,22 @@ static void ppp_lwip_netif_status_callback(struct netif *netif)
 }
 
 /**
- * @brief PPP输出回调函数 - 使用自定义串口接口,不依赖SIO
+ * @brief PPP输出回调函数
  */
 static u32_t ppp_lwip_output_callback(ppp_pcb *pcb, u8_t *data, u32_t len, void *ctx)
 {
     (void)pcb;
     (void)ctx;
+    
+    if (!data || len == 0) {
+        PPP_DEBUG_ERROR("Invalid output data: data=%p, len=%u", data, len);
+        return 0;
+    }
+
+    /* 记录数据活动 */
+    ppp_lwip_record_data_activity();
 
+    /* 发送PPP协议输出日志 */
     PPP_DEBUG_PRINT("=== PPP Protocol Output ===\n");
     PPP_DEBUG_PRINT("PPP TX: %u bytes\n", len);
     
@@ -937,5 +1108,69 @@ const char* ppp_lwip_get_dns(void)
 #endif
 }
 
+/**
+ * @brief PPP连接保活检查
+ * @return true 连接正常,false 连接异常
+ */
+bool ppp_lwip_check_connection_alive(void)
+{
+#ifndef LWIP_PPP_SUPPORT
+    return false;
+#else
+    if (!g_lwip_ctx.initialized || !g_lwip_ctx.connected || !g_lwip_ctx.ppp_pcb) {
+        PPP_DEBUG_WARN("PPP not properly initialized or connected");
+        return false;
+    }
+    
+    // 检查PPP相位状态
+    if (g_lwip_ctx.ppp_pcb->phase != PPP_PHASE_RUNNING) {
+        PPP_DEBUG_WARN("PPP not in RUNNING phase, current phase: %d", g_lwip_ctx.ppp_pcb->phase);
+        return false;
+    }
+    
+    // 检查网络接口状态
+    struct netif *netif = g_lwip_ctx.netif;
+    if (!netif || !netif_is_up(netif) || !netif_is_link_up(netif)) {
+        PPP_DEBUG_WARN("PPP netif is down or link is down");
+        return false;
+    }
+    
+    // 检查IP地址是否有效
+    if (ip4_addr_isany(netif_ip4_addr(netif))) {
+        PPP_DEBUG_WARN("PPP netif has no valid IP address");
+        return false;
+    }
+    
+    PPP_DEBUG_DEBUG("PPP connection alive check passed");
+    return true;
+#endif
+}
+
+/**
+ * @brief 触发PPP连接保活测试
+ * @return PPP_ERR_OK 成功,其他值失败
+ */
+ppp_error_t ppp_lwip_trigger_keepalive(void)
+{
+#ifndef LWIP_PPP_SUPPORT
+    return PPP_ERR_INVALID_PARAM;
+#else
+    if (!g_lwip_ctx.initialized || !g_lwip_ctx.connected || !g_lwip_ctx.ppp_pcb) {
+        return PPP_ERR_INVALID_PARAM;
+    }
+    
+    // 如果LCP echo已启用,强制发送一个echo请求
+    if (g_lwip_ctx.ppp_pcb->settings.lcp_echo_interval > 0) {
+        PPP_DEBUG_INFO("Triggering LCP echo request for connection test");
+        // 通过lwIP的LCP层发送echo请求
+        lcp_echoreq(g_lwip_ctx.ppp_pcb);
+        return PPP_ERR_OK;
+    } else {
+        PPP_DEBUG_WARN("LCP echo is disabled, cannot trigger keepalive");
+        return PPP_ERR_INVALID_PARAM;
+    }
+#endif
+}
+
 
 #endif /* LWIP_PPP_SUPPORT */ 
\ No newline at end of file
index 5eb0bb2..2007eda 100644 (file)
@@ -144,24 +144,28 @@ static void ppp_lwip_receive_thread(void *arg)
             no_data_count++;
             
             /* 减少无数据时的日志输出频率,避免日志开销 */
-            if (no_data_count % 2000 == 0) {  /* 每2000次无数据时打印一次 */
+            if (no_data_count % 5000 == 0) {  /* 每5000次无数据时打印一次 */
                 PPP_DEBUG_DEBUG("PPP RX: No data available (count: %u)", no_data_count);
             }
             
-            /* 短暂让出CPU,避免过度占用 - 优化性能 */
-            if (no_data_count % 10 == 0) {  /* 每10次无数据后短暂休眠 */
-                osal_msleep(1);  /* 1ms休眠,让出CPU */
+            /* 适应性休眠策略,避免过度占用CPU */
+            if (no_data_count % 5 == 0) {  /* 每5次无数据后短暂休眠 */
+                osal_msleep(2);  /* 2ms休眠,让出CPU给tcpip_thread */
             }
         }
         
-        // 统计信息输出 - 每2000次循环输出一次
-        if ((total_packets % 2000) == 0 && total_packets > 0) {
+        // 统计信息输出 - 每5000次循环输出一次,减少日志开销
+        if ((total_packets % 5000) == 0 && total_packets > 0) {
             PPP_DEBUG_DEBUG("PPP lwIP RX: %u fragments, %u complete frames, %u total bytes", 
                           total_packets, complete_frames, total_bytes);
         }
         
-        // 短暂休眠以避免CPU占用过高 - 参考slipif的做法
-        osal_msleep(10);
+        // 适应性休眠以避免CPU占用过高,给tcpip_thread更多时间
+        if (complete_frames > 0) {
+            osal_msleep(5);  /* 有数据时短休眠 */
+        } else {
+            osal_msleep(15); /* 无数据时长休眠 */
+        }
     }
     
     /* 清理资源 */