优化ppp中断所用缓存,移到psram中 2493/1
author孙春阳 <snickersun@163.com>
Mon, 13 Oct 2025 07:45:31 +0000 (15:45 +0800)
committer孙春阳 <snickersun@163.com>
Mon, 13 Oct 2025 07:45:31 +0000 (15:45 +0800)
code/sdk/zhihui/ppp/src/ppp_interrupt.c

index 1be7831..8b9bd84 100644 (file)
@@ -74,8 +74,8 @@ static osal_task *g_ppp_irq_process_task = NULL;
 static unsigned long g_ppp_irq_msg_queue = 0;  // 消息队列ID (OSAL使用unsigned long)
 static volatile bool g_ppp_irq_task_running = false;
 
-/* 乒乓缓冲区 */
-static ppp_ping_pong_buffer_t g_ping_pong_buffers[PPP_PING_PONG_BUFFER_COUNT];
+/* 乒乓缓冲区(动态分配,避免占用DTCM) */
+static ppp_ping_pong_buffer_t *g_ping_pong_buffers = NULL;  // 改为指针,通过malloc动态分配
 static volatile uint8_t g_current_buffer_index = 0;  // ⚠️ volatile不保证原子性,但单字节写入在ARM上通常是原子的
 
 /* 全局时间戳(由定时器更新,ISR只读) */
@@ -172,6 +172,12 @@ static void ppp_irq_process_thread(void *arg)
             continue;
         }
         
+        // ⚠️ 检查内存是否已分配
+        if (g_ping_pong_buffers == NULL) {
+            PPP_DEBUG_ERROR("Buffer memory not allocated");
+            continue;
+        }
+        
         ppp_ping_pong_buffer_t *buffer = &g_ping_pong_buffers[msg.buffer_index];
         
         // 验证数据长度
@@ -255,6 +261,11 @@ static ppp_error_t ppp_flush_buffer_internal(uint8_t buffer_index, bool is_timeo
         return PPP_ERR_INVALID_PARAM;
     }
     
+    // ⚠️ 检查内存是否已分配
+    if (g_ping_pong_buffers == NULL) {
+        return PPP_ERR_INVALID_PARAM;
+    }
+    
     ppp_ping_pong_buffer_t *buffer = &g_ping_pong_buffers[buffer_index];
     
     // 只flush FILLING状态的buffer
@@ -366,6 +377,11 @@ static void ppp_timeout_timer_callback(unsigned long arg)
     
     uint8_t current_idx = g_current_buffer_index;  // 读取一次,避免重复读取
     
