feat(ui+记录): 整定写路径与四类页落地,五类记录写入方补齐
UI 面:ui_data 增加深度 4 参数写队列(请求 168 B、队列 .bss 672 B)与状态机 OK/ERR_RANGE/ERR_LOCKED/ERR_BUSY,ui_data_feed 出队后按注入 ops 走「闭锁 → 整批 预检 → 逐项 prot_set_set_sealed」,只提交改动位图;par 帧尾追加 cal_block (口径 = UA/UN/IA 三路 ADC_CAL_F_VALID,与 protect_task 判据同构,不用 rt.eng 反推,V0.1 下 eng 恒 0)、UI_DATA_VER 升到 2。参数/定值/控制字/软压板四叶绑定 内容页(UI_PAGE_MAP_COUNT 12→16,复用四个查看模块,零新增 .c),编辑态按 is_editable 分派,LOCK(写不进去)与「未标定」(仍可改值)两源两通道两词。 记录面:syslog_request_clear/state/apply 三段式删除 API(UI 只发请求,落地在 defaultTask 的 drain 尾部且必须后置,卷锁一律 try,幂等只认 FR_NO_FILE); 事故/告警/启动/操作/遥控五类各有一个真实写入点,记录类型 = 日志 ID 本身 (一类一个 /log 严格 8.3 文件;64B 定长体没有类型字段位,塞字段会砸掉既有读者)。 为守 protectTask 872 B 静态最坏链另拆 syslog_post_quiet()(无 DBG 的投递核, 丢弃留痕挪到 drain 侧差值补发),syslog_post 对外语义逐字不变。 为什么两道合成一笔而不是各一笔(实测,不是省事):simulator/main.c 同时消费 两道新增 API(整定 pump 与 logtest 清除用例),按道切文件会让中间提交编不过; RAM 受管快照与体积同码凭证描述的是合并后的 .map,拆开必落在「台账与 .map 不同 码」这条红线上。pre-commit 跑钩子前会 stash 未 staged 部分,这类耦合没法绕。 实测:@build 0 错误 0 警告;Code 228,260 / RO 24,960 / RW 1,440 / ZI 135,976 B; RW_IRAM1 79,992 B = 61.0%、RW_CCM 87.9%(阈值 92%);九个任务静态最坏链全 PASS, protectTask 872 B / 57% 改前后逐字节不变(记录投递没垫栈)。主机单测 ui_data 82→ 164、sys_log_mcu 106→137、prot_elm 47→60、iec104 141→154、iec104_serv 28→34, 既有断言零删改;48 个钩子 --all-files 全绿;编号门禁可判定 86.34%(基线 86.0%)、 不可判定 1,153 处低于上限 1,166;doc-links 无法判定 0;UI 黄金 18 页扩到 27 页 连跑两次逐字节一致;字库 diff 空。 顺手修掉三处既有缺陷(都是本轮第一个消费者才暴露):sim_syslog.c 的 s_paths 行宽 16 而 "sim_selftest.log" 正好 16 字符没有 NUL 位(stat/remove 读越过数组尾,此前 靠后面 .rodata 碰巧为 0);ui_w_setlist 二态行 ENTER 不回绕(控制字与软压板出厂值 全在最后一项,按了像没反应而叠层里已是越界值);生成物 ui_menu_tab.h 与 gen_menu.py 模板漂移(上一笔改了模板没重跑生成器),现随生成器输出对齐。 未收口(不算完成):保存后重启值保持与主站 C_RD 读回两条只能上板,台架窗口执行; LOCK 屏显与越界反显的页面侧在模拟器造不出来(模拟器不跑定值自检、无 NAND), 已由生成侧单测与代码注释点名差距;同类页数与钩子数陈述残留另立待办。
This commit is contained in:
@@ -24,6 +24,11 @@
|
||||
* TC-IEC104-011 t2 到期发 S
|
||||
* TC-IEC104-012 t3 空闲发 TESTFR act;未答 t1 超时 → IDLE;con 清挂起不误杀
|
||||
* TC-IEC104-013 遥控两段式:选择/执行成功;失配 PN;拒绝类选择段即 PN
|
||||
* TC-IEC104-030 遥控 / 操作记录投递(道F task-10 的 104 侧写入点):未知 IOA、
|
||||
* YK11 选择与执行、YK12 选择 / 执行 / 非法 DPC 各投哪一类哪一句,外加
|
||||
* "拒绝不投操作记录""记录与压板实际状态一致""文案不超 28 字节"三条会
|
||||
* 静默变坏但台架看不出的点(YK12 的 set_sealed 失败腿不可达,理由写在
|
||||
* 该用例注释里,没有为它伪造定值范围)
|
||||
* TC-IEC104-014 定值两段写(真实 prot_set):越界 PN;执行后 get_f + selfcheck
|
||||
* TC-IEC104-015 C_RD:YC 命中 / 定值命中 / 未知 IOA COT14+EVI
|
||||
* TC-IEC104-016 C_CS:clock_sync 收正确 epoch;IV → PN;clock_sync 失败 → PN
|
||||
@@ -148,6 +153,65 @@ void syslog_post(syslog_id_t id, const char *desc) {
|
||||
rp_s_syslog_count++;
|
||||
}
|
||||
|
||||
/* ---- syslog_post_quiet 桩:记下投了什么(task-10 遥控 / 操作记录用) ----
|
||||
* 真机上 quiet 与 post 的差别只在"投递侧不打日志",收/丢判据逐条相同;
|
||||
* 本套件是协议栈单测,不验投递本身(那归 test/host/sys_log_mcu),只验
|
||||
* **板端源在每条返回路径上投了哪一类、哪一句**——所以这里存成环形日志。 */
|
||||
#define RP_REC_MAX 16u
|
||||
static uint8_t rp_s_rec_id[RP_REC_MAX];
|
||||
static char rp_s_rec_desc[RP_REC_MAX][SYSLOG_DESC_MAX + 1u];
|
||||
static uint32_t rp_s_rec_n; /* 累计条数(不回绕,供"一条都没多投"断言) */
|
||||
static uint32_t rp_s_drop_quiet; /* 本桩不模拟丢弃,恒 0 */
|
||||
|
||||
void syslog_post_quiet(syslog_id_t id, const char *desc) {
|
||||
uint32_t slot;
|
||||
size_t dl = 0u;
|
||||
|
||||
if (desc == NULL) {
|
||||
return;
|
||||
}
|
||||
slot = rp_s_rec_n % RP_REC_MAX;
|
||||
rp_s_rec_id[slot] = (uint8_t)id;
|
||||
while ((dl < SYSLOG_DESC_MAX) && (desc[dl] != '\0')) {
|
||||
dl++;
|
||||
}
|
||||
(void)memcpy(rp_s_rec_desc[slot], desc, dl);
|
||||
rp_s_rec_desc[slot][dl] = '\0';
|
||||
rp_s_rec_n++;
|
||||
}
|
||||
|
||||
uint32_t syslog_post_dropped(void) { return rp_s_drop_quiet; }
|
||||
|
||||
/* 第 k 条(0 起)记录;越界返回 -1 */
|
||||
static int rp_rec_at(uint32_t k, syslog_id_t id, const char *desc)
|
||||
{
|
||||
if (k >= rp_s_rec_n) {
|
||||
return -1;
|
||||
}
|
||||
return (rp_s_rec_id[k % RP_REC_MAX] == (uint8_t)id)
|
||||
&& (strcmp(rp_s_rec_desc[k % RP_REC_MAX], desc) == 0) ? 1 : 0;
|
||||
}
|
||||
|
||||
/* 某类记录一共投了几条 */
|
||||
static uint32_t rp_rec_cnt(syslog_id_t id)
|
||||
{
|
||||
uint32_t i, n = 0u;
|
||||
|
||||
for (i = 0u; (i < rp_s_rec_n) && (i < RP_REC_MAX); i++) {
|
||||
if (rp_s_rec_id[i] == (uint8_t)id) {
|
||||
n++;
|
||||
}
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
static void rp_rec_clear(void)
|
||||
{
|
||||
rp_s_rec_n = 0u;
|
||||
(void)memset(rp_s_rec_id, 0, sizeof(rp_s_rec_id));
|
||||
(void)memset(rp_s_rec_desc, 0, sizeof(rp_s_rec_desc));
|
||||
}
|
||||
|
||||
/* ---- adc_input_desc 桩:V0.1 权威映射(docs/硬件平台/ADC通道映射说明.md) ---- */
|
||||
#include "adc_input.h"
|
||||
|
||||
@@ -809,6 +873,93 @@ static void tc_dc_yk12(void)
|
||||
"TC-IEC104-024 an invalid DPC returns PN in the select phase");
|
||||
}
|
||||
|
||||
/* TC-IEC104-030(道F task-10):遥控记录——板端默认源 s_src_yk_exec() 的三条返回
|
||||
* 路径各投哪一类记录、投几句、是否顺手投了操作记录。
|
||||
* 为什么直接调 s_src_yk_exec 而不是发 ASDU:本套件绑定的是**假源** f_yk,
|
||||
* YK11 / 未知 IOA 在 f_yk 里就被短路(只有 YK12 转发到真板端源,见 f_yk),
|
||||
* 走 ASDU 反而测不到要验的那两条腿;"ASDU -> link -> pts -> 源"这条转发链
|
||||
* 已由 TC-IEC104-013/024 覆盖,不重复。**投递本身**(quiet 通道的收/丢)归
|
||||
* test/host/sys_log_mcu,本用例只钉"哪条路径投了哪一条"。
|
||||
* 覆盖不到的一条腿(登记,不假装):YK12 的 rc!=0 分支要 prot_set_set_sealed
|
||||
* 返 -1 才进得去,而 PS_GLOBAL_EN 的 min/max 恰好就是本函数会写的 0/1 两值
|
||||
* → 该产品路径上不可达,是防御性分支;不为它伪造定值范围(那是改判据)。 */
|
||||
static void tc_yk_records(void)
|
||||
{
|
||||
uint32_t now = 1000u;
|
||||
|
||||
reset_all(now);
|
||||
rp_rec_clear();
|
||||
|
||||
/* 1) 未知 IOA:拒绝,只投一条遥控记录;拒绝没改动任何东西 -> 不该有操作记录 */
|
||||
CHECK(s_src_yk_exec(0x6000u, (uint8_t)IEC104_DPC_ON, 1u) == -1,
|
||||
"TC-IEC104-030 an IOA without output hardware is still rejected");
|
||||
CHECK((rp_s_rec_n == 1u) && (rp_rec_at(0u, SYSLOG_YK, "YK unknown ioa") == 1),
|
||||
"TC-IEC104-030 the reject path posts exactly one telecontrol record");
|
||||
CHECK(rp_rec_cnt(SYSLOG_OPER) == 0u,
|
||||
"TC-IEC104-030 a rejected command posts no operation record");
|
||||
|
||||
/* 2) YK11 选择段:受理但未动作 -> 只有遥控记录 */
|
||||
rp_rec_clear();
|
||||
CHECK((s_src_yk_exec(0x600Au, (uint8_t)IEC104_DPC_ON, 1u) == 0)
|
||||
&& (rp_s_rec_n == 1u) && (rp_rec_at(0u, SYSLOG_YK, "YK11 select") == 1),
|
||||
"TC-IEC104-030 the YK11 select phase posts a select record and acts on nothing");
|
||||
CHECK(rp_rec_cnt(SYSLOG_OPER) == 0u,
|
||||
"TC-IEC104-030 the select phase is not an operation yet");
|
||||
|
||||
/* 3) YK11 执行段:遥控记录 + 操作记录各一条,顺序 = 先命令后动作 */
|
||||
rp_rec_clear();
|
||||
CHECK((s_src_yk_exec(0x600Au, (uint8_t)IEC104_DPC_ON, 0u) == 0)
|
||||
&& (rp_s_rec_n == 2u)
|
||||
&& (rp_rec_at(0u, SYSLOG_YK, "YK11 exec") == 1)
|
||||
&& (rp_rec_at(1u, SYSLOG_OPER, "force reset") == 1),
|
||||
"TC-IEC104-030 the YK11 execute phase posts one telecontrol plus one operation record");
|
||||
|
||||
/* 4) YK12 非法双点值:拒绝 + 一条带原因的遥控记录,压板不动 */
|
||||
rp_rec_clear();
|
||||
CHECK((s_src_yk_exec(0x600Bu, 0u, 0u) == -1) && (rp_s_rec_n == 1u)
|
||||
&& (rp_rec_at(0u, SYSLOG_YK, "YK12 bad dpc") == 1),
|
||||
"TC-IEC104-030 an invalid DPC posts the reason and changes nothing");
|
||||
CHECK(prot_set_get_ctl(PS_GLOBAL_EN) == 1u,
|
||||
"TC-IEC104-030 the invalid DPC leaves the soft plate engaged");
|
||||
|
||||
/* 5) YK12 执行 OFF:遥控 off + 操作 plate out,且压板真的退出了(记录与事实同步) */
|
||||
rp_rec_clear();
|
||||
CHECK((s_src_yk_exec(0x600Bu, (uint8_t)IEC104_DPC_OFF, 0u) == 0)
|
||||
&& (rp_s_rec_n == 2u)
|
||||
&& (rp_rec_at(0u, SYSLOG_YK, "YK12 exec off") == 1)
|
||||
&& (rp_rec_at(1u, SYSLOG_OPER, "plate out") == 1),
|
||||
"TC-IEC104-030 releasing the soft plate records both the command and the operation");
|
||||
CHECK(prot_set_get_ctl(PS_GLOBAL_EN) == 0u,
|
||||
"TC-IEC104-030 the record agrees with the plate state the settings layer holds");
|
||||
|
||||
/* 6) YK12 执行 ON:对称的另一半(只测 OFF 的话,两条 desc 写反也发现不了) */
|
||||
rp_rec_clear();
|
||||
CHECK((s_src_yk_exec(0x600Bu, (uint8_t)IEC104_DPC_ON, 0u) == 0)
|
||||
&& (rp_rec_at(0u, SYSLOG_YK, "YK12 exec on") == 1)
|
||||
&& (rp_rec_at(1u, SYSLOG_OPER, "plate in") == 1),
|
||||
"TC-IEC104-030 engaging the soft plate records the matching pair");
|
||||
|
||||
/* 7) 选择段不落地:YK12 select 只投一条,压板状态不变 */
|
||||
rp_rec_clear();
|
||||
CHECK((s_src_yk_exec(0x600Bu, (uint8_t)IEC104_DPC_OFF, 1u) == 0)
|
||||
&& (rp_s_rec_n == 1u) && (rp_rec_at(0u, SYSLOG_YK, "YK12 select") == 1)
|
||||
&& (prot_set_get_ctl(PS_GLOBAL_EN) == 1u),
|
||||
"TC-IEC104-030 the YK12 select phase records the intent without changing the plate");
|
||||
|
||||
/* 8) 文案长度契约:desc 全是 ROM 常量,任何一条超过 SYSLOG_DESC_MAX 都会在
|
||||
* 投递侧被静默截断(屏上少几个字,没人会去数)-> 在单测里钉住。 */
|
||||
CHECK((strlen(YK_REC_UNKNOWN) <= SYSLOG_DESC_MAX)
|
||||
&& (strlen(YK_REC_YK11_EXEC) <= SYSLOG_DESC_MAX)
|
||||
&& (strlen(YK_REC_YK12_OFF) <= SYSLOG_DESC_MAX)
|
||||
&& (strlen(YK_REC_YK12_FAIL) <= SYSLOG_DESC_MAX)
|
||||
&& (strlen(YK_REC_DPC_BAD) <= SYSLOG_DESC_MAX)
|
||||
&& (strlen(YK_REC_YK12_SEL) <= SYSLOG_DESC_MAX)
|
||||
&& (strlen(YK_REC_YK11_SEL) <= SYSLOG_DESC_MAX)
|
||||
&& (strlen(YK_REC_YK12_ON) <= SYSLOG_DESC_MAX),
|
||||
"TC-IEC104-030 every telecontrol description fits the 28-byte record field");
|
||||
rp_rec_clear();
|
||||
}
|
||||
|
||||
static void tc_se(void)
|
||||
{
|
||||
uint32_t now = 1000u;
|
||||
@@ -1283,6 +1434,7 @@ int main(void)
|
||||
tc_t3_t1();
|
||||
tc_dc();
|
||||
tc_dc_yk12();
|
||||
tc_yk_records();
|
||||
tc_se();
|
||||
tc_rd();
|
||||
tc_cs();
|
||||
|
||||
Reference in New Issue
Block a user