ppp 拨号优化
author孙春阳 <snickersun@163.com>
Sat, 13 Sep 2025 10:08:08 +0000 (18:08 +0800)
committer孙春阳 <snickersun@163.com>
Sat, 13 Sep 2025 10:08:08 +0000 (18:08 +0800)
14 files changed:
code/sdk/drivers/boards/brandy_evb/board_config/board_leiniao.h
code/sdk/zhihui/ppp/example/ppp_at_cmd.c
code/sdk/zhihui/ppp/example/ppp_example.c
code/sdk/zhihui/ppp/include/ppp_api.h
code/sdk/zhihui/ppp/include/ppp_at_handler.h
code/sdk/zhihui/ppp/include/ppp_cat1_api.h
code/sdk/zhihui/ppp/include/ppp_config.h
code/sdk/zhihui/ppp/include/ppp_example.h [new file with mode: 0644]
code/sdk/zhihui/ppp/include/ppp_serial.h
code/sdk/zhihui/ppp/src/ppp_api.c
code/sdk/zhihui/ppp/src/ppp_at_handler.c
code/sdk/zhihui/ppp/src/ppp_cat1_api.c
code/sdk/zhihui/ppp/src/ppp_power_ctl.c
code/sdk/zhihui/ppp/src/ppp_serial.c

