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只读) */
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];
// 验证数据长度
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
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++) {
// ⚠️ 中断中禁止打印!必须极快返回
// 快速路径:参数校验(异常情况也不打印,只统计)
- 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;
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;
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,
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;
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;
}
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;
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;
}
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:");
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);
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);
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));
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;
}
// 乒乓缓冲区状态
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("");