杰理 SDK 文档中心
首页
首页
  • SDK 概述与快速开始

    • SDK 概览与 AC791N 芯片平台
    • 环境搭建与编译指南
    • 烧录与固件升级
    • 工程结构导览
  • 产品方案应用

    • WiFi 摄像头方案
    • WiFi IPC 可视对讲方案
    • WiFi 故事机方案
    • 扫码枪 HID 方案
    • 开发板示例工程
  • 公共应用组件

    • 语音识别 ASR 引擎
    • LLM 与 AI 语音助手接入
    • 摄像头传感器驱动
    • UI 显示框架与驱动
    • USB 主机与设备栈
    • 文件系统与存储管理
    • 系统服务与外设管理
    • 生产测试与射频工具
  • 蓝牙协议栈

    • 经典蓝牙 BR/EDR
    • BLE 低功耗蓝牙
    • 蓝牙 Mesh 网络
    • 蓝牙扩展协议(RCSP/广播/无线麦克风)
  • WiFi 与网络协议栈

    • WiFi 驱动与网络模式
    • lwIP TCP/IP 协议栈
    • 网络安全与加密库
    • 应用层网络协议
    • 流媒体与音视频传输
    • 云平台接入 SDK
    • P2P 远程访问与设备互联
  • 芯片平台与驱动

    • wl82 平台与硬件加速
    • 外设驱动框架
    • 平台配置与固件打包工具
  • 媒体与音频引擎

    • 音频编解码与音源
    • 音效处理引擎
    • 视频与图像处理
  • 操作系统与运行时

    • 实时操作系统与 POSIX 层
    • C/C++ 运行时库
  • 开发资源与文档

    • 文档与规格书
    • 公共示例工程
    • UI 资源工程与打包
    • SDK 辅助工具与脚本

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 能力被组织为三层:

  1. 驱动配置层(apps/common/net/wifi_conf.c):以全局变量的形式集中暴露驱动调优开关与参数。这些变量大多被底层 WiFi 驱动(wifi/wifi_connect.h 对应的实现)直接引用,因此修改后重新编译即可生效,无需改动驱动核心代码——这是 SDK 设计上"配置与实现分离"的关键手段。
  2. 连接 API 层(wifi/wifi_connect.h 接口,如 wifi_get_mode_cur_info、wifi_get_channel、wifi_set_sta_connect_best_ssid 等):提供模式设置、扫描、连接、信息查询等操作入口。
  3. 应用演示层(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_TESTAP 模式设备作为 SoftAP 热点,SSID 为 AP_SSID 前缀,供手机直连配网
STA_MODE_TESTSTA 模式设备作为站点连接路由器,SSID/密码为 STA_SSID/STA_PWD
MONITOR_MODE_TESTMONITOR 模式监听模式,抓取空中报文(嗅探)
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 下取值不同):

