移除固定的包间延迟配置 `OTA_PACKET_DELAY_MS`,采用基于SPI Link v2 CREDIT背压的动态节奏控制,在SpiMaster中通过remoteCredit==0时wait/拒发 实现流量控制,提高OTA传输稳定性。 refactor(stack): 统一任务栈大小配置并添加CPU统计功能 - 在app_config.h中集中定义所有任务栈大小常量,基于实测水位优化分配 - 新增monitor/cpu_stats.cpp组件,提供1Hz FreeRTOS CPU占用采样 - 更新main.cpp中的任务创建使用新的栈大小常量 - 调整health_monitor和ota_relay等任务的栈分配 perf(ota): 改进ESP32和GD32 OTA分区预擦策略 - ESP32 OTA从边写边擦改为整分区预擦模式,避免写入时的扇区擦除阻塞 - GD32 OTA在prepare阶段进行整分区预擦,提升后续写入吞吐量 - 优化OTA协调器状态管理,修复FINALIZING状态残留问题 fix(log): 改进UDP日志发送的堆内存管理 - 当堆内存不足时记录UDP发送跳过的告警信息到ring buffer - 降低UDP发送跳过的内存阈值从10KB到6KB - 降低日志排水最小内存阈值从8KB到4KB docs(readme): 更新OTA配置参数文档说明 移除已废弃的OTA_PACKET_DELAY_MS参数,更新包间节奏控制说明为 基于CREDIT背压机制的描述。
74 lines
2.1 KiB
C++
74 lines
2.1 KiB
C++
/*
|
|
* cpu_stats.h - FreeRTOS 运行时 CPU 占用采样
|
|
*
|
|
* 由独立低优先级任务按固定 1s 周期采样;/system/status 只读最新快照,
|
|
* 不再在 HTTP 线程里调用 uxTaskGetSystemState(避免窗口绑浏览器轮询、减 httpd 栈压)。
|
|
*/
|
|
#pragma once
|
|
|
|
#include <stddef.h>
|
|
#include <stdint.h>
|
|
#include "freertos/FreeRTOS.h"
|
|
#include "freertos/task.h"
|
|
|
|
/** 单次快照最多跟踪的任务数 */
|
|
static constexpr size_t CPU_TASK_SNAPSHOT_MAX = 32;
|
|
|
|
/** 采样周期(ms)— 窗口 sample_ms 应对齐此值 */
|
|
static constexpr uint32_t CPU_STATS_SAMPLE_MS = 1000;
|
|
|
|
struct CpuTaskMetric {
|
|
char name[configMAX_TASK_NAME_LEN];
|
|
UBaseType_t task_number;
|
|
uint64_t runtime_delta;
|
|
double usage_pct;
|
|
};
|
|
|
|
struct CpuUsageSnapshot {
|
|
bool available; ///< 固件是否启用 RUN_TIME_STATS
|
|
bool valid; ///< 是否已有完整窗口(至少两拍)
|
|
uint32_t sample_ms; ///< 本窗口墙钟长度
|
|
double usage_pct; ///< 100 - idle
|
|
double idle_pct;
|
|
CpuTaskMetric tasks[CPU_TASK_SNAPSHOT_MAX];
|
|
size_t task_count;
|
|
};
|
|
|
|
/**
|
|
* @brief CPU 运行时统计(单例 + 1Hz 采样任务)
|
|
*/
|
|
class CpuStats {
|
|
public:
|
|
static CpuStats& instance();
|
|
|
|
/** 创建采样任务(幂等;失败仅打日志,不阻塞启动) */
|
|
void start();
|
|
|
|
/** 线程安全拷贝最新快照(HTTP 用) */
|
|
void getSnapshot(CpuUsageSnapshot& out) const;
|
|
|
|
TaskHandle_t getTaskHandle() const { return m_taskHandle; }
|
|
|
|
private:
|
|
CpuStats() = default;
|
|
|
|
static void taskEntry(void* arg);
|
|
void sampleOnce();
|
|
|
|
mutable portMUX_TYPE m_mux = portMUX_INITIALIZER_UNLOCKED;
|
|
CpuUsageSnapshot m_published = {};
|
|
TaskHandle_t m_taskHandle = nullptr;
|
|
bool m_started = false;
|
|
|
|
/* 基线(仅采样任务写) */
|
|
struct TaskSample {
|
|
UBaseType_t task_number;
|
|
configRUN_TIME_COUNTER_TYPE runtime;
|
|
};
|
|
TaskSample m_lastSamples[CPU_TASK_SNAPSHOT_MAX] = {};
|
|
size_t m_lastCount = 0;
|
|
configRUN_TIME_COUNTER_TYPE m_lastTotal = 0;
|
|
int64_t m_lastTimeUs = 0;
|
|
bool m_hasLast = false;
|
|
};
|