Files
STM32F4-Base/Drivers/BSP/UI/ui_page_view_param.c
T
wandering1 77779d49d6 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),
已由生成侧单测与代码注释点名差距;同类页数与钩子数陈述残留另立待办。
2026-10-26 15:51:12 +08:00

141 lines
7.1 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
* 模块名称:UI Page view_param (参数查看内容页)
* 模块功能:参数定值 → 查看 → 参数 的内容页——8 行数值表(PT/CT 一次二次额定 + 4 个返回系数),每页 8 行、1 页;
* 数据 = 参数快照(Q10)按行表小数位换算,越界项由 bad 回调反显;
* 本文件零 App include;写方向只有一个出口:整定态的"保存"经
* ui_data_param_request() 投递(执行与落盘在 App 侧,本层不碰 prot_set/FatFs)
* 两态一页(道F task-2:整定 4 叶绑定本描述符):同一份描述符既服务"查看"叶子
* (只读——不绑 commit → 无保存行、按键全交回框架 → 像素与绑定前逐位一致),
* 也服务"整定"叶子(123 授权 → 编辑叠层 + 保存行 + 未标定徽标)。
* 分派点只有 pg_init 一处(按 ui_content_page_is_editable() 判),
* 两态共用行表/取数/反显,不存在"查看一套边界、整定另一套边界"
* 为什么这么薄:行表与取数在 ui_w_setview(四个查看页共用一份视图模型),
* 渲染与反显在 ui_w_setlist(与整定页同一组件)——本文件只把视图编号
* 和标准骨架几何令牌接进框架的跳板,改一次口径四处一致
* 适用平台:STM32F407ZGTx / PC 模拟器(共用源码)
* 作者:王建锋
* 创建日期:2026-10-25
* 修改记录:
* v1.0 2026-10-25 王建锋 创建(道E task-15 批 3)
* v1.1 2026-10-26 DTU 项目组 道F task-2:接整定态——pg_init 按权限分派
* attach/attach_edit、新增 pg_key 转发按键、
* pg_draw 追加"未标定"徽标、描述符补
* edit_capable/key_intercept/key_cb 三项
* (只读分支行为逐字不变)
*/
/* 头文件包含区 */
#include "ui_page_view_param.h"
#include "ui_tokens.h"
#include "ui_w_setlist.h"
#include "ui_w_setview.h"
/* 静态变量定义区 */
/* 本页实例(组件状态:编辑态等;查看页只用行游标与反显,实例仍须独占一份,
* 与别的页面共用会互相踩状态——同 ui_w_records 的实例化约定) */
static ui_w_setlist_t s_sl;
/* 函数定义区 */
/*
* 函数功能:开页绑定视图(行表 + 取数/反显回调一次配齐;接框架 init_cb)
* 入口参数:无
* 返回值:无
* 限定条件:框架开页链内调用(uiTask)
* 函数说明:1. 每次开页都重新 attach——组件实例内残留的编辑态/游标会跨页带过来,
* 开页复位比"信任上一次已经清干净"可靠
* 2. **只读 / 整定两态在这里分派一次**,之后所有钩子只看已绑好的回调
* (组件用 commit==NULL 判视图类型,不再回头看权限)
* 3. 时序依据(为什么 init_cb 里问 is_editable() 拿到的就是本次进入的权限):
* 框架 open() 先装 s_perm 与 s_open、最后才调 init_cb
* (ui_content_page.c 的 open:s_perm=perm → s_open=desc → init_cb),
* 所以这里读到的是"本次进入"的真值,不是上一次的残留
*/
static void pg_init(void) {
if (ui_content_page_is_editable()) {
ui_w_setview_attach_edit(&s_sl, UI_W_SETVIEW_PARAM); /* 整定:编辑 + 保存行 + 徽标 */
} else {
ui_w_setview_attach(&s_sl, UI_W_SETVIEW_PARAM); /* 查看:与绑定前完全同一条路径 */
}
}
/*
* 函数功能:数据行数(框架 count_cb;查看视图没有保存行)
* 入口参数:无
* 返回值:行数 uint16_t
* 限定条件:框架绘制/翻页链内
*/
static uint16_t pg_count(void) {
return ui_w_setlist_count(&s_sl);
}
/*
* 函数功能:逐行取数(框架 refresh;内部先按发布序号同步参数帧)
* 入口参数:a_row / a_name / a_value - 契约见 ui_content_page.h
* 返回值:无
* 限定条件:框架绘制链内
*/
static void pg_refresh(uint16_t a_row, char *a_name, char *a_value) {
ui_w_setview_refresh(&s_sl, a_row, a_name, a_value);
}
/*
* 函数功能:自绘层(越界行反显 + 未标定徽标;框架内置区块画完后调用)
* 入口参数:a_layer / a_clip - 契约见 ui_content_page.h
* 返回值:无
* 限定条件:框架绘制链内
* 函数说明:徽标函数自己判"是不是整定视图 + 帧在不在 + cal_block 置没置",
* 页面这里无条件调它——四页少写四个 if,也就少四次写漏的机会;
* 查看页三个条件第一条就不成立,一个像素都不落(vparam~vplate
* 四张黄金参考仍逐位一致)
*/
static void pg_draw(lv_layer_t *a_layer, const lv_area_t *a_clip) {
ui_w_setlist_draw(&s_sl, a_layer, a_clip);
ui_w_setview_draw_cal_badge(a_layer, a_clip);
}
/*
* 函数功能:按键转发(框架 key_cb)
* 入口参数:a_key - LVGL 键值 lv_key_t
* 返回值:true - 本页已消费(框架跳过内置);false - 交回框架(↑↓ 移选、← 关页)
* 限定条件:框架按键链内;描述符须 edit_capable=1 + key_intercept=1
* 函数说明:两态行为的不同**不写在这里**——ui_w_setview_key() 先看视图类型
* (查看页未绑 commit → 直接交回框架,等于本页没有 key_cb),
* 再看参数帧在不在。所以这里必须原样透传返回值,不得就地"或"上什么
*/
static bool pg_key(lv_key_t a_key) {
return (ui_w_setview_key(&s_sl, a_key) != 0u);
}
/*
* 页面描述符(外部链接:生成物 ui_page_registry.c 按菜单树 #page=view_param 绑定引用)
* edit_capable=1 + key_cb + key_intercept=1:同一份描述符两态共用。
* · 整定叶子(123 授权 UI_PERM_MODIFY)→ is_editable() 真 → attach_edit +
* 编辑叠层 + 保存行;key_intercept=1 是**必需**的:编辑中的 ←→ 移位光标
* 要先给页面,否则框架拿 ← 当"关页",编辑到一半就跳出去
* · 查看叶子(无 #P,恒 UI_PERM_VIEW)→ is_editable() 假 → 仍走 attach,
* ui_w_setview_key() 第一条门就把键全部交回框架,↑↓ 移选与 ← 关页全走内置
* ——即"绑了 key_cb 的查看页"与"没有 key_cb 的查看页"行为逐字等价
* (§3.2.7:"权限不足 ENTER 一律忽略")
*/
const content_page_def_t ui_page_view_param_desc = {
.id = "view_param",
.title = "参数",
.selectable = 1u,
.edit_capable = 1u, /* 两态页:能不能真编辑还要看本次进入的权限(is_editable) */
.top_y = UI_LIST_TOP,
.pitch = UI_ROW_PITCH,
.band_h = UI_ROW_BAND_H,
.text_dy = 0,
.left_x = UI_LIST_LEFT_X,
.right_x = UI_LIST_RIGHT_X,
.rows_per_page = UI_LIST_ROWS,
.key_intercept = 1u, /* ← 先交 key_cb:编辑中是"移位光标",非编辑中才轮到关页 */
.init_cb = pg_init,
.count_cb = pg_count,
.refresh = pg_refresh,
.draw_cb = pg_draw,
.key_cb = pg_key,
};