Files
STM32F4-Base/App/task/adc_task.c
T
wandering1 883c9dd0cc 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 实机闭环。
2026-10-10 14:33:32 +08:00

119 lines
5.2 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 Sampling Task
* 模块功能: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 消费者前的强制门禁」+ 建任务前后各跑
* scripts/stack_report.py 做栈预算。
* 适用平台:STM32F407ZGTx + TPAFE5160
* 作者:王建锋
* 创建日期:2026-07-19
* 修改记录:
* 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_init() 已在 app_main_init()(内核启动前)完成
* 函数说明:驱动初始化不在本任务(见限定条件);此处仅清帧统计。
*/
int adc_task_init(void) {
s_frames_consumed = 0u;
s_frames_idle = 0u;
DBG_INFO("adc_task_init");
return 0;
}
/*
* 函数功能:ADC 任务主函数
* 入口参数:arg - FreeRTOS 传入参数(未使用)
* 返 回 值:无
* 限定条件:adc_task_init() 已调用;内核已启动
* 函数说明:每 1ms 触发一次 CONVST(采样节拍),随后原子快照取最新一帧并统计。
* 首拍无帧属正常(本次转换尚未完成);之后每拍消费上一拍触发的帧,
* 故稳态下 consumed 每拍 +1、idle 不再增长。idle 持续增长 = EXTI 未在
* 读帧(异常),由周期心跳日志暴露。
*/
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 (;;) {
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);
}
}