/**
* @file ppp_lwip_thread.c
- * @brief PPPæ\8e¥æ\94¶çº¿ç¨\8bå®\9eç\8e° - å\8f\82è\80\83lwIP slipif_initæ\96¹å¼\8f
+ * @brief PPPæ\8e¥æ\94¶çº¿ç¨\8bå®\9eç\8e° - å\8f\8c线ç¨\8bæ\9e¶æ\9e\84ï¼\9aæ\8e¥æ\94¶çº¿ç¨\8bæ\8b¼å\8c\85 + å¤\84ç\90\86线ç¨\8bå¤\84ç\90\86
*/
#include "ppp_api.h"
#include "ppp_lwip.h"
#include "soc_osal.h"
#include "schedule/osal_task.h"
+#include "msgqueue/osal_msgqueue.h"
#include <stdlib.h>
#include <string.h>
-/* PPP接收线程相关 - 参考slipif_init方式 */
-static osal_task *g_ppp_rx_thread = NULL;
+/* PPP帧队列相关 */
+#define PPP_FRAME_QUEUE_SIZE 32 // 队列大小
+#define PPP_MAX_FRAME_SIZE 1500 // PPP最大帧大小
+
+/* PPP帧结构 */
+typedef struct {
+ uint8_t *data; // 帧数据
+ uint32_t length; // 帧长度
+} ppp_frame_t;
+
+/* PPP字节丢弃统计结构已在ppp_types.h中定义 */
+
+/* PPP线程相关 */
+static osal_task *g_ppp_rx_thread = NULL; // 接收线程
+static osal_task *g_ppp_process_thread = NULL; // 处理线程
static volatile bool g_ppp_rx_thread_running = false;
+static volatile bool g_ppp_process_thread_running = false;
static volatile bool g_ppp_rx_thread_completed = false;
+static volatile bool g_ppp_process_thread_completed = false;
+
+/* PPP帧队列 */
+static unsigned long g_ppp_frame_queue = 0xFFFFFFFFu;
+
+/* PPP接收缓冲区 */
+static uint8_t g_ppp_rx_buffer[PPP_RX_BUFFER_SIZE * 2]; // 双倍缓冲区用于拼包
+static uint32_t g_buffer_pos = 0; // 当前缓冲区位置
+
+/* PPP帧标志 */
+#define PPP_FLAG_CHAR 0x7E // PPP帧标志字符
+#define PPP_ESCAPE_CHAR 0x7D // PPP转义字符
+#define PPP_ESCAPE_MASK 0x20 // PPP转义掩码
+
+/* PPP丢弃统计 */
+static ppp_discard_stats_t g_ppp_discard_stats = {0};
+
+/* PPP帧拼包状态 */
+typedef struct {
+ uint8_t *buffer; // 拼包缓冲区
+ uint32_t buffer_size; // 缓冲区大小
+ uint32_t data_len; // 当前数据长度
+ bool in_frame; // 是否在帧内
+ bool escaped; // 是否转义状态
+} ppp_frame_assembler_t;
+
+static ppp_frame_assembler_t g_frame_assembler = {0};
/**
- * @brief PPP数据接收线程 - 参考slipif_init实现
- *
- * 这个实现参考了lwIP中slipif_init的线程创建方式:
- * 1. 使用标准的线程函数签名
- * 2. 实现流数据处理和PPP帧重组
- * 3. 直接调用lwIP的输入函数
+ * @brief 初始化PPP帧拼包器
*/
-static void ppp_lwip_receive_thread(void *arg)
+static ppp_error_t ppp_frame_assembler_init(void)
{
- (void)arg;
+ g_frame_assembler.buffer_size = PPP_MAX_FRAME_SIZE;
+ g_frame_assembler.buffer = (uint8_t *)malloc(g_frame_assembler.buffer_size);
+ if (!g_frame_assembler.buffer) {
+ PPP_DEBUG_ERROR("Failed to allocate frame assembler buffer");
+ return PPP_ERR_MEMORY;
+ }
- PPP_DEBUG_DEBUG("PPP lwIP receive thread started (slipif-style)");
+ g_frame_assembler.data_len = 0;
+ g_frame_assembler.in_frame = false;
+ g_frame_assembler.escaped = false;
- /* 动态分配接收缓冲区以避免栈溢出 */
- 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");
- return;
+ PPP_DEBUG_INFO("PPP frame assembler initialized with %u bytes buffer",
+ g_frame_assembler.buffer_size);
+ return PPP_ERR_OK;
+}
+
+/**
+ * @brief 清理PPP帧拼包器
+ */
+static void ppp_frame_assembler_cleanup(void)
+{
+ if (g_frame_assembler.buffer) {
+ free(g_frame_assembler.buffer);
+ g_frame_assembler.buffer = NULL;
+ }
+ memset(&g_frame_assembler, 0, sizeof(g_frame_assembler));
+}
+
+/**
+ * @brief 重置帧拼包状态
+ */
+static void ppp_frame_assembler_reset(void)
+{
+ g_frame_assembler.data_len = 0;
+ g_frame_assembler.in_frame = false;
+ g_frame_assembler.escaped = false;
+}
+
+/**
+ * @brief 发送完整PPP帧到队列
+ */
+static ppp_error_t ppp_send_frame_to_queue(const uint8_t *data, uint32_t length)
+{
+ if (!data || length == 0 || length > PPP_MAX_FRAME_SIZE) {
+ return PPP_ERR_INVALID_PARAM;
}
- /* 动态分配PPP流处理缓冲区 */
- uint8_t *stream_buffer = (uint8_t *)malloc(PPP_RX_BUFFER_SIZE * 2);
- if (!stream_buffer) {
- PPP_DEBUG_ERROR("Failed to allocate stream buffer for PPP thread");
- free(rx_buffer);
- return;
+ // 分配帧结构
+ ppp_frame_t *frame = (ppp_frame_t *)malloc(sizeof(ppp_frame_t));
+ if (!frame) {
+ PPP_DEBUG_ERROR("Failed to allocate frame structure");
+
+ // 统计内存分配失败丢弃
+ g_ppp_discard_stats.total_frames_discarded++;
+ g_ppp_discard_stats.malloc_fail_bytes += length;
+ g_ppp_discard_stats.total_bytes_discarded += length;
+
+ return PPP_ERR_MEMORY;
}
- uint32_t bytes_read;
- uint32_t total_packets = 0;
- uint32_t total_bytes = 0;
+ // 分配帧数据
+ frame->data = (uint8_t *)malloc(length);
+ if (!frame->data) {
+ PPP_DEBUG_ERROR("Failed to allocate frame data");
+
+ // 统计内存分配失败丢弃
+ g_ppp_discard_stats.total_frames_discarded++;
+ g_ppp_discard_stats.malloc_fail_bytes += length;
+ g_ppp_discard_stats.total_bytes_discarded += length;
+
+ free(frame);
+ return PPP_ERR_MEMORY;
+ }
- /* PPP流处理状态 */
- uint32_t stream_pos = 0; /* 流缓冲区当前位置 */
- bool in_frame = false; /* 是否正在接收PPP帧 */
- uint32_t frame_start = 0; /* 当前帧开始位置 */
- uint32_t complete_frames = 0; /* 完整帧计数 */
+ // 复制数据
+ memcpy(frame->data, data, length);
+ frame->length = length;
- PPP_DEBUG_DEBUG("PPP lwIP thread: allocated %d bytes RX buffer + %d bytes stream buffer",
- PPP_RX_BUFFER_SIZE, PPP_RX_BUFFER_SIZE * 2);
+ // 发送到队列
+ int ret = osal_msg_queue_write_copy(g_ppp_frame_queue, &frame, sizeof(ppp_frame_t *), 0);
+ if (ret != OSAL_SUCCESS) {
+ PPP_DEBUG_WARN("Failed to send frame to queue: %d, dropping frame", ret);
+
+ // 统计队列满丢弃
+ g_ppp_discard_stats.total_frames_discarded++;
+ g_ppp_discard_stats.queue_full_bytes += length;
+ g_ppp_discard_stats.total_bytes_discarded += length;
+
+ free(frame->data);
+ free(frame);
+ return PPP_ERR_UNKNOWN; // 使用已定义的错误码
+ }
- 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_DEBUG("Sent complete PPP frame to queue: %u bytes", length);
- /* 主接收循环 - 参考slipif的实现方式 */
+ // 更新帧统计
+ g_ppp_discard_stats.total_frames_received++;
+
+ return PPP_ERR_OK;
+}
+
+/**
+ * @brief 处理接收到的字节,进行PPP帧拼包(保留完整帧格式)
+ */
+static ppp_error_t ppp_process_received_byte(uint8_t byte)
+{
+ // PPP帧标志字符
+ if (byte == 0x7E) {
+ if (g_frame_assembler.in_frame && g_frame_assembler.data_len > 0) {
+ // 帧结束,添加结束标志并发送完整帧
+ if (g_frame_assembler.data_len < g_frame_assembler.buffer_size) {
+ g_frame_assembler.buffer[g_frame_assembler.data_len++] = 0x7E;
+
+ PPP_DEBUG_DEBUG("Complete PPP frame assembled: %u bytes (with 0x7E flags)", g_frame_assembler.data_len);
+
+ // 发送完整帧(包含首尾0x7E标志)
+ ppp_send_frame_to_queue(g_frame_assembler.buffer, g_frame_assembler.data_len);
+ } else {
+ // 缓冲区满,丢弃帧
+ PPP_DEBUG_WARN("Frame buffer full, dropping frame");
+ g_ppp_discard_stats.total_frames_discarded++;
+ g_ppp_discard_stats.oversized_frame_bytes += g_frame_assembler.data_len;
+ g_ppp_discard_stats.total_bytes_discarded += g_frame_assembler.data_len;
+ }
+ } else if (g_frame_assembler.in_frame && g_frame_assembler.data_len == 0) {
+ // 连续的0x7E标志,这是正常的
+ PPP_DEBUG_DEBUG("Consecutive 0x7E flag, continuing");
+ } else {
+ // 不在帧内收到0x7E,开始新帧
+ PPP_DEBUG_DEBUG("Starting new frame with 0x7E");
+ }
+
+ // 开始新帧,首先添加起始0x7E标志
+ ppp_frame_assembler_reset();
+ g_frame_assembler.in_frame = true;
+ g_frame_assembler.buffer[g_frame_assembler.data_len++] = 0x7E;
+ return PPP_ERR_OK;
+ }
+
+ // 如果不在帧内,忽略数据
+ if (!g_frame_assembler.in_frame) {
+ // 统计被忽略的数据
+ g_ppp_discard_stats.total_bytes_discarded++;
+ g_ppp_discard_stats.incomplete_frame_bytes++;
+ PPP_DEBUG_DEBUG("Ignoring byte 0x%02X outside frame", byte);
+ return PPP_ERR_OK;
+ }
+
+ // 检查缓冲区空间(为结束0x7E预留1字节)
+ if (g_frame_assembler.data_len >= (g_frame_assembler.buffer_size - 1)) {
+ PPP_DEBUG_WARN("Frame too large (%u bytes), resetting assembler", g_frame_assembler.data_len);
+
+ // 统计超大帧丢弃
+ g_ppp_discard_stats.total_frames_discarded++;
+ g_ppp_discard_stats.oversized_frame_bytes += g_frame_assembler.data_len;
+ g_ppp_discard_stats.total_bytes_discarded += g_frame_assembler.data_len;
+
+ ppp_frame_assembler_reset();
+ return PPP_ERR_UNKNOWN;
+ }
+
+ // 直接添加字节到帧缓冲区(保留原始格式,包括转义字符)
+ g_frame_assembler.buffer[g_frame_assembler.data_len++] = byte;
+
+ return PPP_ERR_OK;
+}
+
+/**
+ * @brief PPP数据接收线程 - 只负责拼包
+ */
+static void ppp_lwip_receive_thread(void *arg)
+{
+ (void)arg;
+
+ PPP_DEBUG_INFO("PPP receive thread started (frame assembly mode)");
+
+ // 分配串口接收缓冲区
+ uint8_t *rx_buffer = (uint8_t *)malloc(PPP_RX_BUFFER_SIZE);
+ if (!rx_buffer) {
+ PPP_DEBUG_ERROR("PPP RX buffer alloc failed");
+ g_ppp_rx_thread_completed = true;
+ return;
+ }
+
+ uint32_t bytes_read = 0;
+ uint32_t total_bytes = 0, total_frames = 0;
+
+ PPP_DEBUG_DEBUG("PPP receive thread: allocated %d bytes RX buffer", PPP_RX_BUFFER_SIZE);
+
+ // 主循环:从串口读取数据并拼包
while (g_ppp_rx_thread_running) {
- // 从串口读取PPP数据 - 使用较短的超时时间提高响应性
+ // 从串口读取数据
ppp_error_t ret = ppp_serial_read(rx_buffer, PPP_RX_BUFFER_SIZE, &bytes_read);
-
+
if (ret == PPP_ERR_OK && bytes_read > 0) {
- total_packets++;
total_bytes += bytes_read;
- 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 (frame_start > PPP_RX_BUFFER_SIZE) {
- uint32_t remaining = stream_pos - frame_start;
- if (remaining > 0) {
- memmove(stream_buffer, stream_buffer + frame_start, remaining);
+ // 更新接收字节统计
+ g_ppp_discard_stats.total_bytes_received += bytes_read;
+
+ PPP_DEBUG_DEBUG("PPP RX: Got %u bytes (total: %u bytes)", bytes_read, total_bytes);
+
+ // 逐字节处理,进行PPP帧拼包(保留完整帧格式)
+ for (uint32_t i = 0; i < bytes_read; i++) {
+ ppp_error_t process_ret = ppp_process_received_byte(rx_buffer[i]);
+ if (process_ret != PPP_ERR_OK) {
+ // 字节处理失败,统计丢弃
+ g_ppp_discard_stats.total_bytes_discarded++;
+ g_ppp_discard_stats.invalid_frame_bytes++;
}
- stream_pos = remaining;
- frame_start = 0;
- /* 保持in_frame状态,不要重置为false */
- /* in_frame状态应该保持,因为我们可能正在处理一个跨缓冲区的帧 */
}
} else if (ret != PPP_ERR_OK) {
- /* 检查是否是因为线程停止导致的错误 */
+ // 读取错误
if (!g_ppp_rx_thread_running) {
- PPP_DEBUG_DEBUG("PPP thread stopping, ignoring read error");
+ PPP_DEBUG_DEBUG("PPP receive 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++;
+ // 没有数据,短暂休眠
+ osal_msleep(1);
+ }
+
+ // 定期打印统计信息
+ if ((total_frames % 100) == 0 && total_frames > 0) {
+ PPP_DEBUG_DEBUG("PPP RX: %u frames assembled, %u total bytes",
+ total_frames, total_bytes);
+ }
+ }
+
+ // 释放缓冲区
+ free(rx_buffer);
+
+ PPP_DEBUG_INFO("PPP receive thread completed");
+ g_ppp_rx_thread_completed = true;
+}
+
+/**
+ * @brief PPP帧处理线程 - 从队列获取完整帧并处理
+ */
+static void ppp_lwip_process_thread(void *arg)
+{
+ (void)arg;
+
+ PPP_DEBUG_INFO("PPP process thread started");
+
+ uint32_t processed_frames = 0;
+ uint32_t processed_bytes = 0;
+
+ // 主循环:从队列获取完整PPP帧并处理
+ while (g_ppp_process_thread_running) {
+ ppp_frame_t *frame = NULL;
+ uint32_t msg_size = sizeof(ppp_frame_t *);
+
+ // 从队列获取帧(超时100ms)
+ int ret = osal_msg_queue_read_copy(g_ppp_frame_queue, &frame, &msg_size, OSAL_MSGQ_WAIT_FOREVER);
+
+ if (ret == OSAL_SUCCESS && frame) {
+ // 处理完整PPP帧
+ PPP_DEBUG_DEBUG("Processing PPP frame: %u bytes", frame->length);
- /* 减少无数据时的日志输出频率,避免日志开销 */
- if (no_data_count % 5000 == 0) { /* 每5000次无数据时打印一次 */
- PPP_DEBUG_DEBUG("PPP RX: No data available (count: %u)", no_data_count);
- }
+ // 调用lwIP处理
+ ppp_lwip_input(frame->data, frame->length);
+
+ // 更新统计
+ processed_frames++;
+ processed_bytes += frame->length;
+
+ // 更新处理统计
+ g_ppp_discard_stats.total_frames_processed++;
+ g_ppp_discard_stats.total_bytes_processed += frame->length;
- /* 适应性休眠策略,避免过度占用CPU */
- if (no_data_count % 5 == 0) { /* 每5次无数据后短暂休眠 */
- osal_msleep(2); /* 2ms休眠,让出CPU给tcpip_thread */
+ // 释放帧内存
+ free(frame->data);
+ free(frame);
+
+ // 定期打印统计
+ if ((processed_frames % 50) == 0) {
+ PPP_DEBUG_DEBUG("PPP Process: %u frames, %u bytes processed",
+ processed_frames, processed_bytes);
+ }
+ } else if (ret != OSAL_SUCCESS) {
+ // 超时或其他错误
+ if (!g_ppp_process_thread_running) {
+ PPP_DEBUG_DEBUG("PPP process thread stopping");
+ break;
+ }
+ // 超时是正常的,其他错误才需要警告
+ if (ret != 0) { // 假设超时返回非0值
+ PPP_DEBUG_WARN("Failed to read from frame queue: %d", ret);
}
}
-
- // 统计信息输出 - 每5000次循环输出一次,减少日志开销
- if ((total_packets % 5000) == 0 && total_packets > 0) {
- PPP_DEBUG_DEBUG("PPP lwIP RX: %u fragments, %u complete 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_frame_t *frame = NULL;
+ uint32_t msg_size = sizeof(ppp_frame_t *);
+ while (osal_msg_queue_read_copy(g_ppp_frame_queue, &frame, &msg_size, 0) == OSAL_SUCCESS) {
+ if (frame) {
+ free(frame->data);
+ free(frame);
}
}
-
- /* 清理资源 */
- free(rx_buffer);
- free(stream_buffer);
-
- PPP_DEBUG_INFO("PPP lwIP receive thread completed");
- g_ppp_rx_thread_completed = true;
-
- PPP_DEBUG_INFO("PPP lwIP receive thread exiting");
+
+ PPP_DEBUG_INFO("PPP process thread completed, processed %u frames, %u bytes",
+ processed_frames, processed_bytes);
+ g_ppp_process_thread_completed = true;
}
/**
- * @brief 启动PPP接收线程 - 参考slipif_init方式
+ * @brief 启动PPP接收和处理线程
*/
ppp_error_t ppp_lwip_start_receive_thread(void)
{
- if (g_ppp_rx_thread != NULL) {
- PPP_DEBUG_WARN("PPP lwIP receive thread already running");
+ if (g_ppp_rx_thread != NULL || g_ppp_process_thread != NULL) {
+ PPP_DEBUG_WARN("PPP threads already running");
return PPP_ERR_INVALID_STATE;
}
- PPP_DEBUG_INFO("Starting PPP lwIP receive thread");
+ PPP_DEBUG_INFO("Starting PPP receive and process threads");
+
+ // 初始化帧拼包器
+ ppp_error_t ret = ppp_frame_assembler_init();
+ if (ret != PPP_ERR_OK) {
+ PPP_DEBUG_ERROR("Failed to initialize frame assembler");
+ return ret;
+ }
+
+ // 创建帧队列
+ int queue_ret = osal_msg_queue_create("ppp_frames", PPP_FRAME_QUEUE_SIZE,
+ &g_ppp_frame_queue, 0, sizeof(ppp_frame_t *));
+ if (queue_ret != OSAL_SUCCESS) {
+ PPP_DEBUG_ERROR("Failed to create PPP frame queue: %d", queue_ret);
+ ppp_frame_assembler_cleanup();
+ return PPP_ERR_MEMORY;
+ }
- // 重置线程完成标志
+ // 重置完成标志
g_ppp_rx_thread_completed = false;
+ g_ppp_process_thread_completed = false;
- // 设置线程运行标志为true(在创建线程之前)
- g_ppp_rx_thread_running = true;
+ // 启动处理线程
+ g_ppp_process_thread_running = true;
+ g_ppp_process_thread = osal_kthread_create((osal_kthread_handler)ppp_lwip_process_thread,
+ NULL, "ppp_process", 4096);
+ if (!g_ppp_process_thread) {
+ PPP_DEBUG_ERROR("Failed to create PPP process thread");
+ g_ppp_process_thread_running = false;
+ osal_msg_queue_delete(g_ppp_frame_queue);
+ g_ppp_frame_queue = 0;
+ ppp_frame_assembler_cleanup();
+ return PPP_ERR_MEMORY;
+ }
- // 创建线程 - 使用正确的OSAL API
+ // 启动接收线程
+ g_ppp_rx_thread_running = true;
g_ppp_rx_thread = osal_kthread_create((osal_kthread_handler)ppp_lwip_receive_thread,
- NULL, "ppp_lwip_rx", 4096);
- if (g_ppp_rx_thread == NULL) {
- PPP_DEBUG_ERROR("Failed to create PPP lwIP receive thread");
- g_ppp_rx_thread_running = false; // 创建失败时重置标志
+ NULL, "ppp_receive", 4096);
+ if (!g_ppp_rx_thread) {
+ PPP_DEBUG_ERROR("Failed to create PPP receive thread");
+ g_ppp_rx_thread_running = false;
+
+ // 清理处理线程
+ g_ppp_process_thread_running = false;
+ osal_kthread_destroy(g_ppp_process_thread, 0);
+ g_ppp_process_thread = NULL;
+
+ // 清理资源
+ osal_msg_queue_delete(g_ppp_frame_queue);
+ g_ppp_frame_queue = 0;
+ ppp_frame_assembler_cleanup();
return PPP_ERR_MEMORY;
}
- PPP_DEBUG_INFO("PPP lwIP receive thread started successfully");
+ PPP_DEBUG_INFO("PPP receive and process threads started successfully");
return PPP_ERR_OK;
}
/**
- * @brief 停止PPP接收线程
+ * @brief 停止PPP接收和处理线程
*/
ppp_error_t ppp_lwip_stop_receive_thread(void)
{
- if (g_ppp_rx_thread == NULL) {
+ if (!g_ppp_rx_thread && !g_ppp_process_thread) {
return PPP_ERR_OK;
}
- PPP_DEBUG_INFO("Stopping PPP lwIP receive thread");
-
- // 停止线程
- g_ppp_rx_thread_running = false;
+ PPP_DEBUG_INFO("Stopping PPP receive and process threads");
- // 等待线程完成,使用completion flag进行同步
- int wait_count = 0;
- const int max_wait = 100; // 最多等待1秒
+ // 停止接收线程
+ if (g_ppp_rx_thread) {
+ g_ppp_rx_thread_running = false;
+
+ // 等待接收线程完成
+ int wait_count = 0;
+ const int max_wait = 100;
+
+ while (wait_count < max_wait && !g_ppp_rx_thread_completed) {
+ osal_msleep(10);
+ wait_count++;
+ }
+
+ if (g_ppp_rx_thread_completed) {
+ PPP_DEBUG_DEBUG("PPP receive thread completed gracefully");
+ } else {
+ PPP_DEBUG_WARN("PPP receive thread did not complete within timeout");
+ }
+
+ osal_kthread_destroy(g_ppp_rx_thread, 0);
+ g_ppp_rx_thread = NULL;
+ }
- while (wait_count < max_wait && !g_ppp_rx_thread_completed) {
- osal_msleep(10);
- wait_count++;
+ // 停止处理线程
+ if (g_ppp_process_thread) {
+ g_ppp_process_thread_running = false;
+
+ // 等待处理线程完成
+ int wait_count = 0;
+ const int max_wait = 100;
+
+ while (wait_count < max_wait && !g_ppp_process_thread_completed) {
+ osal_msleep(10);
+ wait_count++;
+ }
+
+ if (g_ppp_process_thread_completed) {
+ PPP_DEBUG_DEBUG("PPP process thread completed gracefully");
+ } else {
+ PPP_DEBUG_WARN("PPP process thread did not complete within timeout");
+ }
+
+ osal_kthread_destroy(g_ppp_process_thread, 0);
+ g_ppp_process_thread = NULL;
}
- if (g_ppp_rx_thread_completed) {
- PPP_DEBUG_DEBUG("PPP thread completed gracefully after %d ms", wait_count * 10);
- } else {
- PPP_DEBUG_WARN("PPP thread did not complete within timeout, forcing termination");
+ // 清理队列
+ if (g_ppp_frame_queue != 0) {
+ osal_msg_queue_delete(g_ppp_frame_queue);
+ g_ppp_frame_queue = 0;
}
- // 销毁线程
- osal_kthread_destroy(g_ppp_rx_thread, 0);
- g_ppp_rx_thread = NULL;
+ // 清理帧拼包器
+ ppp_frame_assembler_cleanup();
// 重置状态标志
g_ppp_rx_thread_running = false;
+ g_ppp_process_thread_running = false;
g_ppp_rx_thread_completed = false;
+ g_ppp_process_thread_completed = false;
- PPP_DEBUG_INFO("PPP lwIP receive thread stopped");
+ PPP_DEBUG_INFO("PPP receive and process threads stopped");
return PPP_ERR_OK;
}
*/
bool ppp_lwip_is_receive_thread_running(void)
{
- return g_ppp_rx_thread_running && (g_ppp_rx_thread != NULL);
+ return g_ppp_rx_thread_running && (g_ppp_rx_thread != NULL) &&
+ g_ppp_process_thread_running && (g_ppp_process_thread != NULL);
+}
+
+/**
+ * @brief 获取PPP字节丢弃统计信息
+ */
+void ppp_lwip_get_discard_stats(ppp_discard_stats_t *stats)
+{
+ if (stats) {
+ memcpy(stats, &g_ppp_discard_stats, sizeof(ppp_discard_stats_t));
+ }
+}
+
+/**
+ * @brief 重置PPP字节丢弃统计信息
+ */
+void ppp_lwip_reset_discard_stats(void)
+{
+ memset(&g_ppp_discard_stats, 0, sizeof(ppp_discard_stats_t));
+ PPP_DEBUG_INFO("PPP discard statistics reset");
+}
+
+/**
+ * @brief 打印PPP字节丢弃统计信息
+ */
+void ppp_lwip_print_discard_stats(void)
+{
+ PPP_DEBUG_INFO("=== PPP Discard Statistics ===");
+ PPP_DEBUG_INFO("Total Bytes Received: %u", g_ppp_discard_stats.total_bytes_received);
+ PPP_DEBUG_INFO("Total Bytes Processed: %u", g_ppp_discard_stats.total_bytes_processed);
+ PPP_DEBUG_INFO("Total Bytes Discarded: %u", g_ppp_discard_stats.total_bytes_discarded);
+ PPP_DEBUG_INFO(" - Invalid Frame Bytes: %u", g_ppp_discard_stats.invalid_frame_bytes);
+ PPP_DEBUG_INFO(" - Queue Full Bytes: %u", g_ppp_discard_stats.queue_full_bytes);
+ PPP_DEBUG_INFO(" - Malloc Fail Bytes: %u", g_ppp_discard_stats.malloc_fail_bytes);
+ PPP_DEBUG_INFO(" - Oversized Frame Bytes: %u", g_ppp_discard_stats.oversized_frame_bytes);
+ PPP_DEBUG_INFO(" - Incomplete Frame Bytes: %u", g_ppp_discard_stats.incomplete_frame_bytes);
+ PPP_DEBUG_INFO("Total Frames Received: %u", g_ppp_discard_stats.total_frames_received);
+ PPP_DEBUG_INFO("Total Frames Processed: %u", g_ppp_discard_stats.total_frames_processed);
+ PPP_DEBUG_INFO("Total Frames Discarded: %u", g_ppp_discard_stats.total_frames_discarded);
+
+ // 计算丢弃率
+ if (g_ppp_discard_stats.total_bytes_received > 0) {
+ uint32_t discard_rate = (g_ppp_discard_stats.total_bytes_discarded * 100) /
+ g_ppp_discard_stats.total_bytes_received;
+ PPP_DEBUG_INFO("Byte Discard Rate: %u.%02u%%",
+ discard_rate / 100, discard_rate % 100);
+ }
+
+ if (g_ppp_discard_stats.total_frames_received > 0) {
+ uint32_t frame_discard_rate = (g_ppp_discard_stats.total_frames_discarded * 100) /
+ g_ppp_discard_stats.total_frames_received;
+ PPP_DEBUG_INFO("Frame Discard Rate: %u.%02u%%",
+ frame_discard_rate / 100, frame_discard_rate % 100);
+ }
+ PPP_DEBUG_INFO("==============================");
}
\ No newline at end of file