@@ -0,0 +1,463 @@
/*
* 模块名称:ADC 输入层(L1)主机侧单元测试
* 模块功能:在 PC 上对 App/algo/adc_input.c 做离线验证(6 个公开函数 + 2 个静态函数)。
*
* 被测对象:真实源文件 ../../../App/algo/adc_input.c(以 #include 原样纳入,
* 保证测的是生产代码而非副本)。平台依赖由本文件提供的**可注入桩**实现:
* - adc.h -> HAL_ADC_Start / PollForConversion / GetValue / Stop
* (可注入 启动失败 / 第 N 次轮询超时 / 逐 Rank 返回值)
* - tpafe5160.h-> tpafe5160_snapshot(可注入 新帧/无新帧/参数错 + 帧内容)
*
* 为什么要主机侧单测(而不是只用板端套件):
* 1. 本层核心是"**通道号 <-> Rank 顺序 <-> 语义**"三者的映射正确性。板端**无信号源**
* (见 docs/硬件平台/ADC通道映射说明.md §8),无法注入已知电压去验证"读到的是
* 哪只脚";主机侧可直接给每个 Rank 注入互不相同的码值,从而**逐通道钉死映射**
* (这是唯一能在离线端证伪"通道宏写错 -> 读到另一只脚"的手段)。
* 2. HAL 启动失败 / 转换超时 / 参数错等分支在真机上极难稳定复现,主机侧一次钉死。
* 3. 不占 MCU 的 RAM,毫秒级完成。
*
* 覆盖点(对应 docs/算法/继电保护功能复现规划.md §2.1 的 L1-3 / L1-4):
* —— adc_input_init( TC-AI-001..006)——
* TC-AI-001 poll 失败后失败计数可见(前置状态构造)
* TC-AI-002 poll 成功后 TPAFE 侧可取数(前置状态构造)
* TC-AI-003 init 返回 0(映射表自检通过)
* TC-AI-004 init 后 STM32 状态码 = NOT_RUN
* TC-AI-005 init 后失败计数归零
* TC-AI-006 init 后 TPAFE / STM32 两侧均无有效数据(有效标志被清)
* —— adc_input_desc( TC-AI-010..01A)——
* TC-AI-010..018 九个语义通道 -> (来源, 下标) 与权威映射表逐项一致
* TC-AI-019/01A 越界(ADC_SEM_COUNT)与负数语义 -> NULL
* —— map_check( TC-AI-020)——
* TC-AI-020 真实映射表自洽(反向路径结构上不可达,见文件末说明)
* —— stm32_scan( TC-AI-021..03A)——
* TC-AI-021..025 全通道成功:返回 0 / 状态码 / 不计失败 / Start-Stop 各一次 / 轮询 9 次
* TC-AI-026..02B **Rank -> 通道号映射**: UB->CH14(rank9) / UC->CH3(rank4) /
* IB->CH6(rank7) / IC->CH1(rank2) / IN->CH2(rank3) / TEMP->CH5(rank6)
* TC-AI-02C stm32_scan 不置 TPAFE 有效标志(两来源独立)
* TC-AI-030..034 HAL_ADC_Start 失败:返回 -1 / 状态码 RC_START / 计数 +1 / 不调 Stop
* TC-AI-035..039 轮询超时:返回 -2 / 状态码 RC_TIMEOUT / 计数 +1 / 调 Stop 收尾 / 立即退出
* TC-AI-03A 失败计数跨次单调累计
* —— adc_input_raw( TC-AI-040..04B)——
* TC-AI-040..043 参数守卫:out=NULL / 越界 / 负数 -> -1,且不写 out
* TC-AI-044/045 无有效数据 -> -2(两来源分别)
* TC-AI-046..048 poll 快照契约:返回码透传 / 请求 8 通道 / 目的缓冲非空
* TC-AI-049..04B TPAFE 按**下标**取数(UA=6 / UN=5 / IA=2)且补码负值原样保留
* —— adc_input_poll( TC-AI-050..058)——
* TC-AI-050..052 无新帧(0):返回 0 / TPAFE 无效 / STM32 侧照常扫描
* TC-AI-053/054 参数错(-1):返回 -1 / TPAFE 无效
* TC-AI-055 已有有效帧后再"无新帧"**不清零**(保持上次有效值)
* TC-AI-056..058 STM32 失败**不阻断** TPAFE、**不影响** poll 返回值,另由状态码暴露
* —— adc_input_stm32_rc / _errs( TC-AI-060..066)——
* TC-AI-060/061 init 后 = NOT_RUN / 计数 0
* TC-AI-062 成功: rc=OK 且 errs 不变
* TC-AI-063/064 两次失败累计 = 2, rc = 最近一次(TIMEOUT)
* TC-AI-065/066 恢复成功 rc=OK, errs 单调不回退
*
* 通过:全部 TC PASS( main 返回 0)。
* 入口:int main(void),返回 0=PASS / 1=FAIL(由 run 脚本判读)。
*
* 创建日期:2026-10-10
*/
# include <stddef.h>
# include <stdint.h>
# include <stdio.h>
/* ===================== 平台桩(先纳入,覆盖真实头) ===================== */
# include "adc.h"
# include "tpafe5160.h"
/* ===================== HAL ADC1 桩 =====================
* 被测代码经 HAL 只做四件事:启动、逐 Rank 轮询、读 DR、停止。桩把它们变成可注入:
* s_start_rc HAL_ADC_Start 返回值(注入启动失败)
* s_poll_fail_at PollForConversion 第几次(0 基)失败;-1 = 永不失败(注入超时)
* s_poll_vals[i] 第 i 个 Rank 读到的码值(默认 100+i,用于钉死 Rank->通道映射)
* s_poll_calls / s_rank_idx 轮询次数 / 取数次数(观测:超时后是否立即退出)
*/
static HAL_StatusTypeDef s_start_rc = HAL_OK ;
static int s_poll_fail_at = - 1 ;
static uint32_t s_poll_vals [ 16 ] ;
static int s_poll_calls = 0 ;
static int s_rank_idx = 0 ;
static int s_start_calls = 0 ;
static int s_stop_calls = 0 ;
/* 被测代码把 &hadc1 透传给 HAL 桩;桩不读其字段 */
ADC_HandleTypeDef hadc1 ;
HAL_StatusTypeDef HAL_ADC_Start ( ADC_HandleTypeDef * hadc ) {
( void ) hadc ;
s_start_calls + + ;
s_poll_calls = 0 ;
s_rank_idx = 0 ;
return s_start_rc ;
}
HAL_StatusTypeDef HAL_ADC_PollForConversion ( ADC_HandleTypeDef * hadc , uint32_t Timeout ) {
( void ) hadc ;
( void ) Timeout ;
{
int idx = s_poll_calls ;
s_poll_calls + + ;
if ( s_poll_fail_at > = 0 & & idx = = s_poll_fail_at ) {
return HAL_ERROR ;
}
}
return HAL_OK ;
}
uint32_t HAL_ADC_GetValue ( ADC_HandleTypeDef * hadc ) {
uint32_t v ;
( void ) hadc ;
v = ( s_rank_idx < 16 ) ? s_poll_vals [ s_rank_idx ] : 0u ;
s_rank_idx + + ;
return v ;
}
HAL_StatusTypeDef HAL_ADC_Stop ( ADC_HandleTypeDef * hadc ) {
( void ) hadc ;
s_stop_calls + + ;
return HAL_OK ;
}
/* ===================== TPAFE5160 快照桩 ===================== */
static int16_t s_fake_tpafe [ 8 ] ;
static int s_snapshot_rc = 0 ;
static int s_snapshot_calls = 0 ;
static uint8_t s_snapshot_count = 0u ;
static int16_t * s_snapshot_dst = NULL ;
int tpafe5160_snapshot ( int16_t * dst , uint8_t count ) {
uint8_t i ;
s_snapshot_calls + + ;
s_snapshot_count = count ;
s_snapshot_dst = dst ;
if ( s_snapshot_rc = = 1 ) {
for ( i = 0u ; ( i < count ) & & ( i < 8u ) ; i + + ) {
dst [ i ] = s_fake_tpafe [ i ] ;
}
}
return s_snapshot_rc ;
}
/* ===================== 断言 ===================== */
static int s_total = 0 , s_passed = 0 , s_failed = 0 ;
# define CHECK(cond, name) do { \
s_total++; \
if (cond) { s_passed++; printf(" [PASS] %s\n", name); } \
else { s_failed++; printf(" [FAIL] %s (line %d)\n", name, __LINE__); } \
} while (0)
/* ===================== 被测代码(原样纳入生产源) ===================== */
# include "adc_input.c"
/* ===================== 工具 ===================== */
/*
* 函数功能:把全部桩复位到"健康"初值
* 入口参数:无
* 返 回 值:无
* 限定条件:无
* 函数说明:默认 Start 成功、轮询永不超时、第 i 个 Rank 读到 100+i(互不相同,
* 以便逐通道钉死 Rank->通道号映射)、TPAFE 快照无新帧。
*/
static void fakes_reset ( void ) {
uint8_t i ;
s_start_rc = HAL_OK ;
s_poll_fail_at = - 1 ;
s_poll_calls = 0 ;
s_rank_idx = 0 ;
s_start_calls = 0 ;
s_stop_calls = 0 ;
for ( i = 0u ; i < 16u ; i + + ) {
s_poll_vals [ i ] = 100u + ( uint32_t ) i ;
}
s_snapshot_rc = 0 ;
s_snapshot_calls = 0 ;
s_snapshot_count = 0u ;
s_snapshot_dst = NULL ;
for ( i = 0u ; i < 8u ; i + + ) {
s_fake_tpafe [ i ] = 0 ;
}
}
/* ===================== TC-AI-001..006: init ===================== */
static void tc_init ( void ) {
int32_t v = - 999 ;
fakes_reset ( ) ;
/* 前置:制造"STM32 失败一次 + TPAFE 有效一帧"的状态,再验 init 是否清干净 */
s_snapshot_rc = 1 ;
s_fake_tpafe [ 6 ] = 4321 ;
s_start_rc = HAL_ERROR ;
( void ) adc_input_poll ( ) ;
CHECK ( adc_input_stm32_errs ( ) = = 1u , " TC-AI-001 poll 失败后 STM32 失败计数 = 1 " ) ;
CHECK ( ( adc_input_raw ( ADC_SEM_UA , & v ) = = 0 ) & & ( v = = 4321 ) ,
" TC-AI-002 poll 后 UA 可取数且值正确 " ) ;
CHECK ( adc_input_init ( ) = = 0 , " TC-AI-003 adc_input_init 返回 0(映射自检通过) " ) ;
CHECK ( adc_input_stm32_rc ( ) = = ADC_INPUT_RC_NOT_RUN ,
" TC-AI-004 init 后 STM32 状态码 = NOT_RUN " ) ;
CHECK ( adc_input_stm32_errs ( ) = = 0u , " TC-AI-005 init 后 STM32 失败计数归零 " ) ;
CHECK ( ( adc_input_raw ( ADC_SEM_UA , & v ) = = - 2 ) & & ( adc_input_raw ( ADC_SEM_UB , & v ) = = - 2 ) ,
" TC-AI-006 init 后 TPAFE / STM32 两侧均无有效数据 " ) ;
}
/* ===================== TC-AI-010..01A: desc 映射表 ===================== */
static void tc_desc ( void ) {
const adc_channel_desc_t * d ;
d = adc_input_desc ( ADC_SEM_UA ) ;
CHECK ( ( d ! = NULL ) & & ( d - > source = = ADC_SRC_TPAFE ) & & ( d - > index = = 6u ) ,
" TC-AI-010 UA -> TPAFE buf[6] " ) ;
d = adc_input_desc ( ADC_SEM_UB ) ;
CHECK ( ( d ! = NULL ) & & ( d - > source = = ADC_SRC_STM32 ) & & ( d - > index = = 14u ) ,
" TC-AI-011 UB -> STM32 CH14 " ) ;
d = adc_input_desc ( ADC_SEM_UC ) ;
CHECK ( ( d ! = NULL ) & & ( d - > source = = ADC_SRC_STM32 ) & & ( d - > index = = 3u ) ,
" TC-AI-012 UC -> STM32 CH3 " ) ;
d = adc_input_desc ( ADC_SEM_UN ) ;
CHECK ( ( d ! = NULL ) & & ( d - > source = = ADC_SRC_TPAFE ) & & ( d - > index = = 5u ) ,
" TC-AI-013 UN -> TPAFE buf[5] " ) ;
d = adc_input_desc ( ADC_SEM_IA ) ;
CHECK ( ( d ! = NULL ) & & ( d - > source = = ADC_SRC_TPAFE ) & & ( d - > index = = 2u ) ,
" TC-AI-014 IA -> TPAFE buf[2] " ) ;
d = adc_input_desc ( ADC_SEM_IB ) ;
CHECK ( ( d ! = NULL ) & & ( d - > source = = ADC_SRC_STM32 ) & & ( d - > index = = 6u ) ,
" TC-AI-015 IB -> STM32 CH6 " ) ;
d = adc_input_desc ( ADC_SEM_IC ) ;
CHECK ( ( d ! = NULL ) & & ( d - > source = = ADC_SRC_STM32 ) & & ( d - > index = = 1u ) ,
" TC-AI-016 IC -> STM32 CH1 " ) ;
d = adc_input_desc ( ADC_SEM_IN ) ;
CHECK ( ( d ! = NULL ) & & ( d - > source = = ADC_SRC_STM32 ) & & ( d - > index = = 2u ) ,
" TC-AI-017 IN -> STM32 CH2 " ) ;
d = adc_input_desc ( ADC_SEM_TEMP ) ;
CHECK ( ( d ! = NULL ) & & ( d - > source = = ADC_SRC_STM32 ) & & ( d - > index = = 5u ) ,
" TC-AI-018 TEMP -> STM32 CH5 " ) ;
CHECK ( adc_input_desc ( ADC_SEM_COUNT ) = = NULL , " TC-AI-019 越界(ADC_SEM_COUNT) -> NULL " ) ;
CHECK ( adc_input_desc ( ( adc_semantic_t ) ( - 1 ) ) = = NULL , " TC-AI-01A 负数语义 -> NULL " ) ;
}
/* ===================== TC-AI-020: map_check ===================== */
static void tc_map_check ( void ) {
/* 真实映射表自洽:TPAFE 下标 < 8 且每个 STM32 通道号都出现在扫描 Rank 内。
* 反向路径(表不自洽 -> -1)需在运行时改表,而 k_adc_map / k_stm32_rank_ch 均为
* 编译期 static const、无运行时输入可使其不自洽 -> 结构上不可达(见文件末说明)。 */
CHECK ( map_check ( ) = = 0 , " TC-AI-020 映射表自洽(TPAFE 下标与 STM32 Rank 均在范围内) " ) ;
}
/* ===================== TC-AI-021..02C: stm32_scan 成功路径 ===================== */
static void tc_scan_ok ( void ) {
int32_t v = 0 ;
fakes_reset ( ) ;
( void ) adc_input_init ( ) ;
CHECK ( stm32_scan ( ) = = ADC_INPUT_RC_OK , " TC-AI-021 stm32_scan 全通道成功 -> 0 " ) ;
CHECK ( adc_input_stm32_rc ( ) = = ADC_INPUT_RC_OK , " TC-AI-022 状态码 = RC_OK " ) ;
CHECK ( adc_input_stm32_errs ( ) = = 0u , " TC-AI-023 成功不计入失败 " ) ;
CHECK ( ( s_start_calls = = 1 ) & & ( s_stop_calls = = 1 ) , " TC-AI-024 Start / Stop 各一次 " ) ;
CHECK ( ( s_poll_calls = = ( int ) ADC_INPUT_STM32_CH_NUM ) & & ( s_rank_idx = = ( int ) ADC_INPUT_STM32_CH_NUM ) ,
" TC-AI-025 轮询与取数各 9 次(Rank1..9) " ) ;
/* Rank -> 通道号映射:第 i 个 Rank 读到 100+i。
* k_stm32_rank_ch = [CH0..CH7, CH14],故 CH3->103 / CH5->105 / CH6->106 / CH14->108。 */
CHECK ( ( adc_input_raw ( ADC_SEM_UB , & v ) = = 0 ) & & ( v = = 108 ) , " TC-AI-026 UB 取到 CH14(rank9)=108 " ) ;
CHECK ( ( adc_input_raw ( ADC_SEM_UC , & v ) = = 0 ) & & ( v = = 103 ) , " TC-AI-027 UC 取到 CH3(rank4)=103 " ) ;
CHECK ( ( adc_input_raw ( ADC_SEM_IB , & v ) = = 0 ) & & ( v = = 106 ) , " TC-AI-028 IB 取到 CH6(rank7)=106 " ) ;
CHECK ( ( adc_input_raw ( ADC_SEM_IC , & v ) = = 0 ) & & ( v = = 101 ) , " TC-AI-029 IC 取到 CH1(rank2)=101 " ) ;
CHECK ( ( adc_input_raw ( ADC_SEM_IN , & v ) = = 0 ) & & ( v = = 102 ) , " TC-AI-02A IN 取到 CH2(rank3)=102 " ) ;
CHECK ( ( adc_input_raw ( ADC_SEM_TEMP , & v ) = = 0 ) & & ( v = = 105 ) , " TC-AI-02B TEMP 取到 CH5(rank6)=105 " ) ;
CHECK ( adc_input_raw ( ADC_SEM_UA , & v ) = = - 2 , " TC-AI-02C stm32_scan 不置 TPAFE 有效标志 " ) ;
}
/* ===================== TC-AI-030..034: stm32_scan 启动失败 ===================== */
static void tc_scan_start_fail ( void ) {
int32_t v = 0 ;
fakes_reset ( ) ;
( void ) adc_input_init ( ) ;
s_start_rc = HAL_ERROR ;
CHECK ( stm32_scan ( ) = = ADC_INPUT_RC_START , " TC-AI-030 HAL_ADC_Start 失败 -> -1 " ) ;
CHECK ( adc_input_stm32_rc ( ) = = ADC_INPUT_RC_START , " TC-AI-031 状态码 = RC_START " ) ;
CHECK ( adc_input_stm32_errs ( ) = = 1u , " TC-AI-032 失败计数 +1 " ) ;
CHECK ( s_stop_calls = = 0 , " TC-AI-033 启动失败不调用 Stop " ) ;
CHECK ( adc_input_raw ( ADC_SEM_UB , & v ) = = - 2 , " TC-AI-034 启动失败后 STM32 侧仍无有效数据 " ) ;
}
/* ===================== TC-AI-035..03A: stm32_scan 轮询超时 ===================== */
static void tc_scan_timeout ( void ) {
int32_t v = 0 ;
fakes_reset ( ) ;
( void ) adc_input_init ( ) ;
s_poll_fail_at = 4 ; /* 第 5 个 Rank 轮询超时 */
CHECK ( stm32_scan ( ) = = ADC_INPUT_RC_TIMEOUT , " TC-AI-035 轮询超时 -> -2 " ) ;
CHECK ( adc_input_stm32_rc ( ) = = ADC_INPUT_RC_TIMEOUT , " TC-AI-036 状态码 = RC_TIMEOUT " ) ;
CHECK ( adc_input_stm32_errs ( ) = = 1u , " TC-AI-037 超时计入失败 " ) ;
CHECK ( s_stop_calls = = 1 , " TC-AI-038 超时前已 Start -> 调 Stop 收尾 " ) ;
CHECK ( s_poll_calls = = 5 , " TC-AI-039 超时后立即退出(只轮询 5 次) " ) ;
CHECK ( adc_input_raw ( ADC_SEM_UB , & v ) = = - 2 , " TC-AI-039b 超时后 STM32 侧无有效数据 " ) ;
s_poll_fail_at = 0 ; /* 再失败一次 */
( void ) stm32_scan ( ) ;
CHECK ( adc_input_stm32_errs ( ) = = 2u , " TC-AI-03A 失败计数跨次单调累计 = 2 " ) ;
}
/* ===================== TC-AI-040..045: raw 参数守卫与无数据 ===================== */
static void tc_raw_guards ( void ) {
int32_t v = 0 ;
fakes_reset ( ) ;
( void ) adc_input_init ( ) ;
CHECK ( adc_input_raw ( ADC_SEM_UA , NULL ) = = - 1 , " TC-AI-040 out=NULL -> -1 " ) ;
CHECK ( adc_input_raw ( ADC_SEM_COUNT , & v ) = = - 1 , " TC-AI-041 ch 越界 -> -1 " ) ;
CHECK ( adc_input_raw ( ( adc_semantic_t ) ( - 1 ) , & v ) = = - 1 , " TC-AI-042 ch 负数 -> -1 " ) ;
CHECK ( v = = 0 , " TC-AI-043 参数错时不写 out " ) ;
CHECK ( adc_input_raw ( ADC_SEM_UA , & v ) = = - 2 , " TC-AI-044 TPAFE 无有效帧 -> -2 " ) ;
CHECK ( adc_input_raw ( ADC_SEM_UB , & v ) = = - 2 , " TC-AI-045 STM32 无有效扫描 -> -2 " ) ;
}
/* ===================== TC-AI-046..04B: raw TPAFE 取数与补码 ===================== */
static void tc_raw_tpafe ( void ) {
int32_t v = 0 ;
fakes_reset ( ) ;
( void ) adc_input_init ( ) ;
/* 注入 8 路 TPAFE 码值(互不相同),UA 应取 buf[6] / UN 取 buf[5] / IA 取 buf[2] */
s_fake_tpafe [ 0 ] = 1000 ;
s_fake_tpafe [ 1 ] = 1001 ;
s_fake_tpafe [ 2 ] = - 1234 ;
s_fake_tpafe [ 3 ] = 1003 ;
s_fake_tpafe [ 4 ] = 1004 ;
s_fake_tpafe [ 5 ] = 2005 ;
s_fake_tpafe [ 6 ] = 3006 ;
s_fake_tpafe [ 7 ] = 1007 ;
s_snapshot_rc = 1 ;
CHECK ( adc_input_poll ( ) = = 1 , " TC-AI-046 poll 透传 TPAFE 快照码 1 " ) ;
CHECK ( s_snapshot_count = = ( uint8_t ) ADC_INPUT_TPAFE_CH_NUM , " TC-AI-047 快照请求 8 通道 " ) ;
CHECK ( s_snapshot_dst ! = NULL , " TC-AI-048 快照目的缓冲非空 " ) ;
CHECK ( ( adc_input_raw ( ADC_SEM_UA , & v ) = = 0 ) & & ( v = = 3006 ) , " TC-AI-049 UA -> buf[6]=3006 " ) ;
CHECK ( ( adc_input_raw ( ADC_SEM_UN , & v ) = = 0 ) & & ( v = = 2005 ) , " TC-AI-04A UN -> buf[5]=2005 " ) ;
CHECK ( ( adc_input_raw ( ADC_SEM_IA , & v ) = = 0 ) & & ( v = = - 1234 ) ,
" TC-AI-04B IA -> buf[2]=-1234(补码负值原样保留) " ) ;
}
/* ===================== TC-AI-050..058: poll 契约 ===================== */
static void tc_poll ( void ) {
int32_t v = 0 ;
/* --- 无新帧(0):返回 0, TPAFE 无效,STM32 侧照常扫描 --- */
fakes_reset ( ) ;
( void ) adc_input_init ( ) ;
s_snapshot_rc = 0 ;
CHECK ( adc_input_poll ( ) = = 0 , " TC-AI-050 快照无新帧 -> poll 返回 0 " ) ;
CHECK ( adc_input_raw ( ADC_SEM_UA , & v ) = = - 2 , " TC-AI-051 无新帧时 TPAFE 侧无效 " ) ;
CHECK ( adc_input_stm32_rc ( ) = = ADC_INPUT_RC_OK , " TC-AI-052 同拍 STM32 扫描照常执行 " ) ;
/* --- 参数错(-1):返回 -1, TPAFE 无效 --- */
fakes_reset ( ) ;
( void ) adc_input_init ( ) ;
s_snapshot_rc = - 1 ;
CHECK ( adc_input_poll ( ) = = - 1 , " TC-AI-053 快照参数错 -> poll 返回 -1 " ) ;
CHECK ( adc_input_raw ( ADC_SEM_UA , & v ) = = - 2 , " TC-AI-054 参数错时 TPAFE 侧无效 " ) ;
/* --- 已有有效帧后再"无新帧":保持上次有效值(不清零) --- */
fakes_reset ( ) ;
( void ) adc_input_init ( ) ;
s_fake_tpafe [ 6 ] = 777 ;
s_snapshot_rc = 1 ;
( void ) adc_input_poll ( ) ;
s_snapshot_rc = 0 ;
( void ) adc_input_poll ( ) ;
CHECK ( ( adc_input_raw ( ADC_SEM_UA , & v ) = = 0 ) & & ( v = = 777 ) ,
" TC-AI-055 已有有效帧后无新帧不清零 " ) ;
/* --- STM32 失败不阻断 TPAFE、不影响 poll 返回值 --- */
fakes_reset ( ) ;
( void ) adc_input_init ( ) ;
s_fake_tpafe [ 2 ] = 55 ;
s_snapshot_rc = 1 ;
s_start_rc = HAL_ERROR ;
CHECK ( adc_input_poll ( ) = = 1 , " TC-AI-056 STM32 失败不影响 poll 返回值(仍为 1) " ) ;
CHECK ( ( adc_input_raw ( ADC_SEM_IA , & v ) = = 0 ) & & ( v = = 55 ) ,
" TC-AI-057 STM32 失败不影响 TPAFE 取数 " ) ;
CHECK ( adc_input_stm32_rc ( ) = = ADC_INPUT_RC_START , " TC-AI-058 STM32 失败另由状态码暴露 " ) ;
}
/* ===================== TC-AI-060..066: rc / errs 观测 ===================== */
static void tc_rc_errs ( void ) {
fakes_reset ( ) ;
( void ) adc_input_init ( ) ;
CHECK ( adc_input_stm32_rc ( ) = = ADC_INPUT_RC_NOT_RUN , " TC-AI-060 init 后未扫描 = NOT_RUN(-3) " ) ;
CHECK ( adc_input_stm32_errs ( ) = = 0u , " TC-AI-061 init 后失败计数 = 0 " ) ;
( void ) stm32_scan ( ) ; /* 成功 */
CHECK ( ( adc_input_stm32_rc ( ) = = ADC_INPUT_RC_OK ) & & ( adc_input_stm32_errs ( ) = = 0u ) ,
" TC-AI-062 成功: rc=OK 且 errs 不变 " ) ;
s_start_rc = HAL_ERROR ;
( void ) stm32_scan ( ) ; /* 失败 1 */
s_start_rc = HAL_OK ;
s_poll_fail_at = 0 ;
( void ) stm32_scan ( ) ; /* 失败 2 */
CHECK ( adc_input_stm32_errs ( ) = = 2u , " TC-AI-063 两次失败累计 = 2 " ) ;
CHECK ( adc_input_stm32_rc ( ) = = ADC_INPUT_RC_TIMEOUT , " TC-AI-064 rc = 最近一次(TIMEOUT) " ) ;
s_poll_fail_at = - 1 ;
( void ) stm32_scan ( ) ; /* 恢复成功 */
CHECK ( adc_input_stm32_rc ( ) = = ADC_INPUT_RC_OK , " TC-AI-065 恢复成功后 rc=OK " ) ;
CHECK ( adc_input_stm32_errs ( ) = = 2u , " TC-AI-066 errs 单调递增(不因成功回落) " ) ;
}
/* ===================== main ===================== */
int main ( void ) {
printf ( " === ADC Input Tests === \n " ) ;
printf ( " -- init / reset -- \n " ) ;
tc_init ( ) ;
printf ( " -- semantic map desc -- \n " ) ;
tc_desc ( ) ;
printf ( " -- map self-check -- \n " ) ;
tc_map_check ( ) ;
printf ( " -- stm32 scan: success + rank/channel mapping -- \n " ) ;
tc_scan_ok ( ) ;
printf ( " -- stm32 scan: HAL_ADC_Start fail -- \n " ) ;
tc_scan_start_fail ( ) ;
printf ( " -- stm32 scan: poll timeout -- \n " ) ;
tc_scan_timeout ( ) ;
printf ( " -- raw: guards / no-data -- \n " ) ;
tc_raw_guards ( ) ;
printf ( " -- raw: tpafe index + two's complement -- \n " ) ;
tc_raw_tpafe ( ) ;
printf ( " -- poll contract -- \n " ) ;
tc_poll ( ) ;
printf ( " -- rc / errs observability -- \n " ) ;
tc_rc_errs ( ) ;
printf ( " \n === ADC Input Tests: %d/%d PASSED (failed=%d) === \n " ,
s_passed , s_total , s_failed ) ;
return ( s_failed = = 0 ) ? 0 : 1 ;
}