Files
STM32F4-Base/App/algo/adc_health.h
T
wandering1 13a4e61c27 L1-6 采样有效性校验:adc_health 判定层 + 告警编排 + 31 用例单测 + 台架闭环
新增 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 已同步置完成。
2026-10-11 01:28:20 +08:00

127 lines
6.1 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
* 模块名称: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 */