feat(adc): B1 实现 ADC 采集链路(adcTask + 看门狗)

B1(ADC 采集链路)落地,消化 P1-1:
- adc_task.c:空桩 -> 真实消费者。每 1ms 触发一次 CONVST,
  用 tpafe5160_snapshot() 原子取数(AGENTS 铁律)+ 帧统计 +
  每 10s 心跳日志。只取数,不做保护运算。
- Src/freertos.c:手工创建 adcTask(512 words / Normal,落
  USER CODE 保护区,同 timeSyncTask 先例)。
- task_watchdog:新增 TASK_WD_ADC;required_mask 产品 0x37 ->
  0x77、ENABLE_HW_LAYER_TESTS 0x35 -> 0x75。
- default_task.c:栈水位探针增列 adcTask(extern + 表项)。
- 脚本:stack_report.py 增 ROOTS/RUNTIME_ALIAS;gen_task_table
  增 adcTask(README/AGENTS 任务表已 --write)。
- 单测:watchdog_test.c beat_all/掩码断言同步(39 断言全绿)。
- 文档:待处理内容/看门狗设计/RAM 方案/继保规划 同步。

验证:@build 0 错 0 警;stack_report 静态最坏链 504B(余 75%);
pre-commit 全绿。剩 @test 实机闭环。
This commit is contained in:
2026-10-10 14:33:32 +08:00
parent dee6233d50
commit 883c9dd0cc
16 changed files with 165 additions and 58 deletions
+77 -12
View File
@@ -1,11 +1,13 @@
/*
* 模块名称:ADC Sampling Task
* 模块功能:TPAFE5160 8 通道同步采样,数据缓存与通知
* 状态说明:**预留桩(未启用)**——采集链路尚未实现,产品定义未定
* (见 docs/待处理内容.md 阶段 B0/B1)。当前 init/func 为空实现,
* 不触发 CONVST、不消费数据。
* 2026-10-10 起本文件已挂进 MDK-ARM 工程(此前两边都不注册 = 永不编译,
* 改它不生效),但仍未在 Src/freertos.c 创建任务。
* 模块功能:TPAFE5160 8 通道同步采样——1ms 采样节拍 + 原子快照消费 + 帧统计
* 状态说明:**B1 已落地(2026-10-10)**——本任务从空桩转为真实消费者:
* 每 1ms 触发一次 CONVST,用 tpafe5160_snapshot() 原子取数(AGENTS 铁律),
* 统计帧数/无新帧次数,并纳入看门狗 required_mask(TASK_WD_ADC)。
* ⚠ B1 阶段用**任务周期软触发**(osDelayUntil)产生采样节拍,满足 L1-1
* 判据(BUSY 连续脉冲 + frame_seq 持续递增);**精确 1 kHz / 等周波调频**
* 的硬件定时器触发为后续(需 CubeMX 加 TIM)。
* V0.1 上只有 TPAFE 三路(UA/UN/IA)测量有效;本任务只取数,不做保护运算。
* 接入前必读:取数只用 tpafe5160_snapshot()(临界区原子快照,仅任务上下文;
* 旧的 get_buf/data_ready/clear_ready 已删除);接消费者前的强制门禁
* 见根 AGENTS.md「接 ADC / RS-485 消费者前的强制门禁」+ 建任务前后各跑
@@ -16,23 +18,39 @@
* 修改记录:
* v1.0 2026-07-19 王建锋 创建初始版本
* v1.1 2026-10-05 王建锋 P3-11:注明"预留桩(未启用)",避免误认为已实现
* v2.0 2026-10-10 王建锋 B1:实现真实消费者(1ms 节拍 + 原子快照 + 帧统计 +
* 看门狗心跳),由 Src/freertos.c 创建为 adcTask
*/
#include "adc_task.h"
#include "cmsis_os.h"
#include "tpafe5160.h"
#include "task_watchdog.h"
#define DBG_TAG "[ADC_TASK]"
#include "dbg_log.h"
/* 采样节拍周期(ms)。B1:任务周期软触发;硬件定时器方案见文件头说明 */
#define ADC_TASK_BEAT_MS 1U
/* 心跳日志周期(ms):周期性上报帧统计,作为采集链路存活的观测面 */
#define ADC_TASK_REPORT_MS 10000U
/* 最新一帧原始码值(8 通道;语义映射见 docs/硬件平台/ADC通道映射说明.md) */
static int16_t s_frame[TPAFE5160_CH_NUM];
/* 统计:已消费帧数 / 无新帧次数(首拍必为无新帧,之后应稳定为 0 增量) */
static uint32_t s_frames_consumed;
static uint32_t s_frames_idle;
/*
* 函数功能:ADC 任务初始化
* 入口参数:无
* 返 回 值:0 - 成功,-1 - 失败
* 限定条件:TPAFE5160 硬件已上电
* 函数说明:配置采样参数,准备数据缓冲区
* 限定条件:tpafe5160_init() 已在 app_main_init()(内核启动前)完成
* 函数说明:驱动初始化不在本任务(见限定条件);此处仅清帧统计。
*/
int adc_task_init(void) {
s_frames_consumed = 0u;
s_frames_idle = 0u;
DBG_INFO("adc_task_init");
return 0;
}
@@ -41,13 +59,60 @@ int adc_task_init(void) {
* 函数功能:ADC 任务主函数
* 入口参数:arg - FreeRTOS 传入参数(未使用)
* 返 回 值:无
* 限定条件:adc_task_init() 已成功调用
* 函数说明:定时触发 TPAFE5160 同步采样并处理数据
* 限定条件:adc_task_init() 已调用;内核已启动
* 函数说明:每 1ms 触发一次 CONVST(采样节拍),随后原子快照取最新一帧并统计。
* 首拍无帧属正常(本次转换尚未完成);之后每拍消费上一拍触发的帧,
* 故稳态下 consumed 每拍 +1、idle 不再增长。idle 持续增长 = EXTI 未在
* 读帧(异常),由周期心跳日志暴露。
*/
void adc_task_func(void const *arg) {
void adc_task_func(void *arg) {
uint32_t next = osKernelGetTickCount();
uint32_t report_at = next + ADC_TASK_REPORT_MS;
uint8_t first_logged = 0u;
(void)arg;
for (;;) {
osDelay(1000);
int r;
/* 1) 采样节拍:触发一次 CONVST(B1:任务周期软触发) */
tpafe5160_start_conv_irq();
/* 2) 原子快照消费最新一帧(仅任务上下文;1=有新帧 0=无新帧 -1=参数错) */
r = tpafe5160_snapshot(s_frame, (uint8_t)TPAFE5160_CH_NUM);
if (r == 1) {
s_frames_consumed++;
if (first_logged == 0u) {
first_logged = 1u;
/* 只报 TPAFE 三路(UA=buf[6] UN=buf[5] IA=buf[2]),验证取数契约 */
DBG_INFO("first frame: UA=%d UN=%d IA=%d",
s_frame[6], s_frame[5], s_frame[2]);
}
} else if (r == 0) {
s_frames_idle++;
} else {
/* r == -1:参数错。调用点 count 为常量,不可达;不计入 idle 以区分异常 */
}
/* 3) 看门狗心跳(本任务已纳入 required_mask) */
task_wd_beat(TASK_WD_ADC);
/* 4) 周期心跳日志:帧统计 + 驱动侧 FRSTDATA 错误计数 */
{
uint32_t now = osKernelGetTickCount();
if ((int32_t)(now - report_at) >= 0) {
DBG_INFO("frames=%lu idle=%lu seq=%lu frst_err=%u",
(unsigned long)s_frames_consumed,
(unsigned long)s_frames_idle,
(unsigned long)tpafe5160_frame_seq(),
(unsigned)tpafe5160_frstdata_err());
report_at = now + ADC_TASK_REPORT_MS;
}
}
/* 5) 等下一个节拍(固定周期;落后则立即补齐,不累积漂移) */
next += ADC_TASK_BEAT_MS;
(void)osDelayUntil(next);
}
}