970e574433
- CubeMX 加 TIM6(PSC=83 / ARR=999 / ARR 预装载 / NVIC 抢占优先级 6) - Src/main.c 回调加 TIM6 分支触发 CONVST(USER CODE 区) - app_main.c 用 HAL_TIM_Base_Start_IT(&htim6) 替换单次触发 - adc_task.c 退化为纯消费者(1 ms 轮询仅作消费节奏) - @build 0 错 0 警;台架 @test 验收待做 - 同步 ADC采样节拍设计说明 / 继电保护复现规划 / AGENTS / TPAFE README
134 lines
6.4 KiB
C
134 lines
6.4 KiB
C
/*
|
||
* 模块名称:ADC Sampling Task
|
||
* 模块功能:TPAFE5160 8 通道同步采样——帧消费 + 帧统计(节拍由 TIM6 硬件定时器提供)
|
||
* 状态说明:**B1 已落地(2026-10-10)**——本任务从空桩转为真实消费者:
|
||
* 用 tpafe5160_snapshot() 原子取数(AGENTS 铁律),统计帧数/无新帧次数,
|
||
* 并纳入看门狗 required_mask(TASK_WD_ADC)。
|
||
* **采样节拍(v2.2,2026-10-10)**:由 **TIM6 更新中断(1 kHz)** 硬件触发——
|
||
* ISR 内调 tpafe5160_start_conv_irq()(Src/main.c 的
|
||
* HAL_TIM_PeriodElapsedCallback);本任务**不再自行触发**,退化为**纯消费者**,
|
||
* 1ms 轮询(osDelayUntil)仅作消费节奏。详见
|
||
* docs/子系统设计/ADC采样节拍设计说明.md。
|
||
* 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
|
||
* v2.1 2026-10-10 王建锋 日志门控:首帧/周期统计仅在 dbg_console_writer_ready()
|
||
* 为真后落日志。写者未注册时控制台走无锁直发,与
|
||
* defaultTask 的存储初始化日志字节级交错(台架实测);
|
||
* 就绪前挂起上报,就绪后补报最近一帧。
|
||
* v2.2 2026-10-10 王建锋 采样节拍改由 TIM6 更新中断(1 kHz)硬件触发;本任务
|
||
* 删除自行触发,退化为纯消费者(见文件头"采样节拍")。
|
||
*/
|
||
|
||
#include "adc_task.h"
|
||
#include "cmsis_os.h"
|
||
#include "tpafe5160.h"
|
||
#include "task_watchdog.h"
|
||
#include "console_log.h"
|
||
|
||
#define DBG_TAG "[ADC_TASK]"
|
||
#include "dbg_log.h"
|
||
|
||
/* 消费轮询周期(ms)。采样节拍由 TIM6(1 kHz)提供,本周期仅作消费节奏 */
|
||
#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 原子快照取最新一帧并统计。采样节拍由 TIM6 硬件定时器提供
|
||
* (ISR 内触发 CONVST),本任务不再触发。稳态下 consumed 每拍 +1、
|
||
* idle 不再增长;idle 持续增长 = EXTI 未在读帧或 TIM6 未启动(异常),
|
||
* 由周期心跳日志暴露。
|
||
*/
|
||
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) 原子快照消费最新一帧(仅任务上下文;1=有新帧 0=无新帧 -1=参数错)。
|
||
* 采样节拍由 TIM6 更新中断提供(ISR 内触发 CONVST),本任务不触发。 */
|
||
r = tpafe5160_snapshot(s_frame, (uint8_t)TPAFE5160_CH_NUM);
|
||
if (r == 1) {
|
||
s_frames_consumed++;
|
||
} else if (r == 0) {
|
||
s_frames_idle++;
|
||
} else {
|
||
/* r == -1:参数错。调用点 count 为常量,不可达;不计入 idle 以区分异常 */
|
||
}
|
||
|
||
/* 2) 首帧码值上报:**写者就绪后**才落日志。写者未注册时 con_append 走
|
||
* 无锁直发路径,与 defaultTask 的存储初始化日志会字节级交错
|
||
* (2026-10-10 台架实测);此时挂起上报,就绪后补报最近一帧。
|
||
* 只报 TPAFE 三路(UA=buf[6] UN=buf[5] IA=buf[2]),验证取数契约 */
|
||
if ((first_logged == 0u) && (s_frames_consumed != 0u) &&
|
||
(dbg_console_writer_ready() != 0u)) {
|
||
first_logged = 1u;
|
||
DBG_INFO("first frame: UA=%d UN=%d IA=%d",
|
||
s_frame[6], s_frame[5], s_frame[2]);
|
||
}
|
||
|
||
/* 3) 看门狗心跳(本任务已纳入 required_mask) */
|
||
task_wd_beat(TASK_WD_ADC);
|
||
|
||
/* 4) 周期心跳日志:帧统计 + 驱动侧 FRSTDATA 错误计数。
|
||
* 写者就绪前抑制(同 2) 的交错理由);到点无论是否落日志都推进下个上报点 */
|
||
{
|
||
uint32_t now = osKernelGetTickCount();
|
||
|
||
if ((int32_t)(now - report_at) >= 0) {
|
||
if (dbg_console_writer_ready() != 0u) {
|
||
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);
|
||
}
|
||
}
|