- 将SPI OTA帧格式升级为SPI Link v2,采用新的帧格式: | SOF0 0xA5 | SOF1 0x5A | VER 0x02 | FLAGS | SESSION 4B LE | TX_SEQ | ACK_SEQ | CREDIT | TYPE | LEN 2B LE | RSV 2B | PAYLOAD | CRC32 4B LE | - 新增V2_OVERHEAD=20字节开销,APP最大payload为236字节,BOOT为108字节 - 修改帧类型定义:ENTER_BOOT从0xB5合并至0xB0,新增CAN业务类型0xC0~C3 - 更新CAN协议文档,支持SPI Link v2-only模式,调整最大业务payload计算 - 扩展0xC1帧功能,支持双向通信和1Hz主动推送ID快照 - 添加0xC3完整ID快照帧类型,包含seq/rx_count等完整字段 - 更新协议文档中的错误码定义和反馈payload格式 refactor(main): 重构主程序入口并添加CAN反馈任务 - 在main.cpp中添加CAN反馈任务,更新启动流程注释 - 创建createCriticalTask辅助函数,统一关键任务创建逻辑 - 调整SPI初始化顺序,确保CAN反馈任务依赖正确 - 优化错误处理机制,关键任务失败时立即重启 - 将GD32版本探测移至ota_relay任务处理 - 更新版本号至0.3.48,调整编译时间和Git哈希 config: 更新SPI和BLE配置参数 - 添加SPI主机相关配置参数,包括CS GPIO、READY GPIO等引脚定义 - 配置SPI缓冲区大小:APP为256字节,BOOT为128字节 - 更新BLE滑动窗口参数,ACK窗口设为32,数据队列深度为72 - 调整SPI工作队列大小至5120字节,增加任务堆栈监控说明
82 lines
2.4 KiB
C++
82 lines
2.4 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;
|
||
|
||
/** uxTaskGetSystemState 目标缓冲(固定、免每拍 calloc) */
|
||
TaskStatus_t m_taskStatusBuf[CPU_TASK_SNAPSHOT_MAX] = {};
|
||
|
||
/** 任务数截断 WARN 节流(tick) */
|
||
TickType_t m_lastTruncWarnTick = 0;
|
||
/** 运行时计数回绕 WARN 节流(tick) */
|
||
TickType_t m_lastWrapWarnTick = 0;
|
||
};
|