0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

简析esp32的wifi驱动如何被集成进Zephyr的驱动

ZephyrProject 来源:ZephyrProject 作者:ZephyrProject 2021-06-01 10:41 次阅读

分析Zephyr ESP32 WIFI驱动的实现可以更为清晰的掌握esp32 wifi在zephyr上的使用,本文主要分析esp32的wifi驱动如何被集成进Zephyr的驱动,并不涉及esp32 wifi驱动本身API的说明。

框架

目前ESP32 wifi在zephyr上的实现框架如下图

93deaa3e-c240-11eb-9e57-12bb97331649.png

1. esp_private:

esp提供的wifi驱动,不开源,属于zephyr的外部module,其API头文件在moduleshalespressifcomponentsesp_wifiincludeesp_private内

2. adapter

esp提供的zephyr wifi适配层,对esp_private进行封装专门为zephyr用,属于zephyr的外部module,其代码放在moduleshalespressifzephyradaptersrcwifi

3. esp_wifi_drv:

Zephyr中的esp32 wifi驱动,调用adapter,和L2 ethernet进行对接。明明是wifi,不封装为L2 wifi, 而封装为L2 ethernet,这可能是目前zephyr对L2 wifi的抽象还不完备,目前只支持offload wifi。

这部分是后文的主要分析内容,代码在zephyrdriverswifiesp32src

4. L2 ethernet

Zephyr L2 ethernet,提供ethernet初始化/配置/收发功能, 代码在zephyrsubsys etl2ethernet,本文不做分析

esp_wifi_drv

zephyr的esp32 wifi驱动可以分为初始化,收,发三部分来分析:

初始化

主要是完成L2的初始化,注册入device初始化函数eth_esp32_dev_init和iface的初始化函数eth_esp32_init已经L2的发送函数eth_esp32_send

1

2

static const struct ethernet_api eth_esp32_apis = {

.iface_api.init= eth_esp32_init,

.send = eth_esp32_send,

};

NET_DEVICE_DT_INST_DEFINE(0,

eth_esp32_dev_init, NULL,

ð_data, NULL, CONFIG_ETH_INIT_PRIORITY,

ð_esp32_apis, ETHERNET_L2,

NET_L2_GET_CTX_TYPE(ETHERNET_L2), NET_ETH_MTU);

使用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进行管理。

static int eth_esp32_dev_init(const struct device *dev)

{

esp_timer_init();

esp_event_init();

wifi_init_config_t config = WIFI_INIT_CONFIG_DEFAULT();

esp_err_t ret = esp_wifi_init(&config);

ret |= esp_supplicant_init();

ret |= esp_wifi_start();

//安装配置进行WIFI连接

if (IS_ENABLED(CONFIG_ESP32_WIFI_STA_AUTO)) {

wifi_config_t wifi_config = {

.sta = {

.ssid = CONFIG_ESP32_WIFI_SSID,

.password = CONFIG_ESP32_WIFI_PASSWORD,

},

};

ret = esp_wifi_set_mode(WIFI_MODE_STA);

ret |= esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config);

ret |= esp_wifi_connect();

}

if (ret != ESP_OK) {

LOG_ERR(“Connect failed”);

}

return ret;

}

网络初始化, 完成ethernet iface注册,并注册数据接收callback,

static void eth_esp32_init(struct net_if *iface)

{

const struct device *dev = net_if_get_device(iface);

struct esp32_wifi_runtime *dev_data = DEV_DATA(dev);

dev_data-》iface = iface;

esp32_wifi_iface = iface;

//从ESP32读出MAC地址,设置给zephyr的iface

/* Start interface when we are actually connected with WiFi network */

net_if_flag_set(iface, NET_IF_NO_AUTO_START);

esp_read_mac(dev_data-》mac_addr, ESP_MAC_WIFI_STA);

/* Assign link local address. */

net_if_set_link_addr(iface,

dev_data-》mac_addr, 6, NET_LINK_ETHERNET);

//进行ethernet初始化

ethernet_init(iface);

//注册接收数据的callback,当hal esp32 wifi驱动收到网络封包后会调用eth_esp32_rx

esp_wifi_internal_reg_rxcb(ESP_IF_WIFI_STA, eth_esp32_rx);

}

数据接收

