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:
@@ -28,10 +28,17 @@
|
||||
* 否则对端会以为设备时间是 1970-01-01。
|
||||
* 4. 活性分频(每 32 轮才探一次)是 CPU 预算的取舍:写错成每轮都探,就把 100ms
|
||||
* 轮询变成了每轮两次系统调用;写错成分频相位,TESTFR 会迟迟不发。
|
||||
* 5. 操作记录是**审计面**(道F task-19):只要"投了"而不管"改成功了没有",屏上的
|
||||
* 操作记录页就会出现从没发生过的对时;越界拒绝与 RTC 写失败这两条腿必须
|
||||
* 一条都不投,而这只有能注入 sys_clock_set_unix 的返回值才测得到。
|
||||
* 同时钉住"用 quiet 口不用 post 口"——post 的两个满态留痕分支各带约 216 B
|
||||
* 内联行缓冲,iec104Task 的静态最坏链放不下它(台架与单测都看不出这个差别,
|
||||
* 只有 stack_report 会响,所以先在源码侧钉住)。
|
||||
*
|
||||
* 覆盖点:TC-I104SRV-001..004 建监听;010..013 发送与连续短写判死;020..023 时钟
|
||||
* 桥接;030..033 代次重建与 accept 门控;034..036 活性分频与对端 FIN;037..041
|
||||
* 错误丢弃与协议掉线重生。
|
||||
* 错误丢弃与协议掉线重生;050..053 对时的操作记录(道F task-19:成功才记、
|
||||
* 越界拒绝与写钟失败两条腿都不记、每次对时各记一条、且只走 quiet 投递口)。
|
||||
*
|
||||
* 通过:全部 TC PASS(main 返回 0)。
|
||||
* 入口:int main(void),返回 0=PASS / 1=FAIL(由 run 脚本判读)。
|
||||
@@ -194,6 +201,61 @@ static int g_wd_beats;
|
||||
static int g_wd_last_id;
|
||||
static uint32_t g_now;
|
||||
|
||||
/* ===================== sys_log 桩(task-19 操作记录) =====================
|
||||
* 两个投递口都抓下来:quiet 是 iec104Task 该用的那个(本任务栈深,不许在调用链上
|
||||
* 内联日志行缓冲),post 一旦在这里被调到就是"绕回旧口",053 会红。
|
||||
* 投递本身(收/丢/计数)归 test/host/sys_log_mcu,本套只钉"哪条腿投了哪一句"。 */
|
||||
#include "sys_log.h"
|
||||
|
||||
#define RP_I4_REC_MAX 8u
|
||||
static uint8_t rp_i4_id[RP_I4_REC_MAX];
|
||||
static char rp_i4_desc[RP_I4_REC_MAX][SYSLOG_DESC_MAX + 1u];
|
||||
static uint32_t rp_i4_n; /* quiet 通道累计(不回绕,供"恰好几条"断言) */
|
||||
static uint32_t rp_i4_post_n; /* 误用 syslog_post 的次数,期望恒 0 */
|
||||
|
||||
static void rp_i4_rec_clear(void)
|
||||
{
|
||||
rp_i4_n = 0u;
|
||||
rp_i4_post_n = 0u;
|
||||
(void)memset(rp_i4_id, 0, sizeof(rp_i4_id));
|
||||
(void)memset(rp_i4_desc, 0, sizeof(rp_i4_desc));
|
||||
}
|
||||
|
||||
void syslog_post_quiet(syslog_id_t id, const char *desc)
|
||||
{
|
||||
uint32_t slot = rp_i4_n % RP_I4_REC_MAX;
|
||||
size_t dl = 0u;
|
||||
|
||||
if (desc == NULL) {
|
||||
return;
|
||||
}
|
||||
while ((dl < SYSLOG_DESC_MAX) && (desc[dl] != '\0')) {
|
||||
dl++;
|
||||
}
|
||||
(void)memcpy(rp_i4_desc[slot], desc, dl);
|
||||
rp_i4_desc[slot][dl] = '\0';
|
||||
rp_i4_id[slot] = (uint8_t)id;
|
||||
rp_i4_n++;
|
||||
}
|
||||
|
||||
void syslog_post(syslog_id_t id, const char *desc)
|
||||
{
|
||||
(void)id;
|
||||
(void)desc;
|
||||
rp_i4_post_n++;
|
||||
}
|
||||
|
||||
uint32_t syslog_post_dropped(void) { return 0u; }
|
||||
|
||||
static int rp_i4_at(uint32_t k, syslog_id_t id, const char *desc)
|
||||
{
|
||||
if (k >= rp_i4_n) {
|
||||
return 0;
|
||||
}
|
||||
return (rp_i4_id[k % RP_I4_REC_MAX] == (uint8_t)id)
|
||||
&& (strcmp(rp_i4_desc[k % RP_I4_REC_MAX], desc) == 0) ? 1 : 0;
|
||||
}
|
||||
|
||||
uint32_t sys_clock_get(void) { return g_clock_val; }
|
||||
int sys_clock_set_unix(uint32_t unix_secs)
|
||||
{
|
||||
@@ -250,6 +312,7 @@ static void reset_all(void)
|
||||
g_lk_state = IEC104_ST_RUN;
|
||||
g_pts_init = 0;
|
||||
g_clock_val = 1700000000u;
|
||||
rp_i4_rec_clear();
|
||||
g_clock_set_rc = 0;
|
||||
g_clock_last_secs = 0u;
|
||||
g_clock_set_calls = 0;
|
||||
@@ -367,6 +430,38 @@ static void tc_clock(void)
|
||||
reset_all();
|
||||
g_clock_val = 1700000123u;
|
||||
CHECK(s_epoch_ms(NULL) == 1700000123000ULL, "TC-I104SRV-023 with a synced clock the answer is in milliseconds");
|
||||
|
||||
/* ---- task-19:对时 = 操作记录(审计面只记真发生过的动作) ---- */
|
||||
reset_all();
|
||||
(void)s_clock_sync(NULL, 1700000123000ULL);
|
||||
CHECK((rp_i4_n == 1u) && (rp_i4_at(0u, SYSLOG_OPER, "clock set by 104") == 1),
|
||||
"TC-I104SRV-050 a successful sync books exactly one operation record naming the source");
|
||||
|
||||
reset_all();
|
||||
(void)s_clock_sync(NULL, 0x100000000ULL * 1000ULL);
|
||||
CHECK((rp_i4_n == 0u) && (g_clock_set_calls == 0),
|
||||
"TC-I104SRV-050b the out-of-range rejection books nothing (an audit record for something that never happened is worse than none)");
|
||||
|
||||
reset_all();
|
||||
g_clock_set_rc = -1; /* 写钟失败(RTC 回写失败那一类) */
|
||||
CHECK(s_clock_sync(NULL, 1700000123000ULL) == -1,
|
||||
"TC-I104SRV-051 a failed clock write still answers the link layer with -1");
|
||||
CHECK(rp_i4_n == 0u,
|
||||
"TC-I104SRV-051b a failed clock write books no operation record");
|
||||
|
||||
reset_all();
|
||||
(void)s_clock_sync(NULL, 1700000123000ULL);
|
||||
(void)s_clock_sync(NULL, 1700000456000ULL);
|
||||
CHECK((rp_i4_n == 2u) && (rp_i4_at(1u, SYSLOG_OPER, "clock set by 104") == 1),
|
||||
"TC-I104SRV-052 every re-sync is its own operation record (no dedup, no latching)");
|
||||
|
||||
/* 053:用错投递口的形状——iec104Task 是深链任务,只许用 quiet。
|
||||
* 顺带量文案长度:超过 SYSLOG_DESC_MAX 会在投递侧被静默截断。 */
|
||||
reset_all();
|
||||
(void)s_clock_sync(NULL, 1700000123000ULL);
|
||||
CHECK((rp_i4_post_n == 0u) && (rp_i4_n == 1u)
|
||||
&& (strlen("clock set by 104") <= SYSLOG_DESC_MAX),
|
||||
"TC-I104SRV-053 the record goes out over the stack-safe channel only, and its text fits the record field");
|
||||
}
|
||||
|
||||
/* ===================== 代次重建与 accept 门控 ===================== */
|
||||
|
||||
Reference in New Issue
Block a user