门禁扩容:新增 lv-conf-sync、simulator/ 纳入全部钩子;含 L3 定值/元件框架落地

本轮把"自研代码落在门禁之外"的口子收掉,同时落地 LVGL 特性裁剪与
L3 保护定值/元件框架。

门禁(.pre-commit-config.yaml,26 个钩子)
- 新增 scripts/check_lv_conf_sync.py + 钩子 lv-conf-sync:比对两份
  lv_conf.h 的**生效值**(未定义则取 lv_conf_internal.h 兜底默认),
  抓 MISMATCH / LVGL 不认的宏名 / 同文件重复定义
- 顶层 exclude 删掉 simulator/:其下 21 个 tracked 文件全是本项目自研
  代码,生成物(build/、SDL2/、tests/ref/、shot*)已在 .gitignore;
  doc-links 的 exclude 同步删除
- lv-conf-sync 的 files: 覆盖两端配置 → 只改 simulator/lv_conf.h 也触发
  (pre-commit 4.x 已移除 always: true,实测只告警并跳过,无兜底开关)
- 新增 prot-set-unit-test / prot-elm-unit-test 两个主机侧单测钩子
- S11(2.3.5) 判定细化:禁的是"用路径找文件",尖括号系统头带子目录
  (如 <sys/stat.h>)不再误报;全仓库复核仅 2 处项目代码判定变化

模拟器代码整改(纳入钩子后暴露,全部修代码而非豁免)
- cppcheck 4 处:sim_syslog.c 判空分支内解引用 p_epoch(真实 bug)、
  2 处 struct tm 未初始化、1 处指针可加 const
- coding-standard 61 处:44 处函数左大括号并到右括号同行、8 处补函数
  注释、3 处补文件头注释块、2 处 __ 前缀保护宏改 XXX_H、2 处 sprintf
  改 snprintf(写入字节数与原来完全一致)

LVGL 特性裁剪(F-1/F-2/F-3)
- 两端 lv_conf.h 对齐同一特性子集:删 26 个 LVGL 9.3 不存在的选项名、
  3 处重复定义,10 项靠默认值隐式生效的改为显式固化
- 实测对镜像体积中性;价值在防漂移,且模拟器 golden 回归跑的正是固件
  实际编译的配置

L3 软件侧
- App/algo/prot_set.* Q10 定值模型(范围校验 / 整表 all-or-nothing /
  校验和封存-自检-闭锁)+ prot_elm.* 通用"滞回+定时限"元件框架 7 实例
- test/host/prot_set、test/host/prot_elm 主机侧单测;uvprojx 挂载两处

文档同步
- pre-commit使用说明:§2.8 S11 口径、§2.15 lv-conf-sync 详解、新增 §5.5
  复盘(教训:exclude 只写真正不该进钩子的路径)
- AGENTS.md、UI_设计架构 §1.4 第 10 条、RAM 分析、审查报告刷新与销项

验证
- @build BUILD_OK 0/0(Code=194276 RO=15872 RW=876 ZI=139892)
- 模拟器重建:菜单 8 状态像素逐字节一致(池 5368 B)、11 内容页黄金参考
  全过(往返 5448 B)、remo sink 0/25600 位差异、--logtest/--cfgtest PASS
