From: 孙春阳 Date: Mon, 13 Oct 2025 07:45:31 +0000 (+0800) Subject: 优化ppp中断所用缓存,移到psram中 X-Git-Tag: V1.0.9_20251128_194606_LN~250^2~8^2~1 X-Git-Url: http://git.snicker.com.cn/?a=commitdiff_plain;h=77c14f24d7d38af579a98bc5bcdbe20346628e5e;p=mirrors%2FFD230.git 优化ppp中断所用缓存,移到psram中 --- diff --git a/code/sdk/zhihui/ppp/src/ppp_interrupt.c b/code/sdk/zhihui/ppp/src/ppp_interrupt.c index 1be783140..8b9bd8457 100644 --- a/code/sdk/zhihui/ppp/src/ppp_interrupt.c +++ b/code/sdk/zhihui/ppp/src/ppp_interrupt.c @@ -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("");