13a4e61c27
新增 App/algo/adc_health.c/h(纯逻辑判定层,零平台依赖免桩单测): - 静默:两侧帧序号连续 >=100ms 无前进(电平位可自愈,flags() 为 L5-4 闭锁预留) - 丢帧:TPAFE 序号一次前进 >1 计 tgap(与 STM32 侧 adc1_gap 对称,边沿事件) - 单调性:序号倒退锁存位;tick/计数差值法 (int32_t)(a-b) 回绕安全 - 错误增量:FRSTDATA / HAL 错误 / STM32 停摆计数增量,事件位与锁存位编号对齐, 消费者按位图做"每类每次开机留痕一次"编排 adc_task.c v2.9 告警编排(判定与编排分离):严重事件/电平上升沿 DBG_ERROR + SYSLOG_SELFTEST(每类每次开机一次防刷屏),下降沿 DBG_INFO 恢复;gap 不告警 (消费者超拍是已知现象,告警会淹没真故障);心跳行增 tgap 观测字段。 主机单测 test/host/adc_health/ 31 用例全绿(100ms 门限两侧 / 边沿语义 / 倒退锁存 / tick 回绕 / NULL 守卫 / init 幂等),登记 adc-health-unit-test 钩子。 台架 @test PASS:零 [ERR](健康不误报)、tgap=1->2 与 adc1_gap 同步可见、 frames 1000.0 Hz;证据 boot_log_data/20261011_prod_adc_health_boot_log.txt。 抬栈:adc_health_report->syslog_post 控制台回显尾使 adcTask 静态最坏链 832->1080 B(512 words 余 968 B < 1024 B ISR 底线)-> 512->640 words, 复测余 1480 B / 57%,堆 min_ever 7152->6640 B(-512 B 符合预算)。 AGENTS/README 任务表、RAM 方案 §2.3、规划文档 §3.1 L1-6 已同步置完成。
127 lines
6.1 KiB
C
127 lines
6.1 KiB
C
/*
|
||
* 模块名称:ADC 采样有效性校验(L1 采集与预处理,规划项 L1-6)
|
||
* 模块功能:对两片转换器的"节拍是否还在喂数据"做**判定层**(观测计数由
|
||
* `adc_input` / `tpafe5160` 驱动提供,本模块只做判定与告警位):
|
||
* ① 静默(stall):帧序号连续 >= ADC_HEALTH_STALL_MS 无前进;
|
||
* ② 丢帧(gap):帧序号一次前进 >1(消费者超拍,中间帧被覆盖);
|
||
* ③ 单调性破坏:帧序号倒退(计数器被改写 / 驱动 bug,锁存);
|
||
* ④ 错误计数增量:FRSTDATA 跳变 / HAL ADC·DMA 错误 / STM32 停摆计数。
|
||
* ⚠ 本层**纯逻辑**:不碰寄存器、不取数、不打日志——输入是调用方
|
||
* 采集的计数快照,输出是故障位;日志与自检上报由消费者
|
||
* (`App/task/adc_task.c`)按位执行 → 主机侧可单测(L0.5,A-4)。
|
||
* 适用平台:STM32F407ZGTx + TPAFE5160
|
||
* 作者:王建锋
|
||
* 创建日期:2026-10-11
|
||
* 修改记录:
|
||
* v1.0 2026-10-11 王建锋 创建:L1-6 采样有效性校验(静默/丢帧/单调性/错误增量)
|
||
*/
|
||
|
||
#ifndef ADC_HEALTH_H
|
||
#define ADC_HEALTH_H
|
||
|
||
#include <stdint.h>
|
||
|
||
#ifdef __cplusplus
|
||
extern "C" {
|
||
#endif
|
||
|
||
/* 静默判定门限(ms):帧序号连续无前进达到该时长即判静默。
|
||
* 名义节拍 1 kHz → 正常每拍 +1;100 拍无前进不可能是抖动,只可能是
|
||
* 节拍源/转换器/EXTI 真停(消费者超拍只会造成 gap=d>1,不会 d=0)。 */
|
||
#define ADC_HEALTH_STALL_MS 100U
|
||
|
||
/* 电平故障位(adc_health_flags(),当前活跃;stall 可自愈清除,backward 锁存)
|
||
* ——供后续 L5-4「自检失败闭锁」直接消费 */
|
||
#define ADC_HF_TPAFE_STALL (1uL << 0) /* TPAFE 帧序号静默 */
|
||
#define ADC_HF_STM32_STALL (1uL << 1) /* STM32 DMA 完成计数静默 */
|
||
#define ADC_HF_SEQ_BACKWARD (1uL << 2) /* 帧序号倒退(锁存,不自愈) */
|
||
|
||
/* 锁存故障位(adc_health_sticky(),出现过即置位、直到 init 才清;
|
||
* 与电平位共用高位编号,gap 类"常态性超拍"不入锁存) */
|
||
#define ADC_HF_FRSTDATA (1uL << 3) /* FRSTDATA 跳变计数有增量(锁存) */
|
||
#define ADC_HF_STM32_ERR (1uL << 4) /* STM32 停摆计数有增量(锁存) */
|
||
#define ADC_HF_HW_ERR (1uL << 5) /* HAL ADC/DMA 错误回调有增量(锁存) */
|
||
|
||
/* 边沿事件位(adc_health_check() 出参 events,仅本次调用有效)。
|
||
* ⚠ FRSTDATA/STM32_ERR/HW_ERR 三个事件位与同名锁存位**编号一致**——
|
||
* 消费者可直接用 events 掩码对 sticky/logged 位图做"每类留痕一次"的编排 */
|
||
#define ADC_HE_TPAFE_GAP (1uL << 6) /* 本次 TPAFE 序号前进 >1 */
|
||
#define ADC_HE_STM32_GAP (1uL << 7) /* 本次 STM32 gap 计数有增量 */
|
||
#define ADC_HE_STM32_ERR (1uL << 4) /* 本次 STM32 停摆计数有增量 */
|
||
#define ADC_HE_FRSTDATA (1uL << 3) /* 本次 FRSTDATA 计数有增量 */
|
||
#define ADC_HE_HW_ERR (1uL << 5) /* 本次 HAL 错误计数有增量 */
|
||
|
||
/* 计数快照(由调用方采集,本模块不触碰任何驱动/外设) */
|
||
typedef struct {
|
||
uint32_t tpafe_seq; /* tpafe5160_frame_seq() */
|
||
uint32_t tpafe_frst_err; /* tpafe5160_frstdata_err()(驱动为 uint16,此处放宽) */
|
||
uint32_t stm32_seq; /* adc_input_stm32_seq() */
|
||
uint32_t stm32_errs; /* adc_input_stm32_errs() */
|
||
uint32_t stm32_gaps; /* adc_input_stm32_gaps() */
|
||
uint32_t stm32_hw_errs; /* adc_input_stm32_hw_errs() */
|
||
uint32_t now_ms; /* osKernelGetTickCount()(tick 回绕由差值法吸收) */
|
||
} adc_health_in_t;
|
||
|
||
/* 判定结果快照 */
|
||
typedef struct {
|
||
uint32_t flags; /* 电平故障位 ADC_HF_TPAFE/STM32_STALL/SEQ_BACKWARD */
|
||
uint32_t events; /* 本次边沿事件位 ADC_HE_xxx */
|
||
uint32_t sticky; /* 锁存故障位(含电平位的历史并集) */
|
||
uint32_t tpafe_gaps; /* TPAFE 累计丢帧点数(序号前进 >1 的超出部分之和) */
|
||
uint32_t tpafe_stall_ms; /* TPAFE 当前静默时长(0=正常) */
|
||
} adc_health_status_t;
|
||
|
||
/*
|
||
* 函数功能:采样有效性校验初始化(幂等,内核启动前可调)
|
||
* 入口参数:无
|
||
* 返 回 值:无
|
||
* 限定条件:无
|
||
* 函数说明:清全部状态;首次 adc_health_check() 只建基线、不判定。
|
||
*/
|
||
void adc_health_init(void);
|
||
|
||
/*
|
||
* 函数功能:按计数快照做一次有效性判定(每拍调用,开销为常数次整数运算)
|
||
* 入口参数:in - 计数快照(NULL 则本次跳过,out 不动)
|
||
* out - 判定结果(NULL 则仅更新内部状态)
|
||
* 返 回 值:无
|
||
* 限定条件:仅任务上下文(与 adc_input_poll() 同节奏调用)
|
||
* 函数说明:首次调用建立基线(不产生事件/故障)。序号差值按
|
||
* `(int32_t)(now - prev)` 口径计算,tick/计数回绕均安全。
|
||
*/
|
||
void adc_health_check(const adc_health_in_t *in, adc_health_status_t *out);
|
||
|
||
/*
|
||
* 函数功能:读当前电平故障位
|
||
* 入口参数:无
|
||
* 返 回 值:ADC_HF_TPAFE_STALL / ADC_HF_STM32_STALL / ADC_HF_SEQ_BACKWARD 组合
|
||
* 限定条件:无
|
||
* 函数说明:供 L5-4 闭锁判定与 UI;与 check() 出参 flags 同源。
|
||
*/
|
||
uint32_t adc_health_flags(void);
|
||
|
||
/*
|
||
* 函数功能:读锁存故障位(出现过即置位,直到 init 才清)
|
||
* 入口参数:无
|
||
* 返 回 值:电平位 + ADC_HF_FRSTDATA/STM32_ERR/HW_ERR 的并集
|
||
* 限定条件:无
|
||
* 函数说明:stall 自愈后 sticky 仍保留该次故障痕迹("曾经停摆过"必须留痕)。
|
||
*/
|
||
uint32_t adc_health_sticky(void);
|
||
|
||
/*
|
||
* 函数功能:读 TPAFE 累计丢帧点数
|
||
* 入口参数:无
|
||
* 返 回 值:序号前进 >1 的超出部分累计(与 STM32 侧 adc_input_stm32_gaps() 对称)
|
||
* 限定条件:无
|
||
* 函数说明:消费者超拍(单拍耗时 > 1 ms)所致;非零本身不是闭锁条件,
|
||
* 但持续增长说明相量窗出现时间空洞,须排查耗时。
|
||
*/
|
||
uint32_t adc_health_tpafe_gaps(void);
|
||
|
||
#ifdef __cplusplus
|
||
}
|
||
#endif
|
||
|
||
#endif /* ADC_HEALTH_H */
|