本文基于esp32c3说明如何配置使用wifi. 可以使用zephyr自带的esp32c3_devkitm进行验证.
esp32c3自带wifi和蓝牙,zephyr中wifi的数据通路通过ethernet的L2接入TCP/IP, wifi的控制通路通过wifi L2接入net_mgmt. 本文主要说明如何通过配置启用esp32c3,并演示如果使用net_mgmt进行wifi扫描,连接等操作。
配置
增加配置
1 | # 启用WIFI |
在设备树中启用wifi
1 | &wifi { |
Zephyr-3.2.0下 esp32c3使用的wifi节点没有实际的物理参数可配置,仅仅是用来标识启用该设备,如果不添加构建时会被Kconfig检查到报错
1 | warning: WIFI_ESP32 (defined at drivers/wifi/esp32/Kconfig.esp32:3) has direct dependencies DT_HAS_ESPRESSIF_ESP32_WIFI_ENABLED && !SMP && WIFI with value n, but is currently being y-selected by the following symbols: |
代码
Zephyr对wifi的控制操作封装得非常简练,通过net_mgmt
进行控制请求, 结果直接返回或者是通过net_mgmt_init_event_callback/net_mgmt_add_event_callback
注册callback,在callback中处理控制请求的结果。
wifi控制请求
wifi控制的请求全部定义在include/zephyr/net/wifi_mgmt.h
中,有下面6种
NET_REQUEST_WIFI_SCAN
扫描AP节点NET_REQUEST_WIFI_CONNECT
连接AP节点NET_REQUEST_WIFI_DISCONNECT
断开连接NET_REQUEST_WIFI_AP_ENABLE
启用APNET_REQUEST_WIFI_AP_DISABLE
禁用APNET_REQUEST_WIFI_IFACE_STATUS
获取wifi接口状态,例如收发数据量的大小。注意这里获取不到信号强度的。
响应事件
对于请求,会有一些响应事件定义在include/zephyr/net/wifi_mgmt.h
中,有下面5种
NET_EVENT_WIFI_SCAN_RESULT
通知wifi扫描的结果NET_EVENT_WIFI_SCAN_DONE
通知wifi扫描已完成NET_EVENT_WIFI_CONNECT_RESULT
通知连接的结果NET_EVENT_WIFI_DISCONNECT_RESULT
通知断开连接的结果NET_EVENT_WIFI_IFACE_STATUS
通知wifi接口的状态
使用方法
扫描AP节点
1 | struct net_if *iface = net_if_get_default(); |
net_mgmt
执行NET_REQUEST_WIFI_SCAN
用于发动扫描AP,返回为0表示成功启动扫描,返回标准的errno表示失败。每扫到一个AP节点就有一次NET_EVENT_WIFI_SCAN_RESULT
,此时可以从callback获取到AP的信息, 本次扫描结束后产生NET_EVENT_WIFI_SCAN_DONE
.
连接和断开AP节点
1 | struct net_if *iface = net_if_get_default(); |
net_mgmt
执行NET_REQUEST_WIFI_CONNECT
用于执行连接动作,无论连接成功还是失败都会收到NET_EVENT_WIFI_CONNECT_RESULT
, 在callback中可以判断连接的结果。
1 | struct net_if *iface = net_if_get_default(); |
net_mgmt
执行NET_REQUEST_WIFI_DISCONNECT
用于执行断开连接动作,如果返回的状态为-EALREADY
表示已经断开。断开连接时会收到NET_EVENT_WIFI_DISCONNECT_RESULT
, 注意:即便没有执行NET_REQUEST_WIFI_DISCONNECT
而是因为AP主动断开,也会有NET_EVENT_WIFI_DISCONNECT_RESULT
产生
启用和禁用AP模式
通过设置可以让esp32c3处于AP模式
1 | static struct wifi_connect_req_params ap_params; |
net_mgmt
执行NET_REQUEST_WIFI_AP_ENABLE
用于启用AP模式,不会有事件产生
1 | int ret net_mgmt(NET_REQUEST_WIFI_AP_DISABLE, iface, |
net_mgmt
执行NET_REQUEST_WIFI_AP_DISABLE
用于启用AP模式,不会有事件产生
获取WIFI的接口状态
只有在配置了CONFIG_NET_STATISTICS_WIFI=y
和CONFIG_NET_STATISTICS_USER_API=y
的情况下才能获取状态
1 | struct net_if *iface = net_if_get_default(); |
抓取的状态是接口收到的包统计而不是信号强度
1 | struct net_stats_wifi { |
由于状态可以及时返回,我们不需要再去处理NET_EVENT_WIFI_IFACE_STATUS
注册事件处理回调
事件处理回调用于处理响应事件, 首先注册回调
1 | static struct net_mgmt_event_callback wifi_mgmt_cb; |
回调内依照event的不同分别处理
1 | static void wifi_mgmt_event_handler(struct net_mgmt_event_callback *cb, |
不同的事件按照不同的结构来解析cb->info
, NET_EVENT_WIFI_SCAN_RESULT
按照struct wifi_scan_result
进行解析
1 | struct wifi_scan_result { |
wifi的状态按照如下结构解析
1 | struct wifi_status { |
不同的事件status
含义不一样:
NET_EVENT_WIFI_SCAN_DONE
0表示扫描正常结束,其它为不正常结束NET_EVENT_WIFI_CONNECT_RESULT
0表示连接成功,其它为连接失败NET_EVENT_WIFI_DISCONNECT_RESULT
0表示断开连接成功,其它为断开连接失败
代码分析指南
目前zephyr中wifi的控制都是通过驱动注册的struct net_wifi_mgmt_offload
的API来进行,因此wifi的管理实现并不复杂,主要实现在subsys/net/l2/wifi/wifi_mgmt.c
中,例如:
由mgmt的宏包装实现函数
1 | NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_WIFI_CONNECT, wifi_connect); |
再由实现函数调用offload API
1 | static int wifi_connect(uint32_t mgmt_request, struct net_if *iface, |
offload api再向下就对接到驱动中,esp32c3对接到的是drivers/wifi/esp32/src/esp_wifi_drv.c
的esp32_wifi_scan
1 | static const struct net_wifi_mgmt_offload esp32_api = { |
对上net_mgmt(NET_REQUEST_WIFI_CONNECT, iface, &cnx_params, sizeof(struct wifi_connect_req_params))
如何调用到wifi_connect
可以参考Zephyr网络管理模块分析-注册请求机制一文.