From: 孙春阳 Date: Fri, 19 Sep 2025 10:27:35 +0000 (+0800) Subject: 优化ppp收发 X-Git-Tag: leiniao_debug_1.0.0_20250922_020716~13^2~11^2~1 X-Git-Url: http://git.snicker.com.cn/css/static/gitweb.css?a=commitdiff_plain;h=80ddd72e793797683275d349cf53c438ff8998e8;p=mirrors%2FFD230.git 优化ppp收发 --- diff --git a/code/sdk/zhihui/ppp/src/ppp_lwip_thread.c b/code/sdk/zhihui/ppp/src/ppp_lwip_thread.c index 2007edab8..1ebbe1a44 100644 --- a/code/sdk/zhihui/ppp/src/ppp_lwip_thread.c +++ b/code/sdk/zhihui/ppp/src/ppp_lwip_thread.c @@ -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; } } - /* 如果缓冲区使用超过一半,移动未处理的数据到缓冲区开头 */ - 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状态应该保持,因为我们可能正在处理一个跨缓冲区的帧 */ + /* 将新数据追加到流缓冲区 */ + 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; } /** diff --git a/code/sdk/zhihui/ppp/src/ppp_serial.c b/code/sdk/zhihui/ppp/src/ppp_serial.c index 61123c92d..034a4045e 100644 --- a/code/sdk/zhihui/ppp/src/ppp_serial.c +++ b/code/sdk/zhihui/ppp/src/ppp_serial.c @@ -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;