STM_ATEM/User/performance_monitor.c
zhoujie 2cbd4a152d feat(main): 新增性能监控和调试输出功能
- 新增性能监控模块(performance_monitor),用于实时跟踪系统性能指标
- 添加串口调试输出功能,支持系统状态和性能统计的定期输出
- 实现双缓冲机制,提升ADC数据采集和存储的实时性
- 优化数据存储模块,支持校正后数据的存储和双缓冲管理
- 增强错误处理机制,完善中断回调函数和系统错误恢复

♻️ refactor(ltc2508): 重构ADC驱动支持双缓冲

- 将ADC数据存储从单缓冲区重构为双缓冲区结构
- 新增缓冲区状态管理和自动切换机制
- 优化DMA传输完成回调,支持多缓冲区处理
- 提供缓冲区获取和释放的API接口

📝 docs(performance): 新增性能评估报告和使用指南

- 创建STM32F405性能评估报告,详细分析系统性能指标
- 编写双缓冲机制使用指南,说明实现原理和使用方法
- 添加LTC2508驱动使用示例代码

🐛 fix(dma): 调整DMA中断优先级

- 将DMA2_Stream7中断优先级从9调整为6,优化中断响应
- 更新STM32CubeMX配置文件中的中断优先级设置

🔧 chore(config): 优化系统配置和代码结构

- 添加串口调试输出控制开关和间隔配置
- 清理中断处理文件,移除重复的回调函数定义
- 增强错误处理函数,添加系统状态恢复机制
2026-01-25 20:15:47 +08:00

193 lines
5.3 KiB
C

#include "performance_monitor.h"
#include <string.h>
#include <stdlib.h>
// 静态变量
static SystemPerfStats_t g_perf_stats = {0};
static uint32_t g_task_start_time[PERF_MON_MAX_TASKS] = {0};
static uint8_t g_task_active[PERF_MON_MAX_TASKS] = {0};
// 外部符号声明 (用于堆栈监控)
extern uint32_t _estack;
extern uint32_t _Min_Stack_Size;
/**
* @brief 初始化性能监控模块
* @param None
* @retval None
*/
void PerformanceMonitor_Init(void)
{
memset(&g_perf_stats, 0, sizeof(SystemPerfStats_t));
memset(g_task_start_time, 0, sizeof(g_task_start_time));
memset(g_task_active, 0, sizeof(g_task_active));
g_perf_stats.sample_period_ms = PERF_MON_SAMPLE_PERIOD_MS;
g_perf_stats.last_update_tick = HAL_GetTick();
// 初始化最小执行时间为最大值
for (int i = 0; i < PERF_MON_MAX_TASKS; i++) {
g_perf_stats.tasks[i].min_time_us = UINT32_MAX;
}
}
/**
* @brief 开始任务性能监控
* @param task_id: 任务ID
* @retval None
*/
void PerformanceMonitor_TaskStart(PerfTaskID_t task_id)
{
if (task_id >= PERF_MON_MAX_TASKS) return;
g_task_start_time[task_id] = HAL_GetTick() * 1000; // 转换为微秒
g_task_active[task_id] = 1;
}
/**
* @brief 结束任务性能监控
* @param task_id: 任务ID
* @retval None
*/
void PerformanceMonitor_TaskEnd(PerfTaskID_t task_id)
{
if (task_id >= PERF_MON_MAX_TASKS || !g_task_active[task_id]) return;
uint32_t end_time = HAL_GetTick() * 1000; // 转换为微秒
uint32_t execution_time = end_time - g_task_start_time[task_id];
TaskPerfStats_t *task_stats = &g_perf_stats.tasks[task_id];
// 更新统计信息
task_stats->total_time_us += execution_time;
task_stats->call_count++;
// 更新最大最小时间
if (execution_time > task_stats->max_time_us) {
task_stats->max_time_us = execution_time;
}
if (execution_time < task_stats->min_time_us) {
task_stats->min_time_us = execution_time;
}
// 计算平均时间
task_stats->avg_time_us = task_stats->total_time_us / task_stats->call_count;
g_task_active[task_id] = 0;
}
/**
* @brief 更新性能监控统计
* @param None
* @retval None
*/
void PerformanceMonitor_Update(void)
{
uint32_t current_tick = HAL_GetTick();
// 检查是否到了更新周期
if (current_tick - g_perf_stats.last_update_tick < g_perf_stats.sample_period_ms) {
return;
}
// 计算CPU使用率
uint32_t total_cpu_time = 0;
for (int i = 0; i < PERF_MON_MAX_TASKS; i++) {
if (g_perf_stats.tasks[i].call_count > 0) {
// 计算每个任务的CPU使用率
uint32_t task_time_per_period = g_perf_stats.tasks[i].avg_time_us *
(1000 / g_perf_stats.sample_period_ms);
g_perf_stats.tasks[i].cpu_usage_percent =
(float)task_time_per_period / 10000.0f; // 转换为百分比
total_cpu_time += task_time_per_period;
}
}
// 更新总CPU使用率
g_perf_stats.total_cpu_usage_percent = total_cpu_time / 100;
// 更新内存使用情况
g_perf_stats.free_heap_size = PerformanceMonitor_GetFreeHeapSize();
if (g_perf_stats.min_free_heap_size == 0 ||
g_perf_stats.free_heap_size < g_perf_stats.min_free_heap_size) {
g_perf_stats.min_free_heap_size = g_perf_stats.free_heap_size;
}
// 更新栈使用率
g_perf_stats.stack_usage_percent = PerformanceMonitor_GetStackUsage();
g_perf_stats.last_update_tick = current_tick;
}
/**
* @brief 获取性能统计信息
* @param stats: 统计信息结构体指针
* @retval None
*/
void PerformanceMonitor_GetStats(SystemPerfStats_t *stats)
{
if (stats != NULL) {
memcpy(stats, &g_perf_stats, sizeof(SystemPerfStats_t));
}
}
/**
* @brief 重置性能统计
* @param None
* @retval None
*/
void PerformanceMonitor_ResetStats(void)
{
memset(&g_perf_stats, 0, sizeof(SystemPerfStats_t));
g_perf_stats.sample_period_ms = PERF_MON_SAMPLE_PERIOD_MS;
g_perf_stats.last_update_tick = HAL_GetTick();
// 重新初始化最小执行时间
for (int i = 0; i < PERF_MON_MAX_TASKS; i++) {
g_perf_stats.tasks[i].min_time_us = UINT32_MAX;
}
}
/**
* @brief 获取空闲堆内存大小
* @param None
* @retval 空闲堆内存大小(字节)
*/
uint32_t PerformanceMonitor_GetFreeHeapSize(void)
{
// 简单的堆内存检测方法
// 在实际应用中,可能需要更复杂的内存管理
void *ptr = malloc(1);
if (ptr != NULL) {
free(ptr);
// 这里返回一个估算值,实际项目中需要更精确的实现
return 32768; // 假设有32KB空闲堆内存
}
return 0;
}
/**
* @brief 获取栈使用率
* @param None
* @retval 栈使用率百分比
*/
uint32_t PerformanceMonitor_GetStackUsage(void)
{
// 获取当前栈指针
uint32_t current_sp;
__asm volatile ("mov %0, sp" : "=r" (current_sp));
// 计算栈使用量
uint32_t stack_top = (uint32_t)&_estack;
uint32_t min_stack_size = (uint32_t)&_Min_Stack_Size;
uint32_t stack_used = stack_top - current_sp;
// 计算使用率百分比
if (min_stack_size > 0) {
return (stack_used * 100) / min_stack_size;
}
return 0;
}