index c8c6297..969738e 100644 (file)
@@ -101,7 +101,7 @@ const hal_pio_config_t g_pio_function_config[PIN_MAX_NUMBER] = {
     { HAL_PIO_FUNC_GPIO, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_DOWN, HAL_PIO_IE_DISABLE },  // S_MGPIO16 I2C2 SDA Sensor
     { HAL_PIO_FUNC_I2C3_M1, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_MAX, HAL_PIO_IE_ENBALE },   // S_MGPIO17 i2c3 SCL    smart pa\ 预留马达控制 \安全芯片
     { HAL_PIO_FUNC_I2C3_M1, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_MAX, HAL_PIO_IE_ENBALE },   // S_MGPIO18  I2C3 SDA
-    { HAL_PIO_FUNC_UART1, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_MAX, HAL_PIO_IE_DISABLE },    // S_MGPIO19 uart1 tx
+    { HAL_PIO_FUNC_UART1, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_UP, HAL_PIO_IE_DISABLE },    // S_MGPIO19 uart1 tx
     { HAL_PIO_FUNC_UART1, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_UP, HAL_PIO_IE_ENBALE },      // S_MGPIO20 uart1 rx
     { HAL_PIO_FUNC_UART1, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_MAX, HAL_PIO_IE_ENBALE },     // S_MGPIO21 uart1 rts
     { HAL_PIO_FUNC_UART1, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_MAX, HAL_PIO_IE_ENBALE },     // S_MGPIO22 uart1 cts
index 5ab411a..cef480e 100644 (file)
@@ -9,9 +9,12 @@
 #include <string.h>
 #include <math.h>
 #include "ppp_log.h"
+#include "ppp_serial.h"
+#include "ppp_types.h"
+#include "ppp_api.h"
+#include "ppp_at_handler.h"
+#include "ppp_example.h"
 
-/* 外部函数声明 */
-extern void ppp_dial_with_power_example(void);
 
 
 #ifdef __cplusplus
@@ -608,6 +611,230 @@ static uint32_t at_ws_multi_test_status(uint8_t *para, uint32_t paraLen, char *s
     return ERRCODE_SUCC;
 }
 #endif
+
+/* PPP串口模式切换测试指令 */
+static errcode_t at_ppp_mode_switch(uint8_t *para, uint32_t paraLen)
+{
+    uint8_t argv[CUSTOM_UTILS_MAX_ARGC][CUSTOM_UTILS_MAX_ARGV_LEN];
+    uint32_t argc;
+    
+    if (ConvertCmdToParam(para, paraLen, argv, &argc) != CUSTOM_UTILS_SUCCESS) {
+        ppp_print_err("PPP MODE SWITCH Convert Command Failed\n");
+        return ERRCODE_FAIL;
+    }
+    
+    if (argc != 1) {
+        ppp_print_err("PPP MODE SWITCH Set Parameter Failed argc %d\nUsage: AT^PPPMODE=AT|PPP\n", argc);
+        return ERRCODE_FAIL;
+    }
+    
+    errcode_t ret = ppp_test_switch_mode((char*)argv[0]);
+    if (ret == ERRCODE_SUCC) {
+        ppp_print_info("PPP MODE SWITCH: Successfully switched to %s mode\n", argv[0]);
+    } else {
+        ppp_print_err("PPP MODE SWITCH: Failed to switch to %s mode, error: %d\n", argv[0], ret);
+    }
+    
+    return ret;
+}
+
+/* PPP串口状态查询指令 */
+static errcode_t at_ppp_status(uint8_t *para, uint32_t paraLen)
+{
+    (void)para;
+    (void)paraLen;
+    
+    char status_info[512];
+    errcode_t ret = ppp_test_get_status(status_info, sizeof(status_info));
+    if (ret == ERRCODE_SUCC) {
+        ppp_print_info("%s", status_info);
+    } else {
+        ppp_print_err("Failed to get PPP status, error: %d\n", ret);
+    }
+    
+    return ret;
+}
+
+/* AT指令透传功能 */
+static errcode_t at_ppp_transparent(uint8_t *para, uint32_t paraLen)
+{
+    if (paraLen == 0) {
+        ppp_print_err("PPP TRANSPARENT: No AT command provided\nUsage: AT^PPPTRANS=AT+CSQ\n");
+        return ERRCODE_FAIL;
+    }
+    
+    /* 构建AT命令字符串 */
+    char at_cmd[256];
+    if (paraLen >= sizeof(at_cmd)) {
+        ppp_print_err("PPP TRANSPARENT: AT command too long (max %d chars)\n", sizeof(at_cmd) - 1);
+        return ERRCODE_FAIL;
+    }
+    
+    memcpy(at_cmd, para, paraLen);
+    at_cmd[paraLen] = '\0';
+    
+    ppp_print_info("PPP TRANSPARENT: Executing AT command: %s", at_cmd);
+    
+    /* 使用ppp_at_send_command函数 */
+    ppp_at_response_t at_response;
+    const uint32_t timeout_ms = 5000; // 5秒超时
+    
+    ppp_error_t ret = ppp_at_send_command(at_cmd, NULL, timeout_ms, &at_response);
+    
+    if (ret == PPP_ERR_OK && at_response.success) {
+        if (at_response.length > 0) {
+            ppp_print_info("PPP TRANSPARENT: Response (%u bytes):\n%s", at_response.length, at_response.response);
+        } else {
+            ppp_print_info("PPP TRANSPARENT: Command executed successfully (no response data)");
+        }
+        return ERRCODE_SUCC;
+    } else {
+        switch (ret) {
+            case PPP_ERR_INVALID_STATE:
+            case PPP_ERR_INVALID_PARAM:
+                ppp_print_err("PPP TRANSPARENT: Must be in AT mode for transparent transmission\n");
+                ppp_print_info("Please use AT^PPPMODE=AT to switch to AT mode first\n");
+                break;
+            case PPP_ERR_TIMEOUT:
+                ppp_print_warning("PPP TRANSPARENT: No response received (timeout)\n");
+                break;
+            case PPP_ERR_MEMORY:
+                ppp_print_err("PPP TRANSPARENT: Memory allocation failed\n");
+                break;
+            default:
+                ppp_print_err("PPP TRANSPARENT: Failed to execute AT command, error: %d\n", ret);
+                break;
+        }
+        return ERRCODE_FAIL;
+    }
+}
+
+/* PPP串口测试指令 */
+static errcode_t at_ppp_test(uint8_t *para, uint32_t paraLen)
+{
+    (void)para;
+    (void)paraLen;
+    
+    ppp_print_info("PPP TEST: Starting PPP serial test...\n");
+    
+    errcode_t ret = ppp_test_uart_function();
+    if (ret == ERRCODE_SUCC) {
+        ppp_print_info("PPP TEST: UART test completed successfully\n");
+    } else {
+        ppp_print_err("PPP TEST: UART test failed, error: %d\n", ret);
+    }
+    
+    return ret;
+}
+
+/* PPP智能flush测试指令 */
+static errcode_t at_ppp_flush(uint8_t *para, uint32_t paraLen)
+{
+    (void)para;
+    (void)paraLen;
+    
+    ppp_print_info("PPP FLUSH: Triggering periodic flush check...\n");
+    
+    errcode_t ret = ppp_test_smart_flush();
+    if (ret == ERRCODE_SUCC) {
+        ppp_print_info("PPP FLUSH: Periodic flush completed successfully\n");
+    } else {
+        ppp_print_err("PPP FLUSH: Periodic flush failed, error: %d\n", ret);
+    }
+    
+    return ret;
+}
+
+/* PPP环境初始化测试指令 */
+static errcode_t at_ppp_env_init(uint8_t *para, uint32_t paraLen)
+{
+    (void)para;
+    (void)paraLen;
+    
+    ppp_print_info("PPP ENV INIT: Initializing PPP environment...\n");
+    
+    int ret = ppp_env_init();
+    if (ret == 0) {
+        ppp_print_info("PPP ENV INIT: PPP environment initialized successfully (AT mode)\n");
+        return ERRCODE_SUCC;
+    } else {
+        ppp_print_err("PPP ENV INIT: Failed to initialize PPP environment, error: %d\n", ret);
+        return ERRCODE_FAIL;
+    }
+}
+
+/* PPP开始拨号测试指令 */
+static errcode_t at_ppp_start_dial(uint8_t *para, uint32_t paraLen)
+{
+    (void)para;
+    (void)paraLen;
+    
+    ppp_print_info("PPP START DIAL: Starting PPP dial (will auto switch to PPP mode)...\n");
+    
+    int ret = ppp_test_start_dial();
+    if (ret == 0) {
+        ppp_print_info("PPP START DIAL: PPP dial started successfully (now in PPP mode)\n");
+        return ERRCODE_SUCC;
+    } else {
+        ppp_print_err("PPP START DIAL: Failed to start PPP dial, error: %d (back to AT mode)\n", ret);
+        return ERRCODE_FAIL;
+    }
+}
+
+/* PPP停止拨号测试指令 */
+static errcode_t at_ppp_stop_dial(uint8_t *para, uint32_t paraLen)
+{
+    (void)para;
+    (void)paraLen;
+    
+    ppp_print_info("PPP STOP DIAL: Stopping PPP dial (will auto switch to AT mode)...\n");
+    
+    int ret = ppp_test_stop_dial();
+    if (ret == 0) {
+        ppp_print_info("PPP STOP DIAL: PPP dial stopped successfully (now in AT mode)\n");
+        return ERRCODE_SUCC;
+    } else {
+        ppp_print_err("PPP STOP DIAL: Failed to stop PPP dial, error: %d\n", ret);
+        return ERRCODE_FAIL;
+    }
+}
+
+/* PPP环境去初始化测试指令 */
+static errcode_t at_ppp_env_deinit(uint8_t *para, uint32_t paraLen)
+{
+    (void)para;
+    (void)paraLen;
+    
+    ppp_print_info("PPP ENV DEINIT: De-initializing PPP environment...\n");
+    
+    int ret = ppp_env_deinit();
+    if (ret == 0) {
+        ppp_print_info("PPP ENV DEINIT: PPP environment de-initialized successfully\n");
+        return ERRCODE_SUCC;
+    } else {
+        ppp_print_err("PPP ENV DEINIT: Failed to de-initialize PPP environment, error: %d\n", ret);
+        return ERRCODE_FAIL;
+    }
+}
+
+/* PPP完整示例测试指令 */
+static errcode_t at_ppp_example_main(uint8_t *para, uint32_t paraLen)
+{
+    (void)para;
+    (void)paraLen;
+    
+    ppp_print_info("PPP EXAMPLE MAIN: Starting complete PPP example sequence...\n");
+    
+    int ret = ppp_example_main();
+    if (ret == 0) {
+        ppp_print_info("PPP EXAMPLE MAIN: Complete PPP example finished successfully\n");
+        return ERRCODE_SUCC;
+    } else {
+        ppp_print_err("PPP EXAMPLE MAIN: PPP example failed, error: %d\n", ret);
+        return ERRCODE_FAIL;
+    }
+}
+
 static const at_cmd_table_t g_ppp_cmd[] = {
     { (char *)"AT^CAT1POWER",       cat1_power, (char *)"1" },
     { (char *)"AT^CAT1GETSIGNAL",   at_cat1_getsignal, (char *)"1" },
@@ -620,7 +847,18 @@ static const at_cmd_table_t g_ppp_cmd[] = {
     { (char *)"AT^CAT1AT",          at_cat1_atcmd, (char *)"1" },
     { (char *)"AT^HTTPDOWNLOAD",    custom_start_ota_download, (char *)" " },
     { (char *)"AT^CAT1LOGLEVEL",    custom_enable_cat1_debug_log, (char *)" " },
-    { (char *)"AT^PPPDIAL",          ppp_dial_with_power_example, (char *)" " },
+    /* PPP串口测试指令 */
+    { (char *)"AT^PPPMODE",         at_ppp_mode_switch, (char *)"AT|PPP" },
+    { (char *)"AT^PPPSTATUS",       at_ppp_status, (char *)" " },
+    { (char *)"AT^PPPTRANS",        at_ppp_transparent, (char *)"AT_COMMAND" },
+    { (char *)"AT^PPPTEST",         at_ppp_test, (char *)" " },
+    { (char *)"AT^PPPFLUSH",        at_ppp_flush, (char *)" " },
+    /* PPP模块化函数测试指令 */
+    { (char *)"AT^PPPENVINIT",      at_ppp_env_init, (char *)" " },
+    { (char *)"AT^PPPSTARTDIAL",    at_ppp_start_dial, (char *)" " },
+    { (char *)"AT^PPPSTOPDIAL",     at_ppp_stop_dial, (char *)" " },
+    { (char *)"AT^PPPENVIDEINIT",   at_ppp_env_deinit, (char *)" " },
+    { (char *)"AT^PPPEXAMPLE",      at_ppp_example_main, (char *)" " },
 #ifdef SUPPORT_ZHIHUI_WEBSOCKET
     { (char *)"AT^WEBSOCKETTEST",   at_websocket_test_start, (char *)"serverip,port,test_time" },
     { (char *)"AT^STOPWEBSOCKET",   at_websocket_test_stop, (char *)" " },
index 85c89d6..d077fc3 100644 (file)
@@ -1,11 +1,14 @@
 #include "ppp_api.h"
 #include "ppp_config.h"
 #include "ppp_debug.h"
+#include "ppp_serial.h"
+#include "ppp_power_ctl.h"
 #include "osal_task.h"
 #include "soc_osal.h"
 #include "debug_print.h"
 #include <stdio.h>
 #include <string.h>
+#include <stdlib.h>
 
 /* PPP事件回调函数 */
 static void ppp_event_callback(const ppp_event_t *event);
@@ -13,43 +16,51 @@ static void ppp_event_callback(const ppp_event_t *event);
 /* 网络状态监控任务 */
 static void network_monitor_task(void *arg);
 
+/* 外部声明cat1Service兼容接口 */
+extern void cat1_api_enable_cat1(bool isopen);
+extern bool cat1_api_is_cat1_enabled(void);
+extern uint8_t cat1_api_runtime_get_cat1_powerstat(void);
+extern void cat1_api_wakeup_cat1(bool isopen);
+
 /* 全局变量 */
 static bool g_ppp_connected = false;
 static osal_task *g_monitor_task = NULL;
+static bool g_ppp_env_initialized = false;
 
 /**
- * @brief PPP拨号示例主函数
+ * @brief PPP环境初始化
+ * @return 0成功,-1失败
  */
-int ppp_example_main(void)
+int ppp_env_init(void)
 {
-    PRINT("PPP Dial Example Started\r\n");
+    if (g_ppp_env_initialized) {
+        PRINT("PPP environment already initialized\r\n");
+        return 0;
+    }
+
+    PRINT("PPP Environment Initialization Started\r\n");
 
-    /* 配置PPP拨号参数 */
+    /* 1. 配置PPP拨号参数 */
     ppp_config_t config = {
-        .apn = "cmnet",                     // 中国移动APN (对应AT+CGDCONT中的APN)
+        .apn = "cmnet",                     // 中国移动APN
         .username = "",                     // 用户名(通常为空)
         .password = "",                     // 密码(通常为空)
-        .baudrate = 2000000,                // 2M波特率 (对应AT+IPR=2000000)
-        .auto_baudrate = true,              // 启用自动波特率检测 (对应chat文件中的AT握手)
-        .dial_timeout = 30000,              // 30秒拨号超时 (对应chat文件TIMEOUT 5)
+        .baudrate = 2000000,                // 2M波特率
+        .auto_baudrate = true,              // 启用自动波特率检测
+        .dial_timeout = 30000,              // 30秒拨号超时
         .retry_count = 3                    // 重试3次
-        };
-
-    /* 初始化PPP拨号系统 */
-    /* 这将执行完整的chat文件流程:
-     * 1. 跳过开机日志 (对应 '' \rAT)
-     * 2. AT握手 (对应 AT -> OK)  
-     * 3. 设置PDP上下文 (对应 AT+CGDCONT=3,"IP")
-     * 4. PPP拨号 (对应 ATD*99***2# -> CONNECTED)
-     */
-    errcode_t ret = zhihui_ppp_init(&config);
+    };
 
+    /* 2. 初始化PPP拨号系统 (包含GPIO、电源、串口等所有初始化) */
+    PRINT("Initializing PPP system...\r\n");
+    errcode_t ret = zhihui_ppp_init(&config);
     if (ret != ERRCODE_SUCC) {
         PRINT("PPP init failed: error code %d\r\n", ret);
         return -1;
     }
 
-    /* 注册事件回调函数 */
+    /* 3. 注册事件回调函数 */
+    PRINT("Registering PPP event callback...\r\n");
     ret = ppp_register_event_callback(ppp_event_callback);
     if (ret != ERRCODE_SUCC) {
         PRINT("PPP register callback failed\r\n");
@@ -57,28 +68,69 @@ int ppp_example_main(void)
         return -1;
     }
 
-    PRINT("PPP system initialized successfully\r\n");
-
-    /* 创建网络监控任务 */
-    /* 使用正确的OSAL任务创建方式 */
-    // osal_task_attr_t task_attr = {
-        // .name = "net_monitor",
-        // .stack_size = 2048,
-        // .priority = OSAL_TASK_PRIORITY_LOW,
-        // .detached = false
-        // };
-
-    g_monitor_task = osal_kthread_create(network_monitor_task, NULL, "net_monitor", 2048);
+    /* 4. 创建网络监控任务 */
+    PRINT("Creating network monitor task...\r\n");
+    g_monitor_task = osal_kthread_create(network_monitor_task, NULL, "net_monitor", (2048+1024));
     if (g_monitor_task == NULL) {
         PRINT("Failed to create monitor task\r\n");
         zhihui_ppp_deinit();
         return -1;
     }
 
-    /* 开始PPP拨号 */
+    g_ppp_env_initialized = true;
+    PRINT("PPP environment initialized successfully (AT mode)\r\n");
+    if (ppp_is_4g_power_initialized()) {
+        PRINT("4G power control is enabled\r\n");
+    } else {
+        PRINT("4G power control is disabled (using internal power management)\r\n");
+    }
+    
+    return 0;
+
+
+}
+
+/**
+ * @brief 开始PPP拨号
+ * @return 0成功,-1失败
+ */
+int ppp_test_start_dial(void)
+{
+    if (!g_ppp_env_initialized) {
+        PRINT("PPP environment not initialized, call ppp_env_init() first\r\n");
+        PRINT("Please execute: AT^PPPENVINIT\r\n");
+        return -1;
+    }
+
+    if (g_ppp_connected) {
+        PRINT("PPP already connected\r\n");
+        return 0;
+    }
+
     PRINT("Starting PPP dial...\r\n");
-    ret = ppp_start_dial();
+
+    /* 检查PPP模块状态 */
+    ppp_state_t current_state = ppp_get_state();
+    PRINT("Current PPP state: %d\r\n", current_state);
+    
+    if (current_state != PPP_STATE_INITIALIZED) {
+        PRINT("PPP module state error (expected: %d, actual: %d)\r\n", 
+              PPP_STATE_INITIALIZED, current_state);
+        PRINT("Please check if AT^PPPENVINIT was executed successfully\r\n");
+        return -1;
+    }
+
+    /* 开始PPP拨号,这会自动切换到PPP模式 */
+    errcode_t ret = ppp_start_dial();
     if (ret != ERRCODE_SUCC) {
+        PRINT("Failed to start PPP dial: %d\r\n", ret);
+        /* 拨号失败,自动切回AT模式 */
+        ppp_error_t serial_ret = ppp_serial_switch_to_at_mode();
+        if (serial_ret != PPP_ERR_OK) {
+            PRINT("Failed to switch back to AT mode: %d\r\n", serial_ret);
+        } else {
+            PRINT("Switched back to AT mode after dial failure\r\n");
+        }
         return -1;
     }
 
@@ -86,13 +138,20 @@ int ppp_example_main(void)
     uint32_t timeout = 60000; // 60秒超时
     uint32_t start_time = (uint32_t)osal_get_jiffies();
     
+    PRINT("Waiting for PPP connection...\r\n");
     while (!g_ppp_connected && (osal_get_jiffies() - start_time) < osal_msecs_to_jiffies(timeout)) {
         ppp_state_t state = ppp_get_state();
-        PRINT("PPP state: %d\r\n", state);
         
         if (state == PPP_STATE_ERROR) {
             PRINT("PPP connection failed\r\n");
-            break;
+            /* 连接失败,自动切回AT模式 */
+            ppp_error_t serial_ret = ppp_serial_switch_to_at_mode();
+            if (serial_ret != PPP_ERR_OK) {
+                PRINT("Failed to switch back to AT mode: %d\r\n", serial_ret);
+            } else {
+                PRINT("Switched back to AT mode after connection failure\r\n");
+            }
+            return -1;
         }
         
         osal_msleep(1000);
@@ -101,7 +160,7 @@ int ppp_example_main(void)
     if (g_ppp_connected) {
         PRINT("PPP connection established successfully!\r\n");
         
-        /* 获取网络信息 */
+        /* 获取并显示网络信息 */
         ppp_connection_info_t network_info;
         ret = ppp_get_connection_info(&network_info);
         if (ret == ERRCODE_SUCC) {
@@ -128,41 +187,166 @@ int ppp_example_main(void)
                   (network_info.secondary_dns >> 24) & 0xFF);
             PRINT("  MTU:           %u\r\n", network_info.mtu);
         }
-
-        /* 保持连接一段时间进行测试 */
-        PRINT("Keeping connection for 30 seconds...\r\n");
-        osal_msleep(30000);
-
-        /* 断开连接 */
-        PRINT("Disconnecting PPP...\r\n");
-        ppp_stop_dial();
         
-        /* 等待断开完成 */
-        timeout = 10000; // 10秒超时
-        start_time = (uint32_t)osal_get_jiffies();
-        
-        while (g_ppp_connected && (osal_get_jiffies() - start_time) < osal_msecs_to_jiffies(timeout)) {
-            osal_msleep(100);
+        return 0;
+    } else {
+        PRINT("PPP connection timeout\r\n");
+        /* 连接超时,自动切回AT模式 */
+        ppp_error_t serial_ret = ppp_serial_switch_to_at_mode();
+        if (serial_ret != PPP_ERR_OK) {
+            PRINT("Failed to switch back to AT mode: %d\r\n", serial_ret);
+        } else {
+            PRINT("Switched back to AT mode after timeout\r\n");
         }
-        
-        if (!g_ppp_connected) {
-            PRINT("PPP disconnected successfully\r\n");
+        return -1;
+    }
+}
+
+/**
+ * @brief 停止PPP拨号
+ * @return 0成功,-1失败
+ */
+int ppp_test_stop_dial(void)
+{
+    if (!g_ppp_env_initialized) {
+        PRINT("PPP environment not initialized\r\n");
+        PRINT("Please execute: AT^PPPENVINIT first\r\n");
+        return -1;
+    }
+
+    /* 检查PPP模块状态 */
+    ppp_state_t current_state = ppp_get_state();
+    PRINT("Current PPP state: %d\r\n", current_state);
+    
+    if (!g_ppp_connected) {
+        PRINT("PPP not connected\r\n");
+        /* 确保切换到AT模式 */
+        ppp_error_t serial_ret = ppp_serial_switch_to_at_mode();
+        if (serial_ret != PPP_ERR_OK) {
+            PRINT("Failed to switch to AT mode: %d\r\n", serial_ret);
         } else {
-            PRINT("PPP disconnect timeout\r\n");
+            PRINT("Switched to AT mode\r\n");
         }
+        return 0;
+    }
+
+    PRINT("Disconnecting PPP...\r\n");
+
+    /* 停止PPP连接 */
+    errcode_t ret = ppp_stop_dial();
+    if (ret != ERRCODE_SUCC) {
+        PRINT("Failed to stop PPP dial: %d\r\n", ret);
+        return -1;
+    }
+
+    /* 等待断开完成 */
+    uint32_t timeout = 10000; // 10秒超时
+    uint32_t start_time = (uint32_t)osal_get_jiffies();
+    
+    while (g_ppp_connected && (osal_get_jiffies() - start_time) < osal_msecs_to_jiffies(timeout)) {
+        osal_msleep(100);
+    }
+    
+    if (!g_ppp_connected) {
+        PRINT("PPP disconnected successfully\r\n");
     } else {
-        PRINT("PPP connection timeout\r\n");
+        PRINT("PPP disconnect timeout\r\n");
+    }
+
+    /* 自动切换回AT模式 */
+    ppp_error_t serial_ret = ppp_serial_switch_to_at_mode();
+    if (serial_ret != PPP_ERR_OK) {
+        PRINT("Failed to switch back to AT mode: %d\r\n", serial_ret);
+        return -1;
+    } else {
+        PRINT("Switched back to AT mode\r\n");
+    }
+
+    return 0;
+}
+
+/**
+ * @brief PPP环境去初始化
+ * @return 0成功,-1失败
+ */
+int ppp_env_deinit(void)
+{
+    if (!g_ppp_env_initialized) {
+        PRINT("PPP environment not initialized\r\n");
+        return 0;
+    }
+
+    PRINT("PPP Environment De-initialization Started\r\n");
+
+    /* 1. 如果还在连接状态,先断开 */
+    if (g_ppp_connected) {
+        PRINT("Stopping active PPP connection...\r\n");
+        ppp_stop_dial();
     }
 
-    /* 清理资源 */
+    /* 2. 销毁监控任务 */
     if (g_monitor_task) {
+        PRINT("Destroying monitor task...\r\n");
         osal_kthread_destroy(g_monitor_task, 1);
         g_monitor_task = NULL;
     }
+
+    /* 3. 去初始化PPP系统 (包含4G电源管理) */
+    PRINT("De-initializing PPP system...\r\n");
+    errcode_t ret = zhihui_ppp_deinit();
+    if (ret != ERRCODE_SUCC) {
+        PRINT("PPP deinit failed: %d\r\n", ret);
+    }
+
+    g_ppp_env_initialized = false;
+    g_ppp_connected = false;
+    
+    PRINT("PPP environment de-initialized successfully\r\n");
+    
+    /* 如果PPP去初始化失败,返回错误 */
+    if (ret != ERRCODE_SUCC) {
+        return -1;
+    }
     
-    zhihui_ppp_deinit();
-    PRINT("PPP example completed\r\n");
+    return 0;
+}
+
+/**
+ * @brief PPP拨号示例主函数(使用新的分离函数)
+ */
+int ppp_example_main(void)
+{
+    PRINT("PPP Dial Example Started (New Modular Version)\r\n");
+
+    /* 1. 初始化PPP环境 */
+    if (ppp_env_init() != 0) {
+        PRINT("Failed to initialize PPP environment\r\n");
+        return -1;
+    }
+
+    /* 2. 开始拨号 */
+    if (ppp_test_start_dial() != 0) {
+        PRINT("Failed to start PPP dial\r\n");
+        ppp_env_deinit();
+        return -1;
+    }
+
+    /* 3. 保持连接一段时间进行测试 */
+    PRINT("Keeping connection for 30 seconds...\r\n");
+    osal_msleep(30000);
+
+    /* 4. 停止拨号 */
+    if (ppp_test_stop_dial() != 0) {
+        PRINT("Failed to stop PPP dial\r\n");
+    }
+
+    /* 5. 清理环境 */
+    if (ppp_env_deinit() != 0) {
+        PRINT("Failed to deinitialize PPP environment\r\n");
+        return -1;
+    }
 
+    PRINT("PPP example completed successfully\r\n");
     return 0;
 }
 
@@ -214,6 +398,8 @@ static void ppp_event_callback(const ppp_event_t *event)
     }
 }
 
+
+#define STATS_INFO_SIZE 512
 /**
  * @brief 网络状态监控任务
  */
@@ -222,19 +408,60 @@ static void network_monitor_task(void *arg)
     (void)arg;
     
     PRINT("Network monitor task started\r\n");
+    char *stats_info = (char *)malloc(STATS_INFO_SIZE);
+    if (stats_info == NULL) {
+        PRINT("Failed to allocate memory for stats_info\r\n");
+        return;
+    }
 
     while (1) {
         /* 获取统计信息 */
-        ppp_stats_t stats;
+        ppp_test_get_status(stats_info, STATS_INFO_SIZE);    
+        PRINT("%s", stats_info);
 
-        /* 每10秒输出一次统计信息 */
-        osal_msleep(10000);
+        ppp_state_t state = ppp_get_state();
+        switch (state) {
+            case PPP_STATE_IDLE:
+                PRINT("PPP state: IDLE\r\n");
+                break;
+            case PPP_STATE_INITIALIZED:
+                PRINT("PPP state: INITIALIZED\r\n");
+                break;
+            case PPP_STATE_INIT:
+                PRINT("PPP state: INIT\r\n");
+                break;
+            case PPP_STATE_AT_HANDSHAKE:
+                PRINT("PPP state: AT_HANDSHAKE\r\n");
+                break;
+            case PPP_STATE_SET_BAUDRATE:
+                PRINT("PPP state: SET_BAUDRATE\r\n");
+                break;
+            case PPP_STATE_DIALING:
+                PRINT("PPP state: DIALING\r\n");
+                break;
+            case PPP_STATE_CONNECTED:
+                PRINT("PPP state: CONNECTED\r\n");
+                break;
+            case PPP_STATE_DISCONNECTING:
+                PRINT("PPP state: DISCONNECTING\r\n");
+                break;
+            case PPP_STATE_ERROR:
+                PRINT("PPP state: ERROR\r\n");
+                break;
+            default:
+                PRINT("PPP state: UNKNOWN\r\n");
+                break;
+        }
+       
         
         /* 如果PPP未连接且不在拨号过程中,退出监控任务 */
-        ppp_state_t state = ppp_get_state();
-        if (!g_ppp_connected && state == PPP_STATE_IDLE) {
+        if (!g_ppp_connected && 
+            (state == PPP_STATE_IDLE || state == PPP_STATE_ERROR)) {
             break;
         }
+        /* 每10秒输出一次统计信息 */
+        osal_msleep(10000);
+
     }
 
     PRINT("Network monitor task exited\r\n");
index 8c02107..9851977 100644 (file)
@@ -67,6 +67,62 @@ errcode_t ppp_register_event_callback(ppp_event_callback_t callback);
  */
 errcode_t ppp_get_connection_info(ppp_connection_info_t *info);
 
+/**
+ * @brief PPP状态重置(从错误状态恢复)
+ * @return 错误码
+ */
+errcode_t ppp_reset_from_error(void);
+
+/* ========== PPP测试接口 ========== */
+
+/**
+ * @brief PPP串口模式切换
+ * @param mode 目标模式 ("AT" 或 "PPP")
+ * @return 错误码
+ */
+errcode_t ppp_test_switch_mode(const char *mode);
+
+/**
+ * @brief 获取PPP串口状态信息
+ * @param status_info 状态信息字符串缓冲区
+ * @param buffer_size 缓冲区大小
+ * @return 错误码
+ */
+errcode_t ppp_test_get_status(char *status_info, uint32_t buffer_size);
+
+/**
+ * @brief 执行AT指令透传
+ * @param at_command AT指令字符串
+ * @param response 响应缓冲区
+ * @param response_size 响应缓冲区大小
+ * @param response_len 实际响应长度(输出参数)
+ * @param timeout_ms 超时时间(毫秒)
+ * @return 错误码
+ */
+errcode_t ppp_test_execute_at_command(const char *at_command,
+                                     char *response,
+                                     uint32_t response_size,
+                                     uint32_t *response_len,
+                                     uint32_t timeout_ms);
+
+/**
+ * @brief PPP串口基础功能测试
+ * @return 错误码
+ */
+errcode_t ppp_test_uart_function(void);
+
+/**
+ * @brief PPP智能flush测试
+ * @return 错误码
+ */
+errcode_t ppp_test_smart_flush(void);
+
+/**
+ * @brief 检查4G电源是否已初始化
+ * @return true已初始化,false未初始化
+ */
+bool ppp_is_4g_power_initialized(void);
+
 #ifdef __cplusplus
 }
 #endif
index 82ab07c..a61b681 100644 (file)
@@ -71,6 +71,12 @@ ppp_error_t ppp_at_hangup_ppp(void);
  */
 uint32_t ppp_at_get_current_baudrate(void);
 
+/**
+ * @brief 执行波特率自适应握手
+ * @return 错误码
+ */
+ppp_error_t ppp_at_baudrate_handshake(void);
+
 #ifdef __cplusplus
 }
 #endif
index 64acdcc..e3ee9f8 100644 (file)
@@ -35,6 +35,7 @@ errcode_t cat1_server_init(void);
  */
 void cat1_api_enable_cat1(bool isopen);
 
+
 /**
  * @brief 获取cat1是否使能(开机)状态
  */
@@ -156,7 +157,7 @@ void cat1_api_runtime_set_cat1_modemver(char* modemver);
 /********************** 控制接口 **********************/
 
 /**
- * @brief 唤醒Cat1
+ * @brief cat1 唤醒设置, 输入 true 唤醒cat1 modem, false cat1 modem自动休眠
  */
 void cat1_api_wakeup_cat1(uint8_t wakeup);
 
index 966b9ac..0a4571f 100644 (file)
@@ -25,7 +25,7 @@ extern "C" {
 #endif
 
 /* 支持的波特率列表(自适应模式) */
-#define PPP_BAUDRATE_AUTO_LIST      {9600, 57600, 115200 , 2000000}
+#define PPP_BAUDRATE_AUTO_LIST      {2000000, 9600, 57600, 115200 }
 #define PPP_BAUDRATE_AUTO_COUNT     4
 
 /* 支持的固定波特率列表 */
@@ -84,6 +84,7 @@ typedef enum {
     PPP_ERR_INVALID_PARAM,                            // 无效参数
     PPP_ERR_MEMORY,                                    // 内存错误
     PPP_ERR_UART,                                      // 串口错误
+    PPP_ERR_INVALID_STATE,                            // 无效状态
     PPP_ERR_UNKNOWN                                    // 未知错误
 } ppp_error_t;
 
diff --git a/code/sdk/zhihui/ppp/include/ppp_example.h b/code/sdk/zhihui/ppp/include/ppp_example.h
new file mode 100644 (file)
index 0000000..a79021b
--- /dev/null
@@ -0,0 +1,78 @@
+/**
+ * Copyright (c) @CompanyNameMagicTag 2022-2022. All rights reserved. \n
+ *
+ * Description: PPP Example Functions Header \n
+ * Author: @CompanyNameTag \n
+ * History: \n
+ * 2022-07-20, Create file. \n
+ */
+#ifndef PPP_EXAMPLE_H
+#define PPP_EXAMPLE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief PPP环境初始化
+ * 
+ * 负责完整的PPP环境初始化,包括:
+ * 1. 配置和启用4G模块电源控制
+ * 2. 唤醒4G模块
+ * 3. 初始化PPP系统 (zhihui_ppp_init)
+ * 4. 注册事件回调 (ppp_register_event_callback)
+ * 5. 创建PPP状态监控任务
+ * 6. 确保默认工作在AT模式
+ * 
+ * @return 0成功,-1失败
+ */
+int ppp_env_init(void);
+
+/**
+ * @brief 开始PPP拨号
+ * 
+ * env_init之后,可以ppp_start_dial,它会自动切换到ppp模式,
+ * 然后执行拨号,失败后自动切回AT模式。
+ * 
+ * @return 0成功,-1失败
+ */
+int ppp_test_start_dial(void);
+
+/**
+ * @brief 停止PPP拨号
+ * 
+ * 进入ppp后,如果不想上网,或者打算使用at指令,需要先执行它
+ * 断开ppp链接,然后自动切换回AT模式。
+ * 
+ * @return 0成功,-1失败
+ */
+int ppp_test_stop_dial(void);
+
+/**
+ * @brief PPP环境去初始化
+ * 
+ * 销毁所有ppp_env_init建立起来的资源,包括:
+ * 1. 断开活动的PPP连接
+ * 2. 销毁网络监控任务
+ * 3. 去初始化PPP系统
+ * 4. 让4G模块进入休眠状态
+ * 5. 关闭4G模块电源
+ * 
+ * @return 0成功,-1失败
+ */
+int ppp_env_deinit(void);
+
+/**
+ * @brief PPP拨号示例主函数
+ * 
+ * 使用新的模块化函数实现的示例主函数,展示完整的PPP使用流程。
+ * 
+ * @return 0成功,-1失败
+ */
+int ppp_example_main(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* PPP_EXAMPLE_H */ 
\ No newline at end of file
index 274a37a..4296a19 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * @brief PPP串口模块头文件 - 恢复缓存机制
+ * @brief PPP串口模块头文件 - 统一缓冲区管理 + PPP模式智能发送缓冲
  */
 
 #ifndef PPP_SERIAL_H
@@ -19,8 +19,8 @@ typedef void (*ppp_serial_rx_callback_t)(const uint8_t *data, uint16_t length, v
 /* 串口工作模式 */
 typedef enum {
     PPP_SERIAL_MODE_NONE = 0,    // 未初始化
-    PPP_SERIAL_MODE_AT,          // AT命令模式(使用普通UART)
-    PPP_SERIAL_MODE_PPP_DATA     // PPP数据模式(使用普通UART + 缓存)
+    PPP_SERIAL_MODE_AT,          // AT命令模式(直接使用UART)
+    PPP_SERIAL_MODE_PPP_DATA     // PPP数据模式(使用UART + 软件缓冲区 + 智能发送缓冲)
 } ppp_serial_mode_t;
 
 /**
@@ -32,7 +32,7 @@ typedef struct {
     uint8_t tx_pin;                                     // 发送引脚
     uint8_t rx_pin;                                     // 接收引脚
     uint32_t rx_buffer_size;                            // 接收缓冲区大小
-    uint32_t tx_buffer_size;                            // 发送缓冲区大小
+    uint32_t tx_buffer_size;                            // 发送缓冲区大小(PPP模式使用)
     ppp_serial_rx_callback_t rx_callback;              // 接收回调函数
     void *rx_callback_arg;                              // 回调函数参数
 } ppp_serial_config_t;
@@ -47,10 +47,12 @@ typedef struct {
     uint32_t rx_errors;                                 // 接收错误数
     uint32_t rx_buffer_usage;                           // 接收缓冲区使用量
     uint32_t rx_buffer_size;                            // 接收缓冲区大小
+    uint32_t tx_buffer_usage;                           // 发送缓冲区使用量
+    uint32_t tx_buffer_size;                            // 发送缓冲区大小
 } ppp_serial_stats_t;
 
 /**
- * @brief 初始化PPP串口(AT命令模式,准备缓存机制)
+ * @brief 初始化PPP串口(统一缓冲区管理)
  * @param config 串口配置
  * @return 错误码
  */
@@ -62,13 +64,13 @@ ppp_error_t ppp_serial_init(const ppp_serial_config_t *config);
 void ppp_serial_deinit(void);
 
 /**
- * @brief 切换到PPP数据模式(启用缓存机制)
+ * @brief 切换到PPP数据模式(启用软件缓冲区管理)
  * @return 错误码
  */
 ppp_error_t ppp_serial_switch_to_ppp_mode(void);
 
 /**
- * @brief å\88\87æ\8d¢å\9b\9eATå\91½ä»¤æ¨¡å¼\8fï¼\88ç¦\81ç\94¨ç¼\93å­\98æ\9cºå\88)
+ * @brief å\88\87æ\8d¢å\9b\9eATå\91½ä»¤æ¨¡å¼\8fï¼\88ç\9b´æ\8e¥ä½¿ç\94¨UART)
  * @return 错误码
  */
 ppp_error_t ppp_serial_switch_to_at_mode(void);
@@ -80,7 +82,7 @@ ppp_error_t ppp_serial_switch_to_at_mode(void);
 ppp_serial_mode_t ppp_serial_get_mode(void);
 
 /**
- * @brief 发送数据(根据模式选择直接发送或缓存发送)
+ * @brief 发送数据(AT模式直接发送,PPP模式使用智能缓冲发送)
  * @param data 数据指针
  * @param length 数据长度
  * @return 错误码
@@ -88,7 +90,7 @@ ppp_serial_mode_t ppp_serial_get_mode(void);
 ppp_error_t ppp_serial_write(const uint8_t *data, uint32_t length);
 
 /**
- * @brief 读取数据(根据模式选择直接读取或从缓存读取)
+ * @brief 读取数据(AT模式直接从UART读取,PPP模式从软件缓冲区读取)
  * @param buffer 接收缓冲区
  * @param buffer_size 缓冲区大小
  * @param bytes_read 实际读取字节数
@@ -114,6 +116,29 @@ uint32_t ppp_serial_available(void);
  */
 void ppp_serial_flush_rx(void);
 
+/**
+ * @brief 强制发送缓冲区中的所有数据
+ * @return 错误码
+ */
+ppp_error_t ppp_serial_flush_tx(void);
+
+/**
+ * @brief 清空发送缓冲区(丢弃数据)
+ */
+void ppp_serial_flush_tx_discard(void);
+
+/**
+ * @brief 获取发送缓冲区使用情况
+ * @return 发送缓冲区中的数据量
+ */
+uint32_t ppp_serial_tx_available(void);
+
+/**
+ * @brief 定时flush检查函数(智能flush策略)
+ * @return 错误码
+ */
+ppp_error_t ppp_serial_periodic_flush(void);
+
 /**
  * @brief 设置接收回调函数
  * @param callback 回调函数
@@ -128,6 +153,12 @@ ppp_error_t ppp_serial_set_rx_callback(ppp_serial_rx_callback_t callback, void *
  */
 void ppp_serial_get_stats(ppp_serial_stats_t *stats);
 
+/**
+ * @brief 测试UART是否正常工作
+ * @return 错误码
+ */
+ppp_error_t ppp_serial_test_uart(void);
+
 #ifdef __cplusplus
 }
 #endif
index 1603f49..56bf454 100644 (file)
 #include "schedule/osal_task.h"
 #include "securec.h"
 #include "ppp_log.h"
+#include "ppp_types.h"       // 添加类型定义头文件
 // PPP连接状态
 static ppp_state_t g_ppp_state = PPP_STATE_IDLE;
 
 // PPP配置参数
 static ppp_config_t g_ppp_config = {0};
 
+// 4G电源初始化状态
+static bool g_4g_power_initialized = false;
+
 uint8_t g_ppp_enable_debug = PPP_LOG_LEVEL_INFO;
 
 // 外部声明cat1_api_enable_cat1函数(在ppp_cat1_api.c中实现)
@@ -43,38 +47,56 @@ errcode_t zhihui_ppp_init(const ppp_config_t *config)
     // 保存用户配置
     memcpy_s(&g_ppp_config, sizeof(ppp_config_t), config, sizeof(ppp_config_t));
 
-    // 初始化电源控制
+    // 1. GPIO初始化
+    PPP_DEBUG_PRINT("Step 1: Initializing GPIO system\n");
     ppp_api_gpio_init();
 
-    g_ppp_state = PPP_STATE_INITIALIZED;
+    // 2. CAT1电源操作
+    PPP_DEBUG_PRINT("Step 2: Configuring and enabling CAT1 power\n");
     
-    PPP_DEBUG_PRINT("PPP module initialized successfully\n");
-
-    return ERRCODE_SUCC;
-}
+    // 配置4G电源控制引脚
+    ppp_ctl_pin_4g_t pin_config = {
+        .bat_pin = S_AGPIO_L18,
+        .bat_pin_en_value = 1,
+        .pwr_pin = S_AGPIO_L23,
+        .pwr_pin_en_value = 1,
+        .reset_pin = S_AGPIO_L24,
+        .reset_pin_en_value = 0,
+        .ring_pin = PIN_NONE,
+        .ring_pin_en_value = 0,
+        .wakemodem_pin = S_MGPIO22,
+        .wakemodem_pin_en_value = 1
+    };
 
-/**
- * @brief 启动PPP拨号
- */
-errcode_t ppp_start_dial(void)
-{
-    if (g_ppp_state != PPP_STATE_INITIALIZED) {
-        PPP_DEBUG_PRINT("PPP start dial: module not initialized\n");
-        return ERRCODE_FAIL;
+    // 注册4G电源控制引脚配置
+    errcode_t power_ret = ppp_register_ctl_pin(&pin_config);
+    if (power_ret != ERRCODE_SUCC) {
+        PPP_DEBUG_PRINT("Failed to register 4G power control pins: %d\n", power_ret);
+        PPP_DEBUG_PRINT("Continuing without power control...\n");
+        g_4g_power_initialized = false;
+    } else {
+        PPP_DEBUG_PRINT("4G power control pins registered successfully\n");
+        g_4g_power_initialized = true;
+        
+        // 启用4G电源
+        PPP_DEBUG_PRINT("Enabling 4G module power...\n");
+        cat1_api_enable_cat1(true);
+        osal_msleep(2000);  // 等待电源稳定
+        
+        // 唤醒4G模块
+        PPP_DEBUG_PRINT("Waking up 4G module...\n");
+        cat1_api_wakeup_cat1(true);
+        osal_msleep(1000);  // 等待唤醒完成
+        
+        // 检查电源状态
+        bool power_enabled = cat1_api_is_cat1_enabled();
+        uint8_t power_stat = cat1_api_runtime_get_cat1_powerstat();
+        PPP_DEBUG_PRINT("4G power status: %s (runtime stat: %d)\n", 
+                       power_enabled ? "ON" : "OFF", power_stat);
     }
 
-    PPP_DEBUG_PRINT("Starting PPP dial sequence\n");
-
-    // 1. 启动4G电源(通过兼容接口)
-    cat1_api_enable_cat1(true);
-    PPP_DEBUG_PRINT("4G module power enabled\n");
-
-    // 2. 等待4G模块启动(增加等待时间)
-    PPP_DEBUG_PRINT("Waiting for 4G module startup...\n");
-    osal_msleep(5000);  // 增加到5秒
-    PPP_DEBUG_PRINT("4G module startup wait completed\n");
-
-    // 3. 初始化串口(AT命令模式)
+    // 3. UART初始化
+    PPP_DEBUG_PRINT("Step 3: Initializing UART for AT mode\n");
     ppp_serial_config_t serial_config = {
         .uart_bus = SIO_UART_BUS,
         .baudrate = g_ppp_config.baudrate,
@@ -89,35 +111,84 @@ errcode_t ppp_start_dial(void)
     ppp_error_t ret = ppp_serial_init(&serial_config);
     if (ret != PPP_ERR_OK) {
         PPP_DEBUG_PRINT("Failed to initialize serial for AT mode: %d\n", ret);
-        return ERRCODE_FAIL;
+        goto init_failed;
     }
 
-    // 4. 初始化AT命令处理器(使用串口AT模式)
+    // 初始化AT命令处理器
     ret = ppp_at_handler_init(SIO_UART_BUS);
     if (ret != PPP_ERR_OK) {
         PPP_DEBUG_PRINT("Failed to initialize AT handler: %d\n", ret);
         ppp_serial_deinit();
-        return ERRCODE_FAIL;
+        goto init_failed;
     }
 
-    // 5. 执行波特率握手(如果启用自动波特率)
+    // 4. 串口波特率确认
+    PPP_DEBUG_PRINT("Step 4: Confirming UART baudrate\n");
     if (g_ppp_config.auto_baudrate) {
         ret = ppp_at_baudrate_handshake();
         if (ret != PPP_ERR_OK) {
             PPP_DEBUG_PRINT("Baudrate handshake failed: %d\n", ret);
             ppp_at_handler_deinit();
             ppp_serial_deinit();
-            return ERRCODE_FAIL;
+            goto init_failed;
         }
+        PPP_DEBUG_PRINT("Baudrate handshake completed successfully\n");
+    }
+
+    // 5. 默认工作在AT指令模式
+    PPP_DEBUG_PRINT("Step 5: Ensuring default AT command mode\n");
+    ret = ppp_serial_switch_to_at_mode();
+    if (ret != PPP_ERR_OK) {
+        PPP_DEBUG_PRINT("Failed to switch to AT mode: %d\n", ret);
+        // 不作为致命错误,继续执行
+    } else {
+        PPP_DEBUG_PRINT("Successfully switched to AT mode\n");
+    }
+
+    
+    g_ppp_state = PPP_STATE_INITIALIZED;
+    
+    PPP_DEBUG_PRINT("PPP module initialized successfully\n");
+
+    return ERRCODE_SUCC;
+
+init_failed:
+    // 初始化失败,关闭4G电源
+    if (g_4g_power_initialized) {
+        PPP_DEBUG_PRINT("Disabling 4G power due to initialization failure\n");
+        cat1_api_wakeup_cat1(false);
+        osal_msleep(500);
+        cat1_api_enable_cat1(false);
+        g_4g_power_initialized = false;
     }
+    return ERRCODE_FAIL;
+}
+
+static void ppp_lwip_event_callback(const ppp_lwip_event_t *event, void *arg)
+{
+    PPP_DEBUG_PRINT("PPP lwIP event: %d\n", event->type);
+}
+
+/**
+ * @brief 启动PPP拨号
+ */
+errcode_t ppp_start_dial(void)
+{
+    if (g_ppp_state != PPP_STATE_INITIALIZED) {
+        PPP_DEBUG_PRINT("PPP start dial: module not initialized\n");
+        return ERRCODE_FAIL;
+    }
+
+    PPP_DEBUG_PRINT("Starting PPP dial sequence\n");
+    ppp_error_t ret = PPP_ERR_OK;
+
+    // 注意:波特率握手已在ppp_env_init中完成,这里直接开始AT指令序列
 
     // 6. 执行完整的AT指令序列(对应chat文件)
     ret = ppp_at_complete_dial_sequence(g_ppp_config.apn);
     if (ret != PPP_ERR_OK) {
         PPP_DEBUG_PRINT("PPP dial sequence failed: %d\n", ret);
-        ppp_at_handler_deinit();
-        ppp_serial_deinit();
-        g_ppp_state = PPP_STATE_ERROR;
+        // AT指令序列失败,状态保持INITIALIZED,可以重试
         return ERRCODE_FAIL;
     }
 
@@ -131,25 +202,28 @@ errcode_t ppp_start_dial(void)
     ret = ppp_serial_switch_to_ppp_mode();
     if (ret != PPP_ERR_OK) {
         PPP_DEBUG_PRINT("Failed to switch serial to PPP data mode: %d\n", ret);
-        ppp_serial_deinit();
-        return ERRCODE_FAIL;
+        goto error_recovery_at_mode;
     }
 
     // 9. 启动PPP数据接收处理(在lwIP连接之前启动)
     ret = ppp_start_data_receive_thread();
     if (ret != PPP_ERR_OK) {
         PPP_DEBUG_PRINT("Failed to start PPP data receive thread: %d\n", ret);
-        ppp_serial_deinit();
-        return ERRCODE_FAIL;
+        goto error_recovery_at_mode;
     }
 
+    ppp_lwip_config_t lwip_config = {
+        .username = "",
+        .password = "",
+        .event_callback = ppp_lwip_event_callback,
+        .event_callback_arg = NULL
+    };  
     // 10. 初始化lwIP PPP协议栈
-    ret = ppp_lwip_init(NULL);  // 使用默认配置
+    ret = ppp_lwip_init(&lwip_config);  // 使用默认配置
     if (ret != PPP_ERR_OK) {
         PPP_DEBUG_PRINT("Failed to initialize lwIP PPP: %d\n", ret);
         ppp_stop_data_receive_thread();
-        ppp_serial_deinit();
-        return ERRCODE_FAIL;
+        goto error_recovery_at_mode;
     }
 
     // 11. 启动PPP连接(数据接收已准备好)
@@ -158,14 +232,35 @@ errcode_t ppp_start_dial(void)
         PPP_DEBUG_PRINT("Failed to start PPP connection: %d\n", ret);
         ppp_lwip_deinit();
         ppp_stop_data_receive_thread();
-        ppp_serial_deinit();
-        return ERRCODE_FAIL;
+        goto error_recovery_at_mode;
     }
 
     g_ppp_state = PPP_STATE_CONNECTED;
     PPP_DEBUG_PRINT("PPP dial completed successfully - now in data mode\n");
 
     return ERRCODE_SUCC;
+
+error_recovery_at_mode:
+    PPP_DEBUG_PRINT("PPP dial failed, recovering to AT mode\n");
+    
+    // 尝试切换回AT模式
+    ppp_error_t recovery_ret = ppp_serial_switch_to_at_mode();
+    if (recovery_ret == PPP_ERR_OK) {
+        // 重新初始化AT处理器
+        recovery_ret = ppp_at_handler_init(SIO_UART_BUS);
+        if (recovery_ret == PPP_ERR_OK) {
+            PPP_DEBUG_PRINT("Successfully recovered to AT mode\n");
+            // 状态保持INITIALIZED,可以重试
+        } else {
+            PPP_DEBUG_ERROR("Failed to reinitialize AT handler during recovery\n");
+            g_ppp_state = PPP_STATE_ERROR;
+        }
+    } else {
+        PPP_DEBUG_ERROR("Failed to switch back to AT mode during recovery\n");
+        g_ppp_state = PPP_STATE_ERROR;
+    }
+    
+    return ERRCODE_FAIL;
 }
 
 /**
@@ -207,19 +302,12 @@ errcode_t ppp_stop_dial(void)
                 // 继续执行,不返回错误
             }
 
-            // 7. 关闭AT命令处理器
-            ppp_at_handler_deinit();
         } else {
             PPP_DEBUG_WARN("Failed to reinitialize AT handler for hangup: %d", ret);
         }
     }
 
-    // 8. 关闭串口
-    ppp_serial_deinit();
-
-    // 9. 关闭4G电源
-    cat1_api_enable_cat1(false);
-
+   
     g_ppp_state = PPP_STATE_INITIALIZED;
     PPP_DEBUG_PRINT("PPP connection stopped successfully\n");
 
@@ -268,21 +356,84 @@ errcode_t ppp_get_connection_info(ppp_connection_info_t *info)
     return ERRCODE_SUCC;
 }
 
+/**
+ * @brief PPP状态重置(从错误状态恢复)
+ */
+errcode_t ppp_reset_from_error(void)
+{
+    if (g_ppp_state != PPP_STATE_ERROR) {
+        PPP_DEBUG_PRINT("PPP reset: not in error state, current state: %d\n", g_ppp_state);
+        return ERRCODE_SUCC;
+    }
+
+    PPP_DEBUG_PRINT("Resetting PPP from error state\n");
+
+    // 1. 停止所有可能的活动
+    ppp_stop_data_receive_thread();
+    ppp_lwip_deinit();
+
+    // 2. 尝试恢复到AT模式
+    ppp_error_t ret = ppp_serial_switch_to_at_mode();
+    if (ret == PPP_ERR_OK) {
+        // 3. 重新初始化AT处理器
+        ret = ppp_at_handler_init(SIO_UART_BUS);
+        if (ret == PPP_ERR_OK) {
+            g_ppp_state = PPP_STATE_INITIALIZED;
+            PPP_DEBUG_PRINT("PPP successfully reset to INITIALIZED state\n");
+            return ERRCODE_SUCC;
+        } else {
+            PPP_DEBUG_ERROR("Failed to reinitialize AT handler during reset\n");
+        }
+    } else {
+        PPP_DEBUG_ERROR("Failed to switch to AT mode during reset\n");
+    }
+
+    // 如果恢复失败,保持错误状态
+    PPP_DEBUG_ERROR("PPP reset failed, remains in error state\n");
+    return ERRCODE_FAIL;
+}
+
 /**
  * @brief PPP模块去初始化
  */
 errcode_t zhihui_ppp_deinit(void)
 {
-    // 停止连接
+    PPP_DEBUG_PRINT("Starting PPP module deinitialization\n");
+
+    // 1. 停止连接
     if (g_ppp_state != PPP_STATE_IDLE) {
+        PPP_DEBUG_PRINT("Stopping active PPP connection\n");
         ppp_stop_dial();
     }
 
-    // 清理资源
+    // 2. 去初始化串口和AT处理器
+    PPP_DEBUG_PRINT("Deinitializing serial and AT handler\n");
+    ppp_at_handler_deinit();
+    ppp_serial_deinit();
+
+    // 3. 关闭4G电源
+    if (g_4g_power_initialized) {
+        PPP_DEBUG_PRINT("Disabling 4G module power\n");
+        
+        // 让4G模块进入休眠状态
+        PPP_DEBUG_PRINT("Putting 4G module to sleep\n");
+        cat1_api_wakeup_cat1(false);
+        osal_msleep(500);
+        
+        // 关闭4G电源
+        PPP_DEBUG_PRINT("Turning off 4G module power\n");
+        cat1_api_enable_cat1(false);
+        osal_msleep(1000);
+        
+        g_4g_power_initialized = false;
+        PPP_DEBUG_PRINT("4G power disabled successfully\n");
+    }
+
+    // 4. 清理资源
     (void)memset_s(&g_ppp_config, sizeof(ppp_config_t), 0, sizeof(ppp_config_t));
 
     g_ppp_state = PPP_STATE_IDLE;
-    PPP_DEBUG_PRINT("PPP module deinitialized\n");
+    PPP_DEBUG_PRINT("PPP module deinitialized successfully\n");
 
     return ERRCODE_SUCC;
 } 
@@ -366,4 +517,129 @@ ppp_error_t ppp_stop_data_receive_thread(void)
     
     PPP_DEBUG_INFO("PPP data receive thread stopped");
     return PPP_ERR_OK;
+}
+
+/* ========== PPP测试接口实现 ========== */
+
+/**
+ * @brief PPP串口模式切换
+ */
+errcode_t ppp_test_switch_mode(const char *mode)
+{
+    if (mode == NULL) {
+        return ERRCODE_INVALID_PARAM;
+    }
+    
+    ppp_error_t ret;
+    if (strcmp(mode, "AT") == 0) {
+        ret = ppp_serial_switch_to_at_mode();
+    } else if (strcmp(mode, "PPP") == 0) {
+        ret = ppp_serial_switch_to_ppp_mode();
+    } else {
+        return ERRCODE_INVALID_PARAM;
+    }
+    
+    return (ret == PPP_ERR_OK) ? ERRCODE_SUCC : ERRCODE_FAIL;
+}
+
+
+/**
+ * @brief 执行AT指令透传
+ */
+errcode_t ppp_test_execute_at_command(const char *at_command,
+                                     char *response,
+                                     uint32_t response_size,
+                                     uint32_t *response_len,
+                                     uint32_t timeout_ms)
+{
+    if (at_command == NULL || response == NULL || response_len == NULL) {
+        return ERRCODE_INVALID_PARAM;
+    }
+    
+    ppp_at_response_t at_response;
+    ppp_error_t ret = ppp_at_send_command(at_command, NULL, timeout_ms, &at_response);
+    
+    if (ret == PPP_ERR_OK && at_response.success) {
+        uint32_t copy_len = (at_response.length < response_size - 1) ? at_response.length : (response_size - 1);
+        memcpy(response, at_response.response, copy_len);
+        response[copy_len] = '\0';
+        *response_len = copy_len;
+        return ERRCODE_SUCC;
+    } else {
+        *response_len = 0;
+        switch (ret) {
+            case PPP_ERR_INVALID_STATE:
+            case PPP_ERR_INVALID_PARAM:
+                return ERRCODE_INVALID_PARAM;
+            case PPP_ERR_TIMEOUT:
+                return ERRCODE_FAIL;
+            case PPP_ERR_MEMORY:
+                return ERRCODE_MALLOC;
+            default:
+                return ERRCODE_FAIL;
+        }
+    }
+}
+
+/**
+ * @brief PPP串口基础功能测试
+ */
+errcode_t ppp_test_uart_function(void)
+{
+    ppp_error_t ret = ppp_serial_test_uart();
+    return (ret == PPP_ERR_OK) ? ERRCODE_SUCC : ERRCODE_FAIL;
+}
+
+/**
+ * @brief PPP智能flush测试
+ */
+errcode_t ppp_test_smart_flush(void)
+{
+    ppp_error_t ret = ppp_serial_periodic_flush();
+    return (ret == PPP_ERR_OK) ? ERRCODE_SUCC : ERRCODE_FAIL;
+}
+
+/**
+ * @brief 获取PPP测试统计信息
+ */
+errcode_t ppp_test_get_status(char *stats_info, uint32_t buffer_size)
+{
+    if (stats_info == NULL || buffer_size == 0) {
+        return ERRCODE_INVALID_PARAM;
+    }
+    
+    ppp_serial_stats_t stats;
+    ppp_serial_get_stats(&stats);
+    
+    int ret = snprintf(stats_info, buffer_size,
+                      "=== PPP Statistics ===\n"
+                      "Total TX Bytes: %u\n"
+                      "Total RX Bytes: %u\n"
+                      "TX Errors: %u\n"
+                      "RX Errors: %u\n"
+                      "Current RX Buffer Usage: %u/%u (%.1f%%)\n"
+                      "Current TX Buffer Usage: %u/%u (%.1f%%)\n"
+                      "PPP State: %s\n",
+                      stats.tx_bytes,
+                      stats.rx_bytes,
+                      stats.tx_errors,
+                      stats.rx_errors,
+                      stats.rx_buffer_usage, stats.rx_buffer_size,
+                      stats.rx_buffer_size > 0 ? (float)stats.rx_buffer_usage * 100.0f / stats.rx_buffer_size : 0.0f,
+                      stats.tx_buffer_usage, stats.tx_buffer_size,
+                      stats.tx_buffer_size > 0 ? (float)stats.tx_buffer_usage * 100.0f / stats.tx_buffer_size : 0.0f,
+                      (g_ppp_state == PPP_STATE_IDLE) ? "IDLE" :
+                      (g_ppp_state == PPP_STATE_DIALING) ? "DIALING" :
+                      (g_ppp_state == PPP_STATE_CONNECTED) ? "CONNECTED" :
+                      (g_ppp_state == PPP_STATE_DISCONNECTING) ? "DISCONNECTING" : "UNKNOWN");
+    
+    return (ret > 0 && ret < (int)buffer_size) ? ERRCODE_SUCC : ERRCODE_FAIL;
+}
+
+/**
+ * @brief 检查4G电源是否已初始化
+ */
+bool ppp_is_4g_power_initialized(void)
+{
+    return g_4g_power_initialized;
 } 
\ No newline at end of file
index 12e4324..6587a04 100644 (file)
@@ -138,7 +138,7 @@ ppp_error_t ppp_at_baudrate_handshake(void)
         
         /* 增加重试机制 */
         ppp_error_t ret = PPP_ERR_AT_FAILED;
-        for (int retry = 0; retry < 3; retry++) {
+        for (int retry = 0; retry < 1; retry++) {
             PPP_DEBUG_INFO("--- AT Test at %u baud, retry %d/3 ---", baudrate, retry + 1);
             ret = ppp_at_send_command("AT", "OK", 3000, &response);  // 增加超时到3秒
             
@@ -250,11 +250,11 @@ ppp_error_t ppp_at_send_command(const char *command, const char *expected_respon
     uint32_t cmd_len = strlen(cmd_with_crlf);
     
     /* 打印发送的原始数据(十六进制) */
-    PPP_DEBUG_INFO("Sending %u bytes:", cmd_len);
-    for (uint32_t i = 0; i < cmd_len; i++) {
-        PPP_DEBUG_PRINT("%02X ", (uint8_t)cmd_with_crlf[i]);
-    }
-    PPP_DEBUG_PRINT("\n");
+    // PPP_DEBUG_INFO("Sending %u bytes:", cmd_len);
+    // for (uint32_t i = 0; i < cmd_len; i++) {
+    //     PPP_DEBUG_PRINT("%02X ", (uint8_t)cmd_with_crlf[i]);
+    // }
+    // PPP_DEBUG_PRINT("\n");
     
     /* 打印发送的字符串(可见字符) */
     char printable_cmd[PPP_AT_CMD_MAX_LEN + 20];
@@ -292,11 +292,11 @@ ppp_error_t ppp_at_send_command(const char *command, const char *expected_respon
         PPP_DEBUG_INFO("Response received (%u bytes):", response->length);
         
         /* 打印接收的原始数据(十六进制) */
-        for (uint32_t i = 0; i < response->length; i++) {
-            PPP_DEBUG_PRINT("%02X ", (uint8_t)response->response[i]);
-            if ((i + 1) % 16 == 0) PPP_DEBUG_PRINT("\n");
-        }
-        if (response->length % 16 != 0) PPP_DEBUG_PRINT("\n");
+        // for (uint32_t i = 0; i < response->length; i++) {
+        //     PPP_DEBUG_PRINT("%02X ", (uint8_t)response->response[i]);
+        //     if ((i + 1) % 16 == 0) PPP_DEBUG_PRINT("\n");
+        // }
+        // if (response->length % 16 != 0) PPP_DEBUG_PRINT("\n");
         
         /* 打印接收的字符串(可见字符) */
         char printable_resp[PPP_AT_RESPONSE_MAX_LEN + 100];
@@ -401,7 +401,23 @@ ppp_error_t ppp_at_complete_dial_sequence(const char *apn)
     }
     PPP_DEBUG_INFO("AT handshake successful");
     
-    // 3. 设置PDP上下文 (对应chat文件: OK 'AT+CGDCONT=3,"IP"')
+    // 3. 设置固定波特率 (AT+IPR=2000000,掉电保持)
+    // 获取当前波特率并设置为固定波特率
+    uint32_t current_baudrate = ppp_at_get_current_baudrate();
+    if (current_baudrate > 0) {
+        PPP_DEBUG_INFO("Setting fixed baudrate to %u (power-off persistent)", current_baudrate);
+        ret = ppp_at_send_command("AT+IPR=2000000", "OK", 5000, &response);
+        if (ret != PPP_ERR_OK) {
+            PPP_DEBUG_WARN("Failed to set fixed baudrate AT+IPR=2000000, continuing with current rate");
+            // 不作为致命错误,继续执行
+        } else {
+            PPP_DEBUG_INFO("Fixed baudrate 2000000 set successfully (power-off persistent)");
+            // 注意:这里不立即更改串口波特率,因为模块需要时间应用设置
+            // 下次开机时模块将自动使用2M波特率
+        }
+    }
+    
+    // 4. 设置PDP上下文 (对应chat文件: OK 'AT+CGDCONT=3,"IP"')
     char cgdcont_cmd[128];
     if (apn && strlen(apn) > 0) {
         snprintf_s(cgdcont_cmd, sizeof(cgdcont_cmd), sizeof(cgdcont_cmd) - 1, 
@@ -418,7 +434,7 @@ ppp_error_t ppp_at_complete_dial_sequence(const char *apn)
     }
     PPP_DEBUG_INFO("PDP context set successfully");
     
-    // 4. 发送PPP拨号指令 (对应chat文件: OK 'ATD*99***2#' -> CONNECTED)
+    // 5. 发送PPP拨号指令 (对应chat文件: OK 'ATD*99***2#' -> CONNECTED)
     ret = ppp_at_send_command("ATD*99***2#", "CONNECT", 30000, &response);
     if (ret != PPP_ERR_OK) {
         PPP_DEBUG_ERROR("PPP dial failed");
index f45a6b2..19af1cf 100644 (file)
@@ -133,6 +133,14 @@ void cat1_api_enable_cat1(bool isopen)
     }
 }
 
+/**
+ * @brief cat1 唤醒设置, 输入 true 唤醒cat1 modem, false cat1 modem自动休眠
+ */
+void cat1_api_wakeup_cat1(uint8_t wakeup)
+{
+    ppp_api_wakeup_cat1(wakeup);
+}
+
 /**
  * @brief 获取cat1是否使能(开机)状态
  */
@@ -351,13 +359,6 @@ void cat1_api_runtime_set_cat1_modemver(char* modemver)
 
 /********************** 控制接口 **********************/
 
-/**
- * @brief 唤醒Cat1
- */
-void cat1_api_wakeup_cat1(uint8_t wakeup)
-{
-    ppp_api_wakeup_cat1(wakeup);
-}
 
 /**
  * @brief 保持唤醒Cat1
index 2d4c000..a371938 100644 (file)
@@ -57,8 +57,8 @@ static ppp_ctl_pin_4g_t g_ppp_cat1_ctl_pins = {
     0,
     PIN_NONE,//ring_pin
     0,
-    PIN_NONE,//wakemodem_pin
-    0,
+    S_MGPIO22,//wakemodem_pin
+    1,
     #else
     PIN_NONE, //bat_pin
     1,
index 7053144..b871f2b 100644 (file)
@@ -11,7 +11,7 @@
 #include "securec.h"
 #include <string.h>
 
-/* 串口上下文结构 - 恢复缓存机制 */
+/* 串口上下文结构 - 优化缓存机制 */
 typedef struct {
     bool initialized;
     ppp_serial_mode_t current_mode;
@@ -22,20 +22,24 @@ typedef struct {
     uart_attr_t uart_attr;
     uart_buffer_config_t buffer_config;
     
-    /* 接收缓冲区(用于PPP数据模式) */
+    /* 统一的接收缓冲区(AT和PPP模式共用) */
     uint8_t *rx_buffer;
     uint32_t rx_buffer_size;
     uint32_t rx_head;
     uint32_t rx_tail;
     uint32_t rx_count;
     
-    /* 发送缓冲区(用于PPP数据模式) */
+    /* PPP模式的发送缓冲区 */
     uint8_t *tx_buffer;
     uint32_t tx_buffer_size;
+    uint32_t tx_head;
+    uint32_t tx_tail;
+    uint32_t tx_count;
     
     /* 同步对象 */
     osal_mutex rx_mutex;        // 改为结构体而不是指针
     osal_semaphore rx_semaphore; // 改为结构体而不是指针
+    osal_mutex tx_mutex;        // 发送缓冲区互斥锁
     
     /* 回调函数 */
     ppp_serial_rx_callback_t rx_callback;
@@ -46,6 +50,11 @@ typedef struct {
     uint32_t rx_bytes;
     uint32_t tx_errors;
     uint32_t rx_errors;
+    
+    /* 智能flush策略相关 */
+    uint32_t last_tx_time;              // 最后发送时间(ms)
+    uint32_t consecutive_small_packets; // 连续小包计数
+    uint32_t idle_flush_threshold;      // 空闲flush阈值(ms)
 } ppp_serial_context_t;
 
 static ppp_serial_context_t g_serial_ctx = {0};
@@ -54,9 +63,15 @@ static ppp_serial_context_t g_serial_ctx = {0};
 static void ppp_serial_rx_callback(const void *buffer, uint16_t length, bool remaining);
 static uint32_t ppp_serial_buffer_available_space(void);
 static uint32_t ppp_serial_buffer_data_count(void);
+static uint32_t ppp_serial_tx_buffer_available_space(void);
+static uint32_t ppp_serial_tx_buffer_data_count(void);
+static ppp_error_t ppp_serial_flush_tx_buffer_internal(void);
+static bool ppp_serial_is_ppp_control_packet(const uint8_t *data, uint32_t length);
+static bool ppp_serial_should_immediate_flush(const uint8_t *data, uint32_t length, uint32_t buffered_count);
+static uint32_t ppp_serial_get_current_time_ms(void);
 
 /**
- * @brief 初始化PPP串口 - AT命令模式,准备缓存机制
+ * @brief 初始化PPP串口 - 统一缓冲区管理
  */
 ppp_error_t ppp_serial_init(const ppp_serial_config_t *config)
 {
@@ -64,7 +79,18 @@ ppp_error_t ppp_serial_init(const ppp_serial_config_t *config)
         return PPP_ERR_INVALID_PARAM;
     }
 
-    PPP_DEBUG_INFO("Initializing PPP serial in AT command mode with buffer support");
+    PPP_DEBUG_INFO("=== PPP Serial Initialization Start ===");
+    PPP_DEBUG_INFO("Initializing PPP serial with unified buffer management");
+
+    /* 打印配置参数 */
+    PPP_DEBUG_INFO("Configuration parameters:");
+    PPP_DEBUG_INFO("  - UART Bus: %u", config->uart_bus);
+    PPP_DEBUG_INFO("  - Baudrate: %u", config->baudrate);
+    PPP_DEBUG_INFO("  - TX Pin: %u", config->tx_pin);
+    PPP_DEBUG_INFO("  - RX Pin: %u", config->rx_pin);
+    PPP_DEBUG_INFO("  - RX Buffer Size: %u bytes", config->rx_buffer_size);
+    PPP_DEBUG_INFO("  - TX Buffer Size: %u bytes", config->tx_buffer_size);
+    PPP_DEBUG_INFO("  - RX Callback: %s", config->rx_callback ? "Set" : "NULL");
 
     /* 配置UART参数 */
     g_serial_ctx.uart_bus = config->uart_bus;
@@ -75,63 +101,118 @@ ppp_error_t ppp_serial_init(const ppp_serial_config_t *config)
     g_serial_ctx.uart_attr.stop_bits = UART_STOP_BIT_1;
     g_serial_ctx.uart_attr.parity = UART_PARITY_NONE;
 
-    /* 配置UART缓冲区 */
-    static uint8_t uart_rx_buffer[256];
-    g_serial_ctx.buffer_config.rx_buffer = uart_rx_buffer;
-    g_serial_ctx.buffer_config.rx_buffer_size = sizeof(uart_rx_buffer);
+    PPP_DEBUG_INFO("UART attributes configured:");
+    PPP_DEBUG_INFO("  - Baud Rate: %u", g_serial_ctx.uart_attr.baud_rate);
+    PPP_DEBUG_INFO("  - Data Bits: %d", g_serial_ctx.uart_attr.data_bits);
+    PPP_DEBUG_INFO("  - Stop Bits: %d", g_serial_ctx.uart_attr.stop_bits);
+    PPP_DEBUG_INFO("  - Parity: %d", g_serial_ctx.uart_attr.parity);
 
-    /* 初始化UART(AT命令模式) */
-    errcode_t ret = uapi_uart_init(g_serial_ctx.uart_bus, 
-                                   &g_serial_ctx.pin_config,
-                                   &g_serial_ctx.uart_attr, 
-                                   NULL, 
-                                   &g_serial_ctx.buffer_config);
-    if (ret != ERRCODE_SUCC) {
-        PPP_DEBUG_ERROR("Failed to initialize UART for AT mode: %d", ret);
-        return PPP_ERR_UART;
-    }
-
-    /* 分配PPP数据模式的接收缓冲区 */
+    /* 动态分配统一的接收缓冲区 */
     g_serial_ctx.rx_buffer_size = config->rx_buffer_size;
     g_serial_ctx.rx_buffer = (uint8_t *)osal_kmalloc(g_serial_ctx.rx_buffer_size, OSAL_GFP_KERNEL);
     if (g_serial_ctx.rx_buffer == NULL) {
-        PPP_DEBUG_ERROR("Failed to allocate RX buffer");
-        uapi_uart_deinit(g_serial_ctx.uart_bus);
+        PPP_DEBUG_ERROR("Failed to allocate RX buffer (%u bytes)", g_serial_ctx.rx_buffer_size);
         return PPP_ERR_MEMORY;
     }
+    PPP_DEBUG_INFO("RX buffer allocated: %u bytes at 0x%p", g_serial_ctx.rx_buffer_size, g_serial_ctx.rx_buffer);
 
-    /* å\88\86é\85\8dPPPæ\95°æ\8d®æ¨¡å¼\8fç\9a\84发送缓冲区 */
+    /* å\8a¨æ\80\81å\88\86é\85\8d发送缓冲区 */
     g_serial_ctx.tx_buffer_size = config->tx_buffer_size;
     g_serial_ctx.tx_buffer = (uint8_t *)osal_kmalloc(g_serial_ctx.tx_buffer_size, OSAL_GFP_KERNEL);
     if (g_serial_ctx.tx_buffer == NULL) {
-        PPP_DEBUG_ERROR("Failed to allocate TX buffer");
+        PPP_DEBUG_ERROR("Failed to allocate TX buffer (%u bytes)", g_serial_ctx.tx_buffer_size);
         osal_kfree(g_serial_ctx.rx_buffer);
+        g_serial_ctx.rx_buffer = NULL;
+        return PPP_ERR_MEMORY;
+    }
+    PPP_DEBUG_INFO("TX buffer allocated: %u bytes at 0x%p", g_serial_ctx.tx_buffer_size, g_serial_ctx.tx_buffer);
+
+    /* 创建发送缓冲区互斥锁 */
+    if (osal_mutex_init(&g_serial_ctx.tx_mutex) != OSAL_SUCCESS) {
+        PPP_DEBUG_ERROR("Failed to create TX mutex");
+        osal_kfree(g_serial_ctx.rx_buffer);
+        g_serial_ctx.rx_buffer = NULL;
+        osal_kfree(g_serial_ctx.tx_buffer);
+        g_serial_ctx.tx_buffer = NULL;
         uapi_uart_deinit(g_serial_ctx.uart_bus);
         return PPP_ERR_MEMORY;
     }
+    PPP_DEBUG_INFO("TX mutex created successfully");
+
+    /* 配置UART使用我们分配的接收缓冲区 */
+    g_serial_ctx.buffer_config.rx_buffer = g_serial_ctx.rx_buffer;
+    g_serial_ctx.buffer_config.rx_buffer_size = g_serial_ctx.rx_buffer_size;
+
+    PPP_DEBUG_INFO("UART buffer config:");
+    PPP_DEBUG_INFO("  - RX Buffer Address: 0x%p", g_serial_ctx.buffer_config.rx_buffer);
+    PPP_DEBUG_INFO("  - RX Buffer Size: %u", g_serial_ctx.buffer_config.rx_buffer_size);
+    PPP_DEBUG_INFO("PPP TX buffer (software managed):");
+    PPP_DEBUG_INFO("  - TX Buffer Address: 0x%p", g_serial_ctx.tx_buffer);
+    PPP_DEBUG_INFO("  - TX Buffer Size: %u", g_serial_ctx.tx_buffer_size);
+
+    // errcode_t rett = uapi_uart_deinit(g_serial_ctx.uart_bus);
+    // if (rett != ERRCODE_SUCC) {
+    //     PPP_DEBUG_ERROR("Failed to deinitialize UART: error code = %d (0x%x)", rett, rett);
+    //     osal_kfree(g_serial_ctx.rx_buffer);
+    //     g_serial_ctx.rx_buffer = NULL;
+    //     return PPP_ERR_UART;
+    // }
+    // PPP_DEBUG_INFO("UART deinitialized successfully");
+
+    /* 初始化UART */
+    PPP_DEBUG_INFO("Calling uapi_uart_init...");
+    errcode_t ret = uapi_uart_init(g_serial_ctx.uart_bus, 
+                                   &g_serial_ctx.pin_config,
+                                   &g_serial_ctx.uart_attr, 
+                                   NULL, 
+                                   &g_serial_ctx.buffer_config);
+    if (ret != ERRCODE_SUCC) {
+        PPP_DEBUG_ERROR("Failed to initialize UART: error code = %d (0x%x)", ret, ret);
+        PPP_DEBUG_ERROR("UART init failed with bus=%u, tx_pin=%u, rx_pin=%u, baudrate=%u", 
+                       g_serial_ctx.uart_bus, config->tx_pin, config->rx_pin, config->baudrate);
+        osal_kfree(g_serial_ctx.rx_buffer);
+        g_serial_ctx.rx_buffer = NULL;
+        osal_kfree(g_serial_ctx.tx_buffer);
+        g_serial_ctx.tx_buffer = NULL;
+        osal_mutex_destroy(&g_serial_ctx.tx_mutex);
+        return PPP_ERR_UART;
+    }
+    PPP_DEBUG_INFO("UART initialized successfully (error code = %d)", ret);
 
     /* 创建同步对象 */
+    PPP_DEBUG_INFO("Creating synchronization objects...");
     if (osal_mutex_init(&g_serial_ctx.rx_mutex) != OSAL_SUCCESS) {
         PPP_DEBUG_ERROR("Failed to create RX mutex");
-        osal_kfree(g_serial_ctx.tx_buffer);
         osal_kfree(g_serial_ctx.rx_buffer);
+        g_serial_ctx.rx_buffer = NULL;
+        osal_kfree(g_serial_ctx.tx_buffer);
+        g_serial_ctx.tx_buffer = NULL;
         uapi_uart_deinit(g_serial_ctx.uart_bus);
+        osal_mutex_destroy(&g_serial_ctx.tx_mutex);
         return PPP_ERR_MEMORY;
     }
+    PPP_DEBUG_INFO("RX mutex created successfully");
 
     if (osal_sem_init(&g_serial_ctx.rx_semaphore, 0) != OSAL_SUCCESS) {
         PPP_DEBUG_ERROR("Failed to create RX semaphore");
         osal_mutex_destroy(&g_serial_ctx.rx_mutex);
-        osal_kfree(g_serial_ctx.tx_buffer);
         osal_kfree(g_serial_ctx.rx_buffer);
+        g_serial_ctx.rx_buffer = NULL;
+        osal_kfree(g_serial_ctx.tx_buffer);
+        g_serial_ctx.tx_buffer = NULL;
         uapi_uart_deinit(g_serial_ctx.uart_bus);
+        osal_mutex_destroy(&g_serial_ctx.tx_mutex);
         return PPP_ERR_MEMORY;
     }
+    PPP_DEBUG_INFO("RX semaphore created successfully");
 
     /* 初始化缓冲区状态 */
     g_serial_ctx.rx_head = 0;
     g_serial_ctx.rx_tail = 0;
     g_serial_ctx.rx_count = 0;
+    g_serial_ctx.tx_head = 0;
+    g_serial_ctx.tx_tail = 0;
+    g_serial_ctx.tx_count = 0;
     g_serial_ctx.rx_callback = config->rx_callback;
     g_serial_ctx.rx_callback_arg = config->rx_callback_arg;
 
@@ -143,17 +224,30 @@ ppp_error_t ppp_serial_init(const ppp_serial_config_t *config)
     g_serial_ctx.rx_bytes = 0;
     g_serial_ctx.tx_errors = 0;
     g_serial_ctx.rx_errors = 0;
-
-    PPP_DEBUG_INFO("PPP serial initialized in AT command mode with buffer support");
+    
+    /* 初始化智能flush策略参数 */
+    g_serial_ctx.last_tx_time = ppp_serial_get_current_time_ms();
+    g_serial_ctx.consecutive_small_packets = 0;
+    g_serial_ctx.idle_flush_threshold = 10;  // 10ms空闲超时
+
+    PPP_DEBUG_INFO("Buffer state initialized:");
+    PPP_DEBUG_INFO("  - RX Head/Tail/Count: %u/%u/%u", g_serial_ctx.rx_head, g_serial_ctx.rx_tail, g_serial_ctx.rx_count);
+    PPP_DEBUG_INFO("  - TX Head/Tail/Count: %u/%u/%u", g_serial_ctx.tx_head, g_serial_ctx.tx_tail, g_serial_ctx.tx_count);
+    PPP_DEBUG_INFO("  - Current Mode: %d (AT)", g_serial_ctx.current_mode);
+    PPP_DEBUG_INFO("  - Initialized Flag: %s", g_serial_ctx.initialized ? "true" : "false");
+
+    PPP_DEBUG_INFO("PPP serial initialized successfully with unified buffer (%u bytes)", g_serial_ctx.rx_buffer_size);
+    PPP_DEBUG_INFO("=== PPP Serial Initialization Complete ===");
     return PPP_ERR_OK;
 }
 
 /**
- * @brief 切换到PPP数据模式 - 启用缓存机制和UART接收回调
+ * @brief 切换到PPP数据模式 - 启用回调机制进行缓冲区管理
  */
 ppp_error_t ppp_serial_switch_to_ppp_mode(void)
 {
     if (!g_serial_ctx.initialized) {
+        PPP_DEBUG_ERROR("PPP serial not initialized");
         return PPP_ERR_INVALID_PARAM;
     }
 
@@ -162,7 +256,9 @@ ppp_error_t ppp_serial_switch_to_ppp_mode(void)
         return PPP_ERR_OK;
     }
 
-    PPP_DEBUG_INFO("Switching serial from AT mode to PPP data mode (enable buffering)");
+    PPP_DEBUG_INFO("=== Switching to PPP Data Mode ===");
+    PPP_DEBUG_INFO("Current mode: %d (AT) -> %d (PPP_DATA)", g_serial_ctx.current_mode, PPP_SERIAL_MODE_PPP_DATA);
+    PPP_DEBUG_INFO("UART Bus: %u", g_serial_ctx.uart_bus);
 
     /* 清空接收缓冲区 */
     osal_mutex_lock(&g_serial_ctx.rx_mutex);
@@ -171,27 +267,44 @@ ppp_error_t ppp_serial_switch_to_ppp_mode(void)
     g_serial_ctx.rx_count = 0;
     osal_mutex_unlock(&g_serial_ctx.rx_mutex);
 
-    /* 注册UART接收回调,启用缓存机制 */
+    /* 清空发送缓冲区 */
+    osal_mutex_lock(&g_serial_ctx.tx_mutex);
+    g_serial_ctx.tx_head = 0;
+    g_serial_ctx.tx_tail = 0;
+    g_serial_ctx.tx_count = 0;
+    osal_mutex_unlock(&g_serial_ctx.tx_mutex);
+    PPP_DEBUG_INFO("TX buffer cleared for mode switch");
+
+    /* 注册UART接收回调,启用软件缓冲区管理 */
+    PPP_DEBUG_INFO("Registering UART RX callback...");
+    PPP_DEBUG_INFO("  - Bus: %u", g_serial_ctx.uart_bus);
+    PPP_DEBUG_INFO("  - Condition: UART_RX_CONDITION_FULL_OR_SUFFICIENT_DATA_OR_IDLE");
+    PPP_DEBUG_INFO("  - Buffer size: %u", g_serial_ctx.rx_buffer_size);
+    PPP_DEBUG_INFO("  - Callback function: %p", ppp_serial_rx_callback);
+    
     errcode_t ret = uapi_uart_register_rx_callback(g_serial_ctx.uart_bus, 
                                                    UART_RX_CONDITION_FULL_OR_SUFFICIENT_DATA_OR_IDLE,
                                                    g_serial_ctx.rx_buffer_size,
                                                    ppp_serial_rx_callback);
     if (ret != ERRCODE_SUCC) {
-        PPP_DEBUG_ERROR("Failed to register UART RX callback: %d", ret);
+        PPP_DEBUG_ERROR("Failed to register UART RX callback: error code = %d (0x%x)", ret, ret);
         return PPP_ERR_UART;
     }
+    PPP_DEBUG_INFO("UART RX callback registered successfully");
     
     g_serial_ctx.current_mode = PPP_SERIAL_MODE_PPP_DATA;
-    PPP_DEBUG_INFO("Successfully switched to PPP data mode with buffering enabled");
+    PPP_DEBUG_INFO("Mode switched to PPP_DATA (%d)", g_serial_ctx.current_mode);
+    PPP_DEBUG_INFO("=== PPP Data Mode Switch Complete ===");
     return PPP_ERR_OK;
 }
 
 /**
- * @brief 切换回AT命令模式 - 禁用缓存机制和UART接收回调
+ * @brief 切换回AT命令模式 - 禁用回调机制,直接使用UART缓冲区
  */
 ppp_error_t ppp_serial_switch_to_at_mode(void)
 {
     if (!g_serial_ctx.initialized) {
+        PPP_DEBUG_ERROR("PPP serial not initialized");
         return PPP_ERR_INVALID_PARAM;
     }
 
@@ -200,62 +313,137 @@ ppp_error_t ppp_serial_switch_to_at_mode(void)
         return PPP_ERR_OK;
     }
 
-    PPP_DEBUG_INFO("Switching serial from PPP data mode to AT mode (disable buffering)");
+    PPP_DEBUG_INFO("=== Switching to AT Mode ===");
+    PPP_DEBUG_INFO("Current mode: %d (PPP_DATA) -> %d (AT)", g_serial_ctx.current_mode, PPP_SERIAL_MODE_AT);
+    PPP_DEBUG_INFO("UART Bus: %u", g_serial_ctx.uart_bus);
 
-    /* 取消注册UART接收回调,禁用缓存机制 */
+    /* 取消注册UART接收回调,回到直接UART读取模式 */
+    PPP_DEBUG_INFO("Unregistering UART RX callback...");
     uapi_uart_unregister_rx_callback(g_serial_ctx.uart_bus);
+    PPP_DEBUG_INFO("UART RX callback unregistered");
 
     /* 清空接收缓冲区 */
+    PPP_DEBUG_INFO("Clearing RX buffer...");
     osal_mutex_lock(&g_serial_ctx.rx_mutex);
+    uint32_t old_rx_count = g_serial_ctx.rx_count;
     g_serial_ctx.rx_head = 0;
     g_serial_ctx.rx_tail = 0;
     g_serial_ctx.rx_count = 0;
     osal_mutex_unlock(&g_serial_ctx.rx_mutex);
+    PPP_DEBUG_INFO("RX buffer cleared (discarded %u bytes)", old_rx_count);
+
+    /* 清空发送缓冲区 */
+    PPP_DEBUG_INFO("Clearing TX buffer...");
+    osal_mutex_lock(&g_serial_ctx.tx_mutex);
+    uint32_t old_tx_count = g_serial_ctx.tx_count;
+    g_serial_ctx.tx_head = 0;
+    g_serial_ctx.tx_tail = 0;
+    g_serial_ctx.tx_count = 0;
+    osal_mutex_unlock(&g_serial_ctx.tx_mutex);
+    PPP_DEBUG_INFO("TX buffer cleared (discarded %u bytes)", old_tx_count);
 
     g_serial_ctx.current_mode = PPP_SERIAL_MODE_AT;
-    PPP_DEBUG_INFO("Successfully switched back to AT command mode");
+    PPP_DEBUG_INFO("Mode switched to AT (%d)", g_serial_ctx.current_mode);
+    PPP_DEBUG_INFO("=== AT Mode Switch Complete ===");
     return PPP_ERR_OK;
 }
 
 /**
- * @brief 发送数据 - 根据模式选择直接发送或缓存发送
+ * @brief 发送数据 - 两种模式都直接通过UART发送
  */
 ppp_error_t ppp_serial_write(const uint8_t *data, uint32_t length)
 {
     if (!g_serial_ctx.initialized || !data || length == 0) {
+        PPP_DEBUG_ERROR("Invalid parameters: initialized=%s, data=%p, length=%u", 
+                       g_serial_ctx.initialized ? "true" : "false", data, length);
         return PPP_ERR_INVALID_PARAM;
     }
 
+    PPP_DEBUG_INFO("=== PPP Serial Write Start ===");
+    PPP_DEBUG_INFO("Write request: %u bytes in mode %d", length, g_serial_ctx.current_mode);
+    PPP_DEBUG_INFO("UART Bus: %u", g_serial_ctx.uart_bus);
+
     ppp_error_t result = PPP_ERR_OK;
 
     switch (g_serial_ctx.current_mode) {
         case PPP_SERIAL_MODE_AT:
             /* AT命令模式:直接使用UART发送 */
-            PPP_DEBUG_DEBUG("Sending %u bytes via UART (AT mode)", length);
-            PPP_DEBUG_HEXDUMP(data, length);
+            PPP_DEBUG_INFO("Sending %u bytes via UART (AT mode)", length);
+            // PPP_DEBUG_HEXDUMP(data, length);
+            
+            PPP_DEBUG_INFO("Calling uapi_uart_write(bus=%u, data=%p, len=%u, timeout=1000)...", 
+                          g_serial_ctx.uart_bus, data, length);
+            
+            int32_t write_result = uapi_uart_write(g_serial_ctx.uart_bus, data, length, 1000);
+            PPP_DEBUG_INFO("uapi_uart_write returned: %d (expected: %u)", write_result, length);
             
-            if (uapi_uart_write(g_serial_ctx.uart_bus, data, length, 1000) != (int32_t)length) {
-                PPP_DEBUG_ERROR("UART write failed in AT mode");
+            if (write_result != (int32_t)length) {
+                PPP_DEBUG_ERROR("UART write failed in AT mode: returned %d, expected %u", write_result, length);
+                PPP_DEBUG_ERROR("Possible causes: UART not initialized, hardware error, or timeout");
                 g_serial_ctx.tx_errors++;
                 result = PPP_ERR_UART;
             } else {
                 g_serial_ctx.tx_bytes += length;
-                PPP_DEBUG_DEBUG("Sent %u bytes successfully via UART", length);
+                PPP_DEBUG_INFO("Sent %u bytes successfully via UART (total tx: %u bytes)", 
+                              length, g_serial_ctx.tx_bytes);
             }
             break;
 
         case PPP_SERIAL_MODE_PPP_DATA:
-            /* PPP数据模式:直接使用UART发送(PPP数据通常需要立即发送) */
-            PPP_DEBUG_DEBUG("Sending %u bytes via UART (PPP data mode)", length);
-            PPP_DEBUG_HEXDUMP(data, length);
+            /* PPP数据模式:使用缓冲发送 */
+            PPP_DEBUG_INFO("Buffering %u bytes for PPP data mode", length);
+            // PPP_DEBUG_HEXDUMP(data, length);
             
-            if (uapi_uart_write(g_serial_ctx.uart_bus, data, length, 1000) != (int32_t)length) {
-                PPP_DEBUG_ERROR("UART write failed in PPP data mode");
-                g_serial_ctx.tx_errors++;
-                result = PPP_ERR_UART;
+            osal_mutex_lock(&g_serial_ctx.tx_mutex);
+            
+            /* 检查缓冲区空间 */
+            uint32_t available_space = ppp_serial_tx_buffer_available_space();
+            if (available_space < length) {
+                PPP_DEBUG_WARN("TX buffer insufficient space: need %u, available %u", length, available_space);
+                
+                /* 先尝试发送现有缓冲区数据 */
+                osal_mutex_unlock(&g_serial_ctx.tx_mutex);
+                ppp_error_t flush_result = ppp_serial_flush_tx();
+                if (flush_result != PPP_ERR_OK) {
+                    PPP_DEBUG_ERROR("Failed to flush TX buffer before new write");
+                    result = flush_result;
+                    break;
+                }
+                osal_mutex_lock(&g_serial_ctx.tx_mutex);
+                
+                /* 重新检查空间 */
+                available_space = ppp_serial_tx_buffer_available_space();
+                if (available_space < length) {
+                    PPP_DEBUG_ERROR("TX buffer still insufficient after flush: need %u, available %u", 
+                                   length, available_space);
+                    osal_mutex_unlock(&g_serial_ctx.tx_mutex);
+                    g_serial_ctx.tx_errors++;
+                    result = PPP_ERR_UART;
+                    break;
+                }
+            }
+            
+            /* 将数据复制到发送缓冲区 */
+            for (uint32_t i = 0; i < length; i++) {
+                g_serial_ctx.tx_buffer[g_serial_ctx.tx_head] = data[i];
+                g_serial_ctx.tx_head = (g_serial_ctx.tx_head + 1) % g_serial_ctx.tx_buffer_size;
+                g_serial_ctx.tx_count++;
+            }
+            
+            uint32_t buffered_count = g_serial_ctx.tx_count;
+            osal_mutex_unlock(&g_serial_ctx.tx_mutex);
+            
+            PPP_DEBUG_INFO("Buffered %u bytes (total buffered: %u bytes)", length, buffered_count);
+            
+            /* 智能flush策略:根据PPP协议特性决定是否立即发送 */
+            if (ppp_serial_should_immediate_flush(data, length, buffered_count)) {
+                PPP_DEBUG_INFO("Smart flush triggered (buffered: %u, packet: %u bytes)", 
+                              buffered_count, length);
+                result = ppp_serial_flush_tx();
+                g_serial_ctx.last_tx_time = ppp_serial_get_current_time_ms();
             } else {
                 g_serial_ctx.tx_bytes += length;
-                PPP_DEBUG_DEBUG("Sent %u bytes successfully via UART", length);
+                PPP_DEBUG_INFO("Data buffered smartly (total: %u bytes, will flush when appropriate)", buffered_count);
             }
             break;
 
@@ -265,11 +453,16 @@ ppp_error_t ppp_serial_write(const uint8_t *data, uint32_t length)
             break;
     }
 
+    PPP_DEBUG_INFO("Write result: %s (error code: %d)", 
+                   result == PPP_ERR_OK ? "SUCCESS" : "FAILED", result);
+    PPP_DEBUG_INFO("Statistics: tx_bytes=%u, tx_errors=%u", g_serial_ctx.tx_bytes, g_serial_ctx.tx_errors);
+    PPP_DEBUG_INFO("=== PPP Serial Write End ===");
+
     return result;
 }
 
 /**
- * @brief 读取数据 - 根据模式选择直接读取或从缓存读取
+ * @brief 读取数据 - AT模式直接从UART读取,PPP模式从软件缓冲区读取
  */
 ppp_error_t ppp_serial_read(uint8_t *buffer, uint32_t buffer_size, uint32_t *bytes_read)
 {
@@ -289,7 +482,7 @@ ppp_error_t ppp_serial_read(uint8_t *buffer, uint32_t buffer_size, uint32_t *byt
                     *bytes_read = (uint32_t)read_result;
                     g_serial_ctx.rx_bytes += *bytes_read;
                     PPP_DEBUG_DEBUG("Read %u bytes via UART (AT mode)", *bytes_read);
-                    PPP_DEBUG_HEXDUMP(buffer, *bytes_read);
+                    // PPP_DEBUG_HEXDUMP(buffer, *bytes_read);
                 } else if (read_result < 0) {
                     PPP_DEBUG_ERROR("UART read error in AT mode: %d", read_result);
                     g_serial_ctx.rx_errors++;
@@ -299,7 +492,7 @@ ppp_error_t ppp_serial_read(uint8_t *buffer, uint32_t buffer_size, uint32_t *byt
             break;
 
         case PPP_SERIAL_MODE_PPP_DATA:
-            /* PPP数据模式:从缓存读取 */
+            /* PPP数据模式:从软件环形缓冲区读取 */
             osal_mutex_lock(&g_serial_ctx.rx_mutex);
 
             uint32_t available = ppp_serial_buffer_data_count();
@@ -319,8 +512,8 @@ ppp_error_t ppp_serial_read(uint8_t *buffer, uint32_t buffer_size, uint32_t *byt
             *bytes_read = to_read;
             osal_mutex_unlock(&g_serial_ctx.rx_mutex);
 
-            PPP_DEBUG_DEBUG("Read %u bytes from buffer (PPP data mode)", to_read);
-            PPP_DEBUG_HEXDUMP(buffer, to_read);
+            PPP_DEBUG_DEBUG("Read %u bytes from software buffer (PPP data mode)", to_read);
+            // PPP_DEBUG_HEXDUMP(buffer, to_read);
             break;
 
         default:
@@ -371,9 +564,121 @@ uint32_t ppp_serial_available(void)
     uint32_t count = ppp_serial_buffer_data_count();
     osal_mutex_unlock(&g_serial_ctx.rx_mutex);
 
-    return count;
+        return count;
 }
 
+/* 智能flush策略实现函数 */
+
+/**
+ * @brief 获取当前时间(毫秒)
+ */
+static uint32_t ppp_serial_get_current_time_ms(void)
+{
+    unsigned long long jiffies = osal_get_jiffies();
+    return (uint32_t)osal_jiffies_to_msecs((unsigned int)jiffies);
+}
+
+/**
+ * @brief 检测是否为PPP控制包
+ */
+static bool ppp_serial_is_ppp_control_packet(const uint8_t *data, uint32_t length)
+{
+    if (length < 4) {
+        return false;
+    }
+    
+    // PPP协议标识符检查 (跳过地址和控制字段)
+    uint16_t protocol = (data[2] << 8) | data[3];
+    
+    switch (protocol) {
+        case 0xC021:  // LCP (Link Control Protocol)
+        case 0xC023:  // PAP (Password Authentication Protocol)  
+        case 0xC223:  // CHAP (Challenge Handshake Authentication Protocol)
+        case 0x8021:  // IPCP (IP Control Protocol)
+        case 0x8057:  // IPv6CP
+            PPP_DEBUG_DEBUG("PPP control packet detected: protocol=0x%04X", protocol);
+            return true;
+        default:
+            return false;
+    }
+}
+
+/**
+ * @brief 智能flush决策函数
+ */
+static bool ppp_serial_should_immediate_flush(const uint8_t *data, uint32_t length, uint32_t buffered_count)
+{
+    uint32_t current_time = ppp_serial_get_current_time_ms();
+    uint32_t time_since_last_tx = current_time - g_serial_ctx.last_tx_time;
+    
+    // 1. PPP控制包立即发送(最高优先级)
+    if (ppp_serial_is_ppp_control_packet(data, length)) {
+        PPP_DEBUG_INFO("PPP control packet detected, immediate flush");
+        return true;
+    }
+    
+    // 2. 缓冲区接近满(87.5%阈值,比原来的75%更保守)
+    if (buffered_count >= (g_serial_ctx.tx_buffer_size * 7 / 8)) {
+        PPP_DEBUG_INFO("Buffer nearly full (%u/%u), immediate flush", 
+                      buffered_count, g_serial_ctx.tx_buffer_size);
+        return true;
+    }
+    
+    // 3. 大包立即发送(降低阈值到128字节,避免分片)
+    if (length >= 128) {
+        PPP_DEBUG_INFO("Large packet (%u bytes), immediate flush", length);
+        return true;
+    }
+    
+    // 4. 空闲时间超过阈值
+    if (time_since_last_tx >= g_serial_ctx.idle_flush_threshold) {
+        PPP_DEBUG_INFO("Idle timeout (%u ms), immediate flush", time_since_last_tx);
+        return true;
+    }
+    
+    // 5. 连续小包累积策略
+    if (length <= 32) {
+        g_serial_ctx.consecutive_small_packets++;
+        if (g_serial_ctx.consecutive_small_packets >= 3) {
+            PPP_DEBUG_INFO("Multiple small packets accumulated (%u), immediate flush", 
+                          g_serial_ctx.consecutive_small_packets);
+            g_serial_ctx.consecutive_small_packets = 0;
+            return true;
+        }
+    } else {
+        g_serial_ctx.consecutive_small_packets = 0;
+    }
+    
+    return false;
+}
+
+/**
+ * @brief 定时flush检查函数
+ */
+ppp_error_t ppp_serial_periodic_flush(void)
+{
+    if (!g_serial_ctx.initialized || g_serial_ctx.current_mode != PPP_SERIAL_MODE_PPP_DATA) {
+        return PPP_ERR_INVALID_PARAM;
+    }
+    
+    uint32_t current_time = ppp_serial_get_current_time_ms();
+    uint32_t time_since_last_tx = current_time - g_serial_ctx.last_tx_time;
+    
+    osal_mutex_lock(&g_serial_ctx.tx_mutex);
+    uint32_t buffered_count = g_serial_ctx.tx_count;
+    osal_mutex_unlock(&g_serial_ctx.tx_mutex);
+    
+    // 如果有缓冲数据且空闲时间超过阈值,强制flush
+    if (buffered_count > 0 && time_since_last_tx >= g_serial_ctx.idle_flush_threshold) {
+        PPP_DEBUG_INFO("Periodic flush: %u bytes after %u ms idle", 
+                      buffered_count, time_since_last_tx);
+        g_serial_ctx.last_tx_time = current_time;
+        return ppp_serial_flush_tx();
+    }
+    
+    return PPP_ERR_OK;
+} 
+
 /**
  * @brief 清空接收缓冲区
  */
@@ -431,7 +736,6 @@ void ppp_serial_deinit(void)
         osal_kfree(g_serial_ctx.rx_buffer);
         g_serial_ctx.rx_buffer = NULL;
     }
-
     if (g_serial_ctx.tx_buffer) {
         osal_kfree(g_serial_ctx.tx_buffer);
         g_serial_ctx.tx_buffer = NULL;
@@ -440,6 +744,7 @@ void ppp_serial_deinit(void)
     /* 销毁同步对象 */
     osal_mutex_destroy(&g_serial_ctx.rx_mutex);
     osal_sem_destroy(&g_serial_ctx.rx_semaphore);
+    osal_mutex_destroy(&g_serial_ctx.tx_mutex);
 
     /* 清理上下文 */
     memset_s(&g_serial_ctx, sizeof(g_serial_ctx), 0, sizeof(g_serial_ctx));
@@ -467,8 +772,16 @@ void ppp_serial_get_stats(ppp_serial_stats_t *stats)
     stats->rx_bytes = g_serial_ctx.rx_bytes;
     stats->tx_errors = g_serial_ctx.tx_errors;
     stats->rx_errors = g_serial_ctx.rx_errors;
+    
+    osal_mutex_lock(&g_serial_ctx.rx_mutex);
     stats->rx_buffer_usage = g_serial_ctx.rx_count;
     stats->rx_buffer_size = g_serial_ctx.rx_buffer_size;
+    osal_mutex_unlock(&g_serial_ctx.rx_mutex);
+    
+    osal_mutex_lock(&g_serial_ctx.tx_mutex);
+    stats->tx_buffer_usage = g_serial_ctx.tx_count;
+    stats->tx_buffer_size = g_serial_ctx.tx_buffer_size;
+    osal_mutex_unlock(&g_serial_ctx.tx_mutex);
 } 
 
 /* 内部函数实现 */
@@ -532,4 +845,180 @@ static uint32_t ppp_serial_buffer_available_space(void)
 static uint32_t ppp_serial_buffer_data_count(void)
 {
     return g_serial_ctx.rx_count;
+}
+
+/**
+ * @brief 获取发送缓冲区可用空间
+ */
+static uint32_t ppp_serial_tx_buffer_available_space(void)
+{
+    return g_serial_ctx.tx_buffer_size - g_serial_ctx.tx_count;
+}
+
+/**
+ * @brief 获取发送缓冲区数据数量
+ */
+static uint32_t ppp_serial_tx_buffer_data_count(void)
+{
+    return g_serial_ctx.tx_count;
+}
+
+/**
+ * @brief 清空发送缓冲区
+ */
+static ppp_error_t ppp_serial_flush_tx_buffer_internal(void)
+{
+    if (!g_serial_ctx.initialized) {
+        return PPP_ERR_INVALID_PARAM;
+    }
+
+    PPP_DEBUG_INFO("Flushing TX buffer...");
+    osal_mutex_lock(&g_serial_ctx.tx_mutex);
+
+    uint32_t old_count = g_serial_ctx.tx_count;
+    g_serial_ctx.tx_head = 0;
+    g_serial_ctx.tx_tail = 0;
+    g_serial_ctx.tx_count = 0;
+
+    osal_mutex_unlock(&g_serial_ctx.tx_mutex);
+    PPP_DEBUG_INFO("TX buffer flushed (discarded %u bytes)", old_count);
+    return PPP_ERR_OK;
+}
+
+/**
+ * @brief 测试UART是否正常工作
+ */
+ppp_error_t ppp_serial_test_uart(void)
+{
+    if (!g_serial_ctx.initialized) {
+        PPP_DEBUG_ERROR("PPP serial not initialized");
+        return PPP_ERR_INVALID_PARAM;
+    }
+
+    PPP_DEBUG_INFO("=== UART Test Start ===");
+    PPP_DEBUG_INFO("Current state:");
+    PPP_DEBUG_INFO("  - Initialized: %s", g_serial_ctx.initialized ? "true" : "false");
+    PPP_DEBUG_INFO("  - Mode: %d", g_serial_ctx.current_mode);
+    PPP_DEBUG_INFO("  - UART Bus: %u", g_serial_ctx.uart_bus);
+    PPP_DEBUG_INFO("  - TX Pin: %u", g_serial_ctx.pin_config.tx_pin);
+    PPP_DEBUG_INFO("  - RX Pin: %u", g_serial_ctx.pin_config.rx_pin);
+    PPP_DEBUG_INFO("  - Baudrate: %u", g_serial_ctx.uart_attr.baud_rate);
+
+    /* 发送测试字符串 */
+    const char *test_msg = "AT\r\n";
+    uint32_t test_len = strlen(test_msg);
+    
+    PPP_DEBUG_INFO("Sending test AT command: \"%s\"", test_msg);
+    ppp_error_t result = ppp_serial_write((const uint8_t *)test_msg, test_len);
+    
+    PPP_DEBUG_INFO("Test result: %s", result == PPP_ERR_OK ? "SUCCESS" : "FAILED");
+    PPP_DEBUG_INFO("=== UART Test End ===");
+    
+    return result;
+}
+
+/**
+ * @brief 强制发送缓冲区中的所有数据
+ */
+ppp_error_t ppp_serial_flush_tx(void)
+{
+    if (!g_serial_ctx.initialized) {
+        PPP_DEBUG_ERROR("PPP serial not initialized");
+        return PPP_ERR_INVALID_PARAM;
+    }
+
+    PPP_DEBUG_INFO("=== TX Buffer Flush Start ===");
+    
+    osal_mutex_lock(&g_serial_ctx.tx_mutex);
+    
+    uint32_t data_count = ppp_serial_tx_buffer_data_count();
+    if (data_count == 0) {
+        osal_mutex_unlock(&g_serial_ctx.tx_mutex);
+        PPP_DEBUG_INFO("TX buffer is empty, nothing to flush");
+        PPP_DEBUG_INFO("=== TX Buffer Flush End ===");
+        return PPP_ERR_OK;
+    }
+    
+    PPP_DEBUG_INFO("Flushing %u bytes from TX buffer", data_count);
+    
+    /* 创建临时缓冲区来存储要发送的数据 */
+    uint8_t *temp_buffer = (uint8_t *)osal_kmalloc(data_count, OSAL_GFP_KERNEL);
+    if (temp_buffer == NULL) {
+        osal_mutex_unlock(&g_serial_ctx.tx_mutex);
+        PPP_DEBUG_ERROR("Failed to allocate temporary buffer for flush");
+        return PPP_ERR_MEMORY;
+    }
+    
+    /* 从环形缓冲区复制数据到临时缓冲区 */
+    for (uint32_t i = 0; i < data_count; i++) {
+        temp_buffer[i] = g_serial_ctx.tx_buffer[g_serial_ctx.tx_tail];
+        g_serial_ctx.tx_tail = (g_serial_ctx.tx_tail + 1) % g_serial_ctx.tx_buffer_size;
+        g_serial_ctx.tx_count--;
+    }
+    
+    osal_mutex_unlock(&g_serial_ctx.tx_mutex);
+    
+    /* 发送数据 */
+    PPP_DEBUG_INFO("Calling uapi_uart_write(bus=%u, data=%p, len=%u, timeout=1000)...", 
+                  g_serial_ctx.uart_bus, temp_buffer, data_count);
+    // PPP_DEBUG_HEXDUMP(temp_buffer, data_count);
+    
+    int32_t write_result = uapi_uart_write(g_serial_ctx.uart_bus, temp_buffer, data_count, 1000);
+    PPP_DEBUG_INFO("uapi_uart_write returned: %d (expected: %u)", write_result, data_count);
+    
+    ppp_error_t result = PPP_ERR_OK;
+    if (write_result != (int32_t)data_count) {
+        PPP_DEBUG_ERROR("UART write failed during flush: returned %d, expected %u", write_result, data_count);
+        PPP_DEBUG_ERROR("Possible causes: UART not initialized, hardware error, or timeout");
+        g_serial_ctx.tx_errors++;
+        result = PPP_ERR_UART;
+    } else {
+        g_serial_ctx.tx_bytes += data_count;
+        PPP_DEBUG_INFO("Flushed %u bytes successfully (total tx: %u bytes)", 
+                      data_count, g_serial_ctx.tx_bytes);
+    }
+    
+    /* 释放临时缓冲区 */
+    osal_kfree(temp_buffer);
+    
+    PPP_DEBUG_INFO("Flush result: %s (error code: %d)", 
+                   result == PPP_ERR_OK ? "SUCCESS" : "FAILED", result);
+    PPP_DEBUG_INFO("=== TX Buffer Flush End ===");
+    
+    return result;
+}
+
+/**
+ * @brief 清空发送缓冲区(丢弃数据)
+ */
+void ppp_serial_flush_tx_discard(void)
+{
+    if (!g_serial_ctx.initialized) {
+        return;
+    }
+
+    osal_mutex_lock(&g_serial_ctx.tx_mutex);
+    uint32_t old_count = g_serial_ctx.tx_count;
+    g_serial_ctx.tx_head = 0;
+    g_serial_ctx.tx_tail = 0;
+    g_serial_ctx.tx_count = 0;
+    osal_mutex_unlock(&g_serial_ctx.tx_mutex);
+
+    PPP_DEBUG_INFO("TX buffer discarded (%u bytes)", old_count);
+}
+
+/**
+ * @brief 获取发送缓冲区使用情况
+ */
+uint32_t ppp_serial_tx_available(void)
+{
+    if (!g_serial_ctx.initialized) {
+        return 0;
+    }
+
+    osal_mutex_lock(&g_serial_ctx.tx_mutex);
+    uint32_t count = ppp_serial_tx_buffer_data_count();
+    osal_mutex_unlock(&g_serial_ctx.tx_mutex);
+
+    return count;
 } 
\ No newline at end of file