前面的代码可以看到注册的callback是eth_esp32_rx,hal esp32 wifi驱动收到网络封包后会调用eth_esp32_rx,eth_esp32_rx会将网络封包直接转发给IP层

static esp_err_t eth_esp32_rx(void *buffer, uint16_t len, void *eb)

{

struct net_pkt *pkt;

if (esp32_wifi_iface == NULL) {

LOG_ERR(“network interface unavailable”);

return ESP_FAIL;

}

//为封包分配内存

pkt = net_pkt_rx_alloc_with_buffer(esp32_wifi_iface, len,

AF_UNSPEC, 0, K_NO_WAIT);

if (!pkt) {

LOG_ERR(“Failed to get net buffer”);

return ESP_FAIL;

}

//将封包数据从驱动搬运到pkt内

if (net_pkt_write(pkt, buffer, len) 《 0) {

LOG_ERR(“Failed to write pkt”);

goto pkt_unref;

}

//将封包抓发给IP层

if (net_recv_data(esp32_wifi_iface, pkt) 《 0) {

LOG_ERR(“Failed to push received data”);

goto pkt_unref;

}

//通知esp驱动封包数据已经使用完

esp_wifi_internal_free_rx_buffer(eb);

return ESP_OK;

pkt_unref:

net_pkt_unref(pkt);

return ESP_FAIL;

}

数据发送

数据发送的API在初始化时将eth_esp32_send注册进ethernet_api的send, IP层在呼叫L2的send时会找到ethernet_send进行发送,ethernet_send调用就是eth_esp32_send

static int ethernet_send(struct net_if *iface, struct net_pkt *pkt)

{

。。。

//这里api-》send就是注册的eth_esp32_send

ret = net_l2_send(api-》send, net_if_get_device(iface), iface, pkt);

。。。

}

static inline int net_l2_send(net_l2_send_t send_fn,

const struct device *dev,

struct net_if *iface,

struct net_pkt *pkt)

{

net_capture_pkt(iface, pkt);

return send_fn(dev, pkt);

}

static int eth_esp32_send(const struct device *dev, struct net_pkt *pkt)

{

const int pkt_len = net_pkt_get_len(pkt);

//找到frame

/* Read the packet payload */

if (net_pkt_read(pkt, DEV_DATA(dev)-》frame_buf, pkt_len) 《 0) {

return -EIO;

}

//使用hal esp32 wifi进行发送

/* Enqueue packet for transmission */

esp_wifi_internal_tx(ESP_IF_WIFI_STA, (void *)DEV_DATA(dev)-》frame_buf, pkt_len);

LOG_DBG(“pkt sent %p len %d”, pkt, pkt_len);

return 0;

}

待确认

Wifi的帧结构是802.11, 其帧结构和ethernet不一样,现在直接将hal esp32 wifi和zephyr ethernet对接,应该是esp做了相应的转换,具体如何,待确认。

编辑:jq

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 驱动
    +关注

    关注

    12

    文章

    1844

    浏览量

    85402
  • API
    API
    +关注

    关注

    2

    文章

    1506

    浏览量

    62208
  • WIFI
    +关注

    关注

    81

    文章

    5301

    浏览量

    204190
  • ESP
    ESP
    +关注

    关注

    0

    文章

    184

    浏览量

    34006
  • 开源
    +关注

    关注

    3

    文章

    3374

    浏览量

    42599

原文标题:Zephyr ESP32 wifi驱动简析

