slip添加缓存。期望减少丢帧 2497/1 2497/head 2498/target/1
author孙春阳 <snickersun@163.com>
Tue, 14 Oct 2025 01:29:33 +0000 (09:29 +0800)
committer孙春阳 <snickersun@163.com>
Tue, 14 Oct 2025 01:29:33 +0000 (09:29 +0800)
code/sdk/application/brandy/brandy_standard/thread_init.c
code/sdk/open_source/openharmony/third_party/lwip/lwip_adapter/liteos/src/arch/sio.c
code/sdk/open_source/openharmony/third_party/lwip/lwip_v2.1.3/src/netif/slipif.c

index 7b35e12..d51d612 100644 (file)
 #define APP_MAIN_STACK_SIZE         0xC00
 #define SAVE_FILE_STACK_SIZE        0xC00
 #define AUTO_OTA_STACK_SIZE         0xC00
-#define LWIP_MAIN_STACK_SIZE        0xC00
+#define LWIP_MAIN_STACK_SIZE        0xF00
 
 #define TIME_MAX                64
 #define USEC_TO_MILLI           1000
index dc23fc6..ace61d0 100644 (file)
@@ -19,9 +19,9 @@
  * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
- * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * OF SUCH DAMAGE.
  *
  * This file is part of the lwIP TCP/IP stack.
 #include "securec.h"
 #include "errcode.h"
 #include "hal_uart.h"
+#include "osal_task.h"
+#include "osal_msgqueue.h"
+#include "time/osal_timer.h"
+#include "soc_osal.h"
+#include "custom_utils.h"
+#include "thread_init.h"  // 添加:用于app_task_definition_t定义
+#include <string.h>
+#include <stdbool.h>
+#include <stdlib.h>
+
+/* 乒乓缓冲区配置 */
+#ifndef SIO_PING_PONG_BUFFER_SIZE
+#define SIO_PING_PONG_BUFFER_SIZE  2048  // 每个buffer大小(2KB)
+#endif
+
+#define SIO_PING_PONG_BUFFER_COUNT 3     // 三缓冲模式
+#define SIO_PING_PONG_TIMEOUT_MS   30    // buffer超时时间(30ms)
+
+/* SIO中断消息队列配置 */
+#define SIO_IRQ_MSG_QUEUE_SIZE     16    // 队列深度
+#define SIO_IRQ_PROCESS_TASK_PRIO  24    // 处理线程优先级
+#define SIO_IRQ_PROCESS_STACK_SIZE 4096  // 处理线程栈大小
+
+/* 乒乓缓冲区状态 */
+typedef enum {
+    SIO_BUFFER_STATE_EMPTY = 0,      // 空闲,可以写入
+    SIO_BUFFER_STATE_FILLING,        // 正在填充中
+    SIO_BUFFER_STATE_FULL,           // 已满或超时,等待处理
+    SIO_BUFFER_STATE_PROCESSING      // 正在处理中
+} sio_buffer_state_t;
+
+/* 乒乓缓冲区结构 */
+typedef struct {
+    uint8_t *data;                            // 数据缓冲区(动态分配)
+    volatile uint32_t write_pos;              // 当前写入位置
+    volatile sio_buffer_state_t state;        // 缓冲区状态
+    volatile uint32_t last_write_time;        // 最后写入时间戳(ms)
+    volatile uint32_t first_write_time;       // 首次写入时间戳
+} sio_ping_pong_buffer_t;
+
+/* SIO中断消息结构 */
+typedef struct {
+    uint8_t buffer_index;   // 缓冲区索引
+    uint16_t length;        // 数据长度
+} sio_irq_msg_t;
+
+/* SIO统计信息 */
+typedef struct {
+    uint32_t total_interrupts;              // 总中断次数
+    uint32_t total_bytes_received;          // 接收总字节数
+    uint32_t total_bytes_processed;         // 处理总字节数
+    uint32_t error_count;                   // 错误次数
+    uint32_t buffer_full_count;             // buffer满次数
+    uint32_t buffer_timeout_count;          // buffer超时次数
+    uint32_t buffer_switch_count;           // buffer切换次数
+    uint32_t dropped_both_full;             // 两个buffer都满导致丢弃的字节数
+    uint32_t cross_buffer_count;            // 跨buffer写入次数
+} sio_stats_t;
 
 /* SIO UART buffer configuration */
 #define SIO_UART_RX_BUFFER_SIZE    256
@@ -76,8 +134,350 @@ static bool g_sio_uart_initialized = false;
 static uint8_t g_sio_write_buffer[SIO_WRITE_BUFFER_SIZE];
 static uint32_t g_sio_write_buffer_pos = 0;
 
