Files
STM32F4-Base/docs/子系统设计/网络配置说明.md
T
super_agent_bot ad7338365c
CI / 静态门禁 (pre-commit) (push) Failing after 6m14s
CI / 主机侧单测 (MSVC) (push) Successful in 54s
CI / 静态门禁 (pre-commit) (pull_request) Failing after 4m35s
CI / 主机侧单测 (MSVC) (pull_request) Successful in 47s
feat(sntp): 板端 SNTP 校时接入——coreSNTP 序列化器 + [sntp] 段 + 设置页(#73)
- vendored coreSNTP v2.0.0 序列化器(MIT,仅 serializer+LICENSE,零堆),
  48 字节报文编解码在库,节奏与准入判据在本方(RFC 4330 §10 调研口径)
- App/sync/time_sntp.c 挂 timeSyncTask 的 8888 事件循环,等待切片 ≤50 ms,
  不饿任务狗与 IWDG;懒建 UDP socket,代际变化/禁用/死错误码即关闭归还
- 防伪 = OriginTimestamp 逐位等于发出时 T1(含低 16 位随机小数位);
  mode/stratum/闰秒指示/KoD 按 RFC 拒收;DENY·RSTR 换服务器、RATE 只退避
- 主备轮换 + 失败指数退避(5 s 起、60 s 封顶)+ 首轮 1~5 分钟随机错峰;
  成功恢复 poll_min 周期(1~1440 分,出厂默认 60,默认不启用不发包)
- 钟面 = 本地时间:UTC+8 固定偏移落 sys_clock_set_unix(§1.1 时基裁定,
  第三个写入口,装置仍不存时区);|offset|<2 s 只记日志不步进,冷启动或
  更大偏差步进并回写 SD2506,留痕 [SNTP] step 与 syslog OPER
- 首个校验通过的同步置 SYS_EVT_TIMESYNC_READY(就绪位,消费方按需 NoClear)
- [sntp] 配置段(enable/server1/server2/poll_min)属主 sntp_cfg.c,
  注册在 net_cfg_load();UI 页 31「SNTP 设置」(密码叶):启用开关 +
  主/备服务器 octet 编辑 + 周期(分) + 保存,复用 net_cfg_save_request 链
- 测试与门禁:test/host/sntp 新套件(报文/防伪/KoD/退避周期/阶跃域/配置
  注册表)、net_cfg 与 time_sync 套件补 fake、黄金参考 66→74 张零漂移、
  字符集 228 字、Keil 0 错 0 警(RO +5,848 B 含字体)、覆盖率基线回填
- 文档:墙钟维护说明 §16、网络配置说明 [sntp] 节、配置文件设计说明变更记录、
  产品需求 FR-TIME-3 与 8.3/9.1.2 台账、UI 补齐规划/UI补齐 31 叶口径、
  登记簿销项并登记「SNTP 校时真机判据」等台架(PC 时间源 192.168.31.161/.13)
2026-11-04 16:20:22 +08:00

22 KiB
Raw Blame History

网口设置页配置说明

版本:v2.3 日期:2026-10-11 适用工程:STM32F4-Base(STM32F407ZGTx + CH395F 以太网控制器) 范围:UI「网口设置」页可配置的网口参数(IP 地址 / 子网掩码 / 默认网关 / MAC 地址)—— 参数与默认值、持久化、生效链路、页面操作与权限。


0. 速览

项目 内容
可配置 IP 地址、子网掩码、默认网关、MAC 地址
入口 屏幕:通讯参数 → 网口设置(修改密码 123 可编辑;查看密码 000 只读)
存储 NAND Flash 文件 /config.ini(INI [network] 段,通用配置文件,掉电不丢);旧版 /cfg/netcfg.bin 不再读取(存在则忽略,见 §3.2)
生效 按「保存」后立即生效(网络重建约 1~3s,既有 TCP 连接会断开,无需重启)
工厂默认 192.168.31.100 / 255.255.255.0 / 192.168.31.1 / 芯片内置 MAC

典型操作(改 IP):

  1. 屏幕进入 通讯参数 → 网口设置,输入修改密码 123
  2. 选中 IP地址 行 → 回车进编辑 → ↑/↓ 调数字、←/→ 移光标 → 回车确认
  3. 选中 保存 行 → 回车 → 显示 OK
  4. 约 1~3 秒后设备在新 IP 上恢复服务(FTP / 对时 / 远程显示自动重建监听)

1. 可配置参数与工厂默认值

定义在 Drivers/BSP/NETCFG/net_cfg.h 的 net_cfg_t:

参数 字段 工厂默认 说明
IP 地址 ip[4] 192.168.31.100 静态 IP(不启用 DHCP)
子网掩码 mask[4] 255.255.255.0 /24
默认网关 gw[4] 192.168.31.1
MAC 地址 mac[6] 全零 全零 = 不覆盖芯片内置 MAC(见 §2)

工厂默认值是单一来源:net_cfg.c 顶部 NET_CFG_DEF_* 宏,同时用于 s_cfg 静态初始化与 s_defaults(引擎注册的 p_defaults 目标),避免两处漂移。

RAM 副本自启动即有效:s_cfg 以工厂默认值静态初始化(落 .data),不依赖 net_cfg_load() 是否被调用——即便存储异常,页面与网络拿到的也是有效配置而非全零。


2. MAC 地址语义

存储值 net_cfg_get_mac() 返回 网络初始化时
非全零 存储的 MAC 写入芯片 EEPROM
全零(默认) 芯片实际 MAC 影子(已回写时);否则全零 不写,保持芯片内置 MAC
  • 芯片实际 MAC 由 netTask 在网络初始化成功后读回,经 net_cfg_set_active_mac() 存入影子区——供页面只读显示(页面不直接触 SPI)。
  • MAC 写芯片 EEPROM,每上电重放同值幂等。

3. 持久化

3.1 配置文件(INI /config.ini)

网口参数是通用配置文件 /config.ini 的一个段(NAND 卷根,UTF-8/CRLF,文本编辑器可直接改):

; ============================================================
; STM32F4-Base 通用配置文件
; 格式: INI (UTF-8 / CRLF),本文件为配置唯一来源
; - 以 ';' 或 '#' 开头的行为注释,保存时保留
; - 未知段/键保存时保留;缺失段/键保存时写回
; - 编辑后经 FTP 上传或设备端保存,设备 4s 沉降后自动重载
; ============================================================

[network]
ip=192.168.31.100
mask=255.255.255.0
gw=192.168.31.1
mac=00:00:00:00:00:00

出厂模板同时含 [ftp] 段(user / pwd_hash / write,见 §3.4)——本块只展示 [network] 部分。

  • 加载校验(逐键容错):单个键值非法(越界/格式错)不影响其他键——非法键回工厂默认并留痕(parse: [network] <键> value invalid);文件缺失 → 自动生成本模板;文件 > 4KB = 损坏 → 工厂默认 + 重建模板(坏配置不带崩网络)。
  • 保存(外科手术式):注释 / 未知段 / 未知键逐行保留,受管键按 RAM 副本原位改写、缺失键补写;写盘 = 临时文件 /config.TMP + f_rename 原子替换(掉电不损坏目标文件)。
  • 外部变更自动重载(P4 阶段接入):2s 轮询检测 (size, mtime) 变化、4s 沉降(连续 2 次轮询稳定)后重载 [network] 段并重建网络——FTP 上传编辑后的文件无需重启即生效。

完整设计(引擎 / 双端 / 并发模型 D15)见 docs/子系统设计/配置文件设计说明.md。

3.2 旧版二进制档 /cfg/netcfg.bin:已不再兼容(2026-10-10)

旧版格式 /cfg/netcfg.bin(28B:magic 'NCFG' + ver + CRC-16/MODBUS + 18B 字段)的"首次启动自动迁移"已于 2026-10-10 删除(net_cfg_legacy.c/h 整体移除,该格式的解析代码不再存在)。

/config.ini /cfg/netcfg.bin 行为
缺失 存在(有效或无效都一样) 生成出厂模板 → 工厂默认;旧档被忽略(不读、不删、不迁移)
缺失 缺失 生成出厂模板 → 工厂默认
存在 — 正常加载现有文件
  • 删除理由:该一次性路径把整条配置写链(net_cfg_save → cfg_file_save → cfg_store_write_atomic → f_rename → FatFS → dhara FTL)无条件挂进启动期调用图,使 defaultTask 的 armlink 静态最坏栈链 +600 B;而本仓库不存在携带旧档的设备。
  • 对使用方的影响:卷上仍残留旧档的设备升级本版本后,网口配置回落工厂默认(192.168.31.100/24、gw .1),需经 UI「网口设置」或 FTP 上传 /config.ini 重新配置。

3.3 存储后端(双端)

App/cfg/cfg_file_store.h 定义接口(带路径的文件操作),两平台各一份实现(互斥编译):

平台 文件 位置
MCU App/cfg/cfg_file_store_mcu.c NAND 上 FatFS /config.ini(/config.TMP + f_rename 原子写)
模拟器 simulator/sim/cfg_file_store_sim.c 工作目录本地文件 sim_config.ini(fopen/rename)

INI 格式两端一致,文件可互读;mtime 变更令牌:MCU = FAT 打包时间(fdate<<16\|ftime,分钟级粒度),模拟器 = 宿主文件 mtime(秒级)。

3.4 [ftp] 段:FTP 鉴权(2026-10-11 新增)

FTP 服务(lftpd,:21)自 2026-10-11 起启用口令鉴权。配置与 [network] 同文件、同引擎(net_cfg_load() 内统一注册,键表与工厂默认见 Drivers/BSP/NETCFG/ftp_cfg.c/h;鉴权状态机在 Drivers/BSP/NET/lftpd/lftpd_auth.c/h,纯函数、主机侧可测):

[ftp]
user=admin
pwd_hash=d82494f05d6917ba02f7aaa29689ccb444bb73f20380876cb05d1f37537b7892
write=1
键 类型 工厂默认 说明
user STR(≤15 字符) admin 期望用户名,大小写不敏感
pwd_hash STR(64 位 hex) d82494f05d6917ba02f7aaa29689ccb444bb73f20380876cb05d1f37537b7892(即口令 admin) SHA-256(user‖password) 摘要,hex 大小写不敏感
write UINT(0/1) 1 1 = 允许 STOR/DELE;0 = 写命令一律 550 拒(只读卷)

鉴权流程:

  1. USER:不论用户名对错一律回 331(不泄露"用户是否存在";错用户名在 PASS 阶段仍走同耗时哈希路径拉平时间)。
  2. PASS:计算 SHA-256(期望用户名‖口令),与 pwd_hash 恒定时间比较 → 对回 230、错回 530。
  3. 未登录命令门:登录成功前仅 USER / PASS / QUIT / FEAT / SYST / NOOP 放行,其余命令一律 530。
  4. 失败锁定:连续 5 次失败 → 锁定 60 s(窗内所有 PASS 直接 530、不再计数);登录成功清零计数;锁定状态全局跨会话、易失(重启清零)。

改口令步骤(无 UI 入口;下载 /config.ini 编辑后上传,或经串口/烧录工具改写):

  1. 生成新摘要 hex(对 user + 新口令 拼接串做 SHA-256;下例中 user / pwd 为占位,替换为字符串字面量,如 ('admin'+'新口令')):

    python -c "import hashlib;print(hashlib.sha256((user+pwd).encode()).hexdigest())"
    
  2. 把结果写入 [ftp] 段的 pwd_hash=(hex 大小写随意);

  3. 上传回设备——配置引擎 poll 沉降 ≈4 s 后重载,下次登录生效(既有会话不受影响)。

忘口令恢复路径:口令不可从 pwd_hash 反推(这正是哈希的意义)——经串口/烧录工具改写配置,或重烧固件回落出厂默认,然后立即改口令。

出厂默认口令告警:pwd_hash 仍为出厂值时,每次启动打 INFO 锚点 [FTP] using factory default password(改了 pwd_hash 即消失)。

诚实边界:FTP 协议明文传输口令——本方案挡的是未授权访问,不挡网络嗅探(CH395F 上实现 TLS 不现实)。pwd_hash 只防 /config.ini 泄露后的离线口令还原,盐 = 用户名(无每机随机盐,局域网威胁模型下够用)。

3.5 [run_par] 段:运行参数(2026-10-25 新增,「数据可信」运行参数段一项)

遥测死区 9 点的持久载体(引擎属主 defaultTask;现场远程写入口 = 104 段 0x8030~0x8038,本段键供 FTP 手改 / 排障直读,逐项语义与地址表 → docs/子系统设计/IEC104上行设计说明.md §3.4)。值 = 工程量毫单位 int32 有符号 (db_ua=500 即 0.5 V;电流域 db_ia=5 即 0.005 A;频率域 db_freq=500 即 0.5 Hz)。

键 通道 工厂默认 104 写路径合法域(毫单位)
db_ua db_ub db_uc db_un 电压死区 500 0 ~ 50000(50 V)
db_ia db_ib db_ic db_in 电流死区 5 0 ~ 1000(1 A)
db_freq 频率死区 500 0 ~ 5000(5 Hz)
  • 键数 9 ≤ 16,通道系数覆盖不落本段——系数唯一真源 = [adc_cal] / [adc_cal_ofs] 两段(标定落盘与整定入口布局,docs/任务规划/数据可信.md §4.4;104 0x8040~0x804F 写 = adc_cal_set 代理,lead 裁②a)。
  • 守卫在写路径(104/壳 API 拒 NaN/负/越程);文件通路引擎照收(同 adc_cal 的 「人工编辑 + 沉降去抖」契约)——死区超程只让上送变钝、不毁量纲,无合法带哨兵。
  • 生效链路:load/poll 原地改副本 → 104 COV 每拍实时读(无回调,104 改读快照与运行参数段契约); 104 写成功 → SYS_EVT_RUN_PAR_SAVE → 本任务 cfg_file_save() 整档外科落盘。

3.6 [comm] 段:IEC 60870-5-104 通讯参数(2026-10-26 新增,「UI 补齐」波次里的非 UI 前置项,道G task-8)

104 被控站的公共地址与监听端口持久载体(段属主 = App/protocol/iec104/ 配对模块: 工厂默认与合法带见 iec104_comm.h、键表与实现见 iec104_comm.c;注册 iec104_comm_init() 在 app_main_init() 内核前——「先注册后 load」契约同 [adc_cal] / [run_par]):

键 含义 工厂默认 getter 合法带(带外自愈回默认)
ca 公共地址(= 链路地址,ASDU 头 2B) 1 1 ~ 65535
port 被控站 TCP 监听端口 2404 1024 ~ 65535
  • 生效 = 改后重启(与 [network] 免重启重建不同,验收口径 → docs/任务规划/UI补齐.md §2 第 5 行):iec104Task 启动时读一次 getter; 端口另在下次重 bind(拆链/代次重建)自然生效。不挂段回调、不新增事件位—— CH395F 单连接 socket 上「换端口/拒绝重听」= close + re-listen,做成热生效 会被端口扫描打成 SPI/看门狗风暴(详论 → 本段只登记,正文唯一详述处 = docs/子系统设计/IEC104上行设计说明.md §8)。
  • 主站地址(accept 侧 IP 白名单)本段不做:无既有消费点 + 上述拒绝代价 + 配错即锁死真主站,待送检/现场需求立项;读者勿假设该键已存在。
  • 落盘:UI 保存(task-9)经 net_cfg_save_request() → SYS_EVT_CFG_SAVE 整档 外科 save;引擎属主 = defaultTask 不变。
  • 容量台账:本段上线后 /config.ini 受管段 = 6/8([network] 4 键 / [ftp] 3 键 / [adc_cal] 9 键 / [adc_cal_ofs] 8 键 / [run_par] 9 键 / [comm] 2 键);段/键上限 的机器钉 = test/host/cfg_file TC-CONFIG-056/057。

3.7 [sntp] 段:SNTP 校时参数(2026-11-04 新增,板端 SNTP 客户端接入,#57 调研结论)

板端 SNTP 客户端的持久载体(消费方 = App/sync/time_sntp.c,挂在 timeSyncTask 既有循环上,48 字节报文走 PR #74 后的 UDP socket 通道;数据本体 = Drivers/BSP/NETCFG/sntp_cfg.h/.c(纯段数据 + 读写出口,不依赖引擎头——分层门禁 layer-deps 口径),段描述符由 net_cfg.c 的 s_sntp_register() 组装,注册编排 = net_cfg_load() 统一调用——与 [ftp] 同路径,「先注册后 load」成立):

键 含义 工厂默认 getter 合法带(带外自愈回默认)
enable 校时开关 0(出厂关闭) 0/1,非 1 一律视为关
server1 主 SNTP 服务器 0.0.0.0(留空) 点分 IPv4 字面量(引擎 s_decode_ip4 解析;无 DNS)
server2 备 SNTP 服务器 0.0.0.0 同上;主服务器超时/拒绝(KoD DENY·RSTR)自动切换
poll_min 轮询周期(分钟) 60 1 ~ 1440(带外读回 60,不写回 RAM,sntp_cfg_poll_min())
  • 零足迹口径:出厂默认关闭 + 服务器留空 → 不开 socket、不发一个字节(与 「FTP 未配置不监听」一致);配了可达时服务器的现场才启用。
  • 生效链路:页面保存行 → SYS_EVT_CFG_SAVE 整档外科落盘(引擎属主 defaultTask 不变);客户端每轮直接读 RAM 副本,无段回调、不新增事件位。网络重建 (代次变化)时 UDP socket 随芯片复位被弃用,客户端检测 net_get_generation() 变化后关闭旧 fd 并重新 1~5 分钟随机散布首轮(RFC 4330 §10 口径)—— 即 §4.2 自愈机制在 UDP 客户端侧的自然延伸(表内 TCP 三服务之外)。
  • 时钟面口径:校验通过的服务器时间折算为 UTC 后恒加 28800 s(本地 UTC+8,单一「本地钟面」口径,#56 裁决,见 docs/子系统设计/系统墙钟时间维护说明.md §1.1;工程不存时区)再交 sys_clock_set_unix()(内部含 SD2506 RTC 写回);|offset| ≤ 2 s 只记录 不拨针(防 RTC 无谓磨损)。冷启动(钟面无效)直接采用服务器 T3。 防欺骗/退避/KoD 细则 → App/sync/time_sntp.c 文件头 + test/host/sntp(TC 命名即判据)。
  • 容量台账:本段上线后 /config.ini 受管段 = 7/8(前 6 段见 §3.6,本段 4 键)。

4. 生效链路

4.1 上电启动

sequenceDiagram
    autonumber
    participant DT as defaultTask
    participant NT as netTask
    participant CFG as net_cfg
    participant CH as CH395F

    Note over DT,NT: 上电:CubeMX 已创建任务与事件组,调度器启动
    DT->>DT: FatFS 挂载(f_mount;无卷则 f_mkfs)
    DT-->>NT: 置 SYS_EVT_STORAGE_READY(就绪屏障)
    NT->>NT: 等 SYS_EVT_STORAGE_READY(≤10s;超时用工厂默认继续)
    NT->>CFG: net_cfg_load()
    Note over CFG: 注册 [network] 段 → 读 /config.ini;缺失/非法键 → 工厂默认
    CFG-->>NT: RAM 副本(有效)
    NT->>CFG: net_cfg_get() → net_cfg_fmt_ipv4()
    CFG-->>NT: "192.168.001.100"
    NT->>CH: 初始化网络(下发 IP / 掩码 / 网关 / MAC)
    CH-->>NT: 芯片实际 MAC
    NT->>CFG: net_cfg_set_active_mac()(MAC 影子)
    NT->>NT: 置 SYS_EVT_NET_READY(广播网络就绪)

4.2 保存后立即生效

保存网口参数后,设备立即按新参数重建网络,无需重启。

机制:请求 → netTask 重建 → 代次号 → 服务自愈

约束与对策:网络重建会复位 CH395F,所有监听 Socket 随之失效;而三个 TCP 服务(FTP :21 / 对时 :8888 / 远程显示 :7003)的监听由各自任务持有。为此引入"网络代次号"——各服务检测到代次变化后主动重建监听,在新 IP 上恢复服务。

sequenceDiagram
    participant UI as 网口设置页
    participant CFG as net_cfg
    participant NT as netTask
    participant NS as net_socket
    participant SVC as FTP/对时/远程显示

    UI->>CFG: 保存行 ENTER → net_cfg_save()(写盘)
    CFG->>NT: net_cfg_request_apply() → 回调置 SYS_EVT_NET_RECONFIG
    NT->>NT: 主循环检测到该位 → 重建网络(新 IP/掩码/网关/MAC)
    NT->>NS: net_generation_inc()(代次号 +1,此刻网络已可用)
    NT->>SVC: 重新广播 SYS_EVT_NET_READY
    SVC->>SVC: 轮询发现代次变化 → 关闭旧监听 → 重建监听(新 IP)

三个服务的自愈点:

服务 端口 检测位置 自愈方式
FTP 21 lftpd_inet_accept() 代次变化 → 返回 -1 → lftpd_start 外层循环重建监听
对时 8888 time_sync_task() 的 accept 循环 代次变化 → 关旧监听 → 回外层重建
远程显示 7003 ui_net_sink_poll() 代次变化 → 关旧监听/客户端 → 重建

关键设计点:

  1. SPI 归 netTask 独占:UI 只置事件位,不直接操作 CH395F。
  2. 代次号在链路就绪后才递增:避免服务在网络未就绪时抢先重建,也避免 uiTask 阻塞在消息队列上冻结界面。
  3. 无回调 = 空操作:模拟器不注册应用回调,行为退化为"仅写盘"。
  4. 既有连接必断:IP 变更导致连接不可达,属网络层语义。

5. 页面操作(网口设置页)

菜单路径:通讯参数 → 网口设置(菜单节点 30,行尾 #P 需密码)。页面模块 Drivers/BSP/UI/ui_page_net_cfg.c。

5.1 页面布局

行 名称 值格式
0 IP地址 192.168.001.100(每段 %03u 补零,定长 15 字符 = 4 段 × 3 位 + 3 个点)
1 子网掩码 255.255.255.000
2 默认网关 192.168.001.001
3 MAC地址 A4:94:B6:12:34:56(6 字节十六进制,冒号分隔)
4 保存 ENTER → 保存后显示 OK / ERR

5.2 权限

ui_pwd_def.h 编译期密码:

输入的密码 授予权限 页面行为
查看密码 000 UI_PERM_VIEW 只读:ENTER 无效,仅可浏览
修改密码 123 UI_PERM_MODIFY 可编辑:ENTER 进编辑模式

5.3 编辑模式

ENTER 进入选中地址行 → ↑/↓ 调活动字节(0..255 环绕)、←/→ 移字节光标(首↔末环绕)、ENTER 确认退出。调整实时落 RAM 副本(net_cfg_set),只有保存行 ENTER 才写盘并应用(net_cfg_save + net_cfg_request_apply);ESC 退出不写盘、改动丢弃(重启后恢复上次保存值)。

值格式与解析约定:页面写定长 %03u 字符串 → 网络初始化按十进制逐段解析、容忍前导零(如 "001" → 1)。


6. 文件与 API 索引

文件 职责
Drivers/BSP/NETCFG/net_cfg.h/.c 配置核心:RAM 副本 + 工厂默认 + 加载/保存编排 + MAC 影子 + IPv4 格式化([network] 段注册;net_cfg_load() 一并注册 [ftp]/[sntp])
Drivers/BSP/NETCFG/sntp_cfg.h/.c [sntp] 段核心:RAM 副本 + 工厂默认 + 注册 + poll_min 带外自愈出口(App/sync/time_sntp.c 每轮只读)
App/cfg/cfg_file.h/.c 通用配置文件引擎(双端共享核心:解析/校验/外科保存/模板/沉降轮询)
App/cfg/cfg_file_store.h 存储后端接口(带路径的文件操作)
App/cfg/cfg_file_store_mcu.c MCU 后端:FatFS /config.ini(/config.TMP + f_rename 原子写)
simulator/sim/cfg_file_store_sim.c 模拟器后端:本地 sim_config.ini
Drivers/BSP/UI/ui_page_net_cfg.c 网口设置内容页(显示 / 编辑 / 保存)
Drivers/BSP/UI/ui_pwd_def.h 编译期密码(查看 000 / 修改 123)
App/task/net_task.c 上电加载配置 + 消费"立即应用"请求重建网络
Drivers/BSP/NET/net_socket.h/.c 网络代次号(服务自愈依据)

对外 API(net_cfg.h):

API 说明
net_cfg_load() 注册 [network] 段 + 从 /config.ini 加载到 RAM 副本;缺失/非法键回退工厂默认(恒返回 0)
net_cfg_save() 经 cfg_file 引擎写 /config.ini(外科手术式保存);0 成功 / -1 失败
net_cfg_request_apply() 请求立即应用(页面保存成功后调用)
net_cfg_set_apply_cb() 注册"立即应用"平台回调
net_cfg_get() 取 RAM 副本只读指针(恒非空)
net_cfg_set() 更新 RAM 副本(不写盘)
net_cfg_set_active_mac() 回写芯片实际 MAC 影子(netTask 调)
net_cfg_get_mac() 取显示用 MAC(存储非零 → 存储;否则影子;否则全零)
net_cfg_fmt_ipv4() 4 字节 → "192.168.001.100" 定长 15 字符串(缓冲 len ≥ 16)

7. 陷阱

  1. 保存即生效,但连接会断:保存后重建网络(约 1~3s),既有 TCP 连接(FTP / 对时 / 远程显示)会断开并自动重建监听——IP 变更的必然结果,非缺陷。
  2. MAC 全零是哨兵,不是"MAC 为 0":要恢复芯片内置 MAC,把 MAC 字段改回全零并保存。
  3. 配置存在 NAND 上:存储挂载失败时 net_cfg_load 回退工厂默认,网络仍能起,但保存会失败(页面显示 ERR)。
  4. 变更令牌是分钟级:FAT 时间为分钟粒度——同分钟内重写同长度文件,轮询检测不到变化(罕见;下次保存/改长度即恢复检测)。
  5. 改配置需"修改密码":查看密码 000 进页面是只读,ENTER 无效(防误改)。
  6. 新增 TCP 服务需处理重建:须在其监听循环中检测 net_get_generation() 变化并重建监听,否则网络重建后不再可达(见 §4.2)。

8. 相关文档

主题 文档
CH395F 已知陷阱 docs/问题记录/CH395F_Trap_Records.md
网络测试指南 docs/测试说明/板级测试/CH395F_Test_Guide.md
启动顺序 / 就绪屏障 docs/架构设计/项目启动顺序管理.md
项目分层架构 docs/架构设计/项目架构总览.md
内容页框架(含网口设置页) docs/UI设计/内容页架构.md