* 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");
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) {
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;
}
/**
#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 {
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);
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模式从软件缓冲区读取
*/
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;
/* 使用适中的超时时间来平衡响应性和帧完整性 */
// 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;