文章出处:【微信号:ZephyrProject,微信公众号:ZephyrProject】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    esp32用什么软件编程

    ESP32是一款由乐鑫(Espressif)推出的低功耗、高性能的Wi-Fi和蓝牙双模微控制器,广泛应用于物联网、智能家居、智能穿戴等领域。要对ESP32进行编程,需要选择合适的编程软件和开发环境
    的头像 发表于 08-19 17:24 3906次阅读

    ESP32-WROOM-32E、ESP32-WROOM-32D、ESP32-WROOM-32U 有什么区别?ESP32-WROOM-32 后缀字母代表的意思是?

    相信很多人心里都有这样的疑问,今天就教大家怎么区分它们。 32D和32U是同一个芯片ESP32-D0WD的模组,主要区别的天线模式,分别是板载和IPEX外接天线。 32E是用的升级版的芯片
    的头像 发表于 07-17 10:09 1.1w次阅读
    <b class='flag-5'>ESP32</b>-WROOM-32E、<b class='flag-5'>ESP32</b>-WROOM-32D、<b class='flag-5'>ESP32</b>-WROOM-32U  有什么区别?<b class='flag-5'>ESP32</b>-WROOM-32 后缀字母代表的意思是?

    请问ESP32的网口与WIFI能否共存?

    请问ESP32 的网口与WIFI能否共存, 1台电脑用网口TCP-client与ESP32的TCP-server连接; 另一台电脑用WIFI的TCP-client与
    发表于 06-25 06:49

    如何使用espidf将esp32做成WiFi中继?

    如何使用espidf将esp32做成WiFi中继,让esp32通过WiFi连接互联网,同时作为AP,能让连接到esp32AP的设备能够直接访
    发表于 06-25 06:43

    乐鑫esp32系列在睡眠模式下保持蓝牙连接的功耗测试

    本教程适用于ESP32-S3、ESP32-C3、ESP32-C6睡眠模式介绍ESP32系列常见的休眠方式有三种,分别为Modem-sleep、Light-sleep和Deep-slee
    的头像 发表于 06-21 08:04 3187次阅读
    乐鑫<b class='flag-5'>esp32</b>系列在睡眠模式下保持蓝牙连接的功耗测试

    ESP32集成HiLink编译失败的原因?

    /libwpa_supplicant.a esp-idf/driver/libdriver.a /esp32/sources/esp-idf/components/esp_wifi/l
    发表于 06-18 08:19

    请问ESP32有emmc的驱动吗?

    ESP32 有emmc的驱动
    发表于 06-14 06:23

    ESP32驱动3264点阵屏有噪点的原因?

    ESP32 驱动3264点阵屏显示时间,采用ARDUINO编写。 不打开WIFI,显示会一切正常,打开WIFI,显示屏会有噪点闪动,无规律,就是发光的二极管会不时地更亮一下。 用
    发表于 06-13 06:56

    如何在zephyr上使能esp32-c3内置的USB串口?

    如题,请问如何在zephyr上使能esp32-c3内置的 USB 串口。
    发表于 06-12 08:11

    请问ESP32-S3如何驱动QSPI接口的LCD?

    目前项目用ESP32-S3来驱动QSPI接口的LCD,驱动IC为GC9B71(规格书参考附件)。试着在ESP-IDF的范例spi_lcd_touch_example_main基础修改了
    发表于 06-07 06:51

    linux端始终识别不到ESP32-WROOM-32UE的设备id不到probe函数的原因?

    _VENDOR_ID, ESP_DEVICE_ID_2) }, {} }; 但linux端始终识别不到ESP32-WROOM-32UE的设备id不到probe函数内,/sys/bus/sdio/devices下看不到设备节点,
    发表于 06-06 06:44

    ESP32S3用LVGL驱动480*480RGB屏幕,只要连接上WIFI,屏幕显示就会错位怎么解决?

    ESP32S3用LVGL驱动480*480RGB屏幕,只要连接上WIFI,屏幕显示就会错位,请问有解决方案吗? IDF5.1.2
    发表于 06-05 08:15

    基于ESP32开发的工业级2.4GHz WiFi蓝牙模块方案

           ESP32集成了2.4 GHz WiFi和蓝牙双模的单芯片方案,它采用台积电(TSMC)超低功耗的40纳米工艺,具有超高的射频性能、稳定性、通用性和可靠性,以及超低的功耗,满足
    的头像 发表于 05-31 17:06 930次阅读

    ESP32系列ESP32-D0WD双模 超低功耗集成BLE4.2+2.4G WIFI SoC芯片

    ESP32系列ESP32-D0WD双模 超低功耗集成BLE4.2+2.4G WIFI SoC芯片
    的头像 发表于 05-29 11:52 1518次阅读
    <b class='flag-5'>ESP32</b>系列<b class='flag-5'>ESP32</b>-D0WD双模 超低功耗<b class='flag-5'>集成</b>BLE4.2+2.4G <b class='flag-5'>WIFI</b> SoC芯片

    请问foc驱动板上可以用esp32吗?

    foc驱动板上可以用esp32
    发表于 03-19 06:03