+/* 中断使能标志 */
+static volatile bool g_sio_interrupt_enabled = false;
+
+/* 处理线程相关 */
+static uint32_t g_sio_irq_process_task = 0;
+static unsigned long g_sio_irq_msg_queue = 0;
+static volatile bool g_sio_irq_task_running = false;
+
+/* 乒乓缓冲区(动态分配) */
+static sio_ping_pong_buffer_t *g_sio_ping_pong_buffers = NULL;
+static volatile uint8_t g_sio_current_buffer_index = 0;
+
+/* 全局时间戳(由定时器更新) */
+static volatile uint32_t g_sio_timer_timestamp_ms = 0;
+
+/* 定时器相关 */
+static osal_timer g_sio_timeout_timer;
+static volatile bool g_sio_timer_running = false;
+
+/* 统计信息 */
+static sio_stats_t g_sio_stats = {0};
+
+/* 数据处理回调函数指针 - 用于将数据传递给SLIP */
+static void (*g_sio_data_callback)(const uint8_t *data, uint32_t len) = NULL;
+
+/* 内部函数声明 */
+static uint32_t sio_get_current_time_ms(void);
+static errcode_t sio_flush_buffer(uint8_t buffer_index);
+static void sio_timeout_timer_callback(unsigned long arg);
+static void sio_irq_process_thread(void *arg);
+static void sio_uart_rx_interrupt_handler(const void *buffer, uint16_t length, bool error);
+static void sio_print_stats(void);
+
+/* 保留原有的uart_read_data_int_handler声明 */
 extern void uart_read_data_int_handler(const void *buffer, uint16_t length, bool error);
 