+    // ⚠️ 检查内存是否已分配
+    if (g_ping_pong_buffers == NULL) {
+        return;
+    }
+    
     // ⚠️ 新增:检查所有buffer的超时状态(包括当前buffer)
     // 需求4:超时时如果当前buffer未满也要flush,避免数据滞留
     for (uint8_t i = 0; i < PPP_PING_PONG_BUFFER_COUNT; i++) {
@@ -485,7 +501,7 @@ void _ppp_uart_rx_interrupt_handler(const void *buffer, uint16_t length, bool er
     // ⚠️ 中断中禁止打印!必须极快返回
     
     // 快速路径:参数校验(异常情况也不打印,只统计)
-    if ( !buffer || length == 0 || length > 200) {  // 单次中断最多200字节
+    if (!buffer || length == 0 || length > 200 || g_ping_pong_buffers == NULL) {
         // 不打印!在中断中打印会阻塞系统,只记录统计
         g_ppp_interrupt_stats.error_count++;
         return;
@@ -634,7 +650,25 @@ ppp_error_t ppp_interrupt_enable(void)
     
     PPP_DEBUG_INFO("Enabling PPP UART interrupt mode (ping-pong buffer)");
     
-    // 1. 初始化乒乓缓冲区
+    // 1. 动态分配乒乓缓冲区内存
+    if (g_ping_pong_buffers != NULL) {
+        PPP_DEBUG_ERROR("Memory leak detected: g_ping_pong_buffers is not NULL!");
+        free(g_ping_pong_buffers);
+        g_ping_pong_buffers = NULL;
+    }
+    
+    size_t buffer_size = sizeof(ppp_ping_pong_buffer_t) * PPP_PING_PONG_BUFFER_COUNT;
+    g_ping_pong_buffers = (ppp_ping_pong_buffer_t *)malloc(buffer_size);
+    
+    if (g_ping_pong_buffers == NULL) {
+        PPP_DEBUG_ERROR("Failed to allocate %zu bytes for ping-pong buffers", buffer_size);
+        return PPP_ERR_MEMORY;
+    }
+    
+    PPP_DEBUG_INFO("Allocated %zu bytes (%.2f KB) for ping-pong buffers via malloc", 
+                  buffer_size, buffer_size / 1024.0);
+    
+    // 2. 初始化乒乓缓冲区
     for (uint8_t i = 0; i < PPP_PING_PONG_BUFFER_COUNT; i++) {
         g_ping_pong_buffers[i].write_pos = 0;
         g_ping_pong_buffers[i].state = PPP_BUFFER_STATE_EMPTY;
@@ -648,7 +682,7 @@ ppp_error_t ppp_interrupt_enable(void)
                   PPP_PING_PONG_BUFFER_COUNT, PPP_PING_PONG_BUFFER_SIZE,
                   (PPP_PING_PONG_BUFFER_COUNT * PPP_PING_PONG_BUFFER_SIZE) / 1024);
     
-    // 2. 创建消息队列(只传递buffer索引,所以队列可以更小)
+    // 3. 创建消息队列(只传递buffer索引,所以队列可以更小)
     int ret = osal_msg_queue_create(
         "ppp_irq_queue",
         PPP_IRQ_MSG_QUEUE_SIZE,
@@ -659,13 +693,15 @@ ppp_error_t ppp_interrupt_enable(void)
     
     if (ret != OSAL_SUCCESS) {
         PPP_DEBUG_ERROR("Failed to create message queue: 0x%x", ret);
+        free(g_ping_pong_buffers);
+        g_ping_pong_buffers = NULL;
         return PPP_ERR_MEMORY;
     }
     
     PPP_DEBUG_INFO("Message queue created (depth=%d, item_size=%d bytes)", 
                   PPP_IRQ_MSG_QUEUE_SIZE, sizeof(ppp_irq_msg_t));
     
-    // 3. 启动处理线程(使用 osal_kthread_create_ext 创建时指定优先级)
+    // 4. 启动处理线程(使用 osal_kthread_create_ext 创建时指定优先级)
     // ⚠️ 关键修复:必须在创建时就指定优先级,否则线程以默认低优先级创建可能永远得不到调度
     g_ppp_irq_task_running = true;
     
@@ -684,7 +720,10 @@ ppp_error_t ppp_interrupt_enable(void)
     if (!g_ppp_irq_process_task) {
         PPP_DEBUG_ERROR("Failed to create process thread");
         osal_msg_queue_delete(g_ppp_irq_msg_queue);
+        g_ppp_irq_msg_queue = 0;
         g_ppp_irq_task_running = false;
+        free(g_ping_pong_buffers);
+        g_ping_pong_buffers = NULL;
         return PPP_ERR_MEMORY;
     }
     
@@ -693,7 +732,7 @@ ppp_error_t ppp_interrupt_enable(void)
     PPP_DEBUG_INFO("Process thread: stack=%d bytes, priority=MIDDLE(6)", 
                   PPP_IRQ_PROCESS_STACK_SIZE);
     
-    // 4. 启动定时器(30ms周期检查buffer超时)
+    // 5. 启动定时器(30ms周期检查buffer超时)
     // 先设置timer的handler、data和interval
     g_ppp_timeout_timer.handler = ppp_timeout_timer_callback;
     g_ppp_timeout_timer.data = 0;
@@ -705,6 +744,9 @@ ppp_error_t ppp_interrupt_enable(void)
         g_ppp_irq_task_running = false;
         osal_msleep(100);
         osal_msg_queue_delete(g_ppp_irq_msg_queue);
+        g_ppp_irq_msg_queue = 0;
+        free(g_ping_pong_buffers);
+        g_ping_pong_buffers = NULL;
         return PPP_ERR_MEMORY;
     }
     
@@ -717,12 +759,15 @@ ppp_error_t ppp_interrupt_enable(void)
         osal_timer_destroy(&g_ppp_timeout_timer);
         osal_msleep(100);
         osal_msg_queue_delete(g_ppp_irq_msg_queue);
+        g_ppp_irq_msg_queue = 0;
+        free(g_ping_pong_buffers);
+        g_ping_pong_buffers = NULL;
         return PPP_ERR_MEMORY;
     }
     
     PPP_DEBUG_INFO("Timeout timer started (period=%d ms)", PPP_PING_PONG_TIMEOUT_MS);
     
-    // 5. 注册UART中断回调
+    // 6. 注册UART中断回调
     uint8_t uart_bus = ppp_serial_get_uart_bus();
     
     PPP_DEBUG_INFO("Registering UART RX callback:");
@@ -755,14 +800,17 @@ ppp_error_t ppp_interrupt_enable(void)
         g_ppp_irq_task_running = false;
         osal_msleep(100);
         osal_msg_queue_delete(g_ppp_irq_msg_queue);
+        g_ppp_irq_msg_queue = 0;
+        free(g_ping_pong_buffers);
+        g_ping_pong_buffers = NULL;
         
         return PPP_ERR_UART;
     }
     
     PPP_DEBUG_INFO("UART RX callback registered successfully!");
     
-    // 6. 注册UART错误回调(用于详细错误诊断)
-    // 6.1 注册奇偶校验错误回调
+    // 7. 注册UART错误回调(用于详细错误诊断)
+    // 7.1 注册奇偶校验错误回调
     ret = uapi_uart_register_parity_error_callback(uart_bus, ppp_uart_parity_error_callback);
     if (ret != ERRCODE_SUCC) {
         PPP_DEBUG_WARN("Failed to register parity error callback: 0x%x (non-critical)", ret);
@@ -771,7 +819,7 @@ ppp_error_t ppp_interrupt_enable(void)
         PPP_DEBUG_INFO("Parity error callback registered");
     }
     
-    // 6.2 注册帧错误回调
+    // 7.2 注册帧错误回调
     ret = uapi_uart_register_frame_error_callback(uart_bus, ppp_uart_frame_error_callback);
     if (ret != ERRCODE_SUCC) {
         PPP_DEBUG_WARN("Failed to register frame error callback: 0x%x (non-critical)", ret);
@@ -842,27 +890,40 @@ ppp_error_t ppp_interrupt_disable(void)
     g_ppp_irq_msg_queue = 0;
     
     // 5. ⚠️ 数据安全:在清空前,先flush所有有数据的buffer,确保数据不丢失
-    PPP_DEBUG_INFO("Flushing all buffers before disable...");
-    for (uint8_t i = 0; i < PPP_PING_PONG_BUFFER_COUNT; i++) {
-        if (g_ping_pong_buffers[i].state == PPP_BUFFER_STATE_FILLING && 
-            g_ping_pong_buffers[i].write_pos > 0) {
-            PPP_DEBUG_INFO("  Flushing buffer[%u]: %u bytes", 
-                          i, g_ping_pong_buffers[i].write_pos);
-            ppp_flush_buffer(i);
-            // 给处理线程一点时间处理最后的数据
-            osal_msleep(50);
+    if (g_ping_pong_buffers != NULL) {
+        PPP_DEBUG_INFO("Flushing all buffers before disable...");
+        for (uint8_t i = 0; i < PPP_PING_PONG_BUFFER_COUNT; i++) {
+            if (g_ping_pong_buffers[i].state == PPP_BUFFER_STATE_FILLING && 
+                g_ping_pong_buffers[i].write_pos > 0) {
+                PPP_DEBUG_INFO("  Flushing buffer[%u]: %u bytes", 
+                              i, g_ping_pong_buffers[i].write_pos);
+                ppp_flush_buffer(i);
+                // 给处理线程一点时间处理最后的数据
+                osal_msleep(50);
+            }
         }
     }
     
     // 6. 清空乒乓缓冲区
-    for (uint8_t i = 0; i < PPP_PING_PONG_BUFFER_COUNT; i++) {
-        g_ping_pong_buffers[i].write_pos = 0;
-        g_ping_pong_buffers[i].state = PPP_BUFFER_STATE_EMPTY;
-        g_ping_pong_buffers[i].last_write_time = 0;
+    if (g_ping_pong_buffers != NULL) {
+        for (uint8_t i = 0; i < PPP_PING_PONG_BUFFER_COUNT; i++) {
+            g_ping_pong_buffers[i].write_pos = 0;
+            g_ping_pong_buffers[i].state = PPP_BUFFER_STATE_EMPTY;
+            g_ping_pong_buffers[i].last_write_time = 0;
+        }
     }
     g_current_buffer_index = 0;
     
-    // 7. 清零统计信息(为下次启用准备)
+    // 7. 释放动态分配的内存
+    if (g_ping_pong_buffers != NULL) {
+        size_t buffer_size = sizeof(ppp_ping_pong_buffer_t) * PPP_PING_PONG_BUFFER_COUNT;
+        PPP_DEBUG_INFO("Freeing %zu bytes (%.2f KB) of ping-pong buffer memory", 
+                      buffer_size, buffer_size / 1024.0);
+        free(g_ping_pong_buffers);
+        g_ping_pong_buffers = NULL;
+    }
+    
+    // 8. 清零统计信息(为下次启用准备)
     memset(&g_ppp_interrupt_stats, 0, sizeof(ppp_interrupt_stats_t));
     memset(&g_pingpong_stats, 0, sizeof(ppp_pingpong_stats_t));
     memset(&g_uart_error_stats, 0, sizeof(ppp_uart_error_stats_t));
@@ -870,7 +931,7 @@ ppp_error_t ppp_interrupt_disable(void)
     g_ppp_interrupt_enabled = false;
     g_ppp_irq_process_task = NULL;
     
-    PPP_DEBUG_INFO("PPP UART interrupt disabled");
+    PPP_DEBUG_INFO("PPP UART interrupt disabled (memory freed)");
     
     return PPP_ERR_OK;
 }
@@ -921,17 +982,21 @@ void ppp_interrupt_print_stats(void)
     
     // 乒乓缓冲区状态
     PPP_DEBUG_WARN("Buffer Status:");
-    for (uint8_t i = 0; i < PPP_PING_PONG_BUFFER_COUNT; i++) {
-        const char *state_str = "UNKNOWN";
-        switch (g_ping_pong_buffers[i].state) {
-            case PPP_BUFFER_STATE_EMPTY:      state_str = "EMPTY"; break;
-            case PPP_BUFFER_STATE_FILLING:    state_str = "FILLING"; break;
-            case PPP_BUFFER_STATE_FULL:       state_str = "FULL"; break;
-            case PPP_BUFFER_STATE_PROCESSING: state_str = "PROCESSING"; break;
+    if (g_ping_pong_buffers != NULL) {
+        for (uint8_t i = 0; i < PPP_PING_PONG_BUFFER_COUNT; i++) {
+            const char *state_str = "UNKNOWN";
+            switch (g_ping_pong_buffers[i].state) {
+                case PPP_BUFFER_STATE_EMPTY:      state_str = "EMPTY"; break;
+                case PPP_BUFFER_STATE_FILLING:    state_str = "FILLING"; break;
+                case PPP_BUFFER_STATE_FULL:       state_str = "FULL"; break;
+                case PPP_BUFFER_STATE_PROCESSING: state_str = "PROCESSING"; break;
+            }
+            PPP_DEBUG_WARN("  Buffer[%u]: %s, %u/%u bytes%s", 
+                          i, state_str, g_ping_pong_buffers[i].write_pos, PPP_PING_PONG_BUFFER_SIZE,
+                          (i == g_current_buffer_index) ? " (current)" : "");
         }
-        PPP_DEBUG_WARN("  Buffer[%u]: %s, %u/%u bytes%s", 
-                      i, state_str, g_ping_pong_buffers[i].write_pos, PPP_PING_PONG_BUFFER_SIZE,
-                      (i == g_current_buffer_index) ? " (current)" : "");
+    } else {
+        PPP_DEBUG_WARN("  Buffers not allocated");
     }
     PPP_DEBUG_WARN("");