feat(UI/采集/104): 通讯设置页 + 开机账本 + adc_cal 可诊断化——三车道同树一次构建入库
三条道在同一棵树上交付,故合并成**一次权威构建**(@build 0 错 0 警,Code=235236 RO=26308 RW=1572
ZI=136924)后同笔入库;台账已按该构建回填(`ram_baseline.py --update` + `--write`、`chec
k_mem_numbers.py
--write`),凭证与实际 .map 同源。归属如下:
· **通讯设置页**(道G task-9):新增 `Drivers/BSP/UI/ui_page_comm.{c,h}`(通道六注入,与死
区页同骨架同纪
律),`#page=comm` 绑定使 bound **21 → 22**、内容页黄金 **47 → 53**(旧 47 页字节零变化,
新增六态含
WAIT/OK 两张);`iec104_comm` 脏位 + store_save(**无事件位**)挂 defaultTask 同点位
轮询;`port_104` 由
宏改走 getter、`IEC104_SERV_PORT` 删除;字体 +听/监(185 字全覆)。**实机链已闭环**:FTP 外改
[comm]
的 ca/port → 复位 → 串口出现 `section 'comm' (2 keys)` 与 `i104: listening o
n 9004` → 还原 2404,全程无
FAIL ⇒「重启即生效 + 端口真值」不是推断是实测。上限核对 6/8 段、2/16 键,超限现象由 TC-CONFIG-056/057
钉死(注册 -1 + `comm init: FAIL` 锚 + getter 回 ROM),**不抬宏**。
· **开机账本**(道F task-12):新增 `App/util/boot_stats.{c,h}`——上电次数落 SD2506 用户
SRAM(magic +
小端计数 + 版本 + 异或校验),一次上电 = 1 读 + ≤1 写,**零 NAND、零卷锁、零配置段**;四态互斥
UNKNOWN / FRESH / CONTINUED / RESTARTED(BLF=1 才算电池域掉过电),**读失败绝不回写**;
文案口径「自 RTC
电池周期起」,**禁写终身次数**。复位原因优先级链从 `app_main.c` 的 if-else 收进一份真源(串口与屏幕同
源);104 四个只增不清计数 + `iec104_serv_get_stats()` 留在 serv、未塞进 link(会被 open
/close 洗掉)。
运行时长按用户裁定 = **只报本次开机以来**,零新增代码。新套件 `test/host/boot_stats` 21/21,五处注入
**全部有牙**(含「漂一字节被校验和挡下而不是报 256 倍错账」)。
· **adc_cal 可诊断化**(道E task-43):三个 volatile 计数 + `adc_cal_get_stats()`
/ `adc_cal_note_persisted()`
(水位**盖写非自增**,因为一次 save 覆盖整档,数 save 会留假未落盘);「差额 × 脏位」三态语义唯一落在
`adc_cal.h`,其中「差额 > 0 且脏位恒 0」= 绕过语义 setter 的静默丢失;TC-ADCCAL-019~023。
三条**必须留档的自纠**(都是执行道自己报的,我不替他们润色):
① stdint 那条断链是**宿主套件抓到、通讯道先修**,采集道承认自己是重复添加者并删掉自己那份;
② 「exit 2 不是证据,断言变红才是」——采集道第一版反证注入了未声明标识符导致编译错,差点当成功;
③ 套件汇总行原写 `s_total/s_total`,失败时会打印「21/21 PASSED (failed=1)」这种自相矛盾的行,已改。
另修:`check_registration.py` 的 `SIM_EXEMPT` 加一行豁免 `App/util/boot_stats.c
`(依赖 I2C 与 RCC 位掩码,
MCU 专属;核过 `sys_clock.c`/`sha256.c` 同形态先例),注册反向校验 exit 1 → 0。发号 TC-IEC1
04-034、
TC-UIDATA-029 已实抬游标(`TC-IEC104-033→034`、`TC-UIDATA-026→029`)。
门禁:id-check --strict 与 plain 均 rc=0、doc-links --all rc=0、注册校验 0、cppche
ck / coding-standard /
bom-drift 0;iec104 179/179、ui_data 295/295、boot_stats 21/21、adc_cal 11
7/117、run_par 67/67;菜单 8 状态
池 5368 不变、内容页 53/53。**已知遗留**:内容页数 47 → 53 的全仓文本同步尚未做(另卡跟踪),本笔只保
证代码与黄金一致;面板注键真机那一腿缺 CLI,交台架道补。
This commit is contained in:
@@ -54,6 +54,40 @@ static uint8_t s_liveness_ctr;
|
||||
static uint8_t s_send_fail_run;
|
||||
static uint8_t s_conn_dead; /* 发送连败 → 本轮 link 调用返回后拆链 */
|
||||
|
||||
/* ---------------- 只读观测计数(道G task-12;上电以来,跨重连**不清零**)-----------
|
||||
* 与上面三枚的分工要说清:s_liveness_ctr / s_send_fail_run / s_conn_dead 是**控制量**
|
||||
* ——它们为"要不要拆链"服务,会被复位、也是 8 位,拿它们当统计数字必错(拆一次链
|
||||
* 就把连败清零)。下面四枚只做一件事:被 iec104_serv_get_stats() 读出去显示。
|
||||
* 为什么留在本文件而不是并进 App/util/boot_stats:104 的账本归 104(分层),
|
||||
* boot_stats 只管开机账;两边各一张表比一张混表好查。
|
||||
* 为什么**不放进 iec104_link_t**:实例是 serv.c:48 的文件级 static,feed 拿不到指针;
|
||||
* 更要紧的是 link_open/link_close 的语义会把"上电以来"洗成"本次连接"。
|
||||
* 写者 = iec104Task(本文件),读者 = uiTask/feed;u32 单字读写在 Cortex-M4 上原子,
|
||||
* 跨字段不保证同一瞬间——四个数之间没有"合起来才成立"的判据,混窗对显示无害。
|
||||
* 到顶**饱和**不回绕:停在 42 亿一眼能看出到头,回绕成个位数会被读成"刚上电"。 */
|
||||
static uint32_t s_st_conn_up; /* 主站接入次数(accept 成功且已 open link) */
|
||||
static uint32_t s_st_apdu_tx; /* 成功发出的 APDU 帧数(短写不计,那算 tx_fail) */
|
||||
static uint32_t s_st_tx_fail; /* 发送短写/失败次数(与连败复位无关,只累计) */
|
||||
static uint32_t s_st_rx_bytes; /* 收到的字节数(帧数在 link 层重组,serv 只看得见字节) */
|
||||
|
||||
/*
|
||||
* 函数功能:单枚观测计数 +1,到顶饱和(四枚同式,收成一处,别在四个调用点各写一遍)
|
||||
* 入口参数:p - 计数变量地址 uint32_t *
|
||||
* 返 回 值:无 void
|
||||
* 限定条件:iec104Task 上下文(唯一写者);NULL 时无害返回
|
||||
* 函数说明:**只加不清**——观测计数一旦有清零路径,"上电以来"就退化成"上次谁清零
|
||||
* 以来"。p 为 NULL 直接返回(与三个对外 getter 的 NULL 契约一致)。
|
||||
*/
|
||||
static void s_cnt_add(uint32_t *p)
|
||||
{
|
||||
if (p == 0) {
|
||||
return;
|
||||
}
|
||||
if (*p < 0xFFFFFFF0u) {
|
||||
*p = *p + 1u;
|
||||
}
|
||||
}
|
||||
|
||||
/* 前向声明(cfg 初始化引用) */
|
||||
static void s_send_apdu(void *ctx, const uint8_t *apdu, uint16_t len);
|
||||
static int s_clock_sync(void *ctx, uint64_t epoch_ms);
|
||||
@@ -82,8 +116,10 @@ static void s_send_apdu(void *ctx, const uint8_t *apdu, uint16_t len) {
|
||||
ret = net_send(s_client, apdu, (int)len, 0);
|
||||
if (ret == (int)len) {
|
||||
s_send_fail_run = 0u;
|
||||
s_cnt_add(&s_st_apdu_tx); /* 只数真发出去的(道G task-12 观测计数) */
|
||||
return;
|
||||
}
|
||||
s_cnt_add(&s_st_tx_fail); /* 短写/失败也进观测账,与下面的连败判定各管各的 */
|
||||
if (s_send_fail_run < 255u) {
|
||||
s_send_fail_run++;
|
||||
}
|
||||
@@ -222,6 +258,30 @@ static void s_service_link(uint32_t now) {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:读 104 观测计数(契约见 iec104_serv.h 的 iec104_serv_get_stats)
|
||||
* 入口参数:p_out - 输出缓冲;NULL 时无害返回 iec104_serv_stats_t *
|
||||
* 返 回 值:无 void
|
||||
* 限定条件:任意上下文;不取锁、不读时刻、不碰 socket、不阻塞
|
||||
* 函数说明:先读进局部再整体赋出——四枚都读完后才发布,读者拿到的是"同一轮读取"的
|
||||
* 四元组(中途若有新计数产生,那一枚可能偏新一格,但不会读到半改写的字)。
|
||||
* 本函数**不清零、不复位任何计数**:统计口一旦能清零,"上电以来"就退化成
|
||||
* "上次谁读过以来",那条账再没人敢信。
|
||||
*/
|
||||
void iec104_serv_get_stats(iec104_serv_stats_t *p_out)
|
||||
{
|
||||
iec104_serv_stats_t s;
|
||||
|
||||
if (p_out == NULL) {
|
||||
return;
|
||||
}
|
||||
s.conn_up = s_st_conn_up;
|
||||
s.apdu_tx = s_st_apdu_tx;
|
||||
s.tx_fail = s_st_tx_fail;
|
||||
s.rx_bytes = s_st_rx_bytes;
|
||||
*p_out = s;
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:单次服务循环(代次自愈 → accept → 门控收 → 喂 link → 节拍)
|
||||
* 返回值:无
|
||||
@@ -280,6 +340,7 @@ static void s_serv_poll(void) {
|
||||
s_conn_dead = 0u;
|
||||
s_liveness_ctr = 0u;
|
||||
iec104_link_open(&s_link, now);
|
||||
s_cnt_add(&s_st_conn_up); /* 主站接入次数(上电以来;道G task-12) */
|
||||
DBG_INFO("i104: accepted fd=%d", c);
|
||||
}
|
||||
return;
|
||||
@@ -300,6 +361,14 @@ static void s_serv_poll(void) {
|
||||
* 阻塞 recv(文档契约见 net_socket.h net_recv 注释),非阻塞轮询是义务 */
|
||||
n = net_recv_nb(s_client, s_rx, (int)sizeof(s_rx));
|
||||
if (n > 0) {
|
||||
/* 收字节观测计数(道G task-12):这里数的是 recv 段返回的**字节数**,不是
|
||||
* APDU 帧数——帧边界在 link 层重组,serv 这一层看不见;页面文案别写"接收帧数"。
|
||||
* 加法也做饱和:n 最大 128,先留出余量再比,避免"加完才判"溢出成小数字。 */
|
||||
if (s_st_rx_bytes < (0xFFFFFFF0u - (uint32_t)n)) {
|
||||
s_st_rx_bytes = s_st_rx_bytes + (uint32_t)n;
|
||||
} else {
|
||||
s_st_rx_bytes = 0xFFFFFFF0u;
|
||||
}
|
||||
iec104_link_on_rx(&s_link, s_rx, (uint16_t)n, now);
|
||||
} else if (n == 0) {
|
||||
/* 对端关闭:net 层已 auto_relisten;client==listen 时严禁 close */
|
||||
|
||||
Reference in New Issue
Block a user