WiFi 驱动与网络模式
本文档介绍 AC79NN AIoT SDK 中 WiFi 驱动的全局配置体系与 STA / AP / MONITOR 三种网络模式的使用方式,涵盖驱动级调优参数、内存与数据队列管理、lwIP 报文过滤钩子、低功耗/省电机制,以及基于 wifi_demo_task.c 的完整模式切换与连接流程。
Purpose and Scope
本页面向 SDK 5-networking 分类下的 "WiFi 驱动与网络模式" 能力,重点说明:
apps/common/net/wifi_conf.c中全部 WiFi 驱动级全局配置项的含义与设计意图(调试打印、乱序重排、发送队列、扫描驻留、信道质量阈值、低功耗等);- WiFi 三种网络模式(STA 站点模式、AP 软热点模式、MONITOR 监听模式)及其在
apps/demo/demo_DevKitBoard/wifi_demo_task.c中的切换与测试流程; - WiFi 与 lwIP 协议栈之间的接收/发送过滤钩子、DHCP/静态 IP 记忆机制。
以下内容不属于本页范围,请参见 5-networking 分类下的兄弟页面:网络协议栈(lwIP/TCP-IP)细节、云端 IoT 接入(如 qcloud_iot_explorer_sdk 中的 HAL_wifi_ac79.c、wifi_softap.c 等配网实现)、外置 WiFi 模块(apps/common/net/ext_wifi_conf.c)、MAC 地址分配(apps/common/net/assign_macaddr.c)与 UART 透传协议(apps/common/net/wf_uart_protocal.c)。
Overview
AC79NN 是杰理科技(Jieli)推出的 AIoT 平台芯片,内置 WiFi 基带/MAC 与射频前端。SDK 中 WiFi 能力被组织为三层:
- 驱动配置层(
apps/common/net/wifi_conf.c):以全局变量的形式集中暴露驱动调优开关与参数。这些变量大多被底层 WiFi 驱动(wifi/wifi_connect.h对应的实现)直接引用,因此修改后重新编译即可生效,无需改动驱动核心代码——这是 SDK 设计上"配置与实现分离"的关键手段。 - 连接 API 层(
wifi/wifi_connect.h接口,如wifi_get_mode_cur_info、wifi_get_channel、wifi_set_sta_connect_best_ssid等):提供模式设置、扫描、连接、信息查询等操作入口。 - 应用演示层(
apps/demo/demo_DevKitBoard/wifi_demo_task.c):演示开机默认模式选择、模式循环切换、SSID/密码配置、DHCP 与静态 IP 记忆等完整业务流程,是开发者移植与二次开发的模板。
典型使用场景包括:智能音箱/带屏设备的 STA 联网、设备热点配网(SoftAP)、报文嗅探/监控(MONITOR)、以及通过 CONFIG_NO_SDRAM_ENABLE 区分的有/无 SDRAM 内存受限环境下的吞吐与内存折中调优。
Architecture
flowchart TD
subgraph sg_App["应用层 (apps)"]
DemoTask["wifi_demo_task.c<br/>模式测试任务"]
ExtWifi["ext_wifi_conf.c<br/>外置WiFi配置"]
end
subgraph sg_Conf["WiFi配置与连接层"]
WifiConf["wifi_conf.c<br/>驱动全局配置"]
WifiApi["wifi/wifi_connect.h<br/>连接API"]
end
subgraph sg_Stack["网络协议栈"]
Lwip["lwIP"]
Dhcp["DHCP Server/Client"]
end
subgraph sg_Drv["WiFi底层驱动"]
WifiDrv["AC79 WiFi驱动<br/>MAC/基带/RF"]
RfCal["RF温度漂移校准"]
end
subgraph sg_Store["持久化"]
Syscfg["syscfg VM 数据库<br/>SSID/IP记忆"]
end
DemoTask -->|"读取全局变量"| WifiConf
DemoTask -->|"模式设置/连接"| WifiApi
ExtWifi --> WifiApi
WifiConf -->|"参数引用"| WifiDrv
WifiApi --> WifiDrv
WifiDrv --> RfCal
WifiApi -->|"TX/RX钩子"| Lwip
WifiConf -->|"filter回调"| Lwip
Lwip --> Dhcp
DemoTask -->|"syscfg_read/write<br/>VM_STA_IPADDR_INDEX"| Syscfg
WifiApi -->|"SSID记忆<br/>WIFI_STA_INFO_IDX_START"| Syscfg
架构说明:
- wifi_conf.c 是整个驱动配置的"总闸"。它不实现无线协议,而是为底层驱动与 lwIP 提供数百个可调全局量(调试等级、重排开关、队列深度、信道驻留时间、低功耗参数等),其中许多是
const型,编译期即可确定,利于优化。 - wifi/wifi_connect.h API 是应用与驱动之间的稳定契约。应用(demo 任务、外置 WiFi 模块、云 SDK HAL 层)通过它发起扫描、连接、查询状态;驱动通过回调(如密码错误通知
wifi_password_wrong_notify)向应用反馈事件。 - lwIP 钩子(
lwip_low_level_inputput_filter/lwip_low_level_output_filter)是驱动与协议栈之间的"流量阀门",在内存紧张时优先丢弃非关键报文(非 echo 的 ICMP、非 ARP/TCP 包),保证 ARP 与 TCP 控制报文不被饿死。 - syscfg VM 数据库 负责持久化:保存已连接 SSID 列表(
WIFI_STA_INFO_IDX_START起始的索引)、静态 IP 信息(VM_STA_IPADDR_INDEX),实现"冷启动快连"与"断网后记忆恢复"。
驱动全局配置深度解析(wifi_conf.c)
apps/common/net/wifi_conf.c 是 WiFi 驱动配置的集中地,全部配置以全局变量形式暴露。以下按功能分组说明其设计意图。
调试与诊断输出
/*
// 设置WIFI DEBUG 信息输出等级
// Debug information verbosity: lower values indicate higher urgency
// 0:RT_DEBUG_OFF
// 1:RT_DEBUG_ERROR
// 2:RT_DEBUG_WARN
// 3:RT_DEBUG_TRACE
// 4:RT_DEBUG_INFO
// 5:RT_DEBUG_LOUD
*/
const u8 RTDebugLevel = 2;
const char WL_TX_DEBUG = 0; //WIFI底层发送数据FIFO繁忙打印
const char WL_RX_DEBUG = 0; //WIFI底层接收FIFO塞满导致丢包打印
const char WL_TX_ERR_RATIO_DEBUG_SEC = 0; //统计每秒TX数据包成功/失败/重发和错误率
const char WL_RX_ERR_RATIO_DEBUG_SEC = 0; //统计每秒RX数据包成功/失败/错误率
const u16 WL_RX_BACK_GROUND_ERR_CNT_PER_SECOND = 10; //接收本底错误包计数
Source: wifi_conf.c
设计意图:RTDebugLevel = 2 为出厂默认(仅打印 WARN 及以上),WL_*_DEBUG 系列全部默认关闭,避免干扰业务打印。WL_RX_BACK_GROUND_ERR_CNT_PER_SECOND 是工程上常见的"本底噪声补偿"思路——硬件缺少接收正确包的寄存器统计,因此人工设定环境干扰误报基准值(10 包/秒),用于校准误报率统计。排查空中干扰、TX 性能不足、CPU 被阻塞等问题时,可逐个打开这些开关。
包乱序重排与内存折中
#if defined CONFIG_NO_SDRAM_ENABLE
const u8 RxReorderEnable = 0; //底层包乱序整理关闭
const u32 MAX_REORDERING_MPDU_NUM = 1;
#else
const u8 RxReorderEnable = 1; //底层包乱序整理开启
const u32 MAX_REORDERING_MPDU_NUM = 128;
#endif
const u16 MAX_PACKETS_IN_QUEUE = 64; //发送数据包队列
const u16 MAX_PACKETS_IN_MCAST_PS_QUEUE = 8; //MCAST power-save 队列
const u16 MAX_PACKETS_IN_PS_QUEUE = 16; //power-save 队列
const u8 MAX_LEN_OF_BSS_TABLE = 4; //扫描结果BSS表容量
Source: wifi_conf.c
设计意图:CONFIG_NO_SDRAM_ENABLE(无 SDRAM 的小内存配置)下,重排与队列深度被大幅削减——重排关闭时 UDP 重发包会直接上抛到协议栈,换取内存节省;MAX_REORDERING_MPDU_NUM 与 MAX_PACKETS_IN_*_QUEUE 均按有/无 SDRAM 双轨配置。MAX_LEN_OF_BSS_TABLE 决定扫描结果表容量,个数越多占用内存越大,最小为 1。
扫描、信道质量与断线重连
const u16 MAX_CHANNEL_TIME_BSS_INFRA = 200; //扫描每个信道停留时间,单位ms,最小20ms, 200-400ms最佳
const char WIFI_CHANNEL_QUALITY_INDICATION_BAD = 5; //STA信道质量差阈值,低于此值断线重连
//配置为-1则信号再差也不通知断线
const u8 WIFI_COLD_START_FAST_CONNECTION = 1; //启用WIFI冷启动快连
const u8 wifi_ampdu_disable = 0; //AMPDU聚合开关
Source: wifi_conf.c
设计意图:扫描驻留时间 MAX_CHANNEL_TIME_BSS_INFRA 控制在 200–400ms 为最佳区间,过短扫描不全、过长拖慢连接。WIFI_CHANNEL_QUALITY_INDICATION_BAD = 5 表示低于 5 即主动断线重连,避免"信号差但久连不重连"被路由器判定为死终端踢出;但若配置为 -1 则不主动断线,需权衡。WIFI_COLD_START_FAST_CONNECTION 配合 syscfg 中记忆的 SSID 实现上电秒连。
低功耗与省电参数
#if defined CONFIG_WIFI_IDLE_RESUME_BASEBAND_ENABLE
u8 wifi_lowpower_mode = 1; //低功耗模式
#else
u8 wifi_lowpower_mode = 0;
#endif
u8 wifi_psmode_transfer_statistics_enable = 1; //统计低功耗唤醒后的收发包保活状态
u16 wl_custom_listen_interval = 10; //自定义监听间隔
u16 wl_default_listen_interval = 3; //默认监听间隔
u8 wl_transmit_keep_awake_time = 12; //收发包后保持清醒 12*100ms
Source: wifi_conf.c
设计意图:低功耗模式仅在 CONFIG_WIFI_IDLE_RESUME_BASEBAND_ENABLE 编译开关下开启(基带可挂起/恢复)。wl_transmit_keep_awake_time 以 100ms 为单位,保证收发数据后系统维持清醒 1.2 秒,防止数据未处理完就休眠;wl_default_listen_interval = 3 是监听间隔兜底值,防止上层未设置导致异常。wifi_psmode_transfer_statistics_enable 用于验证低功耗唤醒后是否仍处于正常保活状态(如 TCP keepalive)。
独立内存池
static u8 mem_pool[CONFIG_WIFI_MAX_MEM_SIZE]sec(.wifi_mem_pool);
u8 *wifi_mem_pool(u32 *size)
{
if (size == NULL) {
return NULL;
}
*size = CONFIG_WIFI_MAX_MEM_SIZE;
printf("wifi mem pool:%x size:%d\n", mem_pool, *size);
return mem_pool;
}
Source: wifi_conf.c
设计意图:mem_pool 通过 sec(.wifi_mem_pool) 放入独立段,CONFIG_WIFI_USE_TLSF_MEM = 0 时 WiFi 与系统共用内存管理;若开启独立 TLSF 内存管理,则该池可隔离 WiFi 内存波动,避免影响系统主内存。CONFIG_WIFI_MAX_MEM_SIZE 当前为 0,即默认不启用独立池。
密码错误通知与 SSID 记忆管理
void wifi_password_wrong_notify(const u8 *ssid, const u8 *passphrase)
{
if (ssid) {
printf("wrong password info, ssid[%s]\n", ssid);
u8 wifi_ssid_cnt = wifi_get_store_ssid_cnt();
if (wifi_ssid_cnt > 1) {
struct wifi_stored_sta_info sta_info_read[wifi_ssid_cnt];
memset(&sta_info_read, 0, sizeof(sta_info_read));
for (int k = 0; k < wifi_ssid_cnt; k++) {
if (syscfg_read(WIFI_STA_INFO_IDX_START + k, (char *)&sta_info_read[k],
sizeof(struct wifi_stored_sta_info)) < 0) {
break;
}
if (!strcmp((const char *)sta_info_read[k].ssid, ssid)) {
printf("Incorrect password, [%d]%s delete!!", k, sta_info_read[k].ssid);
sta_info_read[k].ssid[0] = 0; //密码错误就清除保存的SSID
syscfg_write(WIFI_STA_INFO_IDX_START + k, (char *)&sta_info_read[k],
sizeof(struct wifi_stored_sta_info));
}
}
}
}
//设置 best ssid flag, 让驱动连接保存的best ssid
wifi_set_sta_connect_best_ssid(1);
}
Source: wifi_conf.c
设计意图:这是驱动回调应用的典型模式——连接密码错误时,驱动通过该回调通知应用;应用遍历 syscfg 中保存的 SSID 表(WIFI_STA_INFO_IDX_START 起始),清除错误密码对应的条目,再指示驱动连接记忆中的最优 SSID。当前函数体被 #if 0 屏蔽(保留原型),实际使能时可实现"自动剔除坏 SSID、回退到最优网络"的容错逻辑。
lwIP 收发过滤钩子(丢包优先级策略)
//用于根据LWIP接收队列溢出情况下快速丢包减轻CPU负担,预留空间接收重要数据包
int lwip_low_level_inputput_filter(u8 *pkg, u32 len)
{
struct iphdr_e *iph = (struct iphdr_e *)(pkg + 10);
u16 protoType = ntohs(iph->h_proto);
//丢弃非 echo/echo-reply 的 ICMP (Time_Ex 等无用包)
if ((protoType != 0x0806) && iph->iphd.protocol == 1
&& *((u8 *)iph + sizeof(struct iphdr_e)) != ICMP_ER
&& *((u8 *)iph + sizeof(struct iphdr_e)) != ICMP_ECHO) {
putchar('C');
return -1;
}
#define PBUF_RESERVED_FOR_ARP 1 //至少预留一个PBUF_POOL给ARP,否则不回复路由器导致断流
#define PBUF_RESERVED_FOR_TCP (PBUF_RESERVED_FOR_ARP+1)
u32 remain_pbuf_pool = memp_get_pbuf_pool_free_cnt();
if (remain_pbuf_pool <= PBUF_RESERVED_FOR_TCP) {
if (remain_pbuf_pool == 0) { //PBUF_POOL耗尽,直接丢弃
putchar('X');
return -1;
} else if (remain_pbuf_pool <= PBUF_RESERVED_FOR_ARP
&& protoType != 0x0806) { //丢弃非ARP包
putchar('Y');
return -1;
} else if (!(protoType == 0x0800 && iph->iphd.protocol == 6)) { //丢弃非TCP包
putchar('D');
return -1;
}
}
return 0;
}
Source: wifi_conf.c
设计意图:接收路径上,当 lwIP 的 PBUF_POOL 接近耗尽时,按"ARP > TCP > 其他"的优先级保留缓冲:ARP 必须回复路由器否则断流,TCP 是业务主流量。丢弃的报文用单字符(C/X/Y/D)打印,便于现场快速识别瓶颈类型。与之对称的 lwip_low_level_output_filter 基于 wifi_get_remain_tx_queue(0) 对发送队列做同样的分级保护。这两个钩子都是弱符号风格的全局函数,被协议栈在收发包入口回调,属于 SDK 提供的内置 QoS/拥塞控制扩展点。
网络模式与连接工作流
AC79NN 的 WiFi 支持三种网络模式,在 wifi_demo_task.c 中通过编译宏选择开机默认模式:
| 模式宏 | 模式 | 说明 |
|---|---|---|
AP_MODE_TEST | AP 模式 | 设备作为 SoftAP 热点,SSID 为 AP_SSID 前缀,供手机直连配网 |
STA_MODE_TEST | STA 模式 | 设备作为站点连接路由器,SSID/密码为 STA_SSID/STA_PWD |
MONITOR_MODE_TEST | MONITOR 模式 | 监听模式,抓取空中报文(嗅探) |
WIFI_MODE_CYCLE_TEST | 循环切换 | 从起始/记忆模式开始循环 AP → STA → MONITOR → AP ... 验证模式切换稳定性 |
//选择其中一种开机默认的模式测试
#define AP_MODE_TEST
//#define STA_MODE_TEST
//#define MONITOR_MODE_TEST
//#define WIFI_MODE_CYCLE_TEST //从起始测试模式开始(FORCE_DEFAULT_MODE=1)
//或最后记忆模式开始(FORCE_DEFAULT_MODE=0), 循环测试WIFI模式切换
#define FORCE_DEFAULT_MODE 0 //0为使用最后记忆的模式, 1为强制默认模式,
//3-200为STA连接超时多少秒,超时则连接最后记忆的或最优网络
#define AP_SSID "AC79_WIFI_DEMO_" // AP模式SSID前缀
#define AP_PWD "" // AP模式密码
#define STA_SSID "JL_WIFI" // STA模式SSID
#define STA_PWD "12345678" // STA模式密码
#define CONNECT_BEST_SSID 0 // STA模式下是否挑选记忆过的信号最优WIFI
Source: wifi_demo_task.c
设计意图:FORCE_DEFAULT_MODE 的取值还承担"连接超时"语义——设为 3–200 时表示 STA 连接超过该秒数仍未成功,则回退到记忆中的最后网络或最优网络,这是保证设备在路由器临时不可用时仍能自愈的重要策略。
STA 模式连接与 IP 获取流程
sequenceDiagram
participant App as 应用任务 wifi_demo_task
participant Cfg as wifi_conf.c 全局配置
participant Api as wifi_connect API
participant Drv as AC79 WiFi 驱动
participant Lw as lwIP / DHCP
participant VM as syscfg VM 存储
App->>Cfg: 读取 RTDebugLevel/队列/重排等参数
App->>Api: 模式设置 STA_MODE + SSID/密码
Api->>Drv: 初始化 MAC/基带/RF
Drv-->>Api: 就绪
Api->>Drv: 扫描信道(每信道 MAX_CHANNEL_TIME_BSS_INFRA=200ms)
Drv-->>Api: BSS 列表(MAX_LEN_OF_BSS_TABLE)
Api->>Drv: 关联/认证目标 AP
Drv-->>Api: 关联成功
Api->>Lw: 启动 DHCP 获取 IP
Lw-->>Api: 分配 IP/网关/DNS
Api-->>App: 网络就绪(模式信息/信道/BSSID/MAC)
App->>VM: 记忆 SSID+IP(VM_STA_IPADDR_INDEX)
关键点:驱动初始化完成后,扫描使用 MAX_CHANNEL_TIME_BSS_INFRA(200ms)驻留每信道,扫描结果写入 MAX_LEN_OF_BSS_TABLE 容量的 BSS 表;连接成功后 lwIP 启动 DHCP,store_dhcp_ipaddr() 将 SSID、网关 BSSID、本地 MAC、IP/掩码/网关/DNS 一并写入 VM_STA_IPADDR_INDEX,为下次冷启动快连与静态 IP 复用做准备。
状态查询 API 使用示例
struct wifi_mode_info info;
info.mode = STA_MODE;
wifi_get_mode_cur_info(&info);
sta_channel = wifi_get_channel();
wifi_get_bssid(gw_mac);
wifi_get_mac(local_mac);
Source: wifi_demo_task.c
设计意图:wifi_get_mode_cur_info 通过 struct wifi_mode_info 输出当前模式与 SSID 等现场信息;wifi_get_channel/wifi_get_bssid/wifi_get_mac 分别获取信道、对端(网关)MAC 与本机 MAC。这三者组合用于 compare_dhcp_ipaddr() 判定当前连接环境是否与记忆的静态 IP 环境一致(SSID、双端 MAC、信道均匹配),一致则复用记忆 IP,跳过 DHCP,实现秒连。
AP 模式局域网配置
static void wifi_set_lan_setting_info(void)
{
struct lan_setting lan_setting_info = {
.WIRELESS_IP_ADDR0 = 192, .WIRELESS_IP_ADDR1 = 168,
.WIRELESS_IP_ADDR2 = 1, .WIRELESS_IP_ADDR3 = 1,
.WIRELESS_NETMASK0 = 255, .WIRELESS_NETMASK1 = 255,
.WIRELESS_NETMASK2 = 255, .WIRELESS_NETMASK3 = 0,
.WIRELESS_GATEWAY0 = 192, .WIRELESS_GATEWAY1 = 168,
.WIRELESS_GATEWAY2 = 1, .WIRELESS_GATEWAY3 = 1,
.SERVER_IPADDR1 = 192, .SERVER_IPADDR2 = 168,
.SERVER_IPADDR3 = 1, .SERVER_IPADDR4 = 1,
.CLIENT_IPADDR1 = 192, .CLIENT_IPADDR2 = 168,
.CLIENT_IPADDR3 = 1, .CLIENT_IPADDR4 = 2,
.SUB_NET_MASK1 = 255, .SUB_NET_MASK2 = 255,
.SUB_NET_MASK3 = 255, .SUB_NET_MASK4 = 0,
};
// 随后调用 net_set_lan_info(&lan_setting_info) 生效
}
Source: wifi_demo_task.c
设计意图:AP 模式下设备自身承担 DHCP Server 职责,lan_setting 中同时给出无线侧 IP(WIRELESS_*)、DHCP Server 地址(SERVER_IPADDR*)与地址池起点(CLIENT_IPADDR*,即 192.168.1.2 起分配)。静态 IP 场景下 wifi_set_sta_ip_info() 以同样的 lan_setting 结构体(从 VM_STA_IPADDR_INDEX 读取)配置 STA 侧固定 IP,两套逻辑共用同一数据结构,保证 AP/STA 网络参数设置路径一致。
模式切换状态机
stateDiagram-v2
[*] --> 上电
上电 --> 模式确定: FORCE_DEFAULT_MODE<br/>0=记忆模式 / 1=默认模式
模式确定 --> AP_MODE: AP_MODE_TEST
模式确定 --> STA_MODE: STA_MODE_TEST
模式确定 --> MONITOR_MODE: MONITOR_MODE_TEST
STA_MODE --> 连接成功: 扫描+关联+DHCP
STA_MODE --> 超时回退: 超过FORCE_DEFAULT_MODE秒
超时回退 --> STA_MODE: 连接记忆/最优SSID
连接成功 --> 循环切换: WIFI_MODE_CYCLE_TEST
AP_MODE --> 循环切换: WIFI_MODE_CYCLE_TEST
MONITOR_MODE --> 循环切换: WIFI_MODE_CYCLE_TEST
循环切换 --> AP_MODE
循环切换 --> STA_MODE
循环切换 --> MONITOR_MODE
设计意图:模式循环测试(WIFI_MODE_CYCLE_TEST)是驱动稳定性验证的核心手段——每次切换都会执行基带/射频重新初始化与协议栈重建,长时间循环可暴露模式切换中的资源泄漏、中断悬挂与状态残留问题,量产前建议作为老化测试项。
配置选项
以下为 wifi_conf.c 中可直接调优的关键全局配置(默认值以非 CONFIG_NO_SDRAM_ENABLE 构建为准;标注"双轨"的选项在有/无 SDRAM 下取值不同):
| 配置项 | 类型 | 默认值 | 说明 |
|---|---|---|---|
RTDebugLevel | u8 | 2 | WiFi 调试输出等级(0=OFF … 5=LOUD),数值越小越紧急 |
WL_TX_DEBUG / WL_RX_DEBUG | char | 0 | 底层发送/接收 FIFO 繁忙(丢包)打印开关 |
WL_TX_ERR_RATIO_DEBUG_SEC / WL_RX_ERR_RATIO_DEBUG_SEC | char | 0 | 每秒 TX/RX 成功/失败/错误率统计打印间隔(秒) |
WL_RX_BACK_GROUND_ERR_CNT_PER_SECOND | u16 | 10 | 接收误报率统计的本底错误包补偿值 |
WL_TX_PEND_DEBUG_SEC / WL_RX_PEND_DEBUG_SEC | char | 2 | 连续 N 秒发送不出/接收不到空中包时打印(判定严重干扰/硬件性能差) |
WL_RX_OVERFLOW_DEBUG | char | 0 | 接收 FIFO 溢出丢包统计开关 |
WIFI_PA_ENABLE | char | 0 | 外挂硬件 PA 功率放大(791X 占用 PA1/PA2 IO),用于远距离传输 |
RxReorderEnable | u8 | 1(双轨:无 SDRAM 为 0) | 底层包乱序整理;关闭时 UDP 重发包上抛但省内存 |
MAX_REORDERING_MPDU_NUM | u32 | 128(双轨:无 SDRAM 为 1) | 重排序 MPDU 数量上限 |
MAX_CHANNEL_TIME_BSS_INFRA | u16 | 200 | 扫描每信道驻留时间(ms),20–400 区间 |
WIFI_CHANNEL_QUALITY_INDICATION_BAD | char | 5 | STA 信道质量差阈值,低于即断线重连;-1 表示不主动断线 |
wifi_temperature_drift_trim_on | char | 0 | WiFi 温度漂移校准开关(CONFIG_RF_TEST_ENABLE 相关) |
wifi_ap_scan_support | char | 0 | AP 扫描开关 |
MAX_PACKETS_IN_QUEUE | u16 | 64(双轨:无 SDRAM 为 16) | 发送数据包队列深度 |
MAX_PACKETS_IN_MCAST_PS_QUEUE | u16 | 8(双轨:无 SDRAM 为 4) | 组播 power-save 队列深度 |
MAX_PACKETS_IN_PS_QUEUE | u16 | 16(双轨:无 SDRAM 为 2) | power-save 队列深度 |
RFIinitUseTrimValue | u8 | 1 | 初始化使用 VM 记忆的 RF trim 值,显著降低初始化时间 |
IPV4_ADDR_CONFLICT_DETECT | u8 | 0(CONFIG_STATIC_IPADDR_ENABLE 下为 1) | 静态 IP 冲突检测 |
ntp_get_time_init | u8 | 1 | 联网后向 ntp_host 列表获取时间 |
rtc_update_interval | u32 | 0 | 通过 NTP 校准 RTC 的时间间隔(ms) |
CONFIG_SDIO_SLAVE_MODE | u8 | 0 | WiFi 模块作为 SDIO 从机 |
WIFI_TX_FULL_WAIT_MODE | u8 | 1(UCOS 下为 0) | 0/1/2,越大吞吐率越高但 WiFi 线程占 CPU 越多 |
WIFI_COLD_START_FAST_CONNECTION | u8 | 1 | 冷启动快连(依赖记忆的 SSID) |
MAX_LEN_OF_BSS_TABLE | u8 | 4(双轨:无 SDRAM 为 2) | 扫描结果 BSS 表容量 |
CONFIG_WIFI_USE_TLSF_MEM | u8 | 0 | 使用独立 TLSF 内存管理,与系统内存隔离 |
CONFIG_WIFI_MAX_MEM_SIZE | 宏 | 0 | 独立内存池大小(当前 0 表示不启用) |
wifi_recv_poll | u8 | 0 | 接收方式:0=中断,1=轮询 |
wifi_lowpower_mode | u8 | 0(CONFIG_WIFI_IDLE_RESUME_BASEBAND_ENABLE 下为 1) | 低功耗模式 |
wifi_psmode_transfer_statistics_enable | u8 | 1 | 统计低功耗唤醒后收发包保活状态 |
wl_custom_listen_interval | u16 | 10 | 自定义监听间隔 |
wl_default_listen_interval | u16 | 3 | 默认监听间隔(兜底值) |
wl_transmit_keep_awake_time | u8 | 12 | 收发包后保持清醒时间(单位 100ms,最小 1) |
wifi_ampdu_disable | u8 | 0 | 关闭 AMPDU 聚合 |
API 参考
以下接口来自 wifi/wifi_connect.h(#include "wifi/wifi_connect.h"),签名依据本 SDK 中的实际调用点归纳;完整声明以头文件为准。
void wifi_get_mode_cur_info(struct wifi_mode_info *info)
查询当前 WiFi 模式与现场信息。调用前需设置 info->mode(如 STA_MODE),返回后 info->ssid 等字段填充当前值。
参数:
info(struct wifi_mode_info *):输出结构体,mode为输入模式枚举,ssid为输出。
u8 wifi_get_channel(void)
获取当前 STA 工作信道。返回值用于 compare_dhcp_ipaddr() 中判断连接环境是否变化。
void wifi_get_bssid(u8 *bssid)
获取当前关联 AP(网关)的 BSSID,6 字节,写入调用者提供的缓冲区。
void wifi_get_mac(u8 *mac)
获取本机 MAC 地址,6 字节。
u32 wifi_get_remain_tx_queue(u8 mode)
查询 WiFi 底层剩余发送队列数。lwip_low_level_output_filter 依据该值做发送侧丢包分级(预留 ARP/TCP 名额)。
void wifi_set_sta_connect_best_ssid(u8 enable)
设置 STA 模式连接记忆中的最优 SSID 标志,用于密码错误或默认连接失败后的回退策略。
u8 wifi_get_store_ssid_cnt(void)
返回 syscfg 中保存的 SSID 条目数量,用于遍历 WIFI_STA_INFO_IDX_START 起始的 SSID 表。
void net_set_lan_info(struct lan_setting *setting)
配置局域网参数(IP/掩码/网关/DHCP Server 与地址池),AP 与静态 IP STA 共用。结构体字段见上文 wifi_set_lan_setting_info() 示例。
int lwip_get_netif_info(u8 index, struct netif_info *info)
获取 lwIP 网络接口信息(IP/掩码/网关),用于静态 IP 记忆比对。
u32 *dns_getserver(u8 num)
获取 DNS 服务器地址指针,store_dhcp_ipaddr() 用其保存记忆 DNS。
失败模式、边界情况与并发
密码错误与坏 SSID 剔除
驱动通过 wifi_password_wrong_notify(ssid, passphrase) 通知应用密码错误。当前源码中函数体被 #if 0 屏蔽,但保留了完整的处理逻辑:遍历 WIFI_STA_INFO_IDX_START 起的 SSID 表,将密码错误的条目 ssid[0] = 0 清除并回写 syscfg,随后调用 wifi_set_sta_connect_best_ssid(1) 让驱动连接记忆中的最优 SSID。若在应用层使能此回调,可实现自动剔除坏配置、回退到可用网络的容错闭环;不使能时,错误密码会反复尝试,表现为连接长时间不成功。
信号质量差与断线重连
WIFI_CHANNEL_QUALITY_INDICATION_BAD = 5 时,STA 模式信道质量一旦低于该阈值即主动断线重连;若配置为 -1 则不通知断线。设计权衡:主动断线能尽快切换到更优网络,但频繁断连会放大弱信号区域的抖动;不主动断线则可能被路由器判定为死终端踢出。WL_TX_PEND_DEBUG_SEC / WL_RX_PEND_DEBUG_SEC(默认 2 秒)用于在"发送不出/收不到空中包"持续发生时打印告警,帮助区分干扰、屏蔽房、板级性能与 CPU 阻塞等根因。
内存紧张下的丢包优先级
无 SDRAM 构建(CONFIG_NO_SDRAM_ENABLE)下,重排关闭、各队列深度大幅缩减,UDP 重发包会上抛,且 lwIP 钩子按"ARP > TCP > 其他"丢弃报文。边界情况:PBUF_POOL 或 WiFi TX 队列完全耗尽时,所有报文(含 ARP)都会丢弃,此时路由器因收不到 ARP 回复而判定断流——因此钩子保证至少预留 1 个 ARP 名额、2 个 TCP 名额。若现场观察到密集的 X/G 打印(全丢),说明内存或队列配置过小,应增大 MAX_PACKETS_IN_QUEUE 或 lwIP PBUF_POOL 数量。
静态 IP 环境漂移
compare_dhcp_ipaddr() 通过比对 SSID、本机 MAC、网关 BSSID(及信道)判断当前环境是否与记忆 IP 一致:一致则复用记忆 IP 跳过 DHCP(秒连);不一致则重新 DHCP 并覆盖记忆。边界情况:若路由器换了网关但 SSID 未变,可能短暂沿用旧 IP 导致网络不可达,直到下次连接重估;源码注释亦指出"路由器未联网时每次连接都重新获取 DHCP"以保证 DNS 可用。
并发与线程安全
wifi_conf.c 中的配置多为 const 全局量(编译期确定,天然线程安全);可变项如 wifi_lowpower_mode、wl_active_wait_interval_count 由驱动内部线程读写,应用层不应并发修改。wl_default_listen_interval = 3 与 wl_custom_listen_interval = 10 的兜底初始化是为了防止上层"没设置就使用"导致的未定义行为。WIFI_TX_FULL_WAIT_MODE 在 UCOS 下默认 0、裸机下默认 1,反映不同调度环境对 WiFi 线程 CPU 占比的容忍度差异。
性能与运维注意事项
- 吞吐与 CPU 权衡:
WIFI_TX_FULL_WAIT_MODE(0/1/2)数值越大吞吐越高、WiFi 线程占 CPU 越多;wifi_ampdu_disable = 0保持 AMPDU 聚合以提升吞吐,关闭可降低对端兼容性问题。 - 冷启动快连:
WIFI_COLD_START_FAST_CONNECTION = 1配合RFIinitUseTrimValue = 1(使用 VM 记忆的 RF trim 值),可显著缩短上电到联网的时间;若 RF 校准环境变化,需关闭 trim 记忆重新校准。 - 低功耗保活:
wl_transmit_keep_awake_time = 12(1.2 秒清醒窗口)保证收发包后不立即休眠;wifi_psmode_transfer_statistics_enable = 1统计唤醒后收发包以确认保活正常。调试低功耗丢包时优先检查监听间隔与清醒窗口的匹配。 - 现场诊断:调试字符
C(丢弃非 echo ICMP)、X/G(缓冲耗尽全丢)、Y/O(仅保 ARP)、D/Q(仅保 TCP)可快速定位瓶颈;WL_TX_ERR_RATIO_DEBUG_SEC可开启每秒收发错误率统计。
扩展点
- lwIP 收发过滤钩子:
lwip_low_level_inputput_filter/lwip_low_level_output_filter是弱符号全局函数,可自行实现替换,实现自定义 QoS/防火墙/流量统计策略(如按端口优先级丢弃)。 - 密码错误回调:
wifi_password_wrong_notify是驱动→应用的反馈通道,当前函数体被#if 0屏蔽;使能并扩展可实现多 SSID 容错切换、配网引导等业务逻辑。 - 内存管理:
CONFIG_WIFI_USE_TLSF_MEM = 1并设置CONFIG_WIFI_MAX_MEM_SIZE后,WiFi 使用独立 TLSF 内存池(sec(.wifi_mem_pool)段),隔离内存波动对系统的影响。 - 外置 WiFi 适配:
apps/common/net/ext_wifi_conf.c提供外置 WiFi 模块的配置路径,与内置驱动共用wifi/wifi_connect.h契约,便于平台间移植。 - 模式循环老化:
WIFI_MODE_CYCLE_TEST循环AP → STA → MONITOR,可作为量产前驱动稳定性老化测试项。
相关链接
- wifi_conf.c(驱动全局配置)
- wifi_demo_task.c(网络模式演示任务)
- ext_wifi_conf.c(外置 WiFi 模块配置,兄弟主题)
- config_network.c(网络配置,兄弟主题)
- assign_macaddr.c(MAC 地址分配,兄弟主题)
- wf_uart_protocal.c(UART 透传协议,兄弟主题)
- 网络协议栈(lwIP/DHCP)细节与云端配网(qcloud_iot_explorer_sdk 的
HAL_wifi_ac79.c、wifi_softap.c)请参见 5-networking 分类下的对应页面。