- 全仓库 cppcheck / coding-standard / no-mojibake --all-files 全过
- check_doc_links --all 129/0;check_mem_numbers --check 内存数字一致
- 端到端:往 simulator/lv_conf.h 注入一行漂移 → 钩子 FAIL(exit 1)
This commit is contained in:
2026-10-11 08:48:49 +08:00
parent 13a4e61c27
commit c936441c83
36 changed files with 2220 additions and 565 deletions
+30 -60
View File
@@ -53,8 +53,7 @@ static int s_generation = 0; /* 网络代次(模拟器恒为 0
* 限定条件:无
* 函数说明:任何 Socket 操作前先调用;已初始化则直接返回
*/
static int ensure_wsa(void)
{
static int ensure_wsa(void) {
static int s_done = 0;
if (s_done == 0) {
@@ -75,8 +74,7 @@ static int ensure_wsa(void)
* 限定条件:s_socks 已定义
* 函数说明:线性扫描,返回首个 in_use == 0 的控制块索引
*/
static int alloc_fd(void)
{
static int alloc_fd(void) {
int i;
for (i = 0; i < NET_MAX_SOCKETS; i++) {
@@ -96,8 +94,7 @@ static int alloc_fd(void)
* 限定条件:两结构体布局一致(均 16 字节,字段偏移相同)
* 函数说明:字段偏移一致,按 sizeof 直接拷贝
*/
static void to_ws_addr(const struct net_sockaddr *addr, struct sockaddr_in *out)
{
static void to_ws_addr(const struct net_sockaddr *addr, struct sockaddr_in *out) {
memcpy(out, addr, sizeof(struct sockaddr_in));
}
@@ -110,8 +107,7 @@ static void to_ws_addr(const struct net_sockaddr *addr, struct sockaddr_in *out)
* 限定条件:两结构体布局一致(均 16 字节,字段偏移相同)
* 函数说明:字段偏移一致,按 sizeof 直接拷贝
*/
static void from_ws_addr(const struct sockaddr_in *in, struct net_sockaddr *out)
{
static void from_ws_addr(const struct sockaddr_in *in, struct net_sockaddr *out) {
memcpy(out, in, sizeof(struct sockaddr_in));
}
@@ -123,8 +119,7 @@ static void from_ws_addr(const struct sockaddr_in *in, struct net_sockaddr *out)
* 限定条件:无
* 函数说明:与 MCU 端 net_init 语义对齐,供上层统一调用
*/
int net_init(const char *ip, const char *mask, const char *gateway, const uint8_t *mac)
{
int net_init(const char *ip, const char *mask, const char *gateway, const uint8_t *mac) {
(void)ip;
(void)mask;
(void)gateway;
@@ -145,8 +140,7 @@ int net_init(const char *ip, const char *mask, const char *gateway, const uint8_
* 限定条件:无
* 函数说明:模拟器无网络重建,代次恒 0,使上层代次自愈逻辑空转
*/
uint32_t net_get_generation(void)
{
uint32_t net_get_generation(void) {
return (uint32_t)s_generation;
}
@@ -157,8 +151,7 @@ uint32_t net_get_generation(void)
* 限定条件:无
* 函数说明:模拟器不会触发,保留接口以对齐 API
*/
void net_generation_inc(void)
{
void net_generation_inc(void) {
s_generation++;
}
@@ -169,8 +162,7 @@ void net_generation_inc(void)
* 限定条件:无
* 函数说明:模拟器无 CH395F 中断,空操作
*/
int net_poll(void)
{
int net_poll(void) {
return 0;
}
@@ -183,8 +175,7 @@ int net_poll(void)
* 限定条件:Winsock 已就绪
* 函数说明:分配空闲控制块,创建 Winsock SOCKET 并置非阻塞
*/
int net_socket(int domain, int type)
{
int net_socket(int domain, int type) {
int idx;
int is_udp;
SOCKET ws;
@@ -238,8 +229,7 @@ int net_socket(int domain, int type)
* 限定条件:socket 已创建
* 函数说明:设置 SO_REUSEADDR 后 bind,便于断线后重监听复用端口
*/
int net_bind(int sockfd, const struct net_sockaddr *addr, int addrlen)
{
int net_bind(int sockfd, const struct net_sockaddr *addr, int addrlen) {
struct sockaddr_in wsaddr;
int yes = 1;
@@ -273,8 +263,7 @@ int net_bind(int sockfd, const struct net_sockaddr *addr, int addrlen)
* 限定条件:socket 已绑定
* 函数说明:backlog 为 1(单客户端),监听 Socket 保持非阻塞
*/
int net_listen(int sockfd)
{
int net_listen(int sockfd) {
if (sockfd < 0 || sockfd >= NET_MAX_SOCKETS || s_socks[sockfd].in_use == 0) {
s_net_errno = NET_ERR_BADF;
return -1;
@@ -301,8 +290,7 @@ int net_listen(int sockfd)
* 函数说明:非阻塞监听下无新连接时返回 -1 并置 NET_ERR_WOULDBLOCK;
* 与 MCU 端不同,Winsock 的 accept 返回独立于监听 Socket 的新 fd
*/
int net_accept(int sockfd, struct net_sockaddr *addr, int *addrlen)
{
int net_accept(int sockfd, struct net_sockaddr *addr, int *addrlen) {
struct sockaddr_in wscli;
int wslen;
SOCKET cws;
@@ -356,8 +344,7 @@ int net_accept(int sockfd, struct net_sockaddr *addr, int *addrlen)
* 而 accept 本就是非阻塞的、**没有 MCU 端的 RPC 成本** → 恒返回 1,
* 使上层门控在模拟器上等价于"改前行为"(逐位一致,不引入新语义)
*/
int net_can_accept(int sockfd)
{
int net_can_accept(int sockfd) {
if (sockfd < 0 || sockfd >= NET_MAX_SOCKETS || s_socks[sockfd].in_use == 0) {
return 0;
}
@@ -372,8 +359,7 @@ int net_can_accept(int sockfd)
* 函数说明:同 net_can_accept——Winsock recv 非阻塞、无 RPC 成本 → 恒返回 1,
* 上层门控在模拟器上不改变既有行为(含"每轮都 recv"的自愈特性)
*/
int net_can_read(int sockfd)
{
int net_can_read(int sockfd) {
if (sockfd < 0 || sockfd >= NET_MAX_SOCKETS || s_socks[sockfd].in_use == 0) {
return 0;
}
@@ -390,8 +376,7 @@ int net_can_read(int sockfd)
* 限定条件:socket 已创建
* 函数说明:非阻塞 Socket 上连接未完成时返回 -1 + NET_ERR_WOULDBLOCK
*/
int net_connect(int sockfd, const struct net_sockaddr *addr, int addrlen)
{
int net_connect(int sockfd, const struct net_sockaddr *addr, int addrlen) {
struct sockaddr_in wsaddr;
if (sockfd < 0 || sockfd >= NET_MAX_SOCKETS || s_socks[sockfd].in_use == 0) {
@@ -430,8 +415,7 @@ int net_connect(int sockfd, const struct net_sockaddr *addr, int addrlen)
* 函数说明:非阻塞单次发送(保持 UI 主循环不阻塞);协议帧小且对端主动
* 读取,实践中一次即发完
*/
int net_send(int sockfd, const void *buf, int len, int flags)
{
int net_send(int sockfd, const void *buf, int len, int flags) {
int r;
if (sockfd < 0 || sockfd >= NET_MAX_SOCKETS || s_socks[sockfd].in_use == 0) {
@@ -473,8 +457,7 @@ int net_send(int sockfd, const void *buf, int len, int flags)
* 函数说明:与 MCU 端语义一致——>0 有数据,0 对端关闭,<0 且 errno 区分
* "暂无数据"与"真错误"
*/
int net_recv(int sockfd, void *buf, int len, int flags)
{
int net_recv(int sockfd, void *buf, int len, int flags) {
int r;
(void)flags;
@@ -519,8 +502,7 @@ int net_recv(int sockfd, void *buf, int len, int flags)
* 限定条件:socket 已创建,buf/dest_addr 非空
*/
int net_sendto(int sockfd, const void *buf, int len, int flags,
const struct net_sockaddr *dest_addr, int addrlen)
{
const struct net_sockaddr *dest_addr, int addrlen) {
struct sockaddr_in wsaddr;
int r;
@@ -563,8 +545,7 @@ int net_sendto(int sockfd, const void *buf, int len, int flags,
* 限定条件:socket 已创建,buf 非空
*/
int net_recvfrom(int sockfd, void *buf, int len, int flags,
struct net_sockaddr *src_addr, int *addrlen)
{
struct net_sockaddr *src_addr, int *addrlen) {
struct sockaddr_in wsaddr;
int wslen;
int r;
@@ -606,8 +587,7 @@ int net_recvfrom(int sockfd, void *buf, int len, int flags,
* 限定条件:socket 已打开(in_use == 1)
* 函数说明:关闭 Winsock 句柄并释放控制块(in_use 清零,net_get_sock 转返回 NULL)
*/
int net_close(int sockfd)
{
int net_close(int sockfd) {
if (sockfd < 0 || sockfd >= NET_MAX_SOCKETS) {
s_net_errno = NET_ERR_BADF;
return -1;
@@ -636,8 +616,7 @@ int net_close(int sockfd)
* 限定条件:socket 已创建
* 函数说明:模拟器以非阻塞 I/O 直接感知事件,回调仅存储不主动触发
*/
int net_set_event_cb(int sockfd, net_event_cb_t cb, void *arg)
{
int net_set_event_cb(int sockfd, net_event_cb_t cb, void *arg) {
if (sockfd < 0 || sockfd >= NET_MAX_SOCKETS || s_socks[sockfd].in_use == 0) {
s_net_errno = NET_ERR_BADF;
return -1;
@@ -656,8 +635,7 @@ int net_set_event_cb(int sockfd, net_event_cb_t cb, void *arg)
* 返回值:最近一次 net_* 操作设置的错误码(NET_OK / NET_ERR_xxx)
* 限定条件:无
*/
int net_get_errno(void)
{
int net_get_errno(void) {
return s_net_errno;
}
@@ -669,8 +647,7 @@ int net_get_errno(void)
* 限定条件:无
* 函数说明:逐段解析后按 NET_HTONL 转网络字节序(与 MCU 端实现一致)
*/
uint32_t net_inet_addr(const char *cp)
{
uint32_t net_inet_addr(const char *cp) {
uint32_t addr = 0;
int i;
@@ -701,8 +678,7 @@ uint32_t net_inet_addr(const char *cp)
* 返回值:buf 指针(buf 为 NULL 时返回 NULL)
* 限定条件:buf 非空且长度足够
*/
char *net_inet_ntoa(uint32_t addr, char *buf)
{
char *net_inet_ntoa(uint32_t addr, char *buf) {
uint32_t naddr = NET_NTOHL(addr);
if (buf == NULL) {
@@ -724,8 +700,7 @@ char *net_inet_ntoa(uint32_t addr, char *buf)
* 返回值:网络序端口
* 限定条件:无
*/
uint16_t net_htons(uint16_t hostshort)
{
uint16_t net_htons(uint16_t hostshort) {
return NET_HTONS(hostshort);
}
@@ -735,8 +710,7 @@ uint16_t net_htons(uint16_t hostshort)
* 返回值:主机序端口
* 限定条件:无
*/
uint16_t net_ntohs(uint16_t netshort)
{
uint16_t net_ntohs(uint16_t netshort) {
return NET_NTOHS(netshort);
}
@@ -746,8 +720,7 @@ uint16_t net_ntohs(uint16_t netshort)
* 返回值:网络序 IP
* 限定条件:无
*/
uint32_t net_htonl(uint32_t hostlong)
{
uint32_t net_htonl(uint32_t hostlong) {
return NET_HTONL(hostlong);
}
@@ -757,8 +730,7 @@ uint32_t net_htonl(uint32_t hostlong)
* 返回值:主机序 IP
* 限定条件:无
*/
uint32_t net_ntohl(uint32_t netlong)
{
uint32_t net_ntohl(uint32_t netlong) {
return NET_NTOHL(netlong);
}
@@ -769,8 +741,7 @@ uint32_t net_ntohl(uint32_t netlong)
* 限定条件:无
* 函数说明:上层据此判断"监听 Socket 是否随客户端一同失效"(单连接模型)
*/
net_sock_t *net_get_sock(int sockfd)
{
net_sock_t *net_get_sock(int sockfd) {
if (sockfd < 0 || sockfd >= NET_MAX_SOCKETS) {
return NULL;
}
@@ -790,8 +761,7 @@ net_sock_t *net_get_sock(int sockfd)
* 限定条件:socket 已创建
* 函数说明:经 Winsock getsockname 读取实际绑定地址
*/
int net_getsockname(int sockfd, struct net_sockaddr *addr, int *addrlen)
{
int net_getsockname(int sockfd, struct net_sockaddr *addr, int *addrlen) {
struct sockaddr_in wsaddr;
int wslen;