ppp串口接收优化,已经达到目前最优,不考虑头尾,中间数据已经比较稳定。少量丢失数据。921600和1000000速率测试通过。
author孙春阳 <snickersun@163.com>
Fri, 10 Oct 2025 13:18:39 +0000 (21:18 +0800)
committer孙春阳 <snickersun@163.com>
Fri, 10 Oct 2025 13:18:39 +0000 (21:18 +0800)
code/sdk/build/config/target_config/brandy/config.py
code/sdk/drivers/chips/brandy/porting/uart/uart_porting.c
code/sdk/zhihui/ppp/example/ppp_at_cmd.c
code/sdk/zhihui/ppp/include/ppp_config.h
code/sdk/zhihui/ppp/src/ppp_api.c
code/sdk/zhihui/ppp/src/ppp_at_handler.c
code/sdk/zhihui/ppp/src/ppp_interrupt.c
code/sdk/zhihui/ppp/src/ppp_lwip_thread.c
code/sdk/zhihui/ppp/src/ppp_serial.c

index 011853c..d55cf33 100644 (file)
@@ -1449,6 +1449,8 @@ target = {
             'LCD_JD9885',
             'SUPPORT_LEINIAO',
             'SKIP_LN_PROTOCOL_TEST',
+            # 'SUPPORT_PPP_SERVICE_POLLING',
+            'SUPPORT_PPP_SERVICE_INTERRUPT',
         ],
         #添加自定义应用
        'ram_component': [
index 7399f2b..b7d3397 100644 (file)
@@ -172,41 +172,37 @@ static uart_config_t g_uart_config[UART_BUS_MAX_NUMBER] = {
     /** UART_BUS_0, which is used to at cmd and debug print in wstp version,
      * and which is used to testustie and debug print in testsuite version
      */
-    #if defined(SUPPORT_CAT1_SERVICE) 
+    #if defined(SUPPORT_CAT1_SERVICE)  || defined(SUPPORT_PPP_SERVICE_POLLING)
     {
         {
             .tx_pin = PIN_NONE,
             .rx_pin = PIN_NONE,
             .cts_pin = PIN_NONE,
             .rts_pin = PIN_NONE
-        },
+        },//pin
         {
             .tx_pin_mode = (pin_mode_t)HAL_PIO_FUNC_MAX,
             .rx_pin_mode = (pin_mode_t)HAL_PIO_FUNC_MAX,
             .cts_pin_mode = (pin_mode_t)HAL_PIO_FUNC_MAX,
             .rts_pin_mode = (pin_mode_t)HAL_PIO_FUNC_MAX
-        },
-        UART_0_IRQN,
-        (osal_irq_handler)irq_uart0_handler,
-        NULL,
+        },//pin_mode
+        UART_0_IRQN,//irq_num
+        (osal_irq_handler)irq_uart0_handler,//irq_func
+        NULL,//rx_callback
         {
             .baud_rate = 115200,
             .data_bits = UART_DATA_BIT_8,
             .parity = UART_PARITY_NONE,
             .stop_bits = UART_STOP_BIT_1,
-        },
+        },//line_config
         {
             .rx_buffer_size = UART_RX_BUFFER_SIZE,
             .rx_buffer = g_uart0_rx_buffer,
         },
-        NULL,
-        #if defined(SUPPORT_TEST_COMMON)
-        false,
-        #else
-        true,
-        #endif
+        NULL, //uart_mutex
+        false, //support_mutex
     },
