出现试产的模组进产测会复位,而同一个固件烧录到调试时使用的几个模组都正常;
当把netcfg_stop(NETCFG_STOP_ALL_CFG_MODULE)屏蔽,试产的模组进产测就正常,但会导致进产测时同时能配网,这个不符合产品设计要求,这个应该怎么解决,SDK版本是3.12.25
T5产测问题
你好!关于 T5 SDK 3.12.25 产测时试产模组复位的问题,这是 netcfg 与产测 Sniffer 模式切换时的资源竞争导致,调试模组和试产模组表现不同通常源于 flash 中 GW_WORK_STAT_MAG_S 和授权信息的差异。下面给出根因、规范方案和验证步骤:
【一、根因分析(源码依据)】
netcfg_stop(0)的行为(components/svc_wifi/src/wifi_netcfg/netcfg_module.c:369):- 传入
NETCFG_STOP_ALL_CFG_MODULE(=0) 会走"停止所有配网"分支 - 先
pTransporter->stopTransporterFn() - 遍历所有已注册模块调用其
stop() - 最后调用
netcfg_module_uninit()→destroyWifiNetcfgFrameSniffer()+destroyWifiNetcfgFrameTransporter()+ 释放链表和 session
- 传入
产测入口
prodtest_ssid_scan(components/svc_mf_test/src/product_autotest/prod_test.c)流程:prodtest_listen_start()→tal_wifi_set_work_mode(WWM_SNIFFER)→tal_wifi_set_cur_channel(6)- 产测必须切到 Sniffer 模式才能在信道 6 被动监听 tuya_mdev_test1
冲突点:如果 netcfg 的 Sniffer(用于 SmartConfig)或 AP 还在运行,产测再切 WWM_SNIFFER 时底层 WiFi HAL 会发生工作模式冲突 → 驱动异常复位。这就是为什么必须先
netcfg_stop(0)释放 netcfg 持有的 WiFi 资源。为什么试产模组会复位,调试模组正常:
- 调试模组:多次烧录/授权,flash 中 GW_WORK_STAT_MAG_S 已稳定(通常 nc_tp 已被清零或处于 GWNS_UNCFG_SMC 之前的状态),
netcfg_module_init()注册的模块少、状态干净 - 试产模组:首次授权后 flash 中可能残留配网中途写入的脏状态(auth_key/uuid 写入了但 wsm 未正确初始化),
netcfg_module_uninit()释放 Sniffer/Transporter 时命中空指针或重复释放,触发 WDT/assert 复位
- 调试模组:多次烧录/授权,flash 中 GW_WORK_STAT_MAG_S 已稳定(通常 nc_tp 已被清零或处于 GWNS_UNCFG_SMC 之前的状态),
【二、正确解决方案】
方案 A(推荐):产测入口前确保 netcfg 处于可安全停止的状态
在调用产测扫描之前,明确判断并等待 netcfg 完成初始化再停止。在 user_main.c 或产测触发位置:
Code: Select all
#include "netcfg_module.h"
#include "tuya_wifi_netcfg.h"
#include "tal_api.h"
static void safe_enter_prodtest(void)
{
// 1) 仅当 netcfg 已初始化时才 stop,避免对未初始化的 session 做 uninit
if (is_netcfg_module_inited()) {
netcfg_stop(NETCFG_STOP_ALL_CFG_MODULE);
// 给 workq 一点时间让 __gw_nw_cfg_stop_cb 真正执行完
tal_system_sleep(200);
}
// 2) 此时再启动产测 Sniffer 就不会与 netcfg 模块冲突
// prodtest_ssid_scan(...)
}关键点:is_netcfg_module_inited() 定义在 components/svc_wifi/src/wifi_netcfg/netcfg_module.c:350,用它代替盲目 stop。
方案 B:检查并清理 flash 脏数据(针对试产模组)
试产首次烧录后执行一次"清配网状态":
Code: Select all
// 清 GW_WORK_STAT_MAG_S,保留 auth_key / uuid / hid / pid
GW_WORK_STAT_MAG_S wsm = {0};
wd_gw_wsm_write(&wsm);或量产治具在烧录授权后增加一步:上电→等待 3s→对串口发 reset 指令→断电,保证首次进产测时 wsm 是干净初值。
方案 C(治标):把 stop 模式改为指定类型而不是全部停止
如果产测场景下你只需要停止 SmartConfig Sniffer,不用停所有配网模块,可以改为:
Code: Select all
// 只停 SmartConfig 类 Sniffer(NETCFG_TY_WF_SMC_HS / NETCFG_TY_WF_AP 等,按实际定义)
netcfg_stop(NETCFG_TY_WF_SMC_HS); // 或具体的 type 宏这样走的是 netcfg_stop() 的"非 0"分支,不会触发 netcfg_module_uninit(),即不会 destroy Sniffer/Transporter 全局对象,避免空指针路径。具体 type 宏以 components/svc_wifi/include/netcfg_module.h 定义为准。
【三、验证步骤】
- 打开详细日志:
tal_log_set_level(TAL_LOG_LEVEL_DEBUG) - 复现时关注以下关键日志:
netcfg module stop type:0x...destroyWifiNetcfgFrameSniffer/Transporterprodtest_listen_start success
- 如复位前看到某个
pHandler->stop返回错误或没打印最后的destroyWifi...,说明是在 uninit 里挂了 - 对比调试模组和试产模组上电后的:
tal_kv_get("gw_wsm", ...)读出的 nc_tp / md 值- auth_key/uuid 是否完整
- 方案 A 改完后,10 台试产模组连续进产测不再复位即为有效
【四、风险与回退】
- 方案 A 加的 sleep(200) 仅在进产测时多 200ms,不影响正常业务流程;如不生效可增大到 500ms
- 方案 B 需量产工艺配合,不改固件
- 方案 C 如果产测期仍需要停 AP 配网,要额外加一次
netcfg_stop(NETCFG_TY_WIFI_AP) - 回退:注释掉新增代码即可
【五、需要你确认的信息】
- 试产模组复位时的完整日志(从产测触发到复位最后一条)
wd_gw_wsm_read()在复位前读到的 nc_tp、md 值- 授权工艺是否在烧录后立刻带电进产测(还是断电后重新上电进产测)
把这几项补上,我可以进一步定位是方案 A 还是 B 更契合你们的量产流程。另外顺带提醒:3.12.25 已是较稳定版本,无需升级 SDK,问题确实在应用层产测时序。
Re: T5产测问题
产测应该是在soc init之前进的,你为啥放在这个地方?
Re: T5产测问题
1、复位时的完整日志见附件
2、烧录后断电重新上电再进成品产测(产线上的产测)
3、产测如果放在soc init之前,进不了产测,工单咨询得到解析是:T5目前还不支持成品产测,详见工单:T202604270137,所以放在soc init之后,扫描到产测路由后,再手动关配网,才导致出现上述复位问题
- Attachments
-
- log.txt
- (155.62 KiB) Downloaded 10 times
Re: T5产测问题
你好 sandy!补充信息很关键,这下能定位根因了。
综合日志+工单 T202604270137 可以确认:T5 SDK 3.12.25 当前不支持原生成品产测模式,只能走"开发产测 + 手动停止配网"的变通方案,而复位的根因是 soc init 之后 netcfg 已经是"运行状态",此时调 netcfg_stop(NETCFG_STOP_ALL_CFG_MODULE) 会走完整的 uninit 流程,与产测 Sniffer 模式切换抢资源。
一、为什么试产模组会复位(确认根因)
soc init 之后 netcfg 模块已经 start,Sniffer/Transporter/Session 都已经分配。此时执行 netcfg_stop(0):
Code: Select all
// components/svc_wifi/src/wifi_netcfg/netcfg_module.c:369
int netcfg_stop(int type) {
...
} else { /*停止所有的配网*/
ptrWifiNetcfgFrameTransporter_t pTransporter = getWifiNetcfgFrameTransporter();
pTransporter->stopTransporterFn(); // 停 Sniffer + 释放队列
tuya_list_for_each(...) { // 遍历所有已 start 模块调 stop
ret = pHandler->stop(pHandler->type);
}
netcfg_module_uninit(); // 释放 session+链表
}
}调试模组 OK、试产模组复位 的差异只可能来自 2 处:
- 授权/license 状态不同:试产模组第一次上电没有授权数据,netcfg 模块在 start 阶段可能还挂了一些未完成的异步任务(license 校验 / 硬重置保护),
stop时这些异步任务回调到已释放的 session 指针 → 野指针复位 - flash GW_WORK_STAT_MAG_S 状态不同:调试模组是"已配网/已激活"状态进产测,
netcfg_stop时各 handler 都是 !isStarted(跳过);试产模组是"未配网/白板"状态,ez_netcfg/ap_netcfg handler 的 isStarted=true,stop 回调执行到stopTransporterFn第二次(上面已经调过一次)→ 双重释放
可以烧录带 debug 信息的固件抓附件日志里复位前最后 300ms 的 PR_DEBUG 输出,重点关注 netcfg module stop type:0xXX 出现了几次、是否有 null pointer / assert / page fault。
二、推荐方案(不用停全部配网,避免 uninit)
改用 "停指定类型 + 保留模块未 uninit" 的方式。既能进产测又不会释放 Sniffer:
方案1(首选):只停 EZ/AP 配网,不碰 Sniffer
Code: Select all
#include "netcfg_module.h"
static void enter_prodtest_safe(void) {
// 只停特定配网类型,不触发 netcfg_module_uninit
netcfg_stop(GWCM_OLD_PROD); // 如果开了生产配网
netcfg_stop(NETCFG_TY_WIFI_EZ); // 停 EZ 配网
netcfg_stop(NETCFG_TY_WIFI_AP_COEXIST); // 停 AP 兼容
netcfg_stop(NETCFG_TY_WIFI_AP); // 停 AP 配网
tal_system_sleep(100); // 等 transporter 任务退出
// 此时 netcfg session/sniffer 仍在,但没有 active 配网
// 产测 prodtest_ssid_scan 内部会 set_cur_channel(6) 接管
}对应 type 定义在 components/svc_wifi/include/netcfg_module.h(非 0 走指定 type 分支,不走 uninit)。
方案2:先 stop 再延时再进产测(快速验证)
如果不想改代码结构,保留 netcfg_stop(0) 但加保护:
Code: Select all
// 1) 先阻止 tuya_wifi_netcfg_stop 并发调用
extern OPERATE_RET tuya_wifi_netcfg_stop(VOID_T);
tuya_wifi_netcfg_stop(); // 走内部锁保护
tal_system_sleep(200); // 等所有异步回调完成
// 2) 再进产测
prodtest_ssid_scan(10000);这个走的是上层 wrap(tuya_wifi_netcfg.c:797),有锁保护,比直接调 netcfg_stop(0) 安全。
方案3:先烧"未授权"固件走开发产测(当前 T5 推荐路径)
既然工单已确认 T5 暂不支持成品产测,生产上可以:
- 产线先烧 开发产测固件(不含 app,纯产测入口)
- 开发产测 PASS 后烧 量产固件
- 量产固件里不再包含
netcfg_stop + prodtest_ssid_scan这段代码
产线两步烧录虽然多一个工序,但规避了当前 SDK 的限制,最稳。
三、复现验证步骤
建议按下面顺序验证,最快定位:
| 步骤 | 动作 | 预期 |
|---|---|---|
| 1 | 方案1 代码替换 netcfg_stop(0) | 不再复位 → 根因=uninit 冲突 |
| 2 | 附件日志开 PR_DEBUG,抓 netcfg stop 前后 | 能看到 stop 调用次数 |
| 3 | 试产模组烧量产授权(apt_cmd set_auth)后再试 | 如 OK → 根因=授权状态 |
四、关于附件日志
方便的话把复位完整日志(含异常栈/page fault 地址)贴上来,重点看:
- 是否出现
assert或NULL pointer - 是否有
stopTransporterFn被调用两次 - 产测前最后一条
netcfg module stop的 type 值
基于这些信息可以给出更精确的 patch。
参考代码:components/svc_wifi/src/wifi_netcfg/netcfg_module.c:369-420(netcfg_stop)、components/svc_mf_test/src/product_autotest/prod_test.c:26,152(产测信道6)、components/svc_wifi/src/wifi_link/tuya_wifi_netcfg.c:797(tuya_wifi_netcfg_stop)。