配置项类型默认值说明
RTDebugLevelu82WiFi 调试输出等级(0=OFF … 5=LOUD),数值越小越紧急
WL_TX_DEBUG / WL_RX_DEBUGchar0底层发送/接收 FIFO 繁忙(丢包)打印开关
WL_TX_ERR_RATIO_DEBUG_SEC / WL_RX_ERR_RATIO_DEBUG_SECchar0每秒 TX/RX 成功/失败/错误率统计打印间隔(秒)
WL_RX_BACK_GROUND_ERR_CNT_PER_SECONDu1610接收误报率统计的本底错误包补偿值
WL_TX_PEND_DEBUG_SEC / WL_RX_PEND_DEBUG_SECchar2连续 N 秒发送不出/接收不到空中包时打印(判定严重干扰/硬件性能差)
WL_RX_OVERFLOW_DEBUGchar0接收 FIFO 溢出丢包统计开关
WIFI_PA_ENABLEchar0外挂硬件 PA 功率放大(791X 占用 PA1/PA2 IO),用于远距离传输
RxReorderEnableu81(双轨:无 SDRAM 为 0)底层包乱序整理;关闭时 UDP 重发包上抛但省内存
MAX_REORDERING_MPDU_NUMu32128(双轨:无 SDRAM 为 1)重排序 MPDU 数量上限
MAX_CHANNEL_TIME_BSS_INFRAu16200扫描每信道驻留时间(ms),20–400 区间
WIFI_CHANNEL_QUALITY_INDICATION_BADchar5STA 信道质量差阈值,低于即断线重连;-1 表示不主动断线
wifi_temperature_drift_trim_onchar0WiFi 温度漂移校准开关(CONFIG_RF_TEST_ENABLE 相关)
wifi_ap_scan_supportchar0AP 扫描开关
MAX_PACKETS_IN_QUEUEu1664(双轨:无 SDRAM 为 16)发送数据包队列深度
MAX_PACKETS_IN_MCAST_PS_QUEUEu168(双轨:无 SDRAM 为 4)组播 power-save 队列深度
MAX_PACKETS_IN_PS_QUEUEu1616(双轨:无 SDRAM 为 2)power-save 队列深度
RFIinitUseTrimValueu81初始化使用 VM 记忆的 RF trim 值,显著降低初始化时间
IPV4_ADDR_CONFLICT_DETECTu80(CONFIG_STATIC_IPADDR_ENABLE 下为 1)静态 IP 冲突检测
ntp_get_time_initu81联网后向 ntp_host 列表获取时间
rtc_update_intervalu320通过 NTP 校准 RTC 的时间间隔(ms)
CONFIG_SDIO_SLAVE_MODEu80WiFi 模块作为 SDIO 从机
WIFI_TX_FULL_WAIT_MODEu81(UCOS 下为 0)0/1/2,越大吞吐率越高但 WiFi 线程占 CPU 越多
WIFI_COLD_START_FAST_CONNECTIONu81冷启动快连(依赖记忆的 SSID)
MAX_LEN_OF_BSS_TABLEu84(双轨:无 SDRAM 为 2)扫描结果 BSS 表容量
CONFIG_WIFI_USE_TLSF_MEMu80使用独立 TLSF 内存管理,与系统内存隔离
CONFIG_WIFI_MAX_MEM_SIZE宏0独立内存池大小(当前 0 表示不启用)
wifi_recv_pollu80接收方式:0=中断,1=轮询
wifi_lowpower_modeu80(CONFIG_WIFI_IDLE_RESUME_BASEBAND_ENABLE 下为 1)低功耗模式
wifi_psmode_transfer_statistics_enableu81统计低功耗唤醒后收发包保活状态
wl_custom_listen_intervalu1610自定义监听间隔
wl_default_listen_intervalu163默认监听间隔(兜底值)
wl_transmit_keep_awake_timeu812收发包后保持清醒时间(单位 100ms,最小 1)
wifi_ampdu_disableu80关闭 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 可开启每秒收发错误率统计。

扩展点

  1. lwIP 收发过滤钩子:lwip_low_level_inputput_filter / lwip_low_level_output_filter 是弱符号全局函数,可自行实现替换,实现自定义 QoS/防火墙/流量统计策略(如按端口优先级丢弃)。
  2. 密码错误回调:wifi_password_wrong_notify 是驱动→应用的反馈通道,当前函数体被 #if 0 屏蔽;使能并扩展可实现多 SSID 容错切换、配网引导等业务逻辑。
  3. 内存管理:CONFIG_WIFI_USE_TLSF_MEM = 1 并设置 CONFIG_WIFI_MAX_MEM_SIZE 后,WiFi 使用独立 TLSF 内存池(sec(.wifi_mem_pool) 段),隔离内存波动对系统的影响。
  4. 外置 WiFi 适配:apps/common/net/ext_wifi_conf.c 提供外置 WiFi 模块的配置路径,与内置驱动共用 wifi/wifi_connect.h 契约,便于平台间移植。
  5. 模式循环老化: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 分类下的对应页面。
Next
lwIP TCP/IP 协议栈