优化ppp收发
author孙春阳 <snickersun@163.com>
Fri, 19 Sep 2025 10:27:35 +0000 (18:27 +0800)
committer孙春阳 <snickersun@163.com>
Fri, 19 Sep 2025 10:27:35 +0000 (18:27 +0800)
code/sdk/zhihui/ppp/src/ppp_lwip_thread.c
code/sdk/zhihui/ppp/src/ppp_serial.c

index 2007eda..1ebbe1a 100644 (file)
@@ -26,13 +26,16 @@ static volatile bool g_ppp_rx_thread_completed = false;
  * 2. 实现流数据处理和PPP帧重组
  * 3. 直接调用lwIP的输入函数
  */
+static uint32_t ppp_process_complete_frames(uint8_t *buffer, uint32_t *buffer_pos);
+
+/* 替换第29-215行的ppp_lwip_receive_thread函数 */
 static void ppp_lwip_receive_thread(void *arg)
 {
     (void)arg;
     
-    PPP_DEBUG_DEBUG("PPP lwIP receive thread started (slipif-style)");
+    PPP_DEBUG_DEBUG("PPP lwIP receive thread started (optimized frame detection)");
     
-    /* 动态分配接收缓冲区以避免栈溢出 */
+    /* 动态分配接收缓冲区 */
     uint8_t *rx_buffer = (uint8_t *)malloc(PPP_RX_BUFFER_SIZE);
     if (!rx_buffer) {
         PPP_DEBUG_ERROR("Failed to allocate RX buffer for PPP thread");
@@ -50,22 +53,16 @@ static void ppp_lwip_receive_thread(void *arg)
     uint32_t bytes_read;
     uint32_t total_packets = 0;
     uint32_t total_bytes = 0;
+    uint32_t complete_frames = 0;
     
     /* PPP流处理状态 */
     uint32_t stream_pos = 0;          /* 流缓冲区当前位置 */
-    bool in_frame = false;            /* 是否正在接收PPP帧 */
-    uint32_t frame_start = 0;         /* 当前帧开始位置 */
-    uint32_t complete_frames = 0;     /* 完整帧计数 */
-    
-    PPP_DEBUG_DEBUG("PPP lwIP thread: allocated %d bytes RX buffer + %d bytes stream buffer", 
-                   PPP_RX_BUFFER_SIZE, PPP_RX_BUFFER_SIZE * 2);
     
-    PPP_DEBUG_CRITICAL("PPP receive thread started and entering main loop");
-    PPP_DEBUG_DEBUG("Thread will read from serial in PPP data mode");
+    PPP_DEBUG_CRITICAL("PPP receive thread started with optimized frame detection");
     
-    /* 主接收循环 - 参考slipif的实现方式 */
+    /* 主接收循环 */
     while (g_ppp_rx_thread_running) {
-        // 从串口读取PPP数据 - 使用较短的超时时间提高响应性
+        // 从串口读取PPP数据
         ppp_error_t ret = ppp_serial_read(rx_buffer, PPP_RX_BUFFER_SIZE, &bytes_read);
         
         if (ret == PPP_ERR_OK && bytes_read > 0) {
@@ -75,107 +72,118 @@ static void ppp_lwip_receive_thread(void *arg)
             PPP_DEBUG_DEBUG("PPP RX: Got %u bytes (total: %u packets, %u bytes)", 
                           bytes_read, total_packets, total_bytes);
             
-            /* 将接收到的数据添加到流缓冲区 - 加强边界检查 */
-            if (stream_pos + bytes_read < PPP_RX_BUFFER_SIZE * 2) {
-                memcpy(stream_buffer + stream_pos, rx_buffer, bytes_read);
-                stream_pos += bytes_read;
-            } else {
-                PPP_DEBUG_WARN("PPP stream buffer overflow, resetting");
-                stream_pos = 0;
-                frame_start = 0;
-                in_frame = false;
-                continue;  // 跳过本次处理,避免缓冲区溢出
-            }
-            
-            /* 处理PPP帧 - 查找0x7E标志并添加边界检查 */
-            for (uint32_t i = frame_start; i < stream_pos && i < PPP_RX_BUFFER_SIZE * 2; i++) {
-                if (stream_buffer[i] == 0x7E) {
-                    if (in_frame && i > frame_start) {
-                        /* 找到帧结束,处理完整的PPP帧 */
-                        uint32_t frame_len = i - frame_start + 1;
-                        
-                        /* 添加帧长度合理性检查 */
-                        if (frame_len > 0 && frame_len <= 1500) {  // PPP最大帧长度
-                            PPP_DEBUG_DEBUG("PPP complete frame found: %u bytes", frame_len);
-                            
-                            /* 确保指针和长度有效 */
-                            if (frame_start + frame_len <= PPP_RX_BUFFER_SIZE * 2 && 
-                                frame_start < PPP_RX_BUFFER_SIZE * 2) {
-                                /* 将完整帧传递给lwIP - 让lwIP自己验证帧的有效性 */
-                                ppp_lwip_input(stream_buffer + frame_start, frame_len);
-                                complete_frames++;
-                            } else {
-                                PPP_DEBUG_WARN("PPP frame pointer out of bounds: start=%u, len=%u", 
-                                              frame_start, frame_len);
-                            }
-                        } else {
-                            PPP_DEBUG_WARN("Invalid PPP frame length: %u (frame_start=%u, i=%u)", 
-                                          frame_len, frame_start, i);
-                        }
-                    }
-                    
-                    /* 开始新帧 */
-                    frame_start = i;
-                    in_frame = true;
+            /* 检查缓冲区空间 */
+            if (stream_pos + bytes_read >= PPP_RX_BUFFER_SIZE * 2) {
+                PPP_DEBUG_WARN("PPP stream buffer full, processing existing frames first");
+                
+                /* 处理现有完整帧以释放空间 */
+                uint32_t processed = ppp_process_complete_frames(stream_buffer, &stream_pos);
+                PPP_DEBUG_INFO("Processed %u frames to free buffer space", processed);
+                
+                /* 如果还是不够空间,重置缓冲区 */
+                if (stream_pos + bytes_read >= PPP_RX_BUFFER_SIZE * 2) {
+                    PPP_DEBUG_WARN("Buffer still full after processing, resetting");
+                    stream_pos = 0;
                 }
             }
             
-            /* å¦\82æ\9e\9cç¼\93å\86²å\8cºä½¿ç\94¨è¶\85è¿\87ä¸\80å\8d\8aï¼\8cç§»å\8a¨æ\9cªå¤\84ç\90\86ç\9a\84æ\95°æ\8d®å\88°ç¼\93å\86²å\8cºå¼\80头 */
-            if (frame_start > PPP_RX_BUFFER_SIZE) {
-                uint32_t remaining = stream_pos - frame_start;
-                if (remaining > 0) {
-                    memmove(stream_buffer, stream_buffer + frame_start, remaining);
-                }
-                stream_pos = remaining;
-                frame_start = 0;
-                /* 保持in_frame状态,不要重置为false */
-                /* in_frame状态应该保持,因为我们可能正在处理一个跨缓冲区的帧 */
+            /* å°\86æ\96°æ\95°æ\8d®è¿½å\8a å\88°æµ\81ç¼\93å\86²å\8cº */
+            memcpy(stream_buffer + stream_pos, rx_buffer, bytes_read);
+            stream_pos += bytes_read;
+            
+            /* 立即处理所有完整的PPP帧 */
+            uint32_t processed_frames = ppp_process_complete_frames(stream_buffer, &stream_pos);
+            complete_frames += processed_frames;
+            
+            if (processed_frames > 0) {
+                PPP_DEBUG_DEBUG("Processed %u complete PPP frames", processed_frames);
             }
+            
         } else if (ret != PPP_ERR_OK) {
-            /* 检查是否是因为线程停止导致的错误 */
             if (!g_ppp_rx_thread_running) {
                 PPP_DEBUG_DEBUG("PPP thread stopping, ignoring read error");
                 break;
             }
             PPP_DEBUG_ERROR("PPP serial read error: %d", ret);
         } else {
-            /* ret == PPP_ERR_OK but bytes_read == 0 - no data available */
-            static uint32_t no_data_count = 0;
-            no_data_count++;
-            
-            /* 减少无数据时的日志输出频率,避免日志开销 */
-            if (no_data_count % 5000 == 0) {  /* 每5000次无数据时打印一次 */
-                PPP_DEBUG_DEBUG("PPP RX: No data available (count: %u)", no_data_count);
-            }
-            
-            /* 适应性休眠策略,避免过度占用CPU */
-            if (no_data_count % 5 == 0) {  /* 每5次无数据后短暂休眠 */
-                osal_msleep(2);  /* 2ms休眠,让出CPU给tcpip_thread */
-            }
+            /* 无数据可读,短暂休眠 */
+            osal_msleep(5);
         }
         
-        // 统计信息输出 - 每5000次循环输出一次,减少日志开销
-        if ((total_packets % 5000) == 0 && total_packets > 0) {
-            PPP_DEBUG_DEBUG("PPP lwIP RX: %u fragments, %u complete frames, %u total bytes", 
+        /* 统计信息输出 */
+        if ((total_packets % 1000) == 0 && total_packets > 0) {
+            PPP_DEBUG_DEBUG("PPP RX Stats: %u packets, %u frames, %u total bytes", 
                           total_packets, complete_frames, total_bytes);
         }
-        
-        // 适应性休眠以避免CPU占用过高,给tcpip_thread更多时间
-        if (complete_frames > 0) {
-            osal_msleep(5);  /* 有数据时短休眠 */
-        } else {
-            osal_msleep(15); /* 无数据时长休眠 */
-        }
     }
     
-    /* 清理资源 */
+    PPP_DEBUG_INFO("PPP receive thread exiting. Stats: %u packets, %u frames, %u bytes",
+                  total_packets, complete_frames, total_bytes);
+    
     free(rx_buffer);
     free(stream_buffer);
-    
-    PPP_DEBUG_INFO("PPP lwIP receive thread completed");
     g_ppp_rx_thread_completed = true;
+}
+
+/**
+ * @brief 处理缓冲区中的所有完整PPP帧
+ * @param buffer 数据缓冲区
+ * @param buffer_pos 缓冲区当前位置指针(会被更新)
+ * @return 处理的帧数量
+ */
+static uint32_t ppp_process_complete_frames(uint8_t *buffer, uint32_t *buffer_pos)
+{
+    uint32_t processed_frames = 0;
+    uint32_t scan_pos = 0;
+    uint32_t frame_start = 0;
+    bool in_frame = false;
+    uint32_t new_buffer_pos = 0;
+    
+    /* 扫描整个缓冲区查找完整的PPP帧 */
+    while (scan_pos < *buffer_pos) {
+        if (buffer[scan_pos] == 0x7E) {  /* PPP帧标志 */
+            if (in_frame) {
+                /* 帧结束 - 处理完整帧 */
+                uint32_t frame_len = scan_pos - frame_start + 1;
+                
+                /* PPP帧长度检查:最小2字节(两个0x7E),最大1500字节 */
+                if (frame_len >= 2 && frame_len <= 1500) {
+                    PPP_DEBUG_DEBUG("Complete PPP frame: %u bytes (start=%u, end=%u)", 
+                                  frame_len, frame_start, scan_pos);
+                    
+                    /* 发送给lwIP处理 - 包括空帧(只有头尾0x7E的帧)*/
+                    ppp_lwip_input(buffer + frame_start, frame_len);
+                    processed_frames++;
+                    
+                    /* 更新缓冲区位置到已处理帧之后 */
+                    new_buffer_pos = scan_pos + 1;
+                } else {
+                    PPP_DEBUG_WARN("Invalid PPP frame length: %u bytes, skipping", frame_len);
+                }
+                
+                in_frame = false;
+            } else {
+                /* 帧开始 */
+                frame_start = scan_pos;
+                in_frame = true;
+            }
+        }
+        scan_pos++;
+    }
+    
+    /* 移动未处理的数据到缓冲区开头 */
+    if (new_buffer_pos > 0 && new_buffer_pos < *buffer_pos) {
+        uint32_t remaining = *buffer_pos - new_buffer_pos;
+        memmove(buffer, buffer + new_buffer_pos, remaining);
+        *buffer_pos = remaining;
+        
+        PPP_DEBUG_DEBUG("Moved %u unprocessed bytes to buffer start", remaining);
+    } else if (new_buffer_pos >= *buffer_pos) {
+        /* 所有数据都已处理 */
+        *buffer_pos = 0;
+    }
     
-    PPP_DEBUG_INFO("PPP lwIP receive thread exiting");
+    return processed_frames;
 }
 
 /**
index 61123c9..034a404 100644 (file)
@@ -13,8 +13,8 @@
 #include "arch_port.h"
 
 /* PPP性能优化配置 */
-#define PPP_OPTIMIZED_UART_WRITE_TIMEOUT    200    /* UART写超时优化: 1000ms -> 200ms */
-#define PPP_OPTIMIZED_UART_READ_TIMEOUT     100    /* UART读超时优化: 200ms -> 100ms */
+#define PPP_OPTIMIZED_UART_WRITE_TIMEOUT    500    /* UART写超时优化: 1000ms -> 200ms */
+#define PPP_OPTIMIZED_UART_READ_TIMEOUT     300    /* UART读超时优化: 200ms -> 100ms */
 
 /* 串口上下文结构 - 优化缓存机制 */
 typedef struct {
@@ -363,8 +363,8 @@ ppp_error_t ppp_serial_write(const uint8_t *data, uint32_t length)
     PPP_DEBUG_DEBUG("=== PPP Serial Write Start ===");
     #ifdef PPP_LOW_POWER_MODE
     ppp_api_wakeup_cat1(true);
-    #endif
     osal_msleep(1);
+    #endif
     PPP_DEBUG_DEBUG("Write request: %u bytes in mode %d", length, g_serial_ctx.current_mode);
     PPP_DEBUG_DEBUG("UART Bus: %u", g_serial_ctx.uart_bus);
 
@@ -443,7 +443,24 @@ ppp_error_t ppp_serial_write(const uint8_t *data, uint32_t length)
 
     return result;
 }
-
+// 根据数据类型动态调整超时
+#define PPP_UART_READ_TIMEOUT_NORMAL    300    // 正常情况300ms
+#define PPP_UART_READ_TIMEOUT_BURST     500    // 连续数据时500ms
+
+// 在ppp_serial.c中实现自适应超时
+static uint32_t get_adaptive_read_timeout(void) {
+    static uint32_t consecutive_reads = 0;
+    static uint32_t last_read_time = 0;
+    uint32_t current_time = osal_get_jiffies();
+    
+    if (current_time - last_read_time < 100) {  // 100ms内的连续读取
+        consecutive_reads++;
+        return PPP_UART_READ_TIMEOUT_BURST;  // 使用更长超时
+    } else {
+        consecutive_reads = 0;
+        return PPP_UART_READ_TIMEOUT_NORMAL;
+    }
+}
 /**
  * @brief 读取数据 - AT模式直接从UART读取,PPP模式从软件缓冲区读取
  */
@@ -460,7 +477,9 @@ ppp_error_t ppp_serial_read(uint8_t *buffer, uint32_t buffer_size, uint32_t *byt
         case PPP_SERIAL_MODE_AT:
         /* AT命令模式:直接从UART读取 */
             {
-                int32_t read_result = uapi_uart_read(g_serial_ctx.uart_bus, buffer, buffer_size, 100);
+                int32_t timeout = get_adaptive_read_timeout();
+                PPP_DEBUG_DEBUG("AT mode: Attempting UART read (timeout: %dms)", timeout);
+                int32_t read_result = uapi_uart_read(g_serial_ctx.uart_bus, buffer, buffer_size, timeout);
                 if (read_result > 0) {
                     *bytes_read = (uint32_t)read_result;
                     g_serial_ctx.rx_bytes += *bytes_read;
@@ -479,7 +498,9 @@ ppp_error_t ppp_serial_read(uint8_t *buffer, uint32_t buffer_size, uint32_t *byt
                 /* 使用适中的超时时间来平衡响应性和帧完整性 */
                 // PPP_DEBUG_DEBUG("PPP mode: Attempting UART read (timeout: 200ms)");
                 /* 优化PPP数据模式读取超时:使用配置的优化值以提高协商响应速度 */
-                int32_t read_result = uapi_uart_read(g_serial_ctx.uart_bus, buffer, buffer_size, PPP_OPTIMIZED_UART_READ_TIMEOUT);
+                int32_t timeout = get_adaptive_read_timeout();
+                PPP_DEBUG_DEBUG("PPP mode: Attempting UART read (timeout: %dms)", timeout);
+                int32_t read_result = uapi_uart_read(g_serial_ctx.uart_bus, buffer, buffer_size, timeout);
                 if (read_result > 0) {
                     *bytes_read = (uint32_t)read_result;
                     g_serial_ctx.rx_bytes += *bytes_read;