分析Zephyr ESP32 WIFI驱动的实现可以更为清晰的掌握esp32 wifi在zephyr上的使用,本文主要分析esp32的wifi驱动如何被集成进Zephyr的驱动,并不涉及esp32 wifi驱动本身API的说明。
框架
目前ESP32 wifi在zephyr上的实现框架如下图
1 esp_private:
esp提供的wifi驱动,不开源,属于zephyr的外部module,其API头文件在modules\hal\espressif\components\esp_wifi\include\esp_private内
2 adapter
esp提供的zephyr wifi适配层,对esp_private进行封装专门为zephyr用,属于zephyr的外部module,其代码放在modules\hal\espressif\zephyr\adapter\src\wifi
3 esp_wifi_drv:
Zephyr中的esp32 wifi驱动,调用adapter,和L2 ethernet进行对接。明明是wifi,不封装为L2 wifi, 而封装为L2 ethernet,这可能是目前zephyr对L2 wifi的抽象还不完备,目前只支持offload wifi。
这部分是后文的主要分析内容,代码在zephyr\drivers\wifi\esp32\src
- L2 ethernet
Zephyr L2 ethernet,提供ethernet初始化/配置/收发功能, 代码在zephyr\subsys\net\l2\ethernet,本文不做分析
esp_wifi_drv
zephyr的esp32 wifi驱动可以分为初始化,收,发三部分来分析:
初始化
主要是完成L2的初始化,注册入device初始化函数eth_esp32_dev_init和iface的初始化函数eth_esp32_init已经L2的发送函数eth_esp32_send
1 | static const struct ethernet_api eth_esp32_apis = { |
使用NET_DEVICE_DT_INST_DEFINE注册后,在系统启动时kernel的POST_KERNEL阶段调用eth_esp32_dev_init,在net初始化阶段调用eth_esp32_init.
eth_esp32_dev_init代码如下,主要是调用hal中提供的一系列初始化和启动函数,让wifi启动,值得注意的是当CONFIG_ESP32_WIFI_STA_AUTO=y
时,zephyr驱动会自动去帮你用配置好的CONFIG_ESP32_WIFI_SSID和CONFIG_ESP32_WIFI_PASSWORD去连接Wifi。如果没有配置,就需要在应用代码中直接调用esp hal的API进行连接,另外就是zephyr目前并没有将esp32 wifi的scan/connect/disconnect做到L2 WIFI内进行管理,可以参考Zephyr网络管理模块分析-注册请求机制, 这边部分也需要在应用中直接调用esp hal的API进行管理。
1 | static int eth_esp32_dev_init(const struct device *dev) |
网络初始化, 完成ethernet iface注册,并注册数据接收callback,
1 | static void eth_esp32_init(struct net_if *iface) |
数据接收
前面的代码可以看到注册的callback是eth_esp32_rx,hal esp32 wifi驱动收到网络封包后会调用eth_esp32_rx,eth_esp32_rx会将网络封包直接转发给IP层
1 | static esp_err_t eth_esp32_rx(void *buffer, uint16_t len, void *eb) |
数据发送
数据发送的API在初始化时将eth_esp32_send注册进ethernet_api的send, IP层在呼叫L2的send时会找到ethernet_send进行发送,ethernet_send调用就是eth_esp32_send
1 | static int ethernet_send(struct net_if *iface, struct net_pkt *pkt) |
待确认
Wifi的帧结构是802.11, 其帧结构和ethernet不一样,现在直接将hal esp32 wifi和zephyr ethernet对接,应该是esp做了相应的转换,具体如何,待确认。