+/**
+ * @brief 获取当前时间戳(毫秒)
+ */
+static uint32_t sio_get_current_time_ms(void)
+{
+    unsigned long long jiffies = osal_get_jiffies();
+    return (uint32_t)osal_jiffies_to_msecs((unsigned int)jiffies);
+}
+
+/**
+ * @brief SIO中断数据处理线程(乒乓缓冲区模式)
+ */
+static void sio_irq_process_thread(void *arg)
+{
+    (void)arg;
+    sio_irq_msg_t msg;
+    unsigned int msg_size = sizeof(sio_irq_msg_t);
+    
+    printf("[SIO] IRQ process thread started (ping-pong mode)\n");
+    
+    while (g_sio_irq_task_running) {
+        int ret = osal_msg_queue_read_copy(
+            g_sio_irq_msg_queue,
+            &msg,
+            &msg_size,
+            OSAL_MSGQ_WAIT_FOREVER
+        );
+        
+        if (ret != OSAL_SUCCESS || !g_sio_irq_task_running) {
+            continue;
+        }
+        
+        if (msg.buffer_index >= SIO_PING_PONG_BUFFER_COUNT) {
+            printf("[SIO] Invalid buffer index: %u\n", msg.buffer_index);
+            continue;
+        }
+        
+        if (g_sio_ping_pong_buffers == NULL) {
+            printf("[SIO] Buffer memory not allocated\n");
+            continue;
+        }
+        
+        sio_ping_pong_buffer_t *buffer = &g_sio_ping_pong_buffers[msg.buffer_index];
+        
+        if (msg.length == 0 || msg.length > SIO_PING_PONG_BUFFER_SIZE) {
+            printf("[SIO] Invalid data length: %u\n", msg.length);
+            buffer->state = SIO_BUFFER_STATE_EMPTY;
+            buffer->write_pos = 0;
+            continue;
+        }
+        
+        buffer->state = SIO_BUFFER_STATE_PROCESSING;
+        
+        // 如果设置了数据回调,调用它(给SLIP使用)
+        if (g_sio_data_callback != NULL) {
+            g_sio_data_callback(buffer->data, msg.length);
+        }
+        
+        g_sio_stats.total_bytes_processed += msg.length;
+        
+        // 释放buffer
+        buffer->state = SIO_BUFFER_STATE_EMPTY;
+        buffer->write_pos = 0;
+        buffer->first_write_time = 0;
+    }
+    
+    printf("[SIO] IRQ process thread exited\n");
+}
+
+/**
+ * @brief 刷新指定buffer到消息队列
+ */
+static errcode_t sio_flush_buffer(uint8_t buffer_index)
+{
+    if (buffer_index >= SIO_PING_PONG_BUFFER_COUNT || g_sio_ping_pong_buffers == NULL) {
+        return ERRCODE_FAIL;
+    }
+    
+    sio_ping_pong_buffer_t *buffer = &g_sio_ping_pong_buffers[buffer_index];
+    
+    if (buffer->state != SIO_BUFFER_STATE_FILLING || buffer->write_pos == 0) {
+        return ERRCODE_SUCC;
+    }
+    
+    buffer->state = SIO_BUFFER_STATE_FULL;
+    
+    sio_irq_msg_t msg = {
+        .buffer_index = buffer_index,
+        .length = (uint16_t)buffer->write_pos
+    };
+    
+    int ret = osal_msg_queue_write_copy(
+        g_sio_irq_msg_queue,
+        &msg,
+        sizeof(sio_irq_msg_t),
+        OSAL_MSGQ_NO_WAIT
+    );
+    
+    if (ret != OSAL_SUCCESS) {
+        return ERRCODE_FAIL;
+    }
+    
+    return ERRCODE_SUCC;
+}
+
+/**
+ * @brief 定时器回调:检查buffer超时并flush,定期打印统计信息
+ * @note 定时器上下文,应快速返回
+ * @param arg 定时器参数(未使用)
+ * @warning osal_timer默认是one-shot,必须在回调中手动重启实现周期性执行
+ */
+static void sio_timeout_timer_callback(unsigned long arg)
+{
+    (void)arg;
+    
+    // 增加定时器调用计数(用于定期打印统计)
+    static volatile uint32_t timer_call_count = 0;
+    timer_call_count++;
+    
+    // 每100次(约3秒)打印一次诊断信息
+    if ((timer_call_count % 100) == 1) {
+        printf("[SIO] Timer callback executed %u times, enabled=%d, running=%d\n", 
+               timer_call_count, g_sio_interrupt_enabled, g_sio_timer_running);
+    }
+    
+    // 每333次(约10秒)打印一次完整统计信息
+    // 30ms * 333 ≈ 10秒
+    if ((timer_call_count % 333) == 0) {
+        sio_print_stats();
+    }
+    
+    if (!g_sio_interrupt_enabled || !g_sio_timer_running) {
+        return;
+    }
+    
+    uint32_t current_time = sio_get_current_time_ms();
+    
+    // ⚠️ 更新全局时间戳(供ISR使用,ISR中不能调用时间函数)
+    g_sio_timer_timestamp_ms = current_time;
+    
+    if (g_sio_ping_pong_buffers == NULL) {
+        goto restart_timer;
+    }
+    
+    uint8_t current_idx = g_sio_current_buffer_index;
+    
+    // ⚠️ 检查所有buffer的超时状态
+    // 需求:超时时如果当前buffer未满也要flush,避免数据滞留
+    for (uint8_t i = 0; i < SIO_PING_PONG_BUFFER_COUNT; i++) {
+        uint8_t current_check = g_sio_current_buffer_index;
+        bool is_current = (i == current_check);
+        
+        sio_ping_pong_buffer_t *buffer = &g_sio_ping_pong_buffers[i];
+        
+        if (buffer->state == SIO_BUFFER_STATE_FILLING && buffer->write_pos > 0) {
+            if (buffer->last_write_time == 0) {
+                buffer->last_write_time = current_time;
+            } else {
+                uint32_t elapsed = current_time - buffer->last_write_time;
+                
+                if (elapsed >= SIO_PING_PONG_TIMEOUT_MS) {
+                    if (sio_flush_buffer(i) == ERRCODE_SUCC) {
+                        g_sio_stats.buffer_timeout_count++;
+                        
+                        if (is_current) {
+                            uint8_t next_idx = (i + 1) % SIO_PING_PONG_BUFFER_COUNT;
+                            if (g_sio_ping_pong_buffers[next_idx].state == SIO_BUFFER_STATE_EMPTY) {
+                                g_sio_current_buffer_index = next_idx;
+                                g_sio_stats.buffer_switch_count++;
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+    
+restart_timer:
+    // ⚠️ 关键修复:osal_timer是one-shot类型,必须手动重启以实现周期性执行
+    if (g_sio_timer_running) {
+        osal_timer_start(&g_sio_timeout_timer);
+    }
+}
+
+/**
+ * @brief UART接收中断回调函数(乒乓缓冲区模式)
+ */
+static void sio_uart_rx_interrupt_handler(const void *buffer, uint16_t length, bool error)
+{
+    if (!buffer || length == 0 || length > 200 || g_sio_ping_pong_buffers == NULL) {
+        g_sio_stats.error_count++;
+        return;
+    }
+    
+    if (error) {
+        g_sio_stats.error_count++;
+    }
+    
+    g_sio_stats.total_interrupts++;
+    g_sio_stats.total_bytes_received += length;
+    
+    uint8_t current_idx = g_sio_current_buffer_index;
+    sio_ping_pong_buffer_t *current_buffer = &g_sio_ping_pong_buffers[current_idx];
+    
+    // 检查当前buffer超时
+    if (current_buffer->state == SIO_BUFFER_STATE_FILLING && 
+        current_buffer->write_pos > 0 && 
+        current_buffer->last_write_time != 0) {
+        uint32_t current_time = g_sio_timer_timestamp_ms;
+        uint32_t elapsed = current_time - current_buffer->last_write_time;
+        
+        if (elapsed >= SIO_PING_PONG_TIMEOUT_MS) {
+            sio_flush_buffer(current_idx);
+            g_sio_stats.buffer_timeout_count++;
+            
+            uint8_t next_idx = (current_idx + 1) % SIO_PING_PONG_BUFFER_COUNT;
+            if (g_sio_ping_pong_buffers[next_idx].state == SIO_BUFFER_STATE_EMPTY) {
+                g_sio_current_buffer_index = next_idx;
+                g_sio_stats.buffer_switch_count++;
+                current_idx = next_idx;
+                current_buffer = &g_sio_ping_pong_buffers[current_idx];
+            }
+        }
+    }
+    
+    // 如果当前buffer不可写,切换
+    if (current_buffer->state != SIO_BUFFER_STATE_EMPTY && 
+        current_buffer->state != SIO_BUFFER_STATE_FILLING) {
+        uint8_t next_idx = (current_idx + 1) % SIO_PING_PONG_BUFFER_COUNT;
+        if (g_sio_ping_pong_buffers[next_idx].state == SIO_BUFFER_STATE_EMPTY) {
+            g_sio_current_buffer_index = next_idx;
+            g_sio_stats.buffer_switch_count++;
+            current_idx = next_idx;
+            current_buffer = &g_sio_ping_pong_buffers[current_idx];
+        }
+    }
+    
+    // 初始化空buffer
+    if (current_buffer->state == SIO_BUFFER_STATE_EMPTY) {
+        current_buffer->state = SIO_BUFFER_STATE_FILLING;
+        current_buffer->write_pos = 0;
+        current_buffer->first_write_time = g_sio_timer_timestamp_ms;
+    }
+    
+    uint32_t available = SIO_PING_PONG_BUFFER_SIZE - current_buffer->write_pos;
+    uint16_t remaining_data = length;
+    const uint8_t *data_ptr = (const uint8_t *)buffer;
+    
+    // 跨buffer写入处理
+    if (current_buffer->state == SIO_BUFFER_STATE_FILLING) {
+        if (remaining_data <= available) {
+            // 数据完全放得下
+            memcpy(current_buffer->data + current_buffer->write_pos, data_ptr, remaining_data);
+            current_buffer->write_pos += remaining_data;
+            current_buffer->last_write_time = 0;
+            
+            // 检查是否填满
+            if (current_buffer->write_pos >= SIO_PING_PONG_BUFFER_SIZE) {
+                sio_flush_buffer(current_idx);
+                g_sio_stats.buffer_full_count++;
+                
+                uint8_t next_idx = (current_idx + 1) % SIO_PING_PONG_BUFFER_COUNT;
+                if (g_sio_ping_pong_buffers[next_idx].state == SIO_BUFFER_STATE_EMPTY) {
+                    g_sio_current_buffer_index = next_idx;
+                    g_sio_stats.buffer_switch_count++;
+                }
+            }
+        } else {
+            // 需要跨buffer写入
+            g_sio_stats.cross_buffer_count++;
+            
+            // 填满当前buffer
+            if (available > 0) {
+                memcpy(current_buffer->data + current_buffer->write_pos, data_ptr, available);
+                current_buffer->write_pos += available;
+                data_ptr += available;
+                remaining_data -= available;
+            }
+            
+            // flush当前buffer
+            sio_flush_buffer(current_idx);
+            g_sio_stats.buffer_full_count++;
+            
+            // 切换到下一个buffer
+            uint8_t next_idx = (current_idx + 1) % SIO_PING_PONG_BUFFER_COUNT;
+            sio_ping_pong_buffer_t *next_buffer = &g_sio_ping_pong_buffers[next_idx];
+            
+            if (next_buffer->state == SIO_BUFFER_STATE_EMPTY && 
+                remaining_data <= SIO_PING_PONG_BUFFER_SIZE) {
+                g_sio_current_buffer_index = next_idx;
+                g_sio_stats.buffer_switch_count++;
+                
+                next_buffer->state = SIO_BUFFER_STATE_FILLING;
+                next_buffer->write_pos = 0;
+                next_buffer->first_write_time = g_sio_timer_timestamp_ms;
+                
+                memcpy(next_buffer->data, data_ptr, remaining_data);
+                next_buffer->write_pos = remaining_data;
+                next_buffer->last_write_time = 0;
+            } else {
+                g_sio_stats.dropped_both_full += remaining_data;
+            }
+        }
+    } else {
+        g_sio_stats.dropped_both_full += length;
+    }
+}
+
 /**
  * Initialize SIO UART
  */
@@ -90,16 +490,16 @@ static errcode_t sio_uart_init(void)
     }
 
     printf(" %s %d\n", __FUNCTION__, __LINE__);
-    /* Initialize UART */
-    // ret = uapi_uart_init(SIO_UART_BUS, (const void*)&g_sio_uart_pin_config, 
-                        //  (const void*)&g_sio_uart_attr, NULL, (void*)&g_sio_uart_buffer_config);
     ret = uapi_uart_set_attr(SIO_UART_BUS, (const void*)&g_sio_uart_attr);
     if (ret != ERRCODE_SUCC) {
         return ret;
     }
 
-    ret = uapi_uart_register_rx_callback(SIO_UART_BUS, UART_RX_CONDITION_FULL_OR_SUFFICIENT_DATA_OR_IDLE,
-        SIO_UART_RX_BUFFER_SIZE, uart_read_data_int_handler);
+    // 使用新的中断处理函数
+    ret = uapi_uart_register_rx_callback(SIO_UART_BUS, 
+        UART_RX_CONDITION_FULL_OR_SUFFICIENT_DATA_OR_IDLE,
+        8,  // 8字节阈值
+        sio_uart_rx_interrupt_handler);
 
     printf("uapi_uart_register_rx_callback ret=%x\r\n", ret);
 
@@ -108,6 +508,328 @@ static errcode_t sio_uart_init(void)
     return ERRCODE_SUCC;
 }
 
+/**
+ * @brief 启用SIO中断模式(乒乓缓冲区)
+ */
+errcode_t sio_interrupt_enable(void (*data_callback)(const uint8_t *data, uint32_t len))
+{
+    if (g_sio_interrupt_enabled) {
+        printf("[SIO] Interrupt already enabled\n");
+        return ERRCODE_SUCC;
+    }
+    
+    printf("[SIO] Enabling interrupt mode (ping-pong buffer)\n");
+    
+    // 保存数据回调函数
+    g_sio_data_callback = data_callback;
+    
+    // 1. 动态分配乒乓缓冲区内存
+    if (g_sio_ping_pong_buffers != NULL) {
+        printf("[SIO] WARNING: Memory leak detected!\n");
+        free(g_sio_ping_pong_buffers);
+        g_sio_ping_pong_buffers = NULL;
+    }
+    
+    size_t buffer_struct_size = sizeof(sio_ping_pong_buffer_t) * SIO_PING_PONG_BUFFER_COUNT;
+    g_sio_ping_pong_buffers = (sio_ping_pong_buffer_t *)malloc(buffer_struct_size);
+    
+    if (g_sio_ping_pong_buffers == NULL) {
+        printf("[SIO] Failed to allocate buffer structures\n");
+        return ERRCODE_MALLOC;
+    }
+    
+    // 为每个buffer分配数据区域
+    for (uint8_t i = 0; i < SIO_PING_PONG_BUFFER_COUNT; i++) {
+        g_sio_ping_pong_buffers[i].data = (uint8_t *)malloc(SIO_PING_PONG_BUFFER_SIZE);
+        if (g_sio_ping_pong_buffers[i].data == NULL) {
+            printf("[SIO] Failed to allocate buffer[%u] data\n", i);
+            // 清理已分配的内存
+            for (uint8_t j = 0; j < i; j++) {
+                free(g_sio_ping_pong_buffers[j].data);
+            }
+            free(g_sio_ping_pong_buffers);
+            g_sio_ping_pong_buffers = NULL;
+            return ERRCODE_MALLOC;
+        }
+        g_sio_ping_pong_buffers[i].write_pos = 0;
+        g_sio_ping_pong_buffers[i].state = SIO_BUFFER_STATE_EMPTY;
+        g_sio_ping_pong_buffers[i].last_write_time = 0;
+        g_sio_ping_pong_buffers[i].first_write_time = 0;
+        memset(g_sio_ping_pong_buffers[i].data, 0, SIO_PING_PONG_BUFFER_SIZE);
+    }
+    g_sio_current_buffer_index = 0;
+    
+    printf("[SIO] Allocated %d x %d bytes = %.2f KB total\n", 
+           SIO_PING_PONG_BUFFER_COUNT, SIO_PING_PONG_BUFFER_SIZE,
+           (SIO_PING_PONG_BUFFER_COUNT * SIO_PING_PONG_BUFFER_SIZE) / 1024.0);
+    
+    // 2. 创建消息队列
+    int ret = osal_msg_queue_create(
+        "sio_irq_queue",
+        SIO_IRQ_MSG_QUEUE_SIZE,
+        &g_sio_irq_msg_queue,
+        0,
+        sizeof(sio_irq_msg_t)
+    );
+    
+    if (ret != OSAL_SUCCESS) {
+        printf("[SIO] Failed to create message queue: 0x%x\n", ret);
+        for (uint8_t i = 0; i < SIO_PING_PONG_BUFFER_COUNT; i++) {
+            free(g_sio_ping_pong_buffers[i].data);
+        }
+        free(g_sio_ping_pong_buffers);
+        g_sio_ping_pong_buffers = NULL;
+        return ERRCODE_FAIL;
+    }
+    
+    printf("[SIO] Message queue created (depth=%d)\n", SIO_IRQ_MSG_QUEUE_SIZE);
+    
+    // 3. 启动处理线程
+    g_sio_irq_task_running = true;
+    
+    app_task_definition_t irq_task_cfg = {0};
+    irq_task_cfg.attr.name = "sio_irq_proc";
+    irq_task_cfg.attr.priority = osPriorityNormal;
+    irq_task_cfg.attr.stack_size = SIO_IRQ_PROCESS_STACK_SIZE;
+    irq_task_cfg.func = (osThreadFunc_t)sio_irq_process_thread;
+    irq_task_cfg.task_handle = &g_sio_irq_process_task;
+    irq_task_cfg.use_mem = USE_EXTEND_MEM;
+    irq_task_cfg.create_queue_handle = NULL;
+    
+    ret = uapi_create_osThread_custom(&irq_task_cfg);
+    if (ret != ERRCODE_SUCC) {
+        printf("[SIO] Failed to create IRQ process thread: 0x%x\n", ret);
+        osal_msg_queue_delete(g_sio_irq_msg_queue);
+        g_sio_irq_msg_queue = 0;
+        g_sio_irq_task_running = false;
+        for (uint8_t i = 0; i < SIO_PING_PONG_BUFFER_COUNT; i++) {
+            free(g_sio_ping_pong_buffers[i].data);
+        }
+        free(g_sio_ping_pong_buffers);
+        g_sio_ping_pong_buffers = NULL;
+        return ERRCODE_FAIL;
+    }
+    
+    printf("[SIO] IRQ process thread created (PSRAM stack)\n");
+    
+    // 4. 启动定时器
+    g_sio_timeout_timer.handler = sio_timeout_timer_callback;
+    g_sio_timeout_timer.data = 0;
+    g_sio_timeout_timer.interval = SIO_PING_PONG_TIMEOUT_MS;
+    
+    ret = osal_timer_init(&g_sio_timeout_timer);
+    if (ret != OSAL_SUCCESS) {
+        printf("[SIO] Failed to init timeout timer: 0x%x\n", ret);
+        g_sio_irq_task_running = false;
+        osal_msleep(100);
+        osal_msg_queue_delete(g_sio_irq_msg_queue);
+        g_sio_irq_msg_queue = 0;
+        for (uint8_t i = 0; i < SIO_PING_PONG_BUFFER_COUNT; i++) {
+            free(g_sio_ping_pong_buffers[i].data);
+        }
+        free(g_sio_ping_pong_buffers);
+        g_sio_ping_pong_buffers = NULL;
+        return ERRCODE_FAIL;
+    }
+    
+    g_sio_timer_running = true;
+    ret = osal_timer_start(&g_sio_timeout_timer);
+    if (ret != OSAL_SUCCESS) {
+        printf("[SIO] Failed to start timeout timer: 0x%x\n", ret);
+        g_sio_timer_running = false;
+        g_sio_irq_task_running = false;
+        osal_timer_destroy(&g_sio_timeout_timer);
+        osal_msleep(100);
+        osal_msg_queue_delete(g_sio_irq_msg_queue);
+        g_sio_irq_msg_queue = 0;
+        for (uint8_t i = 0; i < SIO_PING_PONG_BUFFER_COUNT; i++) {
+            free(g_sio_ping_pong_buffers[i].data);
+        }
+        free(g_sio_ping_pong_buffers);
+        g_sio_ping_pong_buffers = NULL;
+        return ERRCODE_FAIL;
+    }
+    
+    printf("[SIO] Timeout timer started (period=%d ms)\n", SIO_PING_PONG_TIMEOUT_MS);
+    
+    g_sio_interrupt_enabled = true;
+    
+    printf("[SIO] Interrupt mode enabled successfully!\n");
+    printf("  - Buffers: %d x %d KB\n", SIO_PING_PONG_BUFFER_COUNT, SIO_PING_PONG_BUFFER_SIZE / 1024);
+    printf("  - Timeout: %d ms\n", SIO_PING_PONG_TIMEOUT_MS);
+    printf("  - Queue: %d slots\n", SIO_IRQ_MSG_QUEUE_SIZE);
+    
+    return ERRCODE_SUCC;
+}
+
+/**
+ * @brief 禁用SIO中断模式
+ */
+errcode_t sio_interrupt_disable(void)
+{
+    if (!g_sio_interrupt_enabled) {
+        return ERRCODE_SUCC;
+    }
+    
+    printf("[SIO] Disabling interrupt mode\n");
+    
+    // 1. 停止定时器
+    if (g_sio_timer_running) {
+        g_sio_timer_running = false;
+        osal_timer_stop(&g_sio_timeout_timer);
+        osal_timer_destroy(&g_sio_timeout_timer);
+        g_sio_timeout_timer.timer = NULL;
+        printf("[SIO] Timer stopped\n");
+    }
+    
+    // 2. 停止处理线程
+    g_sio_irq_task_running = false;
+    
+    sio_irq_msg_t empty_msg = {0};
+    osal_msg_queue_write_copy(g_sio_irq_msg_queue, &empty_msg, 
+                             sizeof(sio_irq_msg_t), OSAL_MSGQ_NO_WAIT);
+    
+    osal_msleep(200);
+    
+    // 3. 删除消息队列
+    osal_msg_queue_delete(g_sio_irq_msg_queue);
+    g_sio_irq_msg_queue = 0;
+    
+    // 4. 释放内存
+    if (g_sio_ping_pong_buffers != NULL) {
+        for (uint8_t i = 0; i < SIO_PING_PONG_BUFFER_COUNT; i++) {
+            if (g_sio_ping_pong_buffers[i].data != NULL) {
+                free(g_sio_ping_pong_buffers[i].data);
+            }
+        }
+        free(g_sio_ping_pong_buffers);
+        g_sio_ping_pong_buffers = NULL;
+        printf("[SIO] Memory freed\n");
+    }
+    
+    // 5. 清零统计
+    memset(&g_sio_stats, 0, sizeof(sio_stats_t));
+    
+    g_sio_interrupt_enabled = false;
+    g_sio_irq_process_task = 0;
+    g_sio_data_callback = NULL;
+    
+    printf("[SIO] Interrupt mode disabled\n");
+    
+    return ERRCODE_SUCC;
+}
+
+/**
+ * @brief 打印SIO统计信息(乒乓缓冲区模式)
+ */
+void sio_print_stats(void)
+{
+    printf("=== SIO Interrupt Statistics (Ping-Pong Mode) ===\n");
+    printf("Interrupt Status: %s\n", g_sio_interrupt_enabled ? "ENABLED" : "DISABLED");
+    printf("Ping-Pong Buffers: %d x %d bytes = %d KB total\n", 
+           SIO_PING_PONG_BUFFER_COUNT, SIO_PING_PONG_BUFFER_SIZE,
+           (SIO_PING_PONG_BUFFER_COUNT * SIO_PING_PONG_BUFFER_SIZE) / 1024);
+    printf("Timeout: %d ms\n", SIO_PING_PONG_TIMEOUT_MS);
+    printf("Message Queue: %d slots (%d bytes per message)\n", 
+           SIO_IRQ_MSG_QUEUE_SIZE, sizeof(sio_irq_msg_t));
+    printf("\n");
+    
+    // 乒乓缓冲区状态
+    printf("Buffer Status:\n");
+    if (g_sio_ping_pong_buffers != NULL) {
+        for (uint8_t i = 0; i < SIO_PING_PONG_BUFFER_COUNT; i++) {
+            const char *state_str = "UNKNOWN";
+            switch (g_sio_ping_pong_buffers[i].state) {
+                case SIO_BUFFER_STATE_EMPTY:      state_str = "EMPTY"; break;
+                case SIO_BUFFER_STATE_FILLING:    state_str = "FILLING"; break;
+                case SIO_BUFFER_STATE_FULL:       state_str = "FULL"; break;
+                case SIO_BUFFER_STATE_PROCESSING: state_str = "PROCESSING"; break;
+            }
+            printf("  Buffer[%u]: %s, %u/%u bytes%s\n", 
+                   i, state_str, g_sio_ping_pong_buffers[i].write_pos, SIO_PING_PONG_BUFFER_SIZE,
+                   (i == g_sio_current_buffer_index) ? " (current)" : "");
+        }
+    } else {
+        printf("  Buffers not allocated\n");
+    }
+    printf("\n");
+    
+    // 乒乓缓冲区统计
+    printf("Ping-Pong Buffer Statistics:\n");
+    printf("  Buffer Full Count: %u\n", g_sio_stats.buffer_full_count);
+    printf("  Buffer Timeout Count: %u\n", g_sio_stats.buffer_timeout_count);
+    printf("  Buffer Switch Count: %u (success)\n", g_sio_stats.buffer_switch_count);
+    printf("  Cross-Buffer Writes: %u (跨buffer写入)\n", g_sio_stats.cross_buffer_count);
+    printf("  Dropped (Both Full): %u bytes\n", g_sio_stats.dropped_both_full);
+    printf("\n");
+    
+    // 中断层统计
+    printf("=== Interrupt Layer Statistics ===\n");
+    printf("Total UART Interrupts: %u\n", g_sio_stats.total_interrupts);
+    printf("  - With RX Error: %u\n", g_sio_stats.error_count);
+    
+    if (g_sio_stats.total_interrupts > 0) {
+        uint32_t avg_bytes_per_irq = g_sio_stats.total_bytes_received / 
+                                     g_sio_stats.total_interrupts;
+        printf("  Average bytes per interrupt: %u\n", avg_bytes_per_irq);
+        
+        // 错误率
+        if (g_sio_stats.error_count > 0) {
+            uint32_t error_rate = (g_sio_stats.error_count * 10000) / 
+                                  g_sio_stats.total_interrupts;
+            printf("  Error Rate: %u.%02u%%\n", error_rate / 100, error_rate % 100);
+            
+            // 如果错误率 > 1%,发出警告
+            if (error_rate > 100) {
+                printf("  ⚠️  High error rate! Check UART config and cable.\n");
+            }
+        }
+    }
+    printf("\n");
+    
+    // 字节统计
+    printf("Byte Statistics:\n");
+    printf("  Total Bytes Received: %u\n", g_sio_stats.total_bytes_received);
+    printf("  Total Bytes Processed: %u\n", g_sio_stats.total_bytes_processed);
+    printf("  Total Bytes Discarded: %u\n", g_sio_stats.dropped_both_full);
+    printf("\n");
+    
+    // 计算丢包率
+    if (g_sio_stats.total_bytes_received > 0) {
+        uint32_t drop_rate = (g_sio_stats.dropped_both_full * 10000) / 
+                            g_sio_stats.total_bytes_received;
+        printf("Total Drop Rate: %u.%02u%%\n", drop_rate / 100, drop_rate % 100);
+        
+        // 两个buffer都满导致的丢失率
+        if (g_sio_stats.dropped_both_full > 0) {
+            uint32_t both_full_rate = (g_sio_stats.dropped_both_full * 10000) / 
+                                     g_sio_stats.total_bytes_received;
+            printf("Both Buffers Full Rate: %u.%02u%% ⚠️\n", 
+                   both_full_rate / 100, both_full_rate % 100);
+            printf("  (processing too slow or buffers too small)\n");
+        }
+        
+        // 处理效率
+        if (g_sio_stats.total_bytes_processed > 0) {
+            uint32_t process_rate = (g_sio_stats.total_bytes_processed * 10000) / 
+                                   g_sio_stats.total_bytes_received;
+            printf("Process Success Rate: %u.%02u%%\n", 
+                   process_rate / 100, process_rate % 100);
+        }
+    }
+    
+    printf("=================================================\n");
+}
+
+/**
+ * @brief 重置SIO统计信息
+ */
+void sio_reset_stats(void)
+{
+    memset(&g_sio_stats, 0, sizeof(sio_stats_t));
+    printf("[SIO] Statistics reset\n");
+}
+
 /**
  * Opens a serial device for communication.
  *
@@ -281,4 +1003,4 @@ void sio_send_flush(void)
         (void)result; /* Ignore result in flush operation */
         g_sio_write_buffer_pos = 0; /* Reset buffer position */
     }
-} 
\ No newline at end of file
+}
index c96d077..ebf0ff7 100644 (file)
@@ -126,17 +126,46 @@ static volatile bool slipif_thread_running = true;
 /* Global variable to store current netif */
 static struct netif *g_current_slipif_netif = NULL;
 
+/* SIO乒乓buffer扩展函数声明 */
+extern errcode_t sio_interrupt_enable(void (*data_callback)(const uint8_t *data, uint32_t len));
+extern errcode_t sio_interrupt_disable(void);
 /**
  * @ingroup slipif
  * Get the current netif from slipif_loop_thread
  * 
  * @return pointer to the current netif, or NULL if not available
  */
-  static struct netif *slipif_get_current_netif(void)
-  {
-      return g_current_slipif_netif;
+static struct netif *slipif_get_current_netif(void)
+{
+    return g_current_slipif_netif;
+}
+
+/**
+ * @brief SIO数据回调函数 - 从乒乓buffer接收数据并传递给SLIP
+ */
+static void slipif_sio_data_callback(const uint8_t *data, uint32_t len)
+{
+  struct netif *netif = slipif_get_current_netif();
+  
+  if (netif == NULL || netif->state == NULL) {
+    printf("[SLIP] ERROR: netif or netif->state is NULL in SIO callback\n");
+    return;
   }
- 
+  
+#if SLIP_RX_FROM_ISR
+  // ISR模式:逐字节加入队列
+  for (uint32_t i = 0; i < len; i++) {
+    slipif_received_byte(netif, data[i]);
+  }
+#else
+  // 轮询模式:直接处理
+  for (uint32_t i = 0; i < len; i++) {
+    slipif_rxbyte_input(netif, data[i]);
+  }
+#endif
+}
+
+
  /**
   * @ingroup slipif
   * Set the current netif for slipif_loop_thread
@@ -567,6 +596,19 @@ slipif_init(struct netif *netif)
     return ERR_IF;
   }
   LWIP_DEBUGF(SLIP_DEBUG, ("slipif_init: sio_open success, sd=%p\n", priv->sd));
+  
+  /* 设置全局netif供SIO回调使用 */
+  slipif_set_current_netif(netif);
+  
+  /* 启用SIO乒乓buffer中断模式 */
+  printf("[SLIP] Enabling SIO ping-pong buffer interrupt mode...\n");
+  errcode_t ret_sio = sio_interrupt_enable(slipif_sio_data_callback);
+  if (ret_sio != ERRCODE_SUCC) {
+    printf("[SLIP] WARNING: sio_interrupt_enable failed: 0x%x, falling back to polling mode\n", ret_sio);
+  } else {
+    printf("[SLIP] SIO ping-pong buffer enabled successfully!\n");
+    printf("[SLIP] Data flow: UART ISR -> ping-pong buffer -> SIO callback -> SLIP parser\n");
+  }
 #if SLIP_USE_RX_THREAD
   /* Create a thread to poll the serial device. */
   LWIP_DEBUGF(SLIP_DEBUG, ("slipif_init: creating RX thread with stack=%d, prio=%d\n",