-    #elif defined(SUPPORT_PPP_SERVICE)
+    #elif defined(SUPPORT_PPP_SERVICE_INTERRUPT)
     {
         {
             .tx_pin = S_MGPIO19,
index 5851e43..1acaf94 100644 (file)
@@ -926,25 +926,25 @@ static errcode_t at_ppp_show_runtime(uint8_t *para, uint32_t paraLen)
     (void)para;
     (void)paraLen;
     
-    ppp_print_info("PPP RUNTIME SHOW: Current runtime status:\n");
+    ppp_print_warning("PPP RUNTIME SHOW: Current runtime status:\n");
     
     // 显示当前runtime状态
-    ppp_print_info("\n=== Current Runtime Status ===");
-    ppp_print_info("Power Status: %s", cat1_api_runtime_get_cat1_powerstat() ? "ON" : "OFF");
-    ppp_print_info("Network Status: %s", cat1_api_runtime_get_cat1_networkstat() ? "CONNECTED" : "DISCONNECTED");
+    ppp_print_warning("\n=== Current Runtime Status ===");
+    ppp_print_warning("Power Status: %s", cat1_api_runtime_get_cat1_powerstat() ? "ON" : "OFF");
+    ppp_print_warning("Network Status: %s", cat1_api_runtime_get_cat1_networkstat() ? "CONNECTED" : "DISCONNECTED");
     
     int signal = cat1_api_runtime_get_cat1_signal();
     if (signal == 99) {
-        ppp_print_info("Signal Strength: No Signal (99)");
+        ppp_print_warning("Signal Strength: No Signal (99)");
     } else {
-        ppp_print_info("Signal Strength: %d/31 (%s)", signal, 
+        ppp_print_warning("Signal Strength: %d/31 (%s)", signal, 
                        signal >= 20 ? "Excellent" : 
                        signal >= 15 ? "Good" : 
                        signal >= 10 ? "Fair" : 
                        signal >= 5 ? "Poor" : "Very Poor");
     }
     
-    ppp_print_info("SIM Status: %s", cat1_api_runtime_get_cat1_simstat() ? "NORMAL" : "ERROR");
+    ppp_print_warning("SIM Status: %s", cat1_api_runtime_get_cat1_simstat() ? "NORMAL" : "ERROR");
     
     uint8_t net_type = cat1_api_runtime_get_cat1_networktype();
     const char* net_type_str = "Unknown";
@@ -957,33 +957,33 @@ static errcode_t at_ppp_show_runtime(uint8_t *para, uint32_t paraLen)
         case 5: net_type_str = "Registered (Roaming)"; break;
         default: net_type_str = "Invalid"; break;
     }
-    ppp_print_info("Network Type: %d (%s)", net_type, net_type_str);
+    ppp_print_warning("Network Type: %d (%s)", net_type, net_type_str);
     
     char* operator = cat1_api_runtime_get_cat1_operator();
-    ppp_print_info("Operator: %s", (operator && strlen(operator) > 0) ? operator : "Unknown");
+    ppp_print_warning("Operator: %s", (operator && strlen(operator) > 0) ? operator : "Unknown");
     
     char* imei = cat1_api_runtime_get_cat1_imei();
-    ppp_print_info("IMEI: %s", (imei && strlen(imei) > 0) ? imei : "Unknown");
+    ppp_print_warning("IMEI: %s", (imei && strlen(imei) > 0) ? imei : "Unknown");
     
     char* iccid = cat1_api_runtime_get_cat1_iccid();
-    ppp_print_info("ICCID: %s", (iccid && strlen(iccid) > 0) ? iccid : "Unknown");
+    ppp_print_warning("ICCID: %s", (iccid && strlen(iccid) > 0) ? iccid : "Unknown");
     
     char* version = cat1_api_runtime_get_cat1_modemver();
-    ppp_print_info("Modem Version: %s", (version && strlen(version) > 0) ? version : "Unknown");
+    ppp_print_warning("Modem Version: %s", (version && strlen(version) > 0) ? version : "Unknown");
     
-    ppp_print_info("===============================");
+    ppp_print_warning("===============================");
     
     // 显示PPP输出统计信息
     ppp_lwip_output_stats_t ppp_stats;
     if (ppp_lwip_get_output_stats(&ppp_stats) == PPP_ERR_OK) {
-        ppp_print_info("\n=== PPP Output Statistics ===");
-        ppp_print_info("Total Output Packets: %llu", ppp_stats.total_packets);
-        ppp_print_info("Total Output Bytes: %llu", ppp_stats.total_bytes);
-        ppp_print_info("LCP Packets: %u", ppp_stats.lcp_packets);
-        ppp_print_info("IPCP Packets: %u", ppp_stats.ipcp_packets);
-        ppp_print_info("IP Packets: %u", ppp_stats.ip_packets);
-        ppp_print_info("Other Protocol Packets: %u", ppp_stats.other_packets);
-        ppp_print_info("Failed Sends: %u", ppp_stats.failed_sends);
+        ppp_print_warning("\n=== PPP Output Statistics ===");
+        ppp_print_warning("Total Output Packets: %llu", ppp_stats.total_packets);
+        ppp_print_warning("Total Output Bytes: %llu", ppp_stats.total_bytes);
+        ppp_print_warning("LCP Packets: %u", ppp_stats.lcp_packets);
+        ppp_print_warning("IPCP Packets: %u", ppp_stats.ipcp_packets);
+        ppp_print_warning("IP Packets: %u", ppp_stats.ip_packets);
+        ppp_print_warning("Other Protocol Packets: %u", ppp_stats.other_packets);
+        ppp_print_warning("Failed Sends: %u", ppp_stats.failed_sends);
         
         // 计算PPP输出统计的运行时间和速率
         uint32_t current_time = ppp_stats.last_packet_time;
@@ -995,33 +995,36 @@ static errcode_t at_ppp_show_runtime(uint8_t *para, uint32_t paraLen)
         uint32_t ppp_elapsed_sec = ppp_elapsed_ms / 1000;
         
         if (ppp_elapsed_sec > 0) {
-            ppp_print_info("PPP Stats Duration: %u seconds", ppp_elapsed_sec);
+            ppp_print_warning("PPP Stats Duration: %u seconds", ppp_elapsed_sec);
         }
         
         if (ppp_elapsed_ms > 0 && ppp_stats.total_bytes > 0) {
             uint64_t ppp_throughput_bps = (ppp_stats.total_bytes * 1000) / ppp_elapsed_ms;
-            ppp_print_info("PPP Output Throughput: %llu bytes/s", ppp_throughput_bps);
+            ppp_print_warning("PPP Output Throughput: %llu bytes/s", ppp_throughput_bps);
             
             float ppp_packet_rate = (float)ppp_stats.total_packets * 1000 / ppp_elapsed_ms;
-            ppp_print_info("PPP Output Packet Rate: %.1f packets/s", ppp_packet_rate);
+            ppp_print_warning("PPP Output Packet Rate: %.1f packets/s", ppp_packet_rate);
         }
         
         // 计算成功率
         uint64_t total_attempts = ppp_stats.total_packets + ppp_stats.failed_sends;
         if (total_attempts > 0) {
             float success_rate = (float)ppp_stats.total_packets / total_attempts * 100;
-            ppp_print_info("PPP Output Success Rate: %.1f%%", success_rate);
+            ppp_print_warning("PPP Output Success Rate: %.1f%%", success_rate);
         }
         
-        ppp_print_info("=============================");
+        ppp_print_warning("=============================");
     } else {
-        ppp_print_info("\n=== PPP Output Statistics ===");
-        ppp_print_info("Failed to get PPP output statistics");
-        ppp_print_info("=============================");
+        ppp_print_warning("\n=== PPP Output Statistics ===");
+        ppp_print_warning("Failed to get PPP output statistics");
+        ppp_print_warning("=============================");
     }
     
     ppp_lwip_print_discard_stats();
 
+    // 打印中断统计信息
+    ppp_interrupt_print_stats();
+    
     return ERRCODE_SUCC;
 }
 
index 1591842..e960eea 100644 (file)
@@ -27,7 +27,7 @@ extern "C" {
 #define SIO_UART_IRQ_NUM            UART_0_IRQN         // UART IRQ引脚
 #endif
 
-#define PPP_UART_BAUDRATE          115200
+#define PPP_UART_BAUDRATE          921600
 
 /* 支持的波特率列表(自适应模式) */
 #define PPP_BAUDRATE_AUTO_LIST      {9600, 57600, 115200}
@@ -70,11 +70,12 @@ extern "C" {
 
 /* PPP数据接收线程配置 */
 #define PPP_RX_THREAD_STACK_SIZE        4096                // 接收线程栈大小
-#define PPP_RX_THREAD_PRIORITY          osPriorityNormal    // 接收线程优先级
+#define PPP_RX_THREAD_PRIORITY          osPriorityHigh      // 接收线程优先级(提高以确保及时读取数据)
+#define PPP_PROCESS_THREAD_PRIORITY     osPriorityAboveNormal // 处理线程优先级
 
 /* 调试配置 */
 #define PPP_DEBUG_ENABLE            1                   // 启用调试输出
-#define PPP_DEBUG_LEVEL             PPP_DEBUG_LEVEL_INFO // 默认只显示警告和错误 (1=ERROR, 2=WARN, 3=INFO, 4=DEBUG)
+#define PPP_DEBUG_LEVEL             PPP_DEBUG_LEVEL_WARN // 默认只显示警告和错误 (1=ERROR, 2=WARN, 3=INFO, 4=DEBUG)
 
 /*
  * 调试级别说明:
index 196fb8a..731587f 100644 (file)
@@ -142,17 +142,13 @@ errcode_t zhihui_ppp_init(const ppp_config_t *config)
     // 保存用户配置
     memcpy_s(&g_ppp_config, sizeof(ppp_config_t), config, sizeof(ppp_config_t));
 
-    // PPP_DO_SERIAL_TEST 不进行电源初始化, 用于调试串口读取能力测试。
-#if defined(PPP_DO_SERIAL_TEST) && (PPP_DO_SERIAL_TEST == 1)
-    PPP_DEBUG_PRINT("PPP_DO_SERIAL_TEST is defined, skip power init\n");
-#else
     ppp_api_power_init();
-#endif
+    
+    PPP_DEBUG_WARN("Step 3: Initializing UART for AT mode baudrate: %d\n", g_ppp_config.baudrate);
 
 #define PPP_SERIAL_INIT 1 //外接串口调试模组时,串口要设置input防止干扰。
 #if PPP_SERIAL_INIT
     // 3. UART初始化
-    PPP_DEBUG_PRINT("Step 3: Initializing UART for AT mode baudrate: %d\n", g_ppp_config.baudrate);
     ppp_serial_config_t serial_config = {
         .uart_bus = SIO_UART_BUS,
         .irq_num = SIO_UART_IRQ_NUM,
@@ -860,8 +856,7 @@ errcode_t ppp_stop_dial(void)
      ppp_interrupt_disable();
      PPP_DEBUG_INFO("PPP interrupt mode disabled");
  
-     // 打印中断统计信息
-     ppp_interrupt_print_stats();
+
      #else
      // 轮询模式:停止接收线程
      PPP_DEBUG_INFO("Stopping PPP receive thread...");
index f6019ce..7c5fad1 100644 (file)
@@ -998,10 +998,22 @@ static ppp_error_t  ppp_at_wait_response(ppp_at_response_t *response, uint32_t t
         PPP_DEBUG_DEBUG("WAIT_RESPONSE: Attempting UART read #%u...", read_attempts);
         uint32_t uart_read_start = (uint32_t)osal_get_jiffies();
         
-        int32_t ret = uapi_uart_read(g_at_ctx.uart_bus, 
-                                    g_at_response_buffer + bytes_received, 
-                                    g_at_buffer_size - bytes_received - 1, 
-                                    UART_READ_TIMEOUT_MS);
+        #if defined(CONFIG_UART_SUPPORT_DMA)
+        uart_write_dma_config_t dma_cfg = {
+            .src_width = 0,//UART_DMA_WIDTH,
+            .dest_width = 0,//UART_DMA_WIDTH,
+            .burst_length = 2,//UART_DMA_BURST_LENGTH,
+            .priority = 0//UART_DMA_PRIORITY
+        };
+        int32_t ret = uapi_uart_read_by_dma(g_at_ctx.uart_bus, g_at_response_buffer + bytes_received, 
+            g_at_buffer_size - bytes_received - 1
+            , &dma_cfg);
+            
+        #else
+        int32_t ret =uapi_uart_read(g_at_ctx.uart_bus, g_at_response_buffer + bytes_received, 
+            g_at_buffer_size - bytes_received - 1, 
+            UART_READ_TIMEOUT_MS);
+        #endif
         
         uint32_t uart_read_end = (uint32_t)osal_get_jiffies();
         uint32_t uart_read_time = osal_jiffies_to_msecs(uart_read_end - uart_read_start);
index 36583d0..00b0ef9 100644 (file)
@@ -66,7 +66,7 @@ typedef struct {
 } ppp_irq_msg_t;
 
 /* 中断使能标志 */
-static bool g_ppp_interrupt_enabled = false;
+static volatile bool g_ppp_interrupt_enabled = false;
 
 /* 处理线程相关 */
 static osal_task *g_ppp_irq_process_task = NULL;
@@ -75,7 +75,10 @@ static volatile bool g_ppp_irq_task_running = false;
 
 /* 乒乓缓冲区 */
 static ppp_ping_pong_buffer_t g_ping_pong_buffers[PPP_PING_PONG_BUFFER_COUNT];
-static volatile uint8_t g_current_buffer_index = 0;  // 当前正在填充的buffer索引
+static volatile uint8_t g_current_buffer_index = 0;
+
+/* 全局时间戳(由定时器更新,ISR只读) */
+static volatile uint32_t g_timer_timestamp_ms = 0;
 
 /* 定时器相关 */
 static osal_timer g_ppp_timeout_timer;
@@ -94,6 +97,16 @@ typedef struct {
 
 static ppp_pingpong_stats_t g_pingpong_stats = {0};
 
+/* UART错误统计信息 */
+typedef struct {
+    uint32_t parity_error_count;        // 奇偶校验错误次数
+    uint32_t frame_error_count;         // 帧错误次数
+    uint32_t last_parity_error_info[4]; // 最近一次奇偶校验错误信息
+    uint32_t last_frame_error_info[4];  // 最近一次帧错误信息
+} ppp_uart_error_stats_t;
+
+static ppp_uart_error_stats_t g_uart_error_stats = {0};
+
 /* 外部函数声明(在ppp_lwip.c中实现) */
 extern ppp_pcb* ppp_lwip_get_pcb(void);
 extern bool ppp_lwip_is_initialized(void);
@@ -102,6 +115,8 @@ extern bool ppp_lwip_is_initialized(void);
 static uint32_t ppp_get_current_time_ms(void);
 static ppp_error_t ppp_flush_buffer(uint8_t buffer_index);
 static void ppp_timeout_timer_callback(unsigned long arg);
+static void ppp_uart_parity_error_callback(uint32_t *err_info, uint32_t len);
+static void ppp_uart_frame_error_callback(uint32_t *err_info, uint32_t len);
 
 /**
  * @brief 获取当前时间戳(毫秒)
@@ -122,7 +137,9 @@ static void ppp_irq_process_thread(void *arg)
     ppp_irq_msg_t msg;
     unsigned int msg_size = sizeof(ppp_irq_msg_t);
     
-    PPP_DEBUG_INFO("PPP IRQ process thread started (ping-pong mode)");
+    // ⚠️ 使用 WARN 级别确保能看到此日志,用于诊断线程是否正常启动
+    PPP_DEBUG_WARN(">>> PPP IRQ process thread STARTED (ping-pong mode) <<<");
+    PPP_DEBUG_INFO("Thread running, waiting for messages from ISR...");
     #if defined(PPP_DO_SERIAL_TEST) && (PPP_DO_SERIAL_TEST == 1)
     const uint8_t print_data[] = "PPP IRQ process thread started (ping-pong mode)\n";
     uapi_uart_write(SIO_UART_BUS, print_data, sizeof(print_data), 100);
@@ -265,6 +282,15 @@ static ppp_error_t ppp_flush_buffer(uint8_t buffer_index)
  * @note 定时器上下文,应快速返回
  * @param arg 定时器参数(未使用)
  * @warning osal_timer默认是one-shot,必须在回调中手动重启实现周期性执行
+ * 
+ * 数据安全设计(避免竞态):
+ * - 定时器职责:只检查和flush **非当前** buffer(避免与ISR竞争)
+ * - ISR 职责:
+ *   1. 在写入前检查当前buffer是否超时(last_write_time == 0),超时则flush+切换
+ *   2. 检查当前buffer状态,如果不可写则切换
+ *   3. 独占 g_current_buffer_index 的修改权
+ * - 分工明确:定时器不操作当前buffer,ISR负责当前buffer的超时处理
+ * - 数据保证:disable时强制flush所有buffer,确保数据不丢失
  */
 static void ppp_timeout_timer_callback(unsigned long arg)
 {
@@ -286,32 +312,40 @@ static void ppp_timeout_timer_callback(unsigned long arg)
     
     uint32_t current_time = ppp_get_current_time_ms();
     
-    // 检查所有buffer的超时状态
+    // ⚠️ 更新全局时间戳(供ISR使用,ISR中不能调用时间函数)
+    g_timer_timestamp_ms = current_time;
+    
+    uint8_t current_idx = g_current_buffer_index;  // 读取一次,避免重复读取
+    
+    // 检查非当前buffer的超时状态
+    // ⚠️ 数据安全设计:定时器只处理非当前buffer,避免与ISR竞争
+    // 当前buffer的超时由ISR在写入时主动检查并处理
     for (uint8_t i = 0; i < PPP_PING_PONG_BUFFER_COUNT; i++) {
+        // 跳过当前正在写入的buffer(避免与ISR竞争,保证数据安全)
+        if (i == current_idx) {
+            continue;
+        }
+        
         ppp_ping_pong_buffer_t *buffer = &g_ping_pong_buffers[i];
         
         // 只处理FILLING状态的buffer
         if (buffer->state == PPP_BUFFER_STATE_FILLING && buffer->write_pos > 0) {
-            uint32_t elapsed = current_time - buffer->last_write_time;
-            
-            // 超时检查
-            if (elapsed >= PPP_PING_PONG_TIMEOUT_MS) {
-                // 超时,flush buffer
-                PPP_DEBUG_DEBUG("[TIMER] Flushing buffer[%u] due to timeout (%u ms)", i, elapsed);
-                if (ppp_flush_buffer(i) == PPP_ERR_OK) {
-                    g_pingpong_stats.buffer_timeout_count++;
+            // ⚠️ 修复:避免误判超时
+            // last_write_time == 0 表示ISR刚写入数据,需要更新时间戳(不是超时)
+            if (buffer->last_write_time == 0) {
+                // 第一次看到,更新时间戳,不flush
+                buffer->last_write_time = current_time;
+                PPP_DEBUG_DEBUG("[TIMER] Update timestamp for buffer[%u]", i);
+            } else {
+                // 已经有时间戳了,检查是否真的超时
+                uint32_t elapsed = current_time - buffer->last_write_time;
+                
+                if (elapsed >= PPP_PING_PONG_TIMEOUT_MS) {
+                    // 真正超时,flush buffer
+                    PPP_DEBUG_DEBUG("[TIMER] Flushing buffer[%u] due to timeout (%u ms)", i, elapsed);
                     
-                    // ⚠️ 关键修复:Timer flush后切换buffer(类似ISR中buffer满的逻辑)
-                    // 只有当前flush的是正在使用的buffer时才切换
-                    if (i == g_current_buffer_index) {
-                        uint8_t next_idx = (i + 1) % PPP_PING_PONG_BUFFER_COUNT;
-                        ppp_ping_pong_buffer_t *next_buffer = &g_ping_pong_buffers[next_idx];
-                        
-                        if (next_buffer->state == PPP_BUFFER_STATE_EMPTY) {
-                            g_current_buffer_index = next_idx;
-                            g_pingpong_stats.buffer_switch_count++;
-                        }
-                        // 如果next_buffer不是EMPTY,保持当前索引,等待其处理完成
+                    if (ppp_flush_buffer(i) == PPP_ERR_OK) {
+                        g_pingpong_stats.buffer_timeout_count++;
                     }
                 }
             }
@@ -325,6 +359,48 @@ static void ppp_timeout_timer_callback(unsigned long arg)
     }
 }
 
+/**
+ * @brief UART奇偶校验错误回调函数
+ * @param err_info 错误信息数组
+ * @param len 错误信息数组长度
+ * @note 在中断上下文中执行,必须快速返回
+ */
+static void ppp_uart_parity_error_callback(uint32_t *err_info, uint32_t len)
+{
+    g_uart_error_stats.parity_error_count++;
+    
+    // 保存错误信息用于诊断(只保存前4个)
+    if (err_info && len > 0) {
+        uint32_t copy_len = (len > 4) ? 4 : len;
+        for (uint32_t i = 0; i < copy_len; i++) {
+            g_uart_error_stats.last_parity_error_info[i] = err_info[i];
+        }
+    }
+    
+    // ⚠️ 中断中禁止打印日志,只统计
+}
+
+/**
+ * @brief UART帧错误回调函数
+ * @param err_info 错误信息数组
+ * @param len 错误信息数组长度
+ * @note 在中断上下文中执行,必须快速返回
+ */
+static void ppp_uart_frame_error_callback(uint32_t *err_info, uint32_t len)
+{
+    g_uart_error_stats.frame_error_count++;
+    
+    // 保存错误信息用于诊断(只保存前4个)
+    if (err_info && len > 0) {
+        uint32_t copy_len = (len > 4) ? 4 : len;
+        for (uint32_t i = 0; i < copy_len; i++) {
+            g_uart_error_stats.last_frame_error_info[i] = err_info[i];
+        }
+    }
+    
+    // ⚠️ 中断中禁止打印日志,只统计
+}
+
 /**
  * @brief UART接收中断回调函数(乒乓缓冲区模式)
  * @note 中断上下文,必须极快返回
@@ -338,12 +414,13 @@ static void ppp_timeout_timer_callback(unsigned long arg)
 void _ppp_uart_rx_interrupt_handler(const void *buffer, uint16_t length, bool error)
 {
     // 快速路径:参数校验
-    if (error || !buffer || length == 0 || length > 200) {  // 单次中断最多200字节
-        if (error) {
-            g_ppp_interrupt_stats.error_count++;
-        }
+    if ( !buffer || length == 0 || length > 200) {  // 单次中断最多200字节
+        PPP_DEBUG_ERROR("ppp_uart_rx_interrupt_handler !buffer || length == 0 || length > 200 ");
         return;
     }
+    if (error) {
+        g_ppp_interrupt_stats.error_count++;
+    }
     
     // 更新统计(用于诊断 - 可以在统计打印中看到)
     g_ppp_interrupt_stats.total_interrupts++;
@@ -362,6 +439,52 @@ void _ppp_uart_rx_interrupt_handler(const void *buffer, uint16_t length, bool er
     uint8_t current_idx = g_current_buffer_index;
     ppp_ping_pong_buffer_t *current_buffer = &g_ping_pong_buffers[current_idx];
     
+    // ⚠️ 数据安全设计:ISR负责检查当前buffer的超时
+    // 定时器只处理非当前buffer,避免竞态
+    // 
+    // 检查逻辑(方案2 + 全局时间戳):
+    // - last_write_time == 0:ISR刚写入,定时器还没更新时间戳(不算超时)
+    // - last_write_time != 0:定时器已更新过时间戳,可以检查是否真的超时
+    //   使用 g_timer_timestamp_ms(定时器每30ms更新一次)
+    if (current_buffer->state == PPP_BUFFER_STATE_FILLING && 
+        current_buffer->write_pos > 0 && 
+        current_buffer->last_write_time != 0) {  // ← 只检查已有时间戳的
+        // 使用全局时间戳(ISR中安全,不调用函数)
+        uint32_t current_time = g_timer_timestamp_ms;
+        uint32_t elapsed = current_time - current_buffer->last_write_time;
+        
+        if (elapsed >= PPP_PING_PONG_TIMEOUT_MS) {
+            // 当前buffer真的超时了,flush并切换
+            ppp_flush_buffer(current_idx);
+            g_pingpong_stats.buffer_timeout_count++;
+            
+            // 切换到下一个buffer
+            uint8_t next_idx = (current_idx + 1) % PPP_PING_PONG_BUFFER_COUNT;
+            ppp_ping_pong_buffer_t *next_buffer = &g_ping_pong_buffers[next_idx];
+            
+            if (next_buffer->state == PPP_BUFFER_STATE_EMPTY) {
+                g_current_buffer_index = next_idx;
+                g_pingpong_stats.buffer_switch_count++;
+                current_idx = next_idx;
+                current_buffer = next_buffer;
+            }
+        }
+    }
+    
+    // 如果当前buffer不可写(状态不对),尝试切换
+    if (current_buffer->state != PPP_BUFFER_STATE_EMPTY && 
+        current_buffer->state != PPP_BUFFER_STATE_FILLING) {
+        uint8_t next_idx = (current_idx + 1) % PPP_PING_PONG_BUFFER_COUNT;
+        ppp_ping_pong_buffer_t *next_buffer = &g_ping_pong_buffers[next_idx];
+        
+        if (next_buffer->state == PPP_BUFFER_STATE_EMPTY) {
+            g_current_buffer_index = next_idx;
+            g_pingpong_stats.buffer_switch_count++;
+            current_idx = next_idx;
+            current_buffer = next_buffer;
+        }
+    }
+    
     // 尝试写入当前buffer
     uint32_t available = PPP_PING_PONG_BUFFER_SIZE - current_buffer->write_pos;
     
@@ -369,13 +492,16 @@ void _ppp_uart_rx_interrupt_handler(const void *buffer, uint16_t length, bool er
         // buffer是空的,初始化为FILLING状态
         current_buffer->state = PPP_BUFFER_STATE_FILLING;
         current_buffer->write_pos = 0;
+        available = PPP_PING_PONG_BUFFER_SIZE;  // 重新计算可用空间
     }
     
     if (current_buffer->state == PPP_BUFFER_STATE_FILLING && length <= available) {
         // 空间足够,直接写入
         memcpy(current_buffer->data + current_buffer->write_pos, buffer, length);
         current_buffer->write_pos += length;
-        current_buffer->last_write_time = ppp_get_current_time_ms();
+        // ⚠️ 关键修复:移除中断中的时间函数调用(可能导致死机)
+        // current_buffer->last_write_time = ppp_get_current_time_ms();
+        current_buffer->last_write_time = 0;  // 由定时器回调更新
         
         // 检查是否满了
         if (current_buffer->write_pos >= PPP_PING_PONG_BUFFER_SIZE) {
@@ -413,7 +539,9 @@ void _ppp_uart_rx_interrupt_handler(const void *buffer, uint16_t length, bool er
             next_buffer->write_pos = 0;
             memcpy(next_buffer->data, buffer, length);
             next_buffer->write_pos = length;
-            next_buffer->last_write_time = ppp_get_current_time_ms();
+            // ⚠️ 关键修复:移除中断中的时间函数调用(可能导致死机)
+            // next_buffer->last_write_time = ppp_get_current_time_ms();
+            next_buffer->last_write_time = 0;  // 由定时器回调更新
         } else {
             // 两个buffer都不可用,丢弃数据
             g_pingpong_stats.dropped_both_full += length;
@@ -470,16 +598,20 @@ ppp_error_t ppp_interrupt_enable(void)
     PPP_DEBUG_INFO("Message queue created (depth=%d, item_size=%d bytes)", 
                   PPP_IRQ_MSG_QUEUE_SIZE, sizeof(ppp_irq_msg_t));
     
-    // 3. 启动处理线程
+    // 3. 启动处理线程(使用 osal_kthread_create_ext 创建时指定优先级)
+    // ⚠️ 关键修复:必须在创建时就指定优先级,否则线程以默认低优先级创建可能永远得不到调度
     g_ppp_irq_task_running = true;
     
+    osal_kthread_init init_cfg = {
+        .handler = (osal_kthread_handler)ppp_irq_process_thread,
+        .data = NULL,
+        .taskname = "ppp_irq_proc",
+        .stacksize = PPP_IRQ_PROCESS_STACK_SIZE,
+        .taskprio = OSAL_TASK_PRIORITY_MIDDLE  // 使用中等优先级(6),避免阻塞看门狗
+    };
+    
     osal_kthread_lock();
-    g_ppp_irq_process_task = osal_kthread_create(
-        (osal_kthread_handler)ppp_irq_process_thread,
-        NULL,
-        "ppp_irq_proc",
-        PPP_IRQ_PROCESS_STACK_SIZE
-    );
+    g_ppp_irq_process_task = osal_kthread_create_ext(&init_cfg);
     osal_kthread_unlock();
     
     if (!g_ppp_irq_process_task) {
@@ -489,7 +621,10 @@ ppp_error_t ppp_interrupt_enable(void)
         return PPP_ERR_MEMORY;
     }
     
-    PPP_DEBUG_INFO("Process thread created (stack=%d)", PPP_IRQ_PROCESS_STACK_SIZE);
+    PPP_DEBUG_WARN("IRQ process thread created @ %p with MIDDLE priority (6)", 
+                  g_ppp_irq_process_task);
+    PPP_DEBUG_INFO("Process thread: stack=%d bytes, priority=MIDDLE(6)", 
+                  PPP_IRQ_PROCESS_STACK_SIZE);
     
     // 4. 启动定时器(30ms周期检查buffer超时)
     // 先设置timer的handler、data和interval
@@ -526,19 +661,21 @@ ppp_error_t ppp_interrupt_enable(void)
     PPP_DEBUG_INFO("Registering UART RX callback:");
     PPP_DEBUG_INFO("  UART Bus: %d", uart_bus);
     PPP_DEBUG_INFO("  Condition: 0x07 (FULL_OR_SUFFICIENT_DATA_OR_IDLE)");
-    PPP_DEBUG_INFO("  Threshold: 56 bytes");
+    PPP_DEBUG_INFO("  Threshold: 8 bytes");
     PPP_DEBUG_INFO("  Callback: ppp_uart_rx_interrupt_handler @ %p", ppp_uart_rx_interrupt_handler);
     
-    // ⚠️ 关键修复:降低阈值从200到56字节,确保小数据包也能触发中断
-    // PPP LCP/IPCP响应通常只有30-50字节,200字节阈值太高会导致无法触发
+    // ⚠️ 阈值说明:
+    //   - 参数是直接的字节数(不是编码)
+    //   - 8字节阈值确保小数据包能触发(PPP协商包通常30-50字节)
+    //   - 配合IDLE条件,即使不满8字节也会在数据停止时触发
     ret = uapi_uart_register_rx_callback(
         uart_bus,
         0x07,  // UART_RX_CONDITION_FULL_OR_SUFFICIENT_DATA_OR_IDLE
-        8,    // 56字节阈值
+        8,     // 阈值:8字节
         ppp_uart_rx_interrupt_handler
     );
     
-    PPP_DEBUG_INFO("uapi_uart_register_rx_callback returned: 0x%x (ERRCODE_SUCC=0x%x)", 
+    PPP_DEBUG_WARN("uapi_uart_register_rx_callback returned: 0x%x (ERRCODE_SUCC=0x%x)", 
                   ret, ERRCODE_SUCC);
     
     if (ret != ERRCODE_SUCC) {
@@ -557,13 +694,32 @@ ppp_error_t ppp_interrupt_enable(void)
     
     PPP_DEBUG_INFO("UART RX callback registered successfully!");
     
+    // 6. 注册UART错误回调(用于详细错误诊断)
+    // 6.1 注册奇偶校验错误回调
+    ret = uapi_uart_register_parity_error_callback(uart_bus, ppp_uart_parity_error_callback);
+    if (ret != ERRCODE_SUCC) {
+        PPP_DEBUG_WARN("Failed to register parity error callback: 0x%x (non-critical)", ret);
+        // 不是关键错误,继续运行
+    } else {
+        PPP_DEBUG_INFO("Parity error callback registered");
+    }
+    
+    // 6.2 注册帧错误回调
+    ret = uapi_uart_register_frame_error_callback(uart_bus, ppp_uart_frame_error_callback);
+    if (ret != ERRCODE_SUCC) {
+        PPP_DEBUG_WARN("Failed to register frame error callback: 0x%x (non-critical)", ret);
+        // 不是关键错误,继续运行
+    } else {
+        PPP_DEBUG_INFO("Frame error callback registered");
+    }
+    
     g_ppp_interrupt_enabled = true;
     
-    PPP_DEBUG_INFO("PPP UART interrupt enabled successfully (ping-pong mode)");
-    PPP_DEBUG_INFO("  Ping-pong buffers: %d x %d KB", 
+    PPP_DEBUG_WARN("PPP UART interrupt enabled successfully (ping-pong mode)");
+    PPP_DEBUG_WARN("  Ping-pong buffers: %d x %d KB", 
                   PPP_PING_PONG_BUFFER_COUNT, PPP_PING_PONG_BUFFER_SIZE / 1024);
-    PPP_DEBUG_INFO("  Timeout: %d ms", PPP_PING_PONG_TIMEOUT_MS);
-    PPP_DEBUG_INFO("  Message queue: %d slots (only %d bytes per message)", 
+    PPP_DEBUG_WARN("  Timeout: %d ms", PPP_PING_PONG_TIMEOUT_MS);
+    PPP_DEBUG_WARN("  Message queue: %d slots (only %d bytes per message)", 
                   PPP_IRQ_MSG_QUEUE_SIZE, sizeof(ppp_irq_msg_t));
     PPP_DEBUG_INFO("  ISR latency: <5μs (memcpy + queue_write, no malloc!)");
     PPP_DEBUG_INFO("  Data flow: UART IRQ -> ping-pong buffer -> timer/full flush -> msg_queue -> process_thread -> pppos_input_tcpip");
@@ -618,7 +774,20 @@ ppp_error_t ppp_interrupt_disable(void)
     // osal_msg_queue_delete 不会清零队列句柄,但下次 create 需要它为 0
     g_ppp_irq_msg_queue = 0;
     
-    // 5. 清空乒乓缓冲区
+    // 5. ⚠️ 数据安全:在清空前,先flush所有有数据的buffer,确保数据不丢失
+    PPP_DEBUG_INFO("Flushing all buffers before disable...");
+    for (uint8_t i = 0; i < PPP_PING_PONG_BUFFER_COUNT; i++) {
+        if (g_ping_pong_buffers[i].state == PPP_BUFFER_STATE_FILLING && 
+            g_ping_pong_buffers[i].write_pos > 0) {
+            PPP_DEBUG_INFO("  Flushing buffer[%u]: %u bytes", 
+                          i, g_ping_pong_buffers[i].write_pos);
+            ppp_flush_buffer(i);
+            // 给处理线程一点时间处理最后的数据
+            osal_msleep(50);
+        }
+    }
+    
+    // 6. 清空乒乓缓冲区
     for (uint8_t i = 0; i < PPP_PING_PONG_BUFFER_COUNT; i++) {
         g_ping_pong_buffers[i].write_pos = 0;
         g_ping_pong_buffers[i].state = PPP_BUFFER_STATE_EMPTY;
@@ -626,6 +795,11 @@ ppp_error_t ppp_interrupt_disable(void)
     }
     g_current_buffer_index = 0;
     
+    // 7. 清零统计信息(为下次启用准备)
+    memset(&g_ppp_interrupt_stats, 0, sizeof(ppp_interrupt_stats_t));
+    memset(&g_pingpong_stats, 0, sizeof(ppp_pingpong_stats_t));
+    memset(&g_uart_error_stats, 0, sizeof(ppp_uart_error_stats_t));
+    
     g_ppp_interrupt_enabled = false;
     g_ppp_irq_process_task = NULL;
     
@@ -659,7 +833,8 @@ void ppp_interrupt_reset_stats(void)
 {
     memset(&g_ppp_interrupt_stats, 0, sizeof(ppp_interrupt_stats_t));
     memset(&g_pingpong_stats, 0, sizeof(ppp_pingpong_stats_t));
-    PPP_DEBUG_INFO("PPP interrupt statistics reset (including ping-pong stats)");
+    memset(&g_uart_error_stats, 0, sizeof(ppp_uart_error_stats_t));
+    PPP_DEBUG_INFO("PPP interrupt statistics reset (including ping-pong and UART error stats)");
 }
 
 /**
@@ -667,18 +842,18 @@ void ppp_interrupt_reset_stats(void)
  */
 void ppp_interrupt_print_stats(void)
 {
-    PPP_DEBUG_INFO("=== PPP Interrupt Statistics (Ping-Pong Mode) ===");
-    PPP_DEBUG_INFO("Interrupt Status: %s", g_ppp_interrupt_enabled ? "ENABLED" : "DISABLED");
-    PPP_DEBUG_INFO("Ping-Pong Buffers: %d x %d bytes = %d KB total", 
+    PPP_DEBUG_WARN("=== PPP Interrupt Statistics (Ping-Pong Mode) ===");
+    PPP_DEBUG_WARN("Interrupt Status: %s", g_ppp_interrupt_enabled ? "ENABLED" : "DISABLED");
+    PPP_DEBUG_WARN("Ping-Pong Buffers: %d x %d bytes = %d KB total", 
                    PPP_PING_PONG_BUFFER_COUNT, PPP_PING_PONG_BUFFER_SIZE,
                    (PPP_PING_PONG_BUFFER_COUNT * PPP_PING_PONG_BUFFER_SIZE) / 1024);
-    PPP_DEBUG_INFO("Timeout: %d ms", PPP_PING_PONG_TIMEOUT_MS);
-    PPP_DEBUG_INFO("Message Queue: %d slots (%d bytes per message)", 
+                   PPP_DEBUG_WARN("Timeout: %d ms", PPP_PING_PONG_TIMEOUT_MS);
+    PPP_DEBUG_WARN("Message Queue: %d slots (%d bytes per message)", 
                    PPP_IRQ_MSG_QUEUE_SIZE, sizeof(ppp_irq_msg_t));
-    PPP_DEBUG_INFO("");
+    PPP_DEBUG_WARN("");
     
     // 乒乓缓冲区状态
-    PPP_DEBUG_INFO("Buffer Status:");
+    PPP_DEBUG_WARN("Buffer Status:");
     for (uint8_t i = 0; i < PPP_PING_PONG_BUFFER_COUNT; i++) {
         const char *state_str = "UNKNOWN";
         switch (g_ping_pong_buffers[i].state) {
@@ -687,39 +862,112 @@ void ppp_interrupt_print_stats(void)
             case PPP_BUFFER_STATE_FULL:       state_str = "FULL"; break;
             case PPP_BUFFER_STATE_PROCESSING: state_str = "PROCESSING"; break;
         }
-        PPP_DEBUG_INFO("  Buffer[%u]: %s, %u/%u bytes%s", 
+        PPP_DEBUG_WARN("  Buffer[%u]: %s, %u/%u bytes%s", 
                       i, state_str, g_ping_pong_buffers[i].write_pos, PPP_PING_PONG_BUFFER_SIZE,
                       (i == g_current_buffer_index) ? " (current)" : "");
     }
-    PPP_DEBUG_INFO("");
+    PPP_DEBUG_WARN("");
     
     // 乒乓缓冲区统计
-    PPP_DEBUG_INFO("Ping-Pong Buffer Statistics:");
-    PPP_DEBUG_INFO("  Buffer Full Count: %u", g_pingpong_stats.buffer_full_count);
-    PPP_DEBUG_INFO("  Buffer Timeout Count: %u", g_pingpong_stats.buffer_timeout_count);
-    PPP_DEBUG_INFO("  Buffer Switch Count: %u", g_pingpong_stats.buffer_switch_count);
-    PPP_DEBUG_INFO("  Dropped (Both Full): %u bytes ⚠️", g_pingpong_stats.dropped_both_full);
-    PPP_DEBUG_INFO("");
-    
-    // 中断统计
-    PPP_DEBUG_INFO("Total Interrupts: %u", g_ppp_interrupt_stats.total_interrupts);
-    PPP_DEBUG_INFO("  - Success: %u", g_ppp_interrupt_stats.success_count);
-    PPP_DEBUG_INFO("  - Error: %u", g_ppp_interrupt_stats.error_count);
-    PPP_DEBUG_INFO("  - lwIP Error: %u", g_ppp_interrupt_stats.lwip_error_count);
-    PPP_DEBUG_INFO("");
-    
-    // 字节统计
-    PPP_DEBUG_INFO("Total Bytes Received: %u", g_ppp_interrupt_stats.total_bytes_received);
-    PPP_DEBUG_INFO("Total Bytes Sent to lwIP: %u", g_ppp_interrupt_stats.total_bytes_sent_to_lwip);
-    PPP_DEBUG_INFO("");
-    
-    // 丢弃统计
-    PPP_DEBUG_INFO("Dropped Bytes:");
-    PPP_DEBUG_INFO("  - Not Initialized: %u", g_ppp_interrupt_stats.dropped_not_initialized);
-    PPP_DEBUG_INFO("  - lwIP Error: %u", g_ppp_interrupt_stats.dropped_lwip_error);
-    PPP_DEBUG_INFO("  - Queue Full: %u", g_ppp_interrupt_stats.dropped_queue_full);
-    PPP_DEBUG_INFO("  - Both Buffers Full: %u ⚠️", g_pingpong_stats.dropped_both_full);
-    PPP_DEBUG_INFO("");
+    PPP_DEBUG_WARN("Ping-Pong Buffer Statistics:");
+    PPP_DEBUG_WARN("  Buffer Full Count: %u", g_pingpong_stats.buffer_full_count);
+    PPP_DEBUG_WARN("  Buffer Timeout Count: %u", g_pingpong_stats.buffer_timeout_count);
+    PPP_DEBUG_WARN("  Buffer Switch Count: %u", g_pingpong_stats.buffer_switch_count);
+    PPP_DEBUG_WARN("  Dropped (Both Full): %u bytes ⚠️", g_pingpong_stats.dropped_both_full);
+    PPP_DEBUG_WARN("");
+    
+    // 中断层统计
+    PPP_DEBUG_WARN("=== Interrupt Layer Statistics ===");
+    PPP_DEBUG_WARN("Total UART Interrupts: %u", g_ppp_interrupt_stats.total_interrupts);
+    PPP_DEBUG_WARN("  - With RX Error: %u", g_ppp_interrupt_stats.error_count);
+    PPP_DEBUG_WARN("    · Parity Error: %u", g_uart_error_stats.parity_error_count);
+    PPP_DEBUG_WARN("    · Frame Error: %u", g_uart_error_stats.frame_error_count);
+    
+    // 如果有错误,显示错误率和详情
+    if (g_ppp_interrupt_stats.total_interrupts > 0) {
+        uint32_t avg_bytes_per_irq = g_ppp_interrupt_stats.total_bytes_received / 
+                                     g_ppp_interrupt_stats.total_interrupts;
+        PPP_DEBUG_WARN("  Average bytes per interrupt: %u", avg_bytes_per_irq);
+        
+        // 错误率
+        if (g_ppp_interrupt_stats.error_count > 0) {
+            uint32_t error_rate = (g_ppp_interrupt_stats.error_count * 10000) / 
+                                  g_ppp_interrupt_stats.total_interrupts;
+            PPP_DEBUG_WARN("  Error Rate: %u.%02u%%", error_rate / 100, error_rate % 100);
+            
+            // 如果错误率 > 1%,发出警告
+            if (error_rate > 100) {
+                PPP_DEBUG_ERROR("  ⚠️  High error rate! Check UART config and cable.");
+            }
+        }
+    }
+    
+    // 如果有奇偶校验错误,打印最近一次的错误信息
+    if (g_uart_error_stats.parity_error_count > 0) {
+        PPP_DEBUG_INFO("  Last Parity Error Info:");
+        for (uint32_t i = 0; i < 4; i++) {
+            if (g_uart_error_stats.last_parity_error_info[i] != 0) {
+                PPP_DEBUG_INFO("    [%u]: 0x%08X", i, 
+                              g_uart_error_stats.last_parity_error_info[i]);
+            }
+        }
+    }
+    
+    // 如果有帧错误,打印最近一次的错误信息
+    if (g_uart_error_stats.frame_error_count > 0) {
+        PPP_DEBUG_INFO("  Last Frame Error Info:");
+        for (uint32_t i = 0; i < 4; i++) {
+            if (g_uart_error_stats.last_frame_error_info[i] != 0) {
+                PPP_DEBUG_INFO("    [%u]: 0x%08X", i, 
+                              g_uart_error_stats.last_frame_error_info[i]);
+            }
+        }
+    }
+    PPP_DEBUG_WARN("");
+    
+    // 消息层统计
+    PPP_DEBUG_WARN("=== Message Layer Statistics ===");
+    PPP_DEBUG_WARN("Total Messages Sent to lwIP: %u", g_ppp_interrupt_stats.success_count);
+    PPP_DEBUG_WARN("  - lwIP Accept Error: %u", g_ppp_interrupt_stats.lwip_error_count);
+    if (g_ppp_interrupt_stats.success_count > 0) {
+        uint32_t avg_bytes = g_ppp_interrupt_stats.total_bytes_sent_to_lwip / 
+                            g_ppp_interrupt_stats.success_count;
+        PPP_DEBUG_WARN("  Average bytes per message: %u", avg_bytes);
+        
+        // 计算中断聚合比例
+        if (g_ppp_interrupt_stats.total_interrupts > 0) {
+            uint32_t irq_per_msg = g_ppp_interrupt_stats.total_interrupts / 
+                                   g_ppp_interrupt_stats.success_count;
+            PPP_DEBUG_WARN("  Interrupts per message: ~%u (aggregation ratio)", irq_per_msg);
+        }
+    }
+    PPP_DEBUG_WARN("");
+    
+    // 字节统计(与轮询模式格式一致)
+    uint32_t total_discarded = g_ppp_interrupt_stats.dropped_not_initialized + 
+                                g_ppp_interrupt_stats.dropped_lwip_error +
+                                g_ppp_interrupt_stats.dropped_queue_full +
+                                g_pingpong_stats.dropped_both_full;
+    
+    PPP_DEBUG_WARN("");
+    PPP_DEBUG_WARN("Byte Statistics:");
+    PPP_DEBUG_WARN("  Total Bytes Received: %u", g_ppp_interrupt_stats.total_bytes_received);
+    PPP_DEBUG_WARN("  Total Bytes Processed: %u", g_ppp_interrupt_stats.total_bytes_sent_to_lwip);
+    PPP_DEBUG_WARN("  Total Bytes Discarded: %u", total_discarded);
+    PPP_DEBUG_WARN("    - Both Buffers Full: %u", g_pingpong_stats.dropped_both_full);
+    PPP_DEBUG_WARN("    - Queue Full: %u", g_ppp_interrupt_stats.dropped_queue_full);
+    PPP_DEBUG_WARN("  lwIP Errors: %u", g_ppp_interrupt_stats.lwip_error_count);
+    PPP_DEBUG_WARN("");
+    
+    // 详细丢弃统计(INFO级别)
+    if (total_discarded > 0) {
+        PPP_DEBUG_WARN("Detailed Dropped Bytes:");
+        PPP_DEBUG_WARN("  - Not Initialized: %u", g_ppp_interrupt_stats.dropped_not_initialized);
+        PPP_DEBUG_WARN("  - lwIP Error: %u", g_ppp_interrupt_stats.dropped_lwip_error);
+        PPP_DEBUG_WARN("  - Queue Full: %u", g_ppp_interrupt_stats.dropped_queue_full);
+        PPP_DEBUG_WARN("  - Both Buffers Full: %u", g_pingpong_stats.dropped_both_full);
+        PPP_DEBUG_WARN("");
+    }
     
     // 计算丢包率
     if (g_ppp_interrupt_stats.total_bytes_received > 0) {
@@ -728,13 +976,13 @@ void ppp_interrupt_print_stats(void)
                                  g_ppp_interrupt_stats.dropped_queue_full +
                                  g_pingpong_stats.dropped_both_full;
         uint32_t drop_rate = (total_dropped * 10000) / g_ppp_interrupt_stats.total_bytes_received;
-        PPP_DEBUG_INFO("Total Drop Rate: %u.%02u%%", drop_rate / 100, drop_rate % 100);
+        PPP_DEBUG_WARN("Total Drop Rate: %u.%02u%%", drop_rate / 100, drop_rate % 100);
         
         // 队列满导致的丢失率
         if (g_ppp_interrupt_stats.dropped_queue_full > 0) {
             uint32_t queue_full_rate = (g_ppp_interrupt_stats.dropped_queue_full * 10000) / 
                                        g_ppp_interrupt_stats.total_bytes_received;
-            PPP_DEBUG_INFO("Queue Full Rate: %u.%02u%%", queue_full_rate / 100, queue_full_rate % 100);
+            PPP_DEBUG_WARN("Queue Full Rate: %u.%02u%%", queue_full_rate / 100, queue_full_rate % 100);
         }
         
         // 两个buffer都满导致的丢失率
@@ -746,18 +994,7 @@ void ppp_interrupt_print_stats(void)
         }
     }
     
-    // 性能指标
-    if (g_ppp_interrupt_stats.success_count > 0) {
-        uint32_t avg_bytes = g_ppp_interrupt_stats.total_bytes_sent_to_lwip / 
-                            g_ppp_interrupt_stats.success_count;
-        PPP_DEBUG_INFO("Average bytes per message: %u", avg_bytes);
-    }
-    
-    if (g_ppp_interrupt_stats.total_interrupts > 0) {
-        uint32_t avg_bytes_per_irq = g_ppp_interrupt_stats.total_bytes_received / 
-                                     g_ppp_interrupt_stats.total_interrupts;
-        PPP_DEBUG_INFO("Average bytes per interrupt: %u", avg_bytes_per_irq);
-    }
+    // 性能总结(已经在上面各部分显示过了,这里不再重复)
     
-    PPP_DEBUG_INFO("=================================================");
+    PPP_DEBUG_WARN("=================================================");
 } 
\ No newline at end of file
index f4b2d64..580b9a1 100644 (file)
@@ -164,6 +164,15 @@ static ppp_error_t ppp_flush_buffer(uint8_t buffer_index)
 
 /**
  * @brief 定时器回调:检查buffer超时并flush
+ * 
+ * 数据安全设计(避免竞态):
+ * - 定时器职责:只检查和flush **非当前** buffer(避免与接收线程竞争)
+ * - 接收线程职责:
+ *   1. 在循环开始时主动检查当前buffer是否超时,超时则flush+切换
+ *   2. 检查当前buffer状态,如果不可写则切换
+ *   3. 独占 g_current_buffer_index 的修改权
+ * - 分工明确:定时器不操作当前buffer,接收线程负责当前buffer的超时处理
+ * - 数据保证:stop时强制flush所有buffer,确保数据不丢失
  */
 static void ppp_timeout_timer_callback(unsigned long arg)
 {
@@ -174,30 +183,37 @@ static void ppp_timeout_timer_callback(unsigned long arg)
     }
     
     uint32_t current_time = ppp_get_current_time_ms();
+    uint8_t current_idx = g_current_buffer_index;  // 读取一次,避免重复读取
     
-    // 检查所有buffer的超时状态
+    // 检查非当前buffer的超时状态
+    // ⚠️ 数据安全设计:定时器只处理非当前buffer,避免与接收线程竞争
+    // 当前buffer的超时由接收线程主动检查并处理
     for (uint8_t i = 0; i < PPP_PING_PONG_BUFFER_COUNT; i++) {
+        // 跳过当前正在写入的buffer(避免与接收线程竞争,保证数据安全)
+        if (i == current_idx) {
+            continue;
+        }
+        
         ppp_ping_pong_buffer_t *buffer = &g_ping_pong_buffers[i];
         
         // 只处理FILLING状态的buffer
         if (buffer->state == PPP_BUFFER_STATE_FILLING && buffer->write_pos > 0) {
-            uint32_t elapsed = current_time - buffer->last_write_time;
-            
-            if (elapsed >= PPP_PING_PONG_TIMEOUT_MS) {
-                PPP_DEBUG_DEBUG("[TIMER] Flushing buffer[%u] due to timeout (%u ms)", i, elapsed);
+            // ⚠️ 修复:避免误判超时
+            // last_write_time == 0 表示接收线程刚写入数据,需要更新时间戳(不是超时)
+            if (buffer->last_write_time == 0) {
+                // 第一次看到,更新时间戳,不flush
+                buffer->last_write_time = current_time;
+                PPP_DEBUG_DEBUG("[TIMER] Update timestamp for buffer[%u]", i);
+            } else {
+                // 已经有时间戳了,检查是否真的超时
+                uint32_t elapsed = current_time - buffer->last_write_time;
                 
-                if (ppp_flush_buffer(i) == PPP_ERR_OK) {
-                    g_ppp_stats.buffer_timeout_count++;
+                if (elapsed >= PPP_PING_PONG_TIMEOUT_MS) {
+                    // 真正超时,flush buffer
+                    PPP_DEBUG_DEBUG("[TIMER] Flushing buffer[%u] due to timeout (%u ms)", i, elapsed);
                     
-                    // Timer flush后切换buffer
-                    if (i == g_current_buffer_index) {
-                        uint8_t next_idx = (i + 1) % PPP_PING_PONG_BUFFER_COUNT;
-                        ppp_ping_pong_buffer_t *next_buffer = &g_ping_pong_buffers[next_idx];
-                        
-                        if (next_buffer->state == PPP_BUFFER_STATE_EMPTY) {
-                            g_current_buffer_index = next_idx;
-                            g_ppp_stats.buffer_switch_count++;
-                        }
+                    if (ppp_flush_buffer(i) == PPP_ERR_OK) {
+                        g_ppp_stats.buffer_timeout_count++;
                     }
                 }
             }
@@ -315,6 +331,12 @@ static void ppp_lwip_process_thread(void *arg)
 
 /**
  * @brief PPP数据接收线程 - 轮询UART并填充到乒乓buffer
+ * 
+ * 优化设计:
+ * - 每次读取尝试填满当前 buffer 的剩余空间(高效利用)
+ * - 独占 g_current_buffer_index 的修改权(避免竞态)
+ * - 及时检查 buffer 状态并切换(避免数据丢失)
+ * - 检查超时并主动 flush 当前 buffer(配合定时器)
  */
 static void ppp_lwip_receive_thread(void *arg)
 {
@@ -322,9 +344,9 @@ static void ppp_lwip_receive_thread(void *arg)
     
     PPP_DEBUG_INFO("PPP receive thread started (ping-pong polling mode)");
 
-    // å\88\86é\85\8d临æ\97¶è¯»å\8f\96ç¼\93å\86²å\8cºï¼\88æ¯\8f次æ\9c\80å¤\9a读å\8f\96512å­\97è\8a\82)
-    const uint32_t read_chunk_size = 1;
-    uint8_t *rx_buffer = (uint8_t *)malloc(read_chunk_size);
+    // å\88\86é\85\8d临æ\97¶è¯»å\8f\96ç¼\93å\86²å\8cºï¼\88æ\9c\80大读å\8f\96大å°\8f)
+    const uint32_t max_read_size = PPP_PING_PONG_BUFFER_SIZE;
+    uint8_t *rx_buffer = (uint8_t *)malloc(max_read_size);
     if (!rx_buffer) {
         PPP_DEBUG_ERROR("PPP RX buffer alloc failed");
         g_ppp_rx_thread_completed = true;
@@ -332,105 +354,203 @@ static void ppp_lwip_receive_thread(void *arg)
     }
 
     uint32_t total_bytes = 0;
-    uint32_t consecutive_empty = 0;
+    uint32_t last_timeout_check = 0;
 
-    PPP_DEBUG_INFO("PPP receive thread: allocated %d bytes temp buffer", read_chunk_size);
+    PPP_DEBUG_INFO("PPP receive thread: allocated %d bytes temp buffer", max_read_size);
 
     // 主循环:连续轮询UART读取
     while (g_ppp_rx_thread_running) {
+        // 1. ⚠️ 数据安全:主动检查当前 buffer 是否超时
+        //    定时器只处理非当前buffer,所以当前buffer的超时要在这里处理
+        uint8_t current_idx = g_current_buffer_index;
+        ppp_ping_pong_buffer_t *current_buffer = &g_ping_pong_buffers[current_idx];
+        
+        if (current_buffer->state == PPP_BUFFER_STATE_FILLING && 
+            current_buffer->write_pos > 0 &&
+            current_buffer->last_write_time != 0) {  // ← 修复:只有已有时间戳的才检查超时
+            uint32_t current_time = ppp_get_current_time_ms();
+            uint32_t elapsed = current_time - current_buffer->last_write_time;
+            
+            if (elapsed >= PPP_PING_PONG_TIMEOUT_MS) {
+                // 当前buffer超时,flush并切换
+                PPP_DEBUG_DEBUG("[RX] Flushing current buffer[%u] due to timeout (%u ms)", 
+                               current_idx, elapsed);
+                ppp_flush_buffer(current_idx);
+                g_ppp_stats.buffer_timeout_count++;
+                
+                // 切换到下一个EMPTY的buffer
+                uint8_t next_idx = (current_idx + 1) % PPP_PING_PONG_BUFFER_COUNT;
+                ppp_ping_pong_buffer_t *next_buffer = &g_ping_pong_buffers[next_idx];
+                
+                if (next_buffer->state == PPP_BUFFER_STATE_EMPTY) {
+                    g_current_buffer_index = next_idx;
+                    g_ppp_stats.buffer_switch_count++;
+                    current_idx = next_idx;
+                    current_buffer = next_buffer;
+                }
+            }
+        }
+        
+        // 2. 检查当前 buffer 状态,确保可用
+        // 重新读取(可能在步骤1中已经切换了)
+        current_idx = g_current_buffer_index;
+        current_buffer = &g_ping_pong_buffers[current_idx];
+        
+        // 如果当前 buffer 不是 FILLING 状态(可能被定时器 flush 了或正在处理)
+        // 尝试切换到下一个 EMPTY 的 buffer
+        if (current_buffer->state != PPP_BUFFER_STATE_FILLING && 
+            current_buffer->state != PPP_BUFFER_STATE_EMPTY) {
+            
+            bool switched = false;
+            for (uint8_t attempts = 0; attempts < PPP_PING_PONG_BUFFER_COUNT; attempts++) {
+                uint8_t next_idx = (current_idx + attempts + 1) % PPP_PING_PONG_BUFFER_COUNT;
+                ppp_ping_pong_buffer_t *next_buffer = &g_ping_pong_buffers[next_idx];
+                
+                if (next_buffer->state == PPP_BUFFER_STATE_EMPTY) {
+                    g_current_buffer_index = next_idx;
+                    g_ppp_stats.buffer_switch_count++;
+                    current_idx = next_idx;
+                    current_buffer = next_buffer;
+                    switched = true;
+                    PPP_DEBUG_DEBUG("Switched to buffer[%u] (previous not available)", next_idx);
+                    break;
+                }
+            }
+            
+            if (!switched) {
+                // 所有 buffer 都不可用,等待一下
+                g_ppp_stats.dropped_both_full++;
+                
+                // ⚠️ 打印 buffer 状态,帮助诊断
+                static uint32_t drop_log_counter = 0;
+                if ((drop_log_counter++ % 10) == 0) {  // 每 10 次打印一次,避免日志过多
+                    PPP_DEBUG_WARN("Both buffers unavailable! Drop event %u", drop_log_counter);
+                    for (uint8_t i = 0; i < PPP_PING_PONG_BUFFER_COUNT; i++) {
+                        const char *state = "UNKNOWN";
+                        switch (g_ping_pong_buffers[i].state) {
+                            case PPP_BUFFER_STATE_EMPTY: state = "EMPTY"; break;
+                            case PPP_BUFFER_STATE_FILLING: state = "FILLING"; break;
+                            case PPP_BUFFER_STATE_FULL: state = "FULL"; break;
+                            case PPP_BUFFER_STATE_PROCESSING: state = "PROCESSING"; break;
+                        }
+                        PPP_DEBUG_WARN("  Buffer[%u]: %s, %u bytes", 
+                                      i, state, g_ping_pong_buffers[i].write_pos);
+                    }
+                }
+                
+                osal_msleep(1);
+                continue;
+            }
+        }
+        
+        // 2. 初始化 buffer(如果需要)
+        if (current_buffer->state == PPP_BUFFER_STATE_EMPTY) {
+            current_buffer->state = PPP_BUFFER_STATE_FILLING;
+            current_buffer->write_pos = 0;
+            current_buffer->last_write_time = ppp_get_current_time_ms();
+        }
+        
+        // 3. 计算可读取的大小(尝试填满 buffer)
+        uint32_t available = PPP_PING_PONG_BUFFER_SIZE - current_buffer->write_pos;
+        uint32_t read_size = (available < max_read_size) ? available : max_read_size;
+        
+        // 限制单次读取不超过 1024 字节(平衡性能和响应速度)
+        if (read_size > 1024) {
+            read_size = 1024;
+        }
+        
+        // 4. 读取数据
         uint32_t bytes_read = 0;
-        ppp_error_t ret = ppp_serial_tryread(rx_buffer, read_chunk_size, &bytes_read);
+        ppp_error_t ret = ppp_serial_tryread(rx_buffer, read_size, &bytes_read);
         
         if (ret == PPP_ERR_OK && bytes_read > 0) {
             // 成功读取数据
             total_bytes += bytes_read;
-            consecutive_empty = 0;
             g_ppp_stats.read_count++;
             g_ppp_stats.total_bytes_received += bytes_read;
             
-            PPP_DEBUG_DEBUG("PPP RX: Got %u bytes", bytes_read);
+            PPP_DEBUG_DEBUG("PPP RX: Got %u bytes (buffer[%u]: %u/%u)", 
+                           bytes_read, current_idx, current_buffer->write_pos, 
+                           PPP_PING_PONG_BUFFER_SIZE);
             
-            // 填充到乒乓buffer
-            uint32_t processed = 0;
-            while (processed < bytes_read && g_ppp_rx_thread_running) {
-                uint8_t current_idx = g_current_buffer_index;
-                ppp_ping_pong_buffer_t *current_buffer = &g_ping_pong_buffers[current_idx];
-                
-                // 如果buffer是空的,初始化为FILLING状态
-                if (current_buffer->state == PPP_BUFFER_STATE_EMPTY) {
-                    current_buffer->state = PPP_BUFFER_STATE_FILLING;
-                    current_buffer->write_pos = 0;
-                }
-                
-                // 尝试写入当前buffer
-                uint32_t available = PPP_PING_PONG_BUFFER_SIZE - current_buffer->write_pos;
-                uint32_t to_write = bytes_read - processed;
+            // 5. 写入当前 buffer
+            memcpy(current_buffer->data + current_buffer->write_pos, rx_buffer, bytes_read);
+            current_buffer->write_pos += bytes_read;
+            current_buffer->last_write_time = ppp_get_current_time_ms();
+            
+            // 6. 检查是否满了或接近满了
+            if (current_buffer->write_pos >= PPP_PING_PONG_BUFFER_SIZE) {
+                // buffer 满了,立即 flush 并切换
+                PPP_DEBUG_DEBUG("Buffer[%u] full, flushing...", current_idx);
+                ppp_flush_buffer(current_idx);
+                g_ppp_stats.buffer_full_count++;
                 
-                if (current_buffer->state == PPP_BUFFER_STATE_FILLING && to_write <= available) {
-                    // 空间足够,直接写入
-                    memcpy(current_buffer->data + current_buffer->write_pos, 
-                           rx_buffer + processed, to_write);
-                    current_buffer->write_pos += to_write;
-                    current_buffer->last_write_time = ppp_get_current_time_ms();
-                    processed += to_write;
-                    
-                    // 检查是否满了
-                    if (current_buffer->write_pos >= PPP_PING_PONG_BUFFER_SIZE) {
-                        // buffer满,flush
-                        ppp_flush_buffer(current_idx);
-                        g_ppp_stats.buffer_full_count++;
-                        
-                        // 切换到另一个buffer
-                        uint8_t next_idx = (current_idx + 1) % PPP_PING_PONG_BUFFER_COUNT;
-                        ppp_ping_pong_buffer_t *next_buffer = &g_ping_pong_buffers[next_idx];
-                        
-                        if (next_buffer->state == PPP_BUFFER_STATE_EMPTY) {
-                            g_current_buffer_index = next_idx;
-                            g_ppp_stats.buffer_switch_count++;
-                        }
-                    }
-                } else {
-                    // 当前buffer空间不足或不可用,尝试切换
-                    uint8_t next_idx = (current_idx + 1) % PPP_PING_PONG_BUFFER_COUNT;
+                // 切换到下一个 EMPTY 的 buffer
+                bool switched = false;
+                for (uint8_t attempts = 0; attempts < PPP_PING_PONG_BUFFER_COUNT; attempts++) {
+                    uint8_t next_idx = (current_idx + attempts + 1) % PPP_PING_PONG_BUFFER_COUNT;
                     ppp_ping_pong_buffer_t *next_buffer = &g_ping_pong_buffers[next_idx];
                     
                     if (next_buffer->state == PPP_BUFFER_STATE_EMPTY) {
-                        // 先flush当前buffer(如果有数据)
-                        if (current_buffer->state == PPP_BUFFER_STATE_FILLING && 
-                            current_buffer->write_pos > 0) {
-                            ppp_flush_buffer(current_idx);
-                        }
-                        
-                        // 切换到新buffer
                         g_current_buffer_index = next_idx;
                         g_ppp_stats.buffer_switch_count++;
-                        
-                        // 继续处理剩余数据(下次循环会写入新buffer)
-                    } else {
-                        // 两个buffer都不可用,丢弃数据
-                        uint32_t discarded = bytes_read - processed;
-                        g_ppp_stats.dropped_both_full += discarded;
-                        g_ppp_stats.total_bytes_discarded += discarded;
-                        PPP_DEBUG_WARN("Both buffers full, discarding %u bytes", discarded);
+                        switched = true;
+                        PPP_DEBUG_DEBUG("Switched to buffer[%u]", next_idx);
                         break;
                     }
                 }
+                
+                if (!switched) {
+                    // 没有空闲 buffer,等待处理线程
+                    PPP_DEBUG_WARN("No empty buffer available, waiting...");
+                    osal_msleep(1);
+                }
             }
             
             // 有数据,不休眠,继续读取
+            
         } else if (ret != PPP_ERR_OK) {
             // 读取错误
             if (!g_ppp_rx_thread_running) {
                 break;
             }
             PPP_DEBUG_ERROR("PPP serial tryread error: %d", ret);
-            osal_msleep(10);  // 错误时稍微休眠
+            osal_msleep(10);
+            
         } else {
             // 无数据
-            consecutive_empty++;
             g_ppp_stats.read_empty_count++;
             
-            // 无数据时休眠1ms
+            // 7. 检查当前 buffer 是否超时(配合定时器)
+            uint32_t current_time = ppp_get_current_time_ms();
+            if (current_time - last_timeout_check >= PPP_PING_PONG_TIMEOUT_MS) {
+                last_timeout_check = current_time;
+                
+                // 检查当前 buffer 是否有数据且超时
+                if (current_buffer->state == PPP_BUFFER_STATE_FILLING && 
+                    current_buffer->write_pos > 0) {
+                    
+                    uint32_t elapsed = current_time - current_buffer->last_write_time;
+                    if (elapsed >= PPP_PING_PONG_TIMEOUT_MS) {
+                        // 超时,flush 当前 buffer
+                        PPP_DEBUG_DEBUG("Buffer[%u] timeout (%u ms), flushing %u bytes", 
+                                       current_idx, elapsed, current_buffer->write_pos);
+                        ppp_flush_buffer(current_idx);
+                        g_ppp_stats.buffer_timeout_count++;
+                        
+                        // 切换到下一个 buffer
+                        uint8_t next_idx = (current_idx + 1) % PPP_PING_PONG_BUFFER_COUNT;
+                        ppp_ping_pong_buffer_t *next_buffer = &g_ping_pong_buffers[next_idx];
+                        
+                        if (next_buffer->state == PPP_BUFFER_STATE_EMPTY) {
+                            g_current_buffer_index = next_idx;
+                            g_ppp_stats.buffer_switch_count++;
+                        }
+                    }
+                }
+            }
+            
+            // 无数据时休眠 1ms
             osal_msleep(1);
         }
 
@@ -440,6 +560,15 @@ static void ppp_lwip_receive_thread(void *arg)
         }
     }
 
+    // 退出前,flush 当前 buffer(如果有数据)
+    uint8_t final_idx = g_current_buffer_index;
+    ppp_ping_pong_buffer_t *final_buffer = &g_ping_pong_buffers[final_idx];
+    if (final_buffer->state == PPP_BUFFER_STATE_FILLING && final_buffer->write_pos > 0) {
+        PPP_DEBUG_INFO("Flushing final buffer[%u] with %u bytes", 
+                      final_idx, final_buffer->write_pos);
+        ppp_flush_buffer(final_idx);
+    }
+
     // 释放缓冲区
     free(rx_buffer);
 
@@ -523,7 +652,7 @@ ppp_error_t ppp_lwip_start_receive_thread(void)
     app_task_definition_t process_task_cfg = {0};
     process_task_cfg.create_queue_handle = NULL;
     process_task_cfg.attr.name = "ppp_process";
-    process_task_cfg.attr.priority = osPriorityNormal1;
+    process_task_cfg.attr.priority = PPP_PROCESS_THREAD_PRIORITY;  // 使用配置的优先级
     process_task_cfg.attr.stack_size = PPP_PROCESS_STACK_SIZE;
     process_task_cfg.func = ppp_lwip_process_thread;
     process_task_cfg.task_handle = &g_ppp_process_thread_handle;
@@ -540,13 +669,13 @@ ppp_error_t ppp_lwip_start_receive_thread(void)
         return PPP_ERR_MEMORY;
     }
     
-    // 5. 启动接收线程
+    // 5. 启动接收线程(高优先级以确保及时读取数据)
     g_ppp_rx_thread_running = true;
     
     app_task_definition_t rx_task_cfg = {0};
     rx_task_cfg.create_queue_handle = NULL;
     rx_task_cfg.attr.name = "ppp_receive";
-    rx_task_cfg.attr.priority = osPriorityNormal1;
+    rx_task_cfg.attr.priority = PPP_RX_THREAD_PRIORITY;  // 使用配置的高优先级
     rx_task_cfg.attr.stack_size = PPP_RX_STACK_SIZE;
     rx_task_cfg.func = ppp_lwip_receive_thread;
     rx_task_cfg.task_handle = &g_ppp_rx_thread_handle;
@@ -597,7 +726,11 @@ ppp_error_t ppp_lwip_stop_receive_thread(void)
         g_ppp_timer_running = false;
         osal_timer_stop(&g_ppp_timeout_timer);
         osal_timer_destroy(&g_ppp_timeout_timer);
-        PPP_DEBUG_INFO("Timeout timer stopped");
+        
+        // ⚠️ 关键:清零定时器句柄,确保可以重新初始化
+        g_ppp_timeout_timer.timer = NULL;
+        
+        PPP_DEBUG_INFO("Timeout timer stopped and cleared");
     }
     
     // 2. 停止接收线程
@@ -648,10 +781,25 @@ ppp_error_t ppp_lwip_stop_receive_thread(void)
     // 4. 清理队列
     if (g_ppp_msg_queue != 0) {
         osal_msg_queue_delete(g_ppp_msg_queue);
+        
+        // ⚠️ 关键:清零队列句柄,确保可以重新创建
         g_ppp_msg_queue = 0;
     }
     
-    // 5. 清空乒乓缓冲区
+    // 5. ⚠️ 数据安全:在清空前,先flush所有有数据的buffer,确保数据不丢失
+    PPP_DEBUG_INFO("Flushing all buffers before stop...");
+    for (uint8_t i = 0; i < PPP_PING_PONG_BUFFER_COUNT; i++) {
+        if (g_ping_pong_buffers[i].state == PPP_BUFFER_STATE_FILLING && 
+            g_ping_pong_buffers[i].write_pos > 0) {
+            PPP_DEBUG_INFO("  Flushing buffer[%u]: %u bytes", 
+                          i, g_ping_pong_buffers[i].write_pos);
+            ppp_flush_buffer(i);
+            // 给处理线程一点时间处理最后的数据
+            osal_msleep(50);
+        }
+    }
+    
+    // 6. 清空乒乓缓冲区
     for (uint8_t i = 0; i < PPP_PING_PONG_BUFFER_COUNT; i++) {
         g_ping_pong_buffers[i].write_pos = 0;
         g_ping_pong_buffers[i].state = PPP_BUFFER_STATE_EMPTY;
@@ -705,16 +853,16 @@ void ppp_lwip_reset_discard_stats(void)
  */
 void ppp_lwip_print_discard_stats(void)
 {
-    PPP_DEBUG_INFO("=== PPP Polling Statistics (Ping-Pong Mode) ===");
-    PPP_DEBUG_INFO("Mode: Polling (轮询替代中断)");
-    PPP_DEBUG_INFO("Buffers: %d x %d bytes = %d KB total", 
+    PPP_DEBUG_WARN("=== PPP Polling Statistics (Ping-Pong Mode) ===");
+    PPP_DEBUG_WARN("Mode: Polling (轮询替代中断)");
+    PPP_DEBUG_WARN("Buffers: %d x %d bytes = %d KB total", 
                    PPP_PING_PONG_BUFFER_COUNT, PPP_PING_PONG_BUFFER_SIZE,
                    (PPP_PING_PONG_BUFFER_COUNT * PPP_PING_PONG_BUFFER_SIZE) / 1024);
-    PPP_DEBUG_INFO("Timeout: %d ms", PPP_PING_PONG_TIMEOUT_MS);
-    PPP_DEBUG_INFO("");
+                   PPP_DEBUG_WARN("Timeout: %d ms", PPP_PING_PONG_TIMEOUT_MS);
+                   PPP_DEBUG_WARN("");
     
     // Buffer状态
-    PPP_DEBUG_INFO("Buffer Status:");
+    PPP_DEBUG_WARN("Buffer Status:");
     for (uint8_t i = 0; i < PPP_PING_PONG_BUFFER_COUNT; i++) {
         const char *state_str = "UNKNOWN";
         switch (g_ping_pong_buffers[i].state) {
@@ -723,54 +871,54 @@ void ppp_lwip_print_discard_stats(void)
             case PPP_BUFFER_STATE_FULL:       state_str = "FULL"; break;
             case PPP_BUFFER_STATE_PROCESSING: state_str = "PROCESSING"; break;
         }
-        PPP_DEBUG_INFO("  Buffer[%u]: %s, %u/%u bytes%s", 
+        PPP_DEBUG_WARN("  Buffer[%u]: %s, %u/%u bytes%s", 
                       i, state_str, g_ping_pong_buffers[i].write_pos, 
                       PPP_PING_PONG_BUFFER_SIZE,
                       (i == g_current_buffer_index) ? " (current)" : "");
     }
-    PPP_DEBUG_INFO("");
+    PPP_DEBUG_WARN("");
     
     // 乒乓buffer统计
-    PPP_DEBUG_INFO("Ping-Pong Buffer Statistics:");
-    PPP_DEBUG_INFO("  Buffer Full Count: %u", g_ppp_stats.buffer_full_count);
-    PPP_DEBUG_INFO("  Buffer Timeout Count: %u", g_ppp_stats.buffer_timeout_count);
-    PPP_DEBUG_INFO("  Buffer Switch Count: %u", g_ppp_stats.buffer_switch_count);
-    PPP_DEBUG_INFO("");
+    PPP_DEBUG_WARN("Ping-Pong Buffer Statistics:");
+    PPP_DEBUG_WARN("  Buffer Full Count: %u", g_ppp_stats.buffer_full_count);
+    PPP_DEBUG_WARN("  Buffer Timeout Count: %u", g_ppp_stats.buffer_timeout_count);
+    PPP_DEBUG_WARN("  Buffer Switch Count: %u", g_ppp_stats.buffer_switch_count);
+    PPP_DEBUG_WARN("");
     
     // UART轮询统计
-    PPP_DEBUG_INFO("UART Polling Statistics:");
-    PPP_DEBUG_INFO("  Total Read Attempts: %u", g_ppp_stats.read_count + g_ppp_stats.read_empty_count);
-    PPP_DEBUG_INFO("  Successful Reads: %u", g_ppp_stats.read_count);
-    PPP_DEBUG_INFO("  Empty Reads: %u", g_ppp_stats.read_empty_count);
+    PPP_DEBUG_WARN("UART Polling Statistics:");
+    PPP_DEBUG_WARN("  Total Read Attempts: %u", g_ppp_stats.read_count + g_ppp_stats.read_empty_count);
+    PPP_DEBUG_WARN("  Successful Reads: %u", g_ppp_stats.read_count);
+    PPP_DEBUG_WARN("  Empty Reads: %u", g_ppp_stats.read_empty_count);
     if (g_ppp_stats.read_count + g_ppp_stats.read_empty_count > 0) {
         uint32_t hit_rate = (g_ppp_stats.read_count * 100) / 
                            (g_ppp_stats.read_count + g_ppp_stats.read_empty_count);
-        PPP_DEBUG_INFO("  Hit Rate: %u%%", hit_rate);
+                           PPP_DEBUG_WARN("  Hit Rate: %u%%", hit_rate);
     }
-    PPP_DEBUG_INFO("");
+    PPP_DEBUG_WARN("");
     
     // 字节统计
-    PPP_DEBUG_INFO("Byte Statistics:");
-    PPP_DEBUG_INFO("  Total Bytes Received: %u", g_ppp_stats.total_bytes_received);
-    PPP_DEBUG_INFO("  Total Bytes Processed: %u", g_ppp_stats.total_bytes_processed);
-    PPP_DEBUG_INFO("  Total Bytes Discarded: %u", g_ppp_stats.total_bytes_discarded);
-    PPP_DEBUG_INFO("    - Both Buffers Full: %u", g_ppp_stats.dropped_both_full);
-    PPP_DEBUG_INFO("    - Queue Full: %u", g_ppp_stats.dropped_queue_full);
-    PPP_DEBUG_INFO("  lwIP Errors: %u", g_ppp_stats.lwip_error_count);
-    PPP_DEBUG_INFO("");
+    PPP_DEBUG_WARN("Byte Statistics:");
+    PPP_DEBUG_WARN("  Total Bytes Received: %u", g_ppp_stats.total_bytes_received);
+    PPP_DEBUG_WARN("  Total Bytes Processed: %u", g_ppp_stats.total_bytes_processed);
+    PPP_DEBUG_WARN("  Total Bytes Discarded: %u", g_ppp_stats.total_bytes_discarded);
+    PPP_DEBUG_WARN("    - Both Buffers Full: %u", g_ppp_stats.dropped_both_full);
+    PPP_DEBUG_WARN("    - Queue Full: %u", g_ppp_stats.dropped_queue_full);
+    PPP_DEBUG_WARN("  lwIP Errors: %u", g_ppp_stats.lwip_error_count);
+    PPP_DEBUG_WARN("");
     
     // 丢包率
     if (g_ppp_stats.total_bytes_received > 0) {
         uint32_t drop_rate = (g_ppp_stats.total_bytes_discarded * 10000) / 
                             g_ppp_stats.total_bytes_received;
-        PPP_DEBUG_INFO("Drop Rate: %u.%02u%%", drop_rate / 100, drop_rate % 100);
+                            PPP_DEBUG_WARN("Drop Rate: %u.%02u%%", drop_rate / 100, drop_rate % 100);
     }
     
     // 平均字节数
     if (g_ppp_stats.read_count > 0) {
         uint32_t avg_bytes = g_ppp_stats.total_bytes_received / g_ppp_stats.read_count;
-        PPP_DEBUG_INFO("Average bytes per read: %u", avg_bytes);
+        PPP_DEBUG_WARN("Average bytes per read: %u", avg_bytes);
     }
     
-    PPP_DEBUG_INFO("=================================================");
+    PPP_DEBUG_WARN("=================================================");
 }
\ No newline at end of file
index 2ef654e..f68ab04 100644 (file)
 /* PPP性能优化配置 */
 #define PPP_OPTIMIZED_UART_WRITE_TIMEOUT    200    /* UART写超时优化: 1000ms -> 200ms */
 #define PPP_OPTIMIZED_UART_READ_TIMEOUT     100    /* UART读超时优化: 200ms -> 100ms */
-
+#if defined(CONFIG_UART_SUPPORT_DMA)
+#define UART_DMA_WIDTH                         0
+#define UART_DMA_BURST_LENGTH                  2
+#define UART_DMA_PRIORITY                      0
+#define UART_DMA_TX_ENABLE                     1
+#define UART_DMA_RX_ENABLE                     1
+#endif
 /* 串口上下文结构 - 优化缓存机制 */
 typedef struct {
     bool initialized;
@@ -27,6 +33,7 @@ typedef struct {
     uart_pin_config_t pin_config;
     uart_attr_t uart_attr;
     uart_buffer_config_t buffer_config;
+    uart_extra_attr_t extra_attr;
     
     /* 统一的接收缓冲区(AT和PPP模式共用) */
     uint8_t *rx_buffer;
@@ -173,13 +180,39 @@ ppp_error_t ppp_serial_init(const ppp_serial_config_t *config)
 
     /* 初始化UART */
     PPP_DEBUG_DEBUG("Calling uapi_uart_init...");
+    #if defined(PPP_USE_INTERRUPT_MODE) && (PPP_USE_INTERRUPT_MODE == 0)
     // 注意:uart_porting.c中已经做了UART初始化,这里只需要设置属性
-    // 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 defined(CONFIG_UART_SUPPORT_DMA)
+        g_serial_ctx.extra_attr.tx_dma_enable = UART_DMA_TX_ENABLE;
+        g_serial_ctx.extra_attr.tx_int_threshold = 0;
+        g_serial_ctx.extra_attr.rx_dma_enable = UART_DMA_RX_ENABLE;
+        g_serial_ctx.extra_attr.rx_int_threshold = 0;
+        uapi_dma_init();
+        uapi_dma_open();
+        errcode_t ret = uapi_uart_init(g_serial_ctx.uart_bus, 
+            &g_serial_ctx.pin_config,
+            &g_serial_ctx.uart_attr, 
+            &g_serial_ctx.extra_attr, 
+            &g_serial_ctx.buffer_config);
+        #else
+        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);
+        #endif
+
+    #else
+    
+    // 注意:uart_porting.c中已经做了UART初始化,这里只需要设置属性 
+    // 需要配置 SUPPORT_PPP_SERVICE_INTERRUPT 才在uart_porting里初始化uart
     errcode_t ret = uapi_uart_set_attr(g_serial_ctx.uart_bus, &g_serial_ctx.uart_attr);
+  
+    #endif
     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", 
@@ -191,7 +224,6 @@ ppp_error_t ppp_serial_init(const ppp_serial_config_t *config)
         osal_mutex_destroy(&g_serial_ctx.tx_mutex);
         return PPP_ERR_UART;
     }
-
     PPP_DEBUG_INFO("UART initialized successfully (error code = %d)", ret);
 
     /* 创建同步对象 */
@@ -469,7 +501,19 @@ ppp_error_t ppp_serial_read(uint8_t *buffer, uint32_t buffer_size, uint32_t *byt
         case PPP_SERIAL_MODE_AT:
         /* AT命令模式:直接从UART读取 */
             {
+
+                #if defined(CONFIG_UART_SUPPORT_DMA)
+                uart_write_dma_config_t dma_cfg = {
+                    .src_width = UART_DMA_WIDTH,
+                    .dest_width = UART_DMA_WIDTH,
+                    .burst_length = UART_DMA_BURST_LENGTH,
+                    .priority = UART_DMA_PRIORITY
+                };
+                int32_t read_result = uapi_uart_read_by_dma(g_serial_ctx.uart_bus, buffer, buffer_size,&dma_cfg);
+                    
+                #else
                 int32_t read_result = uapi_uart_read(g_serial_ctx.uart_bus, buffer, buffer_size, 100);
+                #endif
                 if (read_result > 0) {
                     *bytes_read = (uint32_t)read_result;
                     g_serial_ctx.rx_bytes += *bytes_read;
@@ -499,9 +543,21 @@ ppp_error_t ppp_serial_read(uint8_t *buffer, uint32_t buffer_size, uint32_t *byt
                     uint8_t *current_buffer = buffer + total_read;
                     
                     // 使用短超时进行读取,类似sio_tryread的1ms超时
-                    int32_t read_result = uapi_uart_read(g_serial_ctx.uart_bus, current_buffer, 
-                                                        remaining, batch_count == 0 ? 10 : 1);
                     
+                    #if defined(CONFIG_UART_SUPPORT_DMA)
+                    uart_write_dma_config_t dma_cfg = {
+                        .src_width = UART_DMA_WIDTH,
+                        .dest_width = UART_DMA_WIDTH,
+                        .burst_length = UART_DMA_BURST_LENGTH,
+                        .priority = UART_DMA_PRIORITY
+                    };
+                    int32_t read_result = uapi_uart_read_by_dma(g_serial_ctx.uart_bus, current_buffer, 
+                        remaining,&dma_cfg);
+                        
+                    #else
+                    int32_t read_result = uapi_uart_read(g_serial_ctx.uart_bus, current_buffer, 
+                        remaining, batch_count == 0 ? 10 : 1);
+                    #endif
                     if (read_result > 0) {
                         total_read += (uint32_t)read_result;
                         g_serial_ctx.rx_bytes += (uint32_t)read_result;
@@ -589,7 +645,19 @@ ppp_error_t ppp_serial_tryread(uint8_t *buffer, uint32_t buffer_size, uint32_t *
 
     if (g_serial_ctx.current_mode == PPP_SERIAL_MODE_PPP_DATA) {
         /* PPP数据模式:使用1ms超时快速读取,类似SLIP的sio_tryread */
+
+        #if defined(CONFIG_UART_SUPPORT_DMA)
+        uart_write_dma_config_t dma_cfg = {
+            .src_width = UART_DMA_WIDTH,
+            .dest_width = UART_DMA_WIDTH,
+            .burst_length = UART_DMA_BURST_LENGTH,
+            .priority = UART_DMA_PRIORITY
+        };
+        int32_t read_result = uapi_uart_read_by_dma(g_serial_ctx.uart_bus, buffer, buffer_size,&dma_cfg);
+            
+        #else
         int32_t read_result = uapi_uart_read(g_serial_ctx.uart_bus, buffer, buffer_size, 0);
+        #endif
         if (read_result > 0) {
             *bytes_read = (uint32_t)read_result;
             g_serial_ctx.rx_bytes += *bytes_read;