T5产测问题
出现试产的模组进产测会复位,而同一个固件烧录到调试时使用的几个模组都正常;
当把netcfg_stop(NETCFG_STOP_ALL_CFG_MODULE)屏蔽,试产的模组进产测就正常,但会导致进产测时同时能配网,这个不符合产品设计要求,这个应该怎么解决,SDK版本是3.12.25
出现试产的模组进产测会复位,而同一个固件烧录到调试时使用的几个模组都正常;
当把netcfg_stop(NETCFG_STOP_ALL_CFG_MODULE)屏蔽,试产的模组进产测就正常,但会导致进产测时同时能配网,这个不符合产品设计要求,这个应该怎么解决,SDK版本是3.12.25
你好!关于 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)冲突点:如果 netcfg 的 Sniffer(用于 SmartConfig)或 AP 还在运行,产测再切 WWM_SNIFFER 时底层 WiFi HAL 会发生工作模式冲突 → 驱动异常复位。这就是为什么必须先 netcfg_stop(0) 释放 netcfg 持有的 WiFi 资源。
为什么试产模组会复位,调试模组正常:
netcfg_module_init() 注册的模块少、状态干净netcfg_module_uninit() 释放 Sniffer/Transporter 时命中空指针或重复释放,触发 WDT/assert 复位【二、正确解决方案】
方案 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 successpHandler->stop 返回错误或没打印最后的 destroyWifi...,说明是在 uninit 里挂了tal_kv_get("gw_wsm", ...) 读出的 nc_tp / md 值【四、风险与回退】
netcfg_stop(NETCFG_TY_WIFI_AP)【五、需要你确认的信息】
wd_gw_wsm_read() 在复位前读到的 nc_tp、md 值把这几项补上,我可以进一步定位是方案 A 还是 B 更契合你们的量产流程。另外顺带提醒:3.12.25 已是较稳定版本,无需升级 SDK,问题确实在应用层产测时序。
产测应该是在soc init之前进的,你为啥放在这个地方?
1、复位时的完整日志见附件
2、烧录后断电重新上电再进成品产测(产线上的产测)
3、产测如果放在soc init之前,进不了产测,工单咨询得到解析是:T5目前还不支持成品产测,详见工单:T202604270137,所以放在soc init之后,扫描到产测路由后,再手动关配网,才导致出现上述复位问题
你好 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 处:
stop 时这些异步任务回调到已释放的 session 指针 → 野指针复位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" 的方式。既能进产测又不会释放 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)。
如果不想改代码结构,保留 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) 安全。
既然工单已确认 T5 暂不支持成品产测,生产上可以:
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 pointerstopTransporterFn 被调用两次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)。