diff --git a/Drivers/BSP/CH395F/ch395f.c b/Drivers/BSP/CH395F/ch395f.c index 2177ab22..0bf815fa 100644 --- a/Drivers/BSP/CH395F/ch395f.c +++ b/Drivers/BSP/CH395F/ch395f.c @@ -692,7 +692,7 @@ ch395f_status_t ch395f_init(void) { * 函数功能:设置CH395的IP地址(低字节在前) * 入口参数:p_ip - 4字节IP地址指针 uint8_t* 192.168.x.x格式 * 限定条件:1. p_ip不可为NULL - * 2. 芯片已初始化 + * 2. 必须在 ch395f_init() 之前调用(手册 §9.2.1:SET_IP 先于 INIT_CH395) */ void ch395f_set_ip_addr(uint8_t *p_ip) { uint8_t i; @@ -721,7 +721,7 @@ void ch395f_set_ip_addr(uint8_t *p_ip) { * 函数功能:设置CH395的网关IP地址(低字节在前) * 入口参数:p_gwip - 4字节网关IP指针 uint8_t* * 限定条件:1. p_gwip不可为NULL - * 2. 芯片已初始化 + * 2. 必须在 ch395f_init() 之前调用(手册 §9.2.1:SET_GWIP 先于 INIT_CH395) */ void ch395f_set_gwip_addr(uint8_t *p_gwip) { uint8_t i; @@ -750,7 +750,7 @@ void ch395f_set_gwip_addr(uint8_t *p_gwip) { * 函数功能:设置CH395的子网掩码(低字节在前) * 入口参数:p_mask - 4字节子网掩码指针 uint8_t* * 限定条件:1. p_mask不可为NULL - * 2. 芯片已初始化 + * 2. 必须在 ch395f_init() 之前调用(手册 §9.2.1:SET_MASK 先于 INIT_CH395) */ void ch395f_set_mask_addr(uint8_t *p_mask) { uint8_t i; @@ -779,8 +779,9 @@ void ch395f_set_mask_addr(uint8_t *p_mask) { * 函数功能:设置CH395的MAC地址(低字节在前,存入EEPROM) * 入口参数:p_mac - 6字节MAC地址指针 uint8_t* * 限定条件:1. p_mac不可为NULL - * 2. 芯片已初始化 - * 函数说明:执行耗时约30us(TE5) + * 2. 必须在 ch395f_init() 之前调用(手册 §9.2.1 步骤①:SET_MAC 写 EEPROM, + * INIT_CH395 加载 MAC;顺序反了则本次上电不生效,回落芯片内置/上次值) + * 函数说明:执行耗时约30us(TE5);写芯片 EEPROM,每上电重放同值幂等 */ void ch395f_set_mac_addr(uint8_t *p_mac) { uint8_t i; diff --git a/Drivers/BSP/NET/net_socket.c b/Drivers/BSP/NET/net_socket.c index b06aee38..dd2ad3d8 100644 --- a/Drivers/BSP/NET/net_socket.c +++ b/Drivers/BSP/NET/net_socket.c @@ -281,6 +281,15 @@ static bool s_mac_is_zero(const uint8_t *p_mac) { ch395f_set_keepalive_intvl(NET_KEEPALIVE_INTVL_MS); /* 5 秒探测一次*/ ch395f_set_keepalive_cnt(NET_KEEPALIVE_CNT); /* 最多探 3 次*/ + /* 设置 MAC(手册 §9.2.1 步骤①:SET_MAC 必须在 INIT_CH395 之前——SET_MAC 写芯片 + * EEPROM,而 INIT_CH395 会初始化/加载 MAC;顺序反了则本次上电芯片仍用旧 MAC, + * UI 配置的 MAC 不生效(回落芯片内置/上次值),设备在线身份与 UI 显示不符。 + * P1-7,2026-10-04);NULL 或全零 = 保持芯片内置 MAC,不下发; + * 写 EEPROM,每上电重放同值幂等 */ + if (mac != NULL && s_mac_is_zero(mac) == false) { + ch395f_set_mac_addr((uint8_t *)mac); + } + /* 设置网络参数(必须在 INIT_CH395 之前调用 */ if (ip != NULL) { uint8_t ip_arr[4]; @@ -307,12 +316,6 @@ static bool s_mac_is_zero(const uint8_t *p_mac) { return NET_ERR_RETURN_1(NET_ERR); } - /* 设置 MAC(须在协议栈初始化之后,限定条件"芯片已初始化";写芯片 EEPROM, - * 每上电重放同值幂等);NULL 或全零 = 保持芯片内置 MAC */ - if (mac != NULL && s_mac_is_zero(mac) == false) { - ch395f_set_mac_addr((uint8_t *)mac); - } - /* 多 Socket 模式:为 Socket 0~7 各分配独立收发缓冲(必须在 OPEN_SOCKET 之前) */ /* 手册(§5.45):48 块 × 512B = 24KB;上电芯片默认仅给 Socket 0~3 分配(接收 8 / 发送 4 块) */ /* Socket 4~7 为 NULL,用到 8 个 Socket 必须重分配;单 Socket 块数为固定布局(ch395f.h,2026-09-22 起与 MSS 解耦) */ diff --git a/Drivers/BSP/NET/net_socket.h b/Drivers/BSP/NET/net_socket.h index d28c0b34..766e48e5 100644 --- a/Drivers/BSP/NET/net_socket.h +++ b/Drivers/BSP/NET/net_socket.h @@ -68,9 +68,9 @@ typedef struct { * mac - MAC 地址(6 字节,低字节在前),NULL 或全零使用芯片内置 * 返回值:0 成功,-1 失败 * 限定条件:SPI2 已正确初始化 - * 函数说明:必须在所有网络操作之前调用;mac 非空且非全零时于协议栈 - * 初始化成功后设置(ch395f_set_mac_addr 写芯片 EEPROM, - * 每上电重放同值幂等) + * 函数说明:必须在所有网络操作之前调用;mac 非空且非全零时在协议栈初始化 + * (CMD_INIT_CH395)之前下发(手册 §9.2.1 步骤①:SET_MAC 写芯片 EEPROM, + * INIT_CH395 加载 MAC——顺序反了则本次上电不生效,回落芯片内置/上次值) */ int net_init(const char *ip, const char *mask, const char *gateway, const uint8_t *mac); diff --git a/docs/待处理内容.md b/docs/待处理内容.md index b9b2a844..22d2054a 100644 --- a/docs/待处理内容.md +++ b/docs/待处理内容.md @@ -37,7 +37,7 @@ | 级别 | 数量 | 关键项 | |---|---|---| -| **P1** | 2 (+1 收尾) | **P1-1 ADC 采样路径产品构建中死亡**;**P1-7 MAC 写入顺序**(待 CH395F 手册 §9.2.1);P1-10 测试固件构建实测闭环(主体已闭环,见 §3.1) | +| **P1** | 1 (+1 收尾) | **P1-1 ADC 采样路径产品构建中死亡**;P1-10 测试固件构建实测闭环(主体已闭环,见 §3.1) | | **P3** | 6 | 卫生项:P3-1/2/4/6/8/11,可随其他修改顺手处理 | | 登记簿 | 10 | 网络:N-2(49s 日志静默,**低风险观察项**)、N-3(L5 基线重验)、N-4(pending 二期)、N-16(A2/A4 专项负向验证)、N-17(探针窗口心跳缺口);存储/日志:**S-1(defaultTask 栈余量 10%,需尽快处理)**、S-2(boot_log 存档)、S-3(USART1 TX-only 根治)、S-4(dhara 重试自旋)、S-5(可选全序列卷锁) | | 测试/基础设施 | 5 | T-7(CI runner 未就绪)+ 测试架构专项 **S12**(断言宏)、**S1-c**(可选单测)、**A-4**(采集链路测试约束)、**A-5 残余**(CI 体积门禁盲区) | @@ -63,13 +63,7 @@ > 排序原则:**先降风险(产品级故障)→ 再补功能(核心链路)→ 再清结构债 → 最后卫生**。 > 本节只给「做什么 / 为什么现在 / 入口在哪 / 完成判据」,明细指向 §3 对应条目。 -### 2.1 阶段 A 残余:立即执行(改动小、风险高) - -| 序 | 任务 | 为什么现在 | 入口 | 完成判据 | -|---|---|---|---|---| -| **A5** | **P1-7 MAC 写入顺序** | 先确认 CH395F 手册 §9.2.1(INIT 是否锁存 MAC)再改;若锁存则 UI 配置 MAC 不生效、设备在线身份错误 | `Drivers/BSP/NET/net_socket.c` `net_init()` | 依手册结论调整顺序或文档化"无需调整" | - -### 2.2 阶段 B:核心功能补齐(产品价值最高,需产品定义确认) +### 2.1 阶段 B:核心功能补齐(产品价值最高,需产品定义确认) > 目标:让 DTU 真正采到数——这是当前**最大的功能空洞**,**当前最高优先级**。 > 一旦 B0 产品定义明确,即可与 B3(纪律门禁)并行启动。 @@ -83,7 +77,7 @@ **建议**:B3 与 B0 并行推进(前者是纪律,后者问甲方);**E-58 修复应在 B1 动消费者之前完成**。 -### 2.3 阶段 C:结构债清理(二期)+ 存储侧健壮性 +### 2.2 阶段 C:结构债清理(二期)+ 存储侧健壮性 | 序 | 任务 | 说明 | 出处 | |---|---|---|---| @@ -93,7 +87,7 @@ | **C5** | 一档剩余 | E-49(RS485 DE 收尾)、E-15(ringbuf 定去留——**已确认零调用者,倾向删除**)、E-61(SD2506 注释订正)、E-16(cfg_file 段名长度)、E-26(UDP 定案,倾向移除)、E-23、E-30 | 一档/二档 | | **C6** | **USART1 TX-only 结构根治**(S-3) | 灭 ORE 僵尸机制根源:改 `.ioc` 令 USART1 不使能 RX / PA10 不复用为 `USART1_RX` → CubeMX 重生成 → 跑 `check_cubemx_survival.py`。属结构性改动,需单开一轮 + 复跑台架闭环 | S-3 | -### 2.4 阶段 D:验证与卫生(常态化) +### 2.3 阶段 D:验证与卫生(常态化) | 序 | 任务 | 说明 | |---|---|---| @@ -103,11 +97,9 @@ | **D5** | **N-16 专项负向台架窗口** | A2/A4 负向场景:PHY 拔线(需断 DTU 侧/关受管交换机端口)、A2 芯片级 `net_init` 失败(SPI 故障注入)、A4 短写压测 | | **D6** | **N-17 探针窗口心跳缺口** | 定位 `time_sync` 监听重建为何阻塞 NET/FTP/UI(~1s 缺口,余量仅 ~0.7s);评估缩短重建重试或让掉线路径不阻塞其它任务 | -### 2.5 建议执行顺序(一图) +### 2.4 建议执行顺序(一图) ``` -【阶段 A 残余】 A5 P1-7(待 CH395F 手册 §9.2.1) - ↓ 【阶段 B 功能】 B0 产品定义确认 ─┬─ B3 E-59 门禁固化(并行) (当前最高优先) └─ E-58 原子快照 → B1 ADC → B2 RS485 ↓ @@ -121,7 +113,7 @@ ## 3. 待办详述 -### 3.1 P1(未闭环 2 项 + 1 项收尾) +### 3.1 P1(未闭环 1 项 + 1 项收尾) #### P1-1 ADC 采样数据路径产品构建中死亡 - **位置**:`App/app/app_main.c`(`tpafe5160_start_conv_irq()` 仅启动时调用一次)+ `Drivers/BSP/TPAFE5160/tpafe5160.c` @@ -130,13 +122,6 @@ - **修复建议**:周期 CONVST 重触发(定时器或任务)+ 数据消费任务;若基线版本有意不实现采集,应删除启动调用并以 `APP_ADC_ENABLE` 真实门控。 - **置信度**:high(代码级确证);P0/P1 定级取决于产品定义(见 §4 待确认)。 -#### P1-7 MAC 写入顺序违反 trap 文档 -- **位置**:`Drivers/BSP/NET/net_socket.c` `net_init()`:`ch395f_init()` → `ch395f_set_mac_addr()` -- **证据**:`docs/问题记录/CH395F_Trap_Records.md` 规定初始化顺序 SET_MAC → SET_IP → INIT_CH395 → SET_PHY;现码把 MAC 放在 INIT 之后。 -- **影响**:若 INIT_CH395 锁存 MAC 寄存器,UI 配置的 MAC 不生效(回落芯片内置),设备在线身份错误、网口排查困难。 -- **修复建议**:`set_mac_addr` 移到 `ch395f_init()` 之前;修改前对照 CH395F 手册 §9.2.1 确认 INIT 是否锁存(见 §4 待确认)。 -- **置信度**:medium。 - #### P1-10 测试固件静态 RAM 预算(基线已重建、测试缓冲已瘦身,剩构建实测闭环) - **位置**:`MDK-ARM/STM32F407-Demo/STM32F407-Demo.sct`(`RW_IRAM1 0x20000000 0x00020000` = 128KB;芯片 192KB 的上部 64KB 有意未映射,克隆芯片兼容性考量) - **历史**(2026-09-15 审计 / 09-16 复现):产品构建静态镜像曾 = 123.6KB/128KB(余量仅 4.4KB);HW 全阶段固件的 PHASE5 三缓冲(3×4093B)→ 超 8.7KB(`L6406E` 实测);NET 固件的 32KB `s_rx_buf` → 超约 28KB。 @@ -171,7 +156,7 @@ | # | 事项 | 发现 | 证据与现状 | 出处 | |---|---|---|---|---| -| S-1 | defaultTask 静态最坏链余量贴线:`storage_bring_up → … → dhara GC → SPI` 链 | 2026-09-22;2026-10-04 重采升级 | **2026-10-04 重采(升级为需尽快处理)**:产品构建(`suite=NONE`)V5 30 min 真实负载实测 **3664B/4096(余量 432B = 10%)**,**已远低于 30% 判据**。处置:栈 4096→4608(CCM 堆余量可覆盖 +512B)或 GC 链缓冲局部削减;建议**提前到阶段 B 之前**处理 | 本文件 §2.3 C4 / §6 | +| S-1 | defaultTask 静态最坏链余量贴线:`storage_bring_up → … → dhara GC → SPI` 链 | 2026-09-22;2026-10-04 重采升级 | **2026-10-04 重采(升级为需尽快处理)**:产品构建(`suite=NONE`)V5 30 min 真实负载实测 **3664B/4096(余量 432B = 10%)**,**已远低于 30% 判据**。处置:栈 4096→4608(CCM 堆余量可覆盖 +512B)或 GC 链缓冲局部削减;建议**提前到阶段 B 之前**处理 | 本文件 §2.2 C4 / §6 | | S-2 | N-2 消化后,台架 20MB 串口日志截头会丢早期 [STACK] 水位行——跨构建的"前后"栈水位对照建议固化 boot_log 快照(`%TEMP%\opencode\boot_log_*.txt`)进 `docs/测试说明/` 存档目录 | 2026-09-22 | 流程项,无代码改动 | 本文件 N-2 佐证 | | S-3 | **USART1 TX-only 结构根治(灭 ORE 僵尸机制)**——ORE 锁存在外设软复位后毫秒级重锁(PA10 悬空 + RX 使能),是 2026-10-02 台架"背靠背 drain 拉长主循环 → 喂狗节奏饥饿 → IWDG 误复位"的**机制根源**。现仅有缓解(单次 drain 250ms 预算 + 发送故障后 300ms 冷却),**未根治** | 2026-10-02(台架 gen-288) | **待办**:改 `.ioc` 令 USART1 为 TX-only → CubeMX 重生成 → 跑 `scripts/check_cubemx_survival.py`。结构性改动,需单开一轮并复跑台架闭环 | `子系统设计/控制台单写者日志设计说明.md` §12(含 O4) | | S-4 | **dhara 重试自旋残留**——`try_recover()` 的 `DHARA_MAX_RETRIES`(8) 自旋在坏块密集时仍可能长时间占用 defaultTask(喂狗点) | 2026-10-02 | 低优先:现有 `vol_lock` + 喂狗节奏缓解;若台架再出"存储侧喂狗饥饿"再排期 | `Lib/dhara/map.c` | @@ -265,7 +250,7 @@ S14 已在 workflow 显式提示"体积门禁未执行"(`::notice::`)并在 **完成判据**:存在**强制的**体积校验路径(CI 侧或本地侧),且文档明确其边界。 -> **注**:本项与 §2 C4(**S-1:defaultTask 栈 3664/4096 ≈ 10%**,需尽快处理)是同一话题的两面 +> **注**:本项与 §2.2 C4(**S-1:defaultTask 栈 3664/4096 ≈ 10%**,需尽快处理)是同一话题的两面 > ——S-1 是**具体风险**,本项是**门禁缺口**。 --- @@ -273,9 +258,8 @@ S14 已在 workflow 显式提示"体积门禁未执行"(`::notice::`)并在 ## 4. 待确认(需手册/硬件/产品定义,暂不直接改码) 1. TPAFE5160 是否有自动扫描模式(决定 P1-1 定 P0 还是 P1)。 -2. CH395F 手册 §9.2.1:`INIT_CH395` 是否锁存 MAC 寄存器(决定 P1-7 修复紧迫度)。 -3. `APP_ADC_ENABLE` / `APP_RS485_ENABLE` 是否应在产品构建真实门控模块(关联 P1-1、P3-11;当前宏已如实标注为"未接线占位",此处确认的是**是否接入真实门控**)。 -4. RS-485 PD0 DE 的半双工方向语义需硬件实测确认(本次仅静态审查)。 +2. `APP_ADC_ENABLE` / `APP_RS485_ENABLE` 是否应在产品构建真实门控模块(关联 P1-1、P3-11;当前宏已如实标注为"未接线占位",此处确认的是**是否接入真实门控**)。 +3. RS-485 PD0 DE 的半双工方向语义需硬件实测确认(本次仅静态审查)。 --- @@ -336,7 +320,7 @@ S14 已在 workflow 显式提示"体积门禁未执行"(`::notice::`)并在 > **2026-10-04 重采**:栈/堆 = **运行时高水位**(产品构建 `suite=NONE`,V5 30 min 真实负载,串口 `[STACK]`, > 证据 `/tmp/v5_soak_serial_20261003.log`);静态区 = `.map` 受管快照。 > ⚠️ **栈水位较 2026-09-21 基线明显上升**(defaultTask 2136→**3664 B**、ftpTask 1184→**2516 B**), -> 系功能与加固陆续入链所致。**S-1 需尽快处理**,见 §2.3 C4。 +> 系功能与加固陆续入链所致。**S-1 需尽快处理**,见 §2.2 C4。 | 项 | 当前值(2026-10-04) | 出处 | |---|---|---| @@ -373,6 +357,6 @@ S14 已在 workflow 显式提示"体积门禁未执行"(`::notice::`)并在 - 已闭环条目的**结论与证据沉淀进模块文档**,本文件不再重复。 - 编号一律**沿用且不回收**(P-x / N-x / S-x / T-x / S1x / A-x);`错误码传播审计.md` 的 E-xx 独立维护。 - 阶段 B 完成后重写 §1(届时 ADC/RS485 应从未闭环消失)。 -- 新增发现按既有惯例分流:能立即修的进 §2 阶段 A/C5;需排期的进 §3 对应编号空间;跨版本观察的进 §3.3(登记簿)。 +- 新增发现按既有惯例分流:能立即修的进 §2(阶段 A/C5);需排期的进 §3 对应编号空间;跨版本观察的进 §3.3(登记簿)。 - 上游引用关系:`问题记录/项目审查与优化建议报告.md`(体系层评审)、`问题记录/错误码传播审计.md`(E-xx)、 `测试说明/实机测试实施指南.md`(执行流程)——三者均不在本文件合并范围。 diff --git a/docs/网络/BSD_Socket_API_函数调用关系.md b/docs/网络/BSD_Socket_API_函数调用关系.md index 31568cdc..938da2a5 100644 --- a/docs/网络/BSD_Socket_API_函数调用关系.md +++ b/docs/网络/BSD_Socket_API_函数调用关系.md @@ -103,7 +103,7 @@ flowchart TB | 函数 | 设计作用 | 主要调用 | 意图 / 注意 | |---|---|---|---| -| `net_init(ip,mask,gw,mac)` | 芯片一次性配置:探测/复位 → 参数 → 协议栈初始化 → MAC → 8 Socket 缓冲布局 → 使能 PING | `net_pending_cancel_all` → `ch395f_check_exist` / `ch395f_reset` / `set_fun_para(0x09)` / `set_tcp_mss` / `set_retrans_count+period` / `set_keepalive_idle+intvl+cnt` → `parse_ip_string` + `set_ip_addr` / `set_gwip_addr` / `set_mask_addr`(或 `set_dhcp`)→ `ch395f_init` → `set_mac_addr` → `set_send_buf` / `set_recv_buf` ×8 → `ping_enable` | ① **重建前**先取消全部挂起 recv 并逐一通知(不通知 = 调用方永久挂死),且必须早于控制块清零与芯片复位;② 重传/KeepAlive 参数**必须**在 `ch395f_init` 之前下发;③ `fun_para=0x09`:多 Socket 模式 + TCP Server 单连接 + DISCONNECT/TIMEOUT 不清缓冲(软件排空后手动关);④ 缓冲布局每 Socket 6 块(收 4 + 发 2)×8 = 48 块恰好用尽,Socket 0~7 必须显式重分配(Trap 01/02);⑤ 捕获 `xTaskGetCurrentTaskHandle` 存入 `s_net_task_handle`(防自通知死锁的判据) | +| `net_init(ip,mask,gw,mac)` | 芯片一次性配置:探测/复位 → 参数 → MAC → 协议栈初始化 → 8 Socket 缓冲布局 → 使能 PING | `net_pending_cancel_all` → `ch395f_check_exist` / `ch395f_reset` / `set_fun_para(0x09)` / `set_tcp_mss` / `set_retrans_count+period` / `set_keepalive_idle+intvl+cnt` → `set_mac_addr` → `parse_ip_string` + `set_ip_addr` / `set_gwip_addr` / `set_mask_addr`(或 `set_dhcp`)→ `ch395f_init` → `set_send_buf` / `set_recv_buf` ×8 → `ping_enable` | ① **重建前**先取消全部挂起 recv 并逐一通知(不通知 = 调用方永久挂死),且必须早于控制块清零与芯片复位;② 重传/KeepAlive/**MAC**/IP/GW/MASK 参数**必须**在 `ch395f_init` 之前下发(手册 §9.2.1:SET_MAC 为步骤①,INIT_CH395 加载 MAC——顺序反了本次上电不生效,P1-7);③ `fun_para=0x09`:多 Socket 模式 + TCP Server 单连接 + DISCONNECT/TIMEOUT 不清缓冲(软件排空后手动关);④ 缓冲布局每 Socket 6 块(收 4 + 发 2)×8 = 48 块恰好用尽,Socket 0~7 必须显式重分配(Trap 01/02);⑤ 捕获 `xTaskGetCurrentTaskHandle` 存入 `s_net_task_handle`(防自通知死锁的判据) | | `net_get_generation()` | 读网络代次号(纯 RAM) | 无 | FTP/UI/对时服务据此感知"网络已重建"→ 放弃旧监听并重建 | | `net_generation_inc()` | 代次号 +1 | 无 | 唯一合法递增点 = `net_stack_bring_up()` 末尾(PHY/链路就绪后)——太早递增会让服务在网络不可用时抢跑重建;模拟器端恒为 0(无重建概念,上层自愈逻辑空转) | @@ -349,8 +349,9 @@ sequenceDiagram | `ch395f_check_exist` / `ch395f_reset` | `net_init` | 上电探测与复位 | | `ch395f_set_fun_para(0x09)` | `net_init` | 多 Socket + TCP 单连接 + 手动关缓冲 | | `ch395f_set_tcp_mss` / `set_retrans_count` / `set_retrans_period` / `set_keepalive_idle+intvl+cnt` | `net_init`(**均须在 `ch395f_init` 之前**) | 值见 `net_config.h` | -| `ch395f_set_ip_addr` / `set_gwip_addr` / `set_mask_addr` / `set_dhcp` | `net_init` | 固定 IP 或 DHCP | -| `ch395f_init` / `ch395f_set_mac_addr` / `ch395f_ping_enable` | `net_init` | 协议栈初始化 / MAC(EEPROM,幂等)/ PING | +| `ch395f_set_mac_addr` | `net_init`(**须在 `ch395f_init` 之前**) | 写芯片 EEPROM;INIT_CH395 加载 MAC(手册 §9.2.1 步骤①,P1-7) | +| `ch395f_set_ip_addr` / `set_gwip_addr` / `set_mask_addr` / `set_dhcp` | `net_init`(**均须在 `ch395f_init` 之前**) | 固定 IP 或 DHCP | +| `ch395f_init` / `ch395f_ping_enable` | `net_init` | 协议栈初始化(INIT_CH395)/ PING(须在 init 之后) | | `ch395f_set_send_buf` / `ch395f_set_recv_buf` | `net_init`(8 Socket 布局);`net_bind`(UDP)(Socket 4~7 兜底) | 每 Socket 收 4 块 + 发 2 块 | | `ch395f_get_glob_int_status_all` | `net_poll`;`net_listen_locked` / `net_connect_locked` / `net_close_locked` / `net_relisten_locked`(清残留) | **读 = 清**(中断清除机制) | | `ch395f_get_sock_int_status` | `net_poll`(逐 Socket SINT);各 open 路径后清残留;事件处理器清 TIMEOUT | **读 = 清** | diff --git a/docs/问题记录/CH395F_Trap_Records.md b/docs/问题记录/CH395F_Trap_Records.md index 6e0842c9..c58ac459 100644 --- a/docs/问题记录/CH395F_Trap_Records.md +++ b/docs/问题记录/CH395F_Trap_Records.md @@ -182,7 +182,7 @@ CH395F 的 RECV 中断是电平触发的——只要接收缓冲区有数据就 ## 附:CH395F 驱动关键点 ### 初始化顺序 -- 必须按手册9.2.1节顺序:`SET_MAC → SET_IP/GWIP/MASK → INIT_CH395 → SET_PHY` +- 必须按手册9.2.1节顺序:`SET_MAC → SET_IP/GWIP/MASK → INIT_CH395 → SET_PHY`(**违反此序曾导致 MAC 不生效,见 Trap 24**) - **IP/网关/掩码必须在 `INIT_CH395` 之前设置**,INIT 会读取并锁定当前寄存器值到协议栈 - **`SET_PHY` 必须在 `INIT_CH395` 之后**,复位 MAC/PHY 建立物理链路,不影响已锁定的协议栈参数 - **`CMD_PING_ENABLE` 不需要显式调用**,INIT 后默认可用 @@ -735,3 +735,35 @@ NET 层 TCP Client(阶段 7)`net_connect()` 返回 0,但 `net_poll()` 报 | 构建 / 回读 / 启动门禁 / 控制台 / 堆 | 0 错 0 警、`No difference found`、FORBID 0、`CONSOLE dropped 0`、`heap free=8776 min_ever=4816`(不变) | **对应文件**:`Drivers/BSP/NET/net_types.h`(`released_abnormal`)、`Drivers/BSP/NET/net_socket.c`(三处置位/清除 + `net_pending_tick` 了结分支)、`Drivers/BSP/NET/lftpd/lftpd.c`(`receive_file` 错误路径 unlink)、`MDK-ARM/ftp_abort_probe.py`(`--check-abort`)。 + +--- + +## Trap 24:MAC 写入顺序违反手册 §9.2.1(SET_MAC 必须在 INIT_CH395 之前) + +### 现象(静态审查发现;手册确证) +`net_init()` 原顺序为 `ch395f_init()`(CMD_INIT_CH395)→ `ch395f_set_mac_addr()`,与手册 §9.2.1 规定的初始化顺序**相反**。后果:INIT_CH395 已按 EEPROM 旧值加载 MAC,其后写入 EEPROM 的新 MAC 本次上电**不生效**(回落芯片内置/上次值,实际"滞后一次上电")→ UI 配置的 MAC 与设备实际在线 MAC 不一致,设备在线身份错误、网口排查困难。本轮未做"UI 改 MAC + 重启"台架复现,结论由手册条文确证。 + +### 根因 +手册 §9.2.1「初始化 CH395,必要操作」顺序为: +① `SET_MAC_ADDR` → ② `SET_IP_ADDR` → ③ `SET_GWIP_ADDR` → ④ `SET_MASK_ADDR` → ⑤ `INIT_CH395`。 +- §5.7:`SET_MAC_ADDR` 把 MAC **写入芯片内部 EEPROM**(约 30us); +- §5.13:`INIT_CH395` **初始化 CH395 的 MAC、PHY 以及 TCP/IP 协议栈**(约 5ms)。 + +即 INIT_CH395 会从 EEPROM **加载** MAC,故 SET_MAC 必须先于 INIT_CH395。原码把 MAC 放在 INIT 之后。 + +**加剧误排的注释**:`ch395f.c` 原把 `set_mac_addr`/`set_ip_addr`/`set_gwip_addr`/`set_mask_addr` 的限定条件标为"芯片已初始化"——与手册矛盾(这四个 SET 实际都在 INIT 之前下发),易被误读为"须在 init 之后调用"。 + +### 解决 +1. `Drivers/BSP/NET/net_socket.c` `net_init()`:把 `ch395f_set_mac_addr()` 从 `ch395f_init()` **之后**移到**之前**(置于 SET_IP/GWIP/MASK 之前,对齐手册步骤①); +2. `ch395f.c`:四个 SET 函数的限定条件注释统一改为"必须在 `ch395f_init()` 之前调用"; +3. `net_socket.h`:`net_init` 注释同步(MAC 于协议栈初始化**之前**下发)。 + +### 影响面 +- 仅 `net_init()` 一处调用(产品路径);改动为**纯顺序调整**,无新增/删除指令、无 RAM 变化; +- `net_stack_bring_up()` 在 `net_init` 后回读芯片 MAC 写 UI 影子(`net_cfg_set_active_mac`)——修复后回读值 = 实际在线 MAC,UI 显示与线上身份一致。 + +### 对应文件 +`Drivers/BSP/NET/net_socket.c`(`net_init` SET_MAC 顺序)、`Drivers/BSP/NET/net_socket.h`(`net_init` 注释)、`Drivers/BSP/CH395F/ch395f.c`(四个 SET 的限定条件注释);`docs/网络/BSD_Socket_API_函数调用关系.md`(§4.1 / §7 顺序)。 + +### 发现时间 +2026-10-04(静态审查项 P1-7;依据手册 §9.2.1 / §5.7 / §